From c51b4f68a7dae21ca69c5e3f3ad2e0075ba74ba2 Mon Sep 17 00:00:00 2001 From: Yinan Xu Date: Sun, 26 Sep 2021 11:39:15 +0800 Subject: [PATCH] extintr: fix clear external interrupt logic --- am/src/nemu/isa/riscv/cte.c | 2 ++ am/src/nemu/isa/riscv/mtime.S | 3 +++ tests/amtest/src/tests/extintr.c | 37 ++++++++++++++++++-------------- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/am/src/nemu/isa/riscv/cte.c b/am/src/nemu/isa/riscv/cte.c index 69969c51..dc69e686 100644 --- a/am/src/nemu/isa/riscv/cte.c +++ b/am/src/nemu/isa/riscv/cte.c @@ -24,6 +24,8 @@ _Context* __am_irq_handle(_Context *c) { ev.event = _EVENT_IRQ_TIMER; break; // SEIP, which is set at mtime.S case 0x9 | INTR_BIT: + // WARNING: this has no effect since in S mode only SSIP can be cleared. + // It's not deleted because we want to test sip write mask. asm volatile ("csrwi sip, 0"); ev.event = _EVENT_IRQ_IODEV; break; case 9: diff --git a/am/src/nemu/isa/riscv/mtime.S b/am/src/nemu/isa/riscv/mtime.S index 70b4cb3c..eb9e7760 100644 --- a/am/src/nemu/isa/riscv/mtime.S +++ b/am/src/nemu/isa/riscv/mtime.S @@ -47,6 +47,9 @@ is_illegal: # the supervisor tries to write mie (enable mie.meie). li a3, 0x800 csrs mie, a3 + # clear the supervisor external interrupt + li a3, 0x200 + csrc mip, a3 csrr a3, mepc addi a3, a3, 4 csrw mepc, a3 diff --git a/tests/amtest/src/tests/extintr.c b/tests/amtest/src/tests/extintr.c index f063636b..7665257d 100644 --- a/tests/amtest/src/tests/extintr.c +++ b/tests/amtest/src/tests/extintr.c @@ -19,9 +19,11 @@ #define SET_INTR(i) WRITE_WORD(INTR_REG_INDEX(i), SET_BIT(READ_INTR_REG(INTR_REG_INDEX(i)), INTR_REG_OFFSET(i))) #define PLIC_BASE_ADDR (0x3c000000UL) +#define PLIC_PRIORITY (PLIC_BASE_ADDR + 0x4UL) #define PLIC_PENDING (PLIC_BASE_ADDR + 0x1000UL) #define PLIC_ENABLE (PLIC_BASE_ADDR + 0x2000UL) #define PLIC_CLAIM (PLIC_BASE_ADDR + 0x200004UL) +// External interrupts start with index PLIC_EXT_INTR_OFFSET #define PLIC_EXT_INTR_OFFSET 2 #define MAX_EXT_INTR 150 @@ -30,18 +32,26 @@ static volatile uint32_t should_claim = -1; void do_ext_intr() { uint32_t claim = READ_WORD(PLIC_CLAIM); - printf("ext_intr: claim %d should_claim %d\n", claim, should_claim); + // printf("DO_EXT_INTR: claim %d should_claim %d\n", claim, should_claim); if (claim) { - assert(claim == should_claim); - CLEAR_INTR(claim - 1); + if (claim != should_claim) { + printf("ERROR: is the external interrupt bit in PLIC cleared correctly?\n"); + assert(0); + } + CLEAR_INTR(claim - PLIC_EXT_INTR_OFFSET); WRITE_WORD(PLIC_CLAIM, claim); + if (READ_WORD(PLIC_CLAIM) != 0) { + printf("ERROR: do you clear the external interrupt source correctly?\n"); + assert(0); + } should_claim = -1; // simply write to mie to trigger an illegal instruction exception // m mode will set mie to enable meip asm volatile("csrs mie, 0"); } else { - read_key(); + printf("ERROR: no claim?\n"); + _halt(1); } } @@ -59,11 +69,9 @@ _Context *external_trap(_Event ev, _Context *ctx) { return ctx; } -static void plic_intr_init() -{ - // TODO: fix init plic priority logic - for (int i = 1; i <= MAX_EXT_INTR; i++) - WRITE_WORD(PLIC_BASE_ADDR + i*sizeof(uint32_t), 0xffffffff); +static void plic_intr_init() { + for (int i = 0; i < MAX_EXT_INTR; i++) + WRITE_WORD(PLIC_PRIORITY + i * sizeof(uint32_t), 0x1); } void external_intr() { @@ -72,12 +80,10 @@ void external_intr() { asm volatile("csrs sstatus, 2"); plic_intr_init(); // trigger interrupts - const uint32_t MAX_RAND_ITER = 500; - int r = 0; + const uint32_t MAX_RAND_ITER = 1000; for (int i = 0; i < MAX_RAND_ITER; i++) { - // int r = rand(); - should_claim = (r % MAX_EXT_INTR) + PLIC_EXT_INTR_OFFSET; - printf("should_claim %d, setting intr\n", should_claim); + should_claim = (rand() % MAX_EXT_INTR) + PLIC_EXT_INTR_OFFSET; + // printf("should_claim %d, setting intr\n", should_claim); WRITE_WORD(PLIC_ENABLE + (should_claim / 32) * 4, (1UL << (should_claim % 32))); SET_INTR(should_claim - PLIC_EXT_INTR_OFFSET); int counter = 0; @@ -85,10 +91,9 @@ void external_intr() { counter++; } if (should_claim != -1) { - printf("external interrupt is not triggered!\n"); + printf("external interrupt %d is not triggered!\n", should_claim); _halt(1); } - r++; } printf("external interrupt test passed!!!\n"); } -- GitLab