All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/1] Paravirtualized control register pinning test
@ 2020-02-19 18:04 John Andersen
  2020-02-19 18:04 ` [PATCH 1/1] x86: Add " John Andersen
  0 siblings, 1 reply; 2+ messages in thread
From: John Andersen @ 2020-02-19 18:04 UTC (permalink / raw)
  To: pbonzini, kvm; +Cc: John Andersen

This is the corresponding test for
https://lore.kernel.org/kvm/20200218215902.5655-1-john.s.andersen@intel.com/T/#t

Thank you!

John Andersen (1):
  x86: Add control register pinning test

 x86/Makefile.common |   3 +-
 lib/x86/desc.h      |   1 +
 lib/x86/processor.h |   1 +
 lib/x86/desc.c      |   8 +++
 x86/cr_pin.c        | 163 ++++++++++++++++++++++++++++++++++++++++++++
 x86/pcid.c          |   8 ---
 x86/unittests.cfg   |   4 ++
 7 files changed, 179 insertions(+), 9 deletions(-)
 create mode 100644 x86/cr_pin.c

-- 
2.21.0


^ permalink raw reply	[flat|nested] 2+ messages in thread

* [PATCH 1/1] x86: Add control register pinning test
  2020-02-19 18:04 [PATCH 0/1] Paravirtualized control register pinning test John Andersen
@ 2020-02-19 18:04 ` John Andersen
  0 siblings, 0 replies; 2+ messages in thread
From: John Andersen @ 2020-02-19 18:04 UTC (permalink / raw)
  To: pbonzini, kvm; +Cc: John Andersen

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.

Signed-off-by: John Andersen <john.s.andersen@intel.com>
---
 x86/Makefile.common |   3 +-
 lib/x86/desc.h      |   1 +
 lib/x86/processor.h |   1 +
 lib/x86/desc.c      |   8 +++
 x86/cr_pin.c        | 163 ++++++++++++++++++++++++++++++++++++++++++++
 x86/pcid.c          |   8 ---
 x86/unittests.cfg   |   4 ++
 7 files changed, 179 insertions(+), 9 deletions(-)
 create mode 100644 x86/cr_pin.c

diff --git a/x86/Makefile.common b/x86/Makefile.common
index ab67ca0..bb5e786 100644
--- a/x86/Makefile.common
+++ b/x86/Makefile.common
@@ -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.flat
 
 test_cases: $(tests-common) $(tests)
 
