forked from luck/tmp_suning_uos_patched
arch/tile: move user_exit() to early kernel entry sequence
This ensures that we always notify context tracking that we
have exited from user space no matter how we enter the kernel.
It is similar to how arm64 handles context tracking, for example.
This allows the removal of all the exception_enter() calls that
were added in commit 49e4e15619
("tile: support CONTEXT_TRACKING and
thus NOHZ_FULL").
Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com>
This commit is contained in:
parent
9ce815ed50
commit
1bb50cad45
@ -572,7 +572,7 @@ intvec_\vecname:
|
|||||||
}
|
}
|
||||||
wh64 r52
|
wh64 r52
|
||||||
|
|
||||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
#if defined(CONFIG_TRACE_IRQFLAGS) || defined(CONFIG_CONTEXT_TRACKING)
|
||||||
.ifnc \function,handle_nmi
|
.ifnc \function,handle_nmi
|
||||||
/*
|
/*
|
||||||
* We finally have enough state set up to notify the irq
|
* We finally have enough state set up to notify the irq
|
||||||
@ -588,6 +588,9 @@ intvec_\vecname:
|
|||||||
{ move r32, r2; move r33, r3 }
|
{ move r32, r2; move r33, r3 }
|
||||||
.endif
|
.endif
|
||||||
TRACE_IRQS_OFF
|
TRACE_IRQS_OFF
|
||||||
|
#ifdef CONFIG_CONTEXT_TRACKING
|
||||||
|
jal context_tracking_user_exit
|
||||||
|
#endif
|
||||||
.ifnc \function,handle_syscall
|
.ifnc \function,handle_syscall
|
||||||
{ move r0, r30; move r1, r31 }
|
{ move r0, r30; move r1, r31 }
|
||||||
{ move r2, r32; move r3, r33 }
|
{ move r2, r32; move r3, r33 }
|
||||||
|
@ -753,7 +753,7 @@ intvec_\vecname:
|
|||||||
}
|
}
|
||||||
wh64 r52
|
wh64 r52
|
||||||
|
|
||||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
#if defined(CONFIG_TRACE_IRQFLAGS) || defined(CONFIG_CONTEXT_TRACKING)
|
||||||
.ifnc \function,handle_nmi
|
.ifnc \function,handle_nmi
|
||||||
/*
|
/*
|
||||||
* We finally have enough state set up to notify the irq
|
* We finally have enough state set up to notify the irq
|
||||||
@ -769,6 +769,9 @@ intvec_\vecname:
|
|||||||
{ move r32, r2; move r33, r3 }
|
{ move r32, r2; move r33, r3 }
|
||||||
.endif
|
.endif
|
||||||
TRACE_IRQS_OFF
|
TRACE_IRQS_OFF
|
||||||
|
#ifdef CONFIG_CONTEXT_TRACKING
|
||||||
|
jal context_tracking_user_exit
|
||||||
|
#endif
|
||||||
.ifnc \function,handle_syscall
|
.ifnc \function,handle_syscall
|
||||||
{ move r0, r30; move r1, r31 }
|
{ move r0, r30; move r1, r31 }
|
||||||
{ move r2, r32; move r3, r33 }
|
{ move r2, r32; move r3, r33 }
|
||||||
|
@ -255,13 +255,6 @@ int do_syscall_trace_enter(struct pt_regs *regs)
|
|||||||
{
|
{
|
||||||
u32 work = ACCESS_ONCE(current_thread_info()->flags);
|
u32 work = ACCESS_ONCE(current_thread_info()->flags);
|
||||||
|
|
||||||
/*
|
|
||||||
* If TIF_NOHZ is set, we are required to call user_exit() before
|
|
||||||
* doing anything that could touch RCU.
|
|
||||||
*/
|
|
||||||
if (work & _TIF_NOHZ)
|
|
||||||
user_exit();
|
|
||||||
|
|
||||||
if (secure_computing() == -1)
|
if (secure_computing() == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -280,12 +273,6 @@ void do_syscall_trace_exit(struct pt_regs *regs)
|
|||||||
{
|
{
|
||||||
long errno;
|
long errno;
|
||||||
|
|
||||||
/*
|
|
||||||
* We may come here right after calling schedule_user()
|
|
||||||
* in which case we can be in RCU user mode.
|
|
||||||
*/
|
|
||||||
user_exit();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The standard tile calling convention returns the value (or negative
|
* The standard tile calling convention returns the value (or negative
|
||||||
* errno) in r0, and zero (or positive errno) in r1.
|
* errno) in r0, and zero (or positive errno) in r1.
|
||||||
@ -322,7 +309,5 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs)
|
|||||||
/* Handle synthetic interrupt delivered only by the simulator. */
|
/* Handle synthetic interrupt delivered only by the simulator. */
|
||||||
void __kprobes do_breakpoint(struct pt_regs* regs, int fault_num)
|
void __kprobes do_breakpoint(struct pt_regs* regs, int fault_num)
|
||||||
{
|
{
|
||||||
enum ctx_state prev_state = exception_enter();
|
|
||||||
send_sigtrap(current, regs);
|
send_sigtrap(current, regs);
|
||||||
exception_exit(prev_state);
|
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/prctl.h>
|
#include <linux/prctl.h>
|
||||||
#include <linux/context_tracking.h>
|
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/traps.h>
|
#include <asm/traps.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
@ -739,7 +738,6 @@ static DEFINE_PER_CPU(unsigned long, ss_saved_pc);
|
|||||||
|
|
||||||
void gx_singlestep_handle(struct pt_regs *regs, int fault_num)
|
void gx_singlestep_handle(struct pt_regs *regs, int fault_num)
|
||||||
{
|
{
|
||||||
enum ctx_state prev_state = exception_enter();
|
|
||||||
unsigned long *ss_pc = this_cpu_ptr(&ss_saved_pc);
|
unsigned long *ss_pc = this_cpu_ptr(&ss_saved_pc);
|
||||||
struct thread_info *info = (void *)current_thread_info();
|
struct thread_info *info = (void *)current_thread_info();
|
||||||
int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP);
|
int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP);
|
||||||
@ -756,7 +754,6 @@ void gx_singlestep_handle(struct pt_regs *regs, int fault_num)
|
|||||||
__insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control);
|
__insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control);
|
||||||
send_sigtrap(current, regs);
|
send_sigtrap(current, regs);
|
||||||
}
|
}
|
||||||
exception_exit(prev_state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include <linux/reboot.h>
|
#include <linux/reboot.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
#include <linux/context_tracking.h>
|
|
||||||
#include <asm/stack.h>
|
#include <asm/stack.h>
|
||||||
#include <asm/traps.h>
|
#include <asm/traps.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
@ -254,7 +253,6 @@ static int do_bpt(struct pt_regs *regs)
|
|||||||
void __kprobes do_trap(struct pt_regs *regs, int fault_num,
|
void __kprobes do_trap(struct pt_regs *regs, int fault_num,
|
||||||
unsigned long reason)
|
unsigned long reason)
|
||||||
{
|
{
|
||||||
enum ctx_state prev_state = exception_enter();
|
|
||||||
siginfo_t info = { 0 };
|
siginfo_t info = { 0 };
|
||||||
int signo, code;
|
int signo, code;
|
||||||
unsigned long address = 0;
|
unsigned long address = 0;
|
||||||
@ -263,7 +261,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
|
|||||||
|
|
||||||
/* Handle breakpoints, etc. */
|
/* Handle breakpoints, etc. */
|
||||||
if (is_kernel && fault_num == INT_ILL && do_bpt(regs))
|
if (is_kernel && fault_num == INT_ILL && do_bpt(regs))
|
||||||
goto done;
|
return;
|
||||||
|
|
||||||
/* Re-enable interrupts, if they were previously enabled. */
|
/* Re-enable interrupts, if they were previously enabled. */
|
||||||
if (!(regs->flags & PT_FLAGS_DISABLE_IRQ))
|
if (!(regs->flags & PT_FLAGS_DISABLE_IRQ))
|
||||||
@ -277,7 +275,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
|
|||||||
const char *name;
|
const char *name;
|
||||||
char buf[100];
|
char buf[100];
|
||||||
if (fixup_exception(regs)) /* ILL_TRANS or UNALIGN_DATA */
|
if (fixup_exception(regs)) /* ILL_TRANS or UNALIGN_DATA */
|
||||||
goto done;
|
return;
|
||||||
if (fault_num >= 0 &&
|
if (fault_num >= 0 &&
|
||||||
fault_num < ARRAY_SIZE(int_name) &&
|
fault_num < ARRAY_SIZE(int_name) &&
|
||||||
int_name[fault_num] != NULL)
|
int_name[fault_num] != NULL)
|
||||||
@ -319,7 +317,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
|
|||||||
case INT_GPV:
|
case INT_GPV:
|
||||||
#if CHIP_HAS_TILE_DMA()
|
#if CHIP_HAS_TILE_DMA()
|
||||||
if (retry_gpv(reason))
|
if (retry_gpv(reason))
|
||||||
goto done;
|
return;
|
||||||
#endif
|
#endif
|
||||||
/*FALLTHROUGH*/
|
/*FALLTHROUGH*/
|
||||||
case INT_UDN_ACCESS:
|
case INT_UDN_ACCESS:
|
||||||
@ -346,7 +344,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
|
|||||||
if (!state ||
|
if (!state ||
|
||||||
(void __user *)(regs->pc) != state->buffer) {
|
(void __user *)(regs->pc) != state->buffer) {
|
||||||
single_step_once(regs);
|
single_step_once(regs);
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -390,9 +388,6 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
|
|||||||
if (signo != SIGTRAP)
|
if (signo != SIGTRAP)
|
||||||
trace_unhandled_signal("trap", regs, address, signo);
|
trace_unhandled_signal("trap", regs, address, signo);
|
||||||
force_sig_info(signo, &info, current);
|
force_sig_info(signo, &info, current);
|
||||||
|
|
||||||
done:
|
|
||||||
exception_exit(prev_state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_nmi(struct pt_regs *regs, int fault_num, unsigned long reason)
|
void do_nmi(struct pt_regs *regs, int fault_num, unsigned long reason)
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/compat.h>
|
#include <linux/compat.h>
|
||||||
#include <linux/prctl.h>
|
#include <linux/prctl.h>
|
||||||
#include <linux/context_tracking.h>
|
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/traps.h>
|
#include <asm/traps.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
@ -1449,7 +1448,6 @@ void jit_bundle_gen(struct pt_regs *regs, tilegx_bundle_bits bundle,
|
|||||||
|
|
||||||
void do_unaligned(struct pt_regs *regs, int vecnum)
|
void do_unaligned(struct pt_regs *regs, int vecnum)
|
||||||
{
|
{
|
||||||
enum ctx_state prev_state = exception_enter();
|
|
||||||
tilegx_bundle_bits __user *pc;
|
tilegx_bundle_bits __user *pc;
|
||||||
tilegx_bundle_bits bundle;
|
tilegx_bundle_bits bundle;
|
||||||
struct thread_info *info = current_thread_info();
|
struct thread_info *info = current_thread_info();
|
||||||
@ -1503,7 +1501,7 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
|
|||||||
*((tilegx_bundle_bits *)(regs->pc)));
|
*((tilegx_bundle_bits *)(regs->pc)));
|
||||||
jit_bundle_gen(regs, bundle, align_ctl);
|
jit_bundle_gen(regs, bundle, align_ctl);
|
||||||
}
|
}
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1527,7 +1525,7 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
|
|||||||
|
|
||||||
trace_unhandled_signal("unaligned fixup trap", regs, 0, SIGBUS);
|
trace_unhandled_signal("unaligned fixup trap", regs, 0, SIGBUS);
|
||||||
force_sig_info(info.si_signo, &info, current);
|
force_sig_info(info.si_signo, &info, current);
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1544,7 +1542,7 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
|
|||||||
trace_unhandled_signal("segfault in unalign fixup", regs,
|
trace_unhandled_signal("segfault in unalign fixup", regs,
|
||||||
(unsigned long)info.si_addr, SIGSEGV);
|
(unsigned long)info.si_addr, SIGSEGV);
|
||||||
force_sig_info(info.si_signo, &info, current);
|
force_sig_info(info.si_signo, &info, current);
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!info->unalign_jit_base) {
|
if (!info->unalign_jit_base) {
|
||||||
@ -1579,7 +1577,7 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
|
|||||||
|
|
||||||
if (IS_ERR((void __force *)user_page)) {
|
if (IS_ERR((void __force *)user_page)) {
|
||||||
pr_err("Out of kernel pages trying do_mmap\n");
|
pr_err("Out of kernel pages trying do_mmap\n");
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the address in the thread_info struct */
|
/* Save the address in the thread_info struct */
|
||||||
@ -1592,9 +1590,6 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
|
|||||||
|
|
||||||
/* Generate unalign JIT */
|
/* Generate unalign JIT */
|
||||||
jit_bundle_gen(regs, GX_INSN_BSWAP(bundle), align_ctl);
|
jit_bundle_gen(regs, GX_INSN_BSWAP(bundle), align_ctl);
|
||||||
|
|
||||||
done:
|
|
||||||
exception_exit(prev_state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __tilegx__ */
|
#endif /* __tilegx__ */
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
#include <linux/syscalls.h>
|
#include <linux/syscalls.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/kdebug.h>
|
#include <linux/kdebug.h>
|
||||||
#include <linux/context_tracking.h>
|
|
||||||
|
|
||||||
#include <asm/pgalloc.h>
|
#include <asm/pgalloc.h>
|
||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
@ -845,9 +844,7 @@ static inline void __do_page_fault(struct pt_regs *regs, int fault_num,
|
|||||||
void do_page_fault(struct pt_regs *regs, int fault_num,
|
void do_page_fault(struct pt_regs *regs, int fault_num,
|
||||||
unsigned long address, unsigned long write)
|
unsigned long address, unsigned long write)
|
||||||
{
|
{
|
||||||
enum ctx_state prev_state = exception_enter();
|
|
||||||
__do_page_fault(regs, fault_num, address, write);
|
__do_page_fault(regs, fault_num, address, write);
|
||||||
exception_exit(prev_state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CHIP_HAS_TILE_DMA()
|
#if CHIP_HAS_TILE_DMA()
|
||||||
|
Loading…
Reference in New Issue
Block a user