Commit 986b37c0 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'x86-cleanups-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 cleanups and msr updates from Ingo Molnar:
 "The main change is a performance/latency improvement to /dev/msr
  access. The rest are misc cleanups"

* 'x86-cleanups-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/msr: Make rdmsrl_safe_on_cpu() scheduling safe as well
  x86/cpuid: Allow cpuid_read() to schedule
  x86/msr: Allow rdmsr_safe_on_cpu() to schedule
  x86/rtc: Stop using deprecated functions
  x86/dumpstack: Unify show_regs()
  x86/fault: Do not print IP in show_fault_oops()
  x86/MSR: Move native_* variants to msr.h
parents e68b4bad 9b9a5135
...@@ -6,20 +6,6 @@ ...@@ -6,20 +6,6 @@
#include <linux/earlycpio.h> #include <linux/earlycpio.h>
#include <linux/initrd.h> #include <linux/initrd.h>
#define native_rdmsr(msr, val1, val2) \
do { \
u64 __val = __rdmsr((msr)); \
(void)((val1) = (u32)__val); \
(void)((val2) = (u32)(__val >> 32)); \
} while (0)
#define native_wrmsr(msr, low, high) \
__wrmsr(msr, low, high)
#define native_wrmsrl(msr, val) \
__wrmsr((msr), (u32)((u64)(val)), \
(u32)((u64)(val) >> 32))
struct ucode_patch { struct ucode_patch {
struct list_head plist; struct list_head plist;
void *data; /* Intel uses only this one */ void *data; /* Intel uses only this one */
......
...@@ -108,6 +108,20 @@ static inline void notrace __wrmsr(unsigned int msr, u32 low, u32 high) ...@@ -108,6 +108,20 @@ static inline void notrace __wrmsr(unsigned int msr, u32 low, u32 high)
: : "c" (msr), "a"(low), "d" (high) : "memory"); : : "c" (msr), "a"(low), "d" (high) : "memory");
} }
#define native_rdmsr(msr, val1, val2) \
do { \
u64 __val = __rdmsr((msr)); \
(void)((val1) = (u32)__val); \
(void)((val2) = (u32)(__val >> 32)); \
} while (0)
#define native_wrmsr(msr, low, high) \
__wrmsr(msr, low, high)
#define native_wrmsrl(msr, val) \
__wrmsr((msr), (u32)((u64)(val)), \
(u32)((u64)(val) >> 32))
static inline unsigned long long native_read_msr(unsigned int msr) static inline unsigned long long native_read_msr(unsigned int msr)
{ {
unsigned long long val; unsigned long long val;
......
...@@ -87,8 +87,6 @@ get_stack_pointer(struct task_struct *task, struct pt_regs *regs) ...@@ -87,8 +87,6 @@ get_stack_pointer(struct task_struct *task, struct pt_regs *regs)
void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
unsigned long *stack, char *log_lvl); unsigned long *stack, char *log_lvl);
extern unsigned int code_bytes;
/* The form of the top of the frame on the stack */ /* The form of the top of the frame on the stack */
struct stack_frame { struct stack_frame {
struct stack_frame *next_frame; struct stack_frame *next_frame;
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/completion.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/msr.h> #include <asm/msr.h>
...@@ -47,19 +48,27 @@ ...@@ -47,19 +48,27 @@
static struct class *cpuid_class; static struct class *cpuid_class;
static enum cpuhp_state cpuhp_cpuid_state; static enum cpuhp_state cpuhp_cpuid_state;
struct cpuid_regs_done {
struct cpuid_regs regs;
struct completion done;
};
static void cpuid_smp_cpuid(void *cmd_block) static void cpuid_smp_cpuid(void *cmd_block)
{ {
struct cpuid_regs *cmd = (struct cpuid_regs *)cmd_block; struct cpuid_regs_done *cmd = cmd_block;
cpuid_count(cmd->regs.eax, cmd->regs.ecx,
&cmd->regs.eax, &cmd->regs.ebx,
&cmd->regs.ecx, &cmd->regs.edx);
cpuid_count(cmd->eax, cmd->ecx, complete(&cmd->done);
&cmd->eax, &cmd->ebx, &cmd->ecx, &cmd->edx);
} }
static ssize_t cpuid_read(struct file *file, char __user *buf, static ssize_t cpuid_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
char __user *tmp = buf; char __user *tmp = buf;
struct cpuid_regs cmd; struct cpuid_regs_done cmd;
int cpu = iminor(file_inode(file)); int cpu = iminor(file_inode(file));
u64 pos = *ppos; u64 pos = *ppos;
ssize_t bytes = 0; ssize_t bytes = 0;
...@@ -68,19 +77,28 @@ static ssize_t cpuid_read(struct file *file, char __user *buf, ...@@ -68,19 +77,28 @@ static ssize_t cpuid_read(struct file *file, char __user *buf,
if (count % 16) if (count % 16)
return -EINVAL; /* Invalid chunk size */ return -EINVAL; /* Invalid chunk size */
init_completion(&cmd.done);
for (; count; count -= 16) { for (; count; count -= 16) {
cmd.eax = pos; call_single_data_t csd = {
cmd.ecx = pos >> 32; .func = cpuid_smp_cpuid,
err = smp_call_function_single(cpu, cpuid_smp_cpuid, &cmd, 1); .info = &cmd,
};
cmd.regs.eax = pos;
cmd.regs.ecx = pos >> 32;
err = smp_call_function_single_async(cpu, &csd);
if (err) if (err)
break; break;
if (copy_to_user(tmp, &cmd, 16)) { wait_for_completion(&cmd.done);
if (copy_to_user(tmp, &cmd.regs, 16)) {
err = -EFAULT; err = -EFAULT;
break; break;
} }
tmp += 16; tmp += 16;
bytes += 16; bytes += 16;
*ppos = ++pos; *ppos = ++pos;
reinit_completion(&cmd.done);
} }
return bytes ? bytes : err; return bytes ? bytes : err;
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
int panic_on_unrecovered_nmi; int panic_on_unrecovered_nmi;
int panic_on_io_nmi; int panic_on_io_nmi;
unsigned int code_bytes = 64; static unsigned int code_bytes = 64;
static int die_counter; static int die_counter;
bool in_task_stack(unsigned long *stack, struct task_struct *task, bool in_task_stack(unsigned long *stack, struct task_struct *task,
...@@ -375,3 +375,50 @@ static int __init code_bytes_setup(char *s) ...@@ -375,3 +375,50 @@ static int __init code_bytes_setup(char *s)
return 1; return 1;
} }
__setup("code_bytes=", code_bytes_setup); __setup("code_bytes=", code_bytes_setup);
void show_regs(struct pt_regs *regs)
{
bool all = true;
int i;
show_regs_print_info(KERN_DEFAULT);
if (IS_ENABLED(CONFIG_X86_32))
all = !user_mode(regs);
__show_regs(regs, all);
/*
* When in-kernel, we also print out the stack and code at the
* time of the fault..
*/
if (!user_mode(regs)) {
unsigned int code_prologue = code_bytes * 43 / 64;
unsigned int code_len = code_bytes;
unsigned char c;
u8 *ip;
show_trace_log_lvl(current, regs, NULL, KERN_DEFAULT);
printk(KERN_DEFAULT "Code: ");
ip = (u8 *)regs->ip - code_prologue;
if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
/* try starting at IP */
ip = (u8 *)regs->ip;
code_len = code_len - code_prologue + 1;
}
for (i = 0; i < code_len; i++, ip++) {
if (ip < (u8 *)PAGE_OFFSET ||
probe_kernel_address(ip, c)) {
pr_cont(" Bad RIP value.");
break;
}
if (ip == (u8 *)regs->ip)
pr_cont("<%02x> ", c);
else
pr_cont("%02x ", c);
}
}
pr_cont("\n");
}
...@@ -127,45 +127,3 @@ int get_stack_info(unsigned long *stack, struct task_struct *task, ...@@ -127,45 +127,3 @@ int get_stack_info(unsigned long *stack, struct task_struct *task,
info->type = STACK_TYPE_UNKNOWN; info->type = STACK_TYPE_UNKNOWN;
return -EINVAL; return -EINVAL;
} }
void show_regs(struct pt_regs *regs)
{
int i;
show_regs_print_info(KERN_EMERG);
__show_regs(regs, !user_mode(regs));
/*
* When in-kernel, we also print out the stack and code at the
* time of the fault..
*/
if (!user_mode(regs)) {
unsigned int code_prologue = code_bytes * 43 / 64;
unsigned int code_len = code_bytes;
unsigned char c;
u8 *ip;
show_trace_log_lvl(current, regs, NULL, KERN_EMERG);
pr_emerg("Code:");
ip = (u8 *)regs->ip - code_prologue;
if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
/* try starting at IP */
ip = (u8 *)regs->ip;
code_len = code_len - code_prologue + 1;
}
for (i = 0; i < code_len; i++, ip++) {
if (ip < (u8 *)PAGE_OFFSET ||
probe_kernel_address(ip, c)) {
pr_cont(" Bad EIP value.");
break;
}
if (ip == (u8 *)regs->ip)
pr_cont(" <%02x>", c);
else
pr_cont(" %02x", c);
}
}
pr_cont("\n");
}
...@@ -149,45 +149,3 @@ int get_stack_info(unsigned long *stack, struct task_struct *task, ...@@ -149,45 +149,3 @@ int get_stack_info(unsigned long *stack, struct task_struct *task,
info->type = STACK_TYPE_UNKNOWN; info->type = STACK_TYPE_UNKNOWN;
return -EINVAL; return -EINVAL;
} }
void show_regs(struct pt_regs *regs)
{
int i;
show_regs_print_info(KERN_DEFAULT);
__show_regs(regs, 1);
/*
* When in-kernel, we also print out the stack and code at the
* time of the fault..
*/
if (!user_mode(regs)) {
unsigned int code_prologue = code_bytes * 43 / 64;
unsigned int code_len = code_bytes;
unsigned char c;
u8 *ip;
show_trace_log_lvl(current, regs, NULL, KERN_DEFAULT);
printk(KERN_DEFAULT "Code: ");
ip = (u8 *)regs->ip - code_prologue;
if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
/* try starting at IP */
ip = (u8 *)regs->ip;
code_len = code_len - code_prologue + 1;
}
for (i = 0; i < code_len; i++, ip++) {
if (ip < (u8 *)PAGE_OFFSET ||
probe_kernel_address(ip, c)) {
pr_cont(" Bad RIP value.");
break;
}
if (ip == (u8 *)regs->ip)
pr_cont("<%02x> ", c);
else
pr_cont("%02x ", c);
}
}
pr_cont("\n");
}
...@@ -41,11 +41,11 @@ EXPORT_SYMBOL(rtc_lock); ...@@ -41,11 +41,11 @@ EXPORT_SYMBOL(rtc_lock);
*/ */
int mach_set_rtc_mmss(const struct timespec *now) int mach_set_rtc_mmss(const struct timespec *now)
{ {
unsigned long nowtime = now->tv_sec; unsigned long long nowtime = now->tv_sec;
struct rtc_time tm; struct rtc_time tm;
int retval = 0; int retval = 0;
rtc_time_to_tm(nowtime, &tm); rtc_time64_to_tm(nowtime, &tm);
if (!rtc_valid_tm(&tm)) { if (!rtc_valid_tm(&tm)) {
retval = mc146818_set_time(&tm); retval = mc146818_set_time(&tm);
if (retval) if (retval)
...@@ -53,7 +53,7 @@ int mach_set_rtc_mmss(const struct timespec *now) ...@@ -53,7 +53,7 @@ int mach_set_rtc_mmss(const struct timespec *now)
__func__, retval); __func__, retval);
} else { } else {
printk(KERN_ERR printk(KERN_ERR
"%s: Invalid RTC value: write of %lx to RTC failed\n", "%s: Invalid RTC value: write of %llx to RTC failed\n",
__func__, nowtime); __func__, nowtime);
retval = -EINVAL; retval = -EINVAL;
} }
......
...@@ -49,7 +49,6 @@ ...@@ -49,7 +49,6 @@
#include <asm/debugreg.h> #include <asm/debugreg.h>
#include <asm/kvm_para.h> #include <asm/kvm_para.h>
#include <asm/irq_remapping.h> #include <asm/irq_remapping.h>
#include <asm/microcode.h>
#include <asm/nospec-branch.h> #include <asm/nospec-branch.h>
#include <asm/virtext.h> #include <asm/virtext.h>
......
...@@ -51,7 +51,6 @@ ...@@ -51,7 +51,6 @@
#include <asm/apic.h> #include <asm/apic.h>
#include <asm/irq_remapping.h> #include <asm/irq_remapping.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/microcode.h>
#include <asm/nospec-branch.h> #include <asm/nospec-branch.h>
#include "trace.h" #include "trace.h"
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/preempt.h> #include <linux/preempt.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/completion.h>
#include <asm/msr.h> #include <asm/msr.h>
static void __rdmsr_on_cpu(void *info) static void __rdmsr_on_cpu(void *info)
...@@ -143,13 +144,19 @@ void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs) ...@@ -143,13 +144,19 @@ void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
} }
EXPORT_SYMBOL(wrmsr_on_cpus); EXPORT_SYMBOL(wrmsr_on_cpus);
struct msr_info_completion {
struct msr_info msr;
struct completion done;
};
/* These "safe" variants are slower and should be used when the target MSR /* These "safe" variants are slower and should be used when the target MSR
may not actually exist. */ may not actually exist. */
static void __rdmsr_safe_on_cpu(void *info) static void __rdmsr_safe_on_cpu(void *info)
{ {
struct msr_info *rv = info; struct msr_info_completion *rv = info;
rv->err = rdmsr_safe(rv->msr_no, &rv->reg.l, &rv->reg.h); rv->msr.err = rdmsr_safe(rv->msr.msr_no, &rv->msr.reg.l, &rv->msr.reg.h);
complete(&rv->done);
} }
static void __wrmsr_safe_on_cpu(void *info) static void __wrmsr_safe_on_cpu(void *info)
...@@ -161,17 +168,26 @@ static void __wrmsr_safe_on_cpu(void *info) ...@@ -161,17 +168,26 @@ static void __wrmsr_safe_on_cpu(void *info)
int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
{ {
struct msr_info_completion rv;
call_single_data_t csd = {
.func = __rdmsr_safe_on_cpu,
.info = &rv,
};
int err; int err;
struct msr_info rv;
memset(&rv, 0, sizeof(rv)); memset(&rv, 0, sizeof(rv));
init_completion(&rv.done);
rv.msr.msr_no = msr_no;
rv.msr_no = msr_no; err = smp_call_function_single_async(cpu, &csd);
err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1); if (!err) {
*l = rv.reg.l; wait_for_completion(&rv.done);
*h = rv.reg.h; err = rv.msr.err;
}
*l = rv.msr.reg.l;
*h = rv.msr.reg.h;
return err ? err : rv.err; return err;
} }
EXPORT_SYMBOL(rdmsr_safe_on_cpu); EXPORT_SYMBOL(rdmsr_safe_on_cpu);
...@@ -209,16 +225,13 @@ EXPORT_SYMBOL(wrmsrl_safe_on_cpu); ...@@ -209,16 +225,13 @@ EXPORT_SYMBOL(wrmsrl_safe_on_cpu);
int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q) int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q)
{ {
u32 low, high;
int err; int err;
struct msr_info rv;
memset(&rv, 0, sizeof(rv)); err = rdmsr_safe_on_cpu(cpu, msr_no, &low, &high);
*q = (u64)high << 32 | low;
rv.msr_no = msr_no; return err;
err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1);
*q = rv.reg.q;
return err ? err : rv.err;
} }
EXPORT_SYMBOL(rdmsrl_safe_on_cpu); EXPORT_SYMBOL(rdmsrl_safe_on_cpu);
......
...@@ -699,7 +699,6 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code, ...@@ -699,7 +699,6 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code,
printk(KERN_CONT "paging request"); printk(KERN_CONT "paging request");
printk(KERN_CONT " at %px\n", (void *) address); printk(KERN_CONT " at %px\n", (void *) address);
printk(KERN_ALERT "IP: %pS\n", (void *)regs->ip);
dump_pagetable(address); dump_pagetable(address);
} }
......
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