[PATCH v8 14/14] arch/tile: enable task isolation functionality

Chris Metcalf
2015-10-20T20:38:28Z

We add the necessary call to task_isolation_enter() in the
prepare_exit_to_usermode() routine. We already unconditionally
call into this routine if TIF_NOHZ is set, since that's where
we do the user_enter() call.

We add calls to task_isolation_check_exception() in places
where exceptions may not generate signals to the application.

In addition, we add an overriding task_isolation_wait() call
that runs a nap instruction while waiting for an interrupt, to
make the task_isolation_enter() loop run in a lower-power state.

Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com>
---
arch/tile/kernel/process.c | 6 +++++-
arch/tile/kernel/ptrace.c | 6 +++++-
arch/tile/kernel/single_step.c | 5 +++++
arch/tile/kernel/unaligned.c | 3 +++
arch/tile/mm/fault.c | 3 +++
arch/tile/mm/homecache.c | 5 ++++-
6 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c
index b5f30d376ce1..832febfd65df 100644
--- a/arch/tile/kernel/process.c
+++ b/arch/tile/kernel/process.c
@@ -29,6 +29,7 @@
#include <linux/signal.h>
#include <linux/delay.h>
#include <linux/context_tracking.h>
+#include <linux/isolation.h>
#include <asm/stack.h>
#include <asm/switch_to.h>
#include <asm/homecache.h>
@@ -495,10 +496,13 @@ void prepare_exit_to_usermode(struct pt_regs *regs, u32 thread_info_flags)
tracehook_notify_resume(regs);
}

+ task_isolation_enter();
+
local_irq_disable();
thread_info_flags = READ_ONCE(current_thread_info()->flags);

- } while (thread_info_flags & _TIF_WORK_MASK);
+ } while ((thread_info_flags & _TIF_WORK_MASK) ||
+ !task_isolation_ready());

if (thread_info_flags & _TIF_SINGLESTEP) {
single_step_once(regs);
diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c
index bdc126faf741..63acf7b4655f 100644
--- a/arch/tile/kernel/ptrace.c
+++ b/arch/tile/kernel/ptrace.c
@@ -23,6 +23,7 @@
#include <linux/elf.h>
#include <linux/tracehook.h>
#include <linux/context_tracking.h>
+#include <linux/isolation.h>
#include <asm/traps.h>
#include <arch/chip.h>

@@ -259,8 +260,11 @@ int do_syscall_trace_enter(struct pt_regs *regs)
* If TIF_NOHZ is set, we are required to call user_exit() before
* doing anything that could touch RCU.
*/
- if (work & _TIF_NOHZ)
+ if (work & _TIF_NOHZ) {
user_exit();
+ if (task_isolation_check_syscall(regs->regs[TREG_SYSCALL_NR]))
+ return -1;
+ }

if (secure_computing() == -1)
return -1;
diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c
index 53f7b9def07b..4cba9f4a1915 100644
--- a/arch/tile/kernel/single_step.c
+++ b/arch/tile/kernel/single_step.c
@@ -23,6 +23,7 @@
#include <linux/types.h>
#include <linux/err.h>
#include <linux/prctl.h>
+#include <linux/isolation.h>
#include <linux/context_tracking.h>
#include <asm/cacheflush.h>
#include <asm/traps.h>
@@ -321,6 +322,8 @@ void single_step_once(struct pt_regs *regs)
int size = 0, sign_ext = 0; /* happy compiler */
int align_ctl;

+ task_isolation_check_exception("single step at %#lx", regs->pc);
+
align_ctl = unaligned_fixup;
switch (task_thread_info(current)->align_ctl) {
case PR_UNALIGN_NOPRINT:
@@ -770,6 +773,8 @@ void single_step_once(struct pt_regs *regs)
unsigned long *ss_pc = this_cpu_ptr(&ss_saved_pc);
unsigned long control = __insn_mfspr(SPR_SINGLE_STEP_CONTROL_K);

+ task_isolation_check_exception("single step at %#lx", regs->pc);
+
*ss_pc = regs->pc;
control |= SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK;
control |= SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK;
diff --git a/arch/tile/kernel/unaligned.c b/arch/tile/kernel/unaligned.c
index d075f92ccee0..dbb9c1144236 100644
--- a/arch/tile/kernel/unaligned.c
+++ b/arch/tile/kernel/unaligned.c
@@ -26,6 +26,7 @@
#include <linux/compat.h>
#include <linux/prctl.h>
#include <linux/context_tracking.h>
+#include <linux/isolation.h>
#include <asm/cacheflush.h>
#include <asm/traps.h>
#include <asm/uaccess.h>
@@ -1547,6 +1548,8 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
goto done;
}

+ task_isolation_check_exception("unaligned JIT at %#lx", regs->pc);
+
if (!info->unalign_jit_base) {
void __user *user_page;

diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c
index 13eac59bf16a..53514ca54143 100644
--- a/arch/tile/mm/fault.c
+++ b/arch/tile/mm/fault.c
@@ -36,6 +36,7 @@
#include <linux/uaccess.h>
#include <linux/kdebug.h>
#include <linux/context_tracking.h>
+#include <linux/isolation.h>

#include <asm/pgalloc.h>
#include <asm/sections.h>
@@ -846,6 +847,8 @@ void do_page_fault(struct pt_regs *regs, int fault_num,
unsigned long address, unsigned long write)
{
enum ctx_state prev_state = exception_enter();
+ task_isolation_check_exception("page fault interrupt %d at %#lx (%#lx)",
+ fault_num, regs->pc, address);
__do_page_fault(regs, fault_num, address, write);
exception_exit(prev_state);
}
diff --git a/arch/tile/mm/homecache.c b/arch/tile/mm/homecache.c
index 40ca30a9fee3..a79325113105 100644
--- a/arch/tile/mm/homecache.c
+++ b/arch/tile/mm/homecache.c
@@ -31,6 +31,7 @@
#include <linux/smp.h>
#include <linux/module.h>
#include <linux/hugetlb.h>
+#include <linux/isolation.h>

#include <asm/page.h>
#include <asm/sections.h>
@@ -83,8 +84,10 @@ static void hv_flush_update(const struct cpumask *cache_cpumask,
* Don't bother to update atomically; losing a count
* here is not that critical.
*/
- for_each_cpu(cpu, &mask)
+ for_each_cpu(cpu, &mask) {
++per_cpu(irq_stat, cpu).irq_hv_flush_count;
+ task_isolation_debug(cpu);
+ }
}

/*
--
2.1.2