提交 f5e7537a 编写于 作者: W William Wang

tests: add riscv64 hugepage-pmp-atom mixed test

上级 926cbae1
......@@ -84,6 +84,9 @@ void _unprotect(_AddressSpace *as);
void _map(_AddressSpace *as, void *va, void *pa, int prot);
_Context *_ucontext(_AddressSpace *as, _Area kstack, void *entry);
// hugepage map for xiangshan testing
void _map_rv_hugepage(_AddressSpace *as, void *va, void *pa, int prot, int pagetable_level);
// ================= Multi-Processor Extension (MPE) =================
int _mpe_init(void (*entry)());
......
......@@ -61,6 +61,7 @@ static inline void *new_page() {
memset(p, 0, PGSIZE);
return p;
}
/*
* Virtual Memory initialize
* pgalloc_f: pointer of page table memory allocater, must return page-aligned address
......@@ -101,12 +102,14 @@ void _protect(_AddressSpace *as) {
void _unprotect(_AddressSpace *as) {
}
/*
* get current satp
*/
void __am_get_cur_as(_Context *c) {
c->pdir = (vme_enable ? (void *)get_satp() : NULL);
}
/*
* switch page table to the given context
*/
......@@ -115,6 +118,7 @@ void __am_switch(_Context *c) {
set_satp(c->pdir);
}
}
/*
* map va to pa with prot permission with page table root as
* Note that RISC-V allow hardware to fault when A and D bit is not set
......@@ -140,6 +144,45 @@ void _map(_AddressSpace *as, void *va, void *pa, int prot) {
}
}
/*
* map va to pa with prot permission with page table root as
* pagetable_level indicates page table level to be used
* 0: basic 4KiB page
* 1: 2MiB megapage
* 2: 1GiB gigapage
* Note that RISC-V allow hardware to fault when A and D bit is not set
*/
void _map_rv_hugepage(_AddressSpace *as, void *va, void *pa, int prot, int pagetable_level) {
int hugepage_size;
switch (pagetable_level) {
case 0: hugepage_size = PGSIZE; break; // 4KiB
case 1: hugepage_size = PGSIZE * 512; break; // 2MiB
case 2: hugepage_size = PGSIZE * 512 * 512; break; // 1GiB
default: assert(0);
}
assert((uintptr_t)va % hugepage_size == 0);
// printf("pa %lx sz %lx\n", pa, hugepage_size);
assert((uintptr_t)pa % hugepage_size == 0);
PTE *pg_base = as->ptr;
PTE *pte;
int level;
for (level = PTW_CONFIG.ptw_level - 1; ; level --) {
pte = &pg_base[VPNi(PTW_CONFIG, (uintptr_t)va, level)];
pg_base = (PTE *)PTE_ADDR(*pte);
if (level == pagetable_level) break;
if (!(*pte & PTE_V)) {
pg_base = new_page();
*pte = PTE_V | (PN(pg_base) << 10);
}
}
int hugepage_pn_shift = pagetable_level * 9;
if (!(*pte & PTE_V)) {
*pte = PTE_V | prot | (PN(pa) >> hugepage_pn_shift << hugepage_pn_shift << 10);
}
printf("map huge page level %d, pte value %lx\n", pagetable_level, *pte);
}
_Context *_ucontext(_AddressSpace *as, _Area kstack, void *entry) {
_Context *c = (_Context*)kstack.end - 1;
......
......@@ -33,6 +33,7 @@ int main(const char *args) {
CASE('p', vm_test, CTE(vm_handler), VME(simple_pgalloc, simple_pgfree));
CASE('c', pmp_test, CTE(simple_trap));
CASE('s', sv39_test, IOE, CTE(simple_trap));
CASE('f', sv39_hp_atom_test, IOE, CTE(simple_trap));
CASE('b', cache_test);
case 'H':
default:
......
......@@ -15,60 +15,60 @@ inline int inst_is_compressed(uint64_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;
volatile uint64_t pmp_store_access_fault_to_be_reported = 0;
volatile uint64_t pmp_store_access_fault_reported = 0;
volatile uint64_t pmp_load_access_fault_to_be_reported = 0;
volatile uint64_t pmp_load_access_fault_reported = 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;
pmp_store_access_fault_to_be_reported = 0;
pmp_store_access_fault_reported = 0;
pmp_load_access_fault_to_be_reported = 0;
pmp_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);
assert(!(pmp_store_access_fault_to_be_reported && pmp_load_access_fault_to_be_reported));
if (pmp_store_access_fault_to_be_reported) {
if (!pmp_store_access_fault_reported || pmp_load_access_fault_reported) {
printf("pmp_store_access_fault_reported %x, pmp_load_access_fault_reported %x\n",
pmp_store_access_fault_reported, pmp_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);
} else if (pmp_load_access_fault_to_be_reported) {
if (!pmp_load_access_fault_reported || pmp_store_access_fault_reported) {
printf("pmp_store_access_fault_reported %x, pmp_load_access_fault_reported %x\n",
pmp_store_access_fault_reported, pmp_load_access_fault_reported);
_halt(1);
}
} else {
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);
if (pmp_load_access_fault_reported || pmp_store_access_fault_reported) {
printf("pmp_store_access_fault_reported %x, pmp_load_access_fault_reported %x\n",
pmp_store_access_fault_reported, pmp_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;
pmp_store_access_fault_to_be_reported = 0;
pmp_store_access_fault_reported = 0;
pmp_load_access_fault_to_be_reported = 0;
pmp_load_access_fault_reported = 0;
}
_Context* store_access_fault_handler(_Event* ev, _Context *c) {
_Context* pmp_store_access_fault_handler(_Event* ev, _Context *c) {
printf("store access fault triggered, sepc %lx\n", c->sepc);
store_access_fault_reported = 1;
pmp_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) {
_Context* pmp_load_access_fault_handler(_Event* ev, _Context *c) {
printf("load access fault triggered, sepc %lx\n", c->sepc);
load_access_fault_reported = 1;
pmp_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);
......@@ -76,12 +76,12 @@ _Context* load_access_fault_handler(_Event* ev, _Context *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);
irq_handler_reg(EXCEPTION_STORE_ACCESS_FAULT, &pmp_store_access_fault_handler);
irq_handler_reg(EXCEPTION_LOAD_ACCESS_FAULT, &pmp_load_access_fault_handler);
printf("start pmp test\n");
#if defined(__ARCH_RISCV64_NOOP) || defined(__ARCH_RISCV32_NOOP) || defined(__ARCH_RISCV64_XS)
// Case: store to address protected by pmp
store_access_fault_to_be_reported = 1;
pmp_store_access_fault_to_be_reported = 1;
volatile int *a = (int *)(0x90000040UL);
*a = 1; // should trigger a fault
result_check();
......@@ -94,35 +94,35 @@ void pmp_test() {
printf("line %d passed\n", __LINE__);
// Case: store to address protected by pmp tor
store_access_fault_to_be_reported = 1;
pmp_store_access_fault_to_be_reported = 1;
int *c = (int *)(0xb0000040UL);
*c = 1; // should trigger a fault
result_check();
printf("line %d passed\n", __LINE__);
// Case: load from address protected by pmp
load_access_fault_to_be_reported = 1;
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;
pmp_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;
pmp_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;
pmp_load_access_fault_to_be_reported = 1;
asm volatile(
"li s4, 0xb0000040;"
"lr.d s5, (s4);"
......@@ -134,7 +134,7 @@ void pmp_test() {
printf("line %d passed\n", __LINE__);
// Case: sc to address protected by pmp
store_access_fault_to_be_reported = 1;
pmp_store_access_fault_to_be_reported = 1;
asm volatile(
"li s4, 0xb0000040;"
"sc.d s5, s5, (s4);"
......@@ -146,7 +146,7 @@ void pmp_test() {
printf("line %d passed\n", __LINE__);
// Case: amo to address protected by pmp
store_access_fault_to_be_reported = 1;
pmp_store_access_fault_to_be_reported = 1;
asm volatile(
"li s4, 0xb0000040;"
"amoadd.d s5, s6, (s4);"
......@@ -158,7 +158,7 @@ void pmp_test() {
printf("line %d passed\n", __LINE__);
// Case: amo to address protected by pmp (w,!r)
store_access_fault_to_be_reported = 1;
pmp_store_access_fault_to_be_reported = 1;
asm volatile(
"li s4, 0xb0008000;"
"amoadd.d s5, s6, (s4);"
......@@ -170,7 +170,7 @@ void pmp_test() {
printf("line %d passed\n", __LINE__);
// Case: amo to address protected by pmp (!w,r)
store_access_fault_to_be_reported = 1;
pmp_store_access_fault_to_be_reported = 1;
asm volatile(
"li s4, 0xb0004000;"
"amoadd.d s5, s6, (s4);"
......@@ -183,12 +183,12 @@ void pmp_test() {
#elif defined(__ARCH_RISCV64_XS_SOUTHLAKE) || defined(__ARCH_RISCV64_XS_SOUTHLAKE_FLASH)
// TODO: update pmp test for southlake
store_access_fault_to_be_reported = 0;
pmp_store_access_fault_to_be_reported = 0;
int *b = (int *)(0x2030000000UL);
*b = 1; // should not trigger a fault
result_check();
store_access_fault_to_be_reported = 1;
pmp_store_access_fault_to_be_reported = 1;
volatile int *a = (int *)(0x2010000040UL);
*a = 1; // should trigger a fault
result_check();
......
......@@ -6,6 +6,8 @@
* RISC-V 64 SV39 Virutal Memory test
*/
#define EXCEPTION_LOAD_ACCESS_FAULT 5
#define EXCEPTION_STORE_ACCESS_FAULT 7
#define EXCEPTION_LOAD_PAGE_FAULT 13
#define EXCEPTION_STORE_PAGE_FAULT 15
......@@ -17,7 +19,11 @@ static char *sv39_alloc_base = (char *)(0x2040000000UL);
// invalid arch
#endif
uint64_t page_fault_to_be_reported = 0;
volatile uint64_t load_page_fault_to_be_reported = 0;
volatile uint64_t store_page_fault_to_be_reported = 0;
volatile uint64_t load_access_fault_to_be_reported = 0;
volatile uint64_t store_access_fault_to_be_reported = 0;
inline int inst_is_compressed(uint64_t addr){
uint8_t byte = *(uint8_t*)addr;
......@@ -26,20 +32,40 @@ inline int inst_is_compressed(uint64_t addr){
_Context* store_page_fault_handler(_Event* ev, _Context *c) {
printf("store page fault triggered\n");
if(!page_fault_to_be_reported){
if(!store_page_fault_to_be_reported){
_halt(1); // something went wrong
}
page_fault_to_be_reported = 0;
store_page_fault_to_be_reported = 0;
c->sepc = inst_is_compressed(c->sepc) ? c->sepc + 2: c->sepc + 4;
return c;
}
_Context* load_page_fault_handler(_Event* ev, _Context *c) {
printf("load page fault triggered\n");
if(!page_fault_to_be_reported){
if(!load_page_fault_to_be_reported){
_halt(1); // something went wrong
}
load_page_fault_to_be_reported = 0;
c->sepc = inst_is_compressed(c->sepc) ? c->sepc + 2: c->sepc + 4;
return c;
}
_Context* load_access_fault_handler(_Event* ev, _Context *c) {
printf("load access fault triggered\n");
if(!load_access_fault_to_be_reported){
_halt(1); // something went wrong
}
page_fault_to_be_reported = 0;
load_access_fault_to_be_reported = 0;
c->sepc = inst_is_compressed(c->sepc) ? c->sepc + 2: c->sepc + 4;
return c;
}
_Context* store_access_fault_handler(_Event* ev, _Context *c) {
printf("store access fault triggered\n");
if(!store_access_fault_to_be_reported){
_halt(1); // something went wrong
}
store_access_fault_to_be_reported = 0;
c->sepc = inst_is_compressed(c->sepc) ? c->sepc + 2: c->sepc + 4;
return c;
}
......@@ -94,17 +120,144 @@ void sv39_test() {
assert(*r_ptr == 'a');
printf("test sv39 store page fault\n");
page_fault_to_be_reported = 1;
*fault_ptr = 'b'; // store: not compressed
if(page_fault_to_be_reported){
store_page_fault_to_be_reported = 1;
*fault_ptr = 'b';
if(store_page_fault_to_be_reported){
_halt(1);
}
printf("test sv39 load page fault\n");
page_fault_to_be_reported = 1;
load_page_fault_to_be_reported = 1;
*w_ptr = *fault_ptr;
if(page_fault_to_be_reported){
if(load_page_fault_to_be_reported){
_halt(1);
}
_halt(0);
}
/*
* RISC-V 64 SV39 Hugepage + Hugepage Atom Inst test
*/
void sv39_hp_atom_test() {
printf("start sv39 hugepage atom test\n");
_vme_init(sv39_pgalloc, sv39_pgfree);
printf("sv39 setup done\n");
#if defined(__ARCH_RISCV64_NOOP) || defined(__ARCH_RISCV32_NOOP) || defined(__ARCH_RISCV64_XS)
_map(&kas, (void *)0x900000000UL, (void *)0x80200000, PTE_R | PTE_A | PTE_D);
// allocate a metapage, not protected by pmp
_map_rv_hugepage(&kas, (void *)0xa00000000UL, (void *)0x80200000, PTE_W | PTE_R | PTE_A | PTE_D, 1);
// allocate a metapage, not protected by pmp, without write perm
_map_rv_hugepage(&kas, (void *)0xb00000000UL, (void *)0x80200000, PTE_R | PTE_A | PTE_D, 1);
// allocate a metapage, not protected by pmp, without read perm
_map_rv_hugepage(&kas, (void *)0xc00000000UL, (void *)0x80200000, PTE_W | PTE_A | PTE_D, 1);
// allocate a metapage, protected by pmp (!rw)
_map_rv_hugepage(&kas, (void *)0xd00000000UL, (void *)0xb0000000, PTE_W | PTE_R | PTE_A | PTE_D, 1);
char *normal_rw_ptr = (char *)(0x900000000UL);
char *hp_rw_ptr = (char *)(0xa00000000UL);
char *hp_r_ptr = (char *)(0xb00000000UL);
char *hp_w_ptr = (char *)(0xc00000000UL);
char *hp_pmp_ptr = (char *)(0xd00000000UL);
printf("memory map done\n");
#elif defined(__ARCH_RISCV64_XS_SOUTHLAKE) || defined(__ARCH_RISCV64_XS_SOUTHLAKE_FLASH)
// TODO
#else
// invalid arch
_halt(1);
#endif
irq_handler_reg(EXCEPTION_STORE_PAGE_FAULT, &store_page_fault_handler);
irq_handler_reg(EXCEPTION_LOAD_PAGE_FAULT, &load_page_fault_handler);
irq_handler_reg(EXCEPTION_STORE_ACCESS_FAULT, &store_access_fault_handler);
irq_handler_reg(EXCEPTION_LOAD_ACCESS_FAULT, &load_access_fault_handler);
printf("test sv39 hugepage data write\n");
*hp_rw_ptr = 'a';
printf("test sv39 hugepage data read\n");
assert(*hp_rw_ptr == 'a');
printf("test sv39 normalpage data read\n");
assert(*normal_rw_ptr == 'a');
printf("test sv39 hugepage store page fault\n");
store_page_fault_to_be_reported = 1;
*hp_r_ptr = 'b';
if(store_page_fault_to_be_reported){
_halt(1);
}
printf("test sv39 hugepage load page fault\n");
load_page_fault_to_be_reported = 1;
*hp_rw_ptr = *hp_w_ptr;
if(load_page_fault_to_be_reported){
_halt(1);
}
printf("test sv39 hugepage store access fault\n");
store_access_fault_to_be_reported = 1;
*hp_pmp_ptr = 'b';
if(store_page_fault_to_be_reported){
_halt(1);
}
printf("test sv39 hugepage load access fault\n");
load_access_fault_to_be_reported = 1;
*hp_rw_ptr = *hp_pmp_ptr;
if(load_access_fault_to_be_reported){
_halt(1);
}
printf("test sv39 hugepage atom store page fault\n");
store_page_fault_to_be_reported = 1;
asm volatile(
"li s4, 0xb00000000;"
"amoadd.d s5, s6, (s4);"
:
:
:"s4","s5","s6"
);
if(store_page_fault_to_be_reported){
_halt(1);
}
printf("test sv39 hugepage atom load page fault\n");
load_page_fault_to_be_reported = 1;
asm volatile(
"li s4, 0xc00000000;"
"lr.d s5, (s4);"
:
:
:"s4","s5","s6"
);
if(load_page_fault_to_be_reported){
_halt(1);
}
printf("test sv39 hugepage atom store access fault\n");
store_access_fault_to_be_reported = 1;
asm volatile(
"li s4, 0xd00000000;"
"amoadd.d s5, s6, (s4);"
:
:
:"s4","s5","s6"
);
if(store_page_fault_to_be_reported){
_halt(1);
}
printf("test sv39 hugepage atom load access fault\n");
load_access_fault_to_be_reported = 1;
asm volatile(
"li s4, 0xd00000000;"
"lr.d s5, (s4);"
:
:
:"s4","s5","s6"
);
if(load_access_fault_to_be_reported){
_halt(1);
}
_halt(0);
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册