Update lowrisc_ibex to lowRISC/ibex@3438b779
Update code from upstream repository
https://github.com/lowRISC/ibex.git to revision
3438b77921941ccbf50cba46b3009a6a37203d4b
* [rtl] Add minor alert for icache ECC error (Greg Chadwick)
* [icache, rtl] Fix ECC error indication (Greg Chadwick)
* [rtl] Add SEC_CM markers for security features (Greg Chadwick)
* [ibex, dv] Makes delays between req, gnt and rvalid configurable
(Prajwala Puttappa)
* [ibex, dv] Added new base, interrupt, debug and mem error sequences
(Prajwala Puttappa)
* [icache] Define some fake DPI functions to simplify linking (Rupert
Swarbrick)
* [ibex, dv] Added agent configuration for
ibex_mem_intf_response_agent (Prajwala Puttappa)
Signed-off-by: Greg Chadwick <gac@lowrisc.org>
diff --git a/hw/vendor/lowrisc_ibex.lock.hjson b/hw/vendor/lowrisc_ibex.lock.hjson
index a3eb684..30cb12d 100644
--- a/hw/vendor/lowrisc_ibex.lock.hjson
+++ b/hw/vendor/lowrisc_ibex.lock.hjson
@@ -9,6 +9,6 @@
upstream:
{
url: https://github.com/lowRISC/ibex.git
- rev: 0f69d4972c5184e8c8de41c4002fb914ef3ce10f
+ rev: 3438b77921941ccbf50cba46b3009a6a37203d4b
}
}
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/icache.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/icache.rst
index 1876986..75115eb 100644
--- a/hw/vendor/lowrisc_ibex/doc/03_reference/icache.rst
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/icache.rst
@@ -164,6 +164,8 @@
To deal with misalignment caused by compressed instructions, there is a 16bit skid buffer to store the upper halfword.
+.. _icache-ecc:
+
Cache ECC protection
^^^^^^^^^^^^^^^^^^^^
@@ -193,6 +195,7 @@
The request which observed an error will fetch it's data from the main instruction memory as normal for a cache miss.
The cache index and way (or ways) with errors are stored in IC1, and a cache write is forced the next cycle to invalidate that line.
Lookup requests will be blocked in IC0 while the invalidation write is performed.
+If an ECC error is seen a minor alert will be signaled.
Cache invalidation
^^^^^^^^^^^^^^^^^^
diff --git a/hw/vendor/lowrisc_ibex/doc/03_reference/security.rst b/hw/vendor/lowrisc_ibex/doc/03_reference/security.rst
index 2c5adf4..866ccc6 100644
--- a/hw/vendor/lowrisc_ibex/doc/03_reference/security.rst
+++ b/hw/vendor/lowrisc_ibex/doc/03_reference/security.rst
@@ -81,6 +81,13 @@
This can be useful to detect fault injection attacks since the register file covers a reasonably large area.
No attempt is made to correct detected errors, but an internal major alert is signaled for the system to take action.
+ICache ECC
+----------
+
+The ICache can be configured with ECC protection.
+When an ECC error is detected a minor alert is signaled.
+See :ref:`icache-ecc` for more information.
+
Hardened PC
-----------
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
index 1963731..c44f570 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_core.sv
@@ -101,6 +101,8 @@
// Debug Interface
input logic debug_req_i,
output crash_dump_t crash_dump_o,
+ // SEC_CM: EXCEPTION.CTRL_FLOW.LOCAL_ESC
+ // SEC_CM: EXCEPTION.CTRL_FLOW.GLOBAL_ESC
output logic double_fault_seen_o,
// RISC-V Formal Interface
@@ -137,6 +139,7 @@
`endif
// CPU Control Signals
+ // SEC_CM: FETCH.CTRL.LC_GATED
input fetch_enable_t fetch_enable_i,
output logic alert_minor_o,
output logic alert_major_o,
@@ -145,6 +148,7 @@
);
localparam int unsigned PMP_NUM_CHAN = 3;
+ // SEC_CM: CORE.DATA_REG_SW.SCA
localparam bit DataIndTiming = SecureIbex;
localparam bit PCIncrCheck = SecureIbex;
localparam bit ShadowCSR = 1'b0;
@@ -177,6 +181,7 @@
logic [31:0] dummy_instr_seed;
logic icache_enable;
logic icache_inval;
+ logic icache_ecc_error;
logic pc_mismatch_alert;
logic csr_shadow_err;
@@ -428,6 +433,7 @@
.dummy_instr_seed_i (dummy_instr_seed),
.icache_enable_i (icache_enable),
.icache_inval_i (icache_inval),
+ .icache_ecc_error_o (icache_ecc_error),
// branch targets
.branch_target_ex_i(branch_target_ex),
@@ -461,6 +467,7 @@
if (SecureIbex) begin : g_instr_req_gated_secure
// For secure Ibex fetch_enable_i must be a specific multi-bit pattern to enable instruction
// fetch
+ // SEC_CM: FETCH.CTRL.LC_GATED
assign instr_req_gated = instr_req_int & (fetch_enable_i == FetchEnableOn);
end else begin : g_instr_req_gated_non_secure
// For non secure Ibex only the bottom bit of fetch enable is considered
@@ -784,6 +791,7 @@
if (RegFileECC) begin : gen_regfile_ecc
+ // SEC_CM: DATA_REG_SW.INTEGRITY
logic [1:0] rf_ecc_err_a, rf_ecc_err_b;
logic rf_ecc_err_a_id, rf_ecc_err_b_id;
@@ -846,8 +854,7 @@
///////////////////
// Minor alert - core is in a recoverable state
- // TODO add I$ ECC errors here
- assign alert_minor_o = 1'b0;
+ assign alert_minor_o = icache_ecc_error;
// Major alert - core is unrecoverable
assign alert_major_o = rf_ecc_err_comb | pc_mismatch_alert | csr_shadow_err;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
index 93f3b84..aa32820 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_cs_registers.sv
@@ -696,6 +696,8 @@
mstack_en = 1'b1;
if (!mcause_d[5]) begin
+ // SEC_CM: EXCEPTION.CTRL_FLOW.LOCAL_ESC
+ // SEC_CM: EXCEPTION.CTRL_FLOW.GLOBAL_ESC
cpuctrl_we = 1'b1;
cpuctrl_d.sync_exc_seen = 1'b1;
@@ -716,6 +718,8 @@
mstatus_en = 1'b1;
mstatus_d.mie = mstatus_q.mpie; // re-enable interrupts
+ // SEC_CM: EXCEPTION.CTRL_FLOW.LOCAL_ESC
+ // SEC_CM: EXCEPTION.CTRL_FLOW.GLOBAL_ESC
cpuctrl_we = 1'b1;
cpuctrl_d.sync_exc_seen = 1'b0;
@@ -1502,6 +1506,7 @@
// Generate fixed time execution bit
if (DataIndTiming) begin : gen_dit
+ // SEC_CM: CORE.DATA_REG_SW.SCA
assign cpuctrl_wdata.data_ind_timing = cpuctrl_wdata_raw.data_ind_timing;
end else begin : gen_no_dit
@@ -1517,6 +1522,7 @@
// Generate dummy instruction signals
if (DummyInstructions) begin : gen_dummy
+ // SEC_CM: CTRL_FLOW.UNPREDICTABLE
assign cpuctrl_wdata.dummy_instr_en = cpuctrl_wdata_raw.dummy_instr_en;
assign cpuctrl_wdata.dummy_instr_mask = cpuctrl_wdata_raw.dummy_instr_mask;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_dummy_instr.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_dummy_instr.sv
index 979ea93..ba33adc 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_dummy_instr.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_dummy_instr.sv
@@ -8,6 +8,7 @@
* Provides pseudo-randomly inserted fake instructions for secure code obfuscation
*/
+// SEC_CM: CTRL_FLOW.UNPREDICTABLE
module ibex_dummy_instr import ibex_pkg::*; #(
parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv
index e4f4ed2..c15a29b 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_icache.sv
@@ -64,7 +64,8 @@
// Cache status
input logic icache_enable_i,
input logic icache_inval_i,
- output logic busy_o
+ output logic busy_o,
+ output logic ecc_error_o
);
// Number of fill buffers (must be >= 2)
@@ -276,7 +277,7 @@
// Append ECC checkbits to write data if required
if (ICacheECC) begin : gen_ecc_wdata
-
+ // SEC_CM: ICACHE.MEM.INTEGRITY
// Tagram ECC
// Reuse the same ecc encoding module for larger cache sizes by padding with zeros
logic [21:0] tag_ecc_input_padded;
@@ -401,6 +402,7 @@
// ECC checking logic
if (ICacheECC) begin : gen_data_ecc_checking
+ // SEC_CM: ICACHE.MEM.INTEGRITY
logic [IC_NUM_WAYS-1:0] tag_err_ic1;
logic [IC_LINE_BEATS*2-1:0] data_err_ic1;
logic ecc_correction_write_d, ecc_correction_write_q;
@@ -441,7 +443,12 @@
end
- assign ecc_err_ic1 = lookup_valid_ic1 & ((|data_err_ic1) | (|tag_err_ic1));
+ // Tag ECC across all ways is always expected to be correct so the check does not need to be
+ // qualified by hit or tag valid. Initial (invalid with correct ECC) tags are written on reset
+ // and all further tag writes produce correct ECC. For data ECC no initialisation is done on
+ // reset so unused data (in particular those ways that don't have a valid tag) may have
+ // incorrect ECC. We only check data ECC where tags indicate it is valid and we have hit on it.
+ assign ecc_err_ic1 = lookup_valid_ic1 & (((|data_err_ic1) & tag_hit_ic1) | (|tag_err_ic1));
// Error correction
// All ways will be invalidated on a tag error to prevent X-propagation from data_err_ic1 on
@@ -500,12 +507,15 @@
assign ecc_write_ways = ecc_correction_ways_q;
assign ecc_write_index = ecc_correction_index_q;
+ assign ecc_error_o = ecc_err_ic1;
end else begin : gen_no_data_ecc
assign ecc_err_ic1 = 1'b0;
assign ecc_write_req = 1'b0;
assign ecc_write_ways = '0;
assign ecc_write_index = '0;
assign hit_data_ic1 = hit_data_ecc_ic1;
+
+ assign ecc_error_o = 1'b0;
end
///////////////////////////////
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
index 2e79573..a00f6bf 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_id_stage.sv
@@ -658,6 +658,7 @@
// (condition pass/fail used same cycle as generated instruction request)
assign branch_set_raw = branch_set_raw_d;
end else begin : g_branch_set_flop
+ // SEC_CM: CORE.DATA_REG_SW.SCA
// Branch set flopped without branch target ALU, or in fixed time execution mode
// (condition pass/fail used next cycle where branch target is calculated)
logic branch_set_raw_q;
@@ -703,6 +704,7 @@
// Branch condition is calculated in the first cycle and flopped for use in the second cycle
// (only used in fixed time execution mode to determine branch destination).
if (DataIndTiming) begin : g_sec_branch_taken
+ // SEC_CM: CORE.DATA_REG_SW.SCA
logic branch_taken_q;
always_ff @(posedge clk_i or negedge rst_ni) begin
@@ -799,6 +801,7 @@
// cond branch operation
// All branches take two cycles in fixed time execution mode, regardless of branch
// condition.
+ // SEC_CM: CORE.DATA_REG_SW.SCA
id_fsm_d = (data_ind_timing_i || (!BranchTargetALU && branch_decision_i)) ?
MULTI_CYCLE : FIRST_CYCLE;
stall_branch = (~BranchTargetALU & branch_decision_i) | data_ind_timing_i;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
index aa63257..2bb2b12 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_if_stage.sv
@@ -87,12 +87,13 @@
input exc_pc_sel_e exc_pc_mux_i, // selects ISR address
input exc_cause_e exc_cause, // selects ISR address for
// vectorized interrupt lines
- input logic dummy_instr_en_i,
- input logic [2:0] dummy_instr_mask_i,
- input logic dummy_instr_seed_en_i,
- input logic [31:0] dummy_instr_seed_i,
- input logic icache_enable_i,
- input logic icache_inval_i,
+ input logic dummy_instr_en_i,
+ input logic [2:0] dummy_instr_mask_i,
+ input logic dummy_instr_seed_en_i,
+ input logic [31:0] dummy_instr_seed_i,
+ input logic icache_enable_i,
+ input logic icache_inval_i,
+ output logic icache_ecc_error_o,
// jump and branch target
input logic [31:0] branch_target_ex_i, // branch/jump target address
@@ -251,7 +252,8 @@
.icache_enable_i ( icache_enable_i ),
.icache_inval_i ( icache_inval_i ),
- .busy_o ( prefetch_busy )
+ .busy_o ( prefetch_busy ),
+ .ecc_error_o ( icache_ecc_error_o )
);
end else begin : gen_prefetch_buffer
// prefetch buffer, caches a fixed number of instructions
@@ -301,6 +303,23 @@
assign ic_data_write_o = 'b0;
assign ic_data_addr_o = 'b0;
assign ic_data_wdata_o = 'b0;
+ assign icache_ecc_error_o = 'b0;
+
+`ifndef SYNTHESIS
+ // If we don't instantiate an icache and this is a simulation then we have a problem because the
+ // simulator might discard the icache module entirely, including some DPI exports that it
+ // implies. This then causes problems for linking against C++ testbench code that expected them.
+ // As a slightly ugly hack, let's define the DPI functions here (the real versions are defined
+ // in prim_util_get_scramble_params.svh)
+ export "DPI-C" function simutil_get_scramble_key;
+ export "DPI-C" function simutil_get_scramble_nonce;
+ function automatic int simutil_get_scramble_key(output bit [127:0] val);
+ return 0;
+ endfunction
+ function automatic int simutil_get_scramble_nonce(output bit [319:0] nonce);
+ return 0;
+ endfunction
+`endif
end
assign unused_fetch_addr_n0 = fetch_addr_n[0];
@@ -340,6 +359,7 @@
// Dummy instruction insertion
if (DummyInstructions) begin : gen_dummy_instr
+ // SEC_CM: CTRL_FLOW.UNPREDICTABLE
logic insert_dummy_instr;
logic [31:0] dummy_instr_data;
@@ -462,6 +482,7 @@
// Check for expected increments of the PC when security hardening enabled
if (PCIncrCheck) begin : g_secure_pc
+ // SEC_CM: PC.CTRL_FLOW.CONSISTENCY
logic [31:0] prev_instr_addr_incr, prev_instr_addr_incr_buf;
logic prev_instr_seq_q, prev_instr_seq_d;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv
index 1f44167..4f986d0 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_lockstep.sv
@@ -6,6 +6,8 @@
// This module instantiates a second copy of the core logic, and compares it's outputs against
// those from the main core. The second core runs synchronously with the main core, delayed by
// LockstepOffset cycles.
+
+// SEC_CM: LOGIC.SHADOW
module ibex_lockstep import ibex_pkg::*; #(
parameter int unsigned LockstepOffset = 2,
parameter bit PMPEnable = 1'b0,
@@ -241,6 +243,7 @@
// Bus integrity checking //
////////////////////////////
+ // SEC_CM: BUS.INTEGRITY
logic bus_intg_err;
logic [1:0] instr_intg_err, data_intg_err;
logic [31:0] unused_wdata;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_fast.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_fast.sv
index 79ed5bc..3f0d27a 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_fast.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_fast.sv
@@ -423,6 +423,7 @@
// Note with data-independent time option, the full divide operation will proceed as
// normal and will naturally return -1
op_remainder_d = '1;
+ // SEC_CM: CORE.DATA_REG_SW.SCA
md_state_d = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A;
// Record that this is a div by zero to stop the sign change at the end of the
// division (in data_ind_timing mode).
@@ -433,6 +434,7 @@
// Note with data-independent time option, the full divide operation will proceed as
// normal and will naturally return operand a
op_remainder_d = {2'b0, op_a_i};
+ // SEC_CM: CORE.DATA_REG_SW.SCA
md_state_d = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A;
end
// 0 - B = 0 iff B == 0
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_slow.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_slow.sv
index b184c5a..214d3f5 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_slow.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_multdiv_slow.sv
@@ -190,6 +190,7 @@
op_a_ext[31:0] & {32{op_b_i[0]}} };
op_b_shift_d = op_b_ext >> 1;
// Proceed with multiplication by 0/1 in data-independent time mode
+ // SEC_CM: CORE.DATA_REG_SW.SCA
md_state_d = (!data_ind_timing_i && ((op_b_ext >> 1) == 0)) ? MD_LAST : MD_COMP;
end
MD_OP_MULH: begin
@@ -205,6 +206,7 @@
// Note with data-independent time option, the full divide operation will proceed as
// normal and will naturally return -1
accum_window_d = {33{1'b1}};
+ // SEC_CM: CORE.DATA_REG_SW.SCA
md_state_d = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A;
// Record that this is a div by zero to stop the sign change at the end of the
// division (in data_ind_timing mode).
@@ -216,6 +218,7 @@
// Note with data-independent time option, the full divide operation will proceed as
// normal and will naturally return operand a
accum_window_d = op_a_ext;
+ // SEC_CM: CORE.DATA_REG_SW.SCA
md_state_d = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A;
end
default:;
@@ -248,6 +251,7 @@
op_b_shift_d = op_b_shift_q >> 1;
// Multiplication is complete once op_b is zero, unless in data_ind_timing mode where
// the maximum possible shift-add operations will be completed regardless of op_b
+ // SEC_CM: CORE.DATA_REG_SW.SCA
md_state_d = ((!data_ind_timing_i && (op_b_shift_d == 0)) ||
(multdiv_count_q == 5'd1)) ? MD_LAST : MD_COMP;
end
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv
index 0cd5e6f..90b0c71 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_ff.sv
@@ -66,6 +66,7 @@
// With dummy instructions enabled, R0 behaves as a real register but will always return 0 for
// real instructions.
if (DummyInstructions) begin : g_dummy_r0
+ // SEC_CM: CTRL_FLOW.UNPREDICTABLE
logic we_r0_dummy;
logic [DataWidth-1:0] rf_r0_q;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv
index 717bcaf..f1e4df7 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_register_file_latch.sv
@@ -122,6 +122,7 @@
// With dummy instructions enabled, R0 behaves as a real register but will always return 0 for
// real instructions.
if (DummyInstructions) begin : g_dummy_r0
+ // SEC_CM: CTRL_FLOW.UNPREDICTABLE
logic we_r0_dummy;
logic r0_clock;
logic [DataWidth-1:0] mem_r0;
diff --git a/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv b/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv
index a33a8fd..b566bb1 100644
--- a/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv
+++ b/hw/vendor/lowrisc_ibex/rtl/ibex_top.sv
@@ -422,8 +422,9 @@
if (ICacheScramble) begin : gen_scramble
- // Scramble key valid starts with OTP returning new valid key and stays high
- // until we request a new valid key.
+ // SEC_CM: ICACHE.MEM.SCRAMBLE
+ // Scramble key valid starts with OTP returning new valid key and stays high
+ // until we request a new valid key.
assign scramble_key_valid_d = scramble_req_q ? scramble_key_valid_i :
icache_inval ? 1'b0 :
scramble_key_valid_q;
@@ -476,6 +477,7 @@
for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_rams_inner
+ // SEC_CM: ICACHE.MEM.SCRAMBLE
// Tag RAM instantiation
prim_ram_1p_scr #(
.Width (TagSizeECC),
@@ -563,6 +565,7 @@
// Redundant lockstep core implementation
if (Lockstep) begin : gen_lockstep
+ // SEC_CM: LOGIC.SHADOW
// Note: certain synthesis tools like DC are very smart at optimizing away redundant logic.
// Hence, we have to insert an optimization barrier at the IOs of the lockstep Ibex.
// This is achieved by manually buffering each bit using prim_buf.