summaryrefslogtreecommitdiffstats
path: root/sys/arm64
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2016-05-17 13:12:26 +0000
committerbz <bz@FreeBSD.org>2016-05-17 13:12:26 +0000
commit083ca1a6aff022bc3199f2bccabb04aa5019127f (patch)
tree4b3edea95c294f9c536c2301b046cb74020caae1 /sys/arm64
parent156fd4834ab9a6f666ba46003a8fd7bd64dfdb39 (diff)
downloadFreeBSD-src-083ca1a6aff022bc3199f2bccabb04aa5019127f.zip
FreeBSD-src-083ca1a6aff022bc3199f2bccabb04aa5019127f.tar.gz
The GIC (v2 at least) has a bit in the TYPER register to indicate whether the GIC
supports the Security Extensions or not. This bit is not the same as the CPU one. Currently we are not checking for either before trying to write to the special registers. This can lead to problems on hardware or simulators that do not provide the security extensions. Add the missing checks. Their interactions with the CPU flag is not entirely clear to me but using a macro will make it easier to quickly adjust the condition once the CPU bits are sorted as well. Reviewed by: br Sponsored by: DARPA/AFRL Differential Revision: https://reviews.freebsd.org/D6397
Diffstat (limited to 'sys/arm64')
-rw-r--r--sys/arm64/arm64/gic.c13
-rw-r--r--sys/arm64/arm64/gic.h1
2 files changed, 10 insertions, 4 deletions
diff --git a/sys/arm64/arm64/gic.c b/sys/arm64/arm64/gic.c
index 2140086..68b7cab 100644
--- a/sys/arm64/arm64/gic.c
+++ b/sys/arm64/arm64/gic.c
@@ -94,6 +94,11 @@ __FBSDID("$FreeBSD$");
#define GIC_LAST_PPI 31 /* core) peripheral interrupts. */
#define GIC_FIRST_SPI 32 /* Irqs 32+ are shared peripherals. */
+/* TYPER Registers */
+#define GICD_TYPER_SECURITYEXT 0x400
+#define GIC_SUPPORT_SECEXT(_sc) \
+ ((_sc->typer & GICD_TYPER_SECURITYEXT) == GICD_TYPER_SECURITYEXT)
+
/* First bit is a polarity bit (0 - low, 1 - high) */
#define GICD_ICFGR_POL_LOW (0 << 0)
#define GICD_ICFGR_POL_HIGH (1 << 0)
@@ -164,7 +169,7 @@ gic_init_secondary(device_t dev)
gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0);
/* Set all the interrupts to be in Group 0 (secure) */
- for (i = 0; i < sc->nirqs; i += 32) {
+ for (i = 0; GIC_SUPPORT_SECEXT(sc) && i < sc->nirqs; i += 32) {
gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0);
}
@@ -221,8 +226,8 @@ arm_gic_attach(device_t dev)
gic_d_write_4(sc, GICD_CTLR, 0x00);
/* Get the number of interrupts */
- sc->nirqs = gic_d_read_4(sc, GICD_TYPER);
- sc->nirqs = 32 * ((sc->nirqs & 0x1f) + 1);
+ sc->typer = gic_d_read_4(sc, GICD_TYPER);
+ sc->nirqs = 32 * ((sc->typer & 0x1f) + 1);
arm_register_root_pic(dev, sc->nirqs);
@@ -257,7 +262,7 @@ arm_gic_attach(device_t dev)
}
/* Set all the interrupts to be in Group 0 (secure) */
- for (i = 0; i < sc->nirqs; i += 32) {
+ for (i = 0; GIC_SUPPORT_SECEXT(sc) && i < sc->nirqs; i += 32) {
gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0);
}
diff --git a/sys/arm64/arm64/gic.h b/sys/arm64/arm64/gic.h
index d22d43b..a8ba6a8 100644
--- a/sys/arm64/arm64/gic.h
+++ b/sys/arm64/arm64/gic.h
@@ -49,6 +49,7 @@ struct arm_gic_softc {
uint8_t ver;
struct mtx mutex;
uint32_t nirqs;
+ uint32_t typer;
};
DECLARE_CLASS(arm_gicv2m_driver);
OpenPOWER on IntegriCloud