x86_64/entry/xen: Do not invoke espfix64 on Xen
[pandora-kernel.git] / arch / x86 / kernel / entry_64.S
index be846d2..c844f08 100644 (file)
 #include <asm/page_types.h>
 #include <asm/irqflags.h>
 #include <asm/paravirt.h>
-#include <asm/ftrace.h>
 #include <asm/percpu.h>
 #include <asm/asm.h>
 #include <asm/context_tracking.h>
 #include <asm/smap.h>
+#include <asm/pgtable_types.h>
 #include <linux/err.h>
 
 /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
        .code64
        .section .entry.text, "ax"
 
-#ifdef CONFIG_FUNCTION_TRACER
-
-#ifdef CC_USING_FENTRY
-# define function_hook __fentry__
-#else
-# define function_hook mcount
-#endif
-
-#ifdef CONFIG_DYNAMIC_FTRACE
-
-ENTRY(function_hook)
-       retq
-END(function_hook)
-
-/* skip is set if stack has been adjusted */
-.macro ftrace_caller_setup skip=0
-       MCOUNT_SAVE_FRAME \skip
-
-       /* Load the ftrace_ops into the 3rd parameter */
-       movq function_trace_op(%rip), %rdx
-
-       /* Load ip into the first parameter */
-       movq RIP(%rsp), %rdi
-       subq $MCOUNT_INSN_SIZE, %rdi
-       /* Load the parent_ip into the second parameter */
-#ifdef CC_USING_FENTRY
-       movq SS+16(%rsp), %rsi
-#else
-       movq 8(%rbp), %rsi
-#endif
-.endm
-
-ENTRY(ftrace_caller)
-       /* Check if tracing was disabled (quick check) */
-       cmpl $0, function_trace_stop
-       jne  ftrace_stub
-
-       ftrace_caller_setup
-       /* regs go into 4th parameter (but make it NULL) */
-       movq $0, %rcx
-
-GLOBAL(ftrace_call)
-       call ftrace_stub
-
-       MCOUNT_RESTORE_FRAME
-ftrace_return:
-
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-GLOBAL(ftrace_graph_call)
-       jmp ftrace_stub
-#endif
-
-GLOBAL(ftrace_stub)
-       retq
-END(ftrace_caller)
-
-ENTRY(ftrace_regs_caller)
-       /* Save the current flags before compare (in SS location)*/
-       pushfq
-
-       /* Check if tracing was disabled (quick check) */
-       cmpl $0, function_trace_stop
-       jne  ftrace_restore_flags
-
-       /* skip=8 to skip flags saved in SS */
-       ftrace_caller_setup 8
-
-       /* Save the rest of pt_regs */
-       movq %r15, R15(%rsp)
-       movq %r14, R14(%rsp)
-       movq %r13, R13(%rsp)
-       movq %r12, R12(%rsp)
-       movq %r11, R11(%rsp)
-       movq %r10, R10(%rsp)
-       movq %rbp, RBP(%rsp)
-       movq %rbx, RBX(%rsp)
-       /* Copy saved flags */
-       movq SS(%rsp), %rcx
-       movq %rcx, EFLAGS(%rsp)
-       /* Kernel segments */
-       movq $__KERNEL_DS, %rcx
-       movq %rcx, SS(%rsp)
-       movq $__KERNEL_CS, %rcx
-       movq %rcx, CS(%rsp)
-       /* Stack - skipping return address */
-       leaq SS+16(%rsp), %rcx
-       movq %rcx, RSP(%rsp)
-
-       /* regs go into 4th parameter */
-       leaq (%rsp), %rcx
-
-GLOBAL(ftrace_regs_call)
-       call ftrace_stub
-
-       /* Copy flags back to SS, to restore them */
-       movq EFLAGS(%rsp), %rax
-       movq %rax, SS(%rsp)
-
-       /* Handlers can change the RIP */
-       movq RIP(%rsp), %rax
-       movq %rax, SS+8(%rsp)
-
-       /* restore the rest of pt_regs */
-       movq R15(%rsp), %r15
-       movq R14(%rsp), %r14
-       movq R13(%rsp), %r13
-       movq R12(%rsp), %r12
-       movq R10(%rsp), %r10
-       movq RBP(%rsp), %rbp
-       movq RBX(%rsp), %rbx
-
-       /* skip=8 to skip flags saved in SS */
-       MCOUNT_RESTORE_FRAME 8
-
-       /* Restore flags */
-       popfq
-
-       jmp ftrace_return
-ftrace_restore_flags:
-       popfq
-       jmp  ftrace_stub
-
-END(ftrace_regs_caller)
-
-
-#else /* ! CONFIG_DYNAMIC_FTRACE */
-
-ENTRY(function_hook)
-       cmpl $0, function_trace_stop
-       jne  ftrace_stub
-
-       cmpq $ftrace_stub, ftrace_trace_function
-       jnz trace
-
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-       cmpq $ftrace_stub, ftrace_graph_return
-       jnz ftrace_graph_caller
-
-       cmpq $ftrace_graph_entry_stub, ftrace_graph_entry
-       jnz ftrace_graph_caller
-#endif
-
-GLOBAL(ftrace_stub)
-       retq
-
-trace:
-       MCOUNT_SAVE_FRAME
-
-       movq RIP(%rsp), %rdi
-#ifdef CC_USING_FENTRY
-       movq SS+16(%rsp), %rsi
-#else
-       movq 8(%rbp), %rsi
-#endif
-       subq $MCOUNT_INSN_SIZE, %rdi
-
-       call   *ftrace_trace_function
-
-       MCOUNT_RESTORE_FRAME
-
-       jmp ftrace_stub
-END(function_hook)
-#endif /* CONFIG_DYNAMIC_FTRACE */
-#endif /* CONFIG_FUNCTION_TRACER */
-
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-ENTRY(ftrace_graph_caller)
-       MCOUNT_SAVE_FRAME
-
-#ifdef CC_USING_FENTRY
-       leaq SS+16(%rsp), %rdi
-       movq $0, %rdx   /* No framepointers needed */
-#else
-       leaq 8(%rbp), %rdi
-       movq (%rbp), %rdx
-#endif
-       movq RIP(%rsp), %rsi
-       subq $MCOUNT_INSN_SIZE, %rsi
-
-       call    prepare_ftrace_return
-
-       MCOUNT_RESTORE_FRAME
-
-       retq
-END(ftrace_graph_caller)
-
-GLOBAL(return_to_handler)
-       subq  $24, %rsp
-
-       /* Save the return values */
-       movq %rax, (%rsp)
-       movq %rdx, 8(%rsp)
-       movq %rbp, %rdi
-
-       call ftrace_return_to_handler
-
-       movq %rax, %rdi
-       movq 8(%rsp), %rdx
-       movq (%rsp), %rax
-       addq $24, %rsp
-       jmp *%rdi
-#endif
-
 
 #ifndef CONFIG_PREEMPT
 #define retint_kernel retint_restore_args
