|
@@ -1048,6 +1048,11 @@ ENTRY(\sym)
|
|
|
CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
|
|
|
|
|
|
.if \paranoid
|
|
|
+ .if \paranoid == 1
|
|
|
+ CFI_REMEMBER_STATE
|
|
|
+ testl $3, CS(%rsp) /* If coming from userspace, switch */
|
|
|
+ jnz 1f /* stacks. */
|
|
|
+ .endif
|
|
|
call save_paranoid
|
|
|
.else
|
|
|
call error_entry
|
|
@@ -1088,6 +1093,36 @@ ENTRY(\sym)
|
|
|
jmp error_exit /* %ebx: no swapgs flag */
|
|
|
.endif
|
|
|
|
|
|
+ .if \paranoid == 1
|
|
|
+ CFI_RESTORE_STATE
|
|
|
+ /*
|
|
|
+ * Paranoid entry from userspace. Switch stacks and treat it
|
|
|
+ * as a normal entry. This means that paranoid handlers
|
|
|
+ * run in real process context if user_mode(regs).
|
|
|
+ */
|
|
|
+1:
|
|
|
+ call error_entry
|
|
|
+
|
|
|
+ DEFAULT_FRAME 0
|
|
|
+
|
|
|
+ movq %rsp,%rdi /* pt_regs pointer */
|
|
|
+ call sync_regs
|
|
|
+ movq %rax,%rsp /* switch stack */
|
|
|
+
|
|
|
+ movq %rsp,%rdi /* pt_regs pointer */
|
|
|
+
|
|
|
+ .if \has_error_code
|
|
|
+ movq ORIG_RAX(%rsp),%rsi /* get error code */
|
|
|
+ movq $-1,ORIG_RAX(%rsp) /* no syscall to restart */
|
|
|
+ .else
|
|
|
+ xorl %esi,%esi /* no error code */
|
|
|
+ .endif
|
|
|
+
|
|
|
+ call \do_sym
|
|
|
+
|
|
|
+ jmp error_exit /* %ebx: no swapgs flag */
|
|
|
+ .endif
|
|
|
+
|
|
|
CFI_ENDPROC
|
|
|
END(\sym)
|
|
|
.endm
|
|
@@ -1108,7 +1143,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=2
|
|
|
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
|
|
@@ -1289,16 +1324,14 @@ idtentry machine_check has_error_code=0 paranoid=1 do_sym=*machine_check_vector(
|
|
|
#endif
|
|
|
|
|
|
/*
|
|
|
- * "Paranoid" exit path from exception stack.
|
|
|
- * Paranoid because this is used by NMIs and cannot take
|
|
|
- * any kernel state for granted.
|
|
|
- * We don't do kernel preemption checks here, because only
|
|
|
- * NMI should be common and it does not enable IRQs and
|
|
|
- * cannot get reschedule ticks.
|
|
|
+ * "Paranoid" exit path from exception stack. This is invoked
|
|
|
+ * only on return from non-NMI IST interrupts that came
|
|
|
+ * from kernel space.
|
|
|
*
|
|
|
- * "trace" is 0 for the NMI handler only, because irq-tracing
|
|
|
- * is fundamentally NMI-unsafe. (we cannot change the soft and
|
|
|
- * hard flags at once, atomically)
|
|
|
+ * We may be returning to very strange contexts (e.g. very early
|
|
|
+ * in syscall entry), so checking for preemption here would
|
|
|
+ * be complicated. Fortunately, we there's no good reason
|
|
|
+ * to try to handle preemption here.
|
|
|
*/
|
|
|
|
|
|
/* ebx: no swapgs flag */
|
|
@@ -1308,43 +1341,14 @@ ENTRY(paranoid_exit)
|
|
|
TRACE_IRQS_OFF_DEBUG
|
|
|
testl %ebx,%ebx /* swapgs needed? */
|
|
|
jnz paranoid_restore
|
|
|
- testl $3,CS(%rsp)
|
|
|
- jnz paranoid_userspace
|
|
|
-paranoid_swapgs:
|
|
|
TRACE_IRQS_IRETQ 0
|
|
|
SWAPGS_UNSAFE_STACK
|
|
|
RESTORE_ALL 8
|
|
|
- jmp irq_return
|
|
|
+ INTERRUPT_RETURN
|
|
|
paranoid_restore:
|
|
|
TRACE_IRQS_IRETQ_DEBUG 0
|
|
|
RESTORE_ALL 8
|
|
|
- jmp irq_return
|
|
|
-paranoid_userspace:
|
|
|
- GET_THREAD_INFO(%rcx)
|
|
|
- movl TI_flags(%rcx),%ebx
|
|
|
- andl $_TIF_WORK_MASK,%ebx
|
|
|
- jz paranoid_swapgs
|
|
|
- movq %rsp,%rdi /* &pt_regs */
|
|
|
- call sync_regs
|
|
|
- movq %rax,%rsp /* switch stack for scheduling */
|
|
|
- testl $_TIF_NEED_RESCHED,%ebx
|
|
|
- jnz paranoid_schedule
|
|
|
- movl %ebx,%edx /* arg3: thread flags */
|
|
|
- TRACE_IRQS_ON
|
|
|
- ENABLE_INTERRUPTS(CLBR_NONE)
|
|
|
- xorl %esi,%esi /* arg2: oldset */
|
|
|
- movq %rsp,%rdi /* arg1: &pt_regs */
|
|
|
- call do_notify_resume
|
|
|
- DISABLE_INTERRUPTS(CLBR_NONE)
|
|
|
- TRACE_IRQS_OFF
|
|
|
- jmp paranoid_userspace
|
|
|
-paranoid_schedule:
|
|
|
- TRACE_IRQS_ON
|
|
|
- ENABLE_INTERRUPTS(CLBR_ANY)
|
|
|
- SCHEDULE_USER
|
|
|
- DISABLE_INTERRUPTS(CLBR_ANY)
|
|
|
- TRACE_IRQS_OFF
|
|
|
- jmp paranoid_userspace
|
|
|
+ INTERRUPT_RETURN
|
|
|
CFI_ENDPROC
|
|
|
END(paranoid_exit)
|
|
|
|