Skip to content

Commit

Permalink
[alert, sival] chip_sw_alert_handler_escalation
Browse files Browse the repository at this point in the history
This commit generalizes the existing `alert_handler_escalation_test`
to all simulation targets to cover the
`chip_sw_alert_handler_escalation` testplan item (as specified in
`hw/top_earlgrey/data/ip/chip_alert_handler_testplan.hjson`).

Signed-off-by: Andrea Caforio <[email protected]>
  • Loading branch information
andrea-caforio committed Dec 15, 2024
1 parent bca9c70 commit bf6fbc2
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 83 deletions.
2 changes: 1 addition & 1 deletion hw/top_earlgrey/data/ip/chip_alert_handler_testplan.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
si_stage: SV3
lc_states: ["PROD"]
tests: ["chip_sw_alert_handler_escalation"]
bazel: []
bazel: ["//sw/device/tests:alert_handler_escalation_test"]
otp_mutate: true
host_support: true
}
Expand Down
2 changes: 1 addition & 1 deletion hw/top_earlgrey/dv/chip_sim_cfg.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -1308,7 +1308,7 @@
{
name: chip_sw_alert_handler_escalation
uvm_test_seq: chip_sw_alert_handler_escalation_vseq
sw_images: ["//sw/device/tests/sim_dv:alert_handler_escalation_test:1:new_rules"]
sw_images: ["//sw/device/tests:alert_handler_escalation_test:1:new_rules"]
en_run_modes: ["sw_test_mode_test_rom"]
// Disable scoreboard to avoid incorrect alert prediction from the alert_monitor. Due to the
// cross-domain alert senders and receivers, the monitor from the chip level did not support
Expand Down
35 changes: 35 additions & 0 deletions sw/device/tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,41 @@ opentitan_test(
],
)

opentitan_test(
name = "alert_handler_escalation_test",
srcs = ["alert_handler_escalation_test.c"],
exec_env = dicts.add(
EARLGREY_TEST_ENVS,
EARLGREY_SILICON_OWNER_ROM_EXT_ENVS,
{
"//hw/top_earlgrey:fpga_cw310_sival": None,
"//hw/top_earlgrey:silicon_creator": None,
},
),
verilator = verilator_params(
timeout = "long",
),
deps = [
"//hw/top_earlgrey:alert_handler_c_regs",
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
"//sw/device/lib/arch:device",
"//sw/device/lib/base:memory",
"//sw/device/lib/base:mmio",
"//sw/device/lib/dif:alert_handler",
"//sw/device/lib/dif:clkmgr",
"//sw/device/lib/dif:keymgr",
"//sw/device/lib/dif:rstmgr",
"//sw/device/lib/dif:rv_core_ibex",
"//sw/device/lib/runtime:hart",
"//sw/device/lib/runtime:ibex",
"//sw/device/lib/runtime:log",
"//sw/device/lib/testing:alert_handler_testutils",
"//sw/device/lib/testing:keymgr_testutils",
"//sw/device/lib/testing:rstmgr_testutils",
"//sw/device/lib/testing/test_framework:ottf_main",
],
)

opentitan_test(
name = "alert_handler_ping_timeout_test",
srcs = ["alert_handler_ping_timeout_test.c"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,6 @@
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
#include "rv_core_ibex_regs.h" // Generated.

/*
- Verify the first escalation results in NMI interrupt serviced by the CPU.
- Verify the second results in device being put in escalate state, via the LC
JTAG TAP.
- Verify the third results in chip reset.
- Ensure that all escalation handshakes complete without errors.
The first escalation is checked via the entry of the NMI handler and polling
by dv. The second escalation is directly checked by dv. The third escalation
is checked via reset reason.
*/

OTTF_DEFINE_TEST_CONFIG();

static dif_clkmgr_t clkmgr;
Expand All @@ -44,47 +32,33 @@ static dif_alert_handler_t alert_handler;
static dif_rv_core_ibex_t rv_core_ibex;
static dif_uart_t uart;

typedef struct node {
const char *name;
dif_alert_handler_alert_t alert;
dif_alert_handler_class_t class;
} node_t;

static const dif_alert_handler_escalation_phase_t kEscProfiles[] = {
// TODO:
// this first/second duration must be long enough to
// accommodate a jtag transaction
// how can this be done in a non-hardcoded way?
{.phase = kDifAlertHandlerClassStatePhase0,
.signal = 0,
.duration_cycles = 10000},
{.phase = kDifAlertHandlerClassStatePhase1,
.signal = 1,
.duration_cycles = 10000},
{.phase = kDifAlertHandlerClassStatePhase2,
.signal = 3,
.duration_cycles = 3000}};

static const dif_alert_handler_class_config_t kConfigProfiles[] = {{
.auto_lock_accumulation_counter = kDifToggleDisabled,
.accumulator_threshold = 0,
.irq_deadline_cycles = 0,
.escalation_phases = kEscProfiles,
.escalation_phases_len = 3,
.crashdump_escalation_phase = kDifAlertHandlerClassStatePhase1,
}};

/**
* External ISR.
*
* Handles all peripheral interrupts on Ibex. PLIC asserts an external interrupt
* line to the CPU, which results in a call to this OTTF ISR. This ISR
* overrides the default OTTF implementation.
*
* @param exc_info Execution info.
*/
void ottf_external_nmi_handler(uint32_t *exc_info) {
// DO NOT REMOVE, DV sync message
LOG_INFO("You are experiencing an NMI");

dif_rv_core_ibex_nmi_state_t nmi_state = (dif_rv_core_ibex_nmi_state_t){0};

CHECK_DIF_OK(dif_rv_core_ibex_get_nmi_state(
&rv_core_ibex, (dif_rv_core_ibex_nmi_state_t *)&nmi_state));

CHECK(nmi_state.alert_enabled && nmi_state.alert_raised,
"Alert handler NMI state not expected:\n\t"
"alert_enable:%x\n\talert_raised:%x\n",
nmi_state.alert_enabled, nmi_state.alert_raised);

dif_alert_handler_class_state_t state;
CHECK_DIF_OK(dif_alert_handler_get_class_state(
&alert_handler, kDifAlertHandlerClassA, &state));

// Now intentionally hang the device
CHECK_DIF_OK(dif_clkmgr_gateable_clock_set_enabled(
&clkmgr, kTopEarlgreyGateableClocksIoDiv4Peri, kDifToggleDisabled));
Expand All @@ -94,7 +68,10 @@ void ottf_external_nmi_handler(uint32_t *exc_info) {
LOG_FATAL("This message should never be seen");
}

bool test_main(void) {
/**
* Initialize the dif handles required for this test.
*/
static void init_peripheral_handles(void) {
CHECK_DIF_OK(dif_clkmgr_init(
mmio_region_from_addr(TOP_EARLGREY_CLKMGR_AON_BASE_ADDR), &clkmgr));

Expand All @@ -114,24 +91,79 @@ bool test_main(void) {

CHECK_DIF_OK(dif_keymgr_init(
mmio_region_from_addr(TOP_EARLGREY_KEYMGR_BASE_ADDR), &keymgr));
}

/**
* Configure the alert handler. The escalation phases (NMI interrupt, LC scrap
* state, chip reset) are assigned to alert class A.
*/
static void config_alert_handler(void) {
// Escalation phase 0 is the NMI interrupt whose timeout value before
// progressing to phase 1 differs depending on the simulation device. For
// example, on the ChipWhisperer 1000000 cycles are enough to prevent a
// premature cancellation of the NMI interrupt handler (see
// `ottf_external_nmi_handler`).
uint32_t phase0DurationCycles = 1000000;
if (kDeviceType == kDeviceSimVerilator) {
phase0DurationCycles /= 10;
} else if (kDeviceType == kDeviceSimDV) {
phase0DurationCycles /= 100;
}

dif_alert_handler_escalation_phase_t escalationProfiles[] = {
{.phase = kDifAlertHandlerClassStatePhase0,
.signal = 0,
.duration_cycles = phase0DurationCycles},
{.phase = kDifAlertHandlerClassStatePhase1,
.signal = 1,
.duration_cycles = 10000},
{.phase = kDifAlertHandlerClassStatePhase2,
.signal = 3,
.duration_cycles = 10000},
};
dif_alert_handler_class_config_t configProfiles[] = {{
.auto_lock_accumulation_counter = kDifToggleDisabled,
.accumulator_threshold = 0,
.irq_deadline_cycles = 0,
.escalation_phases = escalationProfiles,
.escalation_phases_len = 3,
.crashdump_escalation_phase = kDifAlertHandlerClassStatePhase1,
}};

// set the alert we care about to class A
CHECK_DIF_OK(dif_alert_handler_configure_alert(
&alert_handler, kTopEarlgreyAlertIdRvCoreIbexRecovSwErr,
kDifAlertHandlerClassA, /*enabled=*/kDifToggleEnabled,
/*locked=*/kDifToggleEnabled));

// configure class A
CHECK_DIF_OK(dif_alert_handler_configure_class(
&alert_handler, kDifAlertHandlerClassA, configProfiles[0],
/*enabled=*/kDifToggleEnabled,
/*locked=*/kDifToggleEnabled));
}

/**
* - Verify the first escalation results in NMI interrupt serviced by the CPU.
* - Verify the second results in device being put in escalate state, via the LC
* JTAG TAP.
* - Verify the third results in chip reset.
* - Ensure that all escalation handshakes complete without errors.
*
* The first escalation is checked via the entry of the NMI handler and polling
* by dv. The second escalation is directly checked by dv. The third escalation
* is checked via reset reason.
*/
bool test_main(void) {
init_peripheral_handles();

// Check if there was a HW reset caused by the escalation.
dif_rstmgr_reset_info_bitfield_t rst_info;
rst_info = rstmgr_testutils_reason_get();
rstmgr_testutils_reason_clear();

if (rst_info & kDifRstmgrResetInfoPor) {
// set the alert we care about to class A
CHECK_DIF_OK(dif_alert_handler_configure_alert(
&alert_handler, kTopEarlgreyAlertIdRvCoreIbexRecovSwErr,
kDifAlertHandlerClassA, /*enabled=*/kDifToggleEnabled,
/*locked=*/kDifToggleEnabled));

// configurate class A
CHECK_DIF_OK(dif_alert_handler_configure_class(
&alert_handler, kDifAlertHandlerClassA, kConfigProfiles[0],
/*enabled=*/kDifToggleEnabled,
/*locked=*/kDifToggleEnabled));
config_alert_handler();

// Initialize keymgr with otp contents
CHECK_STATUS_OK(keymgr_testutils_advance_state(&keymgr, NULL));
Expand All @@ -151,12 +183,10 @@ bool test_main(void) {
wait_for_interrupt();
LOG_ERROR("Should have reset before this line");
return false;

} else if (rst_info & kDifRstmgrResetInfoEscalation) {
// DO NOT REMOVE, DV sync message
LOG_INFO("Reset due to alert escalation");
return true;

} else {
LOG_ERROR("Unexpected reset info %d", rst_info);
}
Expand Down
25 changes: 0 additions & 25 deletions sw/device/tests/sim_dv/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -649,31 +649,6 @@ opentitan_test(
],
)

opentitan_test(
name = "alert_handler_escalation_test",
srcs = ["alert_handler_escalation.c"],
exec_env = {"//hw/top_earlgrey:sim_dv": None},
deps = [
"//hw/top_earlgrey:alert_handler_c_regs",
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
"//sw/device/lib/arch:device",
"//sw/device/lib/base:memory",
"//sw/device/lib/base:mmio",
"//sw/device/lib/dif:alert_handler",
"//sw/device/lib/dif:clkmgr",
"//sw/device/lib/dif:keymgr",
"//sw/device/lib/dif:rstmgr",
"//sw/device/lib/dif:rv_core_ibex",
"//sw/device/lib/runtime:hart",
"//sw/device/lib/runtime:ibex",
"//sw/device/lib/runtime:log",
"//sw/device/lib/testing:alert_handler_testutils",
"//sw/device/lib/testing:keymgr_testutils",
"//sw/device/lib/testing:rstmgr_testutils",
"//sw/device/lib/testing/test_framework:ottf_main",
],
)

opentitan_test(
name = "alert_handler_entropy_test",
srcs = ["alert_handler_entropy_test.c"],
Expand Down

0 comments on commit bf6fbc2

Please sign in to comment.