@@ -487,8 +284,6 @@ ENDPROC(native_usergs_sysret64)
        TRACE_IRQS_OFF
        .endm
 
-/* save complete stack frame */
-       .pushsection .kprobes.text, "ax"
 ENTRY(save_paranoid)
        XCPT_FRAME 1 RDI+8
        cld
@@ -517,7 +312,6 @@ ENTRY(save_paranoid)
 1:     ret
        CFI_ENDPROC
 END(save_paranoid)
-       .popsection
 
 /*
  * A newly forked process directly context switches into this address.
@@ -975,10 +769,6 @@ END(interrupt)
        call \func
        .endm
 
-/*
- * Interrupt entry/exit should be protected against kprobes
- */
-       .pushsection .kprobes.text, "ax"
        /*
         * The interrupt stubs push (~vector+0x80) onto the stack and
         * then jump to common_interrupt.
@@ -1041,12 +831,45 @@ restore_args:
 
 irq_return:
        INTERRUPT_RETURN
-       _ASM_EXTABLE(irq_return, bad_iret)
 
-#ifdef CONFIG_PARAVIRT
 ENTRY(native_iret)
+       /*
+        * Are we returning to a stack segment from the LDT?  Note: in
+        * 64-bit mode SS:RSP on the exception stack is always valid.
+        */
+#ifdef CONFIG_X86_ESPFIX64
+       testb $4,(SS-RIP)(%rsp)
+       jnz native_irq_return_ldt
+#endif
+
+native_irq_return_iret:
        iretq
