diff --git a/am/include/arch/riscv64-nemu.h b/am/include/arch/riscv64-nemu.h new file mode 100644 index 0000000..f750221 --- /dev/null +++ b/am/include/arch/riscv64-nemu.h @@ -0,0 +1,15 @@ +#ifndef ARCH_H__ +#define ARCH_H__ + +struct Context { + uintptr_t epc, cause, gpr[32], status; + void *pdir; +}; + +#define GPR1 gpr[17] // a7 +#define GPR2 gpr[0] +#define GPR3 gpr[0] +#define GPR4 gpr[0] +#define GPRx gpr[0] + +#endif diff --git a/am/src/nemu/include/nemu.h b/am/src/nemu/include/nemu.h index d629db3..1753f0d 100644 --- a/am/src/nemu/include/nemu.h +++ b/am/src/nemu/include/nemu.h @@ -9,7 +9,7 @@ # define nemu_trap(code) asm volatile (".byte 0xd6" : :"a"(code)) #elif defined(__ISA_MIPS32__) # define nemu_trap(code) asm volatile ("move $v0, %0; .word 0xf0000000" : :"r"(code)) -#elif defined(__ISA_RISCV32__) +#elif defined(__ISA_RISCV32__) || defined(__ISA_RISCV64__) # define nemu_trap(code) asm volatile("mv a0, %0; .word 0x0000006b" : :"r"(code)) #elif # error unsupported ISA __ISA__ diff --git a/am/src/nemu/isa/riscv64/boot/loader.ld b/am/src/nemu/isa/riscv64/boot/loader.ld new file mode 100644 index 0000000..2167b76 --- /dev/null +++ b/am/src/nemu/isa/riscv64/boot/loader.ld @@ -0,0 +1,4 @@ +_pmem_start = 0x80000000; + +/* at $(AM_HOME)/am/src/nemu/scripts/section.ld */ +INCLUDE "section.ld" diff --git a/am/src/nemu/isa/riscv64/boot/start.S b/am/src/nemu/isa/riscv64/boot/start.S new file mode 100644 index 0000000..3e56e5c --- /dev/null +++ b/am/src/nemu/isa/riscv64/boot/start.S @@ -0,0 +1,8 @@ +.section entry, "ax" +.globl _start +.type _start, @function + +_start: + mv s0, zero + la sp, _stack_pointer + jal _trm_init diff --git a/am/src/nemu/isa/riscv64/cte.c b/am/src/nemu/isa/riscv64/cte.c new file mode 100644 index 0000000..d85179d --- /dev/null +++ b/am/src/nemu/isa/riscv64/cte.c @@ -0,0 +1,46 @@ +#include +#include +#include + +static Context* (*user_handler)(Event, Context*) = NULL; + +Context* __am_irq_handle(Context *c) { + if (user_handler) { + Event ev = {0}; + switch (c->cause) { + 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("csrw stvec, %0" : : "r"(__am_asm_trap)); + + // register event handler + user_handler = handler; + + return true; +} + +Context *kcontext(Area kstack, void (*entry)(void *), void *arg) { + return NULL; +} + +void yield() { + asm volatile("li a7, -1; ecall"); +} + +bool ienabled() { + return false; +} + +void iset(bool enable) { +} diff --git a/am/src/nemu/isa/riscv64/trap.S b/am/src/nemu/isa/riscv64/trap.S new file mode 100644 index 0000000..4ebe376 --- /dev/null +++ b/am/src/nemu/isa/riscv64/trap.S @@ -0,0 +1,51 @@ + +#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( 3) 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) sd concat(x, n), (n * 8)(sp); +#define POP(n) ld concat(x, n), (n * 8)(sp); + +#define CONTEXT_SIZE ((32 + 3) * 8) +#define OFFSET_SP ( 2 * 8) +#define OFFSET_CAUSE (32 * 8) +#define OFFSET_STATUS (33 * 8) +#define OFFSET_EPC (34 * 8) + +.globl __am_asm_trap +__am_asm_trap: + addi sp, sp, -CONTEXT_SIZE + + MAP(REGS, PUSH) + + mv t0, sp + addi t0, t0, CONTEXT_SIZE + sd t0, OFFSET_SP(sp) + + csrr t0, scause + csrr t1, sstatus + csrr t2, sepc + + sd t0, OFFSET_CAUSE(sp) + sd t1, OFFSET_STATUS(sp) + sd t2, OFFSET_EPC(sp) + + mv a0, sp + jal __am_irq_handle + + ld t1, OFFSET_STATUS(sp) + ld t2, OFFSET_EPC(sp) + csrw sstatus, t1 + csrw sepc, t2 + + MAP(REGS, POP) + + addi sp, sp, CONTEXT_SIZE + + sret diff --git a/am/src/nemu/isa/riscv64/vme.c b/am/src/nemu/isa/riscv64/vme.c new file mode 100644 index 0000000..361c16a --- /dev/null +++ b/am/src/nemu/isa/riscv64/vme.c @@ -0,0 +1,74 @@ +#include +#include +#include + +static AddrSpace kas = {}; +static void* (*pgalloc_usr)(int) = NULL; +static void (*pgfree_usr)(void*) = NULL; +static int vme_enable = 0; + +static Area segments[] = { // Kernel memory mappings + NEMU_PADDR_SPACE +}; + +#define USER_SPACE RANGE(0x40000000, 0x80000000) + +static inline void set_satp(void *pdir) { + uintptr_t mode = 8ull << 60; + asm volatile("csrw satp, %0" : : "r"(mode | ((uintptr_t)pdir >> 12))); +} + +static inline uintptr_t get_satp() { + uintptr_t satp; + asm volatile("csrr %0, satp" : "=r"(satp)); + return satp << 12; +} + +bool vme_init(void* (*pgalloc_f)(int), void (*pgfree_f)(void*)) { + pgalloc_usr = pgalloc_f; + pgfree_usr = pgfree_f; + + kas.ptr = pgalloc_f(PGSIZE); + + int i; + for (i = 0; i < LENGTH(segments); i ++) { + void *va = segments[i].start; + for (; va < segments[i].end; va += PGSIZE) { + map(&kas, va, va, 0); + } + } + + set_satp(kas.ptr); + vme_enable = 1; + + return true; +} + +void protect(AddrSpace *as) { + PTE *updir = (PTE*)(pgalloc_usr(PGSIZE)); + as->ptr = updir; + as->area = USER_SPACE; + as->pgsize = PGSIZE; + // map kernel space + memcpy(updir, kas.ptr, PGSIZE); +} + +void unprotect(AddrSpace *as) { +} + +void __am_get_cur_as(Context *c) { + c->pdir = (vme_enable ? (void *)get_satp() : NULL); +} + +void __am_switch(Context *c) { + if (vme_enable && c->pdir != NULL) { + set_satp(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/nemu/mpe.c b/am/src/nemu/mpe.c index df21f97..6715aa2 100644 --- a/am/src/nemu/mpe.c +++ b/am/src/nemu/mpe.c @@ -12,6 +12,6 @@ int cpu_current() { return 0; } -int atomic_xchg(int *addr, intptr_t newval) { +int atomic_xchg(int *addr, int newval) { return 0; } diff --git a/am/src/riscv64.h b/am/src/riscv64.h new file mode 100644 index 0000000..398fe0f --- /dev/null +++ b/am/src/riscv64.h @@ -0,0 +1,20 @@ +#ifndef RISCV64_H__ +#define RISCV64_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 0x01 +#define PTE_R 0x02 +#define PTE_W 0x04 +#define PTE_X 0x08 +#define PTE_U 0x10 + +#endif diff --git a/scripts/isa/riscv64.mk b/scripts/isa/riscv64.mk new file mode 100644 index 0000000..fe562a0 --- /dev/null +++ b/scripts/isa/riscv64.mk @@ -0,0 +1,5 @@ +CROSS_COMPILE := riscv64-linux-gnu- +COMMON_FLAGS := -fno-pic -march=rv64g -mcmodel=medany +CFLAGS += $(COMMON_FLAGS) -static +ASFLAGS += $(COMMON_FLAGS) -O0 +LDFLAGS += -melf64lriscv diff --git a/scripts/riscv64-nemu.mk b/scripts/riscv64-nemu.mk new file mode 100644 index 0000000..cb53263 --- /dev/null +++ b/scripts/riscv64-nemu.mk @@ -0,0 +1,2 @@ +include $(AM_HOME)/scripts/isa/riscv64.mk +include $(AM_HOME)/scripts/platform/nemu.mk