Module Name: src Committed By: jmcneill Date: Mon Jun 17 10:15:08 UTC 2019
Modified Files: src/sys/arch/arm/cortex: gicv3.c gicv3.h Log Message: Improve priority handling for cases where access is secure, from OpenBSD. To generate a diff of this commit: cvs rdiff -u -r1.17 -r1.18 src/sys/arch/arm/cortex/gicv3.c cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/cortex/gicv3.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/cortex/gicv3.c diff -u src/sys/arch/arm/cortex/gicv3.c:1.17 src/sys/arch/arm/cortex/gicv3.c:1.18 --- src/sys/arch/arm/cortex/gicv3.c:1.17 Wed Jun 12 11:35:17 2019 +++ src/sys/arch/arm/cortex/gicv3.c Mon Jun 17 10:15:08 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: gicv3.c,v 1.17 2019/06/12 11:35:17 mrg Exp $ */ +/* $NetBSD: gicv3.c,v 1.18 2019/06/17 10:15:08 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -31,7 +31,7 @@ #define _INTR_PRIVATE #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gicv3.c,v 1.17 2019/06/12 11:35:17 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gicv3.c,v 1.18 2019/06/17 10:15:08 jmcneill Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -52,7 +52,9 @@ __KERNEL_RCSID(0, "$NetBSD: gicv3.c,v 1. #define LPITOSOFTC(lpi) \ ((void *)((uintptr_t)(lpi) - offsetof(struct gicv3_softc, sc_lpi))) -#define IPL_TO_PRIORITY(ipl) ((IPL_HIGH - (ipl)) << 4) +#define IPL_TO_PRIORITY(sc, ipl) (((0xff - (ipl)) << (sc)->sc_priority_shift) & 0xff) +#define IPL_TO_PMR(sc, ipl) (((0xff - (ipl)) << (sc)->sc_pmr_shift) & 0xff) +#define IPL_TO_LPIPRIO(sc, ipl) (((0xff - (ipl)) << 4) & 0xff) static struct gicv3_softc *gicv3_softc; @@ -155,7 +157,7 @@ gicv3_establish_irq(struct pic_softc *pi uint64_t irouter; u_int n; - const u_int ipriority_val = 0x80 | IPL_TO_PRIORITY(is->is_ipl); + const u_int ipriority_val = IPL_TO_PRIORITY(sc, is->is_ipl); const u_int ipriority_shift = (is->is_irq & 0x3) * 8; const u_int icfg_shift = (is->is_irq & 0xf) * 2; @@ -206,7 +208,9 @@ gicv3_establish_irq(struct pic_softc *pi static void gicv3_set_priority(struct pic_softc *pic, int ipl) { - icc_pmr_write(IPL_TO_PRIORITY(ipl) << 1); + struct gicv3_softc * const sc = PICTOSOFTC(pic); + + icc_pmr_write(IPL_TO_PMR(sc, ipl)); } static void @@ -246,6 +250,8 @@ gicv3_dist_enable(struct gicv3_softc *sc /* Enable Affinity routing and G1NS interrupts */ gicd_ctrl = GICD_CTRL_EnableGrp1A | GICD_CTRL_Enable | GICD_CTRL_ARE_NS; + if (ISSET(sc->sc_flags, GICV3_F_SECURE)) + gicd_ctrl = (gicd_ctrl & ~GICD_CTRL_EnableGrp1A) << 1; gicd_write_4(sc, GICD_CTRL, gicd_ctrl); } @@ -271,7 +277,7 @@ gicv3_redist_enable(struct gicv3_softc * if (is == NULL) priority |= 0xff << byte_shift; else { - const u_int ipriority_val = 0x80 | IPL_TO_PRIORITY(is->is_ipl); + const u_int ipriority_val = IPL_TO_PRIORITY(sc, is->is_ipl); priority |= ipriority_val << byte_shift; } } @@ -303,19 +309,11 @@ gicv3_cpu_identity(void) { u_int aff3, aff2, aff1, aff0; -#ifdef __aarch64__ - const register_t mpidr = reg_mpidr_el1_read(); + const register_t mpidr = cpu_mpidr_aff_read(); aff0 = __SHIFTOUT(mpidr, MPIDR_AFF0); aff1 = __SHIFTOUT(mpidr, MPIDR_AFF1); aff2 = __SHIFTOUT(mpidr, MPIDR_AFF2); aff3 = __SHIFTOUT(mpidr, MPIDR_AFF3); -#else - const register_t mpidr = armreg_mpidr_read(); - aff0 = __SHIFTOUT(mpidr, MPIDR_AFF0); - aff1 = __SHIFTOUT(mpidr, MPIDR_AFF1); - aff2 = __SHIFTOUT(mpidr, MPIDR_AFF2); - aff3 = 0; -#endif return __SHIFTIN(aff0, GICR_TYPER_Affinity_Value_Aff0) | __SHIFTIN(aff1, GICR_TYPER_Affinity_Value_Aff1) | @@ -545,7 +543,7 @@ gicv3_lpi_establish_irq(struct pic_softc { struct gicv3_softc * const sc = LPITOSOFTC(pic); - sc->sc_lpiconf.base[is->is_irq] = 0x80 | IPL_TO_PRIORITY(is->is_ipl) | GIC_LPICONF_Res1; + sc->sc_lpiconf.base[is->is_irq] = IPL_TO_LPIPRIO(sc, is->is_ipl) | GIC_LPICONF_Res1; bus_dmamap_sync(sc->sc_dmat, sc->sc_lpiconf.map, is->is_irq, 1, BUS_DMASYNC_PREWRITE); } @@ -719,6 +717,7 @@ int gicv3_init(struct gicv3_softc *sc) { const uint32_t gicd_typer = gicd_read_4(sc, GICD_TYPER); + const uint32_t gicd_ctrl = gicd_read_4(sc, GICD_CTRL); int n; KASSERT(CPU_IS_PRIMARY(curcpu())); @@ -728,6 +727,31 @@ gicv3_init(struct gicv3_softc *sc) for (n = 0; n < MAXCPUS; n++) sc->sc_irouter[n] = UINT64_MAX; + sc->sc_priority_shift = 4; + const uint32_t oldnsacr = gicd_read_4(sc, GICD_NSACRn(2)); + gicd_write_4(sc, GICD_NSACRn(2), oldnsacr ^ 0xffffffff); + if (gicd_read_4(sc, GICD_NSACRn(2)) != oldnsacr) { + gicd_write_4(sc, GICD_NSACRn(2), oldnsacr); + sc->sc_priority_shift--; + SET(sc->sc_flags, GICV3_F_SECURE); + } + aprint_verbose_dev(sc->sc_dev, "access is %ssecure\n", + ISSET(sc->sc_flags, GICV3_F_SECURE) ? "" : "in"); + + sc->sc_pmr_shift = 4; + if ((gicd_ctrl & GICD_CTRL_DS) == 0) { + const uint32_t icc_ctlr = icc_ctlr_read(); + const u_int nbits = __SHIFTOUT(icc_ctlr, ICC_CTLR_EL1_PRIbits) + 1; + const u_int oldpmr = icc_pmr_read(); + icc_pmr_write(0xff); + const u_int pmr = icc_pmr_read(); + icc_pmr_write(oldpmr); + if (nbits == 8 - (ffs(pmr) - 1)) + sc->sc_pmr_shift--; + } + aprint_verbose_dev(sc->sc_dev, "priority shift %d, pmr shift %d\n", + sc->sc_priority_shift, sc->sc_pmr_shift); + sc->sc_pic.pic_ops = &gicv3_picops; sc->sc_pic.pic_maxsources = GICD_TYPER_LINES(gicd_typer); snprintf(sc->sc_pic.pic_name, sizeof(sc->sc_pic.pic_name), "gicv3"); Index: src/sys/arch/arm/cortex/gicv3.h diff -u src/sys/arch/arm/cortex/gicv3.h:1.4 src/sys/arch/arm/cortex/gicv3.h:1.5 --- src/sys/arch/arm/cortex/gicv3.h:1.4 Sat Nov 10 11:46:31 2018 +++ src/sys/arch/arm/cortex/gicv3.h Mon Jun 17 10:15:08 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: gicv3.h,v 1.4 2018/11/10 11:46:31 jmcneill Exp $ */ +/* $NetBSD: gicv3.h,v 1.5 2019/06/17 10:15:08 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -60,6 +60,12 @@ struct gicv3_softc { bus_space_handle_t *sc_bsh_r; /* GICR */ u_int sc_bsh_r_count; + u_int sc_flags; +#define GICV3_F_SECURE 0x01 + + u_int sc_priority_shift; + u_int sc_pmr_shift; + uint32_t sc_enabled_sgippi; uint64_t sc_irouter[MAXCPUS];