Skip to content

Commit

Permalink
[rtl] Switch to multi-bit fetch enable
Browse files Browse the repository at this point in the history
The multi-bit enable aids security hardening. For non secure Ibex all
but the bottom bit is ignored so it is effectively a single bit enable.
  • Loading branch information
GregAC committed Feb 21, 2022
1 parent 3475b91 commit b18eceb
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 78 deletions.
7 changes: 5 additions & 2 deletions doc/02_user/integration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,12 @@ Interfaces
+----------------------------+------------------------------------------------------------------------+
| ``double_fault_seen_o`` | A double fault was observed, see :ref:`double-fault-detect` |
+----------------------------+-------------------------+-----+----------------------------------------+
| ``fetch_enable_i`` | 1 | in | Allow the core to fetch instructions. |
| ``fetch_enable_i`` | 4 | in | Allow the core to fetch instructions. |
| | | | If this bit is set low, the core will |
| | | | pause fetching new instructions. |
| | | | pause fetching new instructions. A |
| | | | multi-bit encoding scheme is used. See |
| | | | `FetchEnableOn` / `FetchEnableOff` in |
| | | | :file:`rtl/ibex_pkg.sv` |
+----------------------------+-------------------------+-----+----------------------------------------+
| ``core_sleep_o`` | 1 | out | Core in WFI with no outstanding data |
| | | | or instruction accesses. Deasserts |
Expand Down
96 changes: 48 additions & 48 deletions dv/riscv_compliance/rtl/ibex_riscv_compliance.sv
Original file line number Diff line number Diff line change
Expand Up @@ -131,57 +131,57 @@ module ibex_riscv_compliance (
.DmHaltAddr (32'h00000000 ),
.DmExceptionAddr (32'h00000000 )
) u_top (
.clk_i (clk_sys ),
.rst_ni (rst_sys_n ),
.clk_i (clk_sys ),
.rst_ni (rst_sys_n ),

.test_en_i ('b0 ),
.scan_rst_ni (1'b1 ),
.ram_cfg_i ('b0 ),
.test_en_i ('b0 ),
.scan_rst_ni (1'b1 ),
.ram_cfg_i ('b0 ),

.hart_id_i (32'b0 ),
.hart_id_i (32'b0 ),
// First instruction executed is at 0x0 + 0x80
.boot_addr_i (32'h00000000 ),

.instr_req_o (host_req[CoreI] ),
.instr_gnt_i (host_gnt[CoreI] ),
.instr_rvalid_i (host_rvalid[CoreI]),
.instr_addr_o (host_addr[CoreI] ),
.instr_rdata_i (host_rdata[CoreI] ),
.instr_rdata_intg_i ('0 ),
.instr_err_i (host_err[CoreI] ),

.data_req_o (host_req[CoreD] ),
.data_gnt_i (host_gnt[CoreD] ),
.data_rvalid_i (host_rvalid[CoreD]),
.data_we_o (host_we[CoreD] ),
.data_be_o (host_be[CoreD] ),
.data_addr_o (host_addr[CoreD] ),
.data_wdata_o (host_wdata[CoreD] ),
.data_wdata_intg_o ( ),
.data_rdata_i (host_rdata[CoreD] ),
.data_rdata_intg_i ('0 ),
.data_err_i (host_err[CoreD] ),

.irq_software_i (1'b0 ),
.irq_timer_i (1'b0 ),
.irq_external_i (1'b0 ),
.irq_fast_i (15'b0 ),
.irq_nm_i (1'b0 ),

.scramble_key_valid_i ('0 ),
.scramble_key_i ('0 ),
.scramble_nonce_i ('0 ),
.scramble_req_o ( ),

.debug_req_i ('b0 ),
.crash_dump_o ( ),
.double_fault_seen_o ( ),

.fetch_enable_i ('b1 ),
.alert_minor_o ( ),
.alert_major_internal_o ( ),
.alert_major_bus_o ( ),
.core_sleep_o ( )
.boot_addr_i (32'h00000000 ),

.instr_req_o (host_req[CoreI] ),
.instr_gnt_i (host_gnt[CoreI] ),
.instr_rvalid_i (host_rvalid[CoreI] ),
.instr_addr_o (host_addr[CoreI] ),
.instr_rdata_i (host_rdata[CoreI] ),
.instr_rdata_intg_i ('0 ),
.instr_err_i (host_err[CoreI] ),

.data_req_o (host_req[CoreD] ),
.data_gnt_i (host_gnt[CoreD] ),
.data_rvalid_i (host_rvalid[CoreD] ),
.data_we_o (host_we[CoreD] ),
.data_be_o (host_be[CoreD] ),
.data_addr_o (host_addr[CoreD] ),
.data_wdata_o (host_wdata[CoreD] ),
.data_wdata_intg_o ( ),
.data_rdata_i (host_rdata[CoreD] ),
.data_rdata_intg_i ('0 ),
.data_err_i (host_err[CoreD] ),

.irq_software_i (1'b0 ),
.irq_timer_i (1'b0 ),
.irq_external_i (1'b0 ),
.irq_fast_i (15'b0 ),
.irq_nm_i (1'b0 ),

.scramble_key_valid_i ('0 ),
.scramble_key_i ('0 ),
.scramble_nonce_i ('0 ),
.scramble_req_o ( ),

.debug_req_i ('b0 ),
.crash_dump_o ( ),
.double_fault_seen_o ( ),

.fetch_enable_i (ibex_pkg::FetchEnableOn),
.alert_minor_o ( ),
.alert_major_internal_o ( ),
.alert_major_bus_o ( ),
.core_sleep_o ( )
);

// SRAM block for instruction and data storage
Expand Down
28 changes: 14 additions & 14 deletions dv/uvm/core_ibex/env/core_ibex_dut_probe_if.sv
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@

// Interface to probe DUT internal signal
interface core_ibex_dut_probe_if(input logic clk);
logic reset;
logic illegal_instr;
logic ecall;
logic wfi;
logic ebreak;
logic dret;
logic mret;
logic fetch_enable;
logic core_sleep;
logic alert_minor;
logic alert_major_internal;
logic alert_major_bus;
logic debug_req;
ibex_pkg::priv_lvl_e priv_mode;
logic reset;
logic illegal_instr;
logic ecall;
logic wfi;
logic ebreak;
logic dret;
logic mret;
ibex_pkg::fetch_enable_t fetch_enable;
logic core_sleep;
logic alert_minor;
logic alert_major_internal;
logic alert_major_bus;
logic debug_req;
ibex_pkg::priv_lvl_e priv_mode;

clocking dut_cb @(posedge clk);
output fetch_enable;
Expand Down
6 changes: 3 additions & 3 deletions dv/uvm/core_ibex/tests/core_ibex_base_test.sv
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,10 @@ class core_ibex_base_test extends uvm_test;
enable_irq_seq = cfg.enable_irq_single_seq || cfg.enable_irq_multiple_seq;
phase.raise_objection(this);
cur_run_phase = phase;
dut_vif.dut_cb.fetch_enable <= 1'b0;
dut_vif.dut_cb.fetch_enable <= ibex_pkg::FetchEnableOff;
clk_vif.wait_clks(100);
load_binary_to_mem();
dut_vif.dut_cb.fetch_enable <= 1'b1;
dut_vif.dut_cb.fetch_enable <= ibex_pkg::FetchEnableOn;
send_stimulus();
wait_for_test_done();
cur_run_phase = null;
Expand Down Expand Up @@ -194,7 +194,7 @@ class core_ibex_base_test extends uvm_test;
check_perf_stats();
// De-assert fetch enable to finish the test
clk_vif.wait_clks(10);
dut_vif.dut_cb.fetch_enable <= 1'b0;
dut_vif.dut_cb.fetch_enable <= ibex_pkg::FetchEnableOff;
end
// Wait some time for the remaining instruction to finish
clk_vif.wait_clks(3000);
Expand Down
4 changes: 2 additions & 2 deletions dv/uvm/core_ibex/tests/core_ibex_test_lib.sv
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class core_ibex_reset_test extends core_ibex_base_test;
clk_vif.wait_clks($urandom_range(0, 50000));
fork
begin
dut_vif.dut_cb.fetch_enable <= 1'b0;
dut_vif.dut_cb.fetch_enable <= ibex_pkg::FetchEnableOff;
clk_vif.apply_reset(.reset_width_clks (100));
end
begin
Expand All @@ -61,7 +61,7 @@ class core_ibex_reset_test extends core_ibex_base_test;
end
join
// Assert fetch_enable to have the core start executing from boot address
dut_vif.dut_cb.fetch_enable <= 1'b1;
dut_vif.dut_cb.fetch_enable <= ibex_pkg::FetchEnableOn;
end
endtask

Expand Down
2 changes: 1 addition & 1 deletion examples/simple_system/rtl/ibex_simple_system.sv
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ module ibex_simple_system (
.crash_dump_o (),
.double_fault_seen_o (),

.fetch_enable_i ('b1),
.fetch_enable_i (ibex_pkg::FetchEnableOn),
.alert_minor_o (),
.alert_major_internal_o (),
.alert_major_bus_o (),
Expand Down
21 changes: 19 additions & 2 deletions rtl/ibex_core.sv
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ module ibex_core import ibex_pkg::*; #(
`endif

// CPU Control Signals
input logic fetch_enable_i,
input fetch_enable_t fetch_enable_i,
output logic alert_minor_o,
output logic alert_major_o,
output logic icache_inval_o,
Expand Down Expand Up @@ -450,8 +450,25 @@ module ibex_core import ibex_pkg::*; #(
// available
assign perf_iside_wait = id_in_ready & ~instr_valid_id;

// Multi-bit fetch enable used when SecureIbex == 1. When SecureIbex == 0 only use the bottom-bit
// of fetch_enable_i. Ensure the multi-bit encoding has the bottom bit set for on and unset for
// off so FetchEnableOn/FetchEnableOff can be used without needing to know the value of
// SecureIbex.
`ASSERT_INIT(FetchEnableSecureOnBottomBitSet, FetchEnableOn[0] == 1'b1)
`ASSERT_INIT(FetchEnableSecureOffBottomBitClear, FetchEnableOff[0] == 1'b0)

// fetch_enable_i can be used to stop the core fetching new instructions
assign instr_req_gated = instr_req_int & fetch_enable_i;
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
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
logic unused_fetch_enable;
assign unused_fetch_enable = ^fetch_enable_i[$bits(fetch_enable_t)-1:1];

assign instr_req_gated = instr_req_int & fetch_enable_i[0];
end

//////////////
// ID stage //
Expand Down
4 changes: 2 additions & 2 deletions rtl/ibex_lockstep.sv
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ module ibex_lockstep import ibex_pkg::*; #(
input crash_dump_t crash_dump_i,
input logic double_fault_seen_i,

input logic fetch_enable_i,
input fetch_enable_t fetch_enable_i,
output logic alert_minor_o,
output logic alert_major_internal_o,
output logic alert_major_bus_o,
Expand Down Expand Up @@ -182,7 +182,7 @@ module ibex_lockstep import ibex_pkg::*; #(
logic [14:0] irq_fast;
logic irq_nm;
logic debug_req;
logic fetch_enable;
fetch_enable_t fetch_enable;
logic ic_scr_key_valid;
} delayed_inputs_t;

Expand Down
11 changes: 11 additions & 0 deletions rtl/ibex_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -606,4 +606,15 @@ package ibex_pkg;
128'h14e8cecae3040d5e12286bb3cc113298;
parameter logic [SCRAMBLE_NONCE_W-1:0] RndCnstIbexNonceDefault =
64'hf79780bc735f3843;

// Fetch enable. Mult-bit signal used for security hardening. For non-secure implementation all
// bits other than the bottom bit are ignored.
typedef logic [3:0] fetch_enable_t;

// Note that if adjusting these parameters it is assumed the bottom bit is set for On and unset
// for Off. This allows the use of FetchEnableOn/FetchEnableOff to work for both secure and
// non-secure Ibex. If this assumption is broken the RTL that uses the fetch_enable signal within
// `ibex_core` may need adjusting.
parameter fetch_enable_t FetchEnableOn = 4'b1001;
parameter fetch_enable_t FetchEnableOff = 4'b0110;
endpackage
14 changes: 11 additions & 3 deletions rtl/ibex_top.sv
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ module ibex_top import ibex_pkg::*; #(
`endif

// CPU Control Signals
input logic fetch_enable_i,
input fetch_enable_t fetch_enable_i,
output logic alert_minor_o,
output logic alert_major_internal_o,
output logic alert_major_bus_o,
Expand Down Expand Up @@ -182,6 +182,8 @@ module ibex_top import ibex_pkg::*; #(
logic scramble_key_valid_d, scramble_key_valid_q;
logic scramble_req_d, scramble_req_q;

fetch_enable_t fetch_enable_buf;

/////////////////////
// Main clock gate //
/////////////////////
Expand All @@ -208,6 +210,12 @@ module ibex_top import ibex_pkg::*; #(
// Core instantiation //
////////////////////////

// Buffer fetch_enable_i to prevent synthesis optimising away multi-bit signal
prim_buf #(.Width($bits(fetch_enable_t))) u_fetch_enable_buf (
.in_i (fetch_enable_i),
.out_o(fetch_enable_buf)
);

ibex_core #(
.PMPEnable (PMPEnable),
.PMPGranularity (PMPGranularity),
Expand Down Expand Up @@ -322,7 +330,7 @@ module ibex_top import ibex_pkg::*; #(
.rvfi_ext_mcycle,
`endif

.fetch_enable_i,
.fetch_enable_i(fetch_enable_buf),
.alert_minor_o (core_alert_minor),
.alert_major_o (core_alert_major),
.icache_inval_o(icache_inval),
Expand Down Expand Up @@ -656,7 +664,7 @@ module ibex_top import ibex_pkg::*; #(
logic debug_req_local;
crash_dump_t crash_dump_local;
logic double_fault_seen_local;
logic fetch_enable_local;
fetch_enable_t fetch_enable_local;

logic icache_inval_local;
logic core_busy_local;
Expand Down
2 changes: 1 addition & 1 deletion rtl/ibex_top_tracing.sv
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
output logic double_fault_seen_o,

// CPU Control Signals
input logic fetch_enable_i,
input fetch_enable_t fetch_enable_i,
output logic alert_minor_o,
output logic alert_major_internal_o,
output logic alert_major_bus_o,
Expand Down

0 comments on commit b18eceb

Please sign in to comment.