diff --git a/am/src/nemu/isa/riscv/cte.c b/am/src/nemu/isa/riscv/cte.c index 82387f9b..26eb6fe8 100644 --- a/am/src/nemu/isa/riscv/cte.c +++ b/am/src/nemu/isa/riscv/cte.c @@ -111,6 +111,18 @@ void custom_handler_reg(uintptr_t code, _Context*(*handler)(_Event, _Context*)) break; default: printf("Unrecognized code, custom handler reg ignored\n"); + _halt(2); + } +} + +void irq_handler_reg(uintptr_t code, _Context*(*handler)(_Event*, _Context*)) { + uintptr_t offset = (code << 1) >> 1; + if (INTR_BIT & code) { + assert(offset < INTERRUPT_CAUSE_SIZE); + interrupt_handler[offset] = handler; + } else { + assert(offset < EXCEPTION_CAUSE_SIZE); + exception_handler[offset] = handler; } } diff --git a/am/src/nemu/isa/riscv/cte64.c b/am/src/nemu/isa/riscv/cte64.c index 3a012210..65e4cfb9 100644 --- a/am/src/nemu/isa/riscv/cte64.c +++ b/am/src/nemu/isa/riscv/cte64.c @@ -1,6 +1,6 @@ #include #include - +// #include extern void __am_timervec(void); static void init_machine_exception() { @@ -28,16 +28,16 @@ void __am_init_cte64() { asm volatile("csrw medeleg, %0" : : "r"(0xfffb)); // set PMP to access all memory in S-mode - asm volatile("csrw pmpaddr8, %0" : : "r"(-1)); - asm volatile("csrw pmpcfg2, %0" : : "r"(31)); - #include - + // asm volatile("csrw pmpaddr8, %0" : : "r"(-1)); + // asm volatile("csrw pmpcfg2, %0" : : "r"(31)); + + init_pmp(); // protect 0x90000000 + 0x10000 for test purpose enable_pmp(1, 0x90000000, 0x10000, 0, 0); - printf("pmp NA inited\n"); + // printf("pmp NA inited\n"); // protect 0xb00000000 + 0x100 enable_pmp_TOR(4, 0xb0000000, 0x100, 0, 0); - printf("pmp TOR inited\n"); + //printf("pmp TOR inited\n"); init_machine_exception(); init_timer(); diff --git a/am/src/nemu/isa/riscv/vme.c b/am/src/nemu/isa/riscv/vme.c index cdf816d1..89d6dc8d 100644 --- a/am/src/nemu/isa/riscv/vme.c +++ b/am/src/nemu/isa/riscv/vme.c @@ -12,13 +12,13 @@ static int vme_enable = 0; static const _Area segments[] = { // Kernel memory mappings #if defined(__ARCH_RISCV64_NOOP) || defined(__ARCH_RISCV64_XS) - RANGE_LEN(0x80000000, 0x30000), // PMEM - RANGE_LEN(0xc0000000, 0x100000), // page table + RANGE_LEN(0x80000000, 0x8000000), // PMEM RANGE_LEN(0x40600000, 0x1000), // uart RANGE_LEN(CLINT_MMIO, 0x10000), // clint/timer - // RANGE_LEN(FB_ADDR, 0x400000), // vmem - // RANGE_LEN(SCREEN_ADDR,0x1000), // vmem - // RANGE_LEN(0x3c000000, 0x400000), // PLIC + RANGE_LEN(FB_ADDR, 0x400000), // vmem + RANGE_LEN(SCREEN_ADDR,0x1000), // vmem + RANGE_LEN(0x3c000000, 0x4000000), // PLIC + // RANGE_LEN(0xc0000000, 0x100000), // page table test allocates from this position #else NEMU_PADDR_SPACE, #if __riscv_xlen == 64 diff --git a/am/src/xs/include/xs.h b/am/src/xs/include/xs.h index 98a9bbba..3f77acde 100644 --- a/am/src/xs/include/xs.h +++ b/am/src/xs/include/xs.h @@ -14,6 +14,12 @@ void init_timer(); void enable_timer(); void set_timer_inc(uintptr_t inc); +// PMP related driver functions +void init_pmp(); +void enable_pmp(uintptr_t pmp_reg, uintptr_t pmp_addr, uintptr_t pmp_size, uint8_t lock, uint8_t permission); +void enable_pmp_TOR(uintptr_t pmp_reg, uintptr_t pmp_addr, uintptr_t pmp_size, bool lock, uint8_t permission); +void disable_pmp(uintptr_t pmp_reg); + // plic related driver functions uint32_t plic_get_claim(uint32_t current_context); void plic_clear_intr(uint32_t claim); diff --git a/am/src/xs/isa/riscv/pmp.c b/am/src/xs/isa/riscv/pmp.c index fcc8fe29..a793a8b5 100644 --- a/am/src/xs/isa/riscv/pmp.c +++ b/am/src/xs/isa/riscv/pmp.c @@ -172,6 +172,10 @@ void init_pmp() { for (int i = 0; i < PMP_COUNT; i++) { csr_write_num(PMPADDR_BASE + i, -1L); } + // set PMP to access all memory in S-mode + // asm volatile("csrw pmpaddr8, %0" : : "r"(-1)); + asm volatile("csrw pmpcfg2, %0" : : "r"(31)); + asm volatile("sfence.vma"); } @@ -189,11 +193,10 @@ void enable_pmp(uintptr_t pmp_reg, uintptr_t pmp_addr, uintptr_t pmp_size, uint8 uintptr_t set_content = permission | (lock << 7) | (pmp_size == 4 ? 2 : 3) << 3; uintptr_t cfg_offset = pmp_reg > 7 ? 2 : 0; uintptr_t cfg_shift = pmp_reg & 0x7; - printf("addr %llx, cfg offset %d, shift %d, set_content %d\n", pmp_addr, cfg_offset, cfg_shift, set_content); + // printf("addr %llx, cfg offset %d, shift %d, set_content %d\n", pmp_addr, cfg_offset, cfg_shift, set_content); csr_set_num(PMPCFG_BASE + cfg_offset, set_content << (cfg_shift * 8)); asm volatile("sfence.vma"); } -#include void enable_pmp_TOR(uintptr_t pmp_reg, uintptr_t pmp_addr, uintptr_t pmp_size, bool lock, uint8_t permission) { // similar interface but different implementation // pmp reg and pmp reg + 1 will be used @@ -202,13 +205,13 @@ void enable_pmp_TOR(uintptr_t pmp_reg, uintptr_t pmp_addr, uintptr_t pmp_size, b if (pmp_reg) { csr_write_num(PMPADDR_BASE + pmp_reg - 1, pmp_addr >> 2); } - printf("finished writing ADDR\n"); + // printf("finished writing ADDR\n"); uintptr_t set_content = permission | (lock << 7) | (1 << 3); uintptr_t cfg_offset = pmp_reg > 7 ? 2 : 0; uintptr_t cfg_shift = pmp_reg & 0x7; - printf("addr %llx, cfg offset %d, shift %d, set_content %d\n", pmp_addr, cfg_offset, cfg_shift, set_content); + // printf("addr %llx, cfg offset %d, shift %d, set_content %d\n", pmp_addr, cfg_offset, cfg_shift, set_content); csr_set_num(PMPCFG_BASE + cfg_offset, set_content << (cfg_shift * 8)); - printf("finished writing CFG\n"); + // printf("finished writing CFG\n"); asm volatile("sfence.vma"); } diff --git a/tests/amtest/src/main.c b/tests/amtest/src/main.c index 08048f75..5fc20a2d 100644 --- a/tests/amtest/src/main.c +++ b/tests/amtest/src/main.c @@ -15,61 +15,8 @@ static const char *tests[256] = { ['p'] = "x86 virtual memory test", }; -#define PMP_3 - -void pmp_test() { - printf("start pmp test\n"); - #ifdef PMP_1 - volatile int *a = (int *)(0x90000040UL); - *a = 1; // should trigger a fault - #endif - #ifdef PMP_2 - int *b = (int *)(0xa0000000UL); - *b = 1; // should not trigger a fault - #endif - #ifdef PMP_3 - int *c = (int *)(0xb00000040UL); - *c = 1; // should trigger a fault - #endif - asm volatile("ebreak"); -} - - -static char *sv39_alloc_base = (char *)(0xc0000000UL); -static uintptr_t sv39_alloced_size = 0; -void* sv39_pgalloc(size_t pg_size) { - assert(pg_size == 0x1000); - printf("sv39 pgalloc called\n"); - void *ret = (void *)(sv39_alloc_base + sv39_alloced_size); - sv39_alloced_size += pg_size; - return ret; -} -void sv39_pgfree(void *ptr) { - return ; -} -extern _AddressSpace kas; -#include -void sv39_test() { - printf("start sv39 test\n"); - _vme_init(sv39_pgalloc, sv39_pgfree); - printf("sv39 setup done\n"); - _map(&kas, (void *)0x900000000UL, (void *)0x80020000, PTE_R | PTE_A | PTE_D); - _map(&kas, (void *)0xa00000000UL, (void *)0x80020000, PTE_W | PTE_R | PTE_A | PTE_D); - _map(&kas, (void *)0xb00000000UL, (void *)0x80020000, PTE_A | PTE_D); - printf("memory map done\n"); - char *w_ptr = (char *)(0xa00000000UL); - char *r_ptr = (char *)(0x900000000UL); - char *fault_ptr = (char *)(0xb00000000UL); - *w_ptr = 'a'; - printf("sv39 data written\n"); - assert(*r_ptr == 'a'); - printf("triggering fault\n"); - *fault_ptr = 'b'; - printf("should not reach here!\n"); -} - int main(const char *args) { - char arg = 'e'; + char arg = 's'; switch (arg) { CASE('h', hello); CASE('i', hello_intr, IOE, CTE(simple_trap), REEH(simple_trap), RCEH(simple_trap)); diff --git a/tests/amtest/src/tests/pmp.c b/tests/amtest/src/tests/pmp.c new file mode 100644 index 00000000..01b91ff4 --- /dev/null +++ b/tests/amtest/src/tests/pmp.c @@ -0,0 +1,20 @@ +#include + +#define PMP_1 + +void pmp_test() { + printf("start pmp test\n"); + #ifdef PMP_1 + volatile int *a = (int *)(0x90000040UL); + *a = 1; // should trigger a fault + #endif + #ifdef PMP_2 + int *b = (int *)(0xa0000000UL); + *b = 1; // should not trigger a fault + #endif + #ifdef PMP_3 + int *c = (int *)(0xb00000040UL); + *c = 1; // should trigger a fault + #endif + asm volatile("ebreak"); +} \ No newline at end of file diff --git a/tests/amtest/src/tests/sv39.c b/tests/amtest/src/tests/sv39.c new file mode 100644 index 00000000..72638d03 --- /dev/null +++ b/tests/amtest/src/tests/sv39.c @@ -0,0 +1,34 @@ +#include + +static char *sv39_alloc_base = (char *)(0xc0000000UL); +static uintptr_t sv39_alloced_size = 0; +void* sv39_pgalloc(size_t pg_size) { + assert(pg_size == 0x1000); + printf("sv39 pgalloc called\n"); + void *ret = (void *)(sv39_alloc_base + sv39_alloced_size); + sv39_alloced_size += pg_size; + return ret; +} +void sv39_pgfree(void *ptr) { + return ; +} +extern _AddressSpace kas; +#include +void sv39_test() { + printf("start sv39 test\n"); + _vme_init(sv39_pgalloc, sv39_pgfree); + printf("sv39 setup done\n"); + _map(&kas, (void *)0x900000000UL, (void *)0x80020000, PTE_R | PTE_A | PTE_D); + _map(&kas, (void *)0xa00000000UL, (void *)0x80020000, PTE_W | PTE_R | PTE_A | PTE_D); + _map(&kas, (void *)0xb00000000UL, (void *)0x80020000, PTE_A | PTE_D); + printf("memory map done\n"); + char *w_ptr = (char *)(0xa00000000UL); + char *r_ptr = (char *)(0x900000000UL); + char *fault_ptr = (char *)(0xb00000000UL); + *w_ptr = 'a'; + printf("sv39 data written\n"); + assert(*r_ptr == 'a'); + printf("triggering fault\n"); + *fault_ptr = 'b'; + printf("should not reach here!\n"); +}