Browse Source

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

Pull x86 fixes from Ingo Molnar:
 "Misc fixes: two KASAN fixes, two EFI boot fixes, two boot-delay
  optimization fixes, and a fix for a IRQ handling hang observed on
  virtual platforms"

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/mm, kasan: Silence KASAN warnings in get_wchan()
  compiler, atomics, kasan: Provide READ_ONCE_NOCHECK()
  x86, kasan: Fix build failure on KASAN=y && KMEMCHECK=y kernels
  x86/smpboot: Fix CPU #1 boot timeout
  x86/smpboot: Fix cpu_init_udelay=10000 corner case boot parameter misbehavior
  x86/ioapic: Disable interrupts when re-routing legacy IRQs
  x86/setup: Extend low identity map to cover whole kernel range
  x86/efi: Fix multiple GOP device support
Linus Torvalds 9 years ago
parent
commit
0386729247

+ 6 - 2
arch/x86/boot/compressed/eboot.c

@@ -667,6 +667,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
 		bool conout_found = false;
 		bool conout_found = false;
 		void *dummy = NULL;
 		void *dummy = NULL;
 		u32 h = handles[i];
 		u32 h = handles[i];
+		u32 current_fb_base;
 
 
 		status = efi_call_early(handle_protocol, h,
 		status = efi_call_early(handle_protocol, h,
 					proto, (void **)&gop32);
 					proto, (void **)&gop32);
@@ -678,7 +679,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
 		if (status == EFI_SUCCESS)
 		if (status == EFI_SUCCESS)
 			conout_found = true;
 			conout_found = true;
 
 
-		status = __gop_query32(gop32, &info, &size, &fb_base);
+		status = __gop_query32(gop32, &info, &size, &current_fb_base);
 		if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
 		if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
 			/*
 			/*
 			 * Systems that use the UEFI Console Splitter may
 			 * Systems that use the UEFI Console Splitter may
@@ -692,6 +693,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
 			pixel_format = info->pixel_format;
 			pixel_format = info->pixel_format;
 			pixel_info = info->pixel_information;
 			pixel_info = info->pixel_information;
 			pixels_per_scan_line = info->pixels_per_scan_line;
 			pixels_per_scan_line = info->pixels_per_scan_line;
+			fb_base = current_fb_base;
 
 
 			/*
 			/*
 			 * Once we've found a GOP supporting ConOut,
 			 * Once we've found a GOP supporting ConOut,
@@ -770,6 +772,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
 		bool conout_found = false;
 		bool conout_found = false;
 		void *dummy = NULL;
 		void *dummy = NULL;
 		u64 h = handles[i];
 		u64 h = handles[i];
+		u32 current_fb_base;
 
 
 		status = efi_call_early(handle_protocol, h,
 		status = efi_call_early(handle_protocol, h,
 					proto, (void **)&gop64);
 					proto, (void **)&gop64);
@@ -781,7 +784,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
 		if (status == EFI_SUCCESS)
 		if (status == EFI_SUCCESS)
 			conout_found = true;
 			conout_found = true;
 
 
-		status = __gop_query64(gop64, &info, &size, &fb_base);
+		status = __gop_query64(gop64, &info, &size, &current_fb_base);
 		if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
 		if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
 			/*
 			/*
 			 * Systems that use the UEFI Console Splitter may
 			 * Systems that use the UEFI Console Splitter may
@@ -795,6 +798,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
 			pixel_format = info->pixel_format;
 			pixel_format = info->pixel_format;
 			pixel_info = info->pixel_information;
 			pixel_info = info->pixel_information;
 			pixels_per_scan_line = info->pixels_per_scan_line;
 			pixels_per_scan_line = info->pixels_per_scan_line;
+			fb_base = current_fb_base;
 
 
 			/*
 			/*
 			 * Once we've found a GOP supporting ConOut,
 			 * Once we've found a GOP supporting ConOut,

+ 2 - 3
arch/x86/include/asm/string_64.h

@@ -27,12 +27,11 @@ static __always_inline void *__inline_memcpy(void *to, const void *from, size_t
    function. */
    function. */
 
 
 #define __HAVE_ARCH_MEMCPY 1
 #define __HAVE_ARCH_MEMCPY 1
+extern void *memcpy(void *to, const void *from, size_t len);
 extern void *__memcpy(void *to, const void *from, size_t len);
 extern void *__memcpy(void *to, const void *from, size_t len);
 
 
 #ifndef CONFIG_KMEMCHECK
 #ifndef CONFIG_KMEMCHECK
-#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
-extern void *memcpy(void *to, const void *from, size_t len);
-#else
+#if (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || __GNUC__ < 4
 #define memcpy(dst, src, len)					\
 #define memcpy(dst, src, len)					\
 ({								\
 ({								\
 	size_t __len = (len);					\
 	size_t __len = (len);					\

+ 4 - 0
arch/x86/kernel/apic/io_apic.c

@@ -2907,6 +2907,7 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
 	struct irq_data *irq_data;
 	struct irq_data *irq_data;
 	struct mp_chip_data *data;
 	struct mp_chip_data *data;
 	struct irq_alloc_info *info = arg;
 	struct irq_alloc_info *info = arg;
+	unsigned long flags;
 
 
 	if (!info || nr_irqs > 1)
 	if (!info || nr_irqs > 1)
 		return -EINVAL;
 		return -EINVAL;
@@ -2939,11 +2940,14 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
 
 
 	cfg = irqd_cfg(irq_data);
 	cfg = irqd_cfg(irq_data);
 	add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin);
 	add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin);
+
+	local_irq_save(flags);
 	if (info->ioapic_entry)
 	if (info->ioapic_entry)
 		mp_setup_entry(cfg, data, info->ioapic_entry);
 		mp_setup_entry(cfg, data, info->ioapic_entry);
 	mp_register_handler(virq, data->trigger);
 	mp_register_handler(virq, data->trigger);
 	if (virq < nr_legacy_irqs())
 	if (virq < nr_legacy_irqs())
 		legacy_pic->mask(virq);
 		legacy_pic->mask(virq);
+	local_irq_restore(flags);
 
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG
 	apic_printk(APIC_VERBOSE, KERN_DEBUG
 		    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i Dest:%d)\n",
 		    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i Dest:%d)\n",

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

@@ -550,14 +550,14 @@ unsigned long get_wchan(struct task_struct *p)
 	if (sp < bottom || sp > top)
 	if (sp < bottom || sp > top)
 		return 0;
 		return 0;
 
 
-	fp = READ_ONCE(*(unsigned long *)sp);
+	fp = READ_ONCE_NOCHECK(*(unsigned long *)sp);
 	do {
 	do {
 		if (fp < bottom || fp > top)
 		if (fp < bottom || fp > top)
 			return 0;
 			return 0;
-		ip = READ_ONCE(*(unsigned long *)(fp + sizeof(unsigned long)));
+		ip = READ_ONCE_NOCHECK(*(unsigned long *)(fp + sizeof(unsigned long)));
 		if (!in_sched_functions(ip))
 		if (!in_sched_functions(ip))
 			return ip;
 			return ip;
-		fp = READ_ONCE(*(unsigned long *)fp);
+		fp = READ_ONCE_NOCHECK(*(unsigned long *)fp);
 	} while (count++ < 16 && p->state != TASK_RUNNING);
 	} while (count++ < 16 && p->state != TASK_RUNNING);
 	return 0;
 	return 0;
 }
 }

+ 8 - 0
arch/x86/kernel/setup.c

@@ -1173,6 +1173,14 @@ void __init setup_arch(char **cmdline_p)
 	clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
 	clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
 			swapper_pg_dir     + KERNEL_PGD_BOUNDARY,
 			swapper_pg_dir     + KERNEL_PGD_BOUNDARY,
 			KERNEL_PGD_PTRS);
 			KERNEL_PGD_PTRS);
+
+	/*
+	 * sync back low identity map too.  It is used for example
+	 * in the 32-bit EFI stub.
+	 */
+	clone_pgd_range(initial_page_table,
+			swapper_pg_dir     + KERNEL_PGD_BOUNDARY,
+			KERNEL_PGD_PTRS);
 #endif
 #endif
 
 
 	tboot_probe();
 	tboot_probe();

+ 11 - 4
arch/x86/kernel/smpboot.c

@@ -509,7 +509,7 @@ void __inquire_remote_apic(int apicid)
  */
  */
 #define UDELAY_10MS_DEFAULT 10000
 #define UDELAY_10MS_DEFAULT 10000
 
 
-static unsigned int init_udelay = UDELAY_10MS_DEFAULT;
+static unsigned int init_udelay = INT_MAX;
 
 
 static int __init cpu_init_udelay(char *str)
 static int __init cpu_init_udelay(char *str)
 {
 {
@@ -522,13 +522,16 @@ early_param("cpu_init_udelay", cpu_init_udelay);
 static void __init smp_quirk_init_udelay(void)
 static void __init smp_quirk_init_udelay(void)
 {
 {
 	/* if cmdline changed it from default, leave it alone */
 	/* if cmdline changed it from default, leave it alone */
-	if (init_udelay != UDELAY_10MS_DEFAULT)
+	if (init_udelay != INT_MAX)
 		return;
 		return;
 
 
 	/* if modern processor, use no delay */
 	/* if modern processor, use no delay */
 	if (((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 6)) ||
 	if (((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 6)) ||
 	    ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && (boot_cpu_data.x86 >= 0xF)))
 	    ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && (boot_cpu_data.x86 >= 0xF)))
 		init_udelay = 0;
 		init_udelay = 0;
+
+	/* else, use legacy delay */
+	init_udelay = UDELAY_10MS_DEFAULT;
 }
 }
 
 
 /*
 /*
@@ -657,7 +660,9 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
 		/*
 		/*
 		 * Give the other CPU some time to accept the IPI.
 		 * Give the other CPU some time to accept the IPI.
 		 */
 		 */