-       _ASM_EXTABLE(native_iret, bad_iret)
+       _ASM_EXTABLE(native_irq_return_iret, bad_iret)
+
+#ifdef CONFIG_X86_ESPFIX64
+native_irq_return_ldt:
+       pushq_cfi %rax
+       pushq_cfi %rdi
+       SWAPGS
+       movq PER_CPU_VAR(espfix_waddr),%rdi
+       movq %rax,(0*8)(%rdi)   /* RAX */
+       movq (2*8)(%rsp),%rax   /* RIP */
+       movq %rax,(1*8)(%rdi)
+       movq (3*8)(%rsp),%rax   /* CS */
+       movq %rax,(2*8)(%rdi)
+       movq (4*8)(%rsp),%rax   /* RFLAGS */
+       movq %rax,(3*8)(%rdi)
+       movq (6*8)(%rsp),%rax   /* SS */
+       movq %rax,(5*8)(%rdi)
+       movq (5*8)(%rsp),%rax   /* RSP */
+       movq %rax,(4*8)(%rdi)
+       andl $0xffff0000,%eax
+       popq_cfi %rdi
+       orq PER_CPU_VAR(espfix_stack),%rax
+       SWAPGS
+       movq %rax,%rsp
+       popq_cfi %rax
+       jmp native_irq_return_iret
 #endif
 
        .section .fixup,"ax"
@@ -1110,13 +933,39 @@ ENTRY(retint_kernel)
        call preempt_schedule_irq
        jmp exit_intr
 #endif
-
        CFI_ENDPROC
 END(common_interrupt)
-/*
- * End of kprobes section
- */
-       .popsection
+
+       /*
+        * If IRET takes a fault on the espfix stack, then we
+        * end up promoting it to a doublefault.  In that case,
+        * modify the stack to make it look like we just entered
+        * the #GP handler from user space, similar to bad_iret.
+        */
+#ifdef CONFIG_X86_ESPFIX64
+       ALIGN
+__do_double_fault:
+       XCPT_FRAME 1 RDI+8
+       movq RSP(%rdi),%rax             /* Trap on the espfix stack? */
+       sarq $PGDIR_SHIFT,%rax
+       cmpl $ESPFIX_PGD_ENTRY,%eax
+       jne do_double_fault             /* No, just deliver the fault */
+       cmpl $__KERNEL_CS,CS(%rdi)
+       jne do_double_fault
+       movq RIP(%rdi),%rax
+       cmpq $native_irq_return_iret,%rax
+       jne do_double_fault             /* This shouldn't happen... */
+       movq PER_CPU_VAR(kernel_stack),%rax
+       subq $(6*8-KERNEL_STACK_OFFSET),%rax    /* Reset to original stack */
+       movq %rax,RSP(%rdi)
+       movq $0,(%rax)                  /* Missing (lost) #GP error code */
+       movq $general_protection,RIP(%rdi)
+       retq
+       CFI_ENDPROC
+END(__do_double_fault)
+#else
+# define __do_double_fault do_double_fault
+#endif
 
 /*
  * APIC interrupts.
@@ -1289,7 +1138,7 @@ idtentry overflow do_overflow has_error_code=0
 idtentry bounds do_bounds has_error_code=0
 idtentry invalid_op do_invalid_op has_error_code=0
 idtentry device_not_available do_device_not_available has_error_code=0
-idtentry double_fault do_double_fault has_error_code=1 paranoid=1
+idtentry double_fault __do_double_fault has_error_code=1 paranoid=1
 idtentry coprocessor_segment_overrun do_coprocessor_segment_overrun has_error_code=0
 idtentry invalid_TSS do_invalid_TSS has_error_code=1
 idtentry segment_not_present do_segment_not_present has_error_code=1
@@ -1452,11 +1301,6 @@ apicinterrupt3 HYPERVISOR_CALLBACK_VECTOR \
        hyperv_callback_vector hyperv_vector_handler
 #endif /* CONFIG_HYPERV */
 
-/*
- * Some functions should be protected against kprobes
- */
-       .pushsection .kprobes.text, "ax"
-
 idtentry debug do_debug has_error_code=0 paranoid=1 shift_ist=DEBUG_STACK
 idtentry int3 do_int3 has_error_code=0 paranoid=1 shift_ist=DEBUG_STACK
 idtentry stack_segment do_stack_segment has_error_code=1 paranoid=1
@@ -1576,7 +1420,7 @@ error_sti:
  */
 error_kernelspace:
        incl %ebx
-       leaq irq_return(%rip),%rcx
+       leaq native_irq_return_iret(%rip),%rcx
        cmpq %rcx,RIP+8(%rsp)
        je error_swapgs
        movl %ecx,%eax  /* zero extend */
@@ -1873,7 +1717,3 @@ ENTRY(ignore_sysret)
        CFI_ENDPROC
 END(ignore_sysret)
 
-/*
- * End of kprobes section
- */
-       .popsection