Skip to content

Commit 49e4e15

Browse files
author
Chris Metcalf
committed
tile: support CONTEXT_TRACKING and thus NOHZ_FULL
Add the TIF_NOHZ flag appropriately. Add call to user_exit() on entry to do_work_pending() and on entry to syscalls via do_syscall_trace_enter(), and also the top of do_syscall_trace_exit() just because it's done in x86. Add call to user_enter() at the bottom of do_work_pending() once we have no more work to do before returning to userspace. Wrap all the trap code in exception_enter() / exception_exit(). Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com> Acked-by: Frederic Weisbecker <fweisbec@gmail.com>
1 parent b340c65 commit 49e4e15

File tree

8 files changed

+67
-28
lines changed

8 files changed

+67
-28
lines changed

arch/tile/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ config TILE
2727
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
2828
select HAVE_DEBUG_STACKOVERFLOW
2929
select ARCH_WANT_FRAME_POINTERS
30+
select HAVE_CONTEXT_TRACKING
3031

3132
# FIXME: investigate whether we need/want these options.
3233
# select HAVE_IOREMAP_PROT

arch/tile/include/asm/thread_info.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ extern void _cpu_idle(void);
126126
#define TIF_NOTIFY_RESUME 8 /* callback before returning to user */
127127
#define TIF_SYSCALL_TRACEPOINT 9 /* syscall tracepoint instrumentation */
128128
#define TIF_POLLING_NRFLAG 10 /* idle is polling for TIF_NEED_RESCHED */
129+
#define TIF_NOHZ 11 /* in adaptive nohz mode */
129130

130131
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
131132
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
@@ -138,14 +139,16 @@ extern void _cpu_idle(void);
138139
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
139140
#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
140141
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
142+
#define _TIF_NOHZ (1<<TIF_NOHZ)
141143

142144
/* Work to do on any return to user space. */
143145
#define _TIF_ALLWORK_MASK \
144-
(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SINGLESTEP|\
145-
_TIF_ASYNC_TLB|_TIF_NOTIFY_RESUME)
146+
(_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_SINGLESTEP | \
147+
_TIF_ASYNC_TLB | _TIF_NOTIFY_RESUME | _TIF_NOHZ)
146148

147149
/* Work to do at syscall entry. */
148-
#define _TIF_SYSCALL_ENTRY_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT)
150+
#define _TIF_SYSCALL_ENTRY_WORK \
151+
(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_NOHZ)
149152

150153
/* Work to do at syscall exit. */
151154
#define _TIF_SYSCALL_EXIT_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT)

arch/tile/kernel/process.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <linux/kernel.h>
2828
#include <linux/tracehook.h>
2929
#include <linux/signal.h>
30+
#include <linux/context_tracking.h>
3031
#include <asm/stack.h>
3132
#include <asm/switch_to.h>
3233
#include <asm/homecache.h>
@@ -474,6 +475,8 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags)
474475
if (!user_mode(regs))
475476
return 0;
476477

478+
user_exit();
479+
477480
/* Enable interrupts; they are disabled again on return to caller. */
478481
local_irq_enable();
479482

@@ -496,11 +499,12 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags)
496499
tracehook_notify_resume(regs);
497500
return 1;
498501
}
499-
if (thread_info_flags & _TIF_SINGLESTEP) {
502+
if (thread_info_flags & _TIF_SINGLESTEP)
500503
single_step_once(regs);
501-
return 0;
502-
}
503-
panic("work_pending: bad flags %#x\n", thread_info_flags);
504+
505+
user_enter();
506+
507+
return 0;
504508
}
505509

506510
unsigned long get_wchan(struct task_struct *p)

arch/tile/kernel/ptrace.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/regset.h>
2323
#include <linux/elf.h>
2424
#include <linux/tracehook.h>
25+
#include <linux/context_tracking.h>
2526
#include <asm/traps.h>
2627
#include <arch/chip.h>
2728

@@ -252,12 +253,21 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
252253

