diff options
Diffstat (limited to 'arch/x86/entry/common.c')
-rw-r--r-- | arch/x86/entry/common.c | 33 |
1 files changed, 11 insertions, 22 deletions
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index d69d1b6e6c31..e79d93d44ecd 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c | |||
@@ -45,6 +45,8 @@ __visible void enter_from_user_mode(void) | |||
45 | CT_WARN_ON(ct_state() != CONTEXT_USER); | 45 | CT_WARN_ON(ct_state() != CONTEXT_USER); |
46 | user_exit(); | 46 | user_exit(); |
47 | } | 47 | } |
48 | #else | ||
49 | static inline void enter_from_user_mode(void) {} | ||
48 | #endif | 50 | #endif |
49 | 51 | ||
50 | static void do_audit_syscall_entry(struct pt_regs *regs, u32 arch) | 52 | static void do_audit_syscall_entry(struct pt_regs *regs, u32 arch) |
@@ -85,17 +87,6 @@ unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch) | |||
85 | 87 | ||
86 | work = ACCESS_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY; | 88 | work = ACCESS_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY; |
87 | 89 | ||
88 | #ifdef CONFIG_CONTEXT_TRACKING | ||
89 | /* | ||
90 | * If TIF_NOHZ is set, we are required to call user_exit() before | ||
91 | * doing anything that could touch RCU. | ||
92 | */ | ||
93 | if (work & _TIF_NOHZ) { | ||
94 | enter_from_user_mode(); | ||
95 | work &= ~_TIF_NOHZ; | ||
96 | } | ||
97 | #endif | ||
98 | |||
99 | #ifdef CONFIG_SECCOMP | 90 | #ifdef CONFIG_SECCOMP |
100 | /* | 91 | /* |
101 | * Do seccomp first -- it should minimize exposure of other | 92 | * Do seccomp first -- it should minimize exposure of other |
@@ -344,6 +335,7 @@ __visible void do_syscall_64(struct pt_regs *regs) | |||
344 | struct thread_info *ti = pt_regs_to_thread_info(regs); | 335 | struct thread_info *ti = pt_regs_to_thread_info(regs); |
345 | unsigned long nr = regs->orig_ax; | 336 | unsigned long nr = regs->orig_ax; |
346 | 337 | ||
338 | enter_from_user_mode(); | ||
347 | local_irq_enable(); | 339 | local_irq_enable(); |
348 | 340 | ||
349 | if (READ_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY) | 341 | if (READ_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY) |
@@ -366,9 +358,9 @@ __visible void do_syscall_64(struct pt_regs *regs) | |||
366 | 358 | ||
367 | #if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION) | 359 | #if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION) |
368 | /* | 360 | /* |
369 | * Does a 32-bit syscall. Called with IRQs on and does all entry and | 361 | * Does a 32-bit syscall. Called with IRQs on in CONTEXT_KERNEL. Does |
370 | * exit work and returns with IRQs off. This function is extremely hot | 362 | * all entry and exit work and returns with IRQs off. This function is |
371 | * in workloads that use it, and it's usually called from | 363 | * extremely hot in workloads that use it, and it's usually called from |
372 | * do_fast_syscall_32, so forcibly inline it to improve performance. | 364 | * do_fast_syscall_32, so forcibly inline it to improve performance. |
373 | */ | 365 | */ |
374 | static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs) | 366 | static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs) |
@@ -409,6 +401,7 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs) | |||
409 | /* Handles int $0x80 */ | 401 | /* Handles int $0x80 */ |
410 | __visible void do_int80_syscall_32(struct pt_regs *regs) | 402 | __visible void do_int80_syscall_32(struct pt_regs *regs) |
411 | { | 403 | { |
404 | enter_from_user_mode(); | ||
412 | local_irq_enable(); | 405 | local_irq_enable(); |
413 | do_syscall_32_irqs_on(regs); | 406 | do_syscall_32_irqs_on(regs); |
414 | } | 407 | } |
@@ -431,12 +424,11 @@ __visible long do_fast_syscall_32(struct pt_regs *regs) | |||
431 | */ | 424 | */ |
432 | regs->ip = landing_pad; | 425 | regs->ip = landing_pad; |
433 | 426 | ||
434 | /* | 427 | enter_from_user_mode(); |
435 | * Fetch EBP from where the vDSO stashed it. | 428 | |
436 | * | ||
437 | * WARNING: We are in CONTEXT_USER and RCU isn't paying attention! | ||
438 | */ | ||
439 | local_irq_enable(); | 429 | local_irq_enable(); |
430 | |||
431 | /* Fetch EBP from where the vDSO stashed it. */ | ||
440 | if ( | 432 | if ( |
441 | #ifdef CONFIG_X86_64 | 433 | #ifdef CONFIG_X86_64 |
442 | /* | 434 | /* |
@@ -454,9 +446,6 @@ __visible long do_fast_syscall_32(struct pt_regs *regs) | |||
454 | /* User code screwed up. */ | 446 | /* User code screwed up. */ |
455 | local_irq_disable(); | 447 | local_irq_disable(); |
456 | regs->ax = -EFAULT; | 448 | regs->ax = -EFAULT; |
457 | #ifdef CONFIG_CONTEXT_TRACKING | ||
458 | enter_from_user_mode(); | ||
459 | #endif | ||
460 | prepare_exit_to_usermode(regs); | 449 | prepare_exit_to_usermode(regs); |
461 | return 0; /* Keep it simple: use IRET. */ | 450 | return 0; /* Keep it simple: use IRET. */ |
462 | } | 451 | } |