Message ID | 1512745328-5109-3-git-send-email-peter.maydell@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | hw/arm/virt: Add another UART | expand |
On 2017/12/8 23:02, Peter Maydell wrote: > Currently we only provide one non-secure UART on the virt > board. This is OK for most purposes, but there are some > use cases where having a second UART would be useful (like > bare-metal testing where you don't really want to have to > probe and set up a PCI device just to have a second comms > channel). > > Add a second NS UART to the virt board. This will be the > second serial device if 'secure=no' (the default), and the > third serial device if 'secure=yes'. > > Signed-off-by: Peter Maydell <peter.maydell@linaro.org> > --- > include/hw/arm/virt.h | 2 ++ > hw/arm/virt.c | 19 ++++++++++++++++--- > 2 files changed, 18 insertions(+), 3 deletions(-) > > diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h > index 33b0ff3..685009a 100644 > --- a/include/hw/arm/virt.h > +++ b/include/hw/arm/virt.h > @@ -72,6 +72,7 @@ enum { > VIRT_GPIO, > VIRT_SECURE_UART, > VIRT_SECURE_MEM, > + VIRT_UART_2, > }; > > typedef struct MemMapEntry { > @@ -85,6 +86,7 @@ typedef struct { > bool no_its; > bool no_pmu; > bool claim_edge_triggered_timers; > + bool no_second_uart; > } VirtMachineClass; > > typedef struct { > diff --git a/hw/arm/virt.c b/hw/arm/virt.c > index 543f9bd..e234f55 100644 > --- a/hw/arm/virt.c > +++ b/hw/arm/virt.c > @@ -139,6 +139,7 @@ static const MemMapEntry a15memmap[] = { > [VIRT_FW_CFG] = { 0x09020000, 0x00000018 }, > [VIRT_GPIO] = { 0x09030000, 0x00001000 }, > [VIRT_SECURE_UART] = { 0x09040000, 0x00001000 }, > + [VIRT_UART_2] = { 0x09050000, 0x00001000 }, > [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, > /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ > [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, > @@ -157,6 +158,7 @@ static const int a15irqmap[] = { > [VIRT_PCIE] = 3, /* ... to 6 */ > [VIRT_GPIO] = 7, > [VIRT_SECURE_UART] = 8, > + [VIRT_UART_2] = 9, > [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 */ > @@ -676,7 +678,7 @@ static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart, > > if (uart == VIRT_UART) { > qemu_fdt_setprop_string(vms->fdt, "/chosen", "stdout-path", nodename); > - } else { > + } else if (uart == VIRT_SECURE_UART) { > /* Mark as not usable by the normal world */ > qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled"); > qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay"); > @@ -1260,6 +1262,7 @@ static void machvirt_init(MachineState *machine) > int n, virt_max_cpus; > MemoryRegion *ram = g_new(MemoryRegion, 1); > bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0); > + int uart_count = 0; > > /* We can probe only here because during property set > * KVM is not available yet > @@ -1419,11 +1422,16 @@ static void machvirt_init(MachineState *machine) > > fdt_add_pmu_nodes(vms); > > - create_uart(vms, pic, VIRT_UART, sysmem, serial_hds[0]); > + create_uart(vms, pic, VIRT_UART, sysmem, serial_hds[uart_count++]); > > if (vms->secure) { > create_secure_ram(vms, secure_sysmem); > - create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hds[1]); > + create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, > + serial_hds[uart_count++]); > + } > + > + if (!vmc->no_second_uart) { > + create_uart(vms, pic, VIRT_UART_2, sysmem, serial_hds[uart_count++]); > } > > create_rtc(vms, pic); > @@ -1693,8 +1701,13 @@ static void virt_2_11_instance_init(Object *obj) > > static void virt_machine_2_11_options(MachineClass *mc) > { > + VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); > + > virt_machine_2_12_options(mc); > SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_11); > + > + /* The second NS UART was added in 2.12 */ > + vmc->no_second_uart = true; > } > DEFINE_VIRT_MACHINE(2, 11) > > I'm wondering if it need to provide a machine option for user to choose whether adding the second uart or not. Thanks, -- Shannon
On 12 December 2017 at 05:55, Shannon Zhao <zhaoshenglong@huawei.com> wrote: > On 2017/12/8 23:02, Peter Maydell wrote: >> Currently we only provide one non-secure UART on the virt >> board. This is OK for most purposes, but there are some >> use cases where having a second UART would be useful (like >> bare-metal testing where you don't really want to have to >> probe and set up a PCI device just to have a second comms >> channel). > I'm wondering if it need to provide a machine option for user to choose > whether adding the second uart or not. It seems harmless enough to me to provide it always. It doesn't increase the attack surface for security vulnerabilities because it's the same device as the first UART the guest already has access to. Do you have a scenario in mind where it would be bad to provide the second uart? thanks -- PMM
In case it's of direct interest in this thread, the ARM results on https://www.wireguard.com/build-status/ are running on a QEMU built with this disgusting cludge: https://א.cc/roJ0gMw3 The patch of this thread is the actually correct way of accomplishing what that cludge does.
On Fri, Dec 08, 2017 at 03:02:07PM +0000, Peter Maydell wrote: > Currently we only provide one non-secure UART on the virt > board. This is OK for most purposes, but there are some > use cases where having a second UART would be useful (like > bare-metal testing where you don't really want to have to > probe and set up a PCI device just to have a second comms > channel). > > Add a second NS UART to the virt board. This will be the > second serial device if 'secure=no' (the default), and the > third serial device if 'secure=yes'. > > Signed-off-by: Peter Maydell <peter.maydell@linaro.org> > --- > include/hw/arm/virt.h | 2 ++ > hw/arm/virt.c | 19 ++++++++++++++++--- > 2 files changed, 18 insertions(+), 3 deletions(-) > > diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h > index 33b0ff3..685009a 100644 > --- a/include/hw/arm/virt.h > +++ b/include/hw/arm/virt.h > @@ -72,6 +72,7 @@ enum { > VIRT_GPIO, > VIRT_SECURE_UART, > VIRT_SECURE_MEM, > + VIRT_UART_2, > }; > > typedef struct MemMapEntry { > @@ -85,6 +86,7 @@ typedef struct { > bool no_its; > bool no_pmu; > bool claim_edge_triggered_timers; > + bool no_second_uart; > } VirtMachineClass; > > typedef struct { > diff --git a/hw/arm/virt.c b/hw/arm/virt.c > index 543f9bd..e234f55 100644 > --- a/hw/arm/virt.c > +++ b/hw/arm/virt.c > @@ -139,6 +139,7 @@ static const MemMapEntry a15memmap[] = { > [VIRT_FW_CFG] = { 0x09020000, 0x00000018 }, > [VIRT_GPIO] = { 0x09030000, 0x00001000 }, > [VIRT_SECURE_UART] = { 0x09040000, 0x00001000 }, > + [VIRT_UART_2] = { 0x09050000, 0x00001000 }, > [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, > /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ > [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, > @@ -157,6 +158,7 @@ static const int a15irqmap[] = { > [VIRT_PCIE] = 3, /* ... to 6 */ > [VIRT_GPIO] = 7, > [VIRT_SECURE_UART] = 8, > + [VIRT_UART_2] = 9, > [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 */ > @@ -676,7 +678,7 @@ static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart, > > if (uart == VIRT_UART) { > qemu_fdt_setprop_string(vms->fdt, "/chosen", "stdout-path", nodename); > - } else { > + } else if (uart == VIRT_SECURE_UART) { > /* Mark as not usable by the normal world */ > qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled"); > qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay"); > @@ -1260,6 +1262,7 @@ static void machvirt_init(MachineState *machine) > int n, virt_max_cpus; > MemoryRegion *ram = g_new(MemoryRegion, 1); > bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0); > + int uart_count = 0; > > /* We can probe only here because during property set > * KVM is not available yet > @@ -1419,11 +1422,16 @@ static void machvirt_init(MachineState *machine) > > fdt_add_pmu_nodes(vms); > > - create_uart(vms, pic, VIRT_UART, sysmem, serial_hds[0]); > + create_uart(vms, pic, VIRT_UART, sysmem, serial_hds[uart_count++]); > > if (vms->secure) { > create_secure_ram(vms, secure_sysmem); > - create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hds[1]); > + create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, > + serial_hds[uart_count++]); > + } > + > + if (!vmc->no_second_uart) { Should this be if (!vmc->no_second_uart && serial_hds[uart_count] != NULL) { A bit late now, but maybe the other UART resource allocations should have been conditional on actually being wired up too? Thanks, drew > + create_uart(vms, pic, VIRT_UART_2, sysmem, serial_hds[uart_count++]); > } > > create_rtc(vms, pic); > @@ -1693,8 +1701,13 @@ static void virt_2_11_instance_init(Object *obj) > > static void virt_machine_2_11_options(MachineClass *mc) > { > + VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); > + > virt_machine_2_12_options(mc); > SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_11); > + > + /* The second NS UART was added in 2.12 */ > + vmc->no_second_uart = true; > } > DEFINE_VIRT_MACHINE(2, 11) > > -- > 2.7.4 > >
On 12 December 2017 at 14:45, Andrew Jones <drjones@redhat.com> wrote: > Should this be > > if (!vmc->no_second_uart && serial_hds[uart_count] != NULL) { > > A bit late now, but maybe the other UART resource allocations should have > been conditional on actually being wired up too? What does x86 do? I think the conclusion we came to about UARTs in general was that boards should always create the devices, and the UART models should cope with being passed a NULL chardev backend. (This is like real hardware, where the 2nd UART always exists even if you haven't plugged a cable into the 2nd serial port on the back of the box.) thanks -- PMM
On Tue, Dec 12, 2017 at 02:50:50PM +0000, Peter Maydell wrote: > On 12 December 2017 at 14:45, Andrew Jones <drjones@redhat.com> wrote: > > Should this be > > > > if (!vmc->no_second_uart && serial_hds[uart_count] != NULL) { > > > > A bit late now, but maybe the other UART resource allocations should have > > been conditional on actually being wired up too? > > What does x86 do? Looks like they provide the io-ports unconditionally. > > I think the conclusion we came to about UARTs in general was that > boards should always create the devices, and the UART models > should cope with being passed a NULL chardev backend. (This > is like real hardware, where the 2nd UART always exists even > if you haven't plugged a cable into the 2nd serial port on the > back of the box.) Yes, I guess the real hardware analogy provides the justification for doing it this way. OK, so this patch is fine, but it kills my suggestion for AAVMF to only output debug messages to a debug port when the debug port is actually useful. Now it won't be able to tell the difference unless we can inform it some other way. Thanks, drew > > thanks > -- PMM >
On Fri, Dec 08, 2017 at 03:02:07PM +0000, Peter Maydell wrote: > Currently we only provide one non-secure UART on the virt > board. This is OK for most purposes, but there are some > use cases where having a second UART would be useful (like > bare-metal testing where you don't really want to have to > probe and set up a PCI device just to have a second comms > channel). > > Add a second NS UART to the virt board. This will be the > second serial device if 'secure=no' (the default), and the > third serial device if 'secure=yes'. > > Signed-off-by: Peter Maydell <peter.maydell@linaro.org> > --- > include/hw/arm/virt.h | 2 ++ > hw/arm/virt.c | 19 ++++++++++++++++--- > 2 files changed, 18 insertions(+), 3 deletions(-) Reviewed-by: Andrew Jones <drjones@redhat.com> > > diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h > index 33b0ff3..685009a 100644 > --- a/include/hw/arm/virt.h > +++ b/include/hw/arm/virt.h > @@ -72,6 +72,7 @@ enum { > VIRT_GPIO, > VIRT_SECURE_UART, > VIRT_SECURE_MEM, > + VIRT_UART_2, > }; > > typedef struct MemMapEntry { > @@ -85,6 +86,7 @@ typedef struct { > bool no_its; > bool no_pmu; > bool claim_edge_triggered_timers; > + bool no_second_uart; > } VirtMachineClass; > > typedef struct { > diff --git a/hw/arm/virt.c b/hw/arm/virt.c > index 543f9bd..e234f55 100644 > --- a/hw/arm/virt.c > +++ b/hw/arm/virt.c > @@ -139,6 +139,7 @@ static const MemMapEntry a15memmap[] = { > [VIRT_FW_CFG] = { 0x09020000, 0x00000018 }, > [VIRT_GPIO] = { 0x09030000, 0x00001000 }, > [VIRT_SECURE_UART] = { 0x09040000, 0x00001000 }, > + [VIRT_UART_2] = { 0x09050000, 0x00001000 }, > [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, > /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ > [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, > @@ -157,6 +158,7 @@ static const int a15irqmap[] = { > [VIRT_PCIE] = 3, /* ... to 6 */ > [VIRT_GPIO] = 7, > [VIRT_SECURE_UART] = 8, > + [VIRT_UART_2] = 9, > [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 */ > @@ -676,7 +678,7 @@ static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart, > > if (uart == VIRT_UART) { > qemu_fdt_setprop_string(vms->fdt, "/chosen", "stdout-path", nodename); > - } else { > + } else if (uart == VIRT_SECURE_UART) { > /* Mark as not usable by the normal world */ > qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled"); > qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay"); > @@ -1260,6 +1262,7 @@ static void machvirt_init(MachineState *machine) > int n, virt_max_cpus; > MemoryRegion *ram = g_new(MemoryRegion, 1); > bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0); > + int uart_count = 0; > > /* We can probe only here because during property set > * KVM is not available yet > @@ -1419,11 +1422,16 @@ static void machvirt_init(MachineState *machine) > > fdt_add_pmu_nodes(vms); > > - create_uart(vms, pic, VIRT_UART, sysmem, serial_hds[0]); > + create_uart(vms, pic, VIRT_UART, sysmem, serial_hds[uart_count++]); > > if (vms->secure) { > create_secure_ram(vms, secure_sysmem); > - create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hds[1]); > + create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, > + serial_hds[uart_count++]); > + } > + > + if (!vmc->no_second_uart) { > + create_uart(vms, pic, VIRT_UART_2, sysmem, serial_hds[uart_count++]); > } > > create_rtc(vms, pic); > @@ -1693,8 +1701,13 @@ static void virt_2_11_instance_init(Object *obj) > > static void virt_machine_2_11_options(MachineClass *mc) > { > + VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); > + > virt_machine_2_12_options(mc); > SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_11); > + > + /* The second NS UART was added in 2.12 */ > + vmc->no_second_uart = true; > } > DEFINE_VIRT_MACHINE(2, 11) > > -- > 2.7.4 > >
On 12 December 2017 at 15:16, Andrew Jones <drjones@redhat.com> wrote: > OK, so this patch is fine, but it kills my suggestion for AAVMF to > only output debug messages to a debug port when the debug port is > actually useful. Now it won't be able to tell the difference unless > we can inform it some other way. Yeah, and that might be a nice thing to do. I'm just a little reluctant to have Arm start doing something that we don't already do for x86, or plan to do on x86 in the same way at the same time. thanks -- PMM
Hi Peter, What ever became of this? I still really could use a second UART in the standard configuration. I'm still building with this cludge -- https://א.cc/RXI3ssWV -- in order to run the test suite on build.wireguard.com. Thanks, Jason
On 31 May 2018 at 03:12, Jason A. Donenfeld <Jason@zx2c4.com> wrote: > Hi Peter, > > What ever became of this? I still really could use a second UART in > the standard configuration. I'm still building with this cludge -- > https://א.cc/RXI3ssWV -- in order to run the test suite on > build.wireguard.com. It stalled on the fact that adding the second UART breaks UEFI images (annoyingly, UEFI iterates through UARTs in the DTB in the opposite direction to Linux, so if you add a second UART then it picks that one to use rather than the first one, IIRC). So it would have to be an awkward thing with a new machine option to request the extra UART. thanks -- PMM
On Thu, May 31, 2018 at 10:32 AM, Peter Maydell <peter.maydell@linaro.org> wrote: > It stalled on the fact that adding the second UART breaks > UEFI images (annoyingly, UEFI iterates through UARTs in > the DTB in the opposite direction to Linux, so if you add > a second UART then it picks that one to use rather than > the first one, IIRC). So it would have to be an awkward > thing with a new machine option to request the extra UART. Can you just add them in the opposite order for UEFI then?
On 31 May 2018 at 12:48, Jason A. Donenfeld <Jason@zx2c4.com> wrote: > On Thu, May 31, 2018 at 10:32 AM, Peter Maydell > <peter.maydell@linaro.org> wrote: >> It stalled on the fact that adding the second UART breaks >> UEFI images (annoyingly, UEFI iterates through UARTs in >> the DTB in the opposite direction to Linux, so if you add >> a second UART then it picks that one to use rather than >> the first one, IIRC). So it would have to be an awkward >> thing with a new machine option to request the extra UART. > > Can you just add them in the opposite order for UEFI then? No, because that would break Linux guests. We don't know what guest software we're running (and indeed UEFI typically proceeds to boot Linux). thanks -- PMM
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 33b0ff3..685009a 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -72,6 +72,7 @@ enum { VIRT_GPIO, VIRT_SECURE_UART, VIRT_SECURE_MEM, + VIRT_UART_2, }; typedef struct MemMapEntry { @@ -85,6 +86,7 @@ typedef struct { bool no_its; bool no_pmu; bool claim_edge_triggered_timers; + bool no_second_uart; } VirtMachineClass; typedef struct { diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 543f9bd..e234f55 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -139,6 +139,7 @@ static const MemMapEntry a15memmap[] = { [VIRT_FW_CFG] = { 0x09020000, 0x00000018 }, [VIRT_GPIO] = { 0x09030000, 0x00001000 }, [VIRT_SECURE_UART] = { 0x09040000, 0x00001000 }, + [VIRT_UART_2] = { 0x09050000, 0x00001000 }, [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, @@ -157,6 +158,7 @@ static const int a15irqmap[] = { [VIRT_PCIE] = 3, /* ... to 6 */ [VIRT_GPIO] = 7, [VIRT_SECURE_UART] = 8, + [VIRT_UART_2] = 9, [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 */ @@ -676,7 +678,7 @@ static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart, if (uart == VIRT_UART) { qemu_fdt_setprop_string(vms->fdt, "/chosen", "stdout-path", nodename); - } else { + } else if (uart == VIRT_SECURE_UART) { /* Mark as not usable by the normal world */ qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled"); qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay"); @@ -1260,6 +1262,7 @@ static void machvirt_init(MachineState *machine) int n, virt_max_cpus; MemoryRegion *ram = g_new(MemoryRegion, 1); bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0); + int uart_count = 0; /* We can probe only here because during property set * KVM is not available yet @@ -1419,11 +1422,16 @@ static void machvirt_init(MachineState *machine) fdt_add_pmu_nodes(vms); - create_uart(vms, pic, VIRT_UART, sysmem, serial_hds[0]); + create_uart(vms, pic, VIRT_UART, sysmem, serial_hds[uart_count++]); if (vms->secure) { create_secure_ram(vms, secure_sysmem); - create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hds[1]); + create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, + serial_hds[uart_count++]); + } + + if (!vmc->no_second_uart) { + create_uart(vms, pic, VIRT_UART_2, sysmem, serial_hds[uart_count++]); } create_rtc(vms, pic); @@ -1693,8 +1701,13 @@ static void virt_2_11_instance_init(Object *obj) static void virt_machine_2_11_options(MachineClass *mc) { + VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); + virt_machine_2_12_options(mc); SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_11); + + /* The second NS UART was added in 2.12 */ + vmc->no_second_uart = true; } DEFINE_VIRT_MACHINE(2, 11)
Currently we only provide one non-secure UART on the virt board. This is OK for most purposes, but there are some use cases where having a second UART would be useful (like bare-metal testing where you don't really want to have to probe and set up a PCI device just to have a second comms channel). Add a second NS UART to the virt board. This will be the second serial device if 'secure=no' (the default), and the third serial device if 'secure=yes'. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- include/hw/arm/virt.h | 2 ++ hw/arm/virt.c | 19 ++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) -- 2.7.4