Module Name: src Committed By: jmcneill Date: Wed Jun 26 23:00:10 UTC 2019
Modified Files: src/sys/arch/arm/cortex: gicv3.c Log Message: Change how we detect secure vs non-secure access. Write 0xff to ICC_PMR_EL1 and read back how many bits are implemented, then do the same with a GICD_IPRIORITYR<n> priority value field. If the values differ, assume we have a shifted view of IPRIORITYR. To generate a diff of this commit: cvs rdiff -u -r1.18 -r1.19 src/sys/arch/arm/cortex/gicv3.c 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.18 src/sys/arch/arm/cortex/gicv3.c:1.19 --- src/sys/arch/arm/cortex/gicv3.c:1.18 Mon Jun 17 10:15:08 2019 +++ src/sys/arch/arm/cortex/gicv3.c Wed Jun 26 23:00:09 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: gicv3.c,v 1.18 2019/06/17 10:15:08 jmcneill Exp $ */ +/* $NetBSD: gicv3.c,v 1.19 2019/06/26 23:00:09 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.18 2019/06/17 10:15:08 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gicv3.c,v 1.19 2019/06/26 23:00:09 jmcneill Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -249,9 +249,7 @@ 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_ctrl = GICD_CTRL_EnableGrp1A | GICD_CTRL_ARE_NS; gicd_write_4(sc, GICD_CTRL, gicd_ctrl); } @@ -713,6 +711,28 @@ gicv3_irq_handler(void *frame) pic_set_priority(ci, oldipl); } +static int +gicv3_detect_pmr_bits(struct gicv3_softc *sc) +{ + const uint32_t opmr = icc_pmr_read(); + icc_pmr_write(0xff); + const uint32_t npmr = icc_pmr_read(); + icc_pmr_write(opmr); + + return NBBY - (ffs(npmr) - 1); +} + +static int +gicv3_detect_ipriority_bits(struct gicv3_softc *sc) +{ + const uint32_t oipriorityr = gicd_read_4(sc, GICD_IPRIORITYRn(8)); + gicd_write_4(sc, GICD_IPRIORITYRn(8), oipriorityr | 0xff); + const uint32_t nipriorityr = gicd_read_4(sc, GICD_IPRIORITYRn(8)); + gicd_write_4(sc, GICD_IPRIORITYRn(8), oipriorityr); + + return NBBY - (ffs(nipriorityr & 0xff) - 1); +} + int gicv3_init(struct gicv3_softc *sc) { @@ -728,27 +748,21 @@ gicv3_init(struct gicv3_softc *sc) 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--; + const int pmr_bits = gicv3_detect_pmr_bits(sc); + const int ipriority_bits = gicv3_detect_ipriority_bits(sc); + + if (ipriority_bits != pmr_bits) + --sc->sc_priority_shift; + + aprint_verbose_dev(sc->sc_dev, "%d pmr bits, %d ipriority bits\n", + pmr_bits, ipriority_bits); + } else { + aprint_verbose_dev(sc->sc_dev, "security disabled\n"); } + aprint_verbose_dev(sc->sc_dev, "priority shift %d, pmr shift %d\n", sc->sc_priority_shift, sc->sc_pmr_shift);