diff --git a/lib/x86/desc.h b/lib/x86/desc.h
index 00b9328..89df883 100644
--- a/lib/x86/desc.h
+++ b/lib/x86/desc.h
@@ -216,6 +216,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);
diff --git a/lib/x86/processor.h b/lib/x86/processor.h
index 03fdf64..dedbac0 100644
--- a/lib/x86/processor.h
+++ b/lib/x86/processor.h
@@ -141,6 +141,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))
diff --git a/lib/x86/desc.c b/lib/x86/desc.c
index 451f504..c9363d0 100644
--- a/lib/x86/desc.c
+++ b/lib/x86/desc.c
@@ -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")
diff --git a/x86/cr_pin.c b/x86/cr_pin.c
new file mode 100644
index 0000000..fd25043
--- /dev/null
+++ b/x86/cr_pin.c
@@ -0,0 +1,163 @@
+/* cr pinning tests */
+
+#include "libcflat.h"
+#include "x86/desc.h"
+#include "x86/processor.h"
+#include "x86/vm.h"
+#include "x86/msr.h"
+
+#define USER_BASE	(1 << 24)
+
+#define CR0_PINNED X86_CR0_WP
+#define CR4_SOME_PINNED (X86_CR4_UMIP | X86_CR4_SMEP)
+#define CR4_ALL_PINNED (CR4_SOME_PINNED | X86_CR4_SMAP)
+
+#define MSR_KVM_CR0_PIN_ALLOWED	0x4b564d06
+#define MSR_KVM_CR4_PIN_ALLOWED	0x4b564d07
+#define MSR_KVM_CR0_PINNED	0x4b564d08
+#define MSR_KVM_CR4_PINNED	0x4b564d09
+
+static void test_cr0_pinning(void)
+{
+	unsigned long long r = 0;
+	ulong cr0 = read_cr0();
+	int vector = 0;
+
+	r = rdmsr(MSR_KVM_CR0_PIN_ALLOWED);
+	report(r == CR0_PINNED, "[CR0] MSR_KVM_CR0_PIN_ALLOWED: %llx", r);
+
+	cr0 |= CR0_PINNED;
+
+	vector = write_cr0_checking(cr0);
+	report(vector == 0, "[CR0] enable pinned bits. vector: %d", vector);
+
+	cr0 = read_cr0();
+	report((cr0 & CR0_PINNED) == CR0_PINNED, "[CR0] after enabling pinned bits: %lx", cr0);
+
+	wrmsr(MSR_KVM_CR0_PINNED, CR0_PINNED);
+	r = rdmsr(MSR_KVM_CR0_PINNED);
+	report(r == CR0_PINNED, "[CR0] enable pinning. MSR_KVM_CR0_PINNED: %llx", r);
+
+	vector = write_cr0_checking(cr0);
+	report(vector == 0, "[CR0] write same value");
+
+	vector = write_cr0_checking(cr0 & ~CR0_PINNED);
+	report(vector == GP_VECTOR, "[CR0] disable pinned bits. vector: %d", vector);
+
+	cr0 = read_cr0();
+	report((cr0 & CR0_PINNED) == CR0_PINNED, "[CR0] pinned bits: %lx", cr0 & CR0_PINNED);
+}
+
+static void test_cr4_pin_allowed(void)
+{
+	unsigned long long r = 0;
+
+	r = rdmsr(MSR_KVM_CR4_PIN_ALLOWED);
+	report(r == CR4_ALL_PINNED, "[CR4] MSR_KVM_CR4_PIN_ALLOWED: %llx", r);
+}
+
+static void test_cr4_pinning_some_pinned(void)
+{
+	unsigned long long r = 0;
+	ulong cr4 = read_cr4();
+	int vector = 0;
+
+	cr4 |= CR4_SOME_PINNED;
+
+	vector = write_cr4_checking(cr4);
+	report(vector == 0, "[CR4 SOME] enable pinned bits. vector: %d", vector);
+
+	wrmsr(MSR_KVM_CR4_PINNED, CR4_SOME_PINNED);
+	r = rdmsr(MSR_KVM_CR4_PINNED);
+	report(r == CR4_SOME_PINNED, "[CR4 SOME] enable pinning. MSR_KVM_CR4_PINNED: %llx", r);
+
+	cr4 = read_cr4();
+	report((cr4 & CR4_SOME_PINNED) == CR4_SOME_PINNED, "[CR4 SOME] after enabling pinned bits: %lx", cr4);
+	report(1, "[CR4 SOME] cr4: 0x%08lx", cr4);
+
+	vector = write_cr4_checking(cr4);
+	report(vector == 0, "[CR4 SOME] write same value");
+
+	vector = write_cr4_checking(cr4 & ~CR4_SOME_PINNED);
+	report(vector == GP_VECTOR, "[CR4 SOME] disable pinned bits. vector: %d", vector);
+
+	cr4 = read_cr4();
+	report((cr4 & CR4_SOME_PINNED) == CR4_SOME_PINNED, "[CR4 SOME] pinned bits: %lx", cr4 & CR4_SOME_PINNED);
+
+	vector = write_cr4_checking(cr4 & ~X86_CR4_SMEP);
+	report(vector == GP_VECTOR, "[CR4 SOME] disable single pinned bit. vector: %d", vector);
+
+	cr4 = read_cr4();
+	report((cr4 & CR4_SOME_PINNED) == CR4_SOME_PINNED, "[CR4 SOME] pinned bits: %lx", cr4 & CR4_SOME_PINNED);
+}
+
+static void test_cr4_pinning_all_pinned(void)
+{
+	unsigned long long r = 0;
+	ulong cr4 = read_cr4();
+	int vector = 0;
+
+	wrmsr(MSR_KVM_CR4_PINNED, CR4_ALL_PINNED);
+	r = rdmsr(MSR_KVM_CR4_PINNED);
+	report(r == CR4_ALL_PINNED, "[CR4 ALL] enable pinning. MSR_KVM_CR4_PINNED: %llx", r);
+
+	cr4 |= CR4_ALL_PINNED;
+
+	vector = write_cr4_checking(cr4);
+	report(vector == 0, "[CR4 ALL] enable pinned bits. vector: %d", vector);
+
+	cr4 = read_cr4();
+	report((cr4 & CR4_ALL_PINNED) == CR4_ALL_PINNED, "[CR4 ALL] after enabling pinned bits: %lx", cr4);
+
+	vector = write_cr4_checking(cr4);
+	report(vector == 0, "[CR4 ALL] write same value");
+
+	vector = write_cr4_checking(cr4 & ~CR4_ALL_PINNED);
+	report(vector == GP_VECTOR, "[CR4 ALL] disable pinned bits. vector: %d", vector);
+
+	cr4 = read_cr4();
+	report((cr4 & CR4_ALL_PINNED) == CR4_ALL_PINNED, "[CR4 ALL] pinned bits: %lx", cr4 & CR4_ALL_PINNED);
+}
+
+static void test_cr4_pinning(void)
+{
+	test_cr4_pin_allowed();
+
+	if (!this_cpu_has(X86_FEATURE_UMIP)) {
+		printf("UMIP not available\n");
+		return;
+	}
+
+	if (!this_cpu_has(X86_FEATURE_SMEP)) {
+		printf("SMEP not available\n");
+		return;
+	}
+
+	test_cr4_pinning_some_pinned();
+
+	if (!this_cpu_has(X86_FEATURE_SMAP)) {
+		printf("SMAP not enabled\n");
+		return;
+	}
+
+	test_cr4_pinning_all_pinned();
+}
+
+int main(int ac, char **av)
+{
+	unsigned long i;
+
+	setup_idt();
+	setup_vm();
+
+	// Map first 16MB as supervisor pages
+	for (i = 0; i < USER_BASE; i += PAGE_SIZE) {
+		*get_pte(phys_to_virt(read_cr3()), phys_to_virt(i)) &= ~PT_USER_MASK;
+	}
+
+	test_cr0_pinning();
+	test_cr4_pinning();
+
+	return report_summary();
+}
+
diff --git a/x86/pcid.c b/x86/pcid.c
index ad9d30c..1f36f7d 100644
--- a/x86/pcid.c
+++ b/x86/pcid.c
@@ -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")
diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index f2401eb..5630bb6 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -245,6 +245,10 @@ arch = x86_64
 file = umip.flat
 extra_params = -cpu qemu64,+umip
 
+[cr_pin]
+file = cr_pin.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"
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-02-19 18:03 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-19 18:04 [PATCH 0/1] Paravirtualized control register pinning test John Andersen
2020-02-19 18:04 ` [PATCH 1/1] x86: Add " John Andersen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.