[kvm-unit-tests PATCH 5/6] x86: Cache availability of forced emulation during setup_idt()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Cache whether or not forced emulation is availability during setup_idt()
so that tests can force emulation (or not) in contexts where taking an
exception of any kind will fail.

Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
---
 lib/x86/desc.c   | 22 ++++++++++++++++++++++
 lib/x86/desc.h   | 14 +-------------
 x86/access.c     |  2 +-
 x86/emulator.c   | 11 +++++------
 x86/emulator64.c |  2 +-
 x86/la57.c       |  2 +-
 x86/lam.c        |  2 +-
 x86/msr.c        |  2 +-
 x86/pmu.c        |  2 +-
 9 files changed, 34 insertions(+), 25 deletions(-)

diff --git a/lib/x86/desc.c b/lib/x86/desc.c
index 5748f900..fca37b9a 100644
--- a/lib/x86/desc.c
+++ b/lib/x86/desc.c
@@ -298,6 +298,22 @@ static void *idt_handlers[32] = {
 	[21] = &cp_fault,
 };
 
+bool is_fep_available;
+
+static bool __is_fep_available(void)
+{
+	/*
+	 * Use the non-FEP ASM_TRY() as KVM will inject a #UD on the prefix
+	 * itself if forced emulation is not available.
+	 */
+	asm goto(ASM_TRY("%l[fep_unavailable]")
+		 KVM_FEP "nop\n\t"
+		 ::: "memory" : fep_unavailable);
+	return true;
+fep_unavailable:
+	return false;
+}
+
 void setup_idt(void)
 {
 	int i;
@@ -311,6 +327,12 @@ void setup_idt(void)
 	}
 
 	load_idt();
+
+	/*
+	 * Detect support for forced emulation *after* loading the IDT, as this
+	 * will #UD if FEP is unavailable.
+	 */
+	is_fep_available = __is_fep_available();
 }
 
 void load_idt(void)
diff --git a/lib/x86/desc.h b/lib/x86/desc.h
index a1e60e78..68f38f3d 100644
--- a/lib/x86/desc.h
+++ b/lib/x86/desc.h
@@ -164,19 +164,7 @@ typedef struct  __attribute__((packed)) {
 #define KVM_FEP "ud2; .byte 'k', 'v', 'm';"
 #define ASM_TRY_FEP(catch) __ASM_TRY(KVM_FEP, catch)
 
-static inline bool is_fep_available(void)
-{
-	/*
-	 * Use the non-FEP ASM_TRY() as KVM will inject a #UD on the prefix
-	 * itself if forced emulation is not available.
-	 */
-	asm goto(ASM_TRY("%l[fep_unavailable]")
-		 KVM_FEP "nop\n\t"
-		 ::: "memory" : fep_unavailable);
-	return true;
-fep_unavailable:
-	return false;
-}
+extern bool is_fep_available;
 
 typedef struct {
 	unsigned short offset0;
diff --git a/x86/access.c b/x86/access.c
index f90a72d6..d94910bf 100644
--- a/x86/access.c
+++ b/x86/access.c
@@ -1232,7 +1232,7 @@ void ac_test_run(int pt_levels, bool force_emulation)
 	ac_pt_env_t pt_env;
 	int i, tests, successes;
 
-	if (force_emulation && !is_fep_available()) {
+	if (force_emulation && !is_fep_available) {
 		report_skip("Forced emulation prefix (FEP) not available\n");
 		return;
 	}
diff --git a/x86/emulator.c b/x86/emulator.c
index f8bdc26b..4e1ba12a 100644
--- a/x86/emulator.c
+++ b/x86/emulator.c
@@ -728,7 +728,6 @@ static void handle_db(struct ex_regs *regs)
 static void test_mov_pop_ss_code_db(void)
 {
 	handler old_db_handler = handle_exception(DB_VECTOR, handle_db);
-	bool fep_available = is_fep_available();
 	/* On Intel, code #DBs are inhibited when MOV/POP SS blocking is active. */
 	int nr_expected = is_intel() ? 0 : 1;
 
@@ -761,7 +760,7 @@ static void test_mov_pop_ss_code_db(void)
 		      "mov %%ss, %0\n\t", "mov %0, %%ss\n\t")
 
 	MOV_SS_DB("no fep", "", "");
-	if (fep_available) {
+	if (is_fep_available) {
 		MOV_SS_DB("fep MOV-SS", KVM_FEP, "");
 		MOV_SS_DB("fep XOR", "", KVM_FEP);
 		MOV_SS_DB("fep MOV-SS/fep XOR", KVM_FEP, KVM_FEP);
@@ -774,7 +773,7 @@ static void test_mov_pop_ss_code_db(void)
 		      "push %%ss\n\t", "pop %%ss\n\t")
 
 	POP_SS_DB("no fep", "", "");
-	if (fep_available) {
+	if (is_fep_available) {
 		POP_SS_DB("fep POP-SS", KVM_FEP, "");
 		POP_SS_DB("fep XOR", "", KVM_FEP);
 		POP_SS_DB("fep POP-SS/fep XOR", KVM_FEP, KVM_FEP);
@@ -791,8 +790,8 @@ int main(void)
 	void *mem;
 	void *cross_mem;
 
-	if (!is_fep_available())
-		report_skip("Skipping tests the require forced emulation, "
+	if (!is_fep_available)
+		report_skip("Skipping tests that require forced emulation, "
 			    "use kvm.force_emulation_prefix=1 to enable");
 
 	setup_vm();
@@ -821,7 +820,7 @@ int main(void)
 	//test_lldt(mem);
 	test_ltr(mem);
 
-	if (is_fep_available()) {
+	if (is_fep_available) {
 		test_smsw_reg(mem);
 		test_nop(mem);
 		test_mov_dr(mem);
diff --git a/x86/emulator64.c b/x86/emulator64.c
index 5d1bb0f0..138903af 100644
--- a/x86/emulator64.c
+++ b/x86/emulator64.c
@@ -478,7 +478,7 @@ static void test_emulator_64(void *mem)
 	test_sreg(mem);
 	test_cmov(mem);
 
-	if (is_fep_available()) {
+	if (is_fep_available) {
 		test_mmx_movq_mf(mem);
 		test_movabs(mem);
 		test_user_load_dpl0_seg();
diff --git a/x86/la57.c b/x86/la57.c
index 41764110..d93e286c 100644
--- a/x86/la57.c
+++ b/x86/la57.c
@@ -313,7 +313,7 @@ static void test_canonical_checks(void)
 {
 	__test_canonical_checks(false);
 
-	if (is_fep_available())
+	if (is_fep_available)
 		__test_canonical_checks(true);
 	else
 		report_skip("Force emulation prefix not enabled");
diff --git a/x86/lam.c b/x86/lam.c
index a1c98949..8ad68178 100644
--- a/x86/lam.c
+++ b/x86/lam.c
@@ -184,7 +184,7 @@ static void __test_lam_sup(void *vaddr, void *vaddr_mmio)
 	test_ptr(vaddr_mmio, true);
 	test_invpcid(vaddr);
 	test_invlpg(vaddr, false);
-	if (is_fep_available())
+	if (is_fep_available)
 		test_invlpg(vaddr, true);
 }
 
diff --git a/x86/msr.c b/x86/msr.c
index e21ff0ac..f582a584 100644
--- a/x86/msr.c
+++ b/x86/msr.c
@@ -313,7 +313,7 @@ static void test_cmd_msrs(void)
 		test_wrmsr_fault(MSR_IA32_FLUSH_CMD, "FLUSH_CMD", L1D_FLUSH);
 	}
 
-	if (is_fep_available()) {
+	if (is_fep_available) {
 		for (i = 1; i < 64; i++)
 			test_wrmsr_fep_fault(MSR_IA32_FLUSH_CMD, "FLUSH_CMD", BIT_ULL(i));
 	}
diff --git a/x86/pmu.c b/x86/pmu.c
index 8cf26b12..b794b7d8 100644
--- a/x86/pmu.c
+++ b/x86/pmu.c
@@ -823,7 +823,7 @@ static void warm_up(void)
 
 static void check_counters(void)
 {
-	if (is_fep_available())
+	if (is_fep_available)
 		check_emulated_instr();
 
 	warm_up();
-- 
2.49.0.1266.g31b7d2e469-goog





[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux