From 35175b853cb719f36f6722ea0b39d5ede58fba8e Mon Sep 17 00:00:00 2001 From: kettenis Date: Thu, 13 Oct 2022 18:34:56 +0000 Subject: [PATCH] Properly implement disestablishing LPI interrupts. Fixes a crash when using virtio(4) in combination with agintc(4). ok jsg@, patrick@ --- sys/arch/arm64/dev/agintc.c | 43 ++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/sys/arch/arm64/dev/agintc.c b/sys/arch/arm64/dev/agintc.c index e342d23a951..dc5c899487f 100644 --- a/sys/arch/arm64/dev/agintc.c +++ b/sys/arch/arm64/dev/agintc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: agintc.c,v 1.43 2022/10/13 07:04:53 kettenis Exp $ */ +/* $OpenBSD: agintc.c,v 1.44 2022/10/13 18:34:56 kettenis Exp $ */ /* * Copyright (c) 2007, 2009, 2011, 2017 Dale Rahn * Copyright (c) 2018 Mark Kettenis @@ -1167,7 +1167,8 @@ agintc_intr_establish(int irqno, int type, int level, struct cpu_info *ci, GICR_PROP_GROUP1 | GICR_PROP_ENABLE; /* Make globally visible. */ - cpu_dcache_wb_range((vaddr_t)prop, 1); + cpu_dcache_wb_range((vaddr_t)&prop[irqno - LPI_BASE], + sizeof(*prop)); __asm volatile("dsb sy"); } @@ -1187,23 +1188,35 @@ agintc_intr_disestablish(void *cookie) psw = intr_disable(); - TAILQ_REMOVE(&sc->sc_handler[irqno].iq_list, ih, ih_list); - if (ih->ih_name != NULL) - evcount_detach(&ih->ih_count); + if (irqno < LPI_BASE) { + TAILQ_REMOVE(&sc->sc_handler[irqno].iq_list, ih, ih_list); + agintc_calc_irq(sc, irqno); - agintc_calc_irq(sc, irqno); + /* In case this is an MBI, free it */ + for (i = 0; i < sc->sc_mbi_nranges; i++) { + mr = &sc->sc_mbi_ranges[i]; + if (irqno < mr->mr_base) + continue; + if (irqno >= mr->mr_base + mr->mr_span) + break; + if (mr->mr_mbi[irqno - mr->mr_base] != NULL) + mr->mr_mbi[irqno - mr->mr_base] = NULL; + } + } else { + uint8_t *prop = AGINTC_DMA_KVA(sc->sc_prop); - /* In case this is an MBI, free it */ - for (i = 0; i < sc->sc_mbi_nranges; i++) { - mr = &sc->sc_mbi_ranges[i]; - if (irqno < mr->mr_base) - continue; - if (irqno >= mr->mr_base + mr->mr_span) - break; - if (mr->mr_mbi[irqno - mr->mr_base] != NULL) - mr->mr_mbi[irqno - mr->mr_base] = NULL; + sc->sc_lpi_handler[irqno - LPI_BASE] = NULL; + prop[irqno - LPI_BASE] = 0; + + /* Make globally visible. */ + cpu_dcache_wb_range((vaddr_t)&prop[irqno - LPI_BASE], + sizeof(*prop)); + __asm volatile("dsb sy"); } + if (ih->ih_name != NULL) + evcount_detach(&ih->ih_count); + intr_restore(psw); free(ih, M_DEVBUF, 0); -- 2.20.1