From 4ef5584d11e8f6ddb2ed66707337aa5d49b67e54 Mon Sep 17 00:00:00 2001 From: Jacek Maksymowicz Date: Mon, 8 Apr 2024 16:24:50 +0200 Subject: [PATCH] zynq7000: adjust interrupts for SMP Allow interrupts to run on any core Schedule timer interrupt in a round-robin fashion across both cores Adjust timer to keep the current scheduling period on both cores JIRA: RTOS-796 --- hal/armv7a/zynq7000/interrupts.c | 8 +++++--- hal/armv7a/zynq7000/timer.c | 17 ++++++++++++----- hal/armv7a/zynq7000/zynq.h | 3 +++ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/hal/armv7a/zynq7000/interrupts.c b/hal/armv7a/zynq7000/interrupts.c index 5eb21ba12..e602e7c65 100644 --- a/hal/armv7a/zynq7000/interrupts.c +++ b/hal/armv7a/zynq7000/interrupts.c @@ -31,6 +31,8 @@ #define SGI_FLT_OTHER_CPUS 1 /* Send SGI to all CPUs except the one that called this function */ #define SGI_FLT_THIS_CPU 2 /* Send SGI to the CPU that called this function */ +#define DEFAULT_CPU_MASK 0x3 + /* clang-format off */ enum { @@ -133,7 +135,7 @@ static void interrupts_setConf(unsigned int irqn, u32 conf) } -static void interrupts_setCPU(unsigned int irqn, u32 cpuID) +void _zynq_interrupts_setCPU(unsigned int irqn, u32 cpuID) { u32 mask; @@ -167,7 +169,7 @@ int hal_interruptsSetHandler(intr_handler_t *h) HAL_LIST_ADD(&interrupts_common.handlers[h->n], h); interrupts_setPriority(h->n, 0xa); - interrupts_setCPU(h->n, 0x1); + _zynq_interrupts_setCPU(h->n, DEFAULT_CPU_MASK); interrupts_enableIRQ(h->n); hal_spinlockClear(&interrupts_common.spinlock[h->n], &sc); @@ -228,7 +230,7 @@ void _hal_interruptsInit(void) /* Set required configuration and CPU_0 as a default processor */ for (i = SPI_FIRST_IRQID; i < SIZE_INTERRUPTS; ++i) { interrupts_setConf(i, spiConf[i - SPI_FIRST_IRQID]); - interrupts_setCPU(i, 0x1); + _zynq_interrupts_setCPU(i, DEFAULT_CPU_MASK); } /* SGI and PPI interrupts are fixed to always be on both CPUs */ diff --git a/hal/armv7a/zynq7000/timer.c b/hal/armv7a/zynq7000/timer.c index eac264e6d..11a50a1b5 100644 --- a/hal/armv7a/zynq7000/timer.c +++ b/hal/armv7a/zynq7000/timer.c @@ -18,6 +18,8 @@ #include "hal/spinlock.h" #include "hal/string.h" +#include "zynq.h" + #define TIMER_SRC_CLK_CPU_1x 111111115 /* Hz */ #define TIMER_IRQ_ID 42 @@ -47,13 +49,18 @@ static int _timer_irqHandler(unsigned int n, cpu_context_t *ctx, void *arg) (void)arg; (void)ctx; - u32 st = *(timer_common.ttc + isr); - + spinlock_ctx_t sc; + hal_spinlockSet(&timer_common.sp, &sc); /* Interval IRQ */ - if (st & 0x1) { + if ((*(timer_common.ttc + isr) & 1) != 0) { timer_common.jiffies += timer_common.ticksPerFreq; } + hal_spinlockClear(&timer_common.sp, &sc); + + u32 nextID = hal_cpuGetID() + 1; + u32 nextTargetCPU = (nextID == hal_cpuGetCount()) ? 1 : (1 << nextID); + _zynq_interrupts_setCPU(n, nextTargetCPU); hal_cpuDataSyncBarrier(); return 0; @@ -62,7 +69,7 @@ static int _timer_irqHandler(unsigned int n, cpu_context_t *ctx, void *arg) static time_t hal_timerCyc2Us(time_t cyc) { - return (cyc * 1000LL) / (time_t)(timer_common.ticksPerFreq); + return (cyc * 1000LL) / (time_t)(timer_common.ticksPerFreq * hal_cpuGetCount()); } @@ -167,7 +174,7 @@ void _hal_timerInit(u32 interval) /* Reset counters and restart counting */ *(timer_common.ttc + cnt_ctrl) = 0x10; - hal_timerSetPrescaler(interval); + hal_timerSetPrescaler(interval * hal_cpuGetCount()); hal_spinlockCreate(&timer_common.sp, "timer"); timer_common.handler.f = _timer_irqHandler; diff --git a/hal/armv7a/zynq7000/zynq.h b/hal/armv7a/zynq7000/zynq.h index 9b8528d91..80a31e989 100644 --- a/hal/armv7a/zynq7000/zynq.h +++ b/hal/armv7a/zynq7000/zynq.h @@ -25,4 +25,7 @@ extern int _zynq_setMIO(unsigned int pin, char disableRcvr, char pullup, char io extern int _zynq_setAmbaClk(u32 dev, u32 state); +extern void _zynq_interrupts_setCPU(unsigned int irqn, u32 cpuID); + + #endif