Skip to content

Commit a204ac4

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

4 files changed

Lines changed: 183 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
@@ -2047,6 +2047,13 @@
20472047
sw_images: ["//sw/device/tests:rv_core_ibex_icache_invalidate_test:1:new_rules"]
20482048
en_run_modes: ["sw_test_mode_test_rom"]
20492049
}
2050+
{
2051+
name: chip_sw_rv_core_ibex_mcounteren_writable
2052+
uvm_test_seq: chip_sw_base_vseq
2053+
sw_images: ["//sw/device/tests:rv_core_ibex_mcounteren_writable_test:1:new_rules"]
2054+
en_run_modes: ["sw_test_mode_test_rom"]
2055+
run_opts: ["+sw_test_timeout_ns=7_000_000"]
2056+
}
20502057
{
20512058
name: chip_sw_usb_ast_clk_calib
20522059
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
@@ -7265,6 +7265,19 @@ test_suite(
72657265
],
72667266
)
72677267

7268+
opentitan_test(
7269+
name = "rv_core_ibex_mcounteren_writable_test",
7270+
srcs = ["rv_core_ibex_mcounteren_writable_test.c"],
7271+
exec_env = EARLGREY_TEST_ENVS,
7272+
deps = [
7273+
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
7274+
"//sw/device/lib/base:mmio",
7275+
"//sw/device/lib/base:multibits",
7276+
"//sw/device/lib/testing/test_framework:check",
7277+
"//sw/device/lib/testing/test_framework:ottf_main",
7278+
],
7279+
)
7280+
72687281
opentitan_test(
72697282
name = "rv_core_ibex_epmp_test_functest",
72707283
srcs = ["//sw/device/silicon_creator/manuf/tests:idle_functest.c"],
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
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+
OTTF_DEFINE_TEST_CONFIG();
17+
18+
// Helper functions for accessing the mcounteren CSR
19+
static inline uint32_t csr_read_mcounteren(void) {
20+
uint32_t val;
21+
asm volatile("csrr %0, mcounteren" : "=r"(val));
22+
return val;
23+
}
24+
25+
static inline void csr_write_mcounteren(uint32_t val) {
26+
asm volatile("csrw mcounteren, %0" ::"r"(val));
27+
}
28+
29+
bool test_main(void) {
30+
uint32_t mcounteren_val;
31+
uint32_t mcounteren_writable_val;
32+
uint32_t regwen;
33+
34+
mmio_region_t ibex_cfg =
35+
mmio_region_from_addr(TOP_EARLGREY_RV_CORE_IBEX_CFG_BASE_ADDR);
36+
37+
// Initialize mcounteren to a known value for testing.
38+
csr_write_mcounteren(0);
39+
40+
// Check defaults
41+
// MCOUNTEREN_WRITABLE should default to kMultiBitBool4True.
42+
mcounteren_writable_val =
43+
mmio_region_read32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET);
44+
CHECK(mcounteren_writable_val == kMultiBitBool4True,
45+
"MCOUNTEREN_WRITABLE default should be MuBi4True (0x%x), got 0x%x",
46+
kMultiBitBool4True, mcounteren_writable_val);
47+
// REGWEN should be enabled by default.
48+
regwen = mmio_region_read32(
49+
ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REGWEN_REG_OFFSET);
50+
CHECK(regwen == 1, "MCOUNTEREN_WRITABLE_REGWEN default should be 1, got 0x%x",
51+
regwen);
52+
53+
// Since MCOUNTEREN_WRITABLE is True, writes to mcounteren should succeed.
54+
csr_write_mcounteren(0x5);
55+
mcounteren_val = csr_read_mcounteren();
56+
CHECK(mcounteren_val == 0x5,
57+
"mcounteren should be writable when MCOUNTEREN_WRITABLE is True. "
58+
"Expected 0x5, got 0x%x",
59+
mcounteren_val);
60+
61+
// Locking should succeed while REGWEN is enabled.
62+
mmio_region_write32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET,
63+
kMultiBitBool4False);
64+
mcounteren_writable_val =
65+
mmio_region_read32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET);
66+
CHECK(mcounteren_writable_val == kMultiBitBool4False,
67+
"MCOUNTEREN_WRITABLE write should succeed when unlocked, got 0x%x",
68+
mcounteren_writable_val);
69+
70+
// Since MCOUNTEREN_WRITABLE is now False, writes to mcounteren should be
71+
// ignored.
72+
csr_write_mcounteren(0x0);
73+
mcounteren_val = csr_read_mcounteren();
74+
CHECK(mcounteren_val == 0x5,
75+
"mcounteren writes should be blocked when MCOUNTEREN_WRITABLE is "
76+
"False. Expected 0x5, got 0x%x",
77+
mcounteren_val);
78+
79+
// Unlocking should succeed while REGWEN is enabled.
80+
mmio_region_write32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET,
81+
kMultiBitBool4True);
82+
mcounteren_writable_val =
83+
mmio_region_read32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET);
84+
CHECK(mcounteren_writable_val == kMultiBitBool4True,
85+
"MCOUNTEREN_WRITABLE write should succeed when unlocked, got 0x%x",
86+
mcounteren_writable_val);
87+
88+
// Ensure mcounteren is writable again after restoring MCOUNTEREN_WRITABLE to
89+
// True.
90+
csr_write_mcounteren(0x0);
91+
mcounteren_val = csr_read_mcounteren();
92+
CHECK(mcounteren_val == 0x0,
93+
"mcounteren should be writable again after restoring config. Expected "
94+
"0x0, got 0x%x",
95+
mcounteren_val);
96+
97+
// Lock again, which should succeed.
98+
mmio_region_write32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET,
99+
kMultiBitBool4False);
100+
mcounteren_writable_val =
101+
mmio_region_read32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET);
102+
CHECK(mcounteren_writable_val == kMultiBitBool4False,
103+
"MCOUNTEREN_WRITABLE write should succeed when unlocked, got 0x%x",
104+
mcounteren_writable_val);
105+
106+
// Clear REGWEN to lock MCOUNTEREN_WRITABLE.
107+
mmio_region_write32(ibex_cfg,
108+
RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REGWEN_REG_OFFSET, 0);
109+
regwen = mmio_region_read32(
110+
ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REGWEN_REG_OFFSET);
111+
CHECK(regwen == 0,
112+
"MCOUNTEREN_WRITABLE_REGWEN should read 0 after clearing, got 0x%x",
113+
regwen);
114+
115+
// Write to MCOUNTEREN_WRITABLE while locked should have no effect.
116+
mmio_region_write32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET,
117+
kMultiBitBool4True);
118+
mcounteren_writable_val =
119+
mmio_region_read32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET);
120+
CHECK(mcounteren_writable_val == kMultiBitBool4False,
121+
"MCOUNTEREN_WRITABLE should be unchanged when locked, got 0x%x",
122+
mcounteren_writable_val);
123+
124+
// Since the attempt to flip MCOUNTEREN_WRITABLE to True was
125+
// ignored, writes to mcounteren should be ignored.
126+
csr_write_mcounteren(0x5);
127+
mcounteren_val = csr_read_mcounteren();
128+
CHECK(mcounteren_val == 0x0,
129+
"mcounteren writes should be blocked when MCOUNTEREN_WRITABLE is "
130+
"False. Expected 0x0, got 0x%x",
131+
mcounteren_val);
132+
133+
// Attempt to re-enable REGWEN should fail
134+
mmio_region_write32(ibex_cfg,
135+
RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REGWEN_REG_OFFSET, 1);
136+
regwen = mmio_region_read32(
137+
ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REGWEN_REG_OFFSET);
138+
CHECK(regwen == 0,
139+
"MCOUNTEREN_WRITABLE_REGWEN should remain 0 after attempted "
140+
"re-enable, got 0x%x",
141+
regwen);
142+
143+
// Write to MCOUNTEREN_WRITABLE while locked should have no effect.
144+
mmio_region_write32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET,
145+
kMultiBitBool4True);
146+
mcounteren_writable_val =
147+
mmio_region_read32(ibex_cfg, RV_CORE_IBEX_MCOUNTEREN_WRITABLE_REG_OFFSET);
148+
CHECK(mcounteren_writable_val == kMultiBitBool4False,
149+
"MCOUNTEREN_WRITABLE should be unchanged when locked, got 0x%x",
150+
mcounteren_writable_val);
151+
152+
return true;
153+
}

0 commit comments

Comments
 (0)