Commit d52a7344 authored by Peter Zijlstra's avatar Peter Zijlstra
Browse files

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: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
Link: https://lore.kernel.org/r/20211110101325.364084212@infradead.org
parent 4b5305de
Loading
Loading
Loading
Loading
+11 −12
Original line number Diff line number Diff line
@@ -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
+8 −18
Original line number Diff line number Diff line
@@ -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);
+28 −23
Original line number Diff line number Diff line
@@ -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);

	if (!wrmsr) {
		/* 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",
			 (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: