diff options
| -rw-r--r-- | arch/x86/kernel/entry_64.S | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 320852d02026..7d65133b51be 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
| @@ -191,6 +191,44 @@ ENDPROC(native_usergs_sysret64) | |||
| 191 | .endm | 191 | .endm |
| 192 | 192 | ||
| 193 | /* | 193 | /* |
| 194 | * When dynamic function tracer is enabled it will add a breakpoint | ||
| 195 | * to all locations that it is about to modify, sync CPUs, update | ||
| 196 | * all the code, sync CPUs, then remove the breakpoints. In this time | ||
| 197 | * if lockdep is enabled, it might jump back into the debug handler | ||
| 198 | * outside the updating of the IST protection. (TRACE_IRQS_ON/OFF). | ||
| 199 | * | ||
| 200 | * We need to change the IDT table before calling TRACE_IRQS_ON/OFF to | ||
| 201 | * make sure the stack pointer does not get reset back to the top | ||
| 202 | * of the debug stack, and instead just reuses the current stack. | ||
| 203 | */ | ||
| 204 | #if defined(CONFIG_DYNAMIC_FTRACE) && defined(CONFIG_TRACE_IRQFLAGS) | ||
| 205 | |||
| 206 | .macro TRACE_IRQS_OFF_DEBUG | ||
| 207 | call debug_stack_set_zero | ||
| 208 | TRACE_IRQS_OFF | ||
| 209 | call debug_stack_reset | ||
| 210 | .endm | ||
| 211 | |||
| 212 | .macro TRACE_IRQS_ON_DEBUG | ||
| 213 | call debug_stack_set_zero | ||
| 214 | TRACE_IRQS_ON | ||
| 215 | call debug_stack_reset | ||
| 216 | .endm | ||
| 217 | |||
| 218 | .macro TRACE_IRQS_IRETQ_DEBUG offset=ARGOFFSET | ||
| 219 | bt $9,EFLAGS-\offset(%rsp) /* interrupts off? */ | ||
| 220 | jnc 1f | ||
| 221 | TRACE_IRQS_ON_DEBUG | ||
| 222 | 1: | ||
| 223 | .endm | ||
| 224 | |||
| 225 | #else | ||
| 226 | # define TRACE_IRQS_OFF_DEBUG TRACE_IRQS_OFF | ||
| 227 | # define TRACE_IRQS_ON_DEBUG TRACE_IRQS_ON | ||
| 228 | # define TRACE_IRQS_IRETQ_DEBUG TRACE_IRQS_IRETQ | ||
| 229 | #endif | ||
| 230 | |||
| 231 | /* | ||
| 194 | * C code is not supposed to know about undefined top of stack. Every time | 232 | * C code is not supposed to know about undefined top of stack. Every time |
| 195 | * a C function with an pt_regs argument is called from the SYSCALL based | 233 | * a C function with an pt_regs argument is called from the SYSCALL based |
| 196 | * fast path FIXUP_TOP_OF_STACK is needed. | 234 | * fast path FIXUP_TOP_OF_STACK is needed. |
| @@ -1098,7 +1136,7 @@ ENTRY(\sym) | |||
| 1098 | subq $ORIG_RAX-R15, %rsp | 1136 | subq $ORIG_RAX-R15, %rsp |
| 1099 | CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 | 1137 | CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 |
| 1100 | call save_paranoid | 1138 | call save_paranoid |
| 1101 | TRACE_IRQS_OFF | 1139 | TRACE_IRQS_OFF_DEBUG |
| 1102 | movq %rsp,%rdi /* pt_regs pointer */ | 1140 | movq %rsp,%rdi /* pt_regs pointer */ |
| 1103 | xorl %esi,%esi /* no error code */ | 1141 | xorl %esi,%esi /* no error code */ |
| 1104 | subq $EXCEPTION_STKSZ, INIT_TSS_IST(\ist) | 1142 | subq $EXCEPTION_STKSZ, INIT_TSS_IST(\ist) |
| @@ -1393,7 +1431,7 @@ paranoidzeroentry machine_check *machine_check_vector(%rip) | |||
| 1393 | ENTRY(paranoid_exit) | 1431 | ENTRY(paranoid_exit) |
| 1394 | DEFAULT_FRAME | 1432 | DEFAULT_FRAME |
| 1395 | DISABLE_INTERRUPTS(CLBR_NONE) | 1433 | DISABLE_INTERRUPTS(CLBR_NONE) |
| 1396 | TRACE_IRQS_OFF | 1434 | TRACE_IRQS_OFF_DEBUG |
| 1397 | testl %ebx,%ebx /* swapgs needed? */ | 1435 | testl %ebx,%ebx /* swapgs needed? */ |
| 1398 | jnz paranoid_restore | 1436 | jnz paranoid_restore |
| 1399 | testl $3,CS(%rsp) | 1437 | testl $3,CS(%rsp) |
| @@ -1404,7 +1442,7 @@ paranoid_swapgs: | |||
| 1404 | RESTORE_ALL 8 | 1442 | RESTORE_ALL 8 |
| 1405 | jmp irq_return | 1443 | jmp irq_return |
| 1406 | paranoid_restore: | 1444 | paranoid_restore: |
| 1407 | TRACE_IRQS_IRETQ 0 | 1445 | TRACE_IRQS_IRETQ_DEBUG 0 |
| 1408 | RESTORE_ALL 8 | 1446 | RESTORE_ALL 8 |
| 1409 | jmp irq_return | 1447 | jmp irq_return |
| 1410 | paranoid_userspace: | 1448 | paranoid_userspace: |
