@@ -127,6 +127,27 @@ Xlen Core::get_xlen() const {
127127
128128void Core::set_current_privilege (CSR::PrivilegeLevel privilege) {
129129 state.set_current_privilege (privilege);
130+ const unsigned PRIV_BITS = unsigned (IMF_PRIV_M) | unsigned (IMF_PRIV_H) | unsigned (IMF_PRIV_S);
131+
132+ InstructionFlags base_mask = InstructionFlags (unsigned (check_inst_flags_mask) & ~PRIV_BITS);
133+ InstructionFlags base_val = InstructionFlags (unsigned (check_inst_flags_val) & ~PRIV_BITS);
134+
135+ unsigned allowed_priv = 0 ;
136+ if (privilege >= CSR::PrivilegeLevel::SUPERVISOR) {
137+ allowed_priv |= unsigned (IMF_PRIV_S);
138+ }
139+ if (privilege >= CSR::PrivilegeLevel::HYPERVISOR) {
140+ allowed_priv |= unsigned (IMF_PRIV_H);
141+ }
142+ if (privilege >= CSR::PrivilegeLevel::MACHINE) {
143+ allowed_priv |= unsigned (IMF_PRIV_M);
144+ }
145+ unsigned disallowed_priv = (PRIV_BITS & ~allowed_priv);
146+ InstructionFlags new_mask = InstructionFlags (unsigned (base_mask) | disallowed_priv);
147+ InstructionFlags new_val = base_val;
148+
149+ check_inst_flags_mask = new_mask;
150+ check_inst_flags_val = new_val;
130151}
131152
132153CSR::PrivilegeLevel Core::get_current_privilege () const {
@@ -317,7 +338,18 @@ DecodeState Core::decode(const FetchInterstage &dt) {
317338 ExceptionCause excause = dt.excause ;
318339
319340 dt.inst .flags_alu_op_mem_ctl (flags, alu_op, mem_ctl);
320-
341+ CSR::PrivilegeLevel inst_xret_priv = CSR::PrivilegeLevel::UNPRIVILEGED;
342+ if (flags & IMF_XRET) {
343+ if (flags & IMF_PRIV_M) {
344+ inst_xret_priv = CSR::PrivilegeLevel::MACHINE;
345+ } else if (flags & IMF_PRIV_H) {
346+ inst_xret_priv = CSR::PrivilegeLevel::HYPERVISOR;
347+ } else if (flags & IMF_PRIV_S) {
348+ inst_xret_priv = CSR::PrivilegeLevel::SUPERVISOR;
349+ } else {
350+ inst_xret_priv = CSR::PrivilegeLevel::UNPRIVILEGED;
351+ }
352+ }
321353 if ((flags ^ check_inst_flags_val) & check_inst_flags_mask) { excause = EXCAUSE_INSN_ILLEGAL; }
322354
323355 RegisterId num_rs = (flags & (IMF_ALU_REQ_RS | IMF_ALU_RS_ID)) ? dt.inst .rs () : 0 ;
@@ -333,7 +365,7 @@ DecodeState Core::decode(const FetchInterstage &dt) {
333365
334366 CSR::Address csr_address = (flags & IMF_CSR) ? dt.inst .csr_address () : CSR::Address (0 );
335367 RegisterValue csr_read_val
336- = ((control_state != nullptr && (flags & IMF_CSR))) ? control_state->read (csr_address) : 0 ;
368+ = ((control_state != nullptr && (flags & IMF_CSR))) ? control_state->read (csr_address, get_current_privilege () ) : 0 ;
337369 bool csr_write = (flags & IMF_CSR) && (!(flags & IMF_CSR_TO_ALU) || (num_rs != 0 ));
338370
339371 if ((flags & IMF_EXCEPTION) && (excause == EXCAUSE_NONE)) {
@@ -393,6 +425,7 @@ DecodeState Core::decode(const FetchInterstage &dt) {
393425 .csr_to_alu = bool (flags & IMF_CSR_TO_ALU),
394426 .csr_write = csr_write,
395427 .xret = bool (flags & IMF_XRET),
428+ .xret_privlev = inst_xret_priv,
396429 .insert_stall_before = bool (flags & IMF_CSR) } };
397430}
398431
@@ -463,6 +496,7 @@ ExecuteState Core::execute(const DecodeInterstage &dt) {
463496 .csr = dt.csr ,
464497 .csr_write = dt.csr_write ,
465498 .xret = dt.xret ,
499+ .xret_privlev = dt.xret_privlev ,
466500 } };
467501}
468502
@@ -523,11 +557,12 @@ MemoryState Core::memory(const ExecuteInterstage &dt) {
523557 if (control_state != nullptr && dt.is_valid && dt.excause == EXCAUSE_NONE) {
524558 control_state->increment_internal (CSR::Id::MINSTRET, 1 );
525559 if (dt.csr_write ) {
526- control_state->write (dt.csr_address , dt.alu_val );
560+ control_state->write (dt.csr_address , dt.alu_val , get_current_privilege () );
527561 csr_written = true ;
528562 }
529563 if (dt.xret ) {
530- CSR::PrivilegeLevel restored = control_state->exception_return (get_current_privilege ());
564+ CSR::PrivilegeLevel restored =
565+ control_state->exception_return (get_current_privilege (), dt.xret_privlev );
531566 set_current_privilege (restored);
532567 if (this ->xlen == Xlen::_32)
533568 computed_next_inst_addr
@@ -577,6 +612,7 @@ MemoryState Core::memory(const ExecuteInterstage &dt) {
577612 .regwrite = regwrite,
578613 .is_valid = dt.is_valid ,
579614 .csr_written = csr_written,
615+ .xret_privlev = dt.xret_privlev ,
580616 } };
581617}
582618
0 commit comments