Skip to content

Commit a0c468e

Browse files
committed
Merge tag 'kvm-x86-selftests-6.20' of https://github.com/kvm-x86/linux into HEAD
KVM selftests changes for 6.20 - Add a regression test for TPR<=>CR8 synchronization and IRQ masking. - Overhaul selftest's MMU infrastructure to genericize stage-2 MMU support, and extend x86's infrastructure to support EPT and NPT (for L2 guests). - Extend several nested VMX tests to also cover nested SVM. - Add a selftest for nested VMLOAD/VMSAVE. - Rework the nested dirty log test, originally added as a regression test for PML where KVM logged L2 GPAs instead of L1 GPAs, to improve test coverage and to hopefully make the test easier to understand and maintain.
2 parents 5490063 + a91cc48 commit a0c468e

27 files changed

+1243
-571
lines changed

tools/testing/selftests/kvm/Makefile.kvm

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,13 @@ TEST_GEN_PROGS_x86 += x86/kvm_buslock_test
8989
TEST_GEN_PROGS_x86 += x86/monitor_mwait_test
9090
TEST_GEN_PROGS_x86 += x86/msrs_test
9191
TEST_GEN_PROGS_x86 += x86/nested_close_kvm_test
92+
TEST_GEN_PROGS_x86 += x86/nested_dirty_log_test
9293
TEST_GEN_PROGS_x86 += x86/nested_emulation_test
9394
TEST_GEN_PROGS_x86 += x86/nested_exceptions_test
9495
TEST_GEN_PROGS_x86 += x86/nested_invalid_cr3_test
9596
TEST_GEN_PROGS_x86 += x86/nested_tsc_adjust_test
9697
TEST_GEN_PROGS_x86 += x86/nested_tsc_scaling_test
98+
TEST_GEN_PROGS_x86 += x86/nested_vmsave_vmload_test
9799
TEST_GEN_PROGS_x86 += x86/platform_info_test
98100
TEST_GEN_PROGS_x86 += x86/pmu_counters_test
99101
TEST_GEN_PROGS_x86 += x86/pmu_event_filter_test
@@ -115,7 +117,6 @@ TEST_GEN_PROGS_x86 += x86/ucna_injection_test
115117
TEST_GEN_PROGS_x86 += x86/userspace_io_test
116118
TEST_GEN_PROGS_x86 += x86/userspace_msr_exit_test
117119
TEST_GEN_PROGS_x86 += x86/vmx_apic_access_test
118-
TEST_GEN_PROGS_x86 += x86/vmx_dirty_log_test
119120
TEST_GEN_PROGS_x86 += x86/vmx_exception_with_invalid_guest_state
120121
TEST_GEN_PROGS_x86 += x86/vmx_msrs_test
121122
TEST_GEN_PROGS_x86 += x86/vmx_invalid_nested_guest_state
@@ -124,6 +125,7 @@ TEST_GEN_PROGS_x86 += x86/vmx_set_nested_state_test
124125
TEST_GEN_PROGS_x86 += x86/apic_bus_clock_test
125126
TEST_GEN_PROGS_x86 += x86/xapic_ipi_test
126127
TEST_GEN_PROGS_x86 += x86/xapic_state_test
128+
TEST_GEN_PROGS_x86 += x86/xapic_tpr_test
127129
TEST_GEN_PROGS_x86 += x86/xcr0_cpuid_test
128130
TEST_GEN_PROGS_x86 += x86/xss_msr_test
129131
TEST_GEN_PROGS_x86 += x86/debug_regs

tools/testing/selftests/kvm/include/arm64/kvm_util_arch.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#ifndef SELFTEST_KVM_UTIL_ARCH_H
33
#define SELFTEST_KVM_UTIL_ARCH_H
44

