@@ -491,8 +491,15 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
491491 reg_t page_mask = (reg_t (1 ) << PGSHIFT) - 1 ;
492492 reg_t satp = proc->get_state ()->satp ->readvirt (virt);
493493 vm_info vm = decode_vm_info (proc->get_const_xlen (), false , mode, satp);
494- if (vm.levels == 0 )
494+
495+ // use access flags(shstk) and zicfiss extension as conditions for checking shadow stack
496+ bool check_ss = proc->extension_enabled (EXT_ZICFISS) && access_info.flags .shstk ;
497+
498+ if (vm.levels == 0 ) {
499+ if (check_ss)
500+ trap_store_access_fault (virt, addr, 0 , 0 );
495501 return s2xlate (addr, addr & ((reg_t (2 ) << (proc->xlen -1 ))-1 ), type, type, virt, hlvx, false ) & ~page_mask; // zero-extend from xlen
502+ }
496503
497504 bool s_mode = mode == PRV_S;
498505 bool sum = proc->state .sstatus ->readvirt (virt) & MSTATUS_SUM;
@@ -506,6 +513,9 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
506513 vm.levels = 0 ;
507514
508515 reg_t base = vm.ptbase ;
516+ reg_t vw = PTE_V | PTE_W;
517+ reg_t invalid_pte;
518+
509519 for (int i = vm.levels - 1 ; i >= 0 ; i--) {
510520 int ptshift = i * vm.idxbits ;
511521 reg_t idx = (addr >> (PGSHIFT + ptshift)) & ((1 << vm.idxbits ) - 1 );
@@ -517,6 +527,8 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
517527 bool pbmte = virt ? (proc->get_state ()->henvcfg ->read () & HENVCFG_PBMTE) : (proc->get_state ()->menvcfg ->read () & MENVCFG_PBMTE);
518528 bool hade = virt ? (proc->get_state ()->henvcfg ->read () & HENVCFG_ADUE) : (proc->get_state ()->menvcfg ->read () & MENVCFG_ADUE);
519529
530+ invalid_pte = pte;
531+
520532 if (pte & PTE_RSVD) {
521533 break ;
522534 } else if (!proc->extension_enabled (EXT_SVNAPOT) && (pte & PTE_N)) {
@@ -531,11 +543,23 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
531543 base = ppn << PGSHIFT;
532544 } else if ((pte & PTE_U) ? s_mode && (type == FETCH || !sum) : !s_mode) {
533545 break ;
534- } else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
546+ } else if (!(pte & PTE_V)) {
547+ break ;
548+ } else if (!(pte & PTE_R) && (pte & PTE_W) && !check_ss) {
549+ // allow shadow stack page with R=0, W=1, X=0 permission
550+ break ;
551+ } else if ((type == FETCH || hlvx) && !(pte & PTE_X)) {
535552 break ;
536- } else if (type == FETCH || hlvx ? !(pte & PTE_X) :
537- type == LOAD ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) :
538- !((pte & PTE_R) && (pte & PTE_W))) {
553+ } else if ((type == LOAD) && !(pte & PTE_R) && !(mxr && (pte & PTE_X)) &&
554+ !check_ss) {
555+ // allow ss load page with R=0, W=1, X=0 page
556+ break ;
557+ } else if ((type == STORE) && !((pte & PTE_R) && (pte & PTE_W)) &&
558+ !check_ss) {
559+ // allow ss store page with R=0, W=1, X=0
560+ break ;
561+ } else if (check_ss && ((pte & vw) != vw)) {
562+ // ss load/store page with R=0, W=1, X=0 and valid
539563 break ;
540564 } else if ((ppn & ((reg_t (1 ) << ptshift) - 1 )) != 0 ) {
541565 break ;
@@ -570,10 +594,27 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
570594 }
571595 }
572596
597+ if (check_ss) {
598+ if (!(invalid_pte & PTE_V))
599+ throw trap_store_page_fault (virt, addr, 0 , 0 );
600+ else if (invalid_pte & PTE_W || invalid_pte & PTE_X)
601+ throw trap_store_access_fault (virt, addr, 0 , 0 );
602+ else
603+ throw trap_store_page_fault (virt, addr, 0 , 0 );
604+ }
605+
573606 switch (type) {
574- case FETCH: throw trap_instruction_page_fault (virt, addr, 0 , 0 );
607+ case FETCH: {
608+ if (proc->extension_enabled (EXT_ZICFISS) && ((invalid_pte & vw) == vw))
609+ throw trap_instruction_access_fault (virt, addr, 0 , 0 );
610+ throw trap_instruction_page_fault (virt, addr, 0 , 0 );
611+ }
575612 case LOAD: throw trap_load_page_fault (virt, addr, 0 , 0 );
576- case STORE: throw trap_store_page_fault (virt, addr, 0 , 0 );
613+ case STORE: {
614+ if (proc->extension_enabled (EXT_ZICFISS) && ((invalid_pte & vw) == vw))
615+ throw trap_store_access_fault (virt, addr, 0 , 0 );
616+ throw trap_store_page_fault (virt, addr, 0 , 0 );
617+ }
577618 default : abort ();
578619 }
579620}
0 commit comments