[kvm-unit-tests PATCH 3/5] x86: Add macros to wrap ASM_TRY() for single instructions with output(s)

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

 



Add macros for "safe" execution of instructions with outputs.  Outputs
require dedicated macros as the variadic arguments shenanigans only work
for one type, i.e. can either be used for inputs or outputs, not both.

Opportunistically provide a common macro for RDMSR and RDPMC, the common
macro can also be used for xgetbv_safe().

Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
---
 lib/x86/desc.h      | 22 ++++++++++++++++++++++
 lib/x86/processor.h | 34 ++++++++++++++++------------------
 2 files changed, 38 insertions(+), 18 deletions(-)

diff --git a/lib/x86/desc.h b/lib/x86/desc.h
index 8079d462..7778a0f8 100644
--- a/lib/x86/desc.h
+++ b/lib/x86/desc.h
@@ -283,6 +283,28 @@ extern unsigned long get_gdt_entry_limit(gdt_entry_t *entry);
 	exception_vector();						\
 })
 
+#define asm_safe_out1(insn, output, inputs...)				\
+({									\
+	asm volatile(ASM_TRY("1f")					\
+		     insn "\n\t"					\
+		     "1:\n\t"						\
+		     : output						\
+		     : inputs						\
+		     : "memory");					\
+	exception_vector();						\
+})
+
+#define asm_safe_out2(insn, output1, output2, inputs...)		\
+({									\
+	asm volatile(ASM_TRY("1f")					\
+		     insn "\n\t"					\
+		     "1:\n\t"						\
+		     : output1, output2					\
+		     : inputs						\
+		     : "memory");					\
+	exception_vector();						\
+})
+
 #define __asm_safe_report(want, insn, inputs...)			\
 do {									\
 	int vector = asm_safe(insn, inputs);				\
diff --git a/lib/x86/processor.h b/lib/x86/processor.h
index e05b3fd0..b9f0436c 100644
--- a/lib/x86/processor.h
+++ b/lib/x86/processor.h
@@ -416,18 +416,23 @@ static inline void wrmsr(u32 index, u64 val)
 	asm volatile ("wrmsr" : : "a"(a), "d"(d), "c"(index) : "memory");
 }
 
+#define rdreg64_safe(insn, index, val)					\
+({									\
+	uint32_t a, d;							\
+	int vector;							\
+									\
+	vector = asm_safe_out2(insn, "=a"(a), "=d"(d), "c"(index));	\
+									\
+	if (vector)							\
+		*(val) = 0;						\
+	else								\
+		*(val) = (uint64_t)a | ((uint64_t)d << 32);		\
+	vector;								\
+})
+
 static inline int rdmsr_safe(u32 index, uint64_t *val)
 {
-	uint32_t a, d;
-
-	asm volatile (ASM_TRY("1f")
-		      "rdmsr\n\t"
-		      "1:"
-		      : "=a"(a), "=d"(d)
-		      : "c"(index) : "memory");
-
-	*val = (uint64_t)a | ((uint64_t)d << 32);
-	return exception_vector();
+	return rdreg64_safe("rdmsr", index, val);
 }
 
 static inline int wrmsr_safe(u32 index, u64 val)
@@ -439,14 +444,7 @@ static inline int wrmsr_safe(u32 index, u64 val)
 
 static inline int rdpmc_safe(u32 index, uint64_t *val)
 {
-	uint32_t a, d;
-
-	asm volatile (ASM_TRY("1f")
-		      "rdpmc\n\t"
-		      "1:"
-		      : "=a"(a), "=d"(d) : "c"(index) : "memory");
-	*val = (uint64_t)a | ((uint64_t)d << 32);
-	return exception_vector();
+	return rdreg64_safe("rdpmc", index, val);
 }
 
 static inline uint64_t rdpmc(uint32_t index)
-- 
2.40.0.348.gf938b09366-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