[PATCH v2 2/3] [NOT-FOR-UPSTREAM] lib: utils: irqchip: add QEMU virt test for APLIC wired IRQs
Raymond Mao <[email protected]>
| Newsgroups | org.infradead.lists.opensbi |
|---|---|
| Message-ID | <[email protected]> |
From: Raymond Mao <[email protected]> Add a QEMU virt specific test hook for validating APLIC wired external interrupt handling. When APLIC_QEMU_WIRED_TEST is enabled, keep the test path limited to hwirq 10 and only register it when the current APLIC instance is the M-mode direct-mode provider and that interrupt is not delegated to a child domain. This keeps the test path compatible with the generic APLIC changes while still allowing a DT overlay to expose an M-mode wired IRQ on QEMU virt. Signed-off-by: Raymond Mao <[email protected]> --- Makefile | 3 ++ lib/utils/irqchip/aplic.c | 62 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/Makefile b/Makefile index 46541063..418ee1aa 100644 --- a/Makefile +++ b/Makefile @@ -399,6 +399,9 @@ CFLAGS += $(GENFLAGS) CFLAGS += $(platform-cflags-y) CFLAGS += -fPIE -pie CFLAGS += $(firmware-cflags-y) +ifeq ($(APLIC_QEMU_WIRED_TEST),y) +CFLAGS += -DAPLIC_QEMU_WIRED_TEST +endif CPPFLAGS += $(GENFLAGS) CPPFLAGS += $(platform-cppflags-y) diff --git a/lib/utils/irqchip/aplic.c b/lib/utils/irqchip/aplic.c index 3f4991b5..82efdb71 100644 --- a/lib/utils/irqchip/aplic.c +++ b/lib/utils/irqchip/aplic.c @@ -112,6 +112,7 @@ #define APLIC_DEFAULT_PRIORITY 1 #define APLIC_DISABLE_IDELIVERY 0 #define APLIC_ENABLE_IDELIVERY 1 +#define APLIC_QEMU_TEST_HWIRQ 10 #define APLIC_DISABLE_ITHRESHOLD 1 #define APLIC_ENABLE_ITHRESHOLD 0 @@ -119,6 +120,41 @@ static SBI_LIST_HEAD(aplic_list); static void aplic_writel_msicfg(struct aplic_msicfg_data *msicfg, void *msicfgaddr, void *msicfgaddrH); +#ifdef APLIC_QEMU_WIRED_TEST + +#define UART_QEMU_MMIO 0x10000000UL + +static void aplic_test_uart_handler(void) +{ + volatile u8 *uart = (volatile u8 *)UART_QEMU_MMIO; + + /* Drain RX FIFO to clear the interrupt source */ + while (uart[0x05] & 0x01) { /* LSR.DR */ + u8 ch = uart[0x00]; /* RBR */ + + sbi_printf("[APLIC TEST] UART got '%c'(0x%02x)\n", + (ch >= 32 && ch < 127) ? ch : '.', ch); + } + + /* (Optional) read IIR to acknowledge on some models */ + (void)uart[0x02]; /* IIR is at offset 2 when DLAB=0; */ +} + +static void aplic_hwirq_test_run(unsigned long aplic_addr) +{ + volatile u8 *uart = (volatile u8 *)UART_QEMU_MMIO; + + /* UART: enable RX interrupt */ + uart[0x02] = 0x07; /* FCR enable+clear */ + uart[0x04] |= (1 << 3); /* MCR.OUT2 */ + uart[0x01] |= 0x01; /* IER.ERBFI */ + while (uart[0x05] & 0x01) /* drain */ + (void)uart[0x00]; + + sbi_printf("[APLIC TEST] Setup done. Type keys now.\n"); +} +#endif + static void aplic_init(struct aplic_data *aplic) { struct aplic_delegate_data *deleg; @@ -245,6 +281,20 @@ static int aplic_check_msicfg(struct aplic_msicfg_data *msicfg) return 0; } +#ifdef APLIC_QEMU_WIRED_TEST +static int aplic_hwirq_handler(u32 hwirq, void *opaque) +{ + (void)opaque; + + sbi_printf("[APLIC] Enter registered hwirq %u raw handler callback\n", + hwirq); + + if (hwirq == 10) + aplic_test_uart_handler(); + + return SBI_OK; +} +#endif static inline void *aplic_idc_base(unsigned long aplic_addr, u32 idc_index) { return (void *)(aplic_addr + APLIC_IDC_BASE + @@ -541,6 +591,18 @@ int aplic_cold_irqchip_init(struct aplic_data *aplic) /* Attach to the aplic list */ sbi_list_add_tail(&aplic->node, &aplic_list); +#ifdef APLIC_QEMU_WIRED_TEST + if (aplic_mmode_direct(aplic) && + !aplic_hwirq_delegated(aplic, APLIC_QEMU_TEST_HWIRQ)) { + rc = sbi_irqchip_register_handler(&aplic->irqchip, + APLIC_QEMU_TEST_HWIRQ, 1, + aplic_hwirq_handler, NULL); + if (rc) + return rc; + /* Enable test in M-mode before jumping to any payload */ + aplic_hwirq_test_run(aplic->addr); + } +#endif return 0; } -- 2.25.1 -- opensbi mailing list [email protected] http://lists.infradead.org/mailman/listinfo/opensbi