x86: Add control register pinning tests
PATCH RESEND 1/1 x86: Add control register pinning tests
Paravirutalized control register pinning adds MSRs guests can use to discover which bits in CR0/4 they may pin, and MSRs for activating pinning for any of those bits.
We check that the bits allowed to be pinned for CR4 are UMIP, SMEP, and SMAP. Only WP should be allowed to be pinned in CR0.
We turn on all of the allowed bits, pin them, then attempt to disable them. We verify that the attempt to disable was unsuccessful, and that it generated a general protection fault.
For nested, we check that for when pinning enabled in L1, changing HOST_CR0/4 will not result in the un-setting of pinned bits. The VMX CR pinning tests is it's own test so that the pinning doesn't potentially affect other tests within the same .flat testing VM.
--- x86/Makefile.common | 3 +- lib/x86/desc.h | 1 + lib/x86/msr.h | 8 ++ lib/x86/processor.h | 1 + lib/x86/desc.c | 8 ++ x86/cr_pin_high.c | 208 ++++++++++++++++++++++++++++++++++++++++++++ x86/cr_pin_low.c | 60 +++++++++++++ x86/pcid.c | 8 -- x86/vmx_tests.c | 139 +++++++++++++++++++++++++++++ x86/unittests.cfg | 16 +++- 10 files changed, 442 insertions(+), 10 deletions(-) create mode 100644 x86/cr_pin_high.c create mode 100644 x86/cr_pin_low.c
x86/Makefile.common +2 -1
@@ -58,7 +58,8 @@ tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \ $(TEST_DIR)/init.flat $(TEST_DIR)/smap.flat \ $(TEST_DIR)/hyperv_synic.flat $(TEST_DIR)/hyperv_stimer.flat \ $(TEST_DIR)/hyperv_connections.flat \ - $(TEST_DIR)/umip.flat $(TEST_DIR)/tsx-ctrl.flat + $(TEST_DIR)/umip.flat $(TEST_DIR)/tsx-ctrl.flat \ + $(TEST_DIR)/cr_pin_low.flat $(TEST_DIR)/cr_pin_high.flat test_cases: $(tests-common) $(tests)
lib/x86/desc.h +1 -0
@@ -211,6 +211,7 @@ extern tss64_t tss;#endif unsigned exception_vector (void ); +int write_cr0_checking (unsigned long val);int write_cr4_checking (unsigned long val);unsigned exception_error_code (void );bool exception_rflags_rf (void );
lib/x86/msr.h +8 -0
@@ -431,4 +431,12 @@#define MSR_VM_IGNNE 0xc0010115#define MSR_VM_HSAVE_PA 0xc0010117 +/* KVM MSRs */ +#define MSR_KVM_CR0_PIN_ALLOWED 0x4b564d08 +#define MSR_KVM_CR4_PIN_ALLOWED 0x4b564d09 +#define MSR_KVM_CR0_PINNED_LOW 0x4b564d0a +#define MSR_KVM_CR0_PINNED_HIGH 0x4b564d0b +#define MSR_KVM_CR4_PINNED_LOW 0x4b564d0c +#define MSR_KVM_CR4_PINNED_HIGH 0x4b564d0d +#endif /* _ASM_X86_MSR_INDEX_H */
lib/x86/processor.h +1 -0
@@ -146,6 +146,7 @@ static inline u8 cpuid_maxphyaddr(void)#define X86_FEATURE_SMEP (CPUID(0x7, 0, EBX, 7))#define X86_FEATURE_INVPCID (CPUID(0x7, 0, EBX, 10))#define X86_FEATURE_RTM (CPUID(0x7, 0, EBX, 11)) +#define X86_FEATURE_SMEP (CPUID(0x7, 0, EBX, 7))#define X86_FEATURE_SMAP (CPUID(0x7, 0, EBX, 20))#define X86_FEATURE_PCOMMIT (CPUID(0x7, 0, EBX, 22))#define X86_FEATURE_CLFLUSHOPT (CPUID(0x7, 0, EBX, 23))
lib/x86/desc.c +8 -0
@@ -251,6 +251,14 @@ unsigned exception_vector(void)return vector; } +int write_cr0_checking (unsigned long val) +{ + asm volatile(ASM_TRY("1f") + "mov %0, %%cr0\n\t" + "1:" : : "r" (val)); +return exception_vector (); +} +int write_cr4_checking (unsigned long val) { asm volatile(ASM_TRY("1f")
x86/cr_pin_high.c new file +208 -0
208 lines not on this page · raw message
x86/cr_pin_low.c new file +60 -0
60 lines not on this page · raw message
x86/pcid.c +0 -8
@@ -10,14 +10,6 @@ struct invpcid_desc { unsigned long addr : 64; }; -static int write_cr0_checking (unsigned long val) -{ - asm volatile(ASM_TRY("1f") - "mov %0, %%cr0\n\t" - "1:": : "r" (val)); -return exception_vector (); -} -static int invpcid_checking (unsigned long type,void *desc) { asm volatile (ASM_TRY("1f")
x86/vmx_tests.c +139 -0
151 lines not on this page · raw message
x86/unittests.cfg +15 -1
@@ -245,9 +245,17 @@ arch = x86_64 file = umip.flat extra_params = -cpu qemu64,+umip +[cr_pin_low] +file = cr_pin_low.flat +extra_params = -cpu qemu64,+umip,+smap,+smep + +[cr_pin_high] +file = cr_pin_high.flat +extra_params = -cpu qemu64,+umip,+smap,+smep + [vmx] file = vmx.flat -extra_params = -cpu host,+vmx -append "-exit_monitor_from_l2_test -ept_access* -vmx_smp* -vmx_vmcs_shadow_test -atomic_switch_overflow_msrs_test -vmx_init_signal_test -vmx_apic_passthrough_tpr_threshold_test" +extra_params = -cpu host,+vmx -append "-exit_monitor_from_l2_test -ept_access* -vmx_smp* -vmx_vmcs_shadow_test -atomic_switch_overflow_msrs_test -vmx_init_signal_test -vmx_apic_passthrough_tpr_threshold_test -vmx_cr_pin_test" arch = x86_64 groups = vmx
@@ -306,6 +314,12 @@ extra_params = -cpu host,+vmx -append vmx_vmcs_shadow_test arch = x86_64 groups = vmx +[vmx_cr_pin_test] +file = vmx.flat +extra_params = -cpu host,+vmx -append vmx_cr_pin_test +arch = x86_64 +groups = vmx + [debug] file = debug.flat arch = x86_64
Signature · 1 line
2.21.0