提交 b87c52d2 编写于 作者: L lixin

amtest: add an beu test

* Test the workflow of bus error unit when an ecc error occurs
上级 8fcf7d1b
......@@ -57,7 +57,7 @@ _Context* __am_irq_SEIP_handler(_Event *ev, _Context *c) {
// It's not deleted because we want to test sip write mask.
asm volatile ("csrwi sip, 0");
ev->event = _EVENT_IRQ_IODEV;
printf("inside irq SSIP handler\n");
printf("inside irq SEIP handler\n");
if (custom_external_handler != NULL)
custom_external_handler(*ev, c);
return c;
......
......@@ -25,6 +25,7 @@ int main(const char *args) {
CASE('h', hello);
CASE('i', hello_intr, IOE, CTE(simple_trap), REEH(simple_trap), RCEH(simple_trap), RTEH(simple_trap));
CASE('e', external_intr, IOE, NOTIMEINT(), CTE(external_trap), REEH(external_trap), RTEH(external_trap));
CASE('u', test_BEU, IOE, NOTIMEINT(), CTE(handle_external_trap), REEH(handle_external_trap), RTEH(handle_external_trap));
CASE('d', devscan, IOE);
CASE('m', finalize, PRE_MPE(args[1]), MPE(mp_print));
CASE('t', rtc_test, IOE);
......
#include <amtest.h>
#include <xs.h>
#define READ_WORD(addr) (*((volatile uint32_t *)(addr)))
#define WRITE_WORD(addr, data) (*((volatile uint32_t *)(addr)) = (data))
#define CONTEXT_M 0
#define CONTEXT_S 1
#define PLIC_PRIORITY (PLIC_BASE_ADDR + 0x4UL)
#define PLIC_PENDING (PLIC_BASE_ADDR + 0x1000UL)
#define PLIC_ENABLE(c) (PLIC_BASE_ADDR + 0x2000UL + c*0x80UL)
#define PLIC_THRESHOLD(c) (PLIC_BASE_ADDR + 0x200000UL + c*0x1000UL)
#define PLIC_CLAIM(c) (PLIC_BASE_ADDR + 0x200004UL + c*0x1000UL)
// External interrupts start with index PLIC_EXT_INTR_OFFSET(interrupt source 0 is not used)
#define PLIC_EXT_INTR_OFFSET 1
#define BUS_ERROR_INTERRUPT 256
// BEU constants
#define BEU_BASE 0x1f10010000UL
#define BEU_ENABLE_REG (BEU_BASE + 0x10UL)
#define BEU_PLIC_INTERRUPT_REG (BEU_BASE + 0x18UL)
// error handle
#define error(msg) {printf(msg); _halt(1);}
static volatile uint32_t should_claim = -1;
static volatile bool should_trigger = false;
static volatile int current_context = CONTEXT_S;
static void enable_plic_bus_error_interrupt() {
// enable bus error interrupt 0
plic_enable(CONTEXT_S, BUS_ERROR_INTERRUPT + PLIC_EXT_INTR_OFFSET);
}
static void disable_plic_bus_error_interrupt() {
// disable bus error interrupt 0
plic_disable(CONTEXT_S, BUS_ERROR_INTERRUPT + PLIC_EXT_INTR_OFFSET);
}
void handle_ext_intr() {
if (!should_trigger) {
error("should not trigger\n");
}
uint32_t claim = plic_get_claim(current_context); // READ_WORD(PLIC_CLAIM(current_context));
printf("an interrupt is detected, plic claim is: %d\n", claim);
if (claim) {
if (claim != should_claim) {
error("ERROR: is the external interrupt bit in PLIC cleared correctly?\n");
}
plic_clear_intr(claim); // CLEAR_INTR(claim - PLIC_EXT_INTR_OFFSET);
plic_clear_claim(current_context, claim); // WRITE_WORD(PLIC_CLAIM(current_context), claim);
// NOTE: claim will always be 257 as beu always sends ecc error to plic
should_claim = -1;
// disable ecc error interrupt to continue
disable_plic_bus_error_interrupt();
}
else {
error("ERROR: no claim?\n");
}
}
_Context *handle_external_trap(_Event ev, _Context *ctx) {
switch(ev.event) {
case _EVENT_IRQ_TIMER:
printf("t"); break;
case _EVENT_IRQ_IODEV:
printf("d"); handle_ext_intr(); break;
case _EVENT_YIELD:
printf("y"); break;
default:
printf("u"); _halt(1);
}
return ctx;
}
static void plic_intr_init() {
for (int i = 0; i < MAX_EXTERNAL_INTR + MAX_INTERNAL_INTR + PLIC_EXT_INTR_OFFSET; i++) {
// WRITE_WORD(PLIC_PRIORITY + i * sizeof(uint32_t), 0x1);
plic_set_priority(i, 0x1);
}
for (int i = 0; i < MAX_EXTERNAL_INTR + PLIC_EXT_INTR_OFFSET + MAX_INTERNAL_INTR; i += 32) {
plic_disable_word(CONTEXT_M, i); // WRITE_WORD(PLIC_ENABLE(CONTEXT_M) + i/8, 0);
plic_disable_word(CONTEXT_S, i); // WRITE_WORD(PLIC_ENABLE(CONTEXT_S) + i/8, 0);
}
plic_set_threshold(CONTEXT_M, 0x0); // WRITE_WORD(PLIC_THRESHOLD(CONTEXT_M), 0x0);
plic_set_threshold(CONTEXT_S, 0x0); // WRITE_WORD(PLIC_THRESHOLD(CONTEXT_S), 0x0);
}
static void config_BEU() {
// enable icache , dcache , l2 cache ecc; 7 means 0b111
// 0b1(l2 cache ecc)1(dcache ecc)1(icache ecc)
WRITE_WORD(BEU_ENABLE_REG, READ_WORD(BEU_ENABLE_REG) | 7);
WRITE_WORD(BEU_PLIC_INTERRUPT_REG, READ_WORD(BEU_PLIC_INTERRUPT_REG) | 7);
}
static inline void __attribute__((optimize("O0"))) wait_time(int cnt) {
while(cnt--) {}
}
void test_BEU() {
// NOTE: we are under S mode during testing
// enable supervisor external interrupts
asm volatile("csrs sie, %0" : : "r"((1 << 9)));
asm volatile("csrs sstatus, 2");
plic_intr_init();
// config BEU to enable cache ecc error interrupt
config_BEU();
should_trigger = true;
should_claim = BUS_ERROR_INTERRUPT + PLIC_EXT_INTR_OFFSET;
// enable plic source of BEU
enable_plic_bus_error_interrupt();
// we expect an interrupt from now on
wait_time(1000);
if(should_claim != -1) {
error("beu interrupt is not triggered or not handled correctly\n");
}
printf("beu test passed!!!\n");
_halt(0);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册