summaryrefslogtreecommitdiffstats
path: root/hw/intc/arm_gic.c
diff options
context:
space:
mode:
authorPeter Maydell2016-01-21 16:00:39 +0100
committerPeter Maydell2016-01-21 16:00:39 +0100
commit1a4f446f81c63151efc30f3ce60a749e8a4cf680 (patch)
tree7fb7c5695aad485d9a3a3830177493afb9c704ee /hw/intc/arm_gic.c
parentMerge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (diff)
parenttarget-arm: Implement FPEXC32_EL2 system register (diff)
downloadqemu-1a4f446f81c63151efc30f3ce60a749e8a4cf680.tar.gz
qemu-1a4f446f81c63151efc30f3ce60a749e8a4cf680.tar.xz
qemu-1a4f446f81c63151efc30f3ce60a749e8a4cf680.zip
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20160121' into staging
target-arm queue: * connect SPI devices in Xilinx Zynq platforms * multiple-address-space support * use multiple-address-space support for ARM TrustZone * arm_gic: return correct ID registers for 11MPCore/v1/v2 GICs * various fixes for (currently disabled) AArch64 EL2 and EL3 support * add 'always-on' property to the virt board timer DT entry # gpg: Signature made Thu 21 Jan 2016 14:54:56 GMT using RSA key ID 14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" * remotes/pmaydell/tags/pull-target-arm-20160121: (36 commits) target-arm: Implement FPEXC32_EL2 system register target-arm: ignore ELR_ELx[1] for exception return to 32-bit ARM mode target-arm: Implement remaining illegal return event checks target-arm: Handle exception return from AArch64 to non-EL0 AArch32 target-arm: Fix wrong AArch64 entry offset for EL2/EL3 target target-arm: Pull semihosting handling out to arm_cpu_do_interrupt() target-arm: Use a single entry point for AArch64 and AArch32 exceptions target-arm: Move aarch64_cpu_do_interrupt() to helper.c target-arm: Properly support EL2 and EL3 in arm_el_is_aa64() arm_gic: Update ID registers based on revision hw/arm/virt: Add always-on property to the virt board timer hw/arm/virt: add secure memory region and UART hw/arm/virt: Wire up memory region to CPUs explicitly target-arm: Support multiple address spaces in page table walks target-arm: Implement cpu_get_phys_page_attrs_debug target-arm: Implement asidx_from_attrs target-arm: Add QOM property for Secure memory region qom/cpu: Add MemoryRegion property memory: Add address_space_init_shareable() exec.c: Use correct AddressSpace in watch_mem_read and watch_mem_write ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/intc/arm_gic.c')
-rw-r--r--hw/intc/arm_gic.c35
1 files changed, 30 insertions, 5 deletions
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 13e297d52e..cd60176ff7 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -31,8 +31,16 @@ do { fprintf(stderr, "arm_gic: " fmt , ## __VA_ARGS__); } while (0)
#define DPRINTF(fmt, ...) do {} while(0)
#endif
-static const uint8_t gic_id[] = {
- 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1
+static const uint8_t gic_id_11mpcore[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1
+};
+
+static const uint8_t gic_id_gicv1[] = {
+ 0x04, 0x00, 0x00, 0x00, 0x90, 0xb3, 0x1b, 0x00, 0x0d, 0xf0, 0x05, 0xb1
+};
+
+static const uint8_t gic_id_gicv2[] = {
+ 0x04, 0x00, 0x00, 0x00, 0x90, 0xb4, 0x2b, 0x00, 0x0d, 0xf0, 0x05, 0xb1
};
static inline int gic_get_current_cpu(GICState *s)
@@ -683,14 +691,31 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
}
res = s->sgi_pending[irq][cpu];
- } else if (offset < 0xfe0) {
+ } else if (offset < 0xfd0) {
goto bad_reg;
- } else /* offset >= 0xfe0 */ {
+ } else if (offset < 0x1000) {
if (offset & 3) {
res = 0;
} else {
- res = gic_id[(offset - 0xfe0) >> 2];
+ switch (s->revision) {
+ case REV_11MPCORE:
+ res = gic_id_11mpcore[(offset - 0xfd0) >> 2];
+ break;
+ case 1:
+ res = gic_id_gicv1[(offset - 0xfd0) >> 2];
+ break;
+ case 2:
+ res = gic_id_gicv2[(offset - 0xfd0) >> 2];
+ break;
+ case REV_NVIC:
+ /* Shouldn't be able to get here */
+ abort();
+ default:
+ res = 0;
+ }
}
+ } else {
+ g_assert_not_reached();
}
return res;
bad_reg: