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
This commit is contained in:
commit
986b37c0ae
@ -6,20 +6,6 @@
|
||||
#include <linux/earlycpio.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 list_head plist;
|
||||
void *data; /* Intel uses only this one */
|
||||
|
@ -108,6 +108,20 @@ static inline void notrace __wrmsr(unsigned int msr, u32 low, u32 high)
|
||||
: : "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)
|
||||
{
|
||||
unsigned long long val;
|
||||
|
@ -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,
|
||||
unsigned long *stack, char *log_lvl);
|
||||
|
||||
extern unsigned int code_bytes;
|
||||
|
||||
/* The form of the top of the frame on the stack */
|
||||
struct stack_frame {
|
||||
struct stack_frame *next_frame;
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/completion.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include <asm/msr.h>
|
||||
@ -47,19 +48,27 @@
|
||||
static struct class *cpuid_class;
|
||||
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)
|
||||
{
|
||||
struct cpuid_regs *cmd = (struct cpuid_regs *)cmd_block;
|
||||
struct cpuid_regs_done *cmd = cmd_block;
|
||||
|
||||
cpuid_count(cmd->eax, cmd->ecx,
|
||||
&cmd->eax, &cmd->ebx, &cmd->ecx, &cmd->edx);
|
||||
cpuid_count(cmd->regs.eax, cmd->regs.ecx,
|
||||
&cmd->regs.eax, &cmd->regs.ebx,
|
||||
&cmd->regs.ecx, &cmd->regs.edx);
|
||||
|
||||
complete(&cmd->done);
|
||||
}
|
||||
|
||||
static ssize_t cpuid_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char __user *tmp = buf;
|
||||
struct cpuid_regs cmd;
|
||||
struct cpuid_regs_done cmd;
|
||||
int cpu = iminor(file_inode(file));
|
||||
u64 pos = *ppos;
|
||||
ssize_t bytes = 0;
|
||||
@ -68,19 +77,28 @@ static ssize_t cpuid_read(struct file *file, char __user *buf,
|
||||
if (count % 16)
|
||||
return -EINVAL; /* Invalid chunk size */
|
||||
|
||||
init_completion(&cmd.done);
|
||||
for (; count; count -= 16) {
|
||||
cmd.eax = pos;
|
||||
cmd.ecx = pos >> 32;
|
||||
err = smp_call_function_single(cpu, cpuid_smp_cpuid, &cmd, 1);
|
||||
call_single_data_t csd = {
|
||||
.func = cpuid_smp_cpuid,
|
||||
.info = &cmd,
|
||||
};
|
||||
|
||||
cmd.regs.eax = pos;
|
||||
cmd.regs.ecx = pos >> 32;
|
||||
|
||||
err = smp_call_function_single_async(cpu, &csd);
|
||||
if (err)
|
||||
break;
|
||||
if (copy_to_user(tmp, &cmd, 16)) {
|
||||
wait_for_completion(&cmd.done);
|
||||
if (copy_to_user(tmp, &cmd.regs, 16)) {
|
||||
err = -EFAULT;
|
||||
break;
|
||||
}
|
||||
tmp += 16;
|
||||
bytes += 16;
|
||||
*ppos = ++pos;
|
||||
reinit_completion(&cmd.done);
|
||||
}
|
||||
|
||||
return bytes ? bytes : err;
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
int panic_on_unrecovered_nmi;
|
||||
int panic_on_io_nmi;
|
||||
unsigned int code_bytes = 64;
|
||||
static unsigned int code_bytes = 64;
|
||||
static int die_counter;
|
||||
|
||||
bool in_task_stack(unsigned long *stack, struct task_struct *task,
|
||||
@ -375,3 +375,50 @@ static int __init code_bytes_setup(char *s)
|
||||
return 1;
|
||||
}
|
||||
__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 @@ unknown:
|
||||
info->type = STACK_TYPE_UNKNOWN;
|
||||
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 @@ unknown:
|
||||
info->type = STACK_TYPE_UNKNOWN;
|
||||
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);
|
||||
*/
|
||||
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;
|
||||
int retval = 0;
|
||||
|
||||
rtc_time_to_tm(nowtime, &tm);
|
||||
rtc_time64_to_tm(nowtime, &tm);
|
||||
if (!rtc_valid_tm(&tm)) {
|
||||
retval = mc146818_set_time(&tm);
|
||||
if (retval)
|
||||
@ -53,7 +53,7 @@ int mach_set_rtc_mmss(const struct timespec *now)
|
||||
__func__, retval);
|
||||
} else {
|
||||
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);
|
||||
retval = -EINVAL;
|
||||
}
|
||||
|
@ -49,7 +49,6 @@
|
||||
#include <asm/debugreg.h>
|
||||
#include <asm/kvm_para.h>
|
||||
#include <asm/irq_remapping.h>
|
||||
#include <asm/microcode.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
|
||||
#include <asm/virtext.h>
|
||||
|
@ -51,7 +51,6 @@
|
||||
#include <asm/apic.h>
|
||||
#include <asm/irq_remapping.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/microcode.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
|
||||
#include "trace.h"
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/preempt.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/completion.h>
|
||||
#include <asm/msr.h>
|
||||
|
||||
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)
|
||||
}
|
||||
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
|
||||
may not actually exist. */
|
||||
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)
|
||||
@ -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)
|
||||
{
|
||||
struct msr_info_completion rv;
|
||||
call_single_data_t csd = {
|
||||
.func = __rdmsr_safe_on_cpu,
|
||||
.info = &rv,
|
||||
};
|
||||
int err;
|
||||
struct msr_info 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(cpu, __rdmsr_safe_on_cpu, &rv, 1);
|
||||
*l = rv.reg.l;
|
||||
*h = rv.reg.h;
|
||||
err = smp_call_function_single_async(cpu, &csd);
|
||||
if (!err) {
|
||||
wait_for_completion(&rv.done);
|
||||
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);
|
||||
|
||||
@ -209,16 +225,13 @@ EXPORT_SYMBOL(wrmsrl_safe_on_cpu);
|
||||
|
||||
int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q)
|
||||
{
|
||||
u32 low, high;
|
||||
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;
|
||||
err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1);
|
||||
*q = rv.reg.q;
|
||||
|
||||
return err ? err : rv.err;
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(rdmsrl_safe_on_cpu);
|
||||
|
||||
|
@ -699,7 +699,6 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code,
|
||||
printk(KERN_CONT "paging request");
|
||||
|
||||
printk(KERN_CONT " at %px\n", (void *) address);
|
||||
printk(KERN_ALERT "IP: %pS\n", (void *)regs->ip);
|
||||
|
||||
dump_pagetable(address);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user