-
Notifications
You must be signed in to change notification settings - Fork 726
Description
This is because on boot hart (BSP) we masked all the interrupt for the current hart before we claim pending interrupts, I.e.,
init_cpu -> initLocalIRQController -> plic_init_hart
Later when we do
init_plat -> initIRQController -> plic_init_controller
Code ref:
seL4/include/drivers/irq/riscv_plic0.h
Lines 162 to 192 in ab5192f
| static inline void plic_init_hart(void) | |
| { | |
| word_t hart_id = plic_get_current_hart_id(); | |
| for (int i = 1; i <= PLIC_NUM_INTERRUPTS; i++) { | |
| /* Disable interrupts */ | |
| plic_mask_irq(true, i); | |
| } | |
| /* Set threshold to zero */ | |
| writel(0, (PLIC_PPTR_BASE + plic_thres_offset(hart_id, PLIC_SVC_CONTEXT))); | |
| } | |
| static inline void plic_init_controller(void) | |
| { | |
| for (int i = 1; i <= PLIC_NUM_INTERRUPTS; i++) { | |
| /* Clear all pending bits */ | |
| if (plic_pending_interrupt(i)) { | |
| readl(PLIC_PPTR_BASE + plic_claim_offset(PLIC_HART_ID, PLIC_SVC_CONTEXT)); | |
| writel(i, PLIC_PPTR_BASE + plic_claim_offset(PLIC_HART_ID, PLIC_SVC_CONTEXT)); | |
| } | |
| } | |
| /* Set the priorities of all interrupts to 1 */ | |
| for (int i = 1; i <= PLIC_MAX_IRQ; i++) { | |
| writel(2, PLIC_PPTR_BASE + PLIC_PRIO + PLIC_PRIO_PER_ID * i); | |
| } | |
| } |
seL4/src/arch/riscv/kernel/boot.c
Lines 227 to 235 in ab5192f
| map_kernel_window(); | |
| /* initialise the CPU */ | |
| init_cpu(); | |
| printf("Bootstrapping kernel\n"); | |
| /* initialize the platform */ | |
| init_plat(); |
Per the spec, you can't ack/EOI an interrupt from a hart that doesn't have that interrupt enabled. Linux has stumbled upon the same issue:
https://lore.kernel.org/all/[email protected]/
We don't have to clear any pending interrupts in this function, because even if we clear it by enabling the interrupt, claiming it, then disabling it, it can still be raised again. The proper approach should be just don't care, as the interrupt is already disabled for the hart.