From 9fc7722f35f3105fb2560db754d316ec2d5aafe2 Mon Sep 17 00:00:00 2001 From: lukileczo Date: Tue, 2 Jan 2024 11:27:59 +0100 Subject: [PATCH 1/7] update .codespell_ignore JIRA: RTOS-550 --- .codespell_ignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.codespell_ignore b/.codespell_ignore index c9b36c2dc..37aa2c898 100644 --- a/.codespell_ignore +++ b/.codespell_ignore @@ -3,3 +3,5 @@ ptd mapp pmapp HSI +sie +hart From 9f82f127e3499398fcf9afbf7e2b6cba9d668403 Mon Sep 17 00:00:00 2001 From: lukileczo Date: Thu, 7 Sep 2023 14:19:36 +0200 Subject: [PATCH 2/7] riscv64: adapt to boot from PLO JIRA: RTOS-550 --- hal/riscv64/_init.S | 105 ++++++++++++++------------------------------ hal/riscv64/pmap.c | 4 +- 2 files changed, 36 insertions(+), 73 deletions(-) diff --git a/hal/riscv64/_init.S b/hal/riscv64/_init.S index 001c96069..9be742751 100644 --- a/hal/riscv64/_init.S +++ b/hal/riscv64/_init.S @@ -15,28 +15,21 @@ #define __ASSEMBLY__ - -#define SBI_SET_TIMER 0 -#define SBI_CONSOLE_PUTCHAR 1 -#define SBI_CONSOLE_GETCHAR 2 -#define SBI_CLEAR_IPI 3 -#define SBI_SEND_IPI 4 -#define SBI_REMOTE_FENCE_I 5 -#define SBI_REMOTE_SFENCE_VMA 6 -#define SBI_REMOTE_SFENCE_VMA_ASID 7 -#define SBI_SHUTDOWN 8 +#include +#include #define SR_FS 0x00006000 #define SR_SUM 0x00040000 #define SR_MER 0x00080000 -#include -#include +#define VADDR_SYSPAGE (_end + SIZE_PAGE - 1) .section .init, "x" -/* a1 - contains address of dtb (reserved for use in dtb_parse() ) */ +/* a0 - contains address of syspage + * a1 - contains address of dtb (reserved for use in dtb_parse()) + */ .globl _start .type _start, @function _start: @@ -63,51 +56,37 @@ _start: li t0, SR_SUM | SR_MER csrs sstatus, t0 - -/* Temporary solution: code allowing skipping phoenix-rtos-loader */ - la t0, _syspage_data - ld t0, 28(t0) /* points to syspage->progs address (circular list) */ - mv t1, t0 - beqz t1, dtb - - /* Copy application to _end + 4MB */ - la t4, _end + 4 * 1024 * 1024 - - li a2, SIZE_PAGE - 1 - not a3, a2 - -update_apps: - ld t2, 16(t1) /* prog->start */ - ld t3, 24(t1) /* prog->end */ - - /* Align destination address to SIZE_PAGE */ - add t4, t4, a2 - and t4, t4, a3 - - /* Set new start in prog->start */ - sd t4, 16(t1) - -copy_app: - ld t5, (t2) - addi t2, t2, 8 - sd t5, (t4) - addi t4, t4, 8 - bltu t2, t3, copy_app - - /* Set new end in prog->end */ - sd t4, 24(t1) - - ld t1, (t1) - bne t1, t0, update_apps -/* End of the the temporary code */ + la t0, hal_syspage /* t0 = &hal_syspage (phy) */ + li s1, VADDR_KERNEL + la s2, _start /* s2 = kernel start (phy) */ + la t1, VADDR_SYSPAGE + srli t1, t1, 12 + slli t1, t1, 12 + add t2, t1, s1 + sub t2, t2, s2 + /* store virt addr of syspage in hal_syspage */ + sd t2, (t0) + la t3, hal_relOffs + sub t4, t2, a0 /* t4 = offset between syspage VADDR and syspage PHYADDR */ + sd t4, (t3) + + /* calculate phy addr of syspage end */ + lw t2, 4(a0) /* t2 = syspage->size */ + add t2, t2, t1 + +syspage_cpy: + ld t3, (a0) + addi a0, a0, 8 + sd t3, (t1) + addi t1, t1, 8 + bltu t1, t2, syspage_cpy dtb: call dtb_parse call _pmap_preinit - li a1, VADDR_KERNEL - la a0, _start - sub a1, a1, a0 + /* s1 = VADDR_KERNEL, s2 = _start (phy) */ + sub a1, s1, s2 /* Point stvec to virtual address of intruction after satp write */ la a0, 1f @@ -120,15 +99,6 @@ dtb: add sp, sp, t0 add sp, sp, a1 - /* Initialize syspage pointer */ - la t0, _syspage_data - add t0, t0, a1 - la t1, hal_syspage - sd t0, (t1) - - la a0, hal_relOffs - sd a1, (a0) - la a0, pmap_common srl a0, a0, 12 li a1, 0x8000000000000000 @@ -143,9 +113,7 @@ dtb: la a0, .Lsecondary_park csrw stvec, a0 - call main - li a7, SBI_SHUTDOWN - ecall + j main .align 4 .Lsecondary_park: @@ -153,10 +121,3 @@ dtb: j .Lsecondary_park .size _start, .-_start - -.align 8 -.global _syspage_data -_syspage_data: - /* fill by syspagen */ -.org _syspage_data + 0x400, 0x0 -_syspage_data_end: diff --git a/hal/riscv64/pmap.c b/hal/riscv64/pmap.c index 6b78504ac..84761de6f 100644 --- a/hal/riscv64/pmap.c +++ b/hal/riscv64/pmap.c @@ -393,6 +393,7 @@ void _pmap_init(pmap_t *pmap, void **vstart, void **vend) /* Initialize kernel heap start address */ (*vstart) = (void *)((e + SIZE_PAGE - 1) & ~(SIZE_PAGE - 1)); + (*vstart) += SIZE_PAGE; /* Reserve space for syspage */ /* Initialize temporary page table (used for page table mapping) */ pmap_common.ptable = (*vstart); @@ -462,7 +463,8 @@ void _pmap_preinit(void) /* Get physical kernel address */ pmap_common.kernel = (addr_t)&_start; - pmap_common.kernelsz = (addr_t)&_end - (addr_t)&_start; + /* Add SIZE_PAGE to kernel size for syspage */ + pmap_common.kernelsz = (((addr_t)&_end + SIZE_PAGE - 1) & ~(SIZE_PAGE - 1)) - (addr_t)&_start + SIZE_PAGE; /* pmap_common.pdir2[(VADDR_KERNEL >> 30) % 512] = ((((u64)_start >> 30) << 28) | 0xcf); */ From 351a79113e2442ddc8db097e3d38cbdbf18a8afa Mon Sep 17 00:00:00 2001 From: lukileczo Date: Tue, 2 Jan 2024 15:55:08 +0100 Subject: [PATCH 3/7] riscv64: format code & apply MISRA JIRA: RTOS-550 --- hal/riscv64/arch/cpu.h | 19 ++++--- hal/riscv64/arch/pmap.h | 40 ++++++------- hal/riscv64/arch/spinlock.h | 1 + hal/riscv64/arch/types.h | 2 + hal/riscv64/console.c | 19 ++++--- hal/riscv64/cpu.c | 4 ++ hal/riscv64/dtb.c | 2 +- hal/riscv64/exceptions.c | 43 +++++++------- hal/riscv64/hal.c | 7 +-- hal/riscv64/pmap.c | 109 +++++++++++++++++------------------- hal/riscv64/riscv64.h | 52 ++++++++++------- hal/riscv64/sbi.h | 47 ++++++++-------- hal/riscv64/spinlock.c | 4 +- 13 files changed, 187 insertions(+), 162 deletions(-) diff --git a/hal/riscv64/arch/cpu.h b/hal/riscv64/arch/cpu.h index cfc9dd935..45836ca73 100644 --- a/hal/riscv64/arch/cpu.h +++ b/hal/riscv64/arch/cpu.h @@ -126,13 +126,13 @@ typedef struct { static inline void hal_cpuDisableInterrupts(void) { - __asm__ ("csrc sstatus, 2"); + __asm__ volatile("csrc sstatus, 2"); } static inline void hal_cpuEnableInterrupts(void) { - __asm__ ("csrs sstatus, 2"); + __asm__ volatile("csrs sstatus, 2"); } @@ -141,21 +141,21 @@ static inline void hal_cpuEnableInterrupts(void) static inline void hal_cpuHalt(void) { - __asm__ ("wfi"); + __asm__ volatile("wfi"); } static inline void hal_cpuSetDevBusy(int s) { + (void)s; } static inline void hal_cpuGetCycles(cycles_t *cb) { - __asm__ __volatile__ ( - "rdcycle %0" - : "=r" (*(cycles_t *)cb)); - return; + /* clang-format off */ + __asm__ volatile("rdcycle %0" : "=r"(*(cycles_t *)cb)); + /* clang-format on */ } @@ -164,11 +164,14 @@ static inline void hal_cpuGetCycles(cycles_t *cb) static inline void hal_cpuSetCtxGot(cpu_context_t *ctx, void *got) { + (void)ctx; + (void)got; } static inline void hal_cpuSetGot(void *got) { + (void)got; } @@ -204,7 +207,7 @@ static inline void *hal_cpuGetUserSP(cpu_context_t *ctx) static inline int hal_cpuSupervisorMode(cpu_context_t *ctx) { - return (ctx->sscratch == 0); + return (ctx->sscratch == 0) ? 1 : 0; } diff --git a/hal/riscv64/arch/pmap.h b/hal/riscv64/arch/pmap.h index 5db4ad7ff..05fe3f2f9 100644 --- a/hal/riscv64/arch/pmap.h +++ b/hal/riscv64/arch/pmap.h @@ -17,10 +17,10 @@ #define _HAL_RISCV64_PMAP_H_ /* Predefined virtual addresses */ -#define VADDR_KERNEL 0x0000003fc0000000L /* base virtual address of kernel space */ -#define VADDR_MIN 0x00000000 -#define VADDR_MAX 0xffffffffffffffffL -#define VADDR_USR_MAX VADDR_KERNEL +#define VADDR_KERNEL 0x0000003fc0000000L /* base virtual address of kernel space */ +#define VADDR_MIN 0x00000000 +#define VADDR_MAX 0xffffffffffffffffL +#define VADDR_USR_MAX VADDR_KERNEL /* Architecure dependent page attributes */ @@ -34,26 +34,26 @@ /* Architecure dependent page table attributes */ -#define PTHD_PRESENT 0x01 -#define PTHD_READ 0x02 -#define PTHD_WRITE 0x04 -#define PTHD_EXEC 0x08 -#define PTHD_USER 0x10 +#define PTHD_PRESENT 0x01 +#define PTHD_READ 0x02 +#define PTHD_WRITE 0x04 +#define PTHD_EXEC 0x08 +#define PTHD_USER 0x10 /* Page flags */ -#define PAGE_FREE 0x00000001 +#define PAGE_FREE 0x00000001 -#define PAGE_OWNER_BOOT (0 << 1) -#define PAGE_OWNER_KERNEL (1 << 1) -#define PAGE_OWNER_APP (2 << 1) +#define PAGE_OWNER_BOOT (0 << 1) +#define PAGE_OWNER_KERNEL (1 << 1) +#define PAGE_OWNER_APP (2 << 1) -#define PAGE_KERNEL_SYSPAGE (1 << 4) -#define PAGE_KERNEL_CPU (2 << 4) -#define PAGE_KERNEL_PTABLE (3 << 4) -#define PAGE_KERNEL_PMAP (4 << 4) -#define PAGE_KERNEL_STACK (5 << 4) -#define PAGE_KERNEL_HEAP (6 << 4) +#define PAGE_KERNEL_SYSPAGE (1 << 4) +#define PAGE_KERNEL_CPU (2 << 4) +#define PAGE_KERNEL_PTABLE (3 << 4) +#define PAGE_KERNEL_PMAP (4 << 4) +#define PAGE_KERNEL_STACK (5 << 4) +#define PAGE_KERNEL_HEAP (6 << 4) #ifndef __ASSEMBLY__ @@ -83,6 +83,8 @@ typedef struct _pmap_t { page_t *pmapp; } pmap_t; + #endif + #endif diff --git a/hal/riscv64/arch/spinlock.h b/hal/riscv64/arch/spinlock.h index ed352f866..830f22922 100644 --- a/hal/riscv64/arch/spinlock.h +++ b/hal/riscv64/arch/spinlock.h @@ -29,4 +29,5 @@ typedef struct _spinlock_t { u64 lock; } spinlock_t; + #endif diff --git a/hal/riscv64/arch/types.h b/hal/riscv64/arch/types.h index 49ca71331..56b68254f 100644 --- a/hal/riscv64/arch/types.h +++ b/hal/riscv64/arch/types.h @@ -50,6 +50,8 @@ typedef struct _oid_t { id_t id; } oid_t; + #endif + #endif diff --git a/hal/riscv64/console.c b/hal/riscv64/console.c index 3ccd9b552..f106a4a28 100644 --- a/hal/riscv64/console.c +++ b/hal/riscv64/console.c @@ -18,24 +18,27 @@ #include "sbi.h" -struct { +static struct { spinlock_t spinlock; } console_common; void _hal_consolePrint(const char *s) { - for (; *s; s++) - hal_consolePutch(*s); + while (*s != '\0') { + hal_consolePutch(*s++); + } } void hal_consolePrint(int attr, const char *s) { - if (attr == ATTR_BOLD) + if (attr == ATTR_BOLD) { _hal_consolePrint(CONSOLE_BOLD); - else if (attr != ATTR_USER) + } + else if (attr != ATTR_USER) { _hal_consolePrint(CONSOLE_CYAN); + } _hal_consolePrint(s); _hal_consolePrint(CONSOLE_NORMAL); @@ -47,14 +50,12 @@ void hal_consolePutch(char c) spinlock_ctx_t sc; hal_spinlockSet(&console_common.spinlock, &sc); - sbi_ecall(1, 0, c, 0, 0, 0, 0, 0); + sbi_ecall(SBI_PUTCHAR, 0, c, 0, 0, 0, 0, 0); hal_spinlockClear(&console_common.spinlock, &sc); } -__attribute__ ((section (".init"))) void _hal_consoleInit(void) +__attribute__((section(".init"))) void _hal_consoleInit(void) { hal_spinlockCreate(&console_common.spinlock, "console.spinlock"); - - return; } diff --git a/hal/riscv64/cpu.c b/hal/riscv64/cpu.c index 8da2640a8..b93cc1345 100644 --- a/hal/riscv64/cpu.c +++ b/hal/riscv64/cpu.c @@ -321,10 +321,14 @@ void _hal_cpuInit(void) void hal_cpuBroadcastIPI(unsigned int intr) { + (void)intr; + /* TODO */ } void hal_cpuTlsSet(hal_tls_t *tls, cpu_context_t *ctx) { + (void)ctx; + __asm__ volatile("mv tp, %0" ::"r"(tls->tls_base)); } diff --git a/hal/riscv64/dtb.c b/hal/riscv64/dtb.c index 299f57436..ca594c007 100644 --- a/hal/riscv64/dtb.c +++ b/hal/riscv64/dtb.c @@ -36,7 +36,7 @@ struct _fdt_header_t { }; -struct { +static struct { struct _fdt_header_t *fdth; void *start; diff --git a/hal/riscv64/exceptions.c b/hal/riscv64/exceptions.c index 6d8a9f825..90002e255 100644 --- a/hal/riscv64/exceptions.c +++ b/hal/riscv64/exceptions.c @@ -21,10 +21,10 @@ #include "include/mman.h" -#define SIZE_EXCEPTIONS 16 +#define SIZE_EXCEPTIONS 16 -struct { +static struct { void (*handlers[SIZE_EXCEPTIONS])(unsigned int, exc_context_t *); void (*defaultHandler)(unsigned int, exc_context_t *); spinlock_t spinlock; @@ -36,10 +36,11 @@ void hal_exceptionsDumpContext(char *buff, exc_context_t *ctx, int n) unsigned int i = 0; static const char *mnemonics[] = { - "0 Instruction adrress missaligned", "1 Instruction access fault", "2 Illegal instruction", "3 Breakpoint", - "4 Reserved", "5 Load access fault", "6 AMO address misaligned", "7 Store/AMO access fault", - "8 Environment call", "9 Reserved", "10 Reserved", "11 Reserved", - "12 Instruction page fault", "13 Load page fault", "14 Reserved", "15 Store/AMO page fault" }; + "0 Instruction address missaligned", "1 Instruction access fault", "2 Illegal instruction", "3 Breakpoint", + "4 Reserved", "5 Load access fault", "6 AMO address misaligned", "7 Store/AMO access fault", + "8 Environment call", "9 Reserved", "10 Reserved", "11 Reserved", + "12 Instruction page fault", "13 Load page fault", "14 Reserved", "15 Store/AMO page fault" + }; n &= 0xf; @@ -107,8 +108,6 @@ void hal_exceptionsDumpContext(char *buff, exc_context_t *ctx, int n) buff[i++] = '\n'; buff[i] = 0; - - return; } @@ -126,8 +125,6 @@ static void exceptions_defaultHandler(unsigned int n, exc_context_t *ctx) for (;;) { hal_cpuHalt(); } - - return; } @@ -140,19 +137,24 @@ static void exceptions_trampoline(unsigned int n, exc_context_t *ctx) int hal_exceptionsFaultType(unsigned int n, exc_context_t *ctx) { int prot = PROT_NONE; + u64 cause = ctx->scause; - u64 num = ctx->scause; + (void)n; prot |= PROT_READ; - if (num == 6 || num== 7 || num == 15) + if ((cause == 6) || (cause == 7) || (cause == 15)) { prot |= PROT_WRITE; + } - if (num <= 3 || num == 12) + if ((cause <= 3) || (cause == 12)) { prot |= PROT_EXEC; + } - if ((ctx->sstatus & 0x100) == 0) // from user code + if ((ctx->sstatus & 0x100) == 0) { + /* from user code */ prot |= PROT_USER; + } return prot; } @@ -179,8 +181,9 @@ void exceptions_dispatch(unsigned int n, cpu_context_t *ctx) void (*h)(unsigned int, exc_context_t *); - if (n >= SIZE_EXCEPTIONS) + if (n >= SIZE_EXCEPTIONS) { return; + } hal_spinlockSet(&exceptions_common.spinlock, &sc); h = exceptions_common.handlers[n]; @@ -217,8 +220,9 @@ int hal_exceptionsSetHandler(unsigned int n, void (*handler)(unsigned int, exc_c return 0; } - if (n >= SIZE_EXCEPTIONS) + if (n >= SIZE_EXCEPTIONS) { return -1; + } hal_spinlockSet(&exceptions_common.spinlock, &sc); exceptions_common.handlers[n] = handler; @@ -229,15 +233,14 @@ int hal_exceptionsSetHandler(unsigned int n, void (*handler)(unsigned int, exc_c /* Function initializes exception handling */ -__attribute__ ((section (".init"))) void _hal_exceptionsInit(void) +__attribute__((section(".init"))) void _hal_exceptionsInit(void) { unsigned int k; hal_spinlockCreate(&exceptions_common.spinlock, "exceptions_common.spinlock"); exceptions_common.defaultHandler = (void *)exceptions_defaultHandler; - for (k = 0; k < SIZE_EXCEPTIONS; k++) + for (k = 0; k < SIZE_EXCEPTIONS; k++) { exceptions_common.handlers[k] = exceptions_trampoline; - - return; + } } diff --git a/hal/riscv64/hal.c b/hal/riscv64/hal.c index 881ee2492..c0792e640 100644 --- a/hal/riscv64/hal.c +++ b/hal/riscv64/hal.c @@ -24,7 +24,7 @@ #include "config.h" #include "halsyspage.h" -struct { +static struct { int started; } hal_common; @@ -32,6 +32,7 @@ struct { syspage_t *hal_syspage; addr_t hal_relOffs; + void *hal_syspageRelocate(void *data) { return ((u8 *)data + hal_relOffs); @@ -66,7 +67,7 @@ void hal_lockScheduler(void) } -__attribute__ ((section (".init"))) void _hal_init(void) +__attribute__((section(".init"))) void _hal_init(void) { _hal_spinlockInit(); _hal_consoleInit(); @@ -80,6 +81,4 @@ __attribute__ ((section (".init"))) void _hal_init(void) _hal_cpuInit(); #endif hal_common.started = 0; - - return; } diff --git a/hal/riscv64/pmap.c b/hal/riscv64/pmap.c index 84761de6f..2481626ef 100644 --- a/hal/riscv64/pmap.c +++ b/hal/riscv64/pmap.c @@ -43,11 +43,10 @@ struct { u64 stack[512]; u8 heap[SIZE_PAGE]; -u64 iopdir[512]; + u64 iopdir[512]; /* second pdir for mapping I/O - first 1 GB of memory is mapped linearly at the end of address space */ - /* The order of below fields could be randomized */ u64 minAddr; u64 maxAddr; @@ -61,10 +60,8 @@ u64 iopdir[512]; u64 dtb; u32 dtbsz; - addr_t kernel; size_t kernelsz; - } pmap_common; @@ -83,9 +80,9 @@ int pmap_create(pmap_t *pmap, pmap_t *kpmap, page_t *p, void *vaddr) pages = (kpmap->end - vaddr) / ((ptr_t)SIZE_PAGE << 18); - for (i = 0; i < pages; vaddr += (u64)(SIZE_PAGE << 18), ++i) + for (i = 0; i < pages; vaddr += (u64)(SIZE_PAGE << 18), ++i) { pmap->pdir2[((ptr_t)vaddr >> 30) & 0x1ff] = kpmap->pdir2[((ptr_t)vaddr >> 30) & 0x1ff]; - + } pmap->pdir2[511] = kpmap->pdir2[511]; @@ -98,8 +95,9 @@ addr_t pmap_destroy(pmap_t *pmap, int *i) int kernel = VADDR_KERNEL / ((u64)SIZE_PAGE << 18); while (*i < kernel) { - if (pmap->pdir2[*i] != NULL) + if (pmap->pdir2[*i] != NULL) { return (pmap->pdir2[(*i)++] & (u64)~0x3ff) << 2; + } (*i)++; } @@ -176,7 +174,6 @@ int pmap_enter(pmap_t *pmap, addr_t pa, void *va, int attr, page_t *alloc) hal_spinlockClear(&pmap_common.lock, &sc); return EOK; - } @@ -190,19 +187,22 @@ int pmap_remove(pmap_t *pmap, void *vaddr) pdi1 = ((ptr_t)vaddr >> 21) & 0x1ff; pti = ((ptr_t)vaddr >> 12) & 0x1ff; - if (!pmap->pdir2[pdi2]) + if (!pmap->pdir2[pdi2]) { return EOK; + } hal_spinlockSet(&pmap_common.lock, &sc); /* Map page table corresponding to vaddr at specified virtual address */ - addr = ((a = pmap->pdir2[pdi2]) >> 10) << 12; + a = (pmap->pdir2[pdi2] >> 10) << 12; + addr = (a >> 10) << 12; if ((a & 1) && !(a & 0xa)) { pmap_common.pdir0[((ptr_t)pmap_common.ptable >> 12) & 0x1ff] = (((addr >> 12) << 10) | 0xc7); hal_cpuFlushTLB(pmap_common.ptable); - addr = (((a = pmap_common.ptable[pdi1]) >> 10) << 12); + a = pmap_common.ptable[pdi1]; + addr = (a >> 10) << 12; if ((a & 1) && !(a & 0xa)) { pmap_common.pdir0[((ptr_t)pmap_common.ptable >> 12) & 0x1ff] = (((addr >> 12) << 10) | 0xc7); @@ -230,8 +230,9 @@ addr_t pmap_resolve(pmap_t *pmap, void *vaddr) pdi1 = ((ptr_t)vaddr >> 21) & 0x1ff; pti = ((ptr_t)vaddr >> 12) & 0x000001ff; - if (!pmap->pdir2[pdi2]) + if (!pmap->pdir2[pdi2]) { return 0; + } hal_spinlockSet(&pmap_common.lock, &sc); @@ -267,8 +268,9 @@ int pmap_getPage(page_t *page, addr_t *addr) hal_spinlockSet(&pmap_common.lock, &sc); /* Ignore bbl area */ - if (((a >= 0x80000000) && (a < 0x80200000)) || (a < pmap_common.minAddr)) + if (((a >= 0x80000000) && (a < 0x80200000)) || (a < pmap_common.minAddr)) { a = 0x80200000; + } if (a >= pmap_common.maxAddr) { hal_spinlockClear(&pmap_common.lock, &sc); @@ -281,25 +283,29 @@ int pmap_getPage(page_t *page, addr_t *addr) page->flags = 0; *addr = a + SIZE_PAGE; - if ((prog = hal_syspage->progs) != NULL) { + if (hal_syspage->progs != NULL) { + prog = hal_syspage->progs; do { if (page->addr >= prog->start && page->addr < prog->end) { page->flags = PAGE_OWNER_APP; return EOK; } - } while ((prog = prog->next) != hal_syspage->progs); + prog = prog->next; + } while (prog != hal_syspage->progs); } if ((page->addr >= pmap_common.kernel) && (page->addr < pmap_common.kernel + pmap_common.kernelsz)) { page->flags |= PAGE_OWNER_KERNEL; - if ((page->addr >= (ptr_t)pmap_common.pdir2) && (page->addr < (ptr_t)pmap_common.pdir2 + 3 * SIZE_PAGE)) + if ((page->addr >= (ptr_t)pmap_common.pdir2) && (page->addr < ((ptr_t)pmap_common.pdir2 + 3 * SIZE_PAGE))) { page->flags |= PAGE_KERNEL_PTABLE; + } - if ((page->addr >= (ptr_t)pmap_common.stack) && (page->addr < (ptr_t)pmap_common.stack + SIZE_PAGE)) + if ((page->addr >= (ptr_t)pmap_common.stack) && (page->addr < ((ptr_t)pmap_common.stack + SIZE_PAGE))) { page->flags |= PAGE_KERNEL_STACK; + } } - else if ((page->addr >= pmap_common.dtb) && (page->addr < pmap_common.dtb + pmap_common.dtbsz)) { + else if ((page->addr >= pmap_common.dtb) && (page->addr < (pmap_common.dtb + pmap_common.dtbsz))) { page->flags |= PAGE_OWNER_BOOT; } else { @@ -317,11 +323,13 @@ int _pmap_kernelSpaceExpand(pmap_t *pmap, void **start, void *end, page_t *dp) vaddr = (void *)((ptr_t)(*start + SIZE_PAGE - 1) & ~(SIZE_PAGE - 1)); - if (vaddr >= end) + if (vaddr >= end) { return EOK; + } - if (vaddr < (void *)VADDR_KERNEL) + if (vaddr < (void *)VADDR_KERNEL) { vaddr = (void *)VADDR_KERNEL; + } for (; vaddr < end; vaddr += (1ULL << 30)) { @@ -346,8 +354,9 @@ char pmap_marker(page_t *p) { char *marksets[4] = { "BBBBBBBBBBBBBBBB", "KYCPMSHKKKKKKKKK", "AAAAAAAAAAAAAAAA", "UUUUUUUUUUUUUUUU" }; - if (p->flags & PAGE_FREE) + if (p->flags & PAGE_FREE) { return '.'; + } return marksets[(p->flags >> 1) & 3][(p->flags >> 4) & 0xf]; } @@ -379,10 +388,12 @@ void _pmap_init(pmap_t *pmap, void **vstart, void **vend) a = ntoh64(m[i].addr); l = ntoh64(m[i].limit); - if (a + l > pmap_common.maxAddr) + if ((a + l) > pmap_common.maxAddr) { pmap_common.maxAddr = a + l; - if (a < pmap_common.minAddr) + } + if (a < pmap_common.minAddr) { pmap_common.minAddr = a; + } } /* Initialize kernel page table - remove first 4 MB mapping */ @@ -407,56 +418,37 @@ void _pmap_init(pmap_t *pmap, void **vstart, void **vend) /* Create initial heap */ pmap_enter(pmap, pmap_common.start, (*vstart), PGHD_WRITE | PGHD_PRESENT, NULL); - for (v = *vend; v < (void *)VADDR_KERNEL + (2 << 20); v += SIZE_PAGE) + for (v = *vend; v < (void *)((char *)VADDR_KERNEL + (2 << 20)); v += SIZE_PAGE) { pmap_remove(pmap, v); + } - pmap->satp = ((pmap_resolve(pmap, (void *)pmap_common.pdir2) >> 12) | 0x8000000000000000ULL); + pmap->satp = ((pmap_resolve(pmap, (char *)pmap_common.pdir2) >> 12) | 0x8000000000000000ULL); hal_cpuFlushTLB(NULL); - - return; } int pmap_segment(unsigned int i, void **vaddr, size_t *size, int *prot, void **top) { switch (i) { - case 0: - *vaddr = (void *)VADDR_KERNEL; - *size = (ptr_t)&_etext - VADDR_KERNEL; - *prot = (PROT_EXEC | PROT_READ); - break; - case 1: - *vaddr = &_etext; - *size = (ptr_t)(*top) - (ptr_t)&_etext; - *prot = (PROT_WRITE | PROT_READ); - break; - default: - return -EINVAL; + case 0: + *vaddr = (void *)VADDR_KERNEL; + *size = (ptr_t)&_etext - VADDR_KERNEL; + *prot = (PROT_EXEC | PROT_READ); + break; + case 1: + *vaddr = &_etext; + *size = (ptr_t)(*top) - (ptr_t)&_etext; + *prot = (PROT_WRITE | PROT_READ); + break; + default: + return -EINVAL; } return EOK; } -int pmap_getMapsCnt(void) -{ - return 0; -} - - -int pmap_getMapParameters(u8 id, void **start, void **end) -{ - return EOK; -} - - -void pmap_getAllocatedSegment(void *memStart, void *memStop, void **segStart, void **segStop) -{ - return; -} - - void _pmap_preinit(void) { unsigned int i; @@ -476,8 +468,9 @@ void _pmap_preinit(void) pmap_common.pdir2[(VADDR_KERNEL >> 30) % 512] = ((addr_t)pmap_common.pdir1 >> 2) | 1; pmap_common.pdir1[(VADDR_KERNEL >> 21) % 512] = ((addr_t)pmap_common.pdir0 >> 2) | 1; - for (i = 0; i < 512; i++) + for (i = 0; i < 512; i++) { pmap_common.pdir0[((VADDR_KERNEL >> 12) % 512) + i] = (((((addr_t)&_start + i * SIZE_PAGE) >> 12) << 10) | 0xcf); + } /* Map PLIC (MOD) */ pmap_common.pdir2[511] = 0xcf; diff --git a/hal/riscv64/riscv64.h b/hal/riscv64/riscv64.h index df0ea16da..22e6c4609 100644 --- a/hal/riscv64/riscv64.h +++ b/hal/riscv64/riscv64.h @@ -16,52 +16,66 @@ #ifndef _HAL_RISCV64_H_ #define _HAL_RISCV64_H_ + #include #define csr_set(csr, val) \ ({ \ unsigned long __v = (unsigned long)(val); \ - __asm__ __volatile__("csrs " #csr ", %0" \ - : \ - : "rK"(__v) \ - : "memory"); \ - __v; \ + __asm__ volatile( \ + "csrs " #csr ", %0" \ + : \ + : "rK"(__v) \ + : "memory"); \ }) #define csr_write(csr, val) \ ({ \ unsigned long __v = (unsigned long)(val); \ - __asm__ __volatile__("csrw " #csr ", %0" \ - : \ - : "rK"(__v) \ - : "memory"); \ + __asm__ volatile( \ + "csrw " #csr ", %0" \ + : \ + : "rK"(__v) \ + : "memory"); \ }) #define csr_read(csr) \ ({ \ register unsigned long __v; \ - __asm__ __volatile__("csrr %0, " #csr \ - : "=r"(__v) \ - : \ - : "memory"); \ + __asm__ volatile( \ + "csrr %0, " #csr \ + : "=r"(__v) \ + : \ + : "memory"); \ __v; \ }) +#define csr_clear(csr, val) \ + ({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ volatile( \ + "csrc " #csr ", %0" \ + : \ + : "rK"(__v) \ + : "memory"); \ + }) + + static inline void hal_cpuFlushTLB(void *vaddr) { - __asm__ ("sfence.vma"::); + (void)vaddr; + + __asm__ volatile("sfence.vma" ::); } static inline void hal_cpuSwitchSpace(addr_t pdir) { - __asm__ ("sfence.vma; csrw sptbr, %0"::"r" (pdir)); - - return; + __asm__ volatile("sfence.vma; csrw sptbr, %0" ::"r"(pdir)); } @@ -69,9 +83,9 @@ static inline cycles_t hal_cpuGetCycles2(void) { register cycles_t n; - __asm__ __volatile__ ( + __asm__ __volatile__( "rdtime %0" - : "=r" (n)); + : "=r"(n)); return n; } diff --git a/hal/riscv64/sbi.h b/hal/riscv64/sbi.h index 220ef6dc4..7343387f4 100644 --- a/hal/riscv64/sbi.h +++ b/hal/riscv64/sbi.h @@ -18,15 +18,16 @@ #include -#define SBI_SETTIMER 0 -#define SBI_PUTCHAR 1 -#define SBI_GETCHAR 2 -#define SBI_CLEARIPI 3 -#define SBI_SENDIPI 4 -#define SBI_REMOTE_FENCE_I 5 -#define SBI_REMOTE_SFENCE_VMA 6 -#define SBI_REMOTE_SFENCE_VMA_ASID 7 -#define SBI_SHUTDOWN 8 + +#define SBI_SETTIMER 0 +#define SBI_PUTCHAR 1 +#define SBI_GETCHAR 2 +#define SBI_CLEARIPI 3 +#define SBI_SENDIPI 4 +#define SBI_REMOTE_FENCE_I 5 +#define SBI_REMOTE_SFENCE_VMA 6 +#define SBI_REMOTE_SFENCE_VMA_ASID 7 +#define SBI_SHUTDOWN 8 typedef struct _sbiret_t { @@ -39,20 +40,22 @@ static inline sbiret_t sbi_ecall(int ext, int fid, u64 arg0, u64 arg1, u64 arg2, { sbiret_t ret; - register u64 a0 asm ("a0") = arg0; - register u64 a1 asm ("a1") = arg1; - register u64 a2 asm ("a2") = arg2; - register u64 a3 asm ("a3") = arg3; - register u64 a4 asm ("a4") = arg4; - register u64 a5 asm ("a5") = arg5; - register u64 a6 asm ("a6") = fid; - register u64 a7 asm ("a7") = ext; + register u64 a0 asm("a0") = arg0; + register u64 a1 asm("a1") = arg1; + register u64 a2 asm("a2") = arg2; + register u64 a3 asm("a3") = arg3; + register u64 a4 asm("a4") = arg4; + register u64 a5 asm("a5") = arg5; + register u64 a6 asm("a6") = fid; + register u64 a7 asm("a7") = ext; - __asm__ volatile ("\ - ecall" - : "+r" (a0), "+r" (a1) - : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) - : "memory"); + /* clang-format off */ + __asm__ volatile ( + "ecall" + : "+r" (a0), "+r" (a1) + : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) + : "memory"); + /* clang-format on */ ret.error = a0; ret.value = a1; diff --git a/hal/riscv64/spinlock.c b/hal/riscv64/spinlock.c index c287c6de9..2a63e8d82 100644 --- a/hal/riscv64/spinlock.c +++ b/hal/riscv64/spinlock.c @@ -18,7 +18,7 @@ #include "hal/list.h" -struct { +static struct { spinlock_t spinlock; spinlock_t *first; } spinlock_common; @@ -90,7 +90,7 @@ void hal_spinlockDestroy(spinlock_t *spinlock) } -__attribute__ ((section (".init"))) void _hal_spinlockInit(void) +__attribute__((section(".init"))) void _hal_spinlockInit(void) { spinlock_common.first = NULL; _hal_spinlockCreate(&spinlock_common.spinlock, "spinlock_common.spinlock"); From 9066135d4a4c3d44e8c46a82ad0e85c190a3d7bd Mon Sep 17 00:00:00 2001 From: lukileczo Date: Tue, 2 Jan 2024 16:00:35 +0100 Subject: [PATCH 4/7] riscv64: refactor interrupt handling - simplify interrupt handling code - fix timer interval setting - properly handle interrupts from CLINT and PLIC - remove reading from exec-only pages - mapping is now done correctly JIRA: RTOS-550 --- hal/riscv64/_init.S | 5 +- hal/riscv64/_interrupts.S | 67 +++++----- hal/riscv64/arch/cpu.h | 8 ++ hal/riscv64/arch/interrupts.h | 3 +- hal/riscv64/interrupts.c | 223 ++++++++++++++++++++++++---------- hal/riscv64/plic.c | 101 ++++++++------- hal/riscv64/plic.h | 21 ++-- hal/riscv64/riscv64.h | 17 +-- hal/riscv64/timer.c | 41 +++---- 9 files changed, 297 insertions(+), 189 deletions(-) diff --git a/hal/riscv64/_init.S b/hal/riscv64/_init.S index 9be742751..a459d2871 100644 --- a/hal/riscv64/_init.S +++ b/hal/riscv64/_init.S @@ -20,7 +20,6 @@ #define SR_FS 0x00006000 #define SR_SUM 0x00040000 -#define SR_MER 0x00080000 #define VADDR_SYSPAGE (_end + SIZE_PAGE - 1) @@ -52,8 +51,8 @@ _start: */ li t0, SR_FS csrc sstatus, t0 - /* Allow supervisor access to user space and reading from execute pages (for the time being) */ - li t0, SR_SUM | SR_MER + /* Allow supervisor access to user space */ + li t0, SR_SUM csrs sstatus, t0 la t0, hal_syspage /* t0 = &hal_syspage (phy) */ diff --git a/hal/riscv64/_interrupts.S b/hal/riscv64/_interrupts.S index da08eaea7..12e0d416a 100644 --- a/hal/riscv64/_interrupts.S +++ b/hal/riscv64/_interrupts.S @@ -90,8 +90,8 @@ /* Disable FPU */ li t0, SR_FS csrc sstatus, t0 - /* Allow supervisor access to user space and reading from execute pages (for the time being) */ - li t0, SR_SUM | SR_MXR + /* Allow supervisor access to user space */ + li t0, SR_SUM csrs sstatus, t0 csrrc s1, sstatus, SR_SIE @@ -165,62 +165,51 @@ .endm -.global interrupts_handleintexc -.type interrupts_handleintexc, @function -interrupts_handleintexc: +.global _interrupts_dispatch +.type _interrupts_dispatch, @function +_interrupts_dispatch: .align 8 /* Disable interrupts */ csrc sstatus, SR_SIE SAVE - mv a0, sp - - li t1, 8 - beq s4, t1, 3f - bge s4, zero, 2f - - li t1, 0x8000000000000009 - bne s4, t1, 33f - li a0, 0xa - j 34f - -33: - li t1, 0x8000000000000005 - bne s4, t1, 34f - call handler - mv a0, zero -34: mv a1, sp - call interrupts_dispatchIRQ - j 4f -2: - mv a0, s4 - andi a0, a0, 0xf - mv a1, sp - call exceptions_dispatch - j 5f -3: + /* Check interrupt source */ + li s1, SCAUSE_INTR + and s0, s4, s1 + andi a0, s4, 0xff /* Exception code */ + beqz s0, _interrupts_notIrq + + /* IRQ */ + call interrupts_dispatch + j _interrupts_return + +_interrupts_notIrq: + li t1, SCAUSE_ECALL + bne a0, t1, _interrupts_exception + + /* Syscall */ addi s2, s2, 4 /* move pc past ecall instruction */ sd s2, 248(sp) - mv a0, a7 /* syscall number */ + mv a0, a7 /* syscall number */ ld a1, 288(sp) /* ustack */ csrs sstatus, SR_SIE call syscalls_dispatch sd a0, 56(sp) csrc sstatus, SR_SIE - j 5f -4: - beq a0, zero, 5f - li a0, 0 + + j _interrupts_return + +_interrupts_exception: mv a1, sp - call threads_schedule + call exceptions_dispatch -5: +_interrupts_return: RESTORE sret -.size interrupts_handleintexc, .-interrupts_handleintexc +.size _interrupts_dispatch, .-_interrupts_dispatch diff --git a/hal/riscv64/arch/cpu.h b/hal/riscv64/arch/cpu.h index 45836ca73..2c2bdacd6 100644 --- a/hal/riscv64/arch/cpu.h +++ b/hal/riscv64/arch/cpu.h @@ -30,6 +30,14 @@ #define SIZE_USTACK (8 * SIZE_PAGE) #endif +/* CSR bits */ +#define SCAUSE_INTR (1u << 63) + +#define SCAUSE_ECALL 8u /* Environment call from S-mode */ + +/* Interrupts */ +#define CLINT_IRQ_FLG (1u << 31) /* Marks that interrupt handler is installed for CLINT, not PLIC */ + #ifndef __ASSEMBLY__ diff --git a/hal/riscv64/arch/interrupts.h b/hal/riscv64/arch/interrupts.h index fa1659e0d..05d722362 100644 --- a/hal/riscv64/arch/interrupts.h +++ b/hal/riscv64/arch/interrupts.h @@ -20,7 +20,8 @@ #include "cpu.h" -#define SYSTICK_IRQ 0 +#define SYSTICK_IRQ (5u | CLINT_IRQ_FLG) + typedef struct _intr_handler_t { struct _intr_handler_t *next; diff --git a/hal/riscv64/interrupts.c b/hal/riscv64/interrupts.c index 20534e685..da16d259e 100644 --- a/hal/riscv64/interrupts.c +++ b/hal/riscv64/interrupts.c @@ -25,139 +25,240 @@ #include "proc/userintr.h" #include "include/errno.h" +#include -#define SIZE_INTERRUPTS 16 +#define CLINT_IRQ_SIZE 16 -struct { - spinlock_t spinlocks[SIZE_INTERRUPTS]; - intr_handler_t *handlers[SIZE_INTERRUPTS]; - unsigned int counters[SIZE_INTERRUPTS]; -} interrupts; +#define EXT_IRQ 9 +/* clang-format off */ +enum irq_state { irq_enable = 0, irq_disable }; +/* clang-format on */ -int interrupts_dispatchIRQ(unsigned int n, cpu_context_t *ctx) + +static struct { + struct { + spinlock_t spinlocks[CLINT_IRQ_SIZE]; + unsigned int counters[CLINT_IRQ_SIZE]; + intr_handler_t *handlers[CLINT_IRQ_SIZE]; + } clint; + + struct { + spinlock_t spinlocks[PLIC_IRQ_SIZE]; + unsigned int counters[PLIC_IRQ_SIZE]; + intr_handler_t *handlers[PLIC_IRQ_SIZE]; + } plic; +} interrupts_common; + + +extern int threads_schedule(unsigned int n, cpu_context_t *context, void *arg); + + +static void interrupts_dispatchPlic(cpu_context_t *ctx) { + int reschedule = 0; intr_handler_t *h; spinlock_ctx_t sc; - unsigned int cn = 0; - int res = 0; - if (n >= SIZE_INTERRUPTS) - return 0; + unsigned int irq = plic_claim(1); - if (dtb_getPLIC() && (n != 0)) { - - cn = plic_claim(1); - if (cn == 0) { - return 0; - } - n = cn; + if (irq == 0) { + return; } - hal_spinlockSet(&interrupts.spinlocks[n], &sc); + hal_spinlockSet(&interrupts_common.plic.spinlocks[irq], &sc); - interrupts.counters[n]++; + interrupts_common.plic.counters[irq]++; - if ((h = interrupts.handlers[n]) != NULL) { - do - if (h->f(n, ctx, h->data)) - res = 1; + h = interrupts_common.plic.handlers[irq]; + if (h != NULL) { + do { + reschedule |= h->f(irq, NULL, h->data); + h = h->next; + } while (h != interrupts_common.plic.handlers[irq]); + } - while ((h = h->next) != interrupts.handlers[n]); + if (reschedule != 0) { + threads_schedule(irq, ctx, NULL); } - hal_spinlockClear(&interrupts.spinlocks[n], &sc); + hal_spinlockClear(&interrupts_common.plic.spinlocks[irq], &sc); + + plic_complete(1, irq); +} + + +static void interrupts_dispatchClint(unsigned int n, cpu_context_t *ctx) +{ + intr_handler_t *h; + int reschedule = 0; + spinlock_ctx_t sc; + + hal_spinlockSet(&interrupts_common.clint.spinlocks[n], &sc); + + interrupts_common.clint.counters[n]++; + + h = interrupts_common.clint.handlers[n]; + if (h != NULL) { + do { + reschedule |= h->f(n, NULL, h->data); + h = h->next; + } while (h != interrupts_common.clint.handlers[n]); + } - if (cn != 0) { - plic_complete(1, cn); + if (reschedule != 0) { + threads_schedule(n, ctx, NULL); } - return res; + hal_spinlockClear(&interrupts_common.clint.spinlocks[n], &sc); } -int hal_interruptsSetHandler(intr_handler_t *h) +void interrupts_dispatch(unsigned int n, cpu_context_t *ctx) +{ + if ((n == EXT_IRQ) && (dtb_getPLIC() != 0)) { + interrupts_dispatchPlic(ctx); + } + else { + interrupts_dispatchClint(n, ctx); + } +} + + +static int interrupts_setPlic(intr_handler_t *h, enum irq_state enable) { spinlock_ctx_t sc; - if (h == NULL || h->f == NULL || h->n >= SIZE_INTERRUPTS) + if (h->n >= PLIC_IRQ_SIZE) { return -EINVAL; + } - hal_spinlockSet(&interrupts.spinlocks[h->n], &sc); - HAL_LIST_ADD(&interrupts.handlers[h->n], h); + hal_spinlockSet(&interrupts_common.plic.spinlocks[h->n], &sc); - if (dtb_getPLIC() && (h->n)) { + if (enable == irq_enable) { + HAL_LIST_ADD(&interrupts_common.plic.handlers[h->n], h); plic_priority(h->n, 2); - plic_enableInterrupt(1, h->n, 1); + plic_enableInterrupt(1, h->n); + } + else { + plic_disableInterrupt(1, h->n); + HAL_LIST_REMOVE(&interrupts_common.plic.handlers[h->n], h); } - hal_spinlockClear(&interrupts.spinlocks[h->n], &sc); + hal_spinlockClear(&interrupts_common.plic.spinlocks[h->n], &sc); - return EOK; + return 0; } -int hal_interruptsDeleteHandler(intr_handler_t *h) +static int interrupts_setClint(intr_handler_t *h, enum irq_state enable) { spinlock_ctx_t sc; - if (h == NULL || h->f == NULL || h->n >= SIZE_INTERRUPTS) + if (h->n >= CLINT_IRQ_SIZE) { + return -EINVAL; + } + + hal_spinlockSet(&interrupts_common.clint.spinlocks[h->n], &sc); + + if (enable == irq_enable) { + HAL_LIST_ADD(&interrupts_common.clint.handlers[h->n], h); + csr_set(sie, 1u << h->n); + } + else { + csr_clear(sie, 1u << h->n); + HAL_LIST_REMOVE(&interrupts_common.clint.handlers[h->n], h); + } + + + hal_spinlockClear(&interrupts_common.clint.spinlocks[h->n], &sc); + + return 0; +} + + +int hal_interruptsSetHandler(intr_handler_t *h) +{ + int ret; + + if (h == NULL) { return -EINVAL; + } - hal_spinlockSet(&interrupts.spinlocks[h->n], &sc); - HAL_LIST_REMOVE(&interrupts.handlers[h->n], h); - hal_spinlockClear(&interrupts.spinlocks[h->n], &sc); + if ((h->n & CLINT_IRQ_FLG) != 0) { + h->n = h->n & ~CLINT_IRQ_FLG; + ret = interrupts_setClint(h, irq_enable); + } + else { + ret = interrupts_setPlic(h, irq_enable); + } - return EOK; + return ret; } -__attribute__((aligned(4))) void handler(cpu_context_t *ctx) +int hal_interruptsDeleteHandler(intr_handler_t *h) { - cycles_t c; + int ret; + + if (h == NULL) { + return -EINVAL; + } - c = hal_cpuGetCycles2(); + if ((h->n & CLINT_IRQ_FLG) != 0) { + h->n = h->n & ~CLINT_IRQ_FLG; + ret = interrupts_setClint(h, irq_disable); + } + else { + ret = interrupts_setPlic(h, irq_disable); + } - sbi_ecall(SBI_SETTIMER, 0, c + 1000, 0, 0, 0, 0, 0); + return ret; } char *hal_interruptsFeatures(char *features, unsigned int len) { - if (dtb_getPLIC()) + if (dtb_getPLIC()) { hal_strncpy(features, "Using PLIC interrupt controller", len); - else + } + else { hal_strncpy(features, "PLIC interrupt controller not found", len); + } - features[len - 1] = 0; + features[len - 1] = '\0'; return features; } -extern void interrupts_handleintexc(void *); +extern void _interrupts_dispatch(void *); __attribute__((section(".init"))) void _hal_interruptsInit(void) { - unsigned int k; + unsigned int i; + + for (i = 0; i < CLINT_IRQ_SIZE; i++) { + interrupts_common.clint.handlers[i] = NULL; + interrupts_common.clint.counters[i] = 0; + hal_spinlockCreate(&interrupts_common.clint.spinlocks[i], "interrupts_common.clint"); + } - for (k = 0; k < SIZE_INTERRUPTS; k++) { - interrupts.handlers[k] = NULL; - interrupts.counters[k] = 0; - hal_spinlockCreate(&interrupts.spinlocks[k], "interrupts.spinlocks[]"); + for (i = 0; i < PLIC_IRQ_SIZE; i++) { + interrupts_common.plic.handlers[i] = NULL; + interrupts_common.plic.counters[i] = 0; + hal_spinlockCreate(&interrupts_common.plic.spinlocks[i], "interrupts_common.plic"); } /* Enable HART interrupts */ csr_write(sscratch, 0); csr_write(sie, -1); - - csr_write(stvec, interrupts_handleintexc); + csr_write(stvec, _interrupts_dispatch); /* Initialize PLIC if present */ - if (dtb_getPLIC()) + if (dtb_getPLIC()) { _plic_init(); - - return; + } } diff --git a/hal/riscv64/plic.c b/hal/riscv64/plic.c index 6fb82753d..db81cf918 100644 --- a/hal/riscv64/plic.c +++ b/hal/riscv64/plic.c @@ -15,115 +15,128 @@ #include "plic.h" -#include "include/errno.h" +#include +/* clang-format off */ -struct { +/* PLIC register offsets */ +#define PLIC_PRIORITY(irqn) (0x0000 + (n) * 4) +#define PLIC_REG_PENDING(irqn) (0x1000 + ((irqn) / 32) * 4) +#define PLIC_REG_ENABLE(context, irqn) (0x2000 + (context) * 0x80 + ((irqn) / 32) * 4) +#define PLIC_REG_THRESHOLD(context) (0x200000 + (context) * 0x1000) +#define PLIC_REG_CLAIM(context) (0x200004 + (context) * 0x1000) + +/* clang-format on */ + + +static struct { volatile u8 *regw; - unsigned int baseEnable; - unsigned int baseContext; } plic_common; -static inline u32 plic_read(unsigned int reg) +u32 plic_read(unsigned int reg) { return (u32)(*(volatile u32 *)(plic_common.regw + reg)); } -static inline void plic_write(unsigned int reg, u32 v) +void plic_write(unsigned int reg, u32 v) { - *(volatile u32 *)(plic_common.regw + reg) = v; - return; + *(volatile u32 *)(plic_common.regw + reg) = v; } void plic_priority(unsigned int n, unsigned int priority) { - plic_write(n * 4, priority); - return; + plic_write(PLIC_PRIORITY(n), priority); } u32 plic_priorityGet(unsigned int n) { - return plic_read(n * 4); + return plic_read(PLIC_PRIORITY(n)); } int plic_isPending(unsigned int n) { - u32 reg = n / 32; u32 bitshift = n % 32; - return ((plic_read(0x1000 + 4 * reg) >> bitshift) & 1); + return ((plic_read(PLIC_REG_PENDING(n)) >> bitshift) & 1); } -void plic_tresholdSet(unsigned int hart, unsigned int priority) +void plic_tresholdSet(unsigned int context, unsigned int priority) { - plic_write(plic_common.baseContext + hart * 0x1000, priority); - return; + plic_write(PLIC_REG_THRESHOLD(context), priority); } -u32 plic_tresholdGet(unsigned int hart) +u32 plic_tresholdGet(unsigned int context) { - return plic_read(plic_common.baseContext + hart * 0x1000); + return plic_read(PLIC_REG_THRESHOLD(context)); } -unsigned int plic_claim(unsigned int hart) +unsigned int plic_claim(unsigned int context) { - return plic_read(plic_common.baseContext + hart * 0x1000 + 4); + return plic_read(PLIC_REG_CLAIM(context)); } -int plic_complete(unsigned int hart, unsigned int n) +void plic_complete(unsigned int context, unsigned int n) { - plic_write(plic_common.baseContext + hart * 0x1000 + 4, n); - return EOK; + plic_write(PLIC_REG_CLAIM(context), n); } -int plic_enableInterrupt(unsigned int hart, unsigned int n, char enable) +static int plic_modifyInterrupt(unsigned int context, unsigned int n, char enable) { - u32 reg = n / 32; u32 bitshift = n % 32; - u32 w; + u32 val; - if (n >= 128) - return -ENOENT; + if (n >= PLIC_IRQ_SIZE) { + return -1; + } - w = plic_read(plic_common.baseEnable + hart * 0x80); + val = plic_read(PLIC_REG_ENABLE(context, n)); - if (enable) - w |= (1 << bitshift); - else - w &= ~(1 << bitshift); + if (enable != 0) { + val |= (1 << bitshift); + } + else { + val &= ~(1 << bitshift); + } - plic_write(plic_common.baseEnable + hart * 0x80 + 4 * reg, w); + plic_write(PLIC_REG_ENABLE(context, n), val); - return EOK; + return 0; } -int _plic_init(void) +int plic_enableInterrupt(unsigned int hart, unsigned int n) { - unsigned int i; + return plic_modifyInterrupt(hart, n, 1); +} - plic_common.baseEnable = 0x2000; - plic_common.baseContext = 0x200000; - plic_common.regw = (void *)((u64)((1L << 39) - 1024 * 1024 * 1024 + 0x0c000000)| (u64)0xffffff8000000000); +int plic_disableInterrupt(unsigned int hart, unsigned int n) +{ + return plic_modifyInterrupt(hart, n, 0); +} + + +void _plic_init(void) +{ + unsigned int i; + + plic_common.regw = (void *)((u64)((1L << 39) - 1024 * 1024 * 1024 + 0x0c000000) | (u64)0xffffff8000000000); /* Disable and mask external interrupts */ - for (i = 1; i < 127; i++) { + for (i = 1; i < PLIC_IRQ_SIZE; i++) { plic_priority(i, 0); - plic_enableInterrupt(1, i, 0); + plic_disableInterrupt(1, i); } plic_tresholdSet(1, 1); - - return EOK; } diff --git a/hal/riscv64/plic.h b/hal/riscv64/plic.h index bab131c27..83bf3ec69 100644 --- a/hal/riscv64/plic.h +++ b/hal/riscv64/plic.h @@ -19,31 +19,34 @@ #include -extern void plic_priority(unsigned int n, unsigned int priority); +void plic_priority(unsigned int n, unsigned int priority); -extern u32 plic_priorityGet(unsigned int n); +u32 plic_priorityGet(unsigned int n); -extern int plic_isPending(unsigned int n); +int plic_isPending(unsigned int n); -extern void plic_tresholdSet(unsigned int hart, unsigned int priority); +void plic_tresholdSet(unsigned int context, unsigned int priority); -extern u32 plic_tresholdGet(unsigned int hart); +u32 plic_tresholdGet(unsigned int context); -extern unsigned int plic_claim(unsigned int hart); +unsigned int plic_claim(unsigned int context); -extern int plic_complete(unsigned int hart, unsigned int n); +void plic_complete(unsigned int context, unsigned int n); -extern int plic_enableInterrupt(unsigned int hart, unsigned int n, char enable); +int plic_enableInterrupt(unsigned int context, unsigned int n); -extern int _plic_init(void); +int plic_disableInterrupt(unsigned int context, unsigned int n); + + +void _plic_init(void); #endif diff --git a/hal/riscv64/riscv64.h b/hal/riscv64/riscv64.h index 22e6c4609..3409d6720 100644 --- a/hal/riscv64/riscv64.h +++ b/hal/riscv64/riscv64.h @@ -75,18 +75,13 @@ static inline void hal_cpuFlushTLB(void *vaddr) static inline void hal_cpuSwitchSpace(addr_t pdir) { - __asm__ volatile("sfence.vma; csrw sptbr, %0" ::"r"(pdir)); + /* clang-format off */ + __asm__ volatile( + "sfence.vma\n\t" + "csrw sptbr, %0\n\t" + ::"r"(pdir)); + /* clang-format on */ } -static inline cycles_t hal_cpuGetCycles2(void) -{ - register cycles_t n; - - __asm__ __volatile__( - "rdtime %0" - : "=r"(n)); - return n; -} - #endif diff --git a/hal/riscv64/timer.c b/hal/riscv64/timer.c index 868aef353..c078ae1d2 100644 --- a/hal/riscv64/timer.c +++ b/hal/riscv64/timer.c @@ -19,15 +19,17 @@ #include "riscv64.h" #include "sbi.h" #include "hal/string.h" +#include "hal/console.h" +#include -struct { +static struct { intr_handler_t handler; volatile time_t jiffies; spinlock_t sp; - u32 interval; -} timer; + u64 interval; +} timer_common; static int timer_irqHandler(unsigned int n, cpu_context_t *ctx, void *arg) @@ -36,7 +38,9 @@ static int timer_irqHandler(unsigned int n, cpu_context_t *ctx, void *arg) (void)arg; (void)ctx; - timer.jiffies += timer.interval; + ++timer_common.jiffies; + sbi_ecall(SBI_SETTIMER, 0, csr_read(time) + timer_common.interval, 0, 0, 0, 0, 0); + return 0; } @@ -51,11 +55,11 @@ time_t hal_timerGetUs(void) spinlock_ctx_t sc; time_t ret; - hal_spinlockSet(&timer.sp, &sc); - ret = timer.jiffies; - hal_spinlockClear(&timer.sp, &sc); + hal_spinlockSet(&timer_common.sp, &sc); + ret = timer_common.jiffies; + hal_spinlockClear(&timer_common.sp, &sc); - return ret; + return ret * 1000ULL; } @@ -79,19 +83,14 @@ char *hal_timerFeatures(char *features, unsigned int len) __attribute__((section(".init"))) void _hal_timerInit(u32 interval) { - cycles_t c = hal_cpuGetCycles2() / 1000; - - timer.interval = interval; - timer.jiffies = 0; - - sbi_ecall(SBI_SETTIMER, 0, c + 1000L, 0, 0, 0, 0, 0); - csr_set(sie, SIE_STIE); + timer_common.interval = interval * (TIMER_FREQ / 1000000ULL); + timer_common.jiffies = 0; - hal_spinlockCreate(&timer.sp, "timer"); - timer.handler.f = timer_irqHandler; - timer.handler.n = SYSTICK_IRQ; - timer.handler.data = NULL; - hal_interruptsSetHandler(&timer.handler); + hal_spinlockCreate(&timer_common.sp, "timer"); + timer_common.handler.f = timer_irqHandler; + timer_common.handler.n = SYSTICK_IRQ; + timer_common.handler.data = NULL; + hal_interruptsSetHandler(&timer_common.handler); - return; + sbi_ecall(SBI_SETTIMER, 0, csr_read(time) + timer_common.interval, 0, 0, 0, 0, 0); } From a6e2a9d40bf769bf31df68733b72224a9963783c Mon Sep 17 00:00:00 2001 From: lukileczo Date: Tue, 2 Jan 2024 17:05:57 +0100 Subject: [PATCH 5/7] riscv64/sbi: use SBI calls in ver 0.2+ JIRA: RTOS-550 --- hal/riscv64/Makefile | 2 +- hal/riscv64/console.c | 2 +- hal/riscv64/hal.c | 1 + hal/riscv64/sbi.c | 141 ++++++++++++++++++++++++++++++++++++++++++ hal/riscv64/sbi.h | 65 ++++++++----------- hal/riscv64/timer.c | 4 +- syscalls.c | 6 +- 7 files changed, 173 insertions(+), 48 deletions(-) create mode 100644 hal/riscv64/sbi.c diff --git a/hal/riscv64/Makefile b/hal/riscv64/Makefile index 96dc42f42..d5cda5241 100644 --- a/hal/riscv64/Makefile +++ b/hal/riscv64/Makefile @@ -4,7 +4,7 @@ # Copyright 2018, 2020 Phoenix Systems # -OBJS += $(addprefix $(PREFIX_O)hal/riscv64/, _init.o _string.o _interrupts.o hal.o spinlock.o interrupts.o cpu.o pmap.o dtb.o timer.o string.o exceptions.o plic.o) +OBJS += $(addprefix $(PREFIX_O)hal/riscv64/, _init.o _string.o _interrupts.o hal.o spinlock.o interrupts.o cpu.o pmap.o dtb.o timer.o string.o exceptions.o plic.o sbi.o) CFLAGS += -Ihal/riscv64 OBJS += $(PREFIX_O)hal/riscv64/console.o diff --git a/hal/riscv64/console.c b/hal/riscv64/console.c index f106a4a28..547c20e2c 100644 --- a/hal/riscv64/console.c +++ b/hal/riscv64/console.c @@ -50,7 +50,7 @@ void hal_consolePutch(char c) spinlock_ctx_t sc; hal_spinlockSet(&console_common.spinlock, &sc); - sbi_ecall(SBI_PUTCHAR, 0, c, 0, 0, 0, 0, 0); + hal_sbiPutchar(c); hal_spinlockClear(&console_common.spinlock, &sc); } diff --git a/hal/riscv64/hal.c b/hal/riscv64/hal.c index c0792e640..dcc7ca7b4 100644 --- a/hal/riscv64/hal.c +++ b/hal/riscv64/hal.c @@ -69,6 +69,7 @@ void hal_lockScheduler(void) __attribute__((section(".init"))) void _hal_init(void) { + _hal_sbiInit(); _hal_spinlockInit(); _hal_consoleInit(); diff --git a/hal/riscv64/sbi.c b/hal/riscv64/sbi.c new file mode 100644 index 000000000..e3b20872a --- /dev/null +++ b/hal/riscv64/sbi.c @@ -0,0 +1,141 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * SBI routines (RISCV64) + * + * Copyright 2018, 2020, 2024 Phoenix Systems + * Author: Pawel Pisarczyk, Lukasz Leczkowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include "sbi.h" + +/* Base extension */ +#define SBI_EXT_BASE 0x10 + +#define SBI_BASE_SPEC_VER 0x0 +#define SBI_BASE_IMPL_ID 0x1 +#define SBI_BASE_IMPL_VER 0x2 +#define SBI_BASE_PROBE_EXT 0x3 +#define SBI_BASE_GET_MVENDORID 0x4 +#define SBI_BASE_GET_MARCHID 0x5 +#define SBI_BASE_GET_MIMPLID 0x6 + +/* Timer extension */ +#define SBI_EXT_TIME 0x54494D45 + +#define SBI_TIME_SETTIMER 0x0 + +/* Legacy extensions */ +#define SBI_LEGACY_SETTIMER 0x0 +#define SBI_LEGACY_PUTCHAR 0x1 +#define SBI_LEGACY_GETCHAR 0x2 +#define SBI_LEGACY_CLEARIPI 0x3 +#define SBI_LEGACY_SENDIPI 0x4 +#define SBI_LEGACY_REMOTE_FENCE_I 0x5 +#define SBI_LEGACY_REMOTE_SFENCE_VMA 0x6 +#define SBI_LEGACY_REMOTE_SFENCE_VMA_ASID 0x7 +#define SBI_LEGACY_SHUTDOWN 0x8 + +/* clang-format off */ +#define SBI_MINOR(x) ((x) & 0xffffff) +/* clang-format on */ +#define SBI_MAJOR(x) ((x) >> 24) + + +static struct { + u32 specVersion; + void (*setTimer)(u64); +} sbi_common; + + +static sbiret_t hal_sbiEcall(int ext, int fid, u64 arg0, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5) +{ + sbiret_t ret; + + register u64 a0 asm("a0") = arg0; + register u64 a1 asm("a1") = arg1; + register u64 a2 asm("a2") = arg2; + register u64 a3 asm("a3") = arg3; + register u64 a4 asm("a4") = arg4; + register u64 a5 asm("a5") = arg5; + register u64 a6 asm("a6") = fid; + register u64 a7 asm("a7") = ext; + + /* clang-format off */ + __asm__ volatile ( + "ecall" + : "+r" (a0), "+r" (a1) + : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) + : "memory"); + /* clang-format on */ + + ret.error = a0; + ret.value = a1; + + return ret; +} + +/* Legacy SBI v0.1 calls */ + +static void hal_sbiSetTimerv01(u64 stime) +{ + (void)hal_sbiEcall(SBI_LEGACY_SETTIMER, 0, stime, 0, 0, 0, 0, 0); +} + + +long hal_sbiPutchar(int ch) +{ + return hal_sbiEcall(SBI_LEGACY_PUTCHAR, 0, ch, 0, 0, 0, 0, 0).error; +} + + +long hal_sbiGetchar(void) +{ + return hal_sbiEcall(SBI_LEGACY_GETCHAR, 0, 0, 0, 0, 0, 0, 0).error; +} + +/* SBI v0.2+ calls */ + +sbiret_t hal_sbiGetSpecVersion(void) +{ + return hal_sbiEcall(SBI_EXT_BASE, SBI_BASE_SPEC_VER, 0, 0, 0, 0, 0, 0); +} + + +sbiret_t hal_sbiProbeExtension(long extid) +{ + return hal_sbiEcall(SBI_EXT_BASE, SBI_BASE_PROBE_EXT, extid, 0, 0, 0, 0, 0); +} + + +static void hal_sbiSetTimerv02(u64 stime) +{ + (void)hal_sbiEcall(SBI_EXT_TIME, SBI_TIME_SETTIMER, stime, 0, 0, 0, 0, 0); +} + + +void hal_sbiSetTimer(u64 stime) +{ + sbi_common.setTimer(stime); +} + + +void _hal_sbiInit(void) +{ + sbiret_t ret = hal_sbiGetSpecVersion(); + sbi_common.specVersion = ret.value; + + ret = hal_sbiProbeExtension(SBI_EXT_TIME); + if (ret.error == 0) { + sbi_common.setTimer = hal_sbiSetTimerv02; + } + else { + sbi_common.setTimer = hal_sbiSetTimerv01; + } +} diff --git a/hal/riscv64/sbi.h b/hal/riscv64/sbi.h index 7343387f4..bdb09015d 100644 --- a/hal/riscv64/sbi.h +++ b/hal/riscv64/sbi.h @@ -5,8 +5,8 @@ * * SBI routines (RISCV64) * - * Copyright 2018, 2020 Phoenix Systems - * Author: Pawel Pisarczyk + * Copyright 2018, 2020, 2024 Phoenix Systems + * Author: Pawel Pisarczyk, Lukasz Leczkowski * * This file is part of Phoenix-RTOS. * @@ -19,49 +19,34 @@ #include -#define SBI_SETTIMER 0 -#define SBI_PUTCHAR 1 -#define SBI_GETCHAR 2 -#define SBI_CLEARIPI 3 -#define SBI_SENDIPI 4 -#define SBI_REMOTE_FENCE_I 5 -#define SBI_REMOTE_SFENCE_VMA 6 -#define SBI_REMOTE_SFENCE_VMA_ASID 7 -#define SBI_SHUTDOWN 8 - - -typedef struct _sbiret_t { +typedef struct { long error; long value; } sbiret_t; -static inline sbiret_t sbi_ecall(int ext, int fid, u64 arg0, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5) -{ - sbiret_t ret; - - register u64 a0 asm("a0") = arg0; - register u64 a1 asm("a1") = arg1; - register u64 a2 asm("a2") = arg2; - register u64 a3 asm("a3") = arg3; - register u64 a4 asm("a4") = arg4; - register u64 a5 asm("a5") = arg5; - register u64 a6 asm("a6") = fid; - register u64 a7 asm("a7") = ext; - - /* clang-format off */ - __asm__ volatile ( - "ecall" - : "+r" (a0), "+r" (a1) - : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) - : "memory"); - /* clang-format on */ - - ret.error = a0; - ret.value = a1; - - return ret; -} +/* Legacy SBI v0.1 calls */ + + +long hal_sbiPutchar(int ch); + + +long hal_sbiGetchar(void); + + +/* SBI v0.2+ calls */ + + +sbiret_t hal_sbiGetSpecVersion(void); + + +sbiret_t hal_sbiProbeExtension(long extid); + + +void hal_sbiSetTimer(u64 stime); + + +void _hal_sbiInit(void); #endif diff --git a/hal/riscv64/timer.c b/hal/riscv64/timer.c index c078ae1d2..605d7bfc7 100644 --- a/hal/riscv64/timer.c +++ b/hal/riscv64/timer.c @@ -39,7 +39,7 @@ static int timer_irqHandler(unsigned int n, cpu_context_t *ctx, void *arg) (void)ctx; ++timer_common.jiffies; - sbi_ecall(SBI_SETTIMER, 0, csr_read(time) + timer_common.interval, 0, 0, 0, 0, 0); + hal_sbiSetTimer(csr_read(time) + timer_common.interval); return 0; } @@ -92,5 +92,5 @@ __attribute__((section(".init"))) void _hal_timerInit(u32 interval) timer_common.handler.data = NULL; hal_interruptsSetHandler(&timer_common.handler); - sbi_ecall(SBI_SETTIMER, 0, csr_read(time) + timer_common.interval, 0, 0, 0, 0, 0); + hal_sbiSetTimer(csr_read(time) + timer_common.interval); } diff --git a/syscalls.c b/syscalls.c index 33f81c4f6..27cb68e4b 100644 --- a/syscalls.c +++ b/syscalls.c @@ -1468,7 +1468,7 @@ void syscalls_sbi_putchar(char *ustack) #ifdef __TARGET_RISCV64 char c; GETFROMSTACK(ustack, char, c, 0); - sbi_ecall(SBI_PUTCHAR, 0, c, 0, 0, 0, 0, 0); + (void)hal_sbiPutchar(c); #endif } @@ -1476,9 +1476,7 @@ void syscalls_sbi_putchar(char *ustack) int syscalls_sbi_getchar(char *ustack) { #ifdef __TARGET_RISCV64 - sbiret_t ret; - ret = sbi_ecall(SBI_GETCHAR, 0, 0, 0, 0, 0, 0, 0); - return (int)ret.error; + return (int)hal_sbiGetchar(); #else return -1; #endif From 41a6962879f74667b9c48f2017709de3f6330c8c Mon Sep 17 00:00:00 2001 From: lukileczo Date: Wed, 3 Jan 2024 12:44:51 +0100 Subject: [PATCH 6/7] riscv64: rename status register bits JIRA: RTOS-550 --- hal/riscv64/_init.S | 6 ++---- hal/riscv64/_interrupts.S | 27 ++++++++++----------------- hal/riscv64/arch/cpu.h | 24 +++++++++++------------- hal/riscv64/cpu.c | 4 ++-- 4 files changed, 25 insertions(+), 36 deletions(-) diff --git a/hal/riscv64/_init.S b/hal/riscv64/_init.S index a459d2871..49fadbf7d 100644 --- a/hal/riscv64/_init.S +++ b/hal/riscv64/_init.S @@ -18,8 +18,6 @@ #include #include -#define SR_FS 0x00006000 -#define SR_SUM 0x00040000 #define VADDR_SYSPAGE (_end + SIZE_PAGE - 1) @@ -49,10 +47,10 @@ _start: * Disable FPU to detect illegal usage of * floating point in kernel space */ - li t0, SR_FS + li t0, SSTATUS_FS csrc sstatus, t0 /* Allow supervisor access to user space */ - li t0, SR_SUM + li t0, SSTATUS_SUM csrs sstatus, t0 la t0, hal_syspage /* t0 = &hal_syspage (phy) */ diff --git a/hal/riscv64/_interrupts.S b/hal/riscv64/_interrupts.S index 12e0d416a..f0dfeb12f 100644 --- a/hal/riscv64/_interrupts.S +++ b/hal/riscv64/_interrupts.S @@ -15,13 +15,6 @@ #define __ASSEMBLY__ - -#define SR_SIE 0x00000002 -#define SR_FS 0x00006000 -#define SR_SUM 0x00040000 -#define SR_MXR 0x00080000 - - #include .text @@ -88,13 +81,13 @@ sd sp, 232(sp) /* ksp */ /* Disable FPU */ - li t0, SR_FS + li t0, SSTATUS_FS csrc sstatus, t0 /* Allow supervisor access to user space */ - li t0, SR_SUM + li t0, SSTATUS_SUM csrs sstatus, t0 - csrrc s1, sstatus, SR_SIE + csrrc s1, sstatus, SSTATUS_SIE csrr s2, sepc csrr s3, sbadaddr csrr s4, scause @@ -122,7 +115,7 @@ csrw sscratch, tp ld a0, 240(sp) - andi a0, a0, ~SR_SIE + andi a0, a0, ~SSTATUS_SIE csrw sstatus, a0 ld a2, 248(sp) @@ -170,7 +163,7 @@ _interrupts_dispatch: .align 8 /* Disable interrupts */ - csrc sstatus, SR_SIE + csrc sstatus, SSTATUS_SIE SAVE mv a1, sp @@ -195,10 +188,10 @@ _interrupts_notIrq: mv a0, a7 /* syscall number */ ld a1, 288(sp) /* ustack */ - csrs sstatus, SR_SIE + csrs sstatus, SSTATUS_SIE call syscalls_dispatch sd a0, 56(sp) - csrc sstatus, SR_SIE + csrc sstatus, SSTATUS_SIE j _interrupts_return @@ -216,7 +209,7 @@ _interrupts_return: .global hal_cpuReschedule hal_cpuReschedule: /* Disable interrupts */ - csrc sstatus, SR_SIE + csrc sstatus, SSTATUS_SIE /* Save return address */ csrw sepc, ra @@ -270,7 +263,7 @@ hal_jmp: mv s1, a1 mv s2, a2 mv s3, a3 - csrc sstatus, SR_SIE /* disable interrupts */ + csrc sstatus, SSTATUS_SIE /* disable interrupts */ bnez a2, 2f @@ -292,7 +285,7 @@ hal_jmp: ld a3, (sp) addi sp, sp, 8 1: - csrs sstatus, SR_SIE /* enable interrupts */ + csrs sstatus, SSTATUS_SIE /* enable interrupts */ jr s0 2: diff --git a/hal/riscv64/arch/cpu.h b/hal/riscv64/arch/cpu.h index 2c2bdacd6..6ea7c6fd0 100644 --- a/hal/riscv64/arch/cpu.h +++ b/hal/riscv64/arch/cpu.h @@ -30,11 +30,21 @@ #define SIZE_USTACK (8 * SIZE_PAGE) #endif -/* CSR bits */ +/* Supervisor Cause Register */ #define SCAUSE_INTR (1u << 63) +/* Exception codes */ #define SCAUSE_ECALL 8u /* Environment call from S-mode */ +/* Supervisor Status Register */ +#define SSTATUS_SIE (1u << 1) /* Supervisor Interrupt Enable */ +#define SSTATUS_SPP (1u << 8) /* Previous Supervisor */ +#define SSTATUS_SPIE (1u << 5) /* Previous Supervisor IE */ +#define SSTATUS_FS (3u << 13) /* FPU status */ +#define SSTATUS_SUM (1u << 18) /* Supervisor may access User Memory */ +#define SSTATUS_MXR (1u << 19) /* Make eXecutable Readable */ + + /* Interrupts */ #define CLINT_IRQ_FLG (1u << 31) /* Marks that interrupt handler is installed for CLINT, not PLIC */ @@ -117,18 +127,6 @@ typedef struct { #pragma pack(pop) -/* CSR routines */ - - -#define SR_SIE 0x00000002UL /* Supervisor Interrupt Enable */ -#define SR_SPIE 0x00000020UL /* Previous Supervisor IE */ -#define SR_SPP 0x00000100UL /* Previously Supervisor */ -#define SR_SUM 0x00040000UL /* Supervisor may access User Memory */ - -#define SIE_STIE 0x00000020UL -#define SIE_SEIE 0x00000200UL - - /* interrupts */ diff --git a/hal/riscv64/cpu.c b/hal/riscv64/cpu.c index b93cc1345..aeed520c9 100644 --- a/hal/riscv64/cpu.c +++ b/hal/riscv64/cpu.c @@ -169,12 +169,12 @@ int hal_cpuCreateContext(cpu_context_t **nctx, void *start, void *kstack, size_t if (ustack != NULL) { ctx->sp = (u64)ustack; - ctx->sstatus = csr_read(sstatus) | SR_SPIE | SR_SUM; + ctx->sstatus = csr_read(sstatus) | SSTATUS_SPIE | SSTATUS_SUM; ctx->sscratch = (u64)ctx; ctx->tp = tls->tls_base; } else { - ctx->sstatus = csr_read(sstatus) | SR_SPIE | SR_SPP; + ctx->sstatus = csr_read(sstatus) | SSTATUS_SPIE | SSTATUS_SPP; ctx->sscratch = 0; ctx->tp = 0; } From 46ccb5985fa174859dd4476d0ba755e60237da3e Mon Sep 17 00:00:00 2001 From: lukileczo Date: Wed, 17 Jan 2024 13:39:58 +0100 Subject: [PATCH 7/7] riscv64: refactor kstack handling Modified kstack approach to be the same as on LEON3. Previously kstack wasn't set correctly, resulting in `fork` failure. JIRA: RTOS-550 --- hal/riscv64/_interrupts.S | 53 ++++++++++++++++++++------------------- hal/riscv64/arch/cpu.h | 2 +- hal/riscv64/cpu.c | 13 +++++----- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/hal/riscv64/_interrupts.S b/hal/riscv64/_interrupts.S index f0dfeb12f..b11f62af3 100644 --- a/hal/riscv64/_interrupts.S +++ b/hal/riscv64/_interrupts.S @@ -17,35 +17,44 @@ #include +.extern hal_cpuKernelStack + .text .macro SAVE - /* If coming from userspace, save thread pointer in sscratch and load kernel sp. - * If coming from kernel, sscratch is 0, so we don't swap. + /* Save a0 to sscratch */ + csrw sscratch, a0 + + /* Read sstatus to a0 */ + csrr a0, sstatus + + /* Determine in which mode we were executing before interrupt + * SPP = 0 -> user mode, 1 -> kernel mode */ - csrrw tp, sscratch, tp - bnez tp, 1f + andi a0, a0, 0x100 + beqz a0, 1f - /* Current stack is kernel stack */ + /* Kernel mode */ sd sp, -8(sp) addi sp, sp, -296 j 2f 1: - /* Save context, tp now holds kernel stack pointer. - * Original tp is saved in sscratch + /* User mode + * Load kernel stack pointer from hal_cpuKernelStack */ + ld a0, hal_cpuKernelStack /* Save task's stack pointer */ - sd sp, -8(tp) + sd sp, -8(a0) - /* Swap to current stack */ - addi sp, tp, -296 + /* Swap to kernel stack */ + addi sp, a0, -296 2: - /* restore tp & sscratch */ - csrrw tp, sscratch, tp + /* restore a0 */ + csrr a0, sscratch /* Save context */ sd x1, (sp) /* ra */ @@ -91,28 +100,19 @@ csrr s2, sepc csrr s3, sbadaddr csrr s4, scause - csrr s5, sscratch sd s1, 240(sp) /* sstatus */ sd s2, 248(sp) /* sepc */ sd s3, 256(sp) /* sbadaddr */ sd s4, 264(sp) /* scause */ - sd s5, 272(sp) /* sscratch */ sd tp, 280(sp) /* tp */ - - /* Kernel mode entered */ - csrw sscratch, zero .endm .macro RESTORE /* Switch kernel stack */ ld sp, 232(sp) - ld tp, 272(sp) - - /* Kernel mode left - this loads ksp to sscratch if returning to userspace, else 0 */ - csrw sscratch, tp ld a0, 240(sp) andi a0, a0, ~SSTATUS_SIE @@ -210,6 +210,9 @@ _interrupts_return: hal_cpuReschedule: /* Disable interrupts */ csrc sstatus, SSTATUS_SIE + /* Set SPP to supervisor mode */ + li t0, SSTATUS_SPP + csrs sstatus, t0 /* Save return address */ csrw sepc, ra @@ -230,10 +233,10 @@ hal_cpuReschedule: ld t0, 240(sp) sd zero, 56(sp) - ori t0, t0, 0x100 - andi t1, t0, 0x2 + ori t0, t0, SSTATUS_SPP + andi t1, t0, SSTATUS_SIE sll t1, t1, 4 - andi t0, t0, ~2 + andi t0, t0, ~SSTATUS_SIE or t0, t0, t1 /* Save modified flags in old context */ @@ -289,8 +292,6 @@ hal_jmp: jr s0 2: - csrw sscratch, s1 /* kernel stack pointer */ - mv sp, s2 /* user stack pointer */ addi s3, s3, -1 diff --git a/hal/riscv64/arch/cpu.h b/hal/riscv64/arch/cpu.h index 6ea7c6fd0..d249b7df8 100644 --- a/hal/riscv64/arch/cpu.h +++ b/hal/riscv64/arch/cpu.h @@ -213,7 +213,7 @@ static inline void *hal_cpuGetUserSP(cpu_context_t *ctx) static inline int hal_cpuSupervisorMode(cpu_context_t *ctx) { - return (ctx->sscratch == 0) ? 1 : 0; + return ((ctx->sstatus & SSTATUS_SPP) != 0) ? 1 : 0; } diff --git a/hal/riscv64/cpu.c b/hal/riscv64/cpu.c index aeed520c9..1e4d3f58a 100644 --- a/hal/riscv64/cpu.c +++ b/hal/riscv64/cpu.c @@ -24,6 +24,9 @@ #include "arch/types.h" +ptr_t hal_cpuKernelStack; + + int hal_platformctl(void *ptr) { return EOK; @@ -127,8 +130,8 @@ int hal_cpuCreateContext(cpu_context_t **nctx, void *start, void *kstack, size_t __asm__ volatile("sd gp, %0" : "=m"(ctx->gp)); /* clang-format on */ - ctx->pc = (u64)start; - ctx->sp = (u64)ctx; + ctx->pc = (u64)0; + ctx->sp = (u64)kstack + kstacksz; ctx->t0 = 0; ctx->t1 = 0x0101010101010101; @@ -169,13 +172,11 @@ int hal_cpuCreateContext(cpu_context_t **nctx, void *start, void *kstack, size_t if (ustack != NULL) { ctx->sp = (u64)ustack; - ctx->sstatus = csr_read(sstatus) | SSTATUS_SPIE | SSTATUS_SUM; - ctx->sscratch = (u64)ctx; + ctx->sstatus = (csr_read(sstatus) | SSTATUS_SPIE | SSTATUS_SUM) & ~SSTATUS_SPP; ctx->tp = tls->tls_base; } else { ctx->sstatus = csr_read(sstatus) | SSTATUS_SPIE | SSTATUS_SPP; - ctx->sscratch = 0; ctx->tp = 0; } @@ -216,7 +217,7 @@ void hal_cpuSigreturn(void *kstack, void *ustack, cpu_context_t **ctx) void _hal_cpuSetKernelStack(void *kstack) { - csr_write(sscratch, kstack); + hal_cpuKernelStack = (ptr_t)kstack; }