Commit a585df8e authored by Borislav Petkov's avatar Borislav Petkov Committed by Thomas Gleixner

x86/MSR: Carve out bare minimum accessors

Add __rdmsr() and __wrmsr() which *only* read and write an MSR with
exception handling. Those are going to be used in early code, like the
microcode loader, which cannot stomach tracing code piggybacking on the
MSR operation.

While at it, get rid of __native_write_msr_notrace().
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Reviewed-by: default avatarThomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20170120202955.4091-3-bp@alien8.deSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent c26665ab
...@@ -195,7 +195,7 @@ static inline void native_apic_msr_write(u32 reg, u32 v) ...@@ -195,7 +195,7 @@ static inline void native_apic_msr_write(u32 reg, u32 v)
static inline void native_apic_msr_eoi_write(u32 reg, u32 v) static inline void native_apic_msr_eoi_write(u32 reg, u32 v)
{ {
wrmsr_notrace(APIC_BASE_MSR + (APIC_EOI >> 4), APIC_EOI_ACK, 0); __wrmsr(APIC_BASE_MSR + (APIC_EOI >> 4), APIC_EOI_ACK, 0);
} }
static inline u32 native_apic_msr_read(u32 reg) static inline u32 native_apic_msr_read(u32 reg)
......
...@@ -80,7 +80,14 @@ static inline void do_trace_read_msr(unsigned int msr, u64 val, int failed) {} ...@@ -80,7 +80,14 @@ static inline void do_trace_read_msr(unsigned int msr, u64 val, int failed) {}
static inline void do_trace_rdpmc(unsigned int msr, u64 val, int failed) {} static inline void do_trace_rdpmc(unsigned int msr, u64 val, int failed) {}
#endif #endif
static inline unsigned long long native_read_msr(unsigned int msr) /*
* __rdmsr() and __wrmsr() are the two primitives which are the bare minimum MSR
* accessors and should not have any tracing or other functionality piggybacking
* on them - those are *purely* for accessing MSRs and nothing more. So don't even
* think of extending them - you will be slapped with a stinking trout or a frozen
* shark will reach you, wherever you are! You've been warned.
*/
static inline unsigned long long notrace __rdmsr(unsigned int msr)
{ {
DECLARE_ARGS(val, low, high); DECLARE_ARGS(val, low, high);
...@@ -88,11 +95,30 @@ static inline unsigned long long native_read_msr(unsigned int msr) ...@@ -88,11 +95,30 @@ static inline unsigned long long native_read_msr(unsigned int msr)
"2:\n" "2:\n"
_ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_rdmsr_unsafe) _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_rdmsr_unsafe)
: EAX_EDX_RET(val, low, high) : "c" (msr)); : EAX_EDX_RET(val, low, high) : "c" (msr));
if (msr_tracepoint_active(__tracepoint_read_msr))
do_trace_read_msr(msr, EAX_EDX_VAL(val, low, high), 0);
return EAX_EDX_VAL(val, low, high); return EAX_EDX_VAL(val, low, high);
} }
static inline void notrace __wrmsr(unsigned int msr, u32 low, u32 high)
{
asm volatile("1: wrmsr\n"
"2:\n"
_ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_wrmsr_unsafe)
: : "c" (msr), "a"(low), "d" (high) : "memory");
}
static inline unsigned long long native_read_msr(unsigned int msr)
{
unsigned long long val;
val = __rdmsr(msr);
if (msr_tracepoint_active(__tracepoint_read_msr))
do_trace_read_msr(msr, val, 0);
return val;
}
static inline unsigned long long native_read_msr_safe(unsigned int msr, static inline unsigned long long native_read_msr_safe(unsigned int msr,
int *err) int *err)
{ {
...@@ -114,31 +140,16 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr, ...@@ -114,31 +140,16 @@ 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);
} }
/* Can be uninlined because referenced by paravirt */
static inline void notrace
__native_write_msr_notrace(unsigned int msr, u32 low, u32 high)
{
asm volatile("1: wrmsr\n"
"2:\n"
_ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_wrmsr_unsafe)
: : "c" (msr), "a"(low), "d" (high) : "memory");
}
/* Can be uninlined because referenced by paravirt */ /* Can be uninlined because referenced by paravirt */
static inline void notrace static inline void notrace
native_write_msr(unsigned int msr, u32 low, u32 high) native_write_msr(unsigned int msr, u32 low, u32 high)
{ {
__native_write_msr_notrace(msr, low, high); __wrmsr(msr, low, high);
if (msr_tracepoint_active(__tracepoint_write_msr)) if (msr_tracepoint_active(__tracepoint_write_msr))
do_trace_write_msr(msr, ((u64)high << 32 | low), 0); do_trace_write_msr(msr, ((u64)high << 32 | low), 0);
} }
static inline void
wrmsr_notrace(unsigned int msr, u32 low, u32 high)
{
__native_write_msr_notrace(msr, low, high);
}
/* Can be uninlined because referenced by paravirt */ /* Can be uninlined because referenced by paravirt */
static inline int notrace static inline int notrace
native_write_msr_safe(unsigned int msr, u32 low, u32 high) native_write_msr_safe(unsigned int msr, u32 low, u32 high)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment