diff --git a/am/src/nemu/isa/riscv/cte64.c b/am/src/nemu/isa/riscv/cte64.c index f2e6db6a4026b635d52c8b75eba25b932f178631..b900c24a3112260089902eebfad8b77e13a84f93 100644 --- a/am/src/nemu/isa/riscv/cte64.c +++ b/am/src/nemu/isa/riscv/cte64.c @@ -1,6 +1,6 @@ #include #include -// #include +#include extern void __am_timervec(void); static void init_machine_exception() { @@ -34,11 +34,15 @@ void __am_init_cte64() { init_pmp(); #if defined(__ARCH_RISCV64_NOOP) || defined(__ARCH_RISCV32_NOOP) || defined(__ARCH_RISCV64_XS) // protect 0x90000000 + 0x10000 for test purpose - enable_pmp(1, 0x90000000, 0x10000, 0, 0); + printf("enable_pmp\n"); + enable_pmp(1, 0x90000000, 0x10000, 0, 0); // !rw // printf("pmp NA inited\n"); // protect 0xb00000000 + 0x100 - enable_pmp_TOR(4, 0xb0000000, 0x100, 0, 0); + enable_pmp_TOR(3, 0xb0000000, 0x1000, 0, 0); // !rw //printf("pmp TOR inited\n"); + enable_pmp_TOR(5, 0xb0004000, 0x1000, 0, PMP_R); // r,!w + enable_pmp_TOR(7, 0xb0008000, 0x1000, 0, PMP_W); // !r, w + enable_pmp_TOR(9, 0xb0010000, 0x1000, 0, 0); // !r, w #elif defined(__ARCH_RISCV64_XS_SOUTHLAKE) || defined(__ARCH_RISCV64_XS_SOUTHLAKE_FLASH) // protect 0x210000000 + 0x10000 for test purpose enable_pmp(1, 0x2010000000, 0x10000, 0, 0); diff --git a/am/src/xs/isa/riscv/pmp.c b/am/src/xs/isa/riscv/pmp.c index 3a7300df5476832b623daba5309a7b262b3924e5..0bcd51441d0a663aa3570e79ecb724ac47a3f769 100644 --- a/am/src/xs/isa/riscv/pmp.c +++ b/am/src/xs/isa/riscv/pmp.c @@ -208,7 +208,8 @@ void init_pmp() { } // set PMP to access all memory in S-mode // asm volatile("csrw pmpaddr8, %0" : : "r"(-1)); - asm volatile("csrw pmpcfg2, %0" : : "r"(31)); + // the last pmp pair is used to enable all access (in current case is pmp15) + asm volatile("csrw pmpcfg2, %0" : : "r"((long)31<<(8*7))); asm volatile("sfence.vma"); } diff --git a/tests/amtest/src/tests/pmp.c b/tests/amtest/src/tests/pmp.c index 1691dc352989b8936bb47048d01092959e65f7c7..1f5325e7edfb50f8176f6faf3687b88989188665 100644 --- a/tests/amtest/src/tests/pmp.c +++ b/tests/amtest/src/tests/pmp.c @@ -7,50 +7,191 @@ * You may find related initialzation code in __am_init_cte64() */ -#define PMP_1 - +#define EXCEPTION_LOAD_ACCESS_FAULT 5 #define EXCEPTION_STORE_ACCESS_FAULT 7 -uint64_t access_fault_to_be_reported = 0; +inline int inst_is_compressed(uint64_t addr){ + uint8_t byte = *(uint8_t*)addr; + return (byte & 0x3) != 0x3; +} + +uint64_t store_access_fault_to_be_reported = 0; +uint64_t store_access_fault_reported = 0; +uint64_t load_access_fault_to_be_reported = 0; +uint64_t load_access_fault_reported = 0; -_Context* store_access_fault_handler(_Event* ev, _Context *c) { - printf("store access fault triggered\n"); - if (access_fault_to_be_reported) { - _halt(0); +volatile int result_blackhole = 0; + +void reset_result_flags() { + store_access_fault_to_be_reported = 0; + store_access_fault_reported = 0; + load_access_fault_to_be_reported = 0; + load_access_fault_reported = 0; +} + +void result_check() { + assert(!(store_access_fault_to_be_reported && load_access_fault_to_be_reported)); + if (store_access_fault_to_be_reported) { + if (!store_access_fault_reported || load_access_fault_reported) { + printf("store_access_fault_reported %x, load_access_fault_reported %x\n", + store_access_fault_reported, load_access_fault_reported); + _halt(1); + } + } else if (load_access_fault_to_be_reported) { + if (!load_access_fault_reported || store_access_fault_reported) { + printf("store_access_fault_reported %x, load_access_fault_reported %x\n", + store_access_fault_reported, load_access_fault_reported); + _halt(1); + } } else { - _halt(1); // something went wrong + if (load_access_fault_reported || store_access_fault_reported) { + printf("store_access_fault_reported %x, load_access_fault_reported %x\n", + store_access_fault_reported, load_access_fault_reported); + _halt(1); + } } + // result check passed, reset flags + store_access_fault_to_be_reported = 0; + store_access_fault_reported = 0; + load_access_fault_to_be_reported = 0; + load_access_fault_reported = 0; +} + +_Context* store_access_fault_handler(_Event* ev, _Context *c) { + printf("store access fault triggered, sepc %lx\n", c->sepc); + store_access_fault_reported = 1; + // skip the inst that triggered the exception + c->sepc = inst_is_compressed(c->sepc) ? c->sepc + 2: c->sepc + 4; + // printf("goto %x\n", c->sepc); + return c; +} + +_Context* load_access_fault_handler(_Event* ev, _Context *c) { + printf("load access fault triggered, sepc %lx\n", c->sepc); + load_access_fault_reported = 1; + // skip the inst that triggered the exception + c->sepc = inst_is_compressed(c->sepc) ? c->sepc + 2: c->sepc + 4; + // printf("goto %x\n", c->sepc); return c; } void pmp_test() { irq_handler_reg(EXCEPTION_STORE_ACCESS_FAULT, &store_access_fault_handler); + irq_handler_reg(EXCEPTION_LOAD_ACCESS_FAULT, &load_access_fault_handler); printf("start pmp test\n"); #if defined(__ARCH_RISCV64_NOOP) || defined(__ARCH_RISCV32_NOOP) || defined(__ARCH_RISCV64_XS) - #ifdef PMP_1 - access_fault_to_be_reported = 1; + // Case: store to address protected by pmp + store_access_fault_to_be_reported = 1; volatile int *a = (int *)(0x90000040UL); *a = 1; // should trigger a fault - #endif - #ifdef PMP_2 - access_fault_to_be_reported = 0; + result_check(); + printf("line %d passed\n", __LINE__); + + // Case: store to normal cacheable address int *b = (int *)(0xa0000000UL); *b = 1; // should not trigger a fault - #endif - #ifdef PMP_3 - access_fault_to_be_reported = 1; - int *c = (int *)(0xb00000040UL); + result_check(); + printf("line %d passed\n", __LINE__); + + // Case: store to address protected by pmp tor + store_access_fault_to_be_reported = 1; + int *c = (int *)(0xb0000040UL); *c = 1; // should trigger a fault - #endif + result_check(); + printf("line %d passed\n", __LINE__); + + // Case: load from address protected by pmp + load_access_fault_to_be_reported = 1; + volatile int *d = (int *)(0x90000040UL); + result_blackhole = (*d); // should trigger a fault + result_check(); + printf("line %d passed\n", __LINE__); + + // Case: load from address protected by pmp tor + load_access_fault_to_be_reported = 1; + volatile int *e = (int *)(0xb0000040UL); + result_blackhole = (*e); // should trigger a fault + result_check(); + printf("line %d passed\n", __LINE__); + + // Case: store to address protected by pmp (use pmpcfg2) + store_access_fault_to_be_reported = 1; + int *f = (int *)(0xb0010000UL); + *f = 1; // should trigger a fault + result_check(); + printf("line %d passed\n", __LINE__); + + // Case: lr from address protected by pmp + load_access_fault_to_be_reported = 1; + asm volatile( + "li s4, 0xb0000040;" + "lr.d s5, (s4);" + : + : + :"s4","s5","s6" + ); + result_check(); + printf("line %d passed\n", __LINE__); + + // Case: sc to address protected by pmp + store_access_fault_to_be_reported = 1; + asm volatile( + "li s4, 0xb0000040;" + "sc.d s5, s5, (s4);" + : + : + :"s4","s5","s6" + ); + result_check(); + printf("line %d passed\n", __LINE__); + + // Case: amo to address protected by pmp + store_access_fault_to_be_reported = 1; + asm volatile( + "li s4, 0xb0000040;" + "amoadd.d s5, s6, (s4);" + : + : + :"s4","s5","s6" + ); + result_check(); + printf("line %d passed\n", __LINE__); + + // Case: amo to address protected by pmp (w,!r) + store_access_fault_to_be_reported = 1; + asm volatile( + "li s4, 0xb0008000;" + "amoadd.d s5, s6, (s4);" + : + : + :"s4","s5","s6" + ); + result_check(); + printf("line %d passed\n", __LINE__); + + // Case: amo to address protected by pmp (!w,r) + store_access_fault_to_be_reported = 1; + asm volatile( + "li s4, 0xb0004000;" + "amoadd.d s5, s6, (s4);" + : + : + :"s4","s5","s6" + ); + result_check(); + printf("line %d passed\n", __LINE__); + #elif defined(__ARCH_RISCV64_XS_SOUTHLAKE) || defined(__ARCH_RISCV64_XS_SOUTHLAKE_FLASH) - access_fault_to_be_reported = 0; + // TODO: update pmp test for southlake + store_access_fault_to_be_reported = 0; int *b = (int *)(0x2030000000UL); *b = 1; // should not trigger a fault - access_fault_to_be_reported = 1; + result_check(); + + store_access_fault_to_be_reported = 1; volatile int *a = (int *)(0x2010000040UL); *a = 1; // should trigger a fault - printf("Store access fault not triggered\n"); - _halt(1); + result_check(); #else // invalid arch printf("invalid arch\n"); diff --git a/tests/amtest/src/tests/sv39.c b/tests/amtest/src/tests/sv39.c index 6f4d06925f61542db80dae0acfedccaefbc1f15e..a2df7171bb951585b7b15207d11070022b9e4e18 100644 --- a/tests/amtest/src/tests/sv39.c +++ b/tests/amtest/src/tests/sv39.c @@ -21,7 +21,7 @@ uint64_t page_fault_to_be_reported = 0; inline int inst_is_compressed(uint64_t addr){ uint8_t byte = *(uint8_t*)addr; - return (byte | 0x3) != 0x3; + return (byte & 0x3) != 0x3; } _Context* store_page_fault_handler(_Event* ev, _Context *c) {