summaryrefslogtreecommitdiffstats
path: root/hw/arm/virt.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/arm/virt.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/arm/virt.c')
-rw-r--r--hw/arm/virt.c59
1 files changed, 52 insertions, 7 deletions
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 05f9087cca..15658f49c4 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -123,6 +123,7 @@ static const MemMapEntry a15memmap[] = {
[VIRT_RTC] = { 0x09010000, 0x00001000 },
[VIRT_FW_CFG] = { 0x09020000, 0x00000018 },
[VIRT_GPIO] = { 0x09030000, 0x00001000 },
+ [VIRT_SECURE_UART] = { 0x09040000, 0x00001000 },
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
[VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
@@ -139,6 +140,7 @@ static const int a15irqmap[] = {
[VIRT_RTC] = 2,
[VIRT_PCIE] = 3, /* ... to 6 */
[VIRT_GPIO] = 7,
+ [VIRT_SECURE_UART] = 8,
[VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */
[VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */
[VIRT_PLATFORM_BUS] = 112, /* ...to 112 + PLATFORM_BUS_NUM_IRQS -1 */
@@ -291,6 +293,7 @@ static void fdt_add_timer_nodes(const VirtBoardInfo *vbi, int gictype)
qemu_fdt_setprop_string(vbi->fdt, "/timer", "compatible",
"arm,armv7-timer");
}
+ qemu_fdt_setprop(vbi->fdt, "/timer", "always-on", NULL, 0);
qemu_fdt_setprop_cells(vbi->fdt, "/timer", "interrupts",
GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_S_EL1_IRQ, irqflags,
GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL1_IRQ, irqflags,
@@ -489,16 +492,22 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, int type, bool secure)
}
}
-static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
+static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic, int uart,
+ MemoryRegion *mem)
{
char *nodename;
- hwaddr base = vbi->memmap[VIRT_UART].base;
- hwaddr size = vbi->memmap[VIRT_UART].size;
- int irq = vbi->irqmap[VIRT_UART];
+ hwaddr base = vbi->memmap[uart].base;
+ hwaddr size = vbi->memmap[uart].size;
+ int irq = vbi->irqmap[uart];
const char compat[] = "arm,pl011\0arm,primecell";
const char clocknames[] = "uartclk\0apb_pclk";
+ DeviceState *dev = qdev_create(NULL, "pl011");
+ SysBusDevice *s = SYS_BUS_DEVICE(dev);
- sysbus_create_simple("pl011", base, pic[irq]);
+ qdev_init_nofail(dev);
+ memory_region_add_subregion(mem, base,
+ sysbus_mmio_get_region(s, 0));
+ sysbus_connect_irq(s, 0, pic[irq]);
nodename = g_strdup_printf("/pl011@%" PRIx64, base);
qemu_fdt_add_subnode(vbi->fdt, nodename);
@@ -515,7 +524,14 @@ static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
qemu_fdt_setprop(vbi->fdt, nodename, "clock-names",
clocknames, sizeof(clocknames));
- qemu_fdt_setprop_string(vbi->fdt, "/chosen", "stdout-path", nodename);
+ if (uart == VIRT_UART) {
+ qemu_fdt_setprop_string(vbi->fdt, "/chosen", "stdout-path", nodename);
+ } else {
+ /* Mark as not usable by the normal world */
+ qemu_fdt_setprop_string(vbi->fdt, nodename, "status", "disabled");
+ qemu_fdt_setprop_string(vbi->fdt, nodename, "secure-status", "okay");
+ }
+
g_free(nodename);
}
@@ -995,6 +1011,7 @@ static void machvirt_init(MachineState *machine)
VirtMachineState *vms = VIRT_MACHINE(machine);
qemu_irq pic[NUM_IRQS];
MemoryRegion *sysmem = get_system_memory();
+ MemoryRegion *secure_sysmem = NULL;
int gic_version = vms->gic_version;
int n, max_cpus;
MemoryRegion *ram = g_new(MemoryRegion, 1);
@@ -1053,6 +1070,23 @@ static void machvirt_init(MachineState *machine)
exit(1);
}
+ if (vms->secure) {
+ if (kvm_enabled()) {
+ error_report("mach-virt: KVM does not support Security extensions");
+ exit(1);
+ }
+
+ /* The Secure view of the world is the same as the NonSecure,
+ * but with a few extra devices. Create it as a container region
+ * containing the system memory at low priority; any secure-only
+ * devices go in at higher priority and take precedence.
+ */
+ secure_sysmem = g_new(MemoryRegion, 1);
+ memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory",
+ UINT64_MAX);
+ memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1);
+ }
+
create_fdt(vbi);
for (n = 0; n < smp_cpus; n++) {
@@ -1093,6 +1127,13 @@ static void machvirt_init(MachineState *machine)
"reset-cbar", &error_abort);
}
+ object_property_set_link(cpuobj, OBJECT(sysmem), "memory",
+ &error_abort);
+ if (vms->secure) {
+ object_property_set_link(cpuobj, OBJECT(secure_sysmem),
+ "secure-memory", &error_abort);
+ }
+
object_property_set_bool(cpuobj, true, "realized", NULL);
}
g_strfreev(cpustr);
@@ -1108,7 +1149,11 @@ static void machvirt_init(MachineState *machine)
create_gic(vbi, pic, gic_version, vms->secure);
- create_uart(vbi, pic);
+ create_uart(vbi, pic, VIRT_UART, sysmem);
+
+ if (vms->secure) {
+ create_uart(vbi, pic, VIRT_SECURE_UART, secure_sysmem);
+ }
create_rtc(vbi, pic);