@@ -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,29 @@ 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' ) && (get_field (state->hstatus ->read (), HSTATUS_HUKTE) == 1 );
583+ return !hstatus_hukte;
584+ }
585+
586+ if (((addr >> SYS_MEM_HEADING_BIT) & 0x1 )) {
587+ return ((state->v || forced_virt) &&
588+ ((proc->get_xlen () == 64 ) ? ((state->vsatp ->read () & SATP64_MODE) == 0 ) :
589+ ((state->vsatp ->read () & SATP32_MODE) == 0 )));
590+ }
591+ }
592+
593+ return true ;
594+ }
595+
563596reg_t mmu_t::walk (mem_access_info_t access_info)
564597{
565598 access_type type = access_info.type ;
@@ -582,6 +615,10 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
582615 if (vm.levels == 0 )
583616 return s2xlate (addr, addr & ((reg_t (2 ) << (proc->xlen -1 ))-1 ), type, type, virt, hlvx, false ) & ~page_mask; // zero-extend from xlen
584617
618+ if (proc->extension_enabled (EXT_SVUKTE) && !check_svukte_qualified (addr, mode, access_info.flags .forced_virt )) {
619+ throw_page_access_exception (virt, addr, type);
620+ }
621+
585622 bool s_mode = mode == PRV_S;
586623 bool sum = proc->state .sstatus ->readvirt (virt) & MSTATUS_SUM;
587624 bool mxr = (proc->state .sstatus ->readvirt (false ) | proc->state .sstatus ->readvirt (virt)) & MSTATUS_MXR;
@@ -672,12 +709,7 @@ reg_t mmu_t::walk(mem_access_info_t access_info)
672709 }
673710 }
674711
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- }
712+ throw_page_access_exception (virt, addr, type);
681713}
682714
683715void mmu_t::register_memtracer (memtracer_t * t)
0 commit comments