253254
int do_syscall_trace_enter(struct pt_regs *regs)
254255
{
255-
if (test_thread_flag(TIF_SYSCALL_TRACE)) {
256+
u32 work = ACCESS_ONCE(current_thread_info()->flags);
257+
258+
/*
259+
* If TIF_NOHZ is set, we are required to call user_exit() before
260+
* doing anything that could touch RCU.
261+
*/
262+
if (work & _TIF_NOHZ)
263+
user_exit();
264+
265+
if (work & _TIF_SYSCALL_TRACE) {
256266
if (tracehook_report_syscall_entry(regs))
257267
regs->regs[TREG_SYSCALL_NR] = -1;
258268
}
259269

260-
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
270+
if (work & _TIF_SYSCALL_TRACEPOINT)
261271
trace_sys_enter(regs, regs->regs[TREG_SYSCALL_NR]);
262272

263273
return regs->regs[TREG_SYSCALL_NR];
@@ -267,6 +277,12 @@ void do_syscall_trace_exit(struct pt_regs *regs)
267277
{
268278
long errno;
269279

280+
/*
281+
* We may come here right after calling schedule_user()
282+
* in which case we can be in RCU user mode.
283+
*/
284+
user_exit();
285+
270286
/*
271287
* The standard tile calling convention returns the value (or negative
272288
* errno) in r0, and zero (or positive errno) in r1.
@@ -303,5 +319,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs)
303319
/* Handle synthetic interrupt delivered only by the simulator. */
304320
void __kprobes do_breakpoint(struct pt_regs* regs, int fault_num)
305321
{
322+
enum ctx_state prev_state = exception_enter();
306323
send_sigtrap(current, regs);
324+
exception_exit(prev_state);
307325
}

arch/tile/kernel/single_step.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <linux/types.h>
2424
#include <linux/err.h>
2525
#include <linux/prctl.h>
26+
#include <linux/context_tracking.h>
2627
#include <asm/cacheflush.h>
2728
#include <asm/traps.h>
2829
#include <asm/uaccess.h>
@@ -738,6 +739,7 @@ static DEFINE_PER_CPU(unsigned long, ss_saved_pc);
738739

739740
void gx_singlestep_handle(struct pt_regs *regs, int fault_num)
740741
{
742+
enum ctx_state prev_state = exception_enter();
741743
unsigned long *ss_pc = this_cpu_ptr(&ss_saved_pc);
742744
struct thread_info *info = (void *)current_thread_info();
743745
int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP);
@@ -754,6 +756,7 @@ void gx_singlestep_handle(struct pt_regs *regs, int fault_num)
754756
__insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control);
755757
send_sigtrap(current, regs);
756758
}
759+
exception_exit(prev_state);
757760
}
758761

759762

arch/tile/kernel/traps.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/reboot.h>
2121
#include <linux/uaccess.h>
2222
#include <linux/ptrace.h>
23+
#include <linux/context_tracking.h>
2324
#include <asm/stack.h>
2425
#include <asm/traps.h>
2526
#include <asm/setup.h>
@@ -253,6 +254,7 @@ static int do_bpt(struct pt_regs *regs)
253254
void __kprobes do_trap(struct pt_regs *regs, int fault_num,
254255
unsigned long reason)
255256
{
257+
enum ctx_state prev_state = exception_enter();
256258
siginfo_t info = { 0 };
257259
int signo, code;
258260
unsigned long address = 0;
@@ -261,7 +263,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
261263

262264
/* Handle breakpoints, etc. */
263265
if (is_kernel && fault_num == INT_ILL && do_bpt(regs))
264-
return;
266+
goto done;
265267

266268
/* Re-enable interrupts, if they were previously enabled. */
267269
if (!(regs->flags & PT_FLAGS_DISABLE_IRQ))
@@ -275,7 +277,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
275277
const char *name;
276278
char buf[100];
277279
if (fixup_exception(regs)) /* ILL_TRANS or UNALIGN_DATA */
278-
return;
280+
goto done;
279281
if (fault_num >= 0 &&
280282
fault_num < ARRAY_SIZE(int_name) &&
281283
int_name[fault_num] != NULL)
@@ -294,7 +296,6 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
294296
fault_num, name, regs->pc, buf);
295297
show_regs(regs);
296298
do_exit(SIGKILL); /* FIXME: implement i386 die() */
297-
return;
298299
}
299300

300301
switch (fault_num) {
@@ -308,7 +309,6 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
308309
pr_err("Unreadable instruction for INT_ILL: %#lx\n",
309310
regs->pc);
310311
do_exit(SIGKILL);
311-
return;
312312
}
313313
if (!special_ill(instr, &signo, &code)) {
314314
signo = SIGILL;
@@ -319,7 +319,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
319319
case INT_GPV:
320320
#if CHIP_HAS_TILE_DMA()
321321
if (retry_gpv(reason))
322-
return;
322+
goto done;
323323
#endif
324324
/*FALLTHROUGH*/
325325
case INT_UDN_ACCESS:
@@ -346,7 +346,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
346346
if (!state ||
347347
(void __user *)(regs->pc) != state->buffer) {
348348
single_step_once(regs);
349-
return;
349+
goto done;
350350
}
351351
}
352352
#endif
@@ -380,7 +380,6 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
380380
#endif
381381
default:
382382
panic("Unexpected do_trap interrupt number %d", fault_num);
383-
return;
384383
}
385384

386385
info.si_signo = signo;
@@ -391,6 +390,9 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
391390
if (signo != SIGTRAP)
392391
trace_unhandled_signal("trap", regs, address, signo);
393392
force_sig_info(signo, &info, current);
393+
394+
done:
395+
exception_exit(prev_state);
394396
}
395397

396398
void kernel_double_fault(int dummy, ulong pc, ulong lr, ulong sp, ulong r52)

arch/tile/kernel/unaligned.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/module.h>
2626
#include <linux/compat.h>
2727
#include <linux/prctl.h>
28+
#include <linux/context_tracking.h>
2829
#include <asm/cacheflush.h>
2930
#include <asm/traps.h>
3031
#include <asm/uaccess.h>
@@ -1448,6 +1449,7 @@ void jit_bundle_gen(struct pt_regs *regs, tilegx_bundle_bits bundle,
14481449

14491450
void do_unaligned(struct pt_regs *regs, int vecnum)
14501451
{
1452+
enum ctx_state prev_state = exception_enter();
14511453
tilegx_bundle_bits __user *pc;
14521454
tilegx_bundle_bits bundle;
14531455
struct thread_info *info = current_thread_info();
@@ -1487,12 +1489,11 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
14871489
(int)unaligned_fixup,
14881490
(unsigned long long)regs->ex1,
14891491
(unsigned long long)regs->pc);
1490-
return;
1492+
} else {
1493+
/* Not fixable. Go panic. */
1494+
panic("Unalign exception in Kernel. pc=%lx",
1495+
regs->pc);
14911496
}
1492-
/* Not fixable. Go panic. */
1493-
panic("Unalign exception in Kernel. pc=%lx",
1494-
regs->pc);
1495-
return;
14961497
} else {
14971498
/*
14981499
* Try to fix the exception. If we can't, panic the
@@ -1501,8 +1502,8 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
15011502
bundle = GX_INSN_BSWAP(
15021503
*((tilegx_bundle_bits *)(regs->pc)));
15031504
jit_bundle_gen(regs, bundle, align_ctl);
1504-
return;
15051505
}
1506+
goto done;
15061507
}
15071508

15081509
/*
@@ -1526,7 +1527,7 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
15261527

15271528
trace_unhandled_signal("unaligned fixup trap", regs, 0, SIGBUS);
15281529
force_sig_info(info.si_signo, &info, current);
1529-
return;
1530+
goto done;
15301531
}
15311532

15321533

@@ -1543,7 +1544,7 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
15431544
trace_unhandled_signal("segfault in unalign fixup", regs,
15441545
(unsigned long)info.si_addr, SIGSEGV);
15451546
force_sig_info(info.si_signo, &info, current);
1546-
return;
1547+
goto done;
15471548
}
15481549

15491550
if (!info->unalign_jit_base) {
@@ -1578,7 +1579,7 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
15781579

15791580
if (IS_ERR((void __force *)user_page)) {
15801581
pr_err("Out of kernel pages trying do_mmap\n");
1581-
return;
1582+
goto done;
15821583
}
15831584

15841585
/* Save the address in the thread_info struct */
@@ -1591,6 +1592,9 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
15911592

15921593
/* Generate unalign JIT */
15931594
jit_bundle_gen(regs, GX_INSN_BSWAP(bundle), align_ctl);
1595+
1596+
done:
1597+
exception_exit(prev_state);
15941598
}
15951599

15961600
#endif /* __tilegx__ */

arch/tile/mm/fault.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <linux/syscalls.h>
3636
#include <linux/uaccess.h>
3737
#include <linux/kdebug.h>
38+
#include <linux/context_tracking.h>
3839

3940
#include <asm/pgalloc.h>
4041
#include <asm/sections.h>
@@ -702,6 +703,7 @@ void do_page_fault(struct pt_regs *regs, int fault_num,
702703
unsigned long address, unsigned long write)
703704
{
704705
int is_page_fault;
706+
enum ctx_state prev_state = exception_enter();
705707

706708
#ifdef CONFIG_KPROBES
707709
/*
@@ -711,7 +713,7 @@ void do_page_fault(struct pt_regs *regs, int fault_num,
711713
*/
712714
if (notify_die(DIE_PAGE_FAULT, "page fault", regs, -1,
713715
regs->faultnum, SIGSEGV) == NOTIFY_STOP)
714-
return;
716+
goto done;
715717
#endif
716718

717719
#ifdef __tilegx__
@@ -750,7 +752,6 @@ void do_page_fault(struct pt_regs *regs, int fault_num,
750752
current->comm, current->pid, pc, address);
751753
show_regs(regs);
752754
do_group_exit(SIGKILL);
753-
return;
754755
}
755756
}
756757
#else
@@ -834,12 +835,15 @@ void do_page_fault(struct pt_regs *regs, int fault_num,
834835
async->is_fault = is_page_fault;
835836
async->is_write = write;
836837
async->address = address;
837-
return;
838+
goto done;
838839
}
839840
}
840841
#endif
841842

842843
handle_page_fault(regs, fault_num, is_page_fault, address, write);
844+
845+
done:
846+
exception_exit(prev_state);
843847
}
844848

845849

0 commit comments

Comments
 (0)