x86/msr: Remove .fixup usage
authorPeter Zijlstra <peterz@infradead.org>
Wed, 10 Nov 2021 10:01:10 +0000 (11:01 +0100)
committerPeter Zijlstra <peterz@infradead.org>
Sat, 11 Dec 2021 08:09:47 +0000 (09:09 +0100)
Rework the MSR accessors to remove .fixup usage. Add two new extable
types (to the 4 already existing msr ones) using the new register
infrastructure to record which register should get the error value.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
Link: https://lore.kernel.org/r/20211110101325.364084212@infradead.org
arch/x86/include/asm/extable_fixup_types.h
arch/x86/include/asm/msr.h
arch/x86/mm/extable.c

index 944f832..9d597fe 100644 (file)
 #define        EX_TYPE_COPY                     4
 #define        EX_TYPE_CLEAR_FS                 5
 #define        EX_TYPE_FPU_RESTORE              6
-#define        EX_TYPE_WRMSR                    7
-#define        EX_TYPE_RDMSR                    8
-#define        EX_TYPE_BPF                      9
-
-#define        EX_TYPE_WRMSR_IN_MCE            10
-#define        EX_TYPE_RDMSR_IN_MCE            11
-
-#define        EX_TYPE_DEFAULT_MCE_SAFE        12
-#define        EX_TYPE_FAULT_MCE_SAFE          13
-
-#define        EX_TYPE_POP_ZERO                14
-#define        EX_TYPE_IMM_REG                 15 /* reg := (long)imm */
+#define        EX_TYPE_BPF                      7
+#define        EX_TYPE_WRMSR                    8
+#define        EX_TYPE_RDMSR                    9
+#define        EX_TYPE_WRMSR_SAFE              10 /* reg := -EIO */
+#define        EX_TYPE_RDMSR_SAFE              11 /* reg := -EIO */
+#define        EX_TYPE_WRMSR_IN_MCE            12
+#define        EX_TYPE_RDMSR_IN_MCE            13
+#define        EX_TYPE_DEFAULT_MCE_SAFE        14
+#define        EX_TYPE_FAULT_MCE_SAFE          15
+#define        EX_TYPE_POP_ZERO                16
+#define        EX_TYPE_IMM_REG                 17 /* reg := (long)imm */
 
 #endif
index 6b52182..d42e6c6 100644 (file)
@@ -137,17 +137,11 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr,
 {
        DECLARE_ARGS(val, low, high);
 
-       asm volatile("2: rdmsr ; xor %[err],%[err]\n"
-                    "1:\n\t"
-                    ".section .fixup,\"ax\"\n\t"
-                    "3: mov %[fault],%[err]\n\t"
-                    "xorl %%eax, %%eax\n\t"
-                    "xorl %%edx, %%edx\n\t"
-                    "jmp 1b\n\t"
-                    ".previous\n\t"
-                    _ASM_EXTABLE(2b, 3b)
+       asm volatile("1: rdmsr ; xor %[err],%[err]\n"
+                    "2:\n\t"
+                    _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_RDMSR_SAFE, %[err])
                     : [err] "=r" (*err), EAX_EDX_RET(val, low, high)
-                    : "c" (msr), [fault] "i" (-EIO));
+                    : "c" (msr));
        if (tracepoint_enabled(read_msr))
                do_trace_read_msr(msr, EAX_EDX_VAL(val, low, high), *err);
        return EAX_EDX_VAL(val, low, high);
@@ -169,15 +163,11 @@ native_write_msr_safe(unsigned int msr, u32 low, u32 high)
 {
        int err;
 
-       asm volatile("2: wrmsr ; xor %[err],%[err]\n"
-                    "1:\n\t"
-                    ".section .fixup,\"ax\"\n\t"
-                    "3:  mov %[fault],%[err] ; jmp 1b\n\t"
-                    ".previous\n\t"
-                    _ASM_EXTABLE(2b, 3b)
+       asm volatile("1: wrmsr ; xor %[err],%[err]\n"
+                    "2:\n\t"
+                    _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_WRMSR_SAFE, %[err])
                     : [err] "=a" (err)
-                    : "c" (msr), "0" (low), "d" (high),
-                      [fault] "i" (-EIO)
+                    : "c" (msr), "0" (low), "d" (high)
                     : "memory");
        if (tracepoint_enabled(write_msr))
                do_trace_write_msr(msr, ((u64)high << 32 | low), err);
index cef8901..717cd35 100644 (file)
@@ -83,28 +83,29 @@ static bool ex_handler_copy(const struct exception_table_entry *fixup,
        return ex_handler_fault(fixup, regs, trapnr);
 }
 
-static bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup,
-                                   struct pt_regs *regs)
+static bool ex_handler_msr(const struct exception_table_entry *fixup,
+                          struct pt_regs *regs, bool wrmsr, bool safe, int reg)
 {
-       if (pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n",
+       if (!safe && wrmsr &&
+           pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n",
+                        (unsigned int)regs->cx, (unsigned int)regs->dx,
+                        (unsigned int)regs->ax,  regs->ip, (void *)regs->ip))
+               show_stack_regs(regs);
+
+       if (!safe && !wrmsr &&
+           pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n",
                         (unsigned int)regs->cx, regs->ip, (void *)regs->ip))
                show_stack_regs(regs);
 
-       /* Pretend that the read succeeded and returned 0. */
-       regs->ax = 0;
-       regs->dx = 0;
-       return ex_handler_default(fixup, regs);
-}
+       if (!wrmsr) {
+               /* Pretend that the read succeeded and returned 0. */
+               regs->ax = 0;
+               regs->dx = 0;
+       }
 
-static bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup,
-                                   struct pt_regs *regs)
-{
-       if (pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n",
-                        (unsigned int)regs->cx, (unsigned int)regs->dx,
-                        (unsigned int)regs->ax,  regs->ip, (void *)regs->ip))
-               show_stack_regs(regs);
+       if (safe)
+               *pt_regs_nr(regs, reg) = -EIO;
 
-       /* Pretend that the write succeeded. */
        return ex_handler_default(fixup, regs);
 }
 
@@ -186,18 +187,22 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
                return ex_handler_clear_fs(e, regs);
        case EX_TYPE_FPU_RESTORE:
                return ex_handler_fprestore(e, regs);
-       case EX_TYPE_RDMSR:
-               return ex_handler_rdmsr_unsafe(e, regs);
-       case EX_TYPE_WRMSR:
-               return ex_handler_wrmsr_unsafe(e, regs);
        case EX_TYPE_BPF:
                return ex_handler_bpf(e, regs);
-       case EX_TYPE_RDMSR_IN_MCE:
-               ex_handler_msr_mce(regs, false);
-               break;
+       case EX_TYPE_WRMSR:
+               return ex_handler_msr(e, regs, true, false, reg);
+       case EX_TYPE_RDMSR:
+               return ex_handler_msr(e, regs, false, false, reg);
+       case EX_TYPE_WRMSR_SAFE:
+               return ex_handler_msr(e, regs, true, true, reg);
+       case EX_TYPE_RDMSR_SAFE:
+               return ex_handler_msr(e, regs, false, true, reg);
        case EX_TYPE_WRMSR_IN_MCE:
                ex_handler_msr_mce(regs, true);
                break;
+       case EX_TYPE_RDMSR_IN_MCE:
+               ex_handler_msr_mce(regs, false);
+               break;
        case EX_TYPE_POP_ZERO:
                return ex_handler_pop_zero(e, regs);
        case EX_TYPE_IMM_REG: