Skip to content

Commit 0d8fab5

Browse files
committed
[sw] Add mcounteren_writable test
Signed-off-by: Samuel Riedel <sriedel@lowrisc.org>
1 parent dbf9d1c commit 0d8fab5

4 files changed

Lines changed: 186 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: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7299,6 +7299,19 @@ 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_earlgrey/sw/autogen:top_earlgrey",
7308+
"//sw/device/lib/base:mmio",
7309+
"//sw/device/lib/base:multibits",
7310+
"//sw/device/lib/testing/test_framework:check",
7311+
"//sw/device/lib/testing/test_framework:ottf_main",
7312+
],
7313+
)
7314+
73027315
opentitan_test(
73037316
name = "rv_core_ibex_epmp_test_functest",
73047317
srcs = ["//sw/device/silicon_creator/manuf/tests:idle_functest.c"],
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
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+
// Lock again, which should succeed.
101+
mmio_region_write32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET,
102+
kMultiBitBool4False);
103+
mcounteren_writable_val =
104+
mmio_region_read32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET);
105+
CHECK(mcounteren_writable_val == kMultiBitBool4False,
106+
"MCOUNTEREN_WRITABLE write should succeed when unlocked, got 0x%x",
107+
mcounteren_writable_val);
108+
109+
// Clear REGWEN to lock MCOUNTEREN_WRITABLE.
110+
mmio_region_write32(ibex_cfg,
111+
RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REGWEN_REG_OFFSET, 0);
112+
regwen = mmio_region_read32(
113+
ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REGWEN_REG_OFFSET);
114+
CHECK(regwen == 0,
115+
"MCOUNTEREN_WRITABLE_REGWEN should read 0 after clearing, got 0x%x",
116+
regwen);
117+
118+
// Write to MCOUNTEREN_WRITABLE while locked should have no effect.
119+
mmio_region_write32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET,
120+
kMultiBitBool4True);
121+
mcounteren_writable_val =
122+
mmio_region_read32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET);
123+
CHECK(mcounteren_writable_val == kMultiBitBool4False,
124+
"MCOUNTEREN_WRITABLE should be unchanged when locked, got 0x%x",
125+
mcounteren_writable_val);
126+
127+
// Since the attempt to flip MCOUNTEREN_WRITABLE to True was
128+
// ignored, writes to mcounteren should be ignored.
129+
csr_write_mcounteren(MCOUNTERS_ENABLE);
130+
mcounteren_val = csr_read_mcounteren();
131+
CHECK(mcounteren_val == MCOUNTERS_DISABLE,
132+
"mcounteren writes should be blocked when MCOUNTEREN_WRITABLE is "
133+
"False. Expected 0x%x, got 0x%x",
134+
MCOUNTERS_DISABLE, mcounteren_val);
135+
136+
// Attempt to re-enable REGWEN should fail
137+
mmio_region_write32(ibex_cfg,
138+
RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REGWEN_REG_OFFSET, 1);
139+
regwen = mmio_region_read32(
140+
ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REGWEN_REG_OFFSET);
141+
CHECK(regwen == 0,
142+
"MCOUNTEREN_WRITABLE_REGWEN should remain 0 after attempted "
143+
"re-enable, got 0x%x",
144+
regwen);
145+
146+
// Write to MCOUNTEREN_WRITABLE while locked should have no effect.
147+
mmio_region_write32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET,
148+
kMultiBitBool4True);
149+
mcounteren_writable_val =
150+
mmio_region_read32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET);
151+
CHECK(mcounteren_writable_val == kMultiBitBool4False,
152+
"MCOUNTEREN_WRITABLE should be unchanged when locked, got 0x%x",
153+
mcounteren_writable_val);
154+
155+
return true;
156+
}

0 commit comments

Comments
 (0)