Add mstatus.tw to control U-mode WFI, and prevent mret execution in U-mode.
This commit is contained in:
parent
10ca3aec80
commit
51750eb81d
|
@ -188,10 +188,12 @@ wire [1:0] d_csr_wtype;
|
|||
wire d_csr_w_imm;
|
||||
|
||||
wire x_jump_not_except;
|
||||
wire x_mmode_execution;
|
||||
wire x_permit_wfi;
|
||||
|
||||
hazard3_decode #(
|
||||
`include "hazard3_config_inst.vh"
|
||||
) inst_hazard3_decode (
|
||||
) decode_u (
|
||||
.clk (clk),
|
||||
.rst_n (rst_n),
|
||||
|
||||
|
@ -204,6 +206,8 @@ hazard3_decode #(
|
|||
.x_jump_not_except (x_jump_not_except),
|
||||
|
||||
.debug_mode (debug_mode),
|
||||
.m_mode (x_mmode_execution),
|
||||
.permit_wfi (x_permit_wfi),
|
||||
|
||||
.d_starved (d_starved),
|
||||
.x_stall (x_stall),
|
||||
|
@ -257,8 +261,6 @@ wire m_trap_enter_vld;
|
|||
wire m_trap_enter_soon;
|
||||
wire m_trap_enter_rdy = f_jump_rdy;
|
||||
|
||||
// Privilege state outputs from CSR block
|
||||
wire x_mmode_execution;
|
||||
wire x_mmode_loadstore;
|
||||
wire m_mmode_trap_entry;
|
||||
|
||||
|
@ -821,7 +823,7 @@ wire m_dphase_in_flight = xm_memop != MEMOP_NONE && xm_memop != MEMOP_AMO;
|
|||
hazard3_csr #(
|
||||
.XLEN (W_DATA),
|
||||
`include "hazard3_config_inst.vh"
|
||||
) inst_hazard3_csr (
|
||||
) csr_u (
|
||||
.clk (clk),
|
||||
.rst_n (rst_n),
|
||||
|
||||
|
@ -878,6 +880,7 @@ hazard3_csr #(
|
|||
.pmp_cfg_rdata (x_pmp_cfg_rdata),
|
||||
|
||||
// Other CSR-specific signalling
|
||||
.permit_wfi (x_permit_wfi),
|
||||
.instr_ret (|x_instr_ret)
|
||||
);
|
||||
|
||||
|
|
|
@ -102,6 +102,7 @@ module hazard3_csr #(
|
|||
input wire [W_DATA-1:0] pmp_cfg_rdata,
|
||||
|
||||
// Other CSR-specific signalling
|
||||
output wire permit_wfi,
|
||||
input wire instr_ret
|
||||
);
|
||||
|
||||
|
@ -146,13 +147,14 @@ end
|
|||
|
||||
wire debug_suppresses_trap_update = DEBUG_SUPPORT && (debug_mode || enter_debug_mode);
|
||||
|
||||
|
||||
// Two-level interrupt enable stack, shuffled on entry/exit:
|
||||
// Core execution state, 1 -> M-mode, 0 -> U-mode (if implemented)
|
||||
reg m_mode;
|
||||
|
||||
reg mstatus_mpie;
|
||||
reg mstatus_mie;
|
||||
reg mstatus_mpp; // only MSB is implemented
|
||||
reg mstatus_mprv;
|
||||
reg mstatus_tw;
|
||||
|
||||
wire wen_m_mode = wen && (m_mode || debug_mode);
|
||||
|
||||
|
@ -163,6 +165,7 @@ always @ (posedge clk or negedge rst_n) begin
|
|||
mstatus_mie <= 1'b0;
|
||||
mstatus_mpp <= 1'b1;
|
||||
mstatus_mprv <= 1'b0;
|
||||
mstatus_tw <= 1'b0;
|
||||
end else if (CSR_M_TRAP) begin
|
||||
if (trap_enter_vld && trap_enter_rdy && !debug_suppresses_trap_update) begin
|
||||
if (except == EXCEPT_MRET) begin
|
||||
|
@ -184,7 +187,8 @@ always @ (posedge clk or negedge rst_n) begin
|
|||
mstatus_mie <= wdata_update[3];
|
||||
mstatus_mprv <= wdata_update[17];
|
||||
// Note only the MSB of MPP is implemented. It reads back as 11 or 00.
|
||||
mstatus_mpp <= wdata_update[12];
|
||||
mstatus_mpp <= wdata_update[12] || !U_MODE;
|
||||
mstatus_tw <= wdata_update[21] && U_MODE;
|
||||
end else if (wen && debug_mode && addr == DCSR && U_MODE && DEBUG_SUPPORT) begin
|
||||
// Debugger can change/observe core state directly through
|
||||
// dcsr.prv (this doesn't affect debugger operation, as all
|
||||
|
@ -195,6 +199,9 @@ always @ (posedge clk or negedge rst_n) begin
|
|||
end
|
||||
end
|
||||
|
||||
// Simply trap all U-mode WFIs if timeout bit is set
|
||||
assign permit_wfi = m_mode || !mstatus_tw;
|
||||
|
||||
reg [XLEN-1:0] mscratch;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
|
@ -510,10 +517,10 @@ always @ (*) begin
|
|||
1'b0, // Never any dirty state besides GPRs
|
||||
8'd0, // (WPRI)
|
||||
1'b0, // TSR (Trap SRET), tied 0 if no S mode.
|
||||
1'b0, // TW (Timeout Wait), tied 0 if only M mode.
|
||||
mstatus_tw, // TW (Timeout Wait)
|
||||
1'b0, // TVM (trap virtual memory), tied 0 if no S mode.
|
||||
1'b0, // MXR (Make eXecutable Readable), tied 0 if not S mode.
|
||||
1'b0, // SUM, tied 0, we have no S or U mode
|
||||
1'b0, // MXR (Make eXecutable Readable), tied 0 if no S mode.
|
||||
1'b0, // SUM, tied 0 if no S mode
|
||||
mstatus_mprv, // MPRV (modify privilege)
|
||||
4'd0, // XS, FS always "off" (no extension state to clear!)
|
||||
{2{mstatus_mpp}}, // MPP (M-mode previous privilege), only M and U supported
|
||||
|
|
|
@ -21,6 +21,8 @@ module hazard3_decode #(
|
|||
output wire [W_ADDR-1:0] d_pc,
|
||||
|
||||
input wire debug_mode,
|
||||
input wire m_mode,
|
||||
input wire permit_wfi,
|
||||
|
||||
output wire d_starved,
|
||||
input wire x_stall,
|
||||
|
@ -299,8 +301,9 @@ always @ (*) begin
|
|||
RV_CSRRCI: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = |d_rs1; d_csr_ren = 1'b1 ; d_csr_wtype = CSR_WTYPE_C; d_csr_w_imm = 1'b1; end else begin d_invalid_32bit = 1'b1; end
|
||||
RV_ECALL: if (HAVE_CSR) begin d_except = EXCEPT_ECALL; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||
RV_EBREAK: if (HAVE_CSR) begin d_except = EXCEPT_EBREAK; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||
RV_MRET: if (HAVE_CSR) begin d_except = EXCEPT_MRET; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||
RV_WFI: if (HAVE_CSR) begin d_wfi = 1'b1; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||
RV_MRET: if (HAVE_CSR && m_mode) begin d_except = EXCEPT_MRET; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||
RV_WFI: if (HAVE_CSR && permit_wfi) begin d_wfi = 1'b1; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||
|
||||
default: begin d_invalid_32bit = 1'b1; end
|
||||
endcase
|
||||
|
||||
|
|
Loading…
Reference in New Issue