x86/msr: Remove .fixup usage
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
This commit is contained in:
parent
4b5305decc
commit
d52a7344bd
|
@ -32,17 +32,16 @@
|
|||
#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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
(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);
|
||||
}
|
||||
|
||||
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",
|
||||
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);
|
||||
|
||||
/* Pretend that the write succeeded. */
|
||||
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);
|
||||
|
||||
if (!wrmsr) {
|
||||
/* Pretend that the read succeeded and returned 0. */
|
||||
regs->ax = 0;
|
||||
regs->dx = 0;
|
||||
}
|
||||
|
||||
if (safe)
|
||||
*pt_regs_nr(regs, reg) = -EIO;
|
||||
|
||||
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:
|
||||
|
|
Loading…
Reference in New Issue