aboutsummaryrefslogtreecommitdiff
path: root/hw/arm/virt.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/arm/virt.c')
-rw-r--r--hw/arm/virt.c38
1 files changed, 35 insertions, 3 deletions
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index ffb4983885..8555615256 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -906,7 +906,7 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
}
static void create_uart(const VirtMachineState *vms, int uart,
- MemoryRegion *mem, Chardev *chr)
+ MemoryRegion *mem, Chardev *chr, bool secure)
{
char *nodename;
hwaddr base = vms->memmap[uart].base;
@@ -944,6 +944,8 @@ static void create_uart(const VirtMachineState *vms, int uart,
qemu_fdt_setprop_string(ms->fdt, "/aliases", "serial0", nodename);
} else {
qemu_fdt_setprop_string(ms->fdt, "/aliases", "serial1", nodename);
+ }
+ if (secure) {
/* Mark as not usable by the normal world */
qemu_fdt_setprop_string(ms->fdt, nodename, "status", "disabled");
qemu_fdt_setprop_string(ms->fdt, nodename, "secure-status", "okay");
@@ -2317,11 +2319,41 @@ static void machvirt_init(MachineState *machine)
fdt_add_pmu_nodes(vms);
- create_uart(vms, VIRT_UART0, sysmem, serial_hd(0));
+ /*
+ * The first UART always exists. If the security extensions are
+ * enabled, the second UART also always exists. Otherwise, it only exists
+ * if a backend is configured explicitly via '-serial <backend>'.
+ * This avoids potentially breaking existing user setups that expect
+ * only one NonSecure UART to be present (for instance, older EDK2
+ * binaries).
+ *
+ * The nodes end up in the DTB in reverse order of creation, so we must
+ * create UART0 last to ensure it appears as the first node in the DTB,
+ * for compatibility with guest software that just iterates through the
+ * DTB to find the first UART, as older versions of EDK2 do.
+ * DTB readers that follow the spec, as Linux does, should honour the
+ * aliases node information and /chosen/stdout-path regardless of
+ * the order that nodes appear in the DTB.
+ *
+ * For similar back-compatibility reasons, if UART1 is the secure UART
+ * we create it second (and so it appears first in the DTB), because
+ * that's what QEMU has always done.
+ */
+ if (!vms->secure) {
+ Chardev *serial1 = serial_hd(1);
+
+ if (serial1) {
+ vms->second_ns_uart_present = true;
+ create_uart(vms, VIRT_UART1, sysmem, serial1, false);
+ }
+ }
+ create_uart(vms, VIRT_UART0, sysmem, serial_hd(0), false);
+ if (vms->secure) {
+ create_uart(vms, VIRT_UART1, secure_sysmem, serial_hd(1), true);
+ }
if (vms->secure) {
create_secure_ram(vms, secure_sysmem, secure_tag_sysmem);
- create_uart(vms, VIRT_UART1, secure_sysmem, serial_hd(1));
}
if (tag_sysmem) {