mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
[Priv modes] Add support for U-Mode
- General changes to suport U-mode (fixes #88) - Update documentation - Add priv mode flops to CSRs module - Propagate correct priv mode to PMP module - Implement CSR priv-mode permission checking - Implement illegal U-mode instruction checking - Add extra mstatus bits for U-mode (MPRV and TW)
This commit is contained in:
parent
f54dfe5d4b
commit
2aacd2b98b
10 changed files with 129 additions and 37 deletions
|
@ -90,18 +90,24 @@ Reset Value: ``0x0000_1800``
|
|||
+-------+-----+---------------------------------------------------------------------------------+
|
||||
| Bit# | R/W | Description |
|
||||
+-------+-----+---------------------------------------------------------------------------------+
|
||||
| 12:11 | R | **MPP:** Statically 2'b11 and cannot be altered (read-only). |
|
||||
| 21 | RW | **TW:** Timeout Wait (WFI executed in User Mode will trap to Machine Mode). |
|
||||
+-------+-----+---------------------------------------------------------------------------------+
|
||||
| 17 | RW | **MPRV:** Modify Privilege (Loads and stores use MPP for privilege checking). |
|
||||
+-------+-----+---------------------------------------------------------------------------------+
|
||||
| 12:11 | RW | **MPP:** Machine Previous Privilege mode. |
|
||||
+-------+-----+---------------------------------------------------------------------------------+
|
||||
| 7 | RW | **Previous Interrupt Enable (MPIE)**, i.e., before entering exception handling. |
|
||||
+-------+-----+---------------------------------------------------------------------------------+
|
||||
| 3 | RW | **Interrupt Enable (MIE):** If set to 1'b1, interrupts are globally enabled. |
|
||||
+-------+-----+---------------------------------------------------------------------------------+
|
||||
|
||||
When an exception is encountered, ``mstatus``.MPIE will be set to ``mstatus``.MIE.
|
||||
When the MRET instruction is executed, the value of MPIE will be stored back to ``mstatus``.MIE.
|
||||
When an exception is encountered, ``mstatus``.MPIE will be set to ``mstatus``.MIE, and ``mstatus``.MPP will be set to the current privilege mode.
|
||||
When the MRET instruction is executed, the value of MPIE will be stored back to ``mstatus``.MIE, and the privilege mode will be restored from ``mstatus``.MPP.
|
||||
|
||||
If you want to enable interrupt handling in your exception handler, set ``mstatus``.MIE to 1'b1 inside your handler code.
|
||||
|
||||
Only Machine Mode and User Mode are supported.
|
||||
Any write to ``mstatus``.MPP of an unsupported value will be interpreted as Machine Mode.
|
||||
|
||||
Machine ISA Register (misa)
|
||||
---------------------------
|
||||
|
@ -276,6 +282,15 @@ Reset Value: ``0x0000_0000``
|
|||
| address[33:2] |
|
||||
+----------------+
|
||||
|
||||
Time Registers (time(h))
|
||||
------------------------
|
||||
|
||||
CSR Address: ``0xC01 / 0xC81``
|
||||
|
||||
The User Mode ``time(h)`` registers are not implemented in Ibex.
|
||||
Any access to these registers will trap.
|
||||
It is recommended that trap handler software provides a means of accessing platform-defined ``mtime(h)`` timers where available.
|
||||
|
||||
.. _csr-mhartid:
|
||||
|
||||
Hardware Thread ID (mhartid)
|
||||
|
|
|
@ -15,6 +15,12 @@ For more information, see the :ref:`cs-registers` documentation.
|
|||
The core starts fetching at the address made by concatenating the most significant 3 bytes of the boot address and the reset value (0x80) as the least significant byte.
|
||||
It is assumed that the boot address is supplied via a register to avoid long paths to the instruction fetch unit.
|
||||
|
||||
Privilege Modes
|
||||
---------------
|
||||
|
||||
Ibex supports operation in Machine Mode (M-Mode) and User Mode (U-Mode).
|
||||
The core resets into M-Mode and will jump to M-Mode on any interrupt or exception.
|
||||
On execution of an MRET instruction, the core will return to the Privilege Mode stored in ``mstatus``.MPP.
|
||||
|
||||
Interrupts
|
||||
----------
|
||||
|
@ -80,7 +86,9 @@ Ibex can trigger an exception due to the following exception causes:
|
|||
+----------------+---------------------------------------------------------------+
|
||||
| 7 | Store access fault |
|
||||
+----------------+---------------------------------------------------------------+
|
||||
| 11 | Environment call from M-mode (ECALL) |
|
||||
| 8 | Environment call from U-Mode (ECALL) |
|
||||
+----------------+---------------------------------------------------------------+
|
||||
| 11 | Environment call from M-Mode (ECALL) |
|
||||
+----------------+---------------------------------------------------------------+
|
||||
|
||||
The illegal instruction exception, instruction access fault, LSU error exceptions and ECALL instruction exceptions cannot be disabled and are always active.
|
||||
|
|
|
@ -53,7 +53,7 @@ In addition, the following instruction set extensions are available.
|
|||
Most content of the RISC-V privileged specification is optional.
|
||||
Ibex currently supports the following features according to the RISC-V Privileged Specification, version 1.11.
|
||||
|
||||
* M mode
|
||||
* M-Mode and U-Mode
|
||||
* All CSRs listed in :ref:`cs-registers`
|
||||
* Performance counters as described in :ref:`performance-counters`
|
||||
* Vectorized trap handling as described at :ref:`exceptions-interrupts`
|
||||
|
|
|
@ -69,9 +69,9 @@ lint_off -msg UNUSED -file "*/rtl/ibex_core.sv" -lines 199
|
|||
// Signal unoptimizable: Feedback to clock or circular logic:
|
||||
// ibex_core.id_stage_i.controller_i.ctrl_fsm_cs
|
||||
// Issue lowrisc/ibex#211
|
||||
lint_off -msg UNOPTFLAT -file "*/rtl/ibex_controller.sv" -lines 98
|
||||
lint_off -msg UNOPTFLAT -file "*/rtl/ibex_controller.sv" -lines 100
|
||||
|
||||
// Signal unoptimizable: Feedback to clock or circular logic:
|
||||
// ibex_core.cs_registers_i.mie_q
|
||||
// Issue lowrisc/ibex#212
|
||||
lint_off -msg UNOPTFLAT -file "*/rtl/ibex_cs_registers.sv" -lines 149
|
||||
lint_off -msg UNOPTFLAT -file "*/rtl/ibex_cs_registers.sv" -lines 162
|
||||
|
|
|
@ -74,6 +74,8 @@ module ibex_controller (
|
|||
output logic csr_restore_mret_id_o,
|
||||
output logic csr_save_cause_o,
|
||||
output logic [31:0] csr_mtval_o,
|
||||
input ibex_pkg::priv_lvl_e priv_mode_i,
|
||||
input logic csr_mstatus_tw_i,
|
||||
|
||||
// stall signals
|
||||
input logic stall_lsu_i,
|
||||
|
@ -108,6 +110,7 @@ module ibex_controller (
|
|||
logic halt_if;
|
||||
logic flush_id;
|
||||
logic illegal_dret;
|
||||
logic illegal_umode;
|
||||
logic exc_req_lsu;
|
||||
logic special_req;
|
||||
logic enter_debug_mode;
|
||||
|
@ -157,11 +160,17 @@ module ibex_controller (
|
|||
// "Executing DRET outside of Debug Mode causes an illegal instruction exception."
|
||||
// [Debug Spec v0.13.2, p.41]
|
||||
assign illegal_dret = dret_insn & ~debug_mode_q;
|
||||
|
||||
// Some instructions can only be executed in M-Mode
|
||||
assign illegal_umode = (priv_mode_i != PRIV_LVL_M) &
|
||||
// MRET must be in M-Mode. TW means trap WFI to M-Mode.
|
||||
(mret_insn | (csr_mstatus_tw_i & wfi_insn));
|
||||
|
||||
// This is recorded in the illegal_insn_q flop to help timing. Specifically
|
||||
// it is needed to break the path from ibex_cs_registers/illegal_csr_insn_o
|
||||
// to pc_set_o. Clear when controller is in FLUSH so it won't remain set
|
||||
// once illegal instruction is handled.
|
||||
assign illegal_insn_d = (illegal_insn_i | illegal_dret) & (ctrl_fsm_cs != FLUSH);
|
||||
assign illegal_insn_d = (illegal_insn_i | illegal_dret | illegal_umode) & (ctrl_fsm_cs != FLUSH);
|
||||
|
||||
// exception requests
|
||||
// requests are flopped in exc_req_q. This is cleared when controller is in
|
||||
|
@ -486,7 +495,8 @@ module ibex_controller (
|
|||
csr_mtval_o = instr_is_compressed_i ? {16'b0, instr_compressed_i} : instr_i;
|
||||
|
||||
end else if (ecall_insn) begin
|
||||
exc_cause_o = EXC_CAUSE_ECALL_MMODE;
|
||||
exc_cause_o = (priv_mode_i == PRIV_LVL_M) ? EXC_CAUSE_ECALL_MMODE :
|
||||
EXC_CAUSE_ECALL_UMODE;
|
||||
|
||||
end else if (ebrk_insn) begin
|
||||
if (debug_mode_q) begin
|
||||
|
|
|
@ -196,7 +196,10 @@ module ibex_core #(
|
|||
logic csr_mtvec_init;
|
||||
logic [31:0] csr_mtvec;
|
||||
logic [31:0] csr_mtval;
|
||||
priv_lvl_e priv_mode;
|
||||
logic csr_mstatus_tw;
|
||||
priv_lvl_e priv_mode_id;
|
||||
priv_lvl_e priv_mode_if;
|
||||
priv_lvl_e priv_mode_lsu;
|
||||
|
||||
// debug mode and dcsr configuration
|
||||
logic debug_mode;
|
||||
|
@ -412,6 +415,8 @@ module ibex_core #(
|
|||
.csr_restore_mret_id_o ( csr_restore_mret_id ), // restore mstatus upon MRET
|
||||
.csr_save_cause_o ( csr_save_cause ),
|
||||
.csr_mtval_o ( csr_mtval ),
|
||||
.priv_mode_i ( priv_mode_id ),
|
||||
.csr_mstatus_tw_i ( csr_mstatus_tw ),
|
||||
.illegal_csr_insn_i ( illegal_csr_insn_id ),
|
||||
|
||||
// LSU
|
||||
|
@ -572,7 +577,9 @@ module ibex_core #(
|
|||
|
||||
// Hart ID from outside
|
||||
.hart_id_i ( hart_id_i ),
|
||||
.priv_mode_o ( priv_mode ),
|
||||
.priv_mode_id_o ( priv_mode_id ),
|
||||
.priv_mode_if_o ( priv_mode_if ),
|
||||
.priv_mode_lsu_o ( priv_mode_lsu ),
|
||||
|
||||
// mtvec
|
||||
.csr_mtvec_o ( csr_mtvec ),
|
||||
|
@ -597,6 +604,7 @@ module ibex_core #(
|
|||
.csr_meip_o ( csr_meip ),
|
||||
.csr_mfip_o ( csr_mfip ),
|
||||
.csr_mstatus_mie_o ( csr_mstatus_mie ),
|
||||
.csr_mstatus_tw_o ( csr_mstatus_tw ),
|
||||
.csr_mepc_o ( csr_mepc ),
|
||||
|
||||
// PMP
|
||||
|
@ -640,11 +648,14 @@ module ibex_core #(
|
|||
if (PMPEnable) begin : g_pmp
|
||||
logic [33:0] pmp_req_addr [PMP_NUM_CHAN];
|
||||
pmp_req_e pmp_req_type [PMP_NUM_CHAN];
|
||||
priv_lvl_e pmp_priv_lvl [PMP_NUM_CHAN];
|
||||
|
||||
assign pmp_req_addr[PMP_I] = {2'b00,instr_addr_o[31:0]};
|
||||
assign pmp_req_type[PMP_I] = PMP_ACC_EXEC;
|
||||
assign pmp_priv_lvl[PMP_I] = priv_mode_if;
|
||||
assign pmp_req_addr[PMP_D] = {2'b00,data_addr_o[31:0]};
|
||||
assign pmp_req_type[PMP_D] = data_we_o ? PMP_ACC_WRITE : PMP_ACC_READ;
|
||||
assign pmp_priv_lvl[PMP_D] = priv_mode_lsu;
|
||||
|
||||
ibex_pmp #(
|
||||
.PMPGranularity ( PMPGranularity ),
|
||||
|
@ -656,13 +667,18 @@ module ibex_core #(
|
|||
// Interface to CSRs
|
||||
.csr_pmp_cfg_i ( csr_pmp_cfg ),
|
||||
.csr_pmp_addr_i ( csr_pmp_addr ),
|
||||
.priv_mode_i ( priv_mode ),
|
||||
.priv_mode_i ( pmp_priv_lvl ),
|
||||
// Access checking channels
|
||||
.pmp_req_addr_i ( pmp_req_addr ),
|
||||
.pmp_req_type_i ( pmp_req_type ),
|
||||
.pmp_req_err_o ( pmp_req_err )
|
||||
);
|
||||
end else begin : g_no_pmp
|
||||
// Unused signal tieoff
|
||||
priv_lvl_e unused_priv_lvl_if, unused_priv_lvl_ls;
|
||||
assign unused_priv_lvl_if = priv_mode_if;
|
||||
assign unused_priv_lvl_ls = priv_mode_lsu;
|
||||
// Output tieoff
|
||||
assign pmp_req_err[PMP_I] = 1'b0;
|
||||
assign pmp_req_err[PMP_D] = 1'b0;
|
||||
end
|
||||
|
@ -675,7 +691,7 @@ module ibex_core #(
|
|||
rvfi_intr <= '0;
|
||||
rvfi_order <= '0;
|
||||
rvfi_insn <= '0;
|
||||
rvfi_mode <= '0;
|
||||
rvfi_mode <= {PRIV_LVL_M};
|
||||
rvfi_rs1_addr <= '0;
|
||||
rvfi_rs2_addr <= '0;
|
||||
rvfi_pc_rdata <= '0;
|
||||
|
@ -696,7 +712,7 @@ module ibex_core #(
|
|||
rvfi_intr <= rvfi_intr_d;
|
||||
rvfi_order <= rvfi_order + 64'(rvfi_valid);
|
||||
rvfi_insn <= rvfi_insn_id;
|
||||
rvfi_mode <= PRIV_LVL_M; // TODO: Update for user mode support
|
||||
rvfi_mode <= {priv_mode_id};
|
||||
rvfi_rs1_addr <= rvfi_rs1_addr_id;
|
||||
rvfi_rs2_addr <= rvfi_rs2_addr_id;
|
||||
rvfi_pc_rdata <= pc_id;
|
||||
|
|
|
@ -24,7 +24,12 @@ module ibex_cs_registers #(
|
|||
|
||||
// Hart ID
|
||||
input logic [31:0] hart_id_i,
|
||||
output ibex_pkg::priv_lvl_e priv_mode_o,
|
||||
|
||||
// Privilege mode
|
||||
output ibex_pkg::priv_lvl_e priv_mode_id_o,
|
||||
output ibex_pkg::priv_lvl_e priv_mode_if_o,
|
||||
output ibex_pkg::priv_lvl_e priv_mode_lsu_o,
|
||||
output logic csr_mstatus_tw_o,
|
||||
|
||||
// mtvec
|
||||
output logic [31:0] csr_mtvec_o,
|
||||
|
@ -112,8 +117,15 @@ module ibex_cs_registers #(
|
|||
logic mie;
|
||||
logic mpie;
|
||||
priv_lvl_e mpp;
|
||||
logic mprv;
|
||||
logic tw;
|
||||
} Status_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic mpie;
|
||||
priv_lvl_e mpp;
|
||||
} StatusStk_t;
|
||||
|
||||
// struct for mip/mie CSRs
|
||||
typedef struct packed {
|
||||
logic irq_software;
|
||||
|
@ -145,6 +157,7 @@ module ibex_cs_registers #(
|
|||
logic [31:0] exception_pc;
|
||||
|
||||
// CSRs
|
||||
priv_lvl_e priv_lvl_q, priv_lvl_d;
|
||||
Status_t mstatus_q, mstatus_d;
|
||||
Interrupts_t mie_q, mie_d;
|
||||
logic [31:0] mscratch_q, mscratch_d;
|
||||
|
@ -160,7 +173,7 @@ module ibex_cs_registers #(
|
|||
|
||||
// CSRs for recoverable NMIs
|
||||
// NOTE: these CSRS are nonstandard, see https://github.com/riscv/riscv-isa-manual/issues/261
|
||||
Status_t mstack_q, mstack_d;
|
||||
StatusStk_t mstack_q, mstack_d;
|
||||
logic [31:0] mstack_epc_q, mstack_epc_d;
|
||||
logic [5:0] mstack_cause_q, mstack_cause_d;
|
||||
|
||||
|
@ -205,11 +218,11 @@ module ibex_cs_registers #(
|
|||
assign mhpmcounter_idx = csr_addr[4:0];
|
||||
|
||||
// See RISC-V Privileged Specification, version 1.11, Section 2.1
|
||||
assign illegal_csr_priv = 1'b0; // we only support M-mode
|
||||
assign illegal_csr_priv = (csr_addr[9:8] > {priv_lvl_q});
|
||||
assign illegal_csr_write = (csr_addr[11:10] == 2'b11) && csr_wreq;
|
||||
assign illegal_csr_insn_o = illegal_csr | illegal_csr_write | illegal_csr_priv;
|
||||
assign illegal_csr_insn_o = csr_access_i & (illegal_csr | illegal_csr_write | illegal_csr_priv);
|
||||
|
||||
// mip CSR is purely combintational - must be able to re-enable the clock upon WFI
|
||||
// mip CSR is purely combinational - must be able to re-enable the clock upon WFI
|
||||
assign mip.irq_software = irq_software_i & mie_q.irq_software;
|
||||
assign mip.irq_timer = irq_timer_i & mie_q.irq_timer;
|
||||
assign mip.irq_external = irq_external_i & mie_q.irq_external;
|
||||
|
@ -230,6 +243,7 @@ module ibex_cs_registers #(
|
|||
csr_rdata_int[CSR_MSTATUS_MIE_BIT] = mstatus_q.mie;
|
||||
csr_rdata_int[CSR_MSTATUS_MPIE_BIT] = mstatus_q.mpie;
|
||||
csr_rdata_int[CSR_MSTATUS_MPP_BIT_HIGH:CSR_MSTATUS_MPP_BIT_LOW] = mstatus_q.mpp;
|
||||
csr_rdata_int[CSR_MSTATUS_MPRV_BIT] = mstatus_q.mprv;
|
||||
end
|
||||
|
||||
// misa
|
||||
|
@ -324,7 +338,7 @@ module ibex_cs_registers #(
|
|||
if ((csr_addr[4:0] == 5'b00000) || // CSR_MCOUNTINHIBIT
|
||||
(csr_addr[4:0] == 5'b00001) ||
|
||||
(csr_addr[4:0] == 5'b00010)) begin
|
||||
illegal_csr = csr_access_i;
|
||||
illegal_csr = 1'b1;
|
||||
end
|
||||
|
||||
end else if ((csr_addr & CSR_MASK_MCOUNTER) == CSR_OFF_MCOUNTER) begin
|
||||
|
@ -333,7 +347,7 @@ module ibex_cs_registers #(
|
|||
if ((csr_addr[4:0] == 5'b00000) || // CSR_MCYCLE
|
||||
(csr_addr[4:0] == 5'b00001) ||
|
||||
(csr_addr[4:0] == 5'b00010)) begin // CSR_MINSTRET
|
||||
illegal_csr = csr_access_i;
|
||||
illegal_csr = 1'b1;
|
||||
end
|
||||
|
||||
end else if ((csr_addr & CSR_MASK_MCOUNTER) == CSR_OFF_MCOUNTERH) begin
|
||||
|
@ -342,10 +356,10 @@ module ibex_cs_registers #(
|
|||
if ((csr_addr[4:0] == 5'b00000) || // CSR_MCYCLEH
|
||||
(csr_addr[4:0] == 5'b00001) ||
|
||||
(csr_addr[4:0] == 5'b00010)) begin // CSR_MINSTRETH
|
||||
illegal_csr = csr_access_i;
|
||||
illegal_csr = 1'b1;
|
||||
end
|
||||
end else begin
|
||||
illegal_csr = csr_access_i;
|
||||
illegal_csr = 1'b1;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
|
@ -355,6 +369,7 @@ module ibex_cs_registers #(
|
|||
always_comb begin
|
||||
exception_pc = pc_id_i;
|
||||
|
||||
priv_lvl_d = priv_lvl_q;
|
||||
mstatus_d = mstatus_q;
|
||||
mie_d = mie_q;
|
||||
mscratch_d = mscratch_q;
|
||||
|
@ -382,8 +397,14 @@ module ibex_cs_registers #(
|
|||
mstatus_d = '{
|
||||
mie: csr_wdata_int[CSR_MSTATUS_MIE_BIT],
|
||||
mpie: csr_wdata_int[CSR_MSTATUS_MPIE_BIT],
|
||||
mpp: PRIV_LVL_M
|
||||
mpp: csr_wdata_int[CSR_MSTATUS_MPP_BIT_HIGH:CSR_MSTATUS_MPP_BIT_LOW],
|
||||
mprv: csr_wdata_int[CSR_MSTATUS_MPRV_BIT],
|
||||
tw: csr_wdata_int[CSR_MSTATUS_TW_BIT]
|
||||
};
|
||||
// Convert illegal values to M-mode
|
||||
if ((mstatus_d.mpp != PRIV_LVL_M) && (mstatus_d.mpp != PRIV_LVL_U)) begin
|
||||
mstatus_d.mpp = PRIV_LVL_M;
|
||||
end
|
||||
end
|
||||
|
||||
// interrupt enable
|
||||
|
@ -413,7 +434,10 @@ module ibex_cs_registers #(
|
|||
CSR_DCSR: begin
|
||||
dcsr_d = csr_wdata_int;
|
||||
dcsr_d.xdebugver = XDEBUGVER_STD;
|
||||
dcsr_d.prv = PRIV_LVL_M; // only M-mode is supported
|
||||
// Change to PRIV_LVL_M if sofware writes an unsupported value
|
||||
if ((dcsr_d.prv != PRIV_LVL_M) && (dcsr_d.prv != PRIV_LVL_U)) begin
|
||||
dcsr_d.prv = PRIV_LVL_M;
|
||||
end
|
||||
|
||||
// currently not supported:
|
||||
dcsr_d.nmip = 1'b0;
|
||||
|
@ -471,15 +495,16 @@ module ibex_cs_registers #(
|
|||
if (debug_csr_save_i) begin
|
||||
// all interrupts are masked
|
||||
// do not update cause, epc, tval, epc and status
|
||||
dcsr_d.prv = PRIV_LVL_M;
|
||||
dcsr_d.prv = priv_lvl_q;
|
||||
dcsr_d.cause = debug_cause_i;
|
||||
depc_d = exception_pc;
|
||||
end else begin
|
||||
priv_lvl_d = PRIV_LVL_M;
|
||||
mtval_d = csr_mtval_i;
|
||||
mstatus_d.mie = 1'b0; // disable interrupts
|
||||
// save current status
|
||||
mstatus_d.mpie = mstatus_q.mie;
|
||||
mstatus_d.mpp = PRIV_LVL_M;
|
||||
mstatus_d.mpp = priv_lvl_q;
|
||||
mepc_d = exception_pc;
|
||||
mcause_d = {csr_mcause_i};
|
||||
// save previous status for recoverable NMI
|
||||
|
@ -491,12 +516,15 @@ module ibex_cs_registers #(
|
|||
end // csr_save_cause_i
|
||||
|
||||
csr_restore_mret_i: begin // MRET
|
||||
priv_lvl_d = mstatus_q.mpp;
|
||||
mstatus_d.mie = mstatus_q.mpie; // re-enable interrupts
|
||||
// restore previous status for recoverable NMI
|
||||
mstatus_d.mpie = mstack_q.mpie;
|
||||
mstatus_d.mpp = mstack_q.mpp;
|
||||
mepc_d = mstack_epc_q;
|
||||
mcause_d = mstack_cause_q;
|
||||
mstack_d.mpie = 1'b1;
|
||||
mstack_d.mpp = PRIV_LVL_U;
|
||||
end // csr_restore_mret_i
|
||||
|
||||
default:;
|
||||
|
@ -538,6 +566,7 @@ module ibex_cs_registers #(
|
|||
assign csr_mtvec_o = mtvec_q;
|
||||
|
||||
assign csr_mstatus_mie_o = mstatus_q.mie;
|
||||
assign csr_mstatus_tw_o = mstatus_q.tw;
|
||||
assign debug_single_step_o = dcsr_q.step;
|
||||
assign debug_ebreakm_o = dcsr_q.ebreakm;
|
||||
|
||||
|
@ -546,10 +575,13 @@ module ibex_cs_registers #(
|
|||
// actual registers
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
priv_lvl_q <= PRIV_LVL_M;
|
||||
mstatus_q <= '{
|
||||
mie: 1'b0,
|
||||
mpie: 1'b0,
|
||||
mpp: PRIV_LVL_M
|
||||
mpie: 1'b1,
|
||||
mpp: PRIV_LVL_U,
|
||||
mprv: 1'b0,
|
||||
tw: 1'b0
|
||||
};
|
||||
mie_q <= '0;
|
||||
mscratch_q <= '0;
|
||||
|
@ -568,15 +600,15 @@ module ibex_cs_registers #(
|
|||
dscratch1_q <= '0;
|
||||
|
||||
mstack_q <= '{
|
||||
mie: 1'b0,
|
||||
mpie: 1'b0,
|
||||
mpp: PRIV_LVL_M
|
||||
mpie: 1'b1,
|
||||
mpp: PRIV_LVL_U
|
||||
};
|
||||
mstack_epc_q <= '0;
|
||||
mstack_cause_q <= '0;
|
||||
|
||||
end else begin
|
||||
// update CSRs
|
||||
priv_lvl_q <= priv_lvl_d;
|
||||
mstatus_q <= mstatus_d;
|
||||
mie_q <= mie_d;
|
||||
mscratch_q <= mscratch_d;
|
||||
|
@ -596,7 +628,12 @@ module ibex_cs_registers #(
|
|||
end
|
||||
end
|
||||
|
||||
assign priv_mode_o = mstatus_q.mpp;
|
||||
// Send current priv level to the decoder
|
||||
assign priv_mode_id_o = priv_lvl_q;
|
||||
// New instruction fetches need to account for updates to priv_lvl_q this cycle
|
||||
assign priv_mode_if_o = priv_lvl_d;
|
||||
// Load/store instructions must factor in MPRV for PMP checking
|
||||
assign priv_mode_lsu_o = mstatus_q.mprv ? mstatus_q.mpp : priv_lvl_q;
|
||||
|
||||
// -----------------
|
||||
// PMP registers
|
||||
|
|
|
@ -75,6 +75,8 @@ module ibex_id_stage #(
|
|||
output logic csr_restore_mret_id_o,
|
||||
output logic csr_save_cause_o,
|
||||
output logic [31:0] csr_mtval_o,
|
||||
input ibex_pkg::priv_lvl_e priv_mode_i,
|
||||
input logic csr_mstatus_tw_i,
|
||||
input logic illegal_csr_insn_i,
|
||||
|
||||
// Interface to load store unit
|
||||
|
@ -438,6 +440,8 @@ module ibex_id_stage #(
|
|||
.csr_restore_mret_id_o ( csr_restore_mret_id_o ),
|
||||
.csr_save_cause_o ( csr_save_cause_o ),
|
||||
.csr_mtval_o ( csr_mtval_o ),
|
||||
.priv_mode_i ( priv_mode_i ),
|
||||
.csr_mstatus_tw_i ( csr_mstatus_tw_i ),
|
||||
|
||||
// Debug Signal
|
||||
.debug_mode_o ( debug_mode_o ),
|
||||
|
|
|
@ -180,6 +180,7 @@ typedef enum logic [5:0] {
|
|||
EXC_CAUSE_BREAKPOINT = {1'b0, 5'd03},
|
||||
EXC_CAUSE_LOAD_ACCESS_FAULT = {1'b0, 5'd05},
|
||||
EXC_CAUSE_STORE_ACCESS_FAULT = {1'b0, 5'd07},
|
||||
EXC_CAUSE_ECALL_UMODE = {1'b0, 5'd08},
|
||||
EXC_CAUSE_ECALL_MMODE = {1'b0, 5'd11}
|
||||
} exc_cause_e;
|
||||
|
||||
|
@ -293,6 +294,8 @@ parameter int unsigned CSR_MSTATUS_MIE_BIT = 3;
|
|||
parameter int unsigned CSR_MSTATUS_MPIE_BIT = 7;
|
||||
parameter int unsigned CSR_MSTATUS_MPP_BIT_LOW = 11;
|
||||
parameter int unsigned CSR_MSTATUS_MPP_BIT_HIGH = 12;
|
||||
parameter int unsigned CSR_MSTATUS_MPRV_BIT = 17;
|
||||
parameter int unsigned CSR_MSTATUS_TW_BIT = 21;
|
||||
|
||||
// CSR interrupt pending/enable bits
|
||||
parameter int unsigned CSR_MSIX_BIT = 3;
|
||||
|
|
|
@ -19,8 +19,7 @@ module ibex_pmp #(
|
|||
input ibex_pkg::pmp_cfg_t csr_pmp_cfg_i [PMPNumRegions],
|
||||
input logic [33:0] csr_pmp_addr_i [PMPNumRegions],
|
||||
|
||||
input ibex_pkg::priv_lvl_e priv_mode_i, // Current priv mode, assumed to
|
||||
// be the same for all channels
|
||||
input ibex_pkg::priv_lvl_e priv_mode_i [PMPNumChan],
|
||||
// Access checking channels
|
||||
input logic [33:0] pmp_req_addr_i [PMPNumChan],
|
||||
input ibex_pkg::pmp_req_e pmp_req_type_i [PMPNumChan],
|
||||
|
@ -104,8 +103,8 @@ module ibex_pmp #(
|
|||
~|region_match_partial[c][r-1:0];
|
||||
end
|
||||
end
|
||||
assign access_fault[c] = (priv_mode_i == PRIV_LVL_M) ? |machine_access_fault[c] :
|
||||
~|user_access_allowed[c];
|
||||
assign access_fault[c] = (priv_mode_i[c] == PRIV_LVL_M) ? |machine_access_fault[c] :
|
||||
~|user_access_allowed[c];
|
||||
|
||||
assign pmp_req_err_o[c] = access_fault[c];
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue