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.
This commit is contained in:
Ville Juven 2022-04-06 15:09:05 +03:00 committed by Xiang Xiao
parent 3a26cf6a02
commit d38b4965f8
6 changed files with 72 additions and 40 deletions

View File

@ -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)

View File

@ -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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;

View File

@ -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.