riscv: smp: prepare for more than one IPI type

Right now this is hardcoded to z_sched_ipi(). Make it so that other IPI
services can be added in the future.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
Nicolas Pitre 2023-01-18 17:26:22 -05:00 committed by Carles Cufí
commit 4f9b547ebd

View file

@ -8,6 +8,7 @@
#include <zephyr/kernel.h> #include <zephyr/kernel.h>
#include <ksched.h> #include <ksched.h>
#include <zephyr/irq.h> #include <zephyr/irq.h>
#include <zephyr/sys/atomic.h>
volatile struct { volatile struct {
arch_cpustart_t fn; arch_cpustart_t fn;
@ -54,47 +55,46 @@ void z_riscv_secondary_cpu_init(int cpu_num)
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
static uint32_t *get_hart_msip(int hart_id)
{ #define MSIP(hartid) ((volatile uint32_t *)RISCV_MSIP_BASE)[hartid]
return (uint32_t *)(unsigned long)(RISCV_MSIP_BASE + (hart_id * 4));
} static atomic_val_t cpu_pending_ipi[CONFIG_MP_MAX_NUM_CPUS];
#define IPI_SCHED BIT(0)
void arch_sched_ipi(void) void arch_sched_ipi(void)
{ {
unsigned int key; unsigned int key = arch_irq_lock();
uint32_t i; unsigned int id = _current_cpu->id;
uint8_t id;
key = arch_irq_lock();
id = _current_cpu->id;
unsigned int num_cpus = arch_num_cpus(); unsigned int num_cpus = arch_num_cpus();
for (i = 0U; i < num_cpus; i++) { for (unsigned int i = 0; i < num_cpus; i++) {
if (i != id && _kernel.cpus[i].arch.online) { if (i != id && _kernel.cpus[i].arch.online) {
volatile uint32_t *r = get_hart_msip(_kernel.cpus[i].arch.hartid); atomic_or(&cpu_pending_ipi[i], IPI_SCHED);
*r = 1U; MSIP(_kernel.cpus[i].arch.hartid) = 1;
} }
} }
arch_irq_unlock(key); arch_irq_unlock(key);
} }
static void sched_ipi_handler(const void *unused) static void ipi_handler(const void *unused)
{ {
ARG_UNUSED(unused); ARG_UNUSED(unused);
volatile uint32_t *r = get_hart_msip(csr_read(mhartid)); MSIP(csr_read(mhartid)) = 0;
*r = 0U;
z_sched_ipi(); atomic_val_t pending_ipi = atomic_get(&cpu_pending_ipi[_current_cpu->id]);
if (pending_ipi & IPI_SCHED) {
z_sched_ipi();
}
} }
static int riscv_smp_init(const struct device *dev) static int riscv_smp_init(const struct device *dev)
{ {
ARG_UNUSED(dev); ARG_UNUSED(dev);
IRQ_CONNECT(RISCV_MACHINE_SOFT_IRQ, 0, sched_ipi_handler, NULL, 0); IRQ_CONNECT(RISCV_MACHINE_SOFT_IRQ, 0, ipi_handler, NULL, 0);
irq_enable(RISCV_MACHINE_SOFT_IRQ); irq_enable(RISCV_MACHINE_SOFT_IRQ);
return 0; return 0;