From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756329AbdKCRF6 (ORCPT ); Fri, 3 Nov 2017 13:05:58 -0400 Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:56538 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932450AbdKCRFT (ORCPT ); Fri, 3 Nov 2017 13:05:19 -0400 From: Chris Metcalf To: Steven Rostedt , Ingo Molnar , Peter Zijlstra , Andrew Morton , Rik van Riel , Tejun Heo , Frederic Weisbecker , Thomas Gleixner , "Paul E. McKenney" , Christoph Lameter , Viresh Kumar , Catalin Marinas , Will Deacon , Andy Lutomirski , linux-kernel@vger.kernel.org Cc: Chris Metcalf Subject: [PATCH v16 11/13] arch/tile: enable task isolation functionality Date: Fri, 3 Nov 2017 13:04:50 -0400 Message-Id: <1509728692-10460-12-git-send-email-cmetcalf@mellanox.com> X-Mailer: git-send-email 2.1.2 In-Reply-To: <1509728692-10460-1-git-send-email-cmetcalf@mellanox.com> References: <1509728692-10460-1-git-send-email-cmetcalf@mellanox.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org We add the necessary call to task_isolation_start() 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_interrupt() in places where exceptions may not generate signals to the application. Signed-off-by: Chris Metcalf --- arch/tile/Kconfig | 1 + arch/tile/include/asm/thread_info.h | 2 ++ arch/tile/kernel/hardwall.c | 2 ++ arch/tile/kernel/irq.c | 3 +++ arch/tile/kernel/messaging.c | 4 ++++ arch/tile/kernel/process.c | 4 ++++ arch/tile/kernel/ptrace.c | 10 ++++++++++ arch/tile/kernel/single_step.c | 7 +++++++ arch/tile/kernel/smp.c | 21 +++++++++++---------- arch/tile/kernel/time.c | 2 ++ arch/tile/kernel/unaligned.c | 4 ++++ arch/tile/mm/fault.c | 13 ++++++++++++- arch/tile/mm/homecache.c | 11 +++++++++++ 13 files changed, 73 insertions(+), 11 deletions(-) diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index 4583c0320059..2d644138f2eb 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig @@ -16,6 +16,7 @@ config TILE select GENERIC_STRNCPY_FROM_USER select GENERIC_STRNLEN_USER select HAVE_ARCH_SECCOMP_FILTER + select HAVE_ARCH_TASK_ISOLATION select HAVE_ARCH_TRACEHOOK select HAVE_CONTEXT_TRACKING select HAVE_DEBUG_BUGVERBOSE diff --git a/arch/tile/include/asm/thread_info.h b/arch/tile/include/asm/thread_info.h index b7659b8f1117..3e298bd43d11 100644 --- a/arch/tile/include/asm/thread_info.h +++ b/arch/tile/include/asm/thread_info.h @@ -126,6 +126,7 @@ extern void _cpu_idle(void); #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_TASK_ISOLATION 12 /* in task isolation mode */ #define _TIF_SIGPENDING (1< #include #include +#include #include #include #include @@ -328,6 +329,7 @@ void __kprobes do_hardwall_trap(struct pt_regs* regs, int fault_num) int found_processes; struct pt_regs *old_regs = set_irq_regs(regs); + task_isolation_interrupt("hardwall trap"); irq_enter(); /* Figure out which network trapped. */ diff --git a/arch/tile/kernel/irq.c b/arch/tile/kernel/irq.c index 22044fc691ef..0b1b24b9c496 100644 --- a/arch/tile/kernel/irq.c +++ b/arch/tile/kernel/irq.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -100,6 +101,8 @@ void tile_dev_intr(struct pt_regs *regs, int intnum) /* Track time spent here in an interrupt context. */ old_regs = set_irq_regs(regs); + + task_isolation_interrupt("IPI: IRQ mask %#lx", remaining_irqs); irq_enter(); #ifdef CONFIG_DEBUG_STACKOVERFLOW diff --git a/arch/tile/kernel/messaging.c b/arch/tile/kernel/messaging.c index 7475af3aacec..1cf1630215f0 100644 --- a/arch/tile/kernel/messaging.c +++ b/arch/tile/kernel/messaging.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -86,6 +87,7 @@ void hv_message_intr(struct pt_regs *regs, int intnum) tag = message[0]; #ifdef CONFIG_SMP + task_isolation_interrupt("SMP message %d", tag); evaluate_message(message[0]); #else panic("Received IPI message %d in UP mode", tag); @@ -94,6 +96,8 @@ void hv_message_intr(struct pt_regs *regs, int intnum) HV_IntrMsg *him = (HV_IntrMsg *)message; struct hv_driver_cb *cb = (struct hv_driver_cb *)him->intarg; + task_isolation_interrupt("interrupt message %#lx(%#lx)", + him->intarg, him->intdata); cb->callback(cb, him->intdata); __this_cpu_inc(irq_stat.irq_hv_msg_count); } diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index f0a0e18e4dfb..ac22e971dc1d 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -516,6 +517,9 @@ void prepare_exit_to_usermode(struct pt_regs *regs, u32 thread_info_flags) #endif } + if (thread_info_flags & _TIF_TASK_ISOLATION) + task_isolation_start(); + user_enter(); } diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c index e1a078e6828e..908d57d3d2cf 100644 --- a/arch/tile/kernel/ptrace.c +++ b/arch/tile/kernel/ptrace.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -263,6 +264,15 @@ int do_syscall_trace_enter(struct pt_regs *regs) return -1; } + /* + * In task isolation mode, we may prevent the syscall from + * running, and if so we also deliver a signal to the process. + */ + if (work & _TIF_TASK_ISOLATION) { + if (task_isolation_syscall(regs->regs[TREG_SYSCALL_NR]) == -1) + return -1; + } + if (secure_computing(NULL) == -1) return -1; diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c index de3eae813e52..4d5d4897e70c 100644 --- a/arch/tile/kernel/single_step.c +++ b/arch/tile/kernel/single_step.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -320,6 +321,9 @@ void single_step_once(struct pt_regs *regs) int size = 0, sign_ext = 0; /* happy compiler */ int align_ctl; + /* No signal was generated, but notify task-isolation tasks. */ + task_isolation_interrupt("single step at %#lx", regs->pc); + align_ctl = unaligned_fixup; switch (task_thread_info(current)->align_ctl) { case PR_UNALIGN_NOPRINT: @@ -767,6 +771,9 @@ 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); + /* No signal was generated, but notify task-isolation tasks. */ + task_isolation_interrupt("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/smp.c b/arch/tile/kernel/smp.c index 94a62e1197ce..6b100faa33ef 100644 --- a/arch/tile/kernel/smp.c +++ b/arch/tile/kernel/smp.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -258,10 +259,8 @@ void __init ipi_init(void) #if CHIP_HAS_IPI() -void smp_send_reschedule(int cpu) +static void __smp_send_reschedule(int cpu) { - WARN_ON(cpu_is_offline(cpu)); - /* * We just want to do an MMIO store. The traditional writeq() * functions aren't really correct here, since they're always @@ -273,15 +272,17 @@ void smp_send_reschedule(int cpu) #else -void smp_send_reschedule(int cpu) +static void __smp_send_reschedule(int cpu) { - HV_Coord coord; - - WARN_ON(cpu_is_offline(cpu)); - - coord.y = cpu_y(cpu); - coord.x = cpu_x(cpu); + HV_Coord coord = { .y = cpu_y(cpu), .x = cpu_x(cpu) }; hv_trigger_ipi(coord, IRQ_RESCHEDULE); } #endif /* CHIP_HAS_IPI() */ + +void smp_send_reschedule(int cpu) +{ + WARN_ON(cpu_is_offline(cpu)); + task_isolation_remote(cpu, "reschedule IPI"); + __smp_send_reschedule(cpu); +} diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c index 6643ffbc0615..f74f10d827fa 100644 --- a/arch/tile/kernel/time.c +++ b/arch/tile/kernel/time.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -196,6 +197,7 @@ void do_timer_interrupt(struct pt_regs *regs, int fault_num) arch_local_irq_mask(INT_TILE_TIMER); /* Track time spent here in an interrupt context */ + task_isolation_interrupt("timer"); irq_enter(); /* Track interrupt count. */ diff --git a/arch/tile/kernel/unaligned.c b/arch/tile/kernel/unaligned.c index 8149c38f67b6..ee14a61d0eee 100644 --- a/arch/tile/kernel/unaligned.c +++ b/arch/tile/kernel/unaligned.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1547,6 +1548,9 @@ void do_unaligned(struct pt_regs *regs, int vecnum) return; } + /* No signal was generated, but notify task-isolation tasks. */ + task_isolation_interrupt("unaligned access 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 f58fa06a2214..0a7a731d7413 100644 --- a/arch/tile/mm/fault.c +++ b/arch/tile/mm/fault.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -311,8 +312,13 @@ static int handle_page_fault(struct pt_regs *regs, */ pgd = get_current_pgd(); if (handle_migrating_pte(pgd, fault_num, address, regs->pc, - is_kernel_mode, write)) + is_kernel_mode, write)) { + /* No signal was generated, but notify task-isolation tasks. */ + if (!is_kernel_mode) + task_isolation_interrupt("migration fault at %#lx", + address); return 1; + } si_code = SEGV_MAPERR; @@ -482,6 +488,11 @@ static int handle_page_fault(struct pt_regs *regs, #endif up_read(&mm->mmap_sem); + + /* No signal was generated, but notify task-isolation tasks. */ + if (flags & FAULT_FLAG_USER) + task_isolation_interrupt("page fault at %#lx", address); + return 1; /* diff --git a/arch/tile/mm/homecache.c b/arch/tile/mm/homecache.c index b51cc28acd0a..82bcffb26ec4 100644 --- a/arch/tile/mm/homecache.c +++ b/arch/tile/mm/homecache.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -85,6 +86,16 @@ static void hv_flush_update(const struct cpumask *cache_cpumask, */ for_each_cpu(cpu, &mask) ++per_cpu(irq_stat, cpu).irq_hv_flush_count; + + /* + * Send an extra Linux-level interrupt here to task isolation tasks + * so that they can generate the appropriate signal to kill + * themselves. If we didn't send a Linux interrupt, we would + * interrupt the task into the hypervisor but it wouldn't get a + * signal to advise it of the loss of the cpu. + */ + task_isolation_remote_cpumask_interrupt(&mask, + "remote cache/TLB flush"); } /* -- 2.1.2