From 67699be876bd5afe4fc7ddf48b7363871120de0b Mon Sep 17 00:00:00 2001 From: Zihao Yu Date: Tue, 15 Nov 2022 15:24:49 +0800 Subject: [PATCH] am: add loongarch32r-nemu --- am/include/arch/loongarch32r-nemu.h | 16 +++++++++ am/src/loongarch/loongarch32r.h | 24 ++++++++++++++ am/src/loongarch/nemu/cte.c | 47 +++++++++++++++++++++++++++ am/src/loongarch/nemu/start.S | 8 +++++ am/src/loongarch/nemu/trap.S | 50 +++++++++++++++++++++++++++++ am/src/loongarch/nemu/vme.c | 42 ++++++++++++++++++++++++ am/src/platform/nemu/include/nemu.h | 2 ++ scripts/isa/loongarch32r.mk | 4 +++ scripts/loongarch32r-nemu.mk | 8 +++++ 9 files changed, 201 insertions(+) create mode 100644 am/include/arch/loongarch32r-nemu.h create mode 100644 am/src/loongarch/loongarch32r.h create mode 100644 am/src/loongarch/nemu/cte.c create mode 100644 am/src/loongarch/nemu/start.S create mode 100644 am/src/loongarch/nemu/trap.S create mode 100644 am/src/loongarch/nemu/vme.c create mode 100644 scripts/isa/loongarch32r.mk create mode 100644 scripts/loongarch32r-nemu.mk diff --git a/am/include/arch/loongarch32r-nemu.h b/am/include/arch/loongarch32r-nemu.h new file mode 100644 index 0000000..b0a753b --- /dev/null +++ b/am/include/arch/loongarch32r-nemu.h @@ -0,0 +1,16 @@ +#ifndef __ARCH_H__ +#define __ARCH_H__ + +struct Context { + // TODO: fix the order of these members to match trap.S + uintptr_t gpr[32], era, estat, prmd; + void *pdir; +}; + +#define GPR1 gpr[11] // a7 +#define GPR2 gpr[0] +#define GPR3 gpr[0] +#define GPR4 gpr[0] +#define GPRx gpr[0] + +#endif diff --git a/am/src/loongarch/loongarch32r.h b/am/src/loongarch/loongarch32r.h new file mode 100644 index 0000000..49147b7 --- /dev/null +++ b/am/src/loongarch/loongarch32r.h @@ -0,0 +1,24 @@ +#ifndef LOONGARCH32R_H__ +#define LOONGARCH32R_H__ + +#include + +static inline uint8_t inb(uintptr_t addr) { return *(volatile uint8_t *)addr; } +static inline uint16_t inw(uintptr_t addr) { return *(volatile uint16_t *)addr; } +static inline uint32_t inl(uintptr_t addr) { return *(volatile uint32_t *)addr; } + +static inline void outb(uintptr_t addr, uint8_t data) { *(volatile uint8_t *)addr = data; } +static inline void outw(uintptr_t addr, uint16_t data) { *(volatile uint16_t *)addr = data; } +static inline void outl(uintptr_t addr, uint32_t data) { *(volatile uint32_t *)addr = data; } + +#define PTE_V 0x1 +#define PTE_D 0x2 + +// Page directory and page table constants +#define PTXSHFT 12 // Offset of PTX in a linear address +#define PDXSHFT 22 // Offset of PDX in a linear address + +#define PDX(va) (((uint32_t)(va) >> PDXSHFT) & 0x3ff) +#define PTX(va) (((uint32_t)(va) >> PTXSHFT) & 0x3ff) + +#endif diff --git a/am/src/loongarch/nemu/cte.c b/am/src/loongarch/nemu/cte.c new file mode 100644 index 0000000..ca82de9 --- /dev/null +++ b/am/src/loongarch/nemu/cte.c @@ -0,0 +1,47 @@ +#include +#include +#include + +static Context* (*user_handler)(Event, Context*) = NULL; + +Context* __am_irq_handle(Context *c) { + if (user_handler) { + Event ev = {0}; + uintptr_t ecode = 0; + switch (ccode) { + default: ev.event = EVENT_ERROR; break; + } + + c = user_handler(ev, c); + assert(c != NULL); + } + + return c; +} + +extern void __am_asm_trap(void); + +bool cte_init(Context*(*handler)(Event, Context*)) { + // initialize exception entry + asm volatile("csrwr %0, 0xc" : : "r"(__am_asm_trap)); // 0xc = eentry + + // register event handler + user_handler = handler; + + return true; +} + +Context *kcontext(Area kstack, void (*entry)(void *), void *arg) { + return NULL; +} + +void yield() { + asm volatile("li.w $a7, -1; syscall 0"); +} + +bool ienabled() { + return false; +} + +void iset(bool enable) { +} diff --git a/am/src/loongarch/nemu/start.S b/am/src/loongarch/nemu/start.S new file mode 100644 index 0000000..56341a2 --- /dev/null +++ b/am/src/loongarch/nemu/start.S @@ -0,0 +1,8 @@ +.section entry, "ax" +.globl _start +.type _start, @function + +_start: + move $fp, $zero + la.local $sp, _stack_pointer + bl _trm_init diff --git a/am/src/loongarch/nemu/trap.S b/am/src/loongarch/nemu/trap.S new file mode 100644 index 0000000..e02f7fc --- /dev/null +++ b/am/src/loongarch/nemu/trap.S @@ -0,0 +1,50 @@ +#define concat_temp(x, y) x ## y +#define concat(x, y) concat_temp(x, y) +#define MAP(c, f) c(f) + +#define REGS(f) \ + f( 1) f( 2) f( 4) f( 5) f( 6) f( 7) f( 8) f( 9) \ +f(10) f(11) f(12) f(13) f(14) f(15) f(16) f(17) f(18) f(19) \ +f(20) f(21) f(22) f(23) f(24) f(25) f(26) f(27) f(28) f(29) \ +f(30) f(31) + +#define PUSH(n) st.w $concat(r, n), $sp, (n * 4); +#define POP(n) ld.w $concat(r, n), $sp, (n * 4); + +#define CONTEXT_SIZE ((32 + 3) * 4) +#define OFFSET_SP ( 3 * 4) +#define OFFSET_ESTAT (32 * 4) +#define OFFSET_PRMD (33 * 4) +#define OFFSET_ERA (34 * 4) + +#define CSR_ESTAT 0x5 +#define CSR_PRMD 0x1 +#define CSR_ERA 0x6 + +.align 6 +.globl __am_asm_trap +__am_asm_trap: + addi.w $sp, $sp, -CONTEXT_SIZE + + MAP(REGS, PUSH) + + csrrd $t0, CSR_ESTAT + csrrd $t1, CSR_PRMD + csrrd $t2, CSR_ERA + + st.w $t0, $sp, OFFSET_ESTAT + st.w $t1, $sp, OFFSET_PRMD + st.w $t2, $sp, OFFSET_ERA + + move $a0, $sp + bl __am_irq_handle + + ld.w $t1, $sp, OFFSET_PRMD + ld.w $t2, $sp, OFFSET_ERA + csrwr $t1, CSR_PRMD + csrwr $t2, CSR_ERA + + MAP(REGS, POP) + + addi.w $sp, $sp, CONTEXT_SIZE + ertn diff --git a/am/src/loongarch/nemu/vme.c b/am/src/loongarch/nemu/vme.c new file mode 100644 index 0000000..88c0211 --- /dev/null +++ b/am/src/loongarch/nemu/vme.c @@ -0,0 +1,42 @@ +#include +#include + +#define USER_SPACE RANGE(0x40000000, 0x80000000) + +static void* (*pgalloc_usr)(int) = NULL; +static void (*pgfree_usr)(void*) = NULL; +static int vme_enable = 0; +static PTE *cur_pdir = NULL; + +bool vme_init(void* (*pgalloc_f)(int), void (*pgfree_f)(void*)) { + pgalloc_usr = pgalloc_f; + pgfree_usr = pgfree_f; + vme_enable = 1; + return true; +} + +void protect(AddrSpace *as) { + as->ptr = (PTE*)(pgalloc_usr(PGSIZE)); + as->pgsize = PGSIZE; + as->area = USER_SPACE; +} + +void unprotect(AddrSpace *as) { +} + +void __am_get_cur_as(Context *c) { + c->pdir = (vme_enable ? cur_pdir : NULL); +} + +void __am_switch(Context *c) { + if (vme_enable && c->pdir != NULL) { + cur_pdir = c->pdir; + } +} + +void map(AddrSpace *as, void *va, void *pa, int prot) { +} + +Context *ucontext(AddrSpace *as, Area kstack, void *entry) { + return NULL; +} diff --git a/am/src/platform/nemu/include/nemu.h b/am/src/platform/nemu/include/nemu.h index b2fa83d..a4543ca 100644 --- a/am/src/platform/nemu/include/nemu.h +++ b/am/src/platform/nemu/include/nemu.h @@ -12,6 +12,8 @@ # define nemu_trap(code) asm volatile ("move $v0, %0; sdbbp" : :"r"(code)) #elif defined(__ISA_RISCV32__) || defined(__ISA_RISCV64__) # define nemu_trap(code) asm volatile("mv a0, %0; ebreak" : :"r"(code)) +#elif defined(__ISA_LOONGARCH32R__) +# define nemu_trap(code) asm volatile("move $a0, %0; break 0" : :"r"(code)) #elif # error unsupported ISA __ISA__ #endif diff --git a/scripts/isa/loongarch32r.mk b/scripts/isa/loongarch32r.mk new file mode 100644 index 0000000..48af70a --- /dev/null +++ b/scripts/isa/loongarch32r.mk @@ -0,0 +1,4 @@ +CROSS_COMPILE := loongarch32r-linux-gnusf- +COMMON_FLAGS := -fno-pic +CFLAGS += $(COMMON_FLAGS) -static +ASFLAGS += $(COMMON_FLAGS) -O0 diff --git a/scripts/loongarch32r-nemu.mk b/scripts/loongarch32r-nemu.mk new file mode 100644 index 0000000..906e7c2 --- /dev/null +++ b/scripts/loongarch32r-nemu.mk @@ -0,0 +1,8 @@ +include $(AM_HOME)/scripts/isa/loongarch32r.mk +include $(AM_HOME)/scripts/platform/nemu.mk +CFLAGS += -DISA_H=\"loongarch/loongarch32r.h\" + +AM_SRCS += loongarch/nemu/start.S \ + loongarch/nemu/cte.c \ + loongarch/nemu/trap.S \ + loongarch/nemu/vme.c