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.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into HEAD

* More selftests
* Improved KVM_S390_MEM_OP ioctl input checking
* Add kvm_valid_regs and kvm_dirty_regs invalid bit checking

+503 -185
+8 -6
Documentation/virt/kvm/api.txt
··· 3092 3092 flag KVM_S390_MEMOP_F_INJECT_EXCEPTION is set in the "flags" field. 3093 3093 3094 3094 The start address of the memory region has to be specified in the "gaddr" 3095 - field, and the length of the region in the "size" field. "buf" is the buffer 3096 - supplied by the userspace application where the read data should be written 3097 - to for KVM_S390_MEMOP_LOGICAL_READ, or where the data that should be written 3098 - is stored for a KVM_S390_MEMOP_LOGICAL_WRITE. "buf" is unused and can be NULL 3099 - when KVM_S390_MEMOP_F_CHECK_ONLY is specified. "ar" designates the access 3100 - register number to be used. 3095 + field, and the length of the region in the "size" field (which must not 3096 + be 0). The maximum value for "size" can be obtained by checking the 3097 + KVM_CAP_S390_MEM_OP capability. "buf" is the buffer supplied by the 3098 + userspace application where the read data should be written to for 3099 + KVM_S390_MEMOP_LOGICAL_READ, or where the data that should be written is 3100 + stored for a KVM_S390_MEMOP_LOGICAL_WRITE. When KVM_S390_MEMOP_F_CHECK_ONLY 3101 + is specified, "buf" is unused and can be NULL. "ar" designates the access 3102 + register number to be used; the valid range is 0..15. 3101 3103 3102 3104 The "reserved" field is meant for future extensions. It is not used by 3103 3105 KVM with the currently defined set of flags.
+6
arch/s390/include/uapi/asm/kvm.h
··· 231 231 #define KVM_SYNC_GSCB (1UL << 9) 232 232 #define KVM_SYNC_BPBC (1UL << 10) 233 233 #define KVM_SYNC_ETOKEN (1UL << 11) 234 + 235 + #define KVM_SYNC_S390_VALID_FIELDS \ 236 + (KVM_SYNC_PREFIX | KVM_SYNC_GPRS | KVM_SYNC_ACRS | KVM_SYNC_CRS | \ 237 + KVM_SYNC_ARCH0 | KVM_SYNC_PFAULT | KVM_SYNC_VRS | KVM_SYNC_RICCB | \ 238 + KVM_SYNC_FPRS | KVM_SYNC_GSCB | KVM_SYNC_BPBC | KVM_SYNC_ETOKEN) 239 + 234 240 /* length and alignment of the sdnx as a power of two */ 235 241 #define SDNXC 8 236 242 #define SDNXL (1UL << SDNXC)
+5 -1
arch/s390/kvm/kvm-s390.c
··· 3998 3998 if (kvm_run->immediate_exit) 3999 3999 return -EINTR; 4000 4000 4001 + if (kvm_run->kvm_valid_regs & ~KVM_SYNC_S390_VALID_FIELDS || 4002 + kvm_run->kvm_dirty_regs & ~KVM_SYNC_S390_VALID_FIELDS) 4003 + return -EINVAL; 4004 + 4001 4005 vcpu_load(vcpu); 4002 4006 4003 4007 if (guestdbg_exit_pending(vcpu)) { ··· 4259 4255 const u64 supported_flags = KVM_S390_MEMOP_F_INJECT_EXCEPTION 4260 4256 | KVM_S390_MEMOP_F_CHECK_ONLY; 4261 4257 4262 - if (mop->flags & ~supported_flags) 4258 + if (mop->flags & ~supported_flags || mop->ar >= NUM_ACRS || !mop->size) 4263 4259 return -EINVAL; 4264 4260 4265 4261 if (mop->size > MEM_OP_MAX_SIZE)
+6 -4
tools/testing/selftests/kvm/Makefile
··· 7 7 KSFT_KHDR_INSTALL := 1 8 8 UNAME_M := $(shell uname -m) 9 9 10 - LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/ucall.c lib/sparsebit.c 11 - LIBKVM_x86_64 = lib/x86_64/processor.c lib/x86_64/vmx.c 12 - LIBKVM_aarch64 = lib/aarch64/processor.c 13 - LIBKVM_s390x = lib/s390x/processor.c 10 + LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/sparsebit.c 11 + LIBKVM_x86_64 = lib/x86_64/processor.c lib/x86_64/vmx.c lib/x86_64/ucall.c 12 + LIBKVM_aarch64 = lib/aarch64/processor.c lib/aarch64/ucall.c 13 + LIBKVM_s390x = lib/s390x/processor.c lib/s390x/ucall.c 14 14 15 15 TEST_GEN_PROGS_x86_64 = x86_64/cr4_cpuid_sync_test 16 16 TEST_GEN_PROGS_x86_64 += x86_64/evmcs_test ··· 32 32 TEST_GEN_PROGS_aarch64 += dirty_log_test 33 33 TEST_GEN_PROGS_aarch64 += kvm_create_max_vcpus 34 34 35 + TEST_GEN_PROGS_s390x = s390x/memop 35 36 TEST_GEN_PROGS_s390x += s390x/sync_regs_test 37 + TEST_GEN_PROGS_s390x += dirty_log_test 36 38 TEST_GEN_PROGS_s390x += kvm_create_max_vcpus 37 39 38 40 TEST_GEN_PROGS += $(TEST_GEN_PROGS_$(UNAME_M))
+53 -8
tools/testing/selftests/kvm/dirty_log_test.c
··· 26 26 /* The memory slot index to track dirty pages */ 27 27 #define TEST_MEM_SLOT_INDEX 1 28 28 29 - /* Default guest test memory offset, 1G */ 30 - #define DEFAULT_GUEST_TEST_MEM 0x40000000 29 + /* Default guest test virtual memory offset */ 30 + #define DEFAULT_GUEST_TEST_MEM 0xc0000000 31 31 32 32 /* How many pages to dirty for each guest loop */ 33 33 #define TEST_PAGES_PER_LOOP 1024 ··· 37 37 38 38 /* Interval for each host loop (ms) */ 39 39 #define TEST_HOST_LOOP_INTERVAL 10UL 40 + 41 + /* Dirty bitmaps are always little endian, so we need to swap on big endian */ 42 + #if defined(__s390x__) 43 + # define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7) 44 + # define test_bit_le(nr, addr) \ 45 + test_bit((nr) ^ BITOP_LE_SWIZZLE, addr) 46 + # define set_bit_le(nr, addr) \ 47 + set_bit((nr) ^ BITOP_LE_SWIZZLE, addr) 48 + # define clear_bit_le(nr, addr) \ 49 + clear_bit((nr) ^ BITOP_LE_SWIZZLE, addr) 50 + # define test_and_set_bit_le(nr, addr) \ 51 + test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, addr) 52 + # define test_and_clear_bit_le(nr, addr) \ 53 + test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, addr) 54 + #else 55 + # define test_bit_le test_bit 56 + # define set_bit_le set_bit 57 + # define clear_bit_le clear_bit 58 + # define test_and_set_bit_le test_and_set_bit 59 + # define test_and_clear_bit_le test_and_clear_bit 60 + #endif 40 61 41 62 /* 42 63 * Guest/Host shared variables. Ensure addr_gva2hva() and/or ··· 90 69 */ 91 70 static void guest_code(void) 92 71 { 72 + uint64_t addr; 93 73 int i; 74 + 75 + /* 76 + * On s390x, all pages of a 1M segment are initially marked as dirty 77 + * when a page of the segment is written to for the very first time. 78 + * To compensate this specialty in this test, we need to touch all 79 + * pages during the first iteration. 80 + */ 81 + for (i = 0; i < guest_num_pages; i++) { 82 + addr = guest_test_virt_mem + i * guest_page_size; 83 + *(uint64_t *)addr = READ_ONCE(iteration); 84 + } 94 85 95 86 while (true) { 96 87 for (i = 0; i < TEST_PAGES_PER_LOOP; i++) { 97 - uint64_t addr = guest_test_virt_mem; 88 + addr = guest_test_virt_mem; 98 89 addr += (READ_ONCE(random_array[i]) % guest_num_pages) 99 90 * guest_page_size; 100 91 addr &= ~(host_page_size - 1); ··· 191 158 value_ptr = host_test_mem + page * host_page_size; 192 159 193 160 /* If this is a special page that we were tracking... */ 194 - if (test_and_clear_bit(page, host_bmap_track)) { 161 + if (test_and_clear_bit_le(page, host_bmap_track)) { 195 162 host_track_next_count++; 196 - TEST_ASSERT(test_bit(page, bmap), 163 + TEST_ASSERT(test_bit_le(page, bmap), 197 164 "Page %"PRIu64" should have its dirty bit " 198 165 "set in this iteration but it is missing", 199 166 page); 200 167 } 201 168 202 - if (test_bit(page, bmap)) { 169 + if (test_bit_le(page, bmap)) { 203 170 host_dirty_count++; 204 171 /* 205 172 * If the bit is set, the value written onto ··· 242 209 * should report its dirtyness in the 243 210 * next run 244 211 */ 245 - set_bit(page, host_bmap_track); 212 + set_bit_le(page, host_bmap_track); 246 213 } 247 214 } 248 215 } ··· 326 293 * case where the size is not aligned to 64 pages. 327 294 */ 328 295 guest_num_pages = (1ul << (30 - guest_page_shift)) + 16; 296 + #ifdef __s390x__ 297 + /* Round up to multiple of 1M (segment size) */ 298 + guest_num_pages = (guest_num_pages + 0xff) & ~0xffUL; 299 + #endif 329 300 host_page_size = getpagesize(); 330 301 host_num_pages = (guest_num_pages * guest_page_size) / host_page_size + 331 302 !!((guest_num_pages * guest_page_size) % host_page_size); ··· 340 303 } else { 341 304 guest_test_phys_mem = phys_offset; 342 305 } 306 + 307 + #ifdef __s390x__ 308 + /* Align to 1M (segment size) */ 309 + guest_test_phys_mem &= ~((1 << 20) - 1); 310 + #endif 343 311 344 312 DEBUG("guest physical test memory offset: 0x%lx\n", guest_test_phys_mem); 345 313 ··· 379 337 vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid()); 380 338 #endif 381 339 #ifdef __aarch64__ 382 - ucall_init(vm, UCALL_MMIO, NULL); 340 + ucall_init(vm, NULL); 383 341 #endif 384 342 385 343 /* Export the shared variables to the guest */ ··· 495 453 vm_guest_mode_params_init(VM_MODE_P48V48_4K, true, true); 496 454 vm_guest_mode_params_init(VM_MODE_P48V48_64K, true, true); 497 455 } 456 + #endif 457 + #ifdef __s390x__ 458 + vm_guest_mode_params_init(VM_MODE_P40V48_4K, true, true); 498 459 #endif 499 460 500 461 while ((opt = getopt(argc, argv, "hi:I:p:m:")) != -1) {
+1 -7
tools/testing/selftests/kvm/include/kvm_util.h
··· 165 165 memcpy(&(g), _p, sizeof(g)); \ 166 166 }) 167 167 168 - /* ucall implementation types */ 169 - typedef enum { 170 - UCALL_PIO, 171 - UCALL_MMIO, 172 - } ucall_type_t; 173 - 174 168 /* Common ucalls */ 175 169 enum { 176 170 UCALL_NONE, ··· 180 186 uint64_t args[UCALL_MAX_ARGS]; 181 187 }; 182 188 183 - void ucall_init(struct kvm_vm *vm, ucall_type_t type, void *arg); 189 + void ucall_init(struct kvm_vm *vm, void *arg); 184 190 void ucall_uninit(struct kvm_vm *vm); 185 191 void ucall(uint64_t cmd, int nargs, ...); 186 192 uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc);
+112
tools/testing/selftests/kvm/lib/aarch64/ucall.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * ucall support. A ucall is a "hypercall to userspace". 4 + * 5 + * Copyright (C) 2018, Red Hat, Inc. 6 + */ 7 + #include "kvm_util.h" 8 + #include "../kvm_util_internal.h" 9 + 10 + static vm_vaddr_t *ucall_exit_mmio_addr; 11 + 12 + static bool ucall_mmio_init(struct kvm_vm *vm, vm_paddr_t gpa) 13 + { 14 + if (kvm_userspace_memory_region_find(vm, gpa, gpa + 1)) 15 + return false; 16 + 17 + virt_pg_map(vm, gpa, gpa, 0); 18 + 19 + ucall_exit_mmio_addr = (vm_vaddr_t *)gpa; 20 + sync_global_to_guest(vm, ucall_exit_mmio_addr); 21 + 22 + return true; 23 + } 24 + 25 + void ucall_init(struct kvm_vm *vm, void *arg) 26 + { 27 + vm_paddr_t gpa, start, end, step, offset; 28 + unsigned int bits; 29 + bool ret; 30 + 31 + if (arg) { 32 + gpa = (vm_paddr_t)arg; 33 + ret = ucall_mmio_init(vm, gpa); 34 + TEST_ASSERT(ret, "Can't set ucall mmio address to %lx", gpa); 35 + return; 36 + } 37 + 38 + /* 39 + * Find an address within the allowed physical and virtual address 40 + * spaces, that does _not_ have a KVM memory region associated with 41 + * it. Identity mapping an address like this allows the guest to 42 + * access it, but as KVM doesn't know what to do with it, it 43 + * will assume it's something userspace handles and exit with 44 + * KVM_EXIT_MMIO. Well, at least that's how it works for AArch64. 45 + * Here we start with a guess that the addresses around 5/8th 46 + * of the allowed space are unmapped and then work both down and 47 + * up from there in 1/16th allowed space sized steps. 48 + * 49 + * Note, we need to use VA-bits - 1 when calculating the allowed 50 + * virtual address space for an identity mapping because the upper 51 + * half of the virtual address space is the two's complement of the 52 + * lower and won't match physical addresses. 53 + */ 54 + bits = vm->va_bits - 1; 55 + bits = vm->pa_bits < bits ? vm->pa_bits : bits; 56 + end = 1ul << bits; 57 + start = end * 5 / 8; 58 + step = end / 16; 59 + for (offset = 0; offset < end - start; offset += step) { 60 + if (ucall_mmio_init(vm, start - offset)) 61 + return; 62 + if (ucall_mmio_init(vm, start + offset)) 63 + return; 64 + } 65 + TEST_ASSERT(false, "Can't find a ucall mmio address"); 66 + } 67 + 68 + void ucall_uninit(struct kvm_vm *vm) 69 + { 70 + ucall_exit_mmio_addr = 0; 71 + sync_global_to_guest(vm, ucall_exit_mmio_addr); 72 + } 73 + 74 + void ucall(uint64_t cmd, int nargs, ...) 75 + { 76 + struct ucall uc = { 77 + .cmd = cmd, 78 + }; 79 + va_list va; 80 + int i; 81 + 82 + nargs = nargs <= UCALL_MAX_ARGS ? nargs : UCALL_MAX_ARGS; 83 + 84 + va_start(va, nargs); 85 + for (i = 0; i < nargs; ++i) 86 + uc.args[i] = va_arg(va, uint64_t); 87 + va_end(va); 88 + 89 + *ucall_exit_mmio_addr = (vm_vaddr_t)&uc; 90 + } 91 + 92 + uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc) 93 + { 94 + struct kvm_run *run = vcpu_state(vm, vcpu_id); 95 + struct ucall ucall = {}; 96 + 97 + if (run->exit_reason == KVM_EXIT_MMIO && 98 + run->mmio.phys_addr == (uint64_t)ucall_exit_mmio_addr) { 99 + vm_vaddr_t gva; 100 + 101 + TEST_ASSERT(run->mmio.is_write && run->mmio.len == 8, 102 + "Unexpected ucall exit mmio address access"); 103 + memcpy(&gva, run->mmio.data, sizeof(gva)); 104 + memcpy(&ucall, addr_gva2hva(vm, gva), sizeof(ucall)); 105 + 106 + vcpu_run_complete_io(vm, vcpu_id); 107 + if (uc) 108 + memcpy(uc, &ucall, sizeof(ucall)); 109 + } 110 + 111 + return ucall.cmd; 112 + }
+56
tools/testing/selftests/kvm/lib/s390x/ucall.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * ucall support. A ucall is a "hypercall to userspace". 4 + * 5 + * Copyright (C) 2019 Red Hat, Inc. 6 + */ 7 + #include "kvm_util.h" 8 + 9 + void ucall_init(struct kvm_vm *vm, void *arg) 10 + { 11 + } 12 + 13 + void ucall_uninit(struct kvm_vm *vm) 14 + { 15 + } 16 + 17 + void ucall(uint64_t cmd, int nargs, ...) 18 + { 19 + struct ucall uc = { 20 + .cmd = cmd, 21 + }; 22 + va_list va; 23 + int i; 24 + 25 + nargs = nargs <= UCALL_MAX_ARGS ? nargs : UCALL_MAX_ARGS; 26 + 27 + va_start(va, nargs); 28 + for (i = 0; i < nargs; ++i) 29 + uc.args[i] = va_arg(va, uint64_t); 30 + va_end(va); 31 + 32 + /* Exit via DIAGNOSE 0x501 (normally used for breakpoints) */ 33 + asm volatile ("diag 0,%0,0x501" : : "a"(&uc) : "memory"); 34 + } 35 + 36 + uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc) 37 + { 38 + struct kvm_run *run = vcpu_state(vm, vcpu_id); 39 + struct ucall ucall = {}; 40 + 41 + if (run->exit_reason == KVM_EXIT_S390_SIEIC && 42 + run->s390_sieic.icptcode == 4 && 43 + (run->s390_sieic.ipa >> 8) == 0x83 && /* 0x83 means DIAGNOSE */ 44 + (run->s390_sieic.ipb >> 16) == 0x501) { 45 + int reg = run->s390_sieic.ipa & 0xf; 46 + 47 + memcpy(&ucall, addr_gva2hva(vm, run->s.regs.gprs[reg]), 48 + sizeof(ucall)); 49 + 50 + vcpu_run_complete_io(vm, vcpu_id); 51 + if (uc) 52 + memcpy(uc, &ucall, sizeof(ucall)); 53 + } 54 + 55 + return ucall.cmd; 56 + }
-157
tools/testing/selftests/kvm/lib/ucall.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * ucall support. A ucall is a "hypercall to userspace". 4 - * 5 - * Copyright (C) 2018, Red Hat, Inc. 6 - */ 7 - #include "kvm_util.h" 8 - #include "kvm_util_internal.h" 9 - 10 - #define UCALL_PIO_PORT ((uint16_t)0x1000) 11 - 12 - static ucall_type_t ucall_type; 13 - static vm_vaddr_t *ucall_exit_mmio_addr; 14 - 15 - static bool ucall_mmio_init(struct kvm_vm *vm, vm_paddr_t gpa) 16 - { 17 - if (kvm_userspace_memory_region_find(vm, gpa, gpa + 1)) 18 - return false; 19 - 20 - virt_pg_map(vm, gpa, gpa, 0); 21 - 22 - ucall_exit_mmio_addr = (vm_vaddr_t *)gpa; 23 - sync_global_to_guest(vm, ucall_exit_mmio_addr); 24 - 25 - return true; 26 - } 27 - 28 - void ucall_init(struct kvm_vm *vm, ucall_type_t type, void *arg) 29 - { 30 - ucall_type = type; 31 - sync_global_to_guest(vm, ucall_type); 32 - 33 - if (type == UCALL_PIO) 34 - return; 35 - 36 - if (type == UCALL_MMIO) { 37 - vm_paddr_t gpa, start, end, step, offset; 38 - unsigned bits; 39 - bool ret; 40 - 41 - if (arg) { 42 - gpa = (vm_paddr_t)arg; 43 - ret = ucall_mmio_init(vm, gpa); 44 - TEST_ASSERT(ret, "Can't set ucall mmio address to %lx", gpa); 45 - return; 46 - } 47 - 48 - /* 49 - * Find an address within the allowed physical and virtual address 50 - * spaces, that does _not_ have a KVM memory region associated with 51 - * it. Identity mapping an address like this allows the guest to 52 - * access it, but as KVM doesn't know what to do with it, it 53 - * will assume it's something userspace handles and exit with 54 - * KVM_EXIT_MMIO. Well, at least that's how it works for AArch64. 55 - * Here we start with a guess that the addresses around 5/8th 56 - * of the allowed space are unmapped and then work both down and 57 - * up from there in 1/16th allowed space sized steps. 58 - * 59 - * Note, we need to use VA-bits - 1 when calculating the allowed 60 - * virtual address space for an identity mapping because the upper 61 - * half of the virtual address space is the two's complement of the 62 - * lower and won't match physical addresses. 63 - */ 64 - bits = vm->va_bits - 1; 65 - bits = vm->pa_bits < bits ? vm->pa_bits : bits; 66 - end = 1ul << bits; 67 - start = end * 5 / 8; 68 - step = end / 16; 69 - for (offset = 0; offset < end - start; offset += step) { 70 - if (ucall_mmio_init(vm, start - offset)) 71 - return; 72 - if (ucall_mmio_init(vm, start + offset)) 73 - return; 74 - } 75 - TEST_ASSERT(false, "Can't find a ucall mmio address"); 76 - } 77 - } 78 - 79 - void ucall_uninit(struct kvm_vm *vm) 80 - { 81 - ucall_type = 0; 82 - sync_global_to_guest(vm, ucall_type); 83 - ucall_exit_mmio_addr = 0; 84 - sync_global_to_guest(vm, ucall_exit_mmio_addr); 85 - } 86 - 87 - static void ucall_pio_exit(struct ucall *uc) 88 - { 89 - #ifdef __x86_64__ 90 - asm volatile("in %[port], %%al" 91 - : : [port] "d" (UCALL_PIO_PORT), "D" (uc) : "rax"); 92 - #endif 93 - } 94 - 95 - static void ucall_mmio_exit(struct ucall *uc) 96 - { 97 - *ucall_exit_mmio_addr = (vm_vaddr_t)uc; 98 - } 99 - 100 - void ucall(uint64_t cmd, int nargs, ...) 101 - { 102 - struct ucall uc = { 103 - .cmd = cmd, 104 - }; 105 - va_list va; 106 - int i; 107 - 108 - nargs = nargs <= UCALL_MAX_ARGS ? nargs : UCALL_MAX_ARGS; 109 - 110 - va_start(va, nargs); 111 - for (i = 0; i < nargs; ++i) 112 - uc.args[i] = va_arg(va, uint64_t); 113 - va_end(va); 114 - 115 - switch (ucall_type) { 116 - case UCALL_PIO: 117 - ucall_pio_exit(&uc); 118 - break; 119 - case UCALL_MMIO: 120 - ucall_mmio_exit(&uc); 121 - break; 122 - }; 123 - } 124 - 125 - uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc) 126 - { 127 - struct kvm_run *run = vcpu_state(vm, vcpu_id); 128 - struct ucall ucall = {}; 129 - bool got_ucall = false; 130 - 131 - #ifdef __x86_64__ 132 - if (ucall_type == UCALL_PIO && run->exit_reason == KVM_EXIT_IO && 133 - run->io.port == UCALL_PIO_PORT) { 134 - struct kvm_regs regs; 135 - vcpu_regs_get(vm, vcpu_id, &regs); 136 - memcpy(&ucall, addr_gva2hva(vm, (vm_vaddr_t)regs.rdi), sizeof(ucall)); 137 - got_ucall = true; 138 - } 139 - #endif 140 - if (ucall_type == UCALL_MMIO && run->exit_reason == KVM_EXIT_MMIO && 141 - run->mmio.phys_addr == (uint64_t)ucall_exit_mmio_addr) { 142 - vm_vaddr_t gva; 143 - TEST_ASSERT(run->mmio.is_write && run->mmio.len == 8, 144 - "Unexpected ucall exit mmio address access"); 145 - memcpy(&gva, run->mmio.data, sizeof(gva)); 146 - memcpy(&ucall, addr_gva2hva(vm, gva), sizeof(ucall)); 147 - got_ucall = true; 148 - } 149 - 150 - if (got_ucall) { 151 - vcpu_run_complete_io(vm, vcpu_id); 152 - if (uc) 153 - memcpy(uc, &ucall, sizeof(ucall)); 154 - } 155 - 156 - return ucall.cmd; 157 - }
+56
tools/testing/selftests/kvm/lib/x86_64/ucall.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * ucall support. A ucall is a "hypercall to userspace". 4 + * 5 + * Copyright (C) 2018, Red Hat, Inc. 6 + */ 7 + #include "kvm_util.h" 8 + 9 + #define UCALL_PIO_PORT ((uint16_t)0x1000) 10 + 11 + void ucall_init(struct kvm_vm *vm, void *arg) 12 + { 13 + } 14 + 15 + void ucall_uninit(struct kvm_vm *vm) 16 + { 17 + } 18 + 19 + void ucall(uint64_t cmd, int nargs, ...) 20 + { 21 + struct ucall uc = { 22 + .cmd = cmd, 23 + }; 24 + va_list va; 25 + int i; 26 + 27 + nargs = nargs <= UCALL_MAX_ARGS ? nargs : UCALL_MAX_ARGS; 28 + 29 + va_start(va, nargs); 30 + for (i = 0; i < nargs; ++i) 31 + uc.args[i] = va_arg(va, uint64_t); 32 + va_end(va); 33 + 34 + asm volatile("in %[port], %%al" 35 + : : [port] "d" (UCALL_PIO_PORT), "D" (&uc) : "rax"); 36 + } 37 + 38 + uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc) 39 + { 40 + struct kvm_run *run = vcpu_state(vm, vcpu_id); 41 + struct ucall ucall = {}; 42 + 43 + if (run->exit_reason == KVM_EXIT_IO && run->io.port == UCALL_PIO_PORT) { 44 + struct kvm_regs regs; 45 + 46 + vcpu_regs_get(vm, vcpu_id, &regs); 47 + memcpy(&ucall, addr_gva2hva(vm, (vm_vaddr_t)regs.rdi), 48 + sizeof(ucall)); 49 + 50 + vcpu_run_complete_io(vm, vcpu_id); 51 + if (uc) 52 + memcpy(uc, &ucall, sizeof(ucall)); 53 + } 54 + 55 + return ucall.cmd; 56 + }
+166
tools/testing/selftests/kvm/s390x/memop.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Test for s390x KVM_S390_MEM_OP 4 + * 5 + * Copyright (C) 2019, Red Hat, Inc. 6 + */ 7 + 8 + #include <stdio.h> 9 + #include <stdlib.h> 10 + #include <string.h> 11 + #include <sys/ioctl.h> 12 + 13 + #include "test_util.h" 14 + #include "kvm_util.h" 15 + 16 + #define VCPU_ID 1 17 + 18 + static uint8_t mem1[65536]; 19 + static uint8_t mem2[65536]; 20 + 21 + static void guest_code(void) 22 + { 23 + int i; 24 + 25 + for (;;) { 26 + for (i = 0; i < sizeof(mem2); i++) 27 + mem2[i] = mem1[i]; 28 + GUEST_SYNC(0); 29 + } 30 + } 31 + 32 + int main(int argc, char *argv[]) 33 + { 34 + struct kvm_vm *vm; 35 + struct kvm_run *run; 36 + struct kvm_s390_mem_op ksmo; 37 + int rv, i, maxsize; 38 + 39 + setbuf(stdout, NULL); /* Tell stdout not to buffer its content */ 40 + 41 + maxsize = kvm_check_cap(KVM_CAP_S390_MEM_OP); 42 + if (!maxsize) { 43 + fprintf(stderr, "CAP_S390_MEM_OP not supported -> skip test\n"); 44 + exit(KSFT_SKIP); 45 + } 46 + if (maxsize > sizeof(mem1)) 47 + maxsize = sizeof(mem1); 48 + 49 + /* Create VM */ 50 + vm = vm_create_default(VCPU_ID, 0, guest_code); 51 + run = vcpu_state(vm, VCPU_ID); 52 + 53 + for (i = 0; i < sizeof(mem1); i++) 54 + mem1[i] = i * i + i; 55 + 56 + /* Set the first array */ 57 + ksmo.gaddr = addr_gva2gpa(vm, (uintptr_t)mem1); 58 + ksmo.flags = 0; 59 + ksmo.size = maxsize; 60 + ksmo.op = KVM_S390_MEMOP_LOGICAL_WRITE; 61 + ksmo.buf = (uintptr_t)mem1; 62 + ksmo.ar = 0; 63 + vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); 64 + 65 + /* Let the guest code copy the first array to the second */ 66 + vcpu_run(vm, VCPU_ID); 67 + TEST_ASSERT(run->exit_reason == KVM_EXIT_S390_SIEIC, 68 + "Unexpected exit reason: %u (%s)\n", 69 + run->exit_reason, 70 + exit_reason_str(run->exit_reason)); 71 + 72 + memset(mem2, 0xaa, sizeof(mem2)); 73 + 74 + /* Get the second array */ 75 + ksmo.gaddr = (uintptr_t)mem2; 76 + ksmo.flags = 0; 77 + ksmo.size = maxsize; 78 + ksmo.op = KVM_S390_MEMOP_LOGICAL_READ; 79 + ksmo.buf = (uintptr_t)mem2; 80 + ksmo.ar = 0; 81 + vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); 82 + 83 + TEST_ASSERT(!memcmp(mem1, mem2, maxsize), 84 + "Memory contents do not match!"); 85 + 86 + /* Check error conditions - first bad size: */ 87 + ksmo.gaddr = (uintptr_t)mem1; 88 + ksmo.flags = 0; 89 + ksmo.size = -1; 90 + ksmo.op = KVM_S390_MEMOP_LOGICAL_WRITE; 91 + ksmo.buf = (uintptr_t)mem1; 92 + ksmo.ar = 0; 93 + rv = _vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); 94 + TEST_ASSERT(rv == -1 && errno == E2BIG, "ioctl allows insane sizes"); 95 + 96 + /* Zero size: */ 97 + ksmo.gaddr = (uintptr_t)mem1; 98 + ksmo.flags = 0; 99 + ksmo.size = 0; 100 + ksmo.op = KVM_S390_MEMOP_LOGICAL_WRITE; 101 + ksmo.buf = (uintptr_t)mem1; 102 + ksmo.ar = 0; 103 + rv = _vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); 104 + TEST_ASSERT(rv == -1 && (errno == EINVAL || errno == ENOMEM), 105 + "ioctl allows 0 as size"); 106 + 107 + /* Bad flags: */ 108 + ksmo.gaddr = (uintptr_t)mem1; 109 + ksmo.flags = -1; 110 + ksmo.size = maxsize; 111 + ksmo.op = KVM_S390_MEMOP_LOGICAL_WRITE; 112 + ksmo.buf = (uintptr_t)mem1; 113 + ksmo.ar = 0; 114 + rv = _vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); 115 + TEST_ASSERT(rv == -1 && errno == EINVAL, "ioctl allows all flags"); 116 + 117 + /* Bad operation: */ 118 + ksmo.gaddr = (uintptr_t)mem1; 119 + ksmo.flags = 0; 120 + ksmo.size = maxsize; 121 + ksmo.op = -1; 122 + ksmo.buf = (uintptr_t)mem1; 123 + ksmo.ar = 0; 124 + rv = _vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); 125 + TEST_ASSERT(rv == -1 && errno == EINVAL, "ioctl allows bad operations"); 126 + 127 + /* Bad guest address: */ 128 + ksmo.gaddr = ~0xfffUL; 129 + ksmo.flags = KVM_S390_MEMOP_F_CHECK_ONLY; 130 + ksmo.size = maxsize; 131 + ksmo.op = KVM_S390_MEMOP_LOGICAL_WRITE; 132 + ksmo.buf = (uintptr_t)mem1; 133 + ksmo.ar = 0; 134 + rv = _vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); 135 + TEST_ASSERT(rv > 0, "ioctl does not report bad guest memory access"); 136 + 137 + /* Bad host address: */ 138 + ksmo.gaddr = (uintptr_t)mem1; 139 + ksmo.flags = 0; 140 + ksmo.size = maxsize; 141 + ksmo.op = KVM_S390_MEMOP_LOGICAL_WRITE; 142 + ksmo.buf = 0; 143 + ksmo.ar = 0; 144 + rv = _vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); 145 + TEST_ASSERT(rv == -1 && errno == EFAULT, 146 + "ioctl does not report bad host memory address"); 147 + 148 + /* Bad access register: */ 149 + run->psw_mask &= ~(3UL << (63 - 17)); 150 + run->psw_mask |= 1UL << (63 - 17); /* Enable AR mode */ 151 + vcpu_run(vm, VCPU_ID); /* To sync new state to SIE block */ 152 + ksmo.gaddr = (uintptr_t)mem1; 153 + ksmo.flags = 0; 154 + ksmo.size = maxsize; 155 + ksmo.op = KVM_S390_MEMOP_LOGICAL_WRITE; 156 + ksmo.buf = (uintptr_t)mem1; 157 + ksmo.ar = 17; 158 + rv = _vcpu_ioctl(vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo); 159 + TEST_ASSERT(rv == -1 && errno == EINVAL, "ioctl allows ARs > 15"); 160 + run->psw_mask &= ~(3UL << (63 - 17)); /* Disable AR mode */ 161 + vcpu_run(vm, VCPU_ID); /* Run to sync new state */ 162 + 163 + kvm_vm_free(vm); 164 + 165 + return 0; 166 + }
+34 -2
tools/testing/selftests/kvm/s390x/sync_regs_test.c
··· 25 25 26 26 static void guest_code(void) 27 27 { 28 + register u64 stage asm("11") = 0; 29 + 28 30 for (;;) { 29 - asm volatile ("diag 0,0,0x501"); 30 - asm volatile ("ahi 11,1"); 31 + GUEST_SYNC(0); 32 + asm volatile ("ahi %0,1" : : "r"(stage)); 31 33 } 32 34 } 33 35 ··· 84 82 vm = vm_create_default(VCPU_ID, 0, guest_code); 85 83 86 84 run = vcpu_state(vm, VCPU_ID); 85 + 86 + /* Request reading invalid register set from VCPU. */ 87 + run->kvm_valid_regs = INVALID_SYNC_FIELD; 88 + rv = _vcpu_run(vm, VCPU_ID); 89 + TEST_ASSERT(rv < 0 && errno == EINVAL, 90 + "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n", 91 + rv); 92 + vcpu_state(vm, VCPU_ID)->kvm_valid_regs = 0; 93 + 94 + run->kvm_valid_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS; 95 + rv = _vcpu_run(vm, VCPU_ID); 96 + TEST_ASSERT(rv < 0 && errno == EINVAL, 97 + "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n", 98 + rv); 99 + vcpu_state(vm, VCPU_ID)->kvm_valid_regs = 0; 100 + 101 + /* Request setting invalid register set into VCPU. */ 102 + run->kvm_dirty_regs = INVALID_SYNC_FIELD; 103 + rv = _vcpu_run(vm, VCPU_ID); 104 + TEST_ASSERT(rv < 0 && errno == EINVAL, 105 + "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n", 106 + rv); 107 + vcpu_state(vm, VCPU_ID)->kvm_dirty_regs = 0; 108 + 109 + run->kvm_dirty_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS; 110 + rv = _vcpu_run(vm, VCPU_ID); 111 + TEST_ASSERT(rv < 0 && errno == EINVAL, 112 + "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n", 113 + rv); 114 + vcpu_state(vm, VCPU_ID)->kvm_dirty_regs = 0; 87 115 88 116 /* Request and verify all valid register sets. */ 89 117 run->kvm_valid_regs = TEST_SYNC_FIELDS;