[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.