5+
struct kvm_mmu_arch {};
6+
57
struct kvm_vm_arch {
68
bool has_gic;
79
int gic_fd;

tools/testing/selftests/kvm/include/kvm_util.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,19 @@ enum kvm_mem_region_type {
8888
NR_MEM_REGIONS,
8989
};
9090

91+
struct kvm_mmu {
92+
bool pgd_created;
93+
uint64_t pgd;
94+
int pgtable_levels;
95+
96+
struct kvm_mmu_arch arch;
97+
};
98+
9199
struct kvm_vm {
92100
int mode;
93101
unsigned long type;
94102
int kvm_fd;
95103
int fd;
96-
unsigned int pgtable_levels;
97104
unsigned int page_size;
98105
unsigned int page_shift;
99106
unsigned int pa_bits;
@@ -104,13 +111,18 @@ struct kvm_vm {
104111
struct sparsebit *vpages_valid;
105112
struct sparsebit *vpages_mapped;
106113
bool has_irqchip;
107-
bool pgd_created;
108114
vm_paddr_t ucall_mmio_addr;
109-
vm_paddr_t pgd;
110115
vm_vaddr_t handlers;
111116
uint32_t dirty_ring_size;
112117
uint64_t gpa_tag_mask;
113118

119+
/*
120+
* "mmu" is the guest's stage-1, with a short name because the vast
121+
* majority of tests only care about the stage-1 MMU.
122+
*/
123+
struct kvm_mmu mmu;
124+
struct kvm_mmu stage2_mmu;
125+
114126
struct kvm_vm_arch arch;
115127

116128
struct kvm_binary_stats stats;

tools/testing/selftests/kvm/include/loongarch/kvm_util_arch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#ifndef SELFTEST_KVM_UTIL_ARCH_H
33
#define SELFTEST_KVM_UTIL_ARCH_H
44

5+
struct kvm_mmu_arch {};
56
struct kvm_vm_arch {};
67

78
#endif // SELFTEST_KVM_UTIL_ARCH_H

tools/testing/selftests/kvm/include/riscv/kvm_util_arch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#ifndef SELFTEST_KVM_UTIL_ARCH_H
33
#define SELFTEST_KVM_UTIL_ARCH_H
44

5+
struct kvm_mmu_arch {};
56
struct kvm_vm_arch {};
67

78
#endif // SELFTEST_KVM_UTIL_ARCH_H

tools/testing/selftests/kvm/include/s390/kvm_util_arch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#ifndef SELFTEST_KVM_UTIL_ARCH_H
33
#define SELFTEST_KVM_UTIL_ARCH_H
44

5+
struct kvm_mmu_arch {};
56
struct kvm_vm_arch {};
67

78
#endif // SELFTEST_KVM_UTIL_ARCH_H

tools/testing/selftests/kvm/include/x86/apic.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#define GET_APIC_ID_FIELD(x) (((x) >> 24) & 0xFF)
2929
#define APIC_TASKPRI 0x80
3030
#define APIC_PROCPRI 0xA0
31+
#define GET_APIC_PRI(x) (((x) & GENMASK(7, 4)) >> 4)
32+
#define SET_APIC_PRI(x, y) (((x) & ~GENMASK(7, 4)) | (y << 4))
3133
#define APIC_EOI 0xB0
3234
#define APIC_SPIV 0xF0
3335
#define APIC_SPIV_FOCUS_DISABLED (1 << 9)
@@ -67,6 +69,7 @@
6769
#define APIC_TMICT 0x380
6870
#define APIC_TMCCT 0x390
6971
#define APIC_TDCR 0x3E0
72+
#define APIC_SELF_IPI 0x3F0
7073

7174
void apic_disable(void);
7275
void xapic_enable(void);

tools/testing/selftests/kvm/include/x86/kvm_util_arch.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,28 @@
1010

1111
extern bool is_forced_emulation_enabled;
1212

13+
struct pte_masks {
14+
uint64_t present;
15+
uint64_t writable;
16+
uint64_t user;
17+
uint64_t readable;
18+
uint64_t executable;
19+
uint64_t accessed;
20+
uint64_t dirty;
21+
uint64_t huge;
22+
uint64_t nx;
23+
uint64_t c;
24+
uint64_t s;
25+
26+
uint64_t always_set;
27+
};
28+
29+
struct kvm_mmu_arch {
30+
struct pte_masks pte_masks;
31+
};
32+
33+
struct kvm_mmu;
34+
1335
struct kvm_vm_arch {
1436
vm_vaddr_t gdt;
1537
vm_vaddr_t tss;

tools/testing/selftests/kvm/include/x86/processor.h

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ struct kvm_x86_cpu_feature {
201201
#define X86_FEATURE_TSCRATEMSR KVM_X86_CPU_FEATURE(0x8000000A, 0, EDX, 4)
202202
#define X86_FEATURE_PAUSEFILTER KVM_X86_CPU_FEATURE(0x8000000A, 0, EDX, 10)
203203
#define X86_FEATURE_PFTHRESHOLD KVM_X86_CPU_FEATURE(0x8000000A, 0, EDX, 12)
204+
#define X86_FEATURE_V_VMSAVE_VMLOAD KVM_X86_CPU_FEATURE(0x8000000A, 0, EDX, 15)
204205
#define X86_FEATURE_VGIF KVM_X86_CPU_FEATURE(0x8000000A, 0, EDX, 16)
205206
#define X86_FEATURE_IDLE_HLT KVM_X86_CPU_FEATURE(0x8000000A, 0, EDX, 30)
206207
#define X86_FEATURE_SEV KVM_X86_CPU_FEATURE(0x8000001F, 0, EAX, 1)
@@ -362,16 +363,6 @@ static inline unsigned int x86_model(unsigned int eax)
362363
return ((eax >> 12) & 0xf0) | ((eax >> 4) & 0x0f);
363364
}
364365

365-
/* Page table bitfield declarations */
366-
#define PTE_PRESENT_MASK BIT_ULL(0)
367-
#define PTE_WRITABLE_MASK BIT_ULL(1)
368-
#define PTE_USER_MASK BIT_ULL(2)
369-
#define PTE_ACCESSED_MASK BIT_ULL(5)
370-
#define PTE_DIRTY_MASK BIT_ULL(6)
371-
#define PTE_LARGE_MASK BIT_ULL(7)
372-
#define PTE_GLOBAL_MASK BIT_ULL(8)
373-
#define PTE_NX_MASK BIT_ULL(63)
374-
375366
#define PHYSICAL_PAGE_MASK GENMASK_ULL(51, 12)
376367

377368
#define PAGE_SHIFT 12
@@ -436,8 +427,10 @@ struct kvm_x86_state {
436427

437428
static inline uint64_t get_desc64_base(const struct desc64 *desc)
438429
{
439-
return ((uint64_t)desc->base3 << 32) |
440-
(desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24));
430+
return (uint64_t)desc->base3 << 32 |
431+
(uint64_t)desc->base2 << 24 |
432+
(uint64_t)desc->base1 << 16 |
433+
(uint64_t)desc->base0;
441434
}
442435

443436
static inline uint64_t rdtsc(void)
@@ -1367,9 +1360,7 @@ static inline bool kvm_is_ignore_msrs(void)
13671360
return get_kvm_param_bool("ignore_msrs");
13681361
}
13691362

1370-
uint64_t *__vm_get_page_table_entry(struct kvm_vm *vm, uint64_t vaddr,
1371-
int *level);
1372-
uint64_t *vm_get_page_table_entry(struct kvm_vm *vm, uint64_t vaddr);
1363+
uint64_t *vm_get_pte(struct kvm_vm *vm, uint64_t vaddr);
13731364

13741365
uint64_t kvm_hypercall(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2,
13751366
uint64_t a3);
@@ -1451,10 +1442,52 @@ enum pg_level {
14511442
#define PG_SIZE_2M PG_LEVEL_SIZE(PG_LEVEL_2M)
14521443
#define PG_SIZE_1G PG_LEVEL_SIZE(PG_LEVEL_1G)
14531444

1454-
void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, int level);
1445+
#define PTE_PRESENT_MASK(mmu) ((mmu)->arch.pte_masks.present)
1446+
#define PTE_WRITABLE_MASK(mmu) ((mmu)->arch.pte_masks.writable)
1447+
#define PTE_USER_MASK(mmu) ((mmu)->arch.pte_masks.user)
1448+
#define PTE_READABLE_MASK(mmu) ((mmu)->arch.pte_masks.readable)
1449+
#define PTE_EXECUTABLE_MASK(mmu) ((mmu)->arch.pte_masks.executable)
1450+
#define PTE_ACCESSED_MASK(mmu) ((mmu)->arch.pte_masks.accessed)
1451+
#define PTE_DIRTY_MASK(mmu) ((mmu)->arch.pte_masks.dirty)
1452+
#define PTE_HUGE_MASK(mmu) ((mmu)->arch.pte_masks.huge)
1453+
#define PTE_NX_MASK(mmu) ((mmu)->arch.pte_masks.nx)
1454+
#define PTE_C_BIT_MASK(mmu) ((mmu)->arch.pte_masks.c)
1455+
#define PTE_S_BIT_MASK(mmu) ((mmu)->arch.pte_masks.s)
1456+
#define PTE_ALWAYS_SET_MASK(mmu) ((mmu)->arch.pte_masks.always_set)
1457+
1458+
/*
1459+
* For PTEs without a PRESENT bit (i.e. EPT entries), treat the PTE as present
1460+
* if it's executable or readable, as EPT supports execute-only PTEs, but not
1461+
* write-only PTEs.
1462+
*/
1463+
#define is_present_pte(mmu, pte) \
1464+
(PTE_PRESENT_MASK(mmu) ? \
1465+
!!(*(pte) & PTE_PRESENT_MASK(mmu)) : \
1466+
!!(*(pte) & (PTE_READABLE_MASK(mmu) | PTE_EXECUTABLE_MASK(mmu))))
1467+
#define is_executable_pte(mmu, pte) \
1468+
((*(pte) & (PTE_EXECUTABLE_MASK(mmu) | PTE_NX_MASK(mmu))) == PTE_EXECUTABLE_MASK(mmu))
1469+
#define is_writable_pte(mmu, pte) (!!(*(pte) & PTE_WRITABLE_MASK(mmu)))
1470+
#define is_user_pte(mmu, pte) (!!(*(pte) & PTE_USER_MASK(mmu)))
1471+
#define is_accessed_pte(mmu, pte) (!!(*(pte) & PTE_ACCESSED_MASK(mmu)))
1472+
#define is_dirty_pte(mmu, pte) (!!(*(pte) & PTE_DIRTY_MASK(mmu)))
1473+
#define is_huge_pte(mmu, pte) (!!(*(pte) & PTE_HUGE_MASK(mmu)))
1474+
#define is_nx_pte(mmu, pte) (!is_executable_pte(mmu, pte))
1475+
1476+
void tdp_mmu_init(struct kvm_vm *vm, int pgtable_levels,
1477+
struct pte_masks *pte_masks);
1478+
1479+
void __virt_pg_map(struct kvm_vm *vm, struct kvm_mmu *mmu, uint64_t vaddr,
1480+
uint64_t paddr, int level);
14551481
void virt_map_level(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
14561482
uint64_t nr_bytes, int level);
14571483

1484+
void vm_enable_tdp(struct kvm_vm *vm);
1485+
bool kvm_cpu_has_tdp(void);
1486+
void tdp_map(struct kvm_vm *vm, uint64_t nested_paddr, uint64_t paddr, uint64_t size);
1487+
void tdp_identity_map_default_memslots(struct kvm_vm *vm);
1488+
void tdp_identity_map_1g(struct kvm_vm *vm, uint64_t addr, uint64_t size);
1489+
uint64_t *tdp_get_pte(struct kvm_vm *vm, uint64_t l2_gpa);
1490+
14581491
/*
14591492
* Basic CPU control in CR0
14601493
*/

tools/testing/selftests/kvm/include/x86/svm_util.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ struct svm_test_data {
2727
void *msr; /* gva */
2828
void *msr_hva;
2929
uint64_t msr_gpa;
30+
31+
/* NPT */
32+
uint64_t ncr3_gpa;
3033
};
3134

3235
static inline void vmmcall(void)
@@ -57,6 +60,12 @@ struct svm_test_data *vcpu_alloc_svm(struct kvm_vm *vm, vm_vaddr_t *p_svm_gva);
5760
void generic_svm_setup(struct svm_test_data *svm, void *guest_rip, void *guest_rsp);
5861
void run_guest(struct vmcb *vmcb, uint64_t vmcb_gpa);
5962

63+
static inline bool kvm_cpu_has_npt(void)
64+
{
65+
return kvm_cpu_has(X86_FEATURE_NPT);
66+
}
67+
void vm_enable_npt(struct kvm_vm *vm);
68+
6069
int open_sev_dev_path_or_exit(void);
6170

6271
#endif /* SELFTEST_KVM_SVM_UTILS_H */

0 commit comments

Comments
 (0)