KVM: selftests: Add helpers for safe and safe+forced RDMSR, RDPMC, and XGETBV
authorSean Christopherson <seanjc@google.com>
Tue, 9 Jan 2024 23:02:48 +0000 (15:02 -0800)
committerSean Christopherson <seanjc@google.com>
Tue, 30 Jan 2024 23:29:45 +0000 (15:29 -0800)
Add helpers for safe and safe-with-forced-emulations versions of RDMSR,
RDPMC, and XGETBV.  Use macro shenanigans to eliminate the rather large
amount of boilerplate needed to get values in and out of registers.

Tested-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Link: https://lore.kernel.org/r/20240109230250.424295-29-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
tools/testing/selftests/kvm/include/x86_64/processor.h

index fe891424ff55d9a6f75e3ac347c3a307abcf8088..abac816f6594ca5f8b6899d4ffdf72b72a85e0df 100644 (file)
@@ -1216,20 +1216,34 @@ void vm_install_exception_handler(struct kvm_vm *vm, int vector,
        vector;                                                         \
 })
 
-static inline uint8_t rdmsr_safe(uint32_t msr, uint64_t *val)
-{
-       uint64_t error_code;
-       uint8_t vector;
-       uint32_t a, d;
+#define BUILD_READ_U64_SAFE_HELPER(insn, _fep, _FEP)                   \
+static inline uint8_t insn##_safe ##_fep(uint32_t idx, uint64_t *val)  \
+{                                                                      \
+       uint64_t error_code;                                            \
+       uint8_t vector;                                                 \
+       uint32_t a, d;                                                  \
+                                                                       \
+       asm volatile(KVM_ASM_SAFE##_FEP(#insn)                          \
+                    : "=a"(a), "=d"(d),                                \
+                      KVM_ASM_SAFE_OUTPUTS(vector, error_code)         \
+                    : "c"(idx)                                         \
+                    : KVM_ASM_SAFE_CLOBBERS);                          \
+                                                                       \
+       *val = (uint64_t)a | ((uint64_t)d << 32);                       \
+       return vector;                                                  \
+}
 
-       asm volatile(KVM_ASM_SAFE("rdmsr")
-                    : "=a"(a), "=d"(d), KVM_ASM_SAFE_OUTPUTS(vector, error_code)
-                    : "c"(msr)
-                    : KVM_ASM_SAFE_CLOBBERS);
+/*
+ * Generate {insn}_safe() and {insn}_safe_fep() helpers for instructions that
+ * use ECX as in input index, and EDX:EAX as a 64-bit output.
+ */
+#define BUILD_READ_U64_SAFE_HELPERS(insn)                              \
+       BUILD_READ_U64_SAFE_HELPER(insn, , )                            \
+       BUILD_READ_U64_SAFE_HELPER(insn, _fep, _FEP)                    \
 
-       *val = (uint64_t)a | ((uint64_t)d << 32);
-       return vector;
-}
+BUILD_READ_U64_SAFE_HELPERS(rdmsr)
+BUILD_READ_U64_SAFE_HELPERS(rdpmc)
+BUILD_READ_U64_SAFE_HELPERS(xgetbv)
 
 static inline uint8_t wrmsr_safe(uint32_t msr, uint64_t val)
 {