Browse Source

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
Linus Torvalds 7 years ago
parent
commit
986b37c0ae

+ 0 - 14
arch/x86/include/asm/microcode.h

@@ -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 */

+ 14 - 0
arch/x86/include/asm/msr.h

@@ -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;

+ 0 - 2
arch/x86/include/asm/stacktrace.h

@@ -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;

+ 26 - 8
arch/x86/kernel/cpuid.c

@@ -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 @@
 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,
-		    &cmd->eax, &cmd->ebx, &cmd->ecx, &cmd->edx);
+	complete(&cmd->done);
 }
 }
 
 
 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,
 	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;
-		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)
 		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;

+ 48 - 1
arch/x86/kernel/dumpstack.c

@@ -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)
 	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");
+}

+ 0 - 42
arch/x86/kernel/dumpstack_32.c

@@ -127,45 +127,3 @@ unknown:
 	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");
-}

+ 0 - 42
arch/x86/kernel/dumpstack_64.c

@@ -149,45 +149,3 @@ unknown:
 	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");
-}

+ 3 - 3
arch/x86/kernel/rtc.c

@@ -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)
 			       __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;
 	}
 	}

+ 0 - 1
arch/x86/kvm/svm.c

@@ -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>

+ 0 - 1
arch/x86/kvm/vmx.c

@@ -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"

+ 28 - 15
arch/x86/lib/msr-smp.c

@@ -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)
 }
 }
 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)
 
 
 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(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);
 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)
 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;
-	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);
 EXPORT_SYMBOL(rdmsrl_safe_on_cpu);
 
 

+ 0 - 1
arch/x86/mm/fault.c

@@ -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);
 }
 }