From: Chris Metcalf <cmetcalf@xxxxxxxxxxxx> This commit adds task isolation hooks as follows: - __handle_domain_irq() generates an isolation warning for the local task - irq_work_queue_on() generates an isolation warning for the remote task being interrupted for irq_work - generic_exec_single() generates a remote isolation warning for the remote cpu being IPI'd - smp_call_function_many() generates a remote isolation warning for the set of remote cpus being IPI'd Calls to task_isolation_remote() or task_isolation_interrupt() can be placed in the platform-independent code like this when doing so results in fewer lines of code changes, as for example is true of the users of the arch_send_call_function_*() APIs. Or, they can be placed in the per-architecture code when there are many callers, as for example is true of the smp_send_reschedule() call. A further cleanup might be to create an intermediate layer, so that for example smp_send_reschedule() is a single generic function that just calls arch_smp_send_reschedule(), allowing generic code to be called every time smp_send_reschedule() is invoked. But for now, we just update either callers or callees as makes most sense. Signed-off-by: Alex Belits <abelits@xxxxxxxxxxx> --- kernel/irq/irqdesc.c | 9 +++++++++ kernel/irq_work.c | 5 ++++- kernel/smp.c | 6 +++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 98a5f10d1900..e2b81d035fa1 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -16,6 +16,7 @@ #include <linux/bitmap.h> #include <linux/irqdomain.h> #include <linux/sysfs.h> +#include <linux/isolation.h> #include "internals.h" @@ -670,6 +671,10 @@ int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq, irq = irq_find_mapping(domain, hwirq); #endif + task_isolation_interrupt((irq == hwirq) ? + "irq %d (%s)" : "irq %d (%s hwirq %d)", + irq, domain ? domain->name : "", hwirq); + /* * Some hardware gives randomly wrong interrupts. Rather * than crashing, do something sensible. @@ -711,6 +716,10 @@ int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq, irq = irq_find_mapping(domain, hwirq); + task_isolation_interrupt((irq == hwirq) ? + "NMI irq %d (%s)" : "NMI irq %d (%s hwirq %d)", + irq, domain ? domain->name : "", hwirq); + /* * ack_bad_irq is not NMI-safe, just report * an invalid interrupt. diff --git a/kernel/irq_work.c b/kernel/irq_work.c index 828cc30774bc..8fd4ece43dd8 100644 --- a/kernel/irq_work.c +++ b/kernel/irq_work.c @@ -18,6 +18,7 @@ #include <linux/cpu.h> #include <linux/notifier.h> #include <linux/smp.h> +#include <linux/isolation.h> #include <asm/processor.h> @@ -102,8 +103,10 @@ bool irq_work_queue_on(struct irq_work *work, int cpu) if (cpu != smp_processor_id()) { /* Arch remote IPI send/receive backend aren't NMI safe */ WARN_ON_ONCE(in_nmi()); - if (llist_add(&work->llnode, &per_cpu(raised_list, cpu))) + if (llist_add(&work->llnode, &per_cpu(raised_list, cpu))) { + task_isolation_remote(cpu, "irq_work"); arch_send_call_function_single_ipi(cpu); + } } else { __irq_work_queue_local(work); } diff --git a/kernel/smp.c b/kernel/smp.c index d0ada39eb4d4..3a8bcbdd4ce6 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -20,6 +20,7 @@ #include <linux/sched.h> #include <linux/sched/idle.h> #include <linux/hypervisor.h> +#include <linux/isolation.h> #include "smpboot.h" @@ -176,8 +177,10 @@ static int generic_exec_single(int cpu, call_single_data_t *csd, * locking and barrier primitives. Generic code isn't really * equipped to do the right thing... */ - if (llist_add(&csd->llist, &per_cpu(call_single_queue, cpu))) + if (llist_add(&csd->llist, &per_cpu(call_single_queue, cpu))) { + task_isolation_remote(cpu, "IPI function"); arch_send_call_function_single_ipi(cpu); + } return 0; } @@ -466,6 +469,7 @@ static void smp_call_function_many_cond(const struct cpumask *mask, } /* Send a message to all CPUs in the map */ + task_isolation_remote_cpumask(cfd->cpumask_ipi, "IPI function"); arch_send_call_function_ipi_mask(cfd->cpumask_ipi); if (wait) { -- 2.20.1