Commit 95648c0e authored by Linus Torvalds's avatar Linus Torvalds

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

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
parents 9579f10d 5fa10196
...@@ -134,6 +134,7 @@ extern void efi_setup_page_tables(void); ...@@ -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 old_map_region(efi_memory_desc_t *md);
extern void __init runtime_code_page_mkexec(void); extern void __init runtime_code_page_mkexec(void);
extern void __init efi_runtime_mkexec(void); extern void __init efi_runtime_mkexec(void);
extern void __init efi_apply_memmap_quirks(void);
struct efi_setup_data { struct efi_setup_data {
u64 fw_vendor; u64 fw_vendor;
......
...@@ -544,6 +544,10 @@ ENDPROC(early_idt_handlers) ...@@ -544,6 +544,10 @@ ENDPROC(early_idt_handlers)
/* This is global to keep gas from relaxing the jumps */ /* This is global to keep gas from relaxing the jumps */
ENTRY(early_idt_handler) ENTRY(early_idt_handler)
cld cld
cmpl $X86_TRAP_NMI,(%esp)
je is_nmi # Ignore NMI
cmpl $2,%ss:early_recursion_flag cmpl $2,%ss:early_recursion_flag
je hlt_loop je hlt_loop
incl %ss:early_recursion_flag incl %ss:early_recursion_flag
...@@ -594,8 +598,9 @@ ex_entry: ...@@ -594,8 +598,9 @@ ex_entry:
pop %edx pop %edx
pop %ecx pop %ecx
pop %eax pop %eax
addl $8,%esp /* drop vector number and error code */
decl %ss:early_recursion_flag decl %ss:early_recursion_flag
is_nmi:
addl $8,%esp /* drop vector number and error code */
iret iret
ENDPROC(early_idt_handler) ENDPROC(early_idt_handler)
......
...@@ -343,6 +343,9 @@ early_idt_handlers: ...@@ -343,6 +343,9 @@ early_idt_handlers:
ENTRY(early_idt_handler) ENTRY(early_idt_handler)
cld cld
cmpl $X86_TRAP_NMI,(%rsp)
je is_nmi # Ignore NMI
cmpl $2,early_recursion_flag(%rip) cmpl $2,early_recursion_flag(%rip)
jz 1f jz 1f
incl early_recursion_flag(%rip) incl early_recursion_flag(%rip)
...@@ -405,8 +408,9 @@ ENTRY(early_idt_handler) ...@@ -405,8 +408,9 @@ ENTRY(early_idt_handler)
popq %rdx popq %rdx
popq %rcx popq %rcx
popq %rax popq %rax
addq $16,%rsp # drop vector number and error code
decl early_recursion_flag(%rip) decl early_recursion_flag(%rip)
is_nmi:
addq $16,%rsp # drop vector number and error code
INTERRUPT_RETURN INTERRUPT_RETURN
ENDPROC(early_idt_handler) ENDPROC(early_idt_handler)
......
...@@ -1239,14 +1239,8 @@ void __init setup_arch(char **cmdline_p) ...@@ -1239,14 +1239,8 @@ void __init setup_arch(char **cmdline_p)
register_refined_jiffies(CLOCK_TICK_RATE); register_refined_jiffies(CLOCK_TICK_RATE);
#ifdef CONFIG_EFI #ifdef CONFIG_EFI
/* Once setup is done above, unmap the EFI memory map on if (efi_enabled(EFI_BOOT))
* mismatched firmware/kernel archtectures since there is no efi_apply_memmap_quirks();
* 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();
}
#endif #endif
} }
......
...@@ -1020,13 +1020,17 @@ static inline bool smap_violation(int error_code, struct pt_regs *regs) ...@@ -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, * This routine handles page faults. It determines the address,
* and the problem, and then passes it off to one of the appropriate * and the problem, and then passes it off to one of the appropriate
* routines. * 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 static void __kprobes noinline
__do_page_fault(struct pt_regs *regs, unsigned long error_code) __do_page_fault(struct pt_regs *regs, unsigned long error_code,
unsigned long address)
{ {
struct vm_area_struct *vma; struct vm_area_struct *vma;
struct task_struct *tsk; struct task_struct *tsk;
unsigned long address;
struct mm_struct *mm; struct mm_struct *mm;
int fault; int fault;
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; 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) ...@@ -1034,9 +1038,6 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
tsk = current; tsk = current;
mm = tsk->mm; mm = tsk->mm;
/* Get the faulting address: */
address = read_cr2();
/* /*
* Detect and handle instructions that would cause a page fault for * Detect and handle instructions that would cause a page fault for
* both a tracked kernel page and a userspace page. * both a tracked kernel page and a userspace page.
...@@ -1248,32 +1249,50 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -1248,32 +1249,50 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
} }
dotraplinkage void __kprobes dotraplinkage void __kprobes notrace
do_page_fault(struct pt_regs *regs, unsigned long error_code) 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; 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(); prev_state = exception_enter();
__do_page_fault(regs, error_code); __do_page_fault(regs, error_code, address);
exception_exit(prev_state); 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) unsigned long error_code)
{ {
if (user_mode(regs)) if (user_mode(regs))
trace_page_fault_user(read_cr2(), regs, error_code); trace_page_fault_user(address, regs, error_code);
else 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) 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; enum ctx_state prev_state;
prev_state = exception_enter(); prev_state = exception_enter();
trace_page_fault_entries(regs, error_code); trace_page_fault_entries(address, regs, error_code);
__do_page_fault(regs, error_code); __do_page_fault(regs, error_code, address);
exception_exit(prev_state); exception_exit(prev_state);
} }
#endif /* CONFIG_TRACING */
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/x86_init.h> #include <asm/x86_init.h>
#include <asm/rtc.h> #include <asm/rtc.h>
#include <asm/uv/uv.h>
#define EFI_DEBUG #define EFI_DEBUG
...@@ -1210,3 +1211,22 @@ static int __init parse_efi_cmdline(char *str) ...@@ -1210,3 +1211,22 @@ static int __init parse_efi_cmdline(char *str)
return 0; return 0;
} }
early_param("efi", parse_efi_cmdline); 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);
}
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