From d38b4965f809a95b07f899d996ca3487f713f351 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 6 Apr 2022 15:09:05 +0300 Subject: [PATCH] MPFS: Prepare support for S-mode - Access to PLIC via S-mode registers - Access to IRQs via S-mode registers / definitions - Initialize S-mode registers upon boot - Initialize per CPU area before nx_start NOTE: S-mode requires a companion SW (SBI) which is not yet implemented, thus S-mode is not usable as is, yet. --- arch/risc-v/src/mpfs/hardware/mpfs_plic.h | 4 ++- arch/risc-v/src/mpfs/mpfs_head.S | 20 ++++++------ arch/risc-v/src/mpfs/mpfs_irq.c | 39 +++++++++++------------ arch/risc-v/src/mpfs/mpfs_irq_dispatch.c | 14 ++++---- arch/risc-v/src/mpfs/mpfs_plic.c | 20 ++++++++++-- arch/risc-v/src/mpfs/mpfs_start.c | 15 +++++++++ 6 files changed, 72 insertions(+), 40 deletions(-) diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_plic.h b/arch/risc-v/src/mpfs/hardware/mpfs_plic.h index 11513b7161..67223d14b4 100755 --- a/arch/risc-v/src/mpfs/hardware/mpfs_plic.h +++ b/arch/risc-v/src/mpfs/hardware/mpfs_plic.h @@ -102,7 +102,9 @@ #define MPFS_PLIC_MTHRESHOLD_OFFSET (0x0000) #define MPFS_PLIC_MCLAIM_OFFSET (0x0004) #define MPFS_PLIC_STHRESHOLD_OFFSET (0x1000) -#define MPFS_PLIC_SCLAIM_OFFSET (0x1004) +#define MPFS_PLIC_SCLAIM_OFFSET (0x1004) /* From hart base */ +#define MPFS_PLIC_CLAIM_S_OFFSET (0x1000) /* From mclaim to sclaim */ +#define MPFS_PLIC_THRESHOLD_S_OFFSET (0x1000) /* From mthresh to sthresh */ #define MPFS_PLIC_H0_MTHRESHOLD (MPFS_PLIC_BASE + 0x200000) #define MPFS_PLIC_H0_MCLAIM (MPFS_PLIC_BASE + 0x200004) diff --git a/arch/risc-v/src/mpfs/mpfs_head.S b/arch/risc-v/src/mpfs/mpfs_head.S index e375dce060..30c94f513e 100755 --- a/arch/risc-v/src/mpfs/mpfs_head.S +++ b/arch/risc-v/src/mpfs/mpfs_head.S @@ -100,6 +100,17 @@ __start: csrr a0, mhartid beqz a0, .skip_e51 + /* Clear sscratch if u54 */ + + csrw sscratch, zero + csrw scause, zero + csrw sepc, zero + + /* Disable all interrupts in sie */ + + csrw sie, zero + csrw sip, zero + /* Init delegation registers, mideleg, medeleg, if a U54 * These are not initialised by the hardware and come up in a random state */ @@ -116,15 +127,6 @@ __start: sfence.vma x0, x0 - /* Enable accelerator if present, setting ignored on E51 - * 15,16 = MSTATUS_XS, 17,18 = MSTATUS_MPRV - * not defined on riscv-v/include/csr.h - */ - - /* li t0, (1 << 15) | (1 << 16) | (1 << 17) | (1 << 18) */ - li t0, 0x00018000 /* MSTATUS_XS */ - csrs mstatus, t0 - .skip_e51: /* initialize global pointer, global data diff --git a/arch/risc-v/src/mpfs/mpfs_irq.c b/arch/risc-v/src/mpfs/mpfs_irq.c index 3657f4f901..ce9ff8f919 100755 --- a/arch/risc-v/src/mpfs/mpfs_irq.c +++ b/arch/risc-v/src/mpfs/mpfs_irq.c @@ -56,10 +56,6 @@ void up_irqinitialize(void) up_irq_save(); - /* Disable timer interrupt (in case of hotloading with debugger) */ - - up_disable_irq(RISCV_IRQ_MTIMER); - /* Disable all global interrupts for current hart */ uintptr_t iebase = mpfs_plic_get_iebase(); @@ -104,7 +100,9 @@ void up_irqinitialize(void) /* Attach the ecall interrupt handler */ +#ifndef CONFIG_ARCH_USE_S_MODE irq_attach(RISCV_IRQ_ECALLM, riscv_swint, NULL); +#endif #ifndef CONFIG_BUILD_FLAT irq_attach(RISCV_IRQ_ECALLU, riscv_swint, NULL); @@ -130,17 +128,17 @@ void up_disable_irq(int irq) { int extirq = 0; - if (irq == RISCV_IRQ_MSOFT) + if (irq == RISCV_IRQ_SOFT) { - /* Read mstatus & clear machine software interrupt enable in mie */ + /* Read m/sstatus & clear machine software interrupt enable in m/sie */ - CLEAR_CSR(mie, MIE_MSIE); + CLEAR_CSR(CSR_IE, IE_SIE); } - else if (irq == RISCV_IRQ_MTIMER) + else if (irq == RISCV_IRQ_TIMER) { - /* Read mstatus & clear machine timer interrupt enable in mie */ + /* Read m/sstatus & clear timer interrupt enable in m/sie */ - CLEAR_CSR(mie, MIE_MTIE); + CLEAR_CSR(CSR_IE, IE_TIE); } else if (irq >= MPFS_IRQ_EXT_START) { @@ -173,17 +171,17 @@ void up_enable_irq(int irq) { int extirq; - if (irq == RISCV_IRQ_MSOFT) + if (irq == RISCV_IRQ_SOFT) { - /* Read mstatus & set machine software interrupt enable in mie */ + /* Read m/sstatus & set machine software interrupt enable in m/sie */ - SET_CSR(mie, MIE_MSIE); + SET_CSR(CSR_IE, IE_SIE); } - else if (irq == RISCV_IRQ_MTIMER) + else if (irq == RISCV_IRQ_TIMER) { - /* Read mstatus & set machine timer interrupt enable in mie */ + /* Read m/sstatus & set timer interrupt enable in m/sie */ - SET_CSR(mie, MIE_MTIE); + SET_CSR(CSR_IE, IE_TIE); } else if (irq >= MPFS_IRQ_EXT_START) { @@ -228,12 +226,13 @@ irqstate_t up_irq_enable(void) { irqstate_t oldstat; - /* Enable MEIE (machine external interrupt enable) */ + /* Enable external interrupts (mie/sie) */ - SET_CSR(mie, MIE_MEIE); + SET_CSR(CSR_IE, IE_EIE); - /* Read mstatus & set machine interrupt enable (MIE) in mstatus */ + /* Read and enable global interrupts (M/SIE) in m/sstatus */ + + oldstat = READ_AND_SET_CSR(CSR_STATUS, STATUS_IE); - oldstat = READ_AND_SET_CSR(mstatus, MSTATUS_MIE); return oldstat; } diff --git a/arch/risc-v/src/mpfs/mpfs_irq_dispatch.c b/arch/risc-v/src/mpfs/mpfs_irq_dispatch.c index 168446df0e..51e3537a9d 100755 --- a/arch/risc-v/src/mpfs/mpfs_irq_dispatch.c +++ b/arch/risc-v/src/mpfs/mpfs_irq_dispatch.c @@ -49,7 +49,7 @@ void *riscv_dispatch_irq(uintptr_t vector, uintptr_t *regs) { int irq = (vector & 0x3f); - uintptr_t *mepc = regs; + uintptr_t *epc = regs; /* Check if fault happened */ @@ -71,29 +71,29 @@ void *riscv_dispatch_irq(uintptr_t vector, uintptr_t *regs) uintptr_t claim_address = mpfs_plic_get_claimbase(); - if (irq == RISCV_IRQ_MEXT) + if (irq == RISCV_IRQ_EXT) { uint32_t ext = getreg32(claim_address); - /* Add the value to nuttx irq which is offset to the mext */ + /* Add the value to nuttx irq which is offset to the ext */ irq = MPFS_IRQ_EXT_START + ext; } - /* NOTE: In case of ecall, we need to adjust mepc in the context */ + /* NOTE: In case of ecall, we need to adjust epc in the context */ if (irq == RISCV_IRQ_ECALLM || irq == RISCV_IRQ_ECALLU) { - *mepc += 4; + *epc += 4; } /* Acknowledge the interrupt */ riscv_ack_irq(irq); - /* MEXT means no interrupt */ + /* EXT means no interrupt */ - if (irq != RISCV_IRQ_MEXT && irq != MPFS_IRQ_INVALID) + if (irq != RISCV_IRQ_EXT && irq != MPFS_IRQ_INVALID) { /* Deliver the IRQ */ diff --git a/arch/risc-v/src/mpfs/mpfs_plic.c b/arch/risc-v/src/mpfs/mpfs_plic.c index 98277ae05b..3de194c2e1 100644 --- a/arch/risc-v/src/mpfs/mpfs_plic.c +++ b/arch/risc-v/src/mpfs/mpfs_plic.c @@ -39,6 +39,18 @@ * Pre-processor Definitions ****************************************************************************/ +/* Offset to privilege mode, note that hart0 does not have S-mode */ + +#ifdef CONFIG_ARCH_USE_S_MODE +# define MPFS_PLIC_IEPRIV_OFFSET (MPFS_HART_SIE_OFFSET) +# define MPFS_PLIC_CLAIMPRIV_OFFSET (MPFS_PLIC_CLAIM_S_OFFSET) +# define MPFS_PLIC_THRESHOLDPRIV_OFFSET (MPFS_PLIC_THRESHOLD_S_OFFSET) +#else +# define MPFS_PLIC_IEPRIV_OFFSET (0) +# define MPFS_PLIC_CLAIMPRIV_OFFSET (0) +# define MPFS_PLIC_THRESHOLDPRIV_OFFSET (0) +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -65,7 +77,8 @@ uintptr_t mpfs_plic_get_iebase(void) } else { - iebase = MPFS_PLIC_H1_MIE0 + (hart_id - 1) * MPFS_HART_MIE_OFFSET; + iebase = MPFS_PLIC_H1_MIE0 + MPFS_PLIC_IEPRIV_OFFSET + + (hart_id - 1) * MPFS_HART_MIE_OFFSET; } return iebase; @@ -93,7 +106,7 @@ uintptr_t mpfs_plic_get_claimbase(void) } else { - claim_address = MPFS_PLIC_H1_MCLAIM + + claim_address = MPFS_PLIC_H1_MCLAIM + MPFS_PLIC_CLAIMPRIV_OFFSET + (hart_id - 1) * MPFS_PLIC_NEXTHART_OFFSET; } @@ -123,7 +136,8 @@ uintptr_t mpfs_plic_get_thresholdbase(void) else { threshold_address = MPFS_PLIC_H1_MTHRESHOLD + - (hart_id - 1) * MPFS_PLIC_NEXTHART_OFFSET; + MPFS_PLIC_THRESHOLDPRIV_OFFSET + + (hart_id - 1) * MPFS_PLIC_NEXTHART_OFFSET; } return threshold_address; diff --git a/arch/risc-v/src/mpfs/mpfs_start.c b/arch/risc-v/src/mpfs/mpfs_start.c index ea4e004dd2..8c318218d9 100755 --- a/arch/risc-v/src/mpfs/mpfs_start.c +++ b/arch/risc-v/src/mpfs/mpfs_start.c @@ -34,7 +34,9 @@ #include "mpfs_ddr.h" #include "mpfs_cache.h" #include "mpfs_userspace.h" + #include "riscv_internal.h" +#include "riscv_percpu.h" /**************************************************************************** * Pre-processor Definitions @@ -46,6 +48,10 @@ # define showprogress(c) #endif +#if defined (CONFIG_BUILD_KERNEL) && !defined (CONFIG_ARCH_USE_S_MODE) +# error "Target requires kernel in S-mode, enable CONFIG_ARCH_USE_S_MODE" +#endif + /**************************************************************************** * Public Data ****************************************************************************/ @@ -169,6 +175,15 @@ void __mpfs_start(uint64_t mhartid) mpfs_boardinitialize(); +#ifdef CONFIG_ARCH_USE_S_MODE + /* Initialize the per CPU areas */ + + if (mhartid != 0) + { + riscv_percpu_add_hart(mhartid); + } +#endif /* CONFIG_ARCH_USE_S_MODE */ + /* Initialize the caches. Should only be executed from E51 (hart 0) to be * functional. Consider the caches already configured if running without * the CONFIG_MPFS_BOOTLOADER -option.