arch/riscv: Add IPI support
Use CLINT to send interrupts to another CPU. SMP support is kinda incomplete without it. This patch only enables it for riscv-privilege platforms - specifically, "virt" one. Signed-off-by: Ederson de Souza <ederson.desouza@intel.com>
This commit is contained in:
parent
b0458201cc
commit
2aab236c12
3 changed files with 59 additions and 0 deletions
|
@ -109,6 +109,7 @@ config RISCV
|
||||||
select ARCH_HAS_THREAD_LOCAL_STORAGE
|
select ARCH_HAS_THREAD_LOCAL_STORAGE
|
||||||
select USE_SWITCH
|
select USE_SWITCH
|
||||||
select USE_SWITCH_SUPPORTED
|
select USE_SWITCH_SUPPORTED
|
||||||
|
select SCHED_IPI_SUPPORTED if SMP
|
||||||
imply XIP
|
imply XIP
|
||||||
help
|
help
|
||||||
RISCV architecture
|
RISCV architecture
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <init.h>
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
|
#include <ksched.h>
|
||||||
|
|
||||||
volatile struct {
|
volatile struct {
|
||||||
arch_cpustart_t fn;
|
arch_cpustart_t fn;
|
||||||
|
@ -35,6 +37,61 @@ void z_riscv_secondary_cpu_init(int cpu_num)
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_PMP_STACK_GUARD
|
#ifdef CONFIG_PMP_STACK_GUARD
|
||||||
z_riscv_configure_interrupt_stack_guard();
|
z_riscv_configure_interrupt_stack_guard();
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
irq_enable(RISCV_MACHINE_SOFT_IRQ);
|
||||||
#endif
|
#endif
|
||||||
riscv_cpu_init[cpu_num].fn(riscv_cpu_init[cpu_num].arg);
|
riscv_cpu_init[cpu_num].fn(riscv_cpu_init[cpu_num].arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
static uintptr_t *get_hart_msip(int hart_id)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_64BIT
|
||||||
|
return (uintptr_t *)(uint64_t)(RISCV_MSIP_BASE + (hart_id * 4));
|
||||||
|
#else
|
||||||
|
return (uintptr_t *)(RISCV_MSIP_BASE + (hart_id * 4));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void arch_sched_ipi(void)
|
||||||
|
{
|
||||||
|
unsigned int key;
|
||||||
|
uint32_t i;
|
||||||
|
uint8_t id;
|
||||||
|
|
||||||
|
key = arch_irq_lock();
|
||||||
|
|
||||||
|
id = _current_cpu->id;
|
||||||
|
for (i = 0U; i < CONFIG_MP_NUM_CPUS; i++) {
|
||||||
|
if (i != id) {
|
||||||
|
volatile uint32_t *r = (uint32_t *)get_hart_msip(i);
|
||||||
|
*r = 1U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arch_irq_unlock(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sched_ipi_handler(const void *unused)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(unused);
|
||||||
|
|
||||||
|
volatile uint32_t *r = (uint32_t *)get_hart_msip(_current_cpu->id);
|
||||||
|
*r = 0U;
|
||||||
|
|
||||||
|
z_sched_ipi();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int riscv_smp_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
|
||||||
|
IRQ_CONNECT(RISCV_MACHINE_SOFT_IRQ, 0, sched_ipi_handler, NULL, 0);
|
||||||
|
irq_enable(RISCV_MACHINE_SOFT_IRQ);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_INIT(riscv_smp_init, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||||
|
#endif /* CONFIG_SMP */
|
||||||
|
|
|
@ -12,5 +12,6 @@
|
||||||
#define SIFIVE_SYSCON_TEST 0x00100000
|
#define SIFIVE_SYSCON_TEST 0x00100000
|
||||||
#define RISCV_MTIME_BASE 0x0200BFF8
|
#define RISCV_MTIME_BASE 0x0200BFF8
|
||||||
#define RISCV_MTIMECMP_BASE 0x02004000
|
#define RISCV_MTIMECMP_BASE 0x02004000
|
||||||
|
#define RISCV_MSIP_BASE 0x02000000
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue