From 2f529f9b558ca1c1bd74be7437a84e4711743404 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 01 Nov 2024 02:11:33 +0000 Subject: [PATCH] add xenomai --- kernel/arch/arm64/kernel/smp.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 95 insertions(+), 12 deletions(-) diff --git a/kernel/arch/arm64/kernel/smp.c b/kernel/arch/arm64/kernel/smp.c index 581defe..ba10c60 100644 --- a/kernel/arch/arm64/kernel/smp.c +++ b/kernel/arch/arm64/kernel/smp.c @@ -86,7 +86,7 @@ NR_IPI }; -static int ipi_irq_base __read_mostly; +int ipi_irq_base __read_mostly; static int nr_ipi __read_mostly = NR_IPI; static struct irq_desc *ipi_desc[NR_IPI] __read_mostly; @@ -273,6 +273,7 @@ complete(&cpu_running); local_daif_restore(DAIF_PROCCTX); + local_irq_enable_full(); /* * OK, it's off to the idle thread for us @@ -811,6 +812,8 @@ static void smp_cross_call(const struct cpumask *target, unsigned int ipinr); +static unsigned int get_ipi_count(unsigned int irq, unsigned int cpu); + unsigned long irq_err_count; int arch_show_interrupts(struct seq_file *p, int prec) @@ -822,7 +825,7 @@ seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i, prec >= 4 ? " " : ""); for_each_online_cpu(cpu) - seq_printf(p, "%10u ", kstat_irqs_cpu(irq, cpu)); + seq_printf(p, "%10u ", get_ipi_count(irq, cpu)); seq_printf(p, " %s\n", ipi_types[i]); } @@ -888,7 +891,7 @@ atomic_dec(&waiting_for_crash_ipi); - local_irq_disable(); + local_irq_disable_full(); sdei_mask_local_cpu(); if (IS_ENABLED(CONFIG_HOTPLUG_CPU)) @@ -900,7 +903,7 @@ } /* - * Main handler for inter-processor interrupts + * Main handler for inter-processor interrupts on the in-band stage. */ static void do_handle_IPI(int ipinr) { @@ -963,6 +966,73 @@ trace_ipi_exit_rcuidle(ipi_types[ipinr]); } +static void __smp_cross_call(const struct cpumask *target, unsigned int ipinr) +{ + trace_ipi_raise(target, ipi_types[ipinr]); + __ipi_send_mask(ipi_desc[ipinr], target); +} + +#ifdef CONFIG_IRQ_PIPELINE + +static DEFINE_PER_CPU(unsigned long, ipi_messages); + +static DEFINE_PER_CPU(unsigned int [NR_IPI], ipi_counts); + +static irqreturn_t ipi_handler(int irq, void *data) +{ + unsigned long *pmsg; + unsigned int ipinr; + + /* + * Decode in-band IPIs (0..NR_IPI - 1) multiplexed over + * SGI0. Out-of-band IPIs (SGI1, SGI2) have their own + * individual handler. + */ + pmsg = raw_cpu_ptr(&ipi_messages); + while (*pmsg) { + ipinr = ffs(*pmsg) - 1; + clear_bit(ipinr, pmsg); + __this_cpu_inc(ipi_counts[ipinr]); + do_handle_IPI(ipinr); + } + + return IRQ_HANDLED; +} + +static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) +{ + unsigned int cpu; + + /* regular in-band IPI (multiplexed over SGI0). */ + for_each_cpu(cpu, target) + set_bit(ipinr, &per_cpu(ipi_messages, cpu)); + + wmb(); + __smp_cross_call(target, 0); +} + +static unsigned int get_ipi_count(unsigned int irq, unsigned int cpu) +{ + return per_cpu(ipi_counts[irq - ipi_irq_base], cpu); +} + +void irq_send_oob_ipi(unsigned int irq, + const struct cpumask *cpumask) +{ + unsigned int sgi = irq - ipi_irq_base; + + if (WARN_ON(irq_pipeline_debug() && + (sgi < OOB_IPI_OFFSET || + sgi >= OOB_IPI_OFFSET + OOB_NR_IPI))) + return; + + /* Out-of-band IPI (SGI1-2). */ + __smp_cross_call(cpumask, sgi); +} +EXPORT_SYMBOL_GPL(irq_send_oob_ipi); + +#else + static irqreturn_t ipi_handler(int irq, void *data) { do_handle_IPI(irq - ipi_irq_base); @@ -971,9 +1041,15 @@ static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) { - trace_ipi_raise(target, ipi_types[ipinr]); - __ipi_send_mask(ipi_desc[ipinr], target); + __smp_cross_call(target, ipinr); } + +static unsigned int get_ipi_count(unsigned int irq, unsigned int cpu) +{ + return kstat_irqs_cpu(irq, cpu); +} + +#endif /* CONFIG_IRQ_PIPELINE */ static void ipi_setup(int cpu) { @@ -1001,18 +1077,25 @@ void __init set_smp_ipi_range(int ipi_base, int n) { - int i; + int i, inband_nr_ipi; WARN_ON(n < NR_IPI); nr_ipi = min(n, NR_IPI); + /* + * irq_pipeline: the in-band stage traps SGI0 only, + * over which IPI messages are mutiplexed. Other SGIs + * are available for exchanging out-of-band IPIs. + */ + inband_nr_ipi = irqs_pipelined() ? 1 : nr_ipi; for (i = 0; i < nr_ipi; i++) { - int err; + if (i < inband_nr_ipi) { + int err; - err = request_percpu_irq(ipi_base + i, ipi_handler, - "IPI", &cpu_number); - WARN_ON(err); - + err = request_percpu_irq(ipi_base + i, ipi_handler, + "IPI", &cpu_number); + WARN_ON(err); + } ipi_desc[i] = irq_to_desc(ipi_base + i); irq_set_status_flags(ipi_base + i, IRQ_HIDDEN); -- Gitblit v1.6.2