-		if (init_udelay)
+		if (init_udelay == 0)
+			udelay(10);
+		else
 			udelay(300);
 			udelay(300);
 
 
 		pr_debug("Startup point 1\n");
 		pr_debug("Startup point 1\n");
@@ -668,7 +673,9 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
 		/*
 		/*
 		 * Give the other CPU some time to accept the IPI.
 		 * Give the other CPU some time to accept the IPI.
 		 */
 		 */
-		if (init_udelay)
+		if (init_udelay == 0)
+			udelay(10);
+		else
 			udelay(200);
 			udelay(200);
 
 
 		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP.  */
 		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP.  */

+ 13 - 0
include/linux/compiler-gcc.h

@@ -237,12 +237,25 @@
 #define KASAN_ABI_VERSION 3
 #define KASAN_ABI_VERSION 3
 #endif
 #endif
 
 
+#if GCC_VERSION >= 40902
+/*
+ * Tell the compiler that address safety instrumentation (KASAN)
+ * should not be applied to that function.
+ * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
+ */
+#define __no_sanitize_address __attribute__((no_sanitize_address))
+#endif
+
 #endif	/* gcc version >= 40000 specific checks */
 #endif	/* gcc version >= 40000 specific checks */
 
 
 #if !defined(__noclone)
 #if !defined(__noclone)
 #define __noclone	/* not needed */
 #define __noclone	/* not needed */
 #endif
 #endif
 
 
+#if !defined(__no_sanitize_address)
+#define __no_sanitize_address
+#endif
+
 /*
 /*
  * A trick to suppress uninitialized variable warning without generating any
  * A trick to suppress uninitialized variable warning without generating any
  * code
  * code

+ 53 - 13
include/linux/compiler.h

@@ -198,19 +198,45 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
 
 
 #include <uapi/linux/types.h>
 #include <uapi/linux/types.h>
 
 
-static __always_inline void __read_once_size(const volatile void *p, void *res, int size)
+#define __READ_ONCE_SIZE						\
+({									\
+	switch (size) {							\
+	case 1: *(__u8 *)res = *(volatile __u8 *)p; break;		\
+	case 2: *(__u16 *)res = *(volatile __u16 *)p; break;		\
+	case 4: *(__u32 *)res = *(volatile __u32 *)p; break;		\
+	case 8: *(__u64 *)res = *(volatile __u64 *)p; break;		\
+	default:							\
+		barrier();						\
+		__builtin_memcpy((void *)res, (const void *)p, size);	\
+		barrier();						\
+	}								\
+})
+
+static __always_inline
+void __read_once_size(const volatile void *p, void *res, int size)
 {
 {
-	switch (size) {
-	case 1: *(__u8 *)res = *(volatile __u8 *)p; break;
-	case 2: *(__u16 *)res = *(volatile __u16 *)p; break;
-	case 4: *(__u32 *)res = *(volatile __u32 *)p; break;
-	case 8: *(__u64 *)res = *(volatile __u64 *)p; break;
-	default:
-		barrier();
-		__builtin_memcpy((void *)res, (const void *)p, size);
-		barrier();
-	}
+	__READ_ONCE_SIZE;
+}
+
+#ifdef CONFIG_KASAN
+/*
+ * This function is not 'inline' because __no_sanitize_address confilcts
+ * with inlining. Attempt to inline it may cause a build failure.
+ * 	https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
+ * '__maybe_unused' allows us to avoid defined-but-not-used warnings.
+ */
+static __no_sanitize_address __maybe_unused
+void __read_once_size_nocheck(const volatile void *p, void *res, int size)
+{
+	__READ_ONCE_SIZE;
+}
+#else
+static __always_inline
+void __read_once_size_nocheck(const volatile void *p, void *res, int size)
+{
+	__READ_ONCE_SIZE;
 }
 }
+#endif
 
 
 static __always_inline void __write_once_size(volatile void *p, void *res, int size)
 static __always_inline void __write_once_size(volatile void *p, void *res, int size)
 {
 {
@@ -248,8 +274,22 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
  * required ordering.
  * required ordering.
  */
  */
 
 
-#define READ_ONCE(x) \
-	({ union { typeof(x) __val; char __c[1]; } __u; __read_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
+#define __READ_ONCE(x, check)						\
+({									\
+	union { typeof(x) __val; char __c[1]; } __u;			\
+	if (check)							\
+		__read_once_size(&(x), __u.__c, sizeof(x));		\
+	else								\
+		__read_once_size_nocheck(&(x), __u.__c, sizeof(x));	\
+	__u.__val;							\
+})
+#define READ_ONCE(x) __READ_ONCE(x, 1)
+
+/*
+ * Use READ_ONCE_NOCHECK() instead of READ_ONCE() if you need
+ * to hide memory access from KASAN.
+ */
+#define READ_ONCE_NOCHECK(x) __READ_ONCE(x, 0)
 
 
 #define WRITE_ONCE(x, val) \
 #define WRITE_ONCE(x, val) \
 ({							\
 ({							\