Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 177fed1e authored by Borislav Petkov's avatar Borislav Petkov Committed by H. Peter Anvin
Browse files

x86, msr: Rewrite AMD rd/wrmsr variants



Switch them to native_{rd,wr}msr_safe_regs and remove
pv_cpu_ops.read_msr_amd.

Signed-off-by: default avatarBorislav Petkov <petkovbb@gmail.com>
LKML-Reference: <1251705011-18636-2-git-send-email-petkovbb@gmail.com>
Signed-off-by: default avatarH. Peter Anvin <hpa@zytor.com>
parent 132ec92f
Loading
Loading
Loading
Loading
+21 −17
Original line number Original line Diff line number Diff line
@@ -71,22 +71,6 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr,
	return EAX_EDX_VAL(val, low, high);
	return EAX_EDX_VAL(val, low, high);
}
}


static inline unsigned long long native_read_msr_amd_safe(unsigned int msr,
						      int *err)
{
	DECLARE_ARGS(val, low, high);

	asm volatile("2: rdmsr ; xor %0,%0\n"
		     "1:\n\t"
		     ".section .fixup,\"ax\"\n\t"
		     "3:  mov %3,%0 ; jmp 1b\n\t"
		     ".previous\n\t"
		     _ASM_EXTABLE(2b, 3b)
		     : "=r" (*err), EAX_EDX_RET(val, low, high)
		     : "c" (msr), "D" (0x9c5a203a), "i" (-EFAULT));
	return EAX_EDX_VAL(val, low, high);
}

static inline void native_write_msr(unsigned int msr,
static inline void native_write_msr(unsigned int msr,
				    unsigned low, unsigned high)
				    unsigned low, unsigned high)
{
{
@@ -184,14 +168,34 @@ static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
	*p = native_read_msr_safe(msr, &err);
	*p = native_read_msr_safe(msr, &err);
	return err;
	return err;
}
}

static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
{
{
	u32 gprs[8] = { 0 };
	int err;
	int err;


	*p = native_read_msr_amd_safe(msr, &err);
	gprs[1] = msr;
	gprs[7] = 0x9c5a203a;

	err = native_rdmsr_safe_regs(gprs);

	*p = gprs[0] | ((u64)gprs[2] << 32);

	return err;
	return err;
}
}


static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
{
	u32 gprs[8] = { 0 };

	gprs[0] = (u32)val;
	gprs[1] = msr;
	gprs[2] = val >> 32;
	gprs[7] = 0x9c5a203a;

	return native_wrmsr_safe_regs(gprs);
}

static inline int rdmsr_safe_regs(u32 *regs)
static inline int rdmsr_safe_regs(u32 *regs)
{
{
	return native_rdmsr_safe_regs(regs);
	return native_rdmsr_safe_regs(regs);
+20 −6
Original line number Original line Diff line number Diff line
@@ -166,7 +166,6 @@ struct pv_cpu_ops {


	/* MSR, PMC and TSR operations.
	/* MSR, PMC and TSR operations.
	   err = 0/-EFAULT.  wrmsr returns 0/-EFAULT. */
	   err = 0/-EFAULT.  wrmsr returns 0/-EFAULT. */
	u64 (*read_msr_amd)(unsigned int msr, int *err);
	u64 (*read_msr)(unsigned int msr, int *err);
	u64 (*read_msr)(unsigned int msr, int *err);
	int (*rdmsr_regs)(u32 *regs);
	int (*rdmsr_regs)(u32 *regs);
	int (*write_msr)(unsigned int msr, unsigned low, unsigned high);
	int (*write_msr)(unsigned int msr, unsigned low, unsigned high);
@@ -828,10 +827,6 @@ static inline int paravirt_rdmsr_regs(u32 *regs)
	return PVOP_CALL1(int, pv_cpu_ops.rdmsr_regs, regs);
	return PVOP_CALL1(int, pv_cpu_ops.rdmsr_regs, regs);
}
}


static inline u64 paravirt_read_msr_amd(unsigned msr, int *err)
{
	return PVOP_CALL2(u64, pv_cpu_ops.read_msr_amd, msr, err);
}
static inline int paravirt_write_msr(unsigned msr, unsigned low, unsigned high)
static inline int paravirt_write_msr(unsigned msr, unsigned low, unsigned high)
{
{
	return PVOP_CALL3(int, pv_cpu_ops.write_msr, msr, low, high);
	return PVOP_CALL3(int, pv_cpu_ops.write_msr, msr, low, high);
@@ -887,12 +882,31 @@ static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
}
}
static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
{
{
	u32 gprs[8] = { 0 };
	int err;
	int err;


	*p = paravirt_read_msr_amd(msr, &err);
	gprs[1] = msr;
	gprs[7] = 0x9c5a203a;

	err = paravirt_rdmsr_regs(gprs);

	*p = gprs[0] | ((u64)gprs[2] << 32);

	return err;
	return err;
}
}


static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
{
	u32 gprs[8] = { 0 };

	gprs[0] = (u32)val;
	gprs[1] = msr;
	gprs[2] = val >> 32;
	gprs[7] = 0x9c5a203a;

	return paravirt_wrmsr_regs(gprs);
}

static inline u64 paravirt_read_tsc(void)
static inline u64 paravirt_read_tsc(void)
{
{
	return PVOP_CALL0(u64, pv_cpu_ops.read_tsc);
	return PVOP_CALL0(u64, pv_cpu_ops.read_tsc);
+0 −1
Original line number Original line Diff line number Diff line
@@ -363,7 +363,6 @@ struct pv_cpu_ops pv_cpu_ops = {
	.wbinvd = native_wbinvd,
	.wbinvd = native_wbinvd,
	.read_msr = native_read_msr_safe,
	.read_msr = native_read_msr_safe,
	.rdmsr_regs = native_rdmsr_safe_regs,
	.rdmsr_regs = native_rdmsr_safe_regs,
	.read_msr_amd = native_read_msr_amd_safe,
	.write_msr = native_write_msr_safe,
	.write_msr = native_write_msr_safe,
	.wrmsr_regs = native_wrmsr_safe_regs,
	.wrmsr_regs = native_wrmsr_safe_regs,
	.read_tsc = native_read_tsc,
	.read_tsc = native_read_tsc,