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