@@ -53,6 +53,16 @@ void throw_access_exception(bool virt, reg_t addr, access_type type)
5353 }
5454}
5555
56+ [[noreturn]] void throw_page_access_exception (bool virt, reg_t addr, access_type type)
57+ {
58+ switch (type) {
59+ case FETCH: throw trap_instruction_page_fault (virt, addr, 0 , 0 );
60+ case LOAD: throw trap_load_page_fault (virt, addr, 0 , 0 );
61+ case STORE: throw trap_store_page_fault (virt, addr, 0 , 0 );
62+ default : abort ();
63+ }
64+ }
65+
5666reg_t mmu_t::translate (mem_access_info_t access_info, reg_t len)
5767{
5868 reg_t addr = access_info.transformed_vaddr ;
@@ -560,6 +570,35 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty
560570 }
561571}
562572
573+ bool mmu_t::check_svukte_qualified (reg_t addr, reg_t mode, bool forced_virt)
574+ {
575+ state_t * state = proc->get_state ();
576+
577+ if (mode != PRV_U)
578+ return true ;
579+
580+ if (proc->extension_enabled (' S' ) && get_field (state->senvcfg ->read (), SENVCFG_UKTE)) {
581+ if (forced_virt && state->prv == PRV_U) {
582+ bool hstatus_hukte = proc->extension_enabled (' H' ) &&
583+ (get_field (state->hstatus ->read (), HSTATUS_HUKTE) == 1 );
584+ if (!hstatus_hukte)
585+ return true ;
586+ }
587+
588+ if (((addr >> SYS_MEM_HEADING_BIT) & 0x1 )) {
589+ if ((state->v || forced_virt) &&
590+ ((proc->get_xlen () == 64 ) ? ((state->vsatp ->read () & SATP64_MODE) == 0 ) :
591+ ((state->vsatp ->read () & SATP32_MODE) == 0 ))) {
592+ return true ;
593+ } else {
594+ return false ;
595+ }
596+ }
597+ }
598+
599+ return true ;
600+ }
601+
563602reg_t mmu_t::walk (mem_access_info_t access_info)
564603{
565604 access_type type = access_info.type ;
@@ -582,6 +621,10 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
582621 if (vm.levels == 0 )
583622 return s2xlate (addr, addr & ((reg_t (2 ) << (proc->xlen -1 ))-1 ), type, type, virt, hlvx, false ) & ~page_mask; // zero-extend from xlen
584623
624+ if (proc->extension_enabled (EXT_SVUKTE) && !check_svukte_qualified (addr, mode, access_info.flags .forced_virt )) {
625+ throw_page_access_exception (virt, addr, type);
626+ }
627+
585628 bool s_mode = mode == PRV_S;
586629 bool sum = proc->state .sstatus ->readvirt (virt) & MSTATUS_SUM;
587630 bool mxr = (proc->state .sstatus ->readvirt (false ) | proc->state .sstatus ->readvirt (virt)) & MSTATUS_MXR;
@@ -672,12 +715,7 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
672715 }
673716 }
674717
675- switch (type) {
676- case FETCH: throw trap_instruction_page_fault (virt, addr, 0 , 0 );
677- case LOAD: throw trap_load_page_fault (virt, addr, 0 , 0 );
678- case STORE: throw trap_store_page_fault (virt, addr, 0 , 0 );
679- default : abort ();
680- }
718+ throw_page_access_exception (virt, addr, type);
681719}
682720
683721void mmu_t::register_memtracer (memtracer_t * t)
0 commit comments