Skip to content

Commit

Permalink
[flash_ctrl/dv] Add sec_cm_mem_addr_infection test
Browse files Browse the repository at this point in the history
This commit adds a new test to verify the MEM.ADDR_INFECTION countermeasure.
The test issues a host read request to the flash controller, manipulates
the address inside the flash_phy_rd module, and checks, whether the TL-UL
data integrity error is received. This error is expected as the
MEM.ADDR_INFECTION mitigation should infect the data with the faulty address
leading to an integrity error.

Closes #23898

Signed-off-by: Pascal Nasahl <[email protected]>
  • Loading branch information
nasahlpa authored and vogelpi committed Jul 5, 2024
1 parent f4c7229 commit bd5e2ea
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 0 deletions.
10 changes: 10 additions & 0 deletions hw/ip_templates/flash_ctrl/data/flash_ctrl_sec_cm_testplan.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,16 @@
stage: V2S
tests: ["flash_ctrl_rd_intg", "flash_ctrl_access_after_disable"]
}
{
name: sec_cm_mem_addr_infection
desc: '''Verify the countermeasure(s) MEM.ADDR_INFECTION.
Send a flash request from the host, inject a fault into the address inside
the flash_phy_rd module, and check that we receive the expected TL-UL
integrity error.
'''
stage: V2S
tests: ["flash_ctrl_host_addr_infection"]
}
{
name: sec_cm_mem_disable_config_mubi
desc: "Verify the countermeasure(s) MEM_DISABLE.CONFIG.MUBI."
Expand Down
1 change: 1 addition & 0 deletions hw/ip_templates/flash_ctrl/dv/env/flash_ctrl_env.core
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ filesets:
- seq_lib/flash_ctrl_oversize_error_vseq.sv: {is_include_file: true}
- seq_lib/flash_ctrl_connect_vseq.sv: {is_include_file: true}
- seq_lib/flash_ctrl_disable_vseq.sv: {is_include_file: true}
- seq_lib/flash_ctrl_host_addr_infection_vseq.sv: {is_include_file: true}
- seq_lib/flash_ctrl_rd_path_intg_vseq.sv: {is_include_file: true}
- seq_lib/flash_ctrl_wr_path_intg_vseq.sv: {is_include_file: true}
- seq_lib/flash_ctrl_info_part_access_vseq.sv: {is_include_file: true}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

// This sequence issues a read to the flash controller. Inside the flash controller
// a fault is injected into the address. The goal of this sequence is to check,
// whether the data XOR address infection triggers a data integrity violation.
class flash_ctrl_host_addr_infection_vseq extends flash_ctrl_legacy_base_vseq;
`uvm_object_utils(flash_ctrl_host_addr_infection_vseq)
`uvm_object_new

task body();
string path1, path2;
int state_timeout_ns = 100000; // 100us

flash_op_t host;
bit [TL_AW-1:0] tl_addr;
bit [7:0] addr_glitched;
bit saw_err, completed;
data_4s_t rdata;

flash_otf_region_cfg(.scr_mode(OTFCfgTrue), .ecc_mode(OTFCfgTrue));
cfg.clk_rst_vif.wait_clks(10);

cfg.scb_h.expected_alert["fatal_err"].expected = 1;
cfg.scb_h.expected_alert["fatal_err"].max_delay = 2000;
cfg.scb_h.exp_alert_contd["fatal_err"] = 10000;

// We expect that the TL-UL integrity check fails because address used for
// the access gets manipulated and the data XOR address mechanism infects the
// data, resulting in an integrity error.
cfg.scb_h.exp_tl_rsp_intg_err = 1;

// Generate random address for the read access.
tl_addr[OTFBankId] = $urandom_range(0, 1);
tl_addr[OTFHostId-2:2] = $urandom();
tl_addr[1:0] = 'h0;
`uvm_info(`gfn, $sformatf("Original TL-UL address is 'h%0x", tl_addr), UVM_LOW)

// Flip bits in address before the data XOR address infection is done.
path1 = "tb.dut.u_eflash.gen_flash_cores[0].u_core.u_rd.addr_xor_muxed[8:1]";
path2 = "tb.dut.u_eflash.gen_flash_cores[1].u_core.u_rd.addr_xor_muxed[8:1]";
addr_glitched = tl_addr[8:1] ^ (1 << $urandom_range(0, 7));
`uvm_info(`gfn, $sformatf("Forcing %s to value 'h%0x", path1, addr_glitched), UVM_LOW)
`uvm_info(`gfn, $sformatf("Forcing %s to value 'h%0x", path2, addr_glitched), UVM_LOW)
`DV_CHECK(uvm_hdl_force(path1, addr_glitched))
`DV_CHECK(uvm_hdl_force(path2, addr_glitched))

// Perform the memory access.
tl_access_w_abort(.addr(tl_addr), .write(1'b0), .completed(completed),
.saw_err(saw_err),
.tl_access_timeout_ns(cfg.seq_cfg.erase_timeout_ns),
.data(rdata), .check_rsp(0), .blocking(1),
.tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.flash_ral_name]));

csr_utils_pkg::wait_no_outstanding_access();

`uvm_info(`gfn, "Wait until all drain", UVM_LOW)
cfg.clk_rst_vif.wait_clks(100);
`DV_CHECK(uvm_hdl_release(path1))
`DV_CHECK(uvm_hdl_release(path2))

// reset for the next round
cfg.seq_cfg.disable_flash_init = 1;
cfg.seq_cfg.en_init_keys_seeds = 0;
apply_reset();
csr_wr(.ptr(ral.init), .value(1));
`uvm_info("Test","OTP",UVM_LOW)
otp_model();
`DV_SPINWAIT(wait(cfg.flash_ctrl_vif.rd_buf_en == 1);,
"Timed out waiting for rd_buf_en",
state_timeout_ns)
cfg.clk_rst_vif.wait_clks(10);

// disable tlul_err_cnt check
cfg.tlul_core_obs_cnt = cfg.tlul_core_exp_cnt;
endtask

endclass
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
`include "flash_ctrl_oversize_error_vseq.sv"
`include "flash_ctrl_connect_vseq.sv"
`include "flash_ctrl_disable_vseq.sv"
`include "flash_ctrl_host_addr_infection_vseq.sv"
`include "flash_ctrl_rd_path_intg_vseq.sv"
`include "flash_ctrl_wr_path_intg_vseq.sv"
`include "flash_ctrl_info_part_access_vseq.sv"
Expand Down
7 changes: 7 additions & 0 deletions hw/ip_templates/flash_ctrl/dv/flash_ctrl_base_sim_cfg.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,13 @@
"+ecc_mode=1"]
reseed: 1
}
{
name: flash_ctrl_host_addr_infection
uvm_test_seq: flash_ctrl_host_addr_infection_vseq
run_opts: ["+scb_otf_en=1", "+ecc_mode=1",
"+otf_num_hr=100", "+en_always_read=1"]
reseed: 3
}
]

// List of regressions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,16 @@
stage: V2S
tests: ["flash_ctrl_rd_intg", "flash_ctrl_access_after_disable"]
}
{
name: sec_cm_mem_addr_infection
desc: '''Verify the countermeasure(s) MEM.ADDR_INFECTION.
Send a flash request from the host, inject a fault into the address inside
the flash_phy_rd module, and check that we receive the expected TL-UL
integrity error.
'''
stage: V2S
tests: ["flash_ctrl_host_addr_infection"]
}
{
name: sec_cm_mem_disable_config_mubi
desc: "Verify the countermeasure(s) MEM_DISABLE.CONFIG.MUBI."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ filesets:
- seq_lib/flash_ctrl_oversize_error_vseq.sv: {is_include_file: true}
- seq_lib/flash_ctrl_connect_vseq.sv: {is_include_file: true}
- seq_lib/flash_ctrl_disable_vseq.sv: {is_include_file: true}
- seq_lib/flash_ctrl_host_addr_infection_vseq.sv: {is_include_file: true}
- seq_lib/flash_ctrl_rd_path_intg_vseq.sv: {is_include_file: true}
- seq_lib/flash_ctrl_wr_path_intg_vseq.sv: {is_include_file: true}
- seq_lib/flash_ctrl_info_part_access_vseq.sv: {is_include_file: true}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

// This sequence issues a read to the flash controller. Inside the flash controller
// a fault is injected into the address. The goal of this sequence is to check,
// whether the data XOR address infection triggers a data integrity violation.
class flash_ctrl_host_addr_infection_vseq extends flash_ctrl_legacy_base_vseq;
`uvm_object_utils(flash_ctrl_host_addr_infection_vseq)
`uvm_object_new

task body();
string path1, path2;
int state_timeout_ns = 100000; // 100us

flash_op_t host;
bit [TL_AW-1:0] tl_addr;
bit [7:0] addr_glitched;
bit saw_err, completed;
data_4s_t rdata;

flash_otf_region_cfg(.scr_mode(OTFCfgTrue), .ecc_mode(OTFCfgTrue));
cfg.clk_rst_vif.wait_clks(10);

cfg.scb_h.expected_alert["fatal_err"].expected = 1;
cfg.scb_h.expected_alert["fatal_err"].max_delay = 2000;
cfg.scb_h.exp_alert_contd["fatal_err"] = 10000;

// We expect that the TL-UL integrity check fails because address used for
// the access gets manipulated and the data XOR address mechanism infects the
// data, resulting in an integrity error.
cfg.scb_h.exp_tl_rsp_intg_err = 1;

// Generate random address for the read access.
tl_addr[OTFBankId] = $urandom_range(0, 1);
tl_addr[OTFHostId-2:2] = $urandom();
tl_addr[1:0] = 'h0;
`uvm_info(`gfn, $sformatf("Original TL-UL address is 'h%0x", tl_addr), UVM_LOW)

// Flip bits in address before the data XOR address infection is done.
path1 = "tb.dut.u_eflash.gen_flash_cores[0].u_core.u_rd.addr_xor_muxed[8:1]";
path2 = "tb.dut.u_eflash.gen_flash_cores[1].u_core.u_rd.addr_xor_muxed[8:1]";
addr_glitched = tl_addr[8:1] ^ (1 << $urandom_range(0, 7));
`uvm_info(`gfn, $sformatf("Forcing %s to value 'h%0x", path1, addr_glitched), UVM_LOW)
`uvm_info(`gfn, $sformatf("Forcing %s to value 'h%0x", path2, addr_glitched), UVM_LOW)
`DV_CHECK(uvm_hdl_force(path1, addr_glitched))
`DV_CHECK(uvm_hdl_force(path2, addr_glitched))

// Perform the memory access.
tl_access_w_abort(.addr(tl_addr), .write(1'b0), .completed(completed),
.saw_err(saw_err),
.tl_access_timeout_ns(cfg.seq_cfg.erase_timeout_ns),
.data(rdata), .check_rsp(0), .blocking(1),
.tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.flash_ral_name]));

csr_utils_pkg::wait_no_outstanding_access();

`uvm_info(`gfn, "Wait until all drain", UVM_LOW)
cfg.clk_rst_vif.wait_clks(100);
`DV_CHECK(uvm_hdl_release(path1))
`DV_CHECK(uvm_hdl_release(path2))

// reset for the next round
cfg.seq_cfg.disable_flash_init = 1;
cfg.seq_cfg.en_init_keys_seeds = 0;
apply_reset();
csr_wr(.ptr(ral.init), .value(1));
`uvm_info("Test","OTP",UVM_LOW)
otp_model();
`DV_SPINWAIT(wait(cfg.flash_ctrl_vif.rd_buf_en == 1);,
"Timed out waiting for rd_buf_en",
state_timeout_ns)
cfg.clk_rst_vif.wait_clks(10);

// disable tlul_err_cnt check
cfg.tlul_core_obs_cnt = cfg.tlul_core_exp_cnt;
endtask

endclass
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
`include "flash_ctrl_oversize_error_vseq.sv"
`include "flash_ctrl_connect_vseq.sv"
`include "flash_ctrl_disable_vseq.sv"
`include "flash_ctrl_host_addr_infection_vseq.sv"
`include "flash_ctrl_rd_path_intg_vseq.sv"
`include "flash_ctrl_wr_path_intg_vseq.sv"
`include "flash_ctrl_info_part_access_vseq.sv"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,13 @@
"+ecc_mode=1"]
reseed: 1
}
{
name: flash_ctrl_host_addr_infection
uvm_test_seq: flash_ctrl_host_addr_infection_vseq
run_opts: ["+scb_otf_en=1", "+ecc_mode=1",
"+otf_num_hr=100", "+en_always_read=1"]
reseed: 3
}
]

// List of regressions.
Expand Down

0 comments on commit bd5e2ea

Please sign in to comment.