Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'kvm-s390-next-5.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into HEAD

KVM: s390: add kselftests

This is the initial implementation for KVM selftests on s390.

+494 -10
+2
MAINTAINERS
··· 8797 8797 F: arch/s390/include/asm/kvm* 8798 8798 F: arch/s390/kvm/ 8799 8799 F: arch/s390/mm/gmap.c 8800 + F: tools/testing/selftests/kvm/s390x/ 8801 + F: tools/testing/selftests/kvm/*/s390x/ 8800 8802 8801 8803 KERNEL VIRTUAL MACHINE FOR X86 (KVM/x86) 8802 8804 M: Paolo Bonzini <pbonzini@redhat.com>
+12 -2
tools/testing/selftests/kvm/Makefile
··· 10 10 LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/ucall.c lib/sparsebit.c 11 11 LIBKVM_x86_64 = lib/x86_64/processor.c lib/x86_64/vmx.c 12 12 LIBKVM_aarch64 = lib/aarch64/processor.c 13 + LIBKVM_s390x = lib/s390x/processor.c 13 14 14 15 TEST_GEN_PROGS_x86_64 = x86_64/cr4_cpuid_sync_test 15 16 TEST_GEN_PROGS_x86_64 += x86_64/evmcs_test 16 17 TEST_GEN_PROGS_x86_64 += x86_64/hyperv_cpuid 17 - TEST_GEN_PROGS_x86_64 += x86_64/kvm_create_max_vcpus 18 18 TEST_GEN_PROGS_x86_64 += x86_64/mmio_warning_test 19 19 TEST_GEN_PROGS_x86_64 += x86_64/platform_info_test 20 20 TEST_GEN_PROGS_x86_64 += x86_64/set_sregs_test ··· 26 26 TEST_GEN_PROGS_x86_64 += x86_64/vmx_tsc_adjust_test 27 27 TEST_GEN_PROGS_x86_64 += clear_dirty_log_test 28 28 TEST_GEN_PROGS_x86_64 += dirty_log_test 29 + TEST_GEN_PROGS_x86_64 += kvm_create_max_vcpus 29 30 30 31 TEST_GEN_PROGS_aarch64 += clear_dirty_log_test 31 32 TEST_GEN_PROGS_aarch64 += dirty_log_test 33 + TEST_GEN_PROGS_aarch64 += kvm_create_max_vcpus 34 + 35 + TEST_GEN_PROGS_s390x += s390x/sync_regs_test 36 + TEST_GEN_PROGS_s390x += kvm_create_max_vcpus 32 37 33 38 TEST_GEN_PROGS += $(TEST_GEN_PROGS_$(UNAME_M)) 34 39 LIBKVM += $(LIBKVM_$(UNAME_M)) ··· 48 43 no-pie-option := $(call try-run, echo 'int main() { return 0; }' | \ 49 44 $(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -no-pie -x c - -o "$$TMP", -no-pie) 50 45 51 - LDFLAGS += -pthread $(no-pie-option) 46 + # On s390, build the testcases KVM-enabled 47 + pgste-option = $(call try-run, echo 'int main() { return 0; }' | \ 48 + $(CC) -Werror -Wl$(comma)--s390-pgste -x c - -o "$$TMP",-Wl$(comma)--s390-pgste) 49 + 50 + 51 + LDFLAGS += -pthread $(no-pie-option) $(pgste-option) 52 52 53 53 # After inclusion, $(OUTPUT) is defined and 54 54 # $(TEST_GEN_PROGS) starts with $(OUTPUT)/
+8
tools/testing/selftests/kvm/include/kvm_util.h
··· 41 41 NUM_VM_MODES, 42 42 }; 43 43 44 + #ifdef __aarch64__ 45 + #define VM_MODE_DEFAULT VM_MODE_P40V48_4K 46 + #else 47 + #define VM_MODE_DEFAULT VM_MODE_P52V48_4K 48 + #endif 49 + 44 50 #define vm_guest_mode_string(m) vm_guest_mode_string[m] 45 51 extern const char * const vm_guest_mode_string[]; 46 52 ··· 117 111 struct kvm_sregs *sregs); 118 112 int _vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid, 119 113 struct kvm_sregs *sregs); 114 + #ifdef __KVM_HAVE_VCPU_EVENTS 120 115 void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid, 121 116 struct kvm_vcpu_events *events); 122 117 void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid, 123 118 struct kvm_vcpu_events *events); 119 + #endif 124 120 #ifdef __x86_64__ 125 121 void vcpu_nested_state_get(struct kvm_vm *vm, uint32_t vcpuid, 126 122 struct kvm_nested_state *state);
+22
tools/testing/selftests/kvm/include/s390x/processor.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * s390x processor specific defines 4 + */ 5 + #ifndef SELFTEST_KVM_PROCESSOR_H 6 + #define SELFTEST_KVM_PROCESSOR_H 7 + 8 + /* Bits in the region/segment table entry */ 9 + #define REGION_ENTRY_ORIGIN ~0xfffUL /* region/segment table origin */ 10 + #define REGION_ENTRY_PROTECT 0x200 /* region protection bit */ 11 + #define REGION_ENTRY_NOEXEC 0x100 /* region no-execute bit */ 12 + #define REGION_ENTRY_OFFSET 0xc0 /* region table offset */ 13 + #define REGION_ENTRY_INVALID 0x20 /* invalid region table entry */ 14 + #define REGION_ENTRY_TYPE 0x0c /* region/segment table type mask */ 15 + #define REGION_ENTRY_LENGTH 0x03 /* region third length */ 16 + 17 + /* Bits in the page table entry */ 18 + #define PAGE_INVALID 0x400 /* HW invalid bit */ 19 + #define PAGE_PROTECT 0x200 /* HW read-only bit */ 20 + #define PAGE_NOEXEC 0x100 /* HW no-execute bit */ 21 + 22 + #endif
+1 -1
tools/testing/selftests/kvm/lib/aarch64/processor.c
··· 227 227 uint64_t extra_pg_pages = (extra_mem_pages / ptrs_per_4k_pte) * 2; 228 228 struct kvm_vm *vm; 229 229 230 - vm = vm_create(VM_MODE_P40V48_4K, DEFAULT_GUEST_PHY_PAGES + extra_pg_pages, O_RDWR); 230 + vm = vm_create(VM_MODE_DEFAULT, DEFAULT_GUEST_PHY_PAGES + extra_pg_pages, O_RDWR); 231 231 232 232 kvm_vm_elf_load(vm, program_invocation_name, 0, 0); 233 233 vm_vcpu_add_default(vm, vcpuid, guest_code);
+18 -5
tools/testing/selftests/kvm/lib/kvm_util.c
··· 556 556 int ret; 557 557 struct userspace_mem_region *region; 558 558 size_t huge_page_size = KVM_UTIL_PGS_PER_HUGEPG * vm->page_size; 559 + size_t alignment; 559 560 560 561 TEST_ASSERT((guest_paddr % vm->page_size) == 0, "Guest physical " 561 562 "address not on a page boundary.\n" ··· 606 605 TEST_ASSERT(region != NULL, "Insufficient Memory"); 607 606 region->mmap_size = npages * vm->page_size; 608 607 609 - /* Enough memory to align up to a huge page. */ 608 + #ifdef __s390x__ 609 + /* On s390x, the host address must be aligned to 1M (due to PGSTEs) */ 610 + alignment = 0x100000; 611 + #else 612 + alignment = 1; 613 + #endif 614 + 610 615 if (src_type == VM_MEM_SRC_ANONYMOUS_THP) 611 - region->mmap_size += huge_page_size; 616 + alignment = max(huge_page_size, alignment); 617 + 618 + /* Add enough memory to align up if necessary */ 619 + if (alignment > 1) 620 + region->mmap_size += alignment; 621 + 612 622 region->mmap_start = mmap(NULL, region->mmap_size, 613 623 PROT_READ | PROT_WRITE, 614 624 MAP_PRIVATE | MAP_ANONYMOUS ··· 629 617 "test_malloc failed, mmap_start: %p errno: %i", 630 618 region->mmap_start, errno); 631 619 632 - /* Align THP allocation up to start of a huge page. */ 633 - region->host_mem = align(region->mmap_start, 634 - src_type == VM_MEM_SRC_ANONYMOUS_THP ? huge_page_size : 1); 620 + /* Align host address */ 621 + region->host_mem = align(region->mmap_start, alignment); 635 622 636 623 /* As needed perform madvise */ 637 624 if (src_type == VM_MEM_SRC_ANONYMOUS || src_type == VM_MEM_SRC_ANONYMOUS_THP) { ··· 1229 1218 ret, errno); 1230 1219 } 1231 1220 1221 + #ifdef __KVM_HAVE_VCPU_EVENTS 1232 1222 void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid, 1233 1223 struct kvm_vcpu_events *events) 1234 1224 { ··· 1255 1243 TEST_ASSERT(ret == 0, "KVM_SET_VCPU_EVENTS, failed, rc: %i errno: %i", 1256 1244 ret, errno); 1257 1245 } 1246 + #endif 1258 1247 1259 1248 #ifdef __x86_64__ 1260 1249 void vcpu_nested_state_get(struct kvm_vm *vm, uint32_t vcpuid,
+278
tools/testing/selftests/kvm/lib/s390x/processor.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * KVM selftest s390x library code - CPU-related functions (page tables...) 4 + * 5 + * Copyright (C) 2019, Red Hat, Inc. 6 + */ 7 + 8 + #define _GNU_SOURCE /* for program_invocation_name */ 9 + 10 + #include "processor.h" 11 + #include "kvm_util.h" 12 + #include "../kvm_util_internal.h" 13 + 14 + #define KVM_GUEST_PAGE_TABLE_MIN_PADDR 0x180000 15 + 16 + #define PAGES_PER_REGION 4 17 + 18 + void virt_pgd_alloc(struct kvm_vm *vm, uint32_t memslot) 19 + { 20 + vm_paddr_t paddr; 21 + 22 + TEST_ASSERT(vm->page_size == 4096, "Unsupported page size: 0x%x", 23 + vm->page_size); 24 + 25 + if (vm->pgd_created) 26 + return; 27 + 28 + paddr = vm_phy_pages_alloc(vm, PAGES_PER_REGION, 29 + KVM_GUEST_PAGE_TABLE_MIN_PADDR, memslot); 30 + memset(addr_gpa2hva(vm, paddr), 0xff, PAGES_PER_REGION * vm->page_size); 31 + 32 + vm->pgd = paddr; 33 + vm->pgd_created = true; 34 + } 35 + 36 + /* 37 + * Allocate 4 pages for a region/segment table (ri < 4), or one page for 38 + * a page table (ri == 4). Returns a suitable region/segment table entry 39 + * which points to the freshly allocated pages. 40 + */ 41 + static uint64_t virt_alloc_region(struct kvm_vm *vm, int ri, uint32_t memslot) 42 + { 43 + uint64_t taddr; 44 + 45 + taddr = vm_phy_pages_alloc(vm, ri < 4 ? PAGES_PER_REGION : 1, 46 + KVM_GUEST_PAGE_TABLE_MIN_PADDR, memslot); 47 + memset(addr_gpa2hva(vm, taddr), 0xff, PAGES_PER_REGION * vm->page_size); 48 + 49 + return (taddr & REGION_ENTRY_ORIGIN) 50 + | (((4 - ri) << 2) & REGION_ENTRY_TYPE) 51 + | ((ri < 4 ? (PAGES_PER_REGION - 1) : 0) & REGION_ENTRY_LENGTH); 52 + } 53 + 54 + /* 55 + * VM Virtual Page Map 56 + * 57 + * Input Args: 58 + * vm - Virtual Machine 59 + * gva - VM Virtual Address 60 + * gpa - VM Physical Address 61 + * memslot - Memory region slot for new virtual translation tables 62 + * 63 + * Output Args: None 64 + * 65 + * Return: None 66 + * 67 + * Within the VM given by vm, creates a virtual translation for the page 68 + * starting at vaddr to the page starting at paddr. 69 + */ 70 + void virt_pg_map(struct kvm_vm *vm, uint64_t gva, uint64_t gpa, 71 + uint32_t memslot) 72 + { 73 + int ri, idx; 74 + uint64_t *entry; 75 + 76 + TEST_ASSERT((gva % vm->page_size) == 0, 77 + "Virtual address not on page boundary,\n" 78 + " vaddr: 0x%lx vm->page_size: 0x%x", 79 + gva, vm->page_size); 80 + TEST_ASSERT(sparsebit_is_set(vm->vpages_valid, 81 + (gva >> vm->page_shift)), 82 + "Invalid virtual address, vaddr: 0x%lx", 83 + gva); 84 + TEST_ASSERT((gpa % vm->page_size) == 0, 85 + "Physical address not on page boundary,\n" 86 + " paddr: 0x%lx vm->page_size: 0x%x", 87 + gva, vm->page_size); 88 + TEST_ASSERT((gpa >> vm->page_shift) <= vm->max_gfn, 89 + "Physical address beyond beyond maximum supported,\n" 90 + " paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x", 91 + gva, vm->max_gfn, vm->page_size); 92 + 93 + /* Walk through region and segment tables */ 94 + entry = addr_gpa2hva(vm, vm->pgd); 95 + for (ri = 1; ri <= 4; ri++) { 96 + idx = (gva >> (64 - 11 * ri)) & 0x7ffu; 97 + if (entry[idx] & REGION_ENTRY_INVALID) 98 + entry[idx] = virt_alloc_region(vm, ri, memslot); 99 + entry = addr_gpa2hva(vm, entry[idx] & REGION_ENTRY_ORIGIN); 100 + } 101 + 102 + /* Fill in page table entry */ 103 + idx = (gva >> 12) & 0x0ffu; /* page index */ 104 + if (!(entry[idx] & PAGE_INVALID)) 105 + fprintf(stderr, 106 + "WARNING: PTE for gpa=0x%"PRIx64" already set!\n", gpa); 107 + entry[idx] = gpa; 108 + } 109 + 110 + /* 111 + * Address Guest Virtual to Guest Physical 112 + * 113 + * Input Args: 114 + * vm - Virtual Machine 115 + * gpa - VM virtual address 116 + * 117 + * Output Args: None 118 + * 119 + * Return: 120 + * Equivalent VM physical address 121 + * 122 + * Translates the VM virtual address given by gva to a VM physical 123 + * address and then locates the memory region containing the VM 124 + * physical address, within the VM given by vm. When found, the host 125 + * virtual address providing the memory to the vm physical address is 126 + * returned. 127 + * A TEST_ASSERT failure occurs if no region containing translated 128 + * VM virtual address exists. 129 + */ 130 + vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva) 131 + { 132 + int ri, idx; 133 + uint64_t *entry; 134 + 135 + TEST_ASSERT(vm->page_size == 4096, "Unsupported page size: 0x%x", 136 + vm->page_size); 137 + 138 + entry = addr_gpa2hva(vm, vm->pgd); 139 + for (ri = 1; ri <= 4; ri++) { 140 + idx = (gva >> (64 - 11 * ri)) & 0x7ffu; 141 + TEST_ASSERT(!(entry[idx] & REGION_ENTRY_INVALID), 142 + "No region mapping for vm virtual address 0x%lx", 143 + gva); 144 + entry = addr_gpa2hva(vm, entry[idx] & REGION_ENTRY_ORIGIN); 145 + } 146 + 147 + idx = (gva >> 12) & 0x0ffu; /* page index */ 148 + 149 + TEST_ASSERT(!(entry[idx] & PAGE_INVALID), 150 + "No page mapping for vm virtual address 0x%lx", gva); 151 + 152 + return (entry[idx] & ~0xffful) + (gva & 0xffful); 153 + } 154 + 155 + static void virt_dump_ptes(FILE *stream, struct kvm_vm *vm, uint8_t indent, 156 + uint64_t ptea_start) 157 + { 158 + uint64_t *pte, ptea; 159 + 160 + for (ptea = ptea_start; ptea < ptea_start + 0x100 * 8; ptea += 8) { 161 + pte = addr_gpa2hva(vm, ptea); 162 + if (*pte & PAGE_INVALID) 163 + continue; 164 + fprintf(stream, "%*spte @ 0x%lx: 0x%016lx\n", 165 + indent, "", ptea, *pte); 166 + } 167 + } 168 + 169 + static void virt_dump_region(FILE *stream, struct kvm_vm *vm, uint8_t indent, 170 + uint64_t reg_tab_addr) 171 + { 172 + uint64_t addr, *entry; 173 + 174 + for (addr = reg_tab_addr; addr < reg_tab_addr + 0x400 * 8; addr += 8) { 175 + entry = addr_gpa2hva(vm, addr); 176 + if (*entry & REGION_ENTRY_INVALID) 177 + continue; 178 + fprintf(stream, "%*srt%lde @ 0x%lx: 0x%016lx\n", 179 + indent, "", 4 - ((*entry & REGION_ENTRY_TYPE) >> 2), 180 + addr, *entry); 181 + if (*entry & REGION_ENTRY_TYPE) { 182 + virt_dump_region(stream, vm, indent + 2, 183 + *entry & REGION_ENTRY_ORIGIN); 184 + } else { 185 + virt_dump_ptes(stream, vm, indent + 2, 186 + *entry & REGION_ENTRY_ORIGIN); 187 + } 188 + } 189 + } 190 + 191 + void virt_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent) 192 + { 193 + if (!vm->pgd_created) 194 + return; 195 + 196 + virt_dump_region(stream, vm, indent, vm->pgd); 197 + } 198 + 199 + /* 200 + * Create a VM with reasonable defaults 201 + * 202 + * Input Args: 203 + * vcpuid - The id of the single VCPU to add to the VM. 204 + * extra_mem_pages - The size of extra memories to add (this will 205 + * decide how much extra space we will need to 206 + * setup the page tables using mem slot 0) 207 + * guest_code - The vCPU's entry point 208 + * 209 + * Output Args: None 210 + * 211 + * Return: 212 + * Pointer to opaque structure that describes the created VM. 213 + */ 214 + struct kvm_vm *vm_create_default(uint32_t vcpuid, uint64_t extra_mem_pages, 215 + void *guest_code) 216 + { 217 + /* 218 + * The additional amount of pages required for the page tables is: 219 + * 1 * n / 256 + 4 * (n / 256) / 2048 + 4 * (n / 256) / 2048^2 + ... 220 + * which is definitely smaller than (n / 256) * 2. 221 + */ 222 + uint64_t extra_pg_pages = extra_mem_pages / 256 * 2; 223 + struct kvm_vm *vm; 224 + 225 + vm = vm_create(VM_MODE_DEFAULT, 226 + DEFAULT_GUEST_PHY_PAGES + extra_pg_pages, O_RDWR); 227 + 228 + kvm_vm_elf_load(vm, program_invocation_name, 0, 0); 229 + vm_vcpu_add_default(vm, vcpuid, guest_code); 230 + 231 + return vm; 232 + } 233 + 234 + /* 235 + * Adds a vCPU with reasonable defaults (i.e. a stack and initial PSW) 236 + * 237 + * Input Args: 238 + * vcpuid - The id of the VCPU to add to the VM. 239 + * guest_code - The vCPU's entry point 240 + */ 241 + void vm_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, void *guest_code) 242 + { 243 + size_t stack_size = DEFAULT_STACK_PGS * getpagesize(); 244 + uint64_t stack_vaddr; 245 + struct kvm_regs regs; 246 + struct kvm_sregs sregs; 247 + struct kvm_run *run; 248 + 249 + TEST_ASSERT(vm->page_size == 4096, "Unsupported page size: 0x%x", 250 + vm->page_size); 251 + 252 + stack_vaddr = vm_vaddr_alloc(vm, stack_size, 253 + DEFAULT_GUEST_STACK_VADDR_MIN, 0, 0); 254 + 255 + vm_vcpu_add(vm, vcpuid); 256 + 257 + /* Setup guest registers */ 258 + vcpu_regs_get(vm, vcpuid, &regs); 259 + regs.gprs[15] = stack_vaddr + (DEFAULT_STACK_PGS * getpagesize()) - 160; 260 + vcpu_regs_set(vm, vcpuid, &regs); 261 + 262 + vcpu_sregs_get(vm, vcpuid, &sregs); 263 + sregs.crs[0] |= 0x00040000; /* Enable floating point regs */ 264 + sregs.crs[1] = vm->pgd | 0xf; /* Primary region table */ 265 + vcpu_sregs_set(vm, vcpuid, &sregs); 266 + 267 + run = vcpu_state(vm, vcpuid); 268 + run->psw_mask = 0x0400000180000000ULL; /* DAT enabled + 64 bit mode */ 269 + run->psw_addr = (uintptr_t)guest_code; 270 + } 271 + 272 + void vcpu_dump(FILE *stream, struct kvm_vm *vm, uint32_t vcpuid, uint8_t indent) 273 + { 274 + struct vcpu *vcpu = vm->vcpu_head; 275 + 276 + fprintf(stream, "%*spstate: psw: 0x%.16llx:0x%.16llx\n", 277 + indent, "", vcpu->state->psw_mask, vcpu->state->psw_addr); 278 + }
+1 -1
tools/testing/selftests/kvm/lib/x86_64/processor.c
··· 821 821 uint64_t extra_pg_pages = extra_mem_pages / 512 * 2; 822 822 823 823 /* Create VM */ 824 - vm = vm_create(VM_MODE_P52V48_4K, 824 + vm = vm_create(VM_MODE_DEFAULT, 825 825 DEFAULT_GUEST_PHY_PAGES + extra_pg_pages, 826 826 O_RDWR); 827 827
+151
tools/testing/selftests/kvm/s390x/sync_regs_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Test for s390x KVM_CAP_SYNC_REGS 4 + * 5 + * Based on the same test for x86: 6 + * Copyright (C) 2018, Google LLC. 7 + * 8 + * Adaptions for s390x: 9 + * Copyright (C) 2019, Red Hat, Inc. 10 + * 11 + * Test expected behavior of the KVM_CAP_SYNC_REGS functionality. 12 + */ 13 + 14 + #define _GNU_SOURCE /* for program_invocation_short_name */ 15 + #include <fcntl.h> 16 + #include <stdio.h> 17 + #include <stdlib.h> 18 + #include <string.h> 19 + #include <sys/ioctl.h> 20 + 21 + #include "test_util.h" 22 + #include "kvm_util.h" 23 + 24 + #define VCPU_ID 5 25 + 26 + static void guest_code(void) 27 + { 28 + for (;;) { 29 + asm volatile ("diag 0,0,0x501"); 30 + asm volatile ("ahi 11,1"); 31 + } 32 + } 33 + 34 + #define REG_COMPARE(reg) \ 35 + TEST_ASSERT(left->reg == right->reg, \ 36 + "Register " #reg \ 37 + " values did not match: 0x%llx, 0x%llx\n", \ 38 + left->reg, right->reg) 39 + 40 + static void compare_regs(struct kvm_regs *left, struct kvm_sync_regs *right) 41 + { 42 + int i; 43 + 44 + for (i = 0; i < 16; i++) 45 + REG_COMPARE(gprs[i]); 46 + } 47 + 48 + static void compare_sregs(struct kvm_sregs *left, struct kvm_sync_regs *right) 49 + { 50 + int i; 51 + 52 + for (i = 0; i < 16; i++) 53 + REG_COMPARE(acrs[i]); 54 + 55 + for (i = 0; i < 16; i++) 56 + REG_COMPARE(crs[i]); 57 + } 58 + 59 + #undef REG_COMPARE 60 + 61 + #define TEST_SYNC_FIELDS (KVM_SYNC_GPRS|KVM_SYNC_ACRS|KVM_SYNC_CRS) 62 + #define INVALID_SYNC_FIELD 0x80000000 63 + 64 + int main(int argc, char *argv[]) 65 + { 66 + struct kvm_vm *vm; 67 + struct kvm_run *run; 68 + struct kvm_regs regs; 69 + struct kvm_sregs sregs; 70 + int rv, cap; 71 + 72 + /* Tell stdout not to buffer its content */ 73 + setbuf(stdout, NULL); 74 + 75 + cap = kvm_check_cap(KVM_CAP_SYNC_REGS); 76 + if (!cap) { 77 + fprintf(stderr, "CAP_SYNC_REGS not supported, skipping test\n"); 78 + exit(KSFT_SKIP); 79 + } 80 + 81 + /* Create VM */ 82 + vm = vm_create_default(VCPU_ID, 0, guest_code); 83 + 84 + run = vcpu_state(vm, VCPU_ID); 85 + 86 + /* Request and verify all valid register sets. */ 87 + run->kvm_valid_regs = TEST_SYNC_FIELDS; 88 + rv = _vcpu_run(vm, VCPU_ID); 89 + TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv); 90 + TEST_ASSERT(run->exit_reason == KVM_EXIT_S390_SIEIC, 91 + "Unexpected exit reason: %u (%s)\n", 92 + run->exit_reason, 93 + exit_reason_str(run->exit_reason)); 94 + TEST_ASSERT(run->s390_sieic.icptcode == 4 && 95 + (run->s390_sieic.ipa >> 8) == 0x83 && 96 + (run->s390_sieic.ipb >> 16) == 0x501, 97 + "Unexpected interception code: ic=%u, ipa=0x%x, ipb=0x%x\n", 98 + run->s390_sieic.icptcode, run->s390_sieic.ipa, 99 + run->s390_sieic.ipb); 100 + 101 + vcpu_regs_get(vm, VCPU_ID, &regs); 102 + compare_regs(&regs, &run->s.regs); 103 + 104 + vcpu_sregs_get(vm, VCPU_ID, &sregs); 105 + compare_sregs(&sregs, &run->s.regs); 106 + 107 + /* Set and verify various register values */ 108 + run->s.regs.gprs[11] = 0xBAD1DEA; 109 + run->s.regs.acrs[0] = 1 << 11; 110 + 111 + run->kvm_valid_regs = TEST_SYNC_FIELDS; 112 + run->kvm_dirty_regs = KVM_SYNC_GPRS | KVM_SYNC_ACRS; 113 + rv = _vcpu_run(vm, VCPU_ID); 114 + TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv); 115 + TEST_ASSERT(run->exit_reason == KVM_EXIT_S390_SIEIC, 116 + "Unexpected exit reason: %u (%s)\n", 117 + run->exit_reason, 118 + exit_reason_str(run->exit_reason)); 119 + TEST_ASSERT(run->s.regs.gprs[11] == 0xBAD1DEA + 1, 120 + "r11 sync regs value incorrect 0x%llx.", 121 + run->s.regs.gprs[11]); 122 + TEST_ASSERT(run->s.regs.acrs[0] == 1 << 11, 123 + "acr0 sync regs value incorrect 0x%llx.", 124 + run->s.regs.acrs[0]); 125 + 126 + vcpu_regs_get(vm, VCPU_ID, &regs); 127 + compare_regs(&regs, &run->s.regs); 128 + 129 + vcpu_sregs_get(vm, VCPU_ID, &sregs); 130 + compare_sregs(&sregs, &run->s.regs); 131 + 132 + /* Clear kvm_dirty_regs bits, verify new s.regs values are 133 + * overwritten with existing guest values. 134 + */ 135 + run->kvm_valid_regs = TEST_SYNC_FIELDS; 136 + run->kvm_dirty_regs = 0; 137 + run->s.regs.gprs[11] = 0xDEADBEEF; 138 + rv = _vcpu_run(vm, VCPU_ID); 139 + TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv); 140 + TEST_ASSERT(run->exit_reason == KVM_EXIT_S390_SIEIC, 141 + "Unexpected exit reason: %u (%s)\n", 142 + run->exit_reason, 143 + exit_reason_str(run->exit_reason)); 144 + TEST_ASSERT(run->s.regs.gprs[11] != 0xDEADBEEF, 145 + "r11 sync regs value incorrect 0x%llx.", 146 + run->s.regs.gprs[11]); 147 + 148 + kvm_vm_free(vm); 149 + 150 + return 0; 151 + }
+1 -1
tools/testing/selftests/kvm/x86_64/kvm_create_max_vcpus.c tools/testing/selftests/kvm/kvm_create_max_vcpus.c
··· 27 27 printf("Testing creating %d vCPUs, with IDs %d...%d.\n", 28 28 num_vcpus, first_vcpu_id, first_vcpu_id + num_vcpus - 1); 29 29 30 - vm = vm_create(VM_MODE_P52V48_4K, DEFAULT_GUEST_PHY_PAGES, O_RDWR); 30 + vm = vm_create(VM_MODE_DEFAULT, DEFAULT_GUEST_PHY_PAGES, O_RDWR); 31 31 32 32 for (i = 0; i < num_vcpus; i++) { 33 33 int vcpu_id = first_vcpu_id + i;