]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 8 Mar 2014 01:38:36 +0000 (17:38 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 8 Mar 2014 01:38:36 +0000 (17:38 -0800)
Pull x86 fixes from Peter Anvin:
 "A small collection of minor fixes.  The FPU stuff is still pending, I
  fear.  I haven't heard anything from Suresh so I suspect I'm going to
  have to dig into the init specifics myself and fix up the patchset"

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86: Ignore NMIs that come in during early boot
  x86, trace: Further robustify CR2 handling vs tracing
  x86, trace: Fix CR2 corruption when tracing page faults
  x86/efi: Quirk out SGI UV

arch/x86/include/asm/efi.h
arch/x86/kernel/head_32.S
arch/x86/kernel/head_64.S
arch/x86/kernel/setup.c
arch/x86/mm/fault.c
arch/x86/platform/efi/efi.c

index 3d6b9f81cc683e63fbdac6c3243ab7069087e0cd..acd86c850414e7f3adfffe860ffd22bd17e0d459 100644 (file)
@@ -134,6 +134,7 @@ extern void efi_setup_page_tables(void);
 extern void __init old_map_region(efi_memory_desc_t *md);
 extern void __init runtime_code_page_mkexec(void);
 extern void __init efi_runtime_mkexec(void);
+extern void __init efi_apply_memmap_quirks(void);
 
 struct efi_setup_data {
        u64 fw_vendor;
index 81ba27679f18ec6100bd167c3739608631a7c475..d2a21590794a868456f9f49ae41d28d5d7954de7 100644 (file)
@@ -544,6 +544,10 @@ ENDPROC(early_idt_handlers)
        /* This is global to keep gas from relaxing the jumps */
 ENTRY(early_idt_handler)
        cld
+
+       cmpl $X86_TRAP_NMI,(%esp)
+       je is_nmi               # Ignore NMI
+
        cmpl $2,%ss:early_recursion_flag
        je hlt_loop
        incl %ss:early_recursion_flag
@@ -594,8 +598,9 @@ ex_entry:
        pop %edx
        pop %ecx
        pop %eax
-       addl $8,%esp            /* drop vector number and error code */
        decl %ss:early_recursion_flag
+is_nmi:
+       addl $8,%esp            /* drop vector number and error code */
        iret
 ENDPROC(early_idt_handler)
 
index e1aabdb314c83740dd686eb4c70a6f40c312e258..33f36c78594e49d15867165f3a57b37336874cd7 100644 (file)
@@ -343,6 +343,9 @@ early_idt_handlers:
 ENTRY(early_idt_handler)
        cld
 
+       cmpl $X86_TRAP_NMI,(%rsp)
+       je is_nmi               # Ignore NMI
+
        cmpl $2,early_recursion_flag(%rip)
        jz  1f
        incl early_recursion_flag(%rip)
@@ -405,8 +408,9 @@ ENTRY(early_idt_handler)
        popq %rdx
        popq %rcx
        popq %rax
-       addq $16,%rsp           # drop vector number and error code
        decl early_recursion_flag(%rip)
+is_nmi:
+       addq $16,%rsp           # drop vector number and error code
        INTERRUPT_RETURN
 ENDPROC(early_idt_handler)
 
index 06853e6703541f8349106e17330f86621fa984db..ce72964b2f469db1b3c626ecadc18c2998ef98a4 100644 (file)
@@ -1239,14 +1239,8 @@ void __init setup_arch(char **cmdline_p)
        register_refined_jiffies(CLOCK_TICK_RATE);
 
 #ifdef CONFIG_EFI
-       /* Once setup is done above, unmap the EFI memory map on
-        * mismatched firmware/kernel archtectures since there is no
-        * support for runtime services.
-        */
-       if (efi_enabled(EFI_BOOT) && !efi_is_native()) {
-               pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
-               efi_unmap_memmap();
-       }
+       if (efi_enabled(EFI_BOOT))
+               efi_apply_memmap_quirks();
 #endif
 }
 
index 6dea040cc3a1d794c60466fb9e78eaa552b8806e..a10c8c79216187d2faa5add449762710d51c759b 100644 (file)
@@ -1020,13 +1020,17 @@ static inline bool smap_violation(int error_code, struct pt_regs *regs)
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
  * routines.
+ *
+ * This function must have noinline because both callers
+ * {,trace_}do_page_fault() have notrace on. Having this an actual function
+ * guarantees there's a function trace entry.
  */
-static void __kprobes
-__do_page_fault(struct pt_regs *regs, unsigned long error_code)
+static void __kprobes noinline
+__do_page_fault(struct pt_regs *regs, unsigned long error_code,
+               unsigned long address)
 {
        struct vm_area_struct *vma;
        struct task_struct *tsk;
-       unsigned long address;
        struct mm_struct *mm;
        int fault;
        unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
@@ -1034,9 +1038,6 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
        tsk = current;
        mm = tsk->mm;
 
-       /* Get the faulting address: */
-       address = read_cr2();
-
        /*
         * Detect and handle instructions that would cause a page fault for
         * both a tracked kernel page and a userspace page.
@@ -1248,32 +1249,50 @@ good_area:
        up_read(&mm->mmap_sem);
 }
 
-dotraplinkage void __kprobes
+dotraplinkage void __kprobes notrace
 do_page_fault(struct pt_regs *regs, unsigned long error_code)
 {
+       unsigned long address = read_cr2(); /* Get the faulting address */
        enum ctx_state prev_state;
 
+       /*
+        * We must have this function tagged with __kprobes, notrace and call
+        * read_cr2() before calling anything else. To avoid calling any kind
+        * of tracing machinery before we've observed the CR2 value.
+        *
+        * exception_{enter,exit}() contain all sorts of tracepoints.
+        */
+
        prev_state = exception_enter();
-       __do_page_fault(regs, error_code);
+       __do_page_fault(regs, error_code, address);
        exception_exit(prev_state);
 }
 
-static void trace_page_fault_entries(struct pt_regs *regs,
+#ifdef CONFIG_TRACING
+static void trace_page_fault_entries(unsigned long address, struct pt_regs *regs,
                                     unsigned long error_code)
 {
        if (user_mode(regs))
-               trace_page_fault_user(read_cr2(), regs, error_code);
+               trace_page_fault_user(address, regs, error_code);
        else
-               trace_page_fault_kernel(read_cr2(), regs, error_code);
+               trace_page_fault_kernel(address, regs, error_code);
 }
 
-dotraplinkage void __kprobes
+dotraplinkage void __kprobes notrace
 trace_do_page_fault(struct pt_regs *regs, unsigned long error_code)
 {
+       /*
+        * The exception_enter and tracepoint processing could
+        * trigger another page faults (user space callchain
+        * reading) and destroy the original cr2 value, so read
+        * the faulting address now.
+        */
+       unsigned long address = read_cr2();
        enum ctx_state prev_state;
 
        prev_state = exception_enter();
-       trace_page_fault_entries(regs, error_code);
-       __do_page_fault(regs, error_code);
+       trace_page_fault_entries(address, regs, error_code);
+       __do_page_fault(regs, error_code, address);
        exception_exit(prev_state);
 }
+#endif /* CONFIG_TRACING */
index 1a201ac7cef8a1f7f4ce5cff2a8f8dbc6b540c00..b97acecf3fd95667e2b67bba8f88bb80428480bb 100644 (file)
@@ -52,6 +52,7 @@
 #include <asm/tlbflush.h>
 #include <asm/x86_init.h>
 #include <asm/rtc.h>
+#include <asm/uv/uv.h>
 
 #define EFI_DEBUG
 
@@ -1210,3 +1211,22 @@ static int __init parse_efi_cmdline(char *str)
        return 0;
 }
 early_param("efi", parse_efi_cmdline);
+
+void __init efi_apply_memmap_quirks(void)
+{
+       /*
+        * Once setup is done earlier, unmap the EFI memory map on mismatched
+        * firmware/kernel architectures since there is no support for runtime
+        * services.
+        */
+       if (!efi_is_native()) {
+               pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
+               efi_unmap_memmap();
+       }
+
+       /*
+        * UV doesn't support the new EFI pagetable mapping yet.
+        */
+       if (is_uv_system())
+               set_bit(EFI_OLD_MEMMAP, &x86_efi_facility);
+}