Skip to content

Commit 5428a5a

Browse files
SamuelRiedelnasahlpa
authored andcommitted
[sw] Add mcounteren_writable test
Software test to verify that the `mcounteren_writable` can be set and cleared and locked. This test also verifies that it locks the `mcounteren` CSR in Ibex Signed-off-by: Samuel Riedel <sriedel@lowrisc.org>
1 parent 6876667 commit 5428a5a

4 files changed

Lines changed: 195 additions & 0 deletions

File tree

hw/top_earlgrey/data/ip/chip_rv_core_ibex_testplan.hjson

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,16 @@
226226
tests: ["chip_sw_rv_core_ibex_lockstep_glitch"]
227227
bazel: []
228228
}
229+
{
230+
name: chip_sw_rv_core_ibex_mcounteren_writable
231+
desc: '''Verifies that the mcounteren_writable register is lockable.
232+
'''
233+
stage: V2
234+
si_stage: SV1
235+
lc_states: ["PROD"]
236+
tests: ["chip_sw_rv_core_ibex_mcounteren_writable"]
237+
bazel: ["//sw/device/tests:rv_core_ibex_mcounteren_writable_test"]
238+
}
229239
{
230240
name: chip_sw_rv_core_ibex_alerts
231241
desc: '''Inject and verify all available faults in rv_core_ibex / ibex_top.

hw/top_earlgrey/dv/chip_sim_cfg.hjson

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,6 +2046,13 @@
20462046
sw_images: ["//sw/device/tests:rv_core_ibex_icache_invalidate_test:1:new_rules"]
20472047
en_run_modes: ["sw_test_mode_test_rom"]
20482048
}
2049+
{
2050+
name: chip_sw_rv_core_ibex_mcounteren_writable
2051+
uvm_test_seq: chip_sw_base_vseq
2052+
sw_images: ["//sw/device/tests:rv_core_ibex_mcounteren_writable_test:1:new_rules"]
2053+
en_run_modes: ["sw_test_mode_test_rom"]
2054+
run_opts: ["+sw_test_timeout_ns=7_000_000"]
2055+
}
20492056
{
20502057
name: chip_sw_usb_ast_clk_calib
20512058
uvm_test_seq: "chip_sw_usb_ast_clk_calib_vseq"

sw/device/tests/BUILD

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7299,6 +7299,20 @@ test_suite(
72997299
],
73007300
)
73017301

7302+
opentitan_test(
7303+
name = "rv_core_ibex_mcounteren_writable_test",
7304+
srcs = ["rv_core_ibex_mcounteren_writable_test.c"],
7305+
exec_env = EARLGREY_TEST_ENVS,
7306+
deps = [
7307+
"//hw/top:rv_core_ibex_c_regs",
7308+
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
7309+
"//sw/device/lib/base:mmio",
7310+
"//sw/device/lib/base:multibits",
7311+
"//sw/device/lib/testing/test_framework:check",
7312+
"//sw/device/lib/testing/test_framework:ottf_main",
7313+
],
7314+
)
7315+
73027316
opentitan_test(
73037317
name = "rv_core_ibex_epmp_test_functest",
73047318
srcs = ["//sw/device/silicon_creator/manuf/tests:idle_functest.c"],
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
// Copyright lowRISC contributors (OpenTitan project).
2+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
// Verifies that the mcounteren_writable register properly locks the mcounteren
6+
// CSR and that the register is write-protected when locked.
7+
8+
#include "sw/device/lib/base/mmio.h"
9+
#include "sw/device/lib/base/multibits.h"
10+
#include "sw/device/lib/testing/test_framework/check.h"
11+
#include "sw/device/lib/testing/test_framework/ottf_main.h"
12+
13+
#include "hw/top/rv_core_ibex_regs.h"
14+
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
15+
16+
#define MCOUNTERS_DISABLE (0x0)
17+
#define MCOUNTERS_ENABLE (0x5)
18+
19+
OTTF_DEFINE_TEST_CONFIG();
20+
21+
// Helper functions for accessing the mcounteren CSR
22+
static inline uint32_t csr_read_mcounteren(void) {
23+
uint32_t val;
24+
asm volatile("csrr %0, mcounteren" : "=r"(val));
25+
return val;
26+
}
27+
28+
static inline void csr_write_mcounteren(uint32_t val) {
29+
asm volatile("csrw mcounteren, %0" ::"r"(val));
30+
}
31+
32+
bool test_main(void) {
33+
uint32_t mcounteren_val;
34+
uint32_t mcounteren_writable_val;
35+
uint32_t regwen;
36+
37+
mmio_region_t ibex_cfg =
38+
mmio_region_from_addr(TOP_EARLGREY_RV_CORE_IBEX_CFG_BASE_ADDR);
39+
40+
// Initialize mcounteren to a known value for testing.
41+
csr_write_mcounteren(MCOUNTERS_DISABLE);
42+
43+
// Check defaults
44+
// MCOUNTEREN_WRITABLE should default to kMultiBitBool4True.
45+
mcounteren_writable_val =
46+
mmio_region_read32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET);
47+
CHECK(mcounteren_writable_val == kMultiBitBool4True,
48+
"MCOUNTEREN_WRITABLE default should be MuBi4True (0x%x), got 0x%x",
49+
kMultiBitBool4True, mcounteren_writable_val);
50+
// REGWEN should be enabled by default.
51+
regwen = mmio_region_read32(
52+
ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REGWEN_REG_OFFSET);
53+
CHECK(regwen == 1, "MCOUNTEREN_WRITABLE_REGWEN default should be 1, got 0x%x",
54+
regwen);
55+
56+
// Since MCOUNTEREN_WRITABLE is True, writes to mcounteren should succeed.
57+
csr_write_mcounteren(MCOUNTERS_ENABLE);
58+
mcounteren_val = csr_read_mcounteren();
59+
CHECK(mcounteren_val == MCOUNTERS_ENABLE,
60+
"mcounteren should be writable when MCOUNTEREN_WRITABLE is True. "
61+
"Expected 0x%x, got 0x%x",
62+
MCOUNTERS_ENABLE, mcounteren_val);
63+
64+
// Locking should succeed while REGWEN is enabled.
65+
mmio_region_write32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET,
66+
kMultiBitBool4False);
67+
mcounteren_writable_val =
68+
mmio_region_read32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET);
69+
CHECK(mcounteren_writable_val == kMultiBitBool4False,
70+
"MCOUNTEREN_WRITABLE write should succeed when unlocked, got 0x%x",
71+
mcounteren_writable_val);
72+
73+
// Since MCOUNTEREN_WRITABLE is now False, writes to mcounteren should be
74+
// ignored.
75+
csr_write_mcounteren(MCOUNTERS_DISABLE);
76+
mcounteren_val = csr_read_mcounteren();
77+
CHECK(mcounteren_val == MCOUNTERS_ENABLE,
78+
"mcounteren writes should be blocked when MCOUNTEREN_WRITABLE is "
79+
"False. Expected 0x%x, got 0x%x",
80+
MCOUNTERS_ENABLE, mcounteren_val);
81+
82+
// Unlocking should succeed while REGWEN is enabled.
83+
mmio_region_write32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET,
84+
kMultiBitBool4True);
85+
mcounteren_writable_val =
86+
mmio_region_read32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET);
87+
CHECK(mcounteren_writable_val == kMultiBitBool4True,
88+
"MCOUNTEREN_WRITABLE write should succeed when unlocked, got 0x%x",
89+
mcounteren_writable_val);
90+
91+
// Ensure mcounteren is writable again after restoring MCOUNTEREN_WRITABLE to
92+
// True.
93+
csr_write_mcounteren(MCOUNTERS_DISABLE);
94+
mcounteren_val = csr_read_mcounteren();
95+
CHECK(mcounteren_val == MCOUNTERS_DISABLE,
96+
"mcounteren should be writable again after restoring config. Expected "
97+
"0x%x, got 0x%x",
98+
MCOUNTERS_DISABLE, mcounteren_val);
99+
100+
// Enable mcounteren again.
101+
csr_write_mcounteren(MCOUNTERS_ENABLE);
102+
mcounteren_val = csr_read_mcounteren();
103+
CHECK(mcounteren_val == MCOUNTERS_ENABLE,
104+
"mcounteren should be writable again after restoring config. Expected "
105+
"0x%x, got 0x%x",
106+
MCOUNTERS_ENABLE, mcounteren_val);
107+
108+
// Lock again, which should succeed.
109+
mmio_region_write32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET,
110+
kMultiBitBool4False);
111+
mcounteren_writable_val =
112+
mmio_region_read32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET);
113+
CHECK(mcounteren_writable_val == kMultiBitBool4False,
114+
"MCOUNTEREN_WRITABLE write should succeed when unlocked, got 0x%x",
115+
mcounteren_writable_val);
116+
117+
// Clear REGWEN to lock MCOUNTEREN_WRITABLE.
118+
mmio_region_write32(ibex_cfg,
119+
RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REGWEN_REG_OFFSET, 0);
120+
regwen = mmio_region_read32(
121+
ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REGWEN_REG_OFFSET);
122+
CHECK(regwen == 0,
123+
"MCOUNTEREN_WRITABLE_REGWEN should read 0 after clearing, got 0x%x",
124+
regwen);
125+
126+
// Write to MCOUNTEREN_WRITABLE while locked should have no effect.
127+
mmio_region_write32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET,
128+
kMultiBitBool4True);
129+
mcounteren_writable_val =
130+
mmio_region_read32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET);
131+
CHECK(mcounteren_writable_val == kMultiBitBool4False,
132+
"MCOUNTEREN_WRITABLE should be unchanged when locked, got 0x%x",
133+
mcounteren_writable_val);
134+
135+
// Since the attempt to flip MCOUNTEREN_WRITABLE to True was
136+
// ignored, writes to mcounteren should be ignored.
137+
csr_write_mcounteren(MCOUNTERS_DISABLE);
138+
mcounteren_val = csr_read_mcounteren();
139+
CHECK(mcounteren_val == MCOUNTERS_ENABLE,
140+
"mcounteren writes should be blocked when MCOUNTEREN_WRITABLE is "
141+
"False. Expected 0x%x, got 0x%x",
142+
MCOUNTERS_ENABLE, mcounteren_val);
143+
144+
// Attempt to re-enable REGWEN should fail
145+
mmio_region_write32(ibex_cfg,
146+
RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REGWEN_REG_OFFSET, 1);
147+
regwen = mmio_region_read32(
148+
ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REGWEN_REG_OFFSET);
149+
CHECK(regwen == 0,
150+
"MCOUNTEREN_WRITABLE_REGWEN should remain 0 after attempted "
151+
"re-enable, got 0x%x",
152+
regwen);
153+
154+
// Write to MCOUNTEREN_WRITABLE while locked should have no effect.
155+
mmio_region_write32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET,
156+
kMultiBitBool4True);
157+
mcounteren_writable_val =
158+
mmio_region_read32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET);
159+
CHECK(mcounteren_writable_val == kMultiBitBool4False,
160+
"MCOUNTEREN_WRITABLE should be unchanged when locked, got 0x%x",
161+
mcounteren_writable_val);
162+
163+
return true;
164+
}

0 commit comments

Comments
 (0)