summaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests
diff options
context:
space:
mode:
authorPeter Xu <peterx@redhat.com>2019-08-29 21:36:18 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2019-09-24 07:37:22 -0400
commit567a9f1e9deb273a2c02dd18c254208537fcefaa (patch)
treeefc6f180c0248bae650effc207bd5716024f7e67 /tools/testing/selftests
parent338eb29876b9e571273175f167fcd58d9441ac8e (diff)
KVM: selftests: Introduce VM_MODE_PXXV48_4K
The naming VM_MODE_P52V48_4K is explicit but unclear when used on x86_64 machines, because x86_64 machines are having various physical address width rather than some static values. Here's some examples: - Intel Xeon E3-1220: 36 bits - Intel Core i7-8650: 39 bits - AMD EPYC 7251: 48 bits All of them are using 48 bits linear address width but with totally different physical address width (and most of the old machines should be less than 52 bits). Let's create a new guest mode called VM_MODE_PXXV48_4K for current x86_64 tests and make it as the default to replace the old naming of VM_MODE_P52V48_4K because it shows more clearly that the PA width is not really a constant. Meanwhile we also stop assuming all the x86 machines are having 52 bits PA width but instead we fetch the real vm->pa_bits from CPUID 0x80000008 during runtime. We currently make this exclusively used by x86_64 but no other arch. As a slight touch up, moving DEBUG macro from dirty_log_test.c to kvm_util.h so lib can use it too. Signed-off-by: Peter Xu <peterx@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'tools/testing/selftests')
-rw-r--r--tools/testing/selftests/kvm/dirty_log_test.c5
-rw-r--r--tools/testing/selftests/kvm/include/kvm_util.h11
-rw-r--r--tools/testing/selftests/kvm/include/x86_64/processor.h3
-rw-r--r--tools/testing/selftests/kvm/lib/aarch64/processor.c3
-rw-r--r--tools/testing/selftests/kvm/lib/kvm_util.c29
-rw-r--r--tools/testing/selftests/kvm/lib/x86_64/processor.c30
6 files changed, 67 insertions, 14 deletions
diff --git a/tools/testing/selftests/kvm/dirty_log_test.c b/tools/testing/selftests/kvm/dirty_log_test.c
index cf2099abb121..12c36fa356a8 100644
--- a/tools/testing/selftests/kvm/dirty_log_test.c
+++ b/tools/testing/selftests/kvm/dirty_log_test.c
@@ -19,8 +19,6 @@
19#include "kvm_util.h" 19#include "kvm_util.h"
20#include "processor.h" 20#include "processor.h"
21 21
22#define DEBUG printf
23
24#define VCPU_ID 1 22#define VCPU_ID 1
25 23
26/* The memory slot index to track dirty pages */ 24/* The memory slot index to track dirty pages */
@@ -289,6 +287,7 @@ static void run_test(enum vm_guest_mode mode, unsigned long iterations,
289 287
290 switch (mode) { 288 switch (mode) {
291 case VM_MODE_P52V48_4K: 289 case VM_MODE_P52V48_4K:
290 case VM_MODE_PXXV48_4K:
292 guest_pa_bits = 52; 291 guest_pa_bits = 52;
293 guest_page_shift = 12; 292 guest_page_shift = 12;
294 break; 293 break;
@@ -488,7 +487,7 @@ int main(int argc, char *argv[])
488#endif 487#endif
489 488
490#ifdef __x86_64__ 489#ifdef __x86_64__
491 vm_guest_mode_params_init(VM_MODE_P52V48_4K, true, true); 490 vm_guest_mode_params_init(VM_MODE_PXXV48_4K, true, true);
492#endif 491#endif
493#ifdef __aarch64__ 492#ifdef __aarch64__
494 vm_guest_mode_params_init(VM_MODE_P40V48_4K, true, true); 493 vm_guest_mode_params_init(VM_MODE_P40V48_4K, true, true);
diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
index b2c15135f596..ef3259c5e856 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -24,6 +24,12 @@ struct kvm_vm;
24typedef uint64_t vm_paddr_t; /* Virtual Machine (Guest) physical address */ 24typedef uint64_t vm_paddr_t; /* Virtual Machine (Guest) physical address */
25typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */ 25typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */
26 26
27#ifndef NDEBUG
28#define DEBUG(...) printf(__VA_ARGS__);
29#else
30#define DEBUG(...)
31#endif
32
27/* Minimum allocated guest virtual and physical addresses */ 33/* Minimum allocated guest virtual and physical addresses */
28#define KVM_UTIL_MIN_VADDR 0x2000 34#define KVM_UTIL_MIN_VADDR 0x2000
29 35
@@ -38,11 +44,14 @@ enum vm_guest_mode {
38 VM_MODE_P48V48_64K, 44 VM_MODE_P48V48_64K,
39 VM_MODE_P40V48_4K, 45 VM_MODE_P40V48_4K,
40 VM_MODE_P40V48_64K, 46 VM_MODE_P40V48_64K,
47 VM_MODE_PXXV48_4K, /* For 48bits VA but ANY bits PA */
41 NUM_VM_MODES, 48 NUM_VM_MODES,
42}; 49};
43 50
44#ifdef __aarch64__ 51#if defined(__aarch64__)
45#define VM_MODE_DEFAULT VM_MODE_P40V48_4K 52#define VM_MODE_DEFAULT VM_MODE_P40V48_4K
53#elif defined(__x86_64__)
54#define VM_MODE_DEFAULT VM_MODE_PXXV48_4K
46#else 55#else
47#define VM_MODE_DEFAULT VM_MODE_P52V48_4K 56#define VM_MODE_DEFAULT VM_MODE_P52V48_4K
48#endif 57#endif
diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h
index 80d19740d2dc..0c17f2ee685e 100644
--- a/tools/testing/selftests/kvm/include/x86_64/processor.h
+++ b/tools/testing/selftests/kvm/include/x86_64/processor.h
@@ -325,6 +325,9 @@ uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index);
325void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index, 325void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
326 uint64_t msr_value); 326 uint64_t msr_value);
327 327
328uint32_t kvm_get_cpuid_max(void);
329void kvm_get_cpu_address_width(unsigned int *pa_bits, unsigned int *va_bits);
330
328/* 331/*
329 * Basic CPU control in CR0 332 * Basic CPU control in CR0
330 */ 333 */
diff --git a/tools/testing/selftests/kvm/lib/aarch64/processor.c b/tools/testing/selftests/kvm/lib/aarch64/processor.c
index 486400a97374..86036a59a668 100644
--- a/tools/testing/selftests/kvm/lib/aarch64/processor.c
+++ b/tools/testing/selftests/kvm/lib/aarch64/processor.c
@@ -264,6 +264,9 @@ void aarch64_vcpu_setup(struct kvm_vm *vm, int vcpuid, struct kvm_vcpu_init *ini
264 case VM_MODE_P52V48_4K: 264 case VM_MODE_P52V48_4K:
265 TEST_ASSERT(false, "AArch64 does not support 4K sized pages " 265 TEST_ASSERT(false, "AArch64 does not support 4K sized pages "
266 "with 52-bit physical address ranges"); 266 "with 52-bit physical address ranges");
267 case VM_MODE_PXXV48_4K:
268 TEST_ASSERT(false, "AArch64 does not support 4K sized pages "
269 "with ANY-bit physical address ranges");
267 case VM_MODE_P52V48_64K: 270 case VM_MODE_P52V48_64K:
268 tcr_el1 |= 1ul << 14; /* TG0 = 64KB */ 271 tcr_el1 |= 1ul << 14; /* TG0 = 64KB */
269 tcr_el1 |= 6ul << 32; /* IPS = 52 bits */ 272 tcr_el1 |= 6ul << 32; /* IPS = 52 bits */
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index 34a8a6572c7c..bb8f993b25fb 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -8,6 +8,7 @@
8#include "test_util.h" 8#include "test_util.h"
9#include "kvm_util.h" 9#include "kvm_util.h"
10#include "kvm_util_internal.h" 10#include "kvm_util_internal.h"
11#include "processor.h"
11 12
12#include <assert.h> 13#include <assert.h>
13#include <sys/mman.h> 14#include <sys/mman.h>
@@ -101,12 +102,13 @@ static void vm_open(struct kvm_vm *vm, int perm)
101} 102}
102 103
103const char * const vm_guest_mode_string[] = { 104const char * const vm_guest_mode_string[] = {
104 "PA-bits:52, VA-bits:48, 4K pages", 105 "PA-bits:52, VA-bits:48, 4K pages",
105 "PA-bits:52, VA-bits:48, 64K pages", 106 "PA-bits:52, VA-bits:48, 64K pages",
106 "PA-bits:48, VA-bits:48, 4K pages", 107 "PA-bits:48, VA-bits:48, 4K pages",
107 "PA-bits:48, VA-bits:48, 64K pages", 108 "PA-bits:48, VA-bits:48, 64K pages",
108 "PA-bits:40, VA-bits:48, 4K pages", 109 "PA-bits:40, VA-bits:48, 4K pages",
109 "PA-bits:40, VA-bits:48, 64K pages", 110 "PA-bits:40, VA-bits:48, 64K pages",
111 "PA-bits:ANY, VA-bits:48, 4K pages",
110}; 112};
111_Static_assert(sizeof(vm_guest_mode_string)/sizeof(char *) == NUM_VM_MODES, 113_Static_assert(sizeof(vm_guest_mode_string)/sizeof(char *) == NUM_VM_MODES,
112 "Missing new mode strings?"); 114 "Missing new mode strings?");
@@ -184,6 +186,21 @@ struct kvm_vm *_vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
184 vm->page_size = 0x10000; 186 vm->page_size = 0x10000;
185 vm->page_shift = 16; 187 vm->page_shift = 16;
186 break; 188 break;
189 case VM_MODE_PXXV48_4K:
190#ifdef __x86_64__
191 kvm_get_cpu_address_width(&vm->pa_bits, &vm->va_bits);
192 TEST_ASSERT(vm->va_bits == 48, "Linear address width "
193 "(%d bits) not supported", vm->va_bits);
194 vm->pgtable_levels = 4;
195 vm->page_size = 0x1000;
196 vm->page_shift = 12;
197 DEBUG("Guest physical address width detected: %d\n",
198 vm->pa_bits);
199#else
200 TEST_ASSERT(false, "VM_MODE_PXXV48_4K not supported on "
201 "non-x86 platforms");
202#endif
203 break;
187 default: 204 default:
188 TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", mode); 205 TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", mode);
189 } 206 }
diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c
index 0a5e487dbc50..c53dbc6bc568 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/processor.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c
@@ -228,7 +228,7 @@ void sregs_dump(FILE *stream, struct kvm_sregs *sregs,
228 228
229void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot) 229void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot)
230{ 230{
231 TEST_ASSERT(vm->mode == VM_MODE_P52V48_4K, "Attempt to use " 231 TEST_ASSERT(vm->mode == VM_MODE_PXXV48_4K, "Attempt to use "
232 "unknown or unsupported guest mode, mode: 0x%x", vm->mode); 232 "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
233 233
234 /* If needed, create page map l4 table. */ 234 /* If needed, create page map l4 table. */
@@ -261,7 +261,7 @@ void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
261 uint16_t index[4]; 261 uint16_t index[4];
262 struct pageMapL4Entry *pml4e; 262 struct pageMapL4Entry *pml4e;
263 263
264 TEST_ASSERT(vm->mode == VM_MODE_P52V48_4K, "Attempt to use " 264 TEST_ASSERT(vm->mode == VM_MODE_PXXV48_4K, "Attempt to use "
265 "unknown or unsupported guest mode, mode: 0x%x", vm->mode); 265 "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
266 266
267 TEST_ASSERT((vaddr % vm->page_size) == 0, 267 TEST_ASSERT((vaddr % vm->page_size) == 0,
@@ -547,7 +547,7 @@ vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
547 struct pageDirectoryEntry *pde; 547 struct pageDirectoryEntry *pde;
548 struct pageTableEntry *pte; 548 struct pageTableEntry *pte;
549 549
550 TEST_ASSERT(vm->mode == VM_MODE_P52V48_4K, "Attempt to use " 550 TEST_ASSERT(vm->mode == VM_MODE_PXXV48_4K, "Attempt to use "
551 "unknown or unsupported guest mode, mode: 0x%x", vm->mode); 551 "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
552 552
553 index[0] = (gva >> 12) & 0x1ffu; 553 index[0] = (gva >> 12) & 0x1ffu;
@@ -621,7 +621,7 @@ static void vcpu_setup(struct kvm_vm *vm, int vcpuid, int pgd_memslot, int gdt_m
621 kvm_setup_gdt(vm, &sregs.gdt, gdt_memslot, pgd_memslot); 621 kvm_setup_gdt(vm, &sregs.gdt, gdt_memslot, pgd_memslot);
622 622
623 switch (vm->mode) { 623 switch (vm->mode) {
624 case VM_MODE_P52V48_4K: 624 case VM_MODE_PXXV48_4K:
625 sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG; 625 sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG;
626 sregs.cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR; 626 sregs.cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR;
627 sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX); 627 sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX);
@@ -1157,3 +1157,25 @@ bool is_intel_cpu(void)
1157 chunk = (const uint32_t *)("GenuineIntel"); 1157 chunk = (const uint32_t *)("GenuineIntel");
1158 return (ebx == chunk[0] && edx == chunk[1] && ecx == chunk[2]); 1158 return (ebx == chunk[0] && edx == chunk[1] && ecx == chunk[2]);
1159} 1159}
1160
1161uint32_t kvm_get_cpuid_max(void)
1162{
1163 return kvm_get_supported_cpuid_entry(0x80000000)->eax;
1164}
1165
1166void kvm_get_cpu_address_width(unsigned int *pa_bits, unsigned int *va_bits)
1167{
1168 struct kvm_cpuid_entry2 *entry;
1169 bool pae;
1170
1171 /* SDM 4.1.4 */
1172 if (kvm_get_cpuid_max() < 0x80000008) {
1173 pae = kvm_get_supported_cpuid_entry(1)->edx & (1 << 6);
1174 *pa_bits = pae ? 36 : 32;
1175 *va_bits = 32;
1176 } else {
1177 entry = kvm_get_supported_cpuid_entry(0x80000008);
1178 *pa_bits = entry->eax & 0xff;
1179 *va_bits = (entry->eax >> 8) & 0xff;
1180 }
1181}