Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 49e4e156 authored by Chris Metcalf's avatar Chris Metcalf
Browse files

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: default avatarChris Metcalf <cmetcalf@ezchip.com>
Acked-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
parent b340c656
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ config TILE
	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
	select HAVE_DEBUG_STACKOVERFLOW
	select ARCH_WANT_FRAME_POINTERS
	select HAVE_CONTEXT_TRACKING

# FIXME: investigate whether we need/want these options.
#	select HAVE_IOREMAP_PROT
+6 −3
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@ extern void _cpu_idle(void);
#define TIF_NOTIFY_RESUME	8	/* callback before returning to user */
#define TIF_SYSCALL_TRACEPOINT	9	/* syscall tracepoint instrumentation */
#define TIF_POLLING_NRFLAG	10	/* idle is polling for TIF_NEED_RESCHED */
#define TIF_NOHZ		11	/* in adaptive nohz mode */

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

/* Work to do on any return to user space. */
#define _TIF_ALLWORK_MASK \
	(_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_SINGLESTEP | \
   _TIF_ASYNC_TLB|_TIF_NOTIFY_RESUME)
	 _TIF_ASYNC_TLB | _TIF_NOTIFY_RESUME | _TIF_NOHZ)

/* Work to do at syscall entry. */
#define _TIF_SYSCALL_ENTRY_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT)
#define _TIF_SYSCALL_ENTRY_WORK \
	(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_NOHZ)

/* Work to do at syscall exit. */
#define _TIF_SYSCALL_EXIT_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT)
+8 −4
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/kernel.h>
#include <linux/tracehook.h>
#include <linux/signal.h>
#include <linux/context_tracking.h>
#include <asm/stack.h>
#include <asm/switch_to.h>
#include <asm/homecache.h>
@@ -474,6 +475,8 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags)
	if (!user_mode(regs))
		return 0;

	user_exit();

	/* Enable interrupts; they are disabled again on return to caller. */
	local_irq_enable();

@@ -496,12 +499,13 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags)
		tracehook_notify_resume(regs);
		return 1;
	}
	if (thread_info_flags & _TIF_SINGLESTEP) {
	if (thread_info_flags & _TIF_SINGLESTEP)
		single_step_once(regs);

	user_enter();

	return 0;
}
	panic("work_pending: bad flags %#x\n", thread_info_flags);
}

unsigned long get_wchan(struct task_struct *p)
{
+20 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <linux/regset.h>
#include <linux/elf.h>
#include <linux/tracehook.h>
#include <linux/context_tracking.h>
#include <asm/traps.h>
#include <arch/chip.h>

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

int do_syscall_trace_enter(struct pt_regs *regs)
{
	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
	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 (work & _TIF_SYSCALL_TRACE) {
		if (tracehook_report_syscall_entry(regs))
			regs->regs[TREG_SYSCALL_NR] = -1;
	}

	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
	if (work & _TIF_SYSCALL_TRACEPOINT)
		trace_sys_enter(regs, regs->regs[TREG_SYSCALL_NR]);

	return regs->regs[TREG_SYSCALL_NR];
@@ -267,6 +277,12 @@ void do_syscall_trace_exit(struct pt_regs *regs)
{
	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
	 * 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)
/* Handle synthetic interrupt delivered only by the simulator. */
void __kprobes do_breakpoint(struct pt_regs* regs, int fault_num)
{
	enum ctx_state prev_state = exception_enter();
	send_sigtrap(current, regs);
	exception_exit(prev_state);
}
+3 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <linux/types.h>
#include <linux/err.h>
#include <linux/prctl.h>
#include <linux/context_tracking.h>
#include <asm/cacheflush.h>
#include <asm/traps.h>
#include <asm/uaccess.h>
@@ -738,6 +739,7 @@ static DEFINE_PER_CPU(unsigned long, ss_saved_pc);

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);
	struct thread_info *info = (void *)current_thread_info();
	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)
		__insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control);
		send_sigtrap(current, regs);
	}
	exception_exit(prev_state);
}


Loading