Cause illegal instruction exception for access violations on CSRs

This commit adds checks to CSR accesses. If a CSR is accessed that is not
implemented, or if a read-only CSR is written to, an illegal instruction
exception is caused.
This commit is contained in:
Pirmin Vogel 2019-05-29 17:32:02 +01:00
parent 3ea6744f81
commit d4b349766e
4 changed files with 46 additions and 10 deletions

View file

@ -139,6 +139,8 @@ module ibex_core #(
csr_num_e csr_addr;
logic [31:0] csr_rdata;
logic [31:0] csr_wdata;
logic illegal_csr_insn_id; // CSR access to non-existent register,
// with wrong priviledge level, or missing write permissions
// Data Memory Control
logic data_we_ex;
@ -345,6 +347,7 @@ module ibex_core #(
.csr_restore_mret_id_o ( csr_restore_mret_id ), // control signal to restore pc
.csr_restore_dret_id_o ( csr_restore_dret_id ), // control signal to restore pc
.csr_save_cause_o ( csr_save_cause ),
.illegal_csr_insn_i ( illegal_csr_insn_id ),
// LSU
.data_req_ex_o ( data_req_ex ), // to load store unit
@ -520,7 +523,7 @@ module ibex_core #(
.csr_restore_dret_i ( csr_restore_dret_id ),
.csr_cause_i ( csr_cause ),
.csr_save_cause_i ( csr_save_cause ),
.illegal_csr_insn_o ( illegal_csr_insn_id ),
// performance counter related signals
.insn_ret_i ( insn_ret ),

View file

@ -71,6 +71,9 @@ module ibex_cs_registers #(
input ibex_defines::exc_cause_e csr_cause_i,
input logic csr_save_cause_i,
output logic illegal_csr_insn_o, // access to non-existent CSR,
// with wrong priviledge level, or
// missing write permissions
// Performance Counters
input logic insn_ret_i, // instr retired in ID/EX stage
input logic if_valid_i, // IF stage gives a new instr
@ -79,7 +82,7 @@ module ibex_cs_registers #(
input logic is_decoding_i, // controller is in DECODE state
input logic imiss_i, // instr fetch
input logic pc_set_i, // pc was set to a new value
input logic pc_set_i, // PC was set to a new value
input logic jump_i, // jump instr seen (j, jr, jal, jalr)
input logic branch_i, // branch instr seen (bf, bnf)
input logic branch_taken_i, // branch was taken
@ -200,6 +203,11 @@ module ibex_cs_registers #(
Status_t mstatus_q, mstatus_n;
logic [31:0] exception_pc;
// Access violation signals
logic illegal_csr;
logic illegal_csr_priv;
logic illegal_csr_write;
/////////////
// CSR reg //
/////////////
@ -208,9 +216,14 @@ module ibex_cs_registers #(
assign csr_addr = {csr_addr_i};
assign mhpmcounter_idx = csr_addr[4:0];
assign illegal_csr_priv = 1'b0; // we only support M-mode
assign illegal_csr_write = (csr_addr[11:10] == 2'b11) && csr_we_int;
assign illegal_csr_insn_o = illegal_csr | illegal_csr_write | illegal_csr_priv;
// read logic
always_comb begin
csr_rdata_int = '0;
illegal_csr = 1'b0;
unique case (csr_addr_i)
// mstatus: always M-mode, contains IE bit
@ -256,10 +269,32 @@ module ibex_cs_registers #(
default: begin
if (csr_addr_i == CSR_MCOUNTER_SETUP_MASK) begin
csr_rdata_int = mhpmevent[mhpmcounter_idx];
// check access to non-existent or already covered CSRs
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;
end
end else if (csr_addr_i == CSR_MCOUNTER_MASK) begin
csr_rdata_int = mhpmcounter_q[mhpmcounter_idx][31: 0];
// check access to non-existent or already covered CSRs
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;
end
end else if (csr_addr_i == CSR_MCOUNTERH_MASK) begin
csr_rdata_int = mhpmcounter_q[mhpmcounter_idx][63:32];
// check access to non-existent or already covered CSRs
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;
end
end else begin
illegal_csr = csr_access_i;
end
end
endcase

View file

@ -96,7 +96,6 @@ module ibex_decoder #(
logic branch_in_id;
logic jump_in_id;
csr_op_e csr_op;
logic csr_illegal;
opcode_e opcode;
@ -125,7 +124,7 @@ module ibex_decoder #(
csr_access_o = 1'b0;
csr_status_o = 1'b0;
csr_illegal = 1'b0;
csr_op = CSR_OP_NONE;
csr_op_o = CSR_OP_NONE;
data_we_o = 1'b0;
data_type_o = 2'b00;
@ -496,9 +495,9 @@ module ibex_decoder #(
end
unique case (instr_rdata_i[13:12])
2'b01: csr_op = CSR_OP_WRITE;
2'b10: csr_op = CSR_OP_SET;
2'b11: csr_op = CSR_OP_CLEAR;
2'b01: csr_op_o = CSR_OP_WRITE;
2'b10: csr_op_o = CSR_OP_SET;
2'b11: csr_op_o = CSR_OP_CLEAR;
default: csr_illegal = 1'b1;
endcase
@ -514,7 +513,6 @@ module ibex_decoder #(
end
illegal_insn_o = csr_illegal;
end
end
@ -549,7 +547,6 @@ module ibex_decoder #(
assign mult_int_en_o = RV32M ? ((deassert_we_i) ? 1'b0 : mult_int_en) : 1'b0;
assign div_int_en_o = RV32M ? ((deassert_we_i) ? 1'b0 : div_int_en ) : 1'b0;
assign data_req_o = (deassert_we_i) ? 1'b0 : data_req;
assign csr_op_o = (deassert_we_i) ? CSR_OP_NONE : csr_op;
assign jump_in_id_o = (deassert_we_i) ? 1'b0 : jump_in_id;
assign branch_in_id_o = (deassert_we_i) ? 1'b0 : branch_in_id;

View file

@ -94,6 +94,7 @@ module ibex_id_stage #(
output logic csr_restore_mret_id_o,
output logic csr_restore_dret_id_o,
output logic csr_save_cause_o,
input logic illegal_csr_insn_i,
// Interface to load store unit
output logic data_req_ex_o,
@ -407,7 +408,7 @@ module ibex_id_stage #(
////////////////
// Controller //
////////////////
assign illegal_insn_o = illegal_insn_dec | illegal_reg_rv32e;
assign illegal_insn_o = illegal_insn_dec | illegal_reg_rv32e | illegal_csr_insn_i;
ibex_controller controller_i (
.clk_i ( clk_i ),