summaryrefslogtreecommitdiffstats
path: root/sys/arm64
diff options
context:
space:
mode:
authorandrew <andrew@FreeBSD.org>2016-03-29 13:51:26 +0000
committerandrew <andrew@FreeBSD.org>2016-03-29 13:51:26 +0000
commit68e9a48abbf297dc6891e141adfa1e5ba920d0a8 (patch)
treefbac3dbd1af39a613ec233a225dcab32f5f4bed5 /sys/arm64
parent0c56c4836fb66323fbdf2fb55029e6b977409891 (diff)
downloadFreeBSD-src-68e9a48abbf297dc6891e141adfa1e5ba920d0a8.zip
FreeBSD-src-68e9a48abbf297dc6891e141adfa1e5ba920d0a8.tar.gz
Read the CPU ID for the current CPU from the GIC. The GIC may have a
different ID space than the kernel. Because of this we need to read the ID from the hardware. The hardware will provide this value to the CPU by reading any of the first 8 Interrupt Processor Targets Registers. Obtained from: ABT Systems Ltd Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D5706
Diffstat (limited to 'sys/arm64')
-rw-r--r--sys/arm64/arm64/gic.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/sys/arm64/arm64/gic.c b/sys/arm64/arm64/gic.c
index 0a13b12..74349bc 100644
--- a/sys/arm64/arm64/gic.c
+++ b/sys/arm64/arm64/gic.c
@@ -162,7 +162,7 @@ arm_gic_attach(device_t dev)
{
struct arm_gic_softc *sc;
int i;
- uint32_t icciidr;
+ uint32_t icciidr, mask;
if (arm_gic_sc)
return (ENXIO);
@@ -212,10 +212,28 @@ arm_gic_attach(device_t dev)
gic_d_write_4(sc, GICD_ICENABLER(i >> 5), 0xFFFFFFFF);
}
+ /* Read the current cpuid mask by reading ITARGETSR{0..7} */
+ for (i = 0; i < 8; i++) {
+ mask = gic_d_read_4(sc, GICD_ITARGETSR(i));
+ if (mask != 0)
+ break;
+ }
+ /* No mask found, assume we are on CPU interface 0 */
+ if (mask == 0)
+ mask = 1;
+
+ /* Collect the mask in the lower byte */
+ mask |= mask >> 16;
+ mask |= mask >> 8;
+ /* Distribute this back to the upper bytes */
+ mask |= mask << 8;
+ mask |= mask << 16;
+
for (i = 0; i < sc->nirqs; i += 4) {
gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0);
- gic_d_write_4(sc, GICD_ITARGETSR(i >> 2),
- 1 << 0 | 1 << 8 | 1 << 16 | 1 << 24);
+ if (i > 32) {
+ gic_d_write_4(sc, GICD_ITARGETSR(i >> 2), mask);
+ }
}
/* Set all the interrupts to be in Group 0 (secure) */
OpenPOWER on IntegriCloud