xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/14 v4] PL011 emulation support in Xen
@ 2017-06-06 17:25 Bhupinder Thakur
  2017-06-06 17:25 ` [PATCH 01/14 v4] xen/arm: vpl011: Move vgic register access functions to vreg.h Bhupinder Thakur
                   ` (14 more replies)
  0 siblings, 15 replies; 65+ messages in thread
From: Bhupinder Thakur @ 2017-06-06 17:25 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

PL011 emulation for guests in Xen
===================================
Linaro has published VM System specification for ARM Processors, which
provides a set of guidelines for both guest OS and hypervisor implementations, 
such that building OS images according to these guidelines guarantees
that those images can also run on hypervisors compliant with this specification.

One of the spec requirements is that the hypervisor must provide an
emulated PL011 UART as a serial console which meets the minimum requirements in 
SBSA UART as defined in appendix B of the following 
ARM Server Base Architecture Document:

https://static.docs.arm.com/den0029/a/Server_Base_System_Architecture_v3_1_ARM_DEN_0029A.pdf.

This feature allows the Xen guests to use SBSA compliant pl011 UART as 
as a console. 

Note that SBSA pl011 UART is a subset of full featured ARM pl011 UART and
supports only a subset of registers as mentioned below. It does not support
rx/tx DMA.

Currently, Xen supports paravirtualized (aka PV console) and an emulated serial 
consoles. This feature will expose an emulated SBSA pl011 UART console to the
guest, which a user can access using xenconsole.

The device tree passed to the guest VM will contain the pl011 MMIO address 
range and an irq for receiving rx/tx pl011 interrupts. The device tree format 
is specified in Documentation/devicetree/bindings/serial/arm_sbsa_uart.txt.

The Xen hypervisor will expose two types of interfaces to the backend and domU. 

The interface exposed to domU will be an emulated pl011 UART by emulating the 
access to the following pl011 registers by the guest.

- Data register (DR)            - RW
- Raw interrupt status register (RIS)   - RO
- Masked interrupt status register (MIS)- RO
- Interrupt Mask (IMSC)         - RW
- Interrupt Clear (ICR)         - WO

It will also inject the pl011 interrupts to the guest in the following 
conditions:

- incoming data in the rx buffer for the guest
- there is space in the tx buffer for the guest to write more data

The interface exposed to the backend will be the same PV console interface, 
which minimizes the changes required in xenconsole to support a new pl011 console.

This interface has rx and tx ring buffers and an event channel for 
sending/receiving events from the backend. 

So essentially Xen handles the data on behalf of domU and the backend. Any data 
written by domU is captured by Xen and written to the TX (OUT) ring buffer 
and a pl011 event is raised to the backend to read the TX ring buffer.
 
Similarly on reciving a pl011 event, Xen injects an interrupt to guest to
indicate there is data available in the RX (IN) ring buffer.

The pl011 UART state is completely captured in the set of registers 
mentioned above and this state is updated everytime there is an event from 
the backend or there is register read/write access from domU. 

For example, if domU has masked the rx interrupt in the IMSC register, then Xen 
will not inject an interrupt to guest and will just update the RIS register. 
Once the interrupt is unmasked by guest, the interrupt will be delivered to the 
guest.

Changes summary:

Xen Hypervisor
===============

1. Add emulation code to emulate read/write access to pl011 registers and pl011 
   interrupts:
    - It emulates DR read/write by reading and writing from/to the IN and 
      OUT ring buffers and raising an event to dom0 when there is data in 
      the OUT ring buffer and injecting an interrupt to the guest when there 
      is data in the IN ring buffer.
    - Other registers are related to interrupt management and essentially 
      control when interrupts are delivered to the guest.

2. Add a new domctl API to initialize vpl011 emulation in Xen.

3. Enable vpl011 emulation for a domain based on a libxl option passed during 
   domain creation.

Toolstack
==========

1. Add a new option "vuart" in the domU configuration file to enable/disable vuart.

2. Create a SBSA UART DT node in the guest device tree. It uses a fixed
   vpl011 SPI IRQ number and MMIO address.

3. Call vpl011 init DOMCTL API to enable vpl011 emulation.

5. Add a new vuart xenstore node, which contains:
    - ring-ref
    - event channel
    - buffer limit
    - type

Xenconsoled
============

1. Split the domain structure to support multiple consoles.

2. Modify different APIs such as buffer_append() etc. to operate on the 
   console structure.
   
3. Add support for handling multiple consoles.

4. Add support for vuart console:

The vpl011 changes available at the following repo:

url: ssh://git@git.linaro.org:/people/bhupinder.thakur/xen.git
branch: vpl011_v4

There are some TBD items which need to be looked at in the future:

1. Currently UEFI firmware logs the output to hvc console only. How can 
   UEFI firmware be made aware of pl011 console and how it can use it
   as a console instead of hvc.
2. Linux seems to have hvc console as the default console i.e. if no
   console is specified then it uses hvc as the console. How can an 
   option be provided in Linux to select either hvc or pl011 as the 
   default console.

3. ACPI support for pl011 device.

CC: ij
CC: wl
CC: ss
CC: jg
CC: kw

Bhupinder Thakur (14):
  xen/arm: vpl011: Move vgic register access functions to vreg.h
  xen/arm: vpl011: Define generic vreg_reg* access functions in vreg.h
  xen/arm: vpl011: Add pl011 uart emulation in Xen
  xen/arm: vpl011: Add support for vuart in libxl
  xen/arm: vpl011: Allocate a new GFN in the toolstack for vuart
  xen/arm: vpl011: Add a new domctl API to initialize vpl011
  xen/arm: vpl011: Add a new vuart node in the xenstore
  xen/arm: vpl011: Modify xenconsole to define and use a new console    
    structure
  xen/arm: vpl011: Modify xenconsole functions to take console structure
    as input
  xen/arm: vpl011: Modify xenconsole to support multiple consoles
  xen/arm: vpl011: Add support for vuart console in xenconsole
  xen/arm: vpl011: Add a new vuart console type to xenconsole client
  xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree
  xen/arm: vpl011: Update documentation for vuart console support

 config/arm32.mk                      |   1 +
 config/arm64.mk                      |   1 +
 docs/man/xl.cfg.pod.5.in             |   9 +
 docs/misc/console.txt                |  44 ++-
 tools/console/Makefile               |   4 +-
 tools/console/client/main.c          |  25 +-
 tools/console/daemon/io.c            | 544 ++++++++++++++++++++++++-----------
 tools/libxc/include/xc_dom.h         |   3 +
 tools/libxc/include/xenctrl.h        |  17 ++
 tools/libxc/xc_dom_arm.c             |  12 +-
 tools/libxc/xc_dom_boot.c            |   2 +
 tools/libxc/xc_domain.c              |  23 ++
 tools/libxl/libxl.h                  |   6 +
 tools/libxl/libxl_arch.h             |   7 +
 tools/libxl/libxl_arm.c              |  71 ++++-
 tools/libxl/libxl_console.c          |  47 +++
 tools/libxl/libxl_create.c           |  12 +-
 tools/libxl/libxl_device.c           |   9 +-
 tools/libxl/libxl_dom.c              |   8 +-
 tools/libxl/libxl_internal.h         |   7 +
 tools/libxl/libxl_types.idl          |   7 +
 tools/libxl/libxl_types_internal.idl |   1 +
 tools/libxl/libxl_x86.c              |   8 +
 tools/xl/Makefile                    |   4 +
 tools/xl/xl_cmdtable.c               |   4 +
 tools/xl/xl_console.c                |  11 +-
 tools/xl/xl_parse.c                  |   8 +
 xen/arch/arm/Kconfig                 |   5 +
 xen/arch/arm/Makefile                |   1 +
 xen/arch/arm/domain.c                |   2 +
 xen/arch/arm/domctl.c                |  44 ++-
 xen/arch/arm/vgic-v2.c               |  28 +-
 xen/arch/arm/vgic-v3.c               |  40 +--
 xen/arch/arm/vpl011.c                | 418 +++++++++++++++++++++++++++
 xen/include/asm-arm/domain.h         |   6 +
 xen/include/asm-arm/pl011-uart.h     |   2 +
 xen/include/asm-arm/vgic.h           | 111 +------
 xen/include/asm-arm/vpl011.h         |  74 +++++
 xen/include/asm-arm/vreg.h           | 109 +++++++
 xen/include/public/arch-arm.h        |   6 +
 xen/include/public/domctl.h          |  12 +
 xen/include/public/io/console.h      |   4 +
 42 files changed, 1421 insertions(+), 336 deletions(-)
 create mode 100644 xen/arch/arm/vpl011.c
 create mode 100644 xen/include/asm-arm/vpl011.h

-- 
2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 65+ messages in thread
* [PATCH 03/14 v4] xen/arm: vpl011: Add pl011 uart emulation in Xen
@ 2017-06-06 10:02 Bhupinder Thakur
  0 siblings, 0 replies; 65+ messages in thread
From: Bhupinder Thakur @ 2017-06-06 10:02 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

Add emulation code to emulate read/write access to pl011 registers
and pl011 interrupts:

    - Emulate DR read/write by reading and writing from/to the IN
      and OUT ring buffers and raising an event to the backend when
      there is data in the OUT ring buffer and injecting an interrupt
      to the guest when there is data in the IN ring buffer

    - Other registers are related to interrupt management and
      essentially control when interrupts are delivered to the guest

The SBSA compliant pl011 uart is covered in Appendix B of
https://static.docs.arm.com/den0029/a/Server_Base_System_Architecture_v3_1_ARM_DEN_0029A.pdf

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
---

Changes since v3:
- Moved the call to DEFINE_XEN_FLEX_RING from vpl011.h to public/console.h. This macro defines
  standard functions to operate on the ring buffer.
- Lock taken while updating the interrupt mask and clear registers in mmio_write.
- Use gfn_t instead of xen_pfn_t.
- vgic_free_virq called if there is any error in vpl011 initialization.
- mmio handlers freed if there is any error in vpl011 initialization.
- Removed vpl011->initialized flag usage as the same check could be done 
  using vpl011->ring-ref.
- Used return instead of break in the switch handling of emulation of different pl011 registers.
- Renamed vpl011_update_spi() to vpl011_update().

Changes since v2:
- Use generic vreg_reg* for read/write of registers emulating pl011.
- Use generic ring buffer functions defined using DEFINE_XEN_FLEX_RING.
- Renamed the SPI injection function to vpl011_update_spi() to reflect level 
  triggered nature of pl011 interrupts.
- The pl011 register access address should always be the base address of the
  corresponding register as per section B of the SBSA document. For this reason,
  the register range address access is not allowed.

Changes since v1:
- Removed the optimiztion related to sendiing events to xenconsole 
- Use local variables as ring buffer indices while using the ring buffer

 tools/console/daemon/io.c        |   2 +-
 xen/arch/arm/Kconfig             |   5 +
 xen/arch/arm/Makefile            |   1 +
 xen/arch/arm/vpl011.c            | 418 +++++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/domain.h     |   6 +
 xen/include/asm-arm/pl011-uart.h |   2 +
 xen/include/asm-arm/vpl011.h     |  74 +++++++
 xen/include/public/arch-arm.h    |   6 +
 xen/include/public/io/console.h  |   4 +
 9 files changed, 517 insertions(+), 1 deletion(-)
 create mode 100644 xen/arch/arm/vpl011.c
 create mode 100644 xen/include/asm-arm/vpl011.h

diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index 7e6a886..947f13a 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -21,6 +21,7 @@
 
 #include "utils.h"
 #include "io.h"
+#include <string.h>
 #include <xenevtchn.h>
 #include <xengnttab.h>
 #include <xenstore.h>
@@ -29,7 +30,6 @@
 
 #include <stdlib.h>
 #include <errno.h>
-#include <string.h>
 #include <poll.h>
 #include <fcntl.h>
 #include <unistd.h>
diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index d46b98c..c1a0e7f 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -50,6 +50,11 @@ config HAS_ITS
         prompt "GICv3 ITS MSI controller support" if EXPERT = "y"
         depends on HAS_GICV3
 
+config VPL011_CONSOLE
+	bool "Emulated pl011 console support"
+	default y
+	---help---
+	  Allows a guest to use pl011 UART as a console
 endmenu
 
 menu "ARM errata workaround via the alternative framework"
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 49e1fb2..15efc13 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -52,6 +52,7 @@ obj-y += vm_event.o
 obj-y += vtimer.o
 obj-y += vpsci.o
 obj-y += vuart.o
+obj-$(CONFIG_VPL011_CONSOLE) += vpl011.o
 
 #obj-bin-y += ....o
 
diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
new file mode 100644
index 0000000..9b1f27e
--- /dev/null
+++ b/xen/arch/arm/vpl011.c
@@ -0,0 +1,418 @@
+/*
+ * arch/arm/vpl011.c
+ *
+ * Virtual PL011 UART
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/errno.h>
+#include <xen/event.h>
+#include <xen/guest_access.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/mm.h>
+#include <xen/sched.h>
+#include <public/domctl.h>
+#include <public/io/console.h>
+#include <asm-arm/pl011-uart.h>
+#include <asm-arm/vgic-emul.h>
+#include <asm-arm/vpl011.h>
+
+static bool vpl011_reg32_check_access(struct hsr_dabt dabt)
+{
+    return (dabt.size != DABT_DOUBLE_WORD);
+}
+
+static void vpl011_update(struct domain *d)
+{
+    struct vpl011 *vpl011 = &d->arch.vpl011;
+
+    /*
+     * TODO: PL011 interrupts are level triggered which means
+     * that interrupt needs to be set/clear instead of being
+     * injected. However, currently vGIC does not handle level 
+     * triggered interrupts properly. This function needs to be 
+     * revisited once vGIC starts handling level triggered 
+     * interrupts.
+     */
+    if ( vpl011->uartris & vpl011->uartimsc )
+        vgic_vcpu_inject_spi(d, GUEST_VPL011_SPI);
+}
+
+static uint8_t vpl011_read_data(struct domain *d)
+{
+    unsigned long flags;
+    uint8_t data = 0;
+    struct vpl011 *vpl011 = &d->arch.vpl011;
+    struct xencons_interface *intf = vpl011->ring_buf;
+    XENCONS_RING_IDX in_cons = intf->in_cons;
+    XENCONS_RING_IDX in_prod = intf->in_prod;
+
+    VPL011_LOCK(d, flags);
+
+    /*
+     * It is expected that there will be data in the ring buffer when this
+     * function is called since the guest is expected to read the data register
+     * only if the TXFE flag is not set.
+     * If the guest still does read when TXFE bit is set then 0 will be returned.
+     */
+    if ( xencons_queued(in_prod, in_cons, sizeof(intf->in)) > 0 )
+    {
+        data = intf->in[xencons_mask(in_cons, sizeof(intf->in))];
+        in_cons += 1;
+        intf->in_cons = in_cons;
+        smp_mb();
+    }
+    else
+    {
+        gprintk(XENLOG_ERR, "vpl011: Unexpected IN ring buffer empty\n");
+    }
+
+    if ( xencons_queued(in_prod, in_cons, sizeof(intf->in)) == 0 )
+    {
+        vpl011->uartfr |= RXFE;
+        vpl011->uartris &= ~RXI;
+    }
+    vpl011->uartfr &= ~RXFF;
+    VPL011_UNLOCK(d, flags);
+
+    return data;
+}
+
+static void vpl011_write_data(struct domain *d, uint8_t data)
+{
+    unsigned long flags;
+    struct vpl011 *vpl011 = &d->arch.vpl011;
+    struct xencons_interface *intf = vpl011->ring_buf;
+    XENCONS_RING_IDX out_cons = intf->out_cons;
+    XENCONS_RING_IDX out_prod = intf->out_prod;
+
+    VPL011_LOCK(d, flags);
+
+    /*
+     * It is expected that the ring is not full when this function is called
+     * as the guest is expected to write to the data register only when the
+     * TXFF flag is not set.
+     * In case the guest does write even when the TXFF flag is set then the
+     * data will be silently dropped.
+     */
+    if ( xencons_queued(out_prod, out_cons, sizeof(intf->out)) !=
+         sizeof (intf->out) )
+    {
+        intf->out[xencons_mask(out_prod, sizeof(intf->out))] = data;
+        smp_wmb();
+        out_prod += 1;
+        intf->out_prod = out_prod;
+    }
+    else
+    {
+        gprintk(XENLOG_ERR, "vpl011: Unexpected OUT ring buffer full\n");
+    }
+
+    if ( xencons_queued(out_prod, out_cons, sizeof(intf->out)) ==
+         sizeof (intf->out) )
+    {
+        vpl011->uartfr |= TXFF;
+        vpl011->uartris &= ~TXI;
+    }
+
+    vpl011->uartfr |= BUSY;
+
+    vpl011->uartfr &= ~TXFE;
+
+    VPL011_UNLOCK(d, flags);
+
+    /*
+     * Send an event to console backend to indicate that there is 
+     * data in the OUT ring buffer.
+     */
+    notify_via_xen_event_channel(d, vpl011->evtchn);
+}
+
+static int vpl011_mmio_read(struct vcpu *v,
+                            mmio_info_t *info,
+                            register_t *r,
+                            void *priv)
+{
+    struct hsr_dabt dabt = info->dabt;
+    uint32_t vpl011_reg = (uint32_t)(info->gpa - GUEST_PL011_BASE);
+    struct vpl011 *vpl011 = &v->domain->arch.vpl011;
+
+    switch ( vpl011_reg )
+    {
+    case DR:
+        /*
+         * Since pl011 registers are 32-bit registers, all registers
+         * are handled similarly allowing 8-bit, 16-bit and 32-bit
+         * accesses.
+         */
+        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
+
+        *r = vreg_reg32_extract(vpl011_read_data(v->domain), info);
+        return 1;
+
+    case RSR:
+        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
+
+        /* It always returns 0 as there are no physical errors. */
+        *r = 0;
+        return 1;
+
+    case FR:
+        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
+
+        *r = vreg_reg32_extract(vpl011->uartfr, info);
+        return 1;
+
+    case RIS:
+        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
+
+        *r = vreg_reg32_extract(vpl011->uartris, info);
+        return 1;
+
+    case MIS:
+        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
+
+        *r = vreg_reg32_extract(vpl011->uartris & 
+                                vpl011->uartimsc, info);
+        return 1;
+
+    case IMSC:
+        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
+
+        *r = vreg_reg32_extract(vpl011->uartimsc, info);
+        return 1;
+
+    case ICR:
+        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
+
+        /* Only write is valid. */
+        return 0;
+
+    default:
+        gprintk(XENLOG_ERR, "vpl011: unhandled read r%d offset %#08x\n",
+                dabt.reg, vpl011_reg);
+        return 0;
+    }
+
+    return 1;
+
+bad_width:
+    gprintk(XENLOG_ERR, "vpl011: bad read width %d r%d offset %#08x\n",
+            dabt.size, dabt.reg, vpl011_reg);
+    domain_crash_synchronous();
+    return 0;
+
+}
+
+static int vpl011_mmio_write(struct vcpu *v,
+                             mmio_info_t *info,
+                             register_t r,
+                             void *priv)
+{
+    struct hsr_dabt dabt = info->dabt;
+    uint32_t vpl011_reg = (uint32_t)(info->gpa - GUEST_PL011_BASE);
+    struct vpl011 *vpl011 = &v->domain->arch.vpl011;
+    struct domain *d = v->domain;
+    unsigned long flags;
+
+    switch ( vpl011_reg )
+    {
+    case DR:
+    {
+        uint32_t data = 0;
+
+        /*
+         * Since pl011 registers are 32-bit registers, all registers
+         * are handled similarly allowing 8-bit, 16-bit and 32-bit
+         * accesses.
+         */
+        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
+
+        vreg_reg32_update(&data, r, info);
+        data &= 0xFF;
+        vpl011_write_data(v->domain, data);
+        return 1;
+    }
+    case RSR: /* Nothing to clear. */
+        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
+
+        return 1; 
+
+    case FR:
+    case RIS:
+    case MIS:
+        goto write_ignore;
+
+    case IMSC:
+        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
+
+        VPL011_LOCK(d, flags);
+        vreg_reg32_update(&vpl011->uartimsc, r, info);
+        VPL011_UNLOCK(d, flags);
+        vpl011_update(v->domain);
+        return 1;
+
+    case ICR:
+        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
+
+        VPL011_LOCK(d, flags);
+        vreg_reg32_clearbits(&vpl011->uartris, r, info);
+        VPL011_UNLOCK(d, flags);
+        vpl011_update(d);
+        return 1;
+
+    default:
+        gprintk(XENLOG_ERR, "vpl011: unhandled write r%d offset %#08x\n",
+                dabt.reg, vpl011_reg);
+        return 0;
+    }
+
+write_ignore:
+    return 1;
+
+bad_width:
+    gprintk(XENLOG_ERR, "vpl011: bad write width %d r%d offset %#08x\n",
+            dabt.size, dabt.reg, vpl011_reg);
+    domain_crash_synchronous();
+    return 0;
+
+}
+
+static const struct mmio_handler_ops vpl011_mmio_handler = {
+    .read = vpl011_mmio_read,
+    .write = vpl011_mmio_write,
+};
+
+static void vpl011_data_avail(struct domain *d)
+{
+    unsigned long flags;
+    struct vpl011 *vpl011 = &d->arch.vpl011;
+    struct xencons_interface *intf = vpl011->ring_buf;
+    XENCONS_RING_IDX in_cons = intf->in_cons;
+    XENCONS_RING_IDX in_prod = intf->in_prod;
+    XENCONS_RING_IDX out_cons = intf->out_cons;
+    XENCONS_RING_IDX out_prod = intf->out_prod;
+    XENCONS_RING_IDX in_ring_qsize, out_ring_qsize;
+
+    VPL011_LOCK(d, flags);
+
+    in_ring_qsize = xencons_queued(in_prod,
+                                   in_cons,
+                                   sizeof(intf->in));
+
+    out_ring_qsize = xencons_queued(out_prod,
+                                    out_cons,
+                                    sizeof(intf->out));
+
+    /* Update the uart rx state if the buffer is not empty. */
+    if ( in_ring_qsize != 0 )
+    {
+        vpl011->uartfr &= ~RXFE;
+        if ( in_ring_qsize == sizeof(intf->in) )
+            vpl011->uartfr |= RXFF;
+        vpl011->uartris |= RXI;
+    }
+
+    /* Update the uart tx state if the buffer is not full. */
+    if ( out_ring_qsize != sizeof(intf->out) )
+    {
+        vpl011->uartfr &= ~TXFF;
+        vpl011->uartris |= TXI;
+        if ( out_ring_qsize == 0 )
+        {
+            vpl011->uartfr &= ~BUSY;
+            vpl011->uartfr |= TXFE;
+        }
+    }
+
+    VPL011_UNLOCK(d, flags);
+
+    vpl011_update(d);
+}
+
+
+static void vpl011_notification(struct vcpu *v, unsigned int port)
+{
+    vpl011_data_avail(v->domain);
+}
+
+int domain_vpl011_init(struct domain *d, struct vpl011_init_info *info)
+{
+    int rc;
+    struct vpl011 *vpl011 = &d->arch.vpl011;
+
+    if ( vpl011->ring_buf )
+        return 0;
+
+    /* Map the guest PFN to Xen address space. */
+    rc =  prepare_ring_for_helper(d,
+                                  gfn_x(info->gfn),
+                                  &vpl011->ring_page,
+                                  &vpl011->ring_buf);
+    if ( rc < 0 )
+        goto out;
+
+    rc = vgic_reserve_virq(d, GUEST_VPL011_SPI);
+    if ( !rc )
+    {
+        rc = -EINVAL;
+        goto out1;
+    }
+
+    register_mmio_handler(d, &vpl011_mmio_handler,
+                          GUEST_PL011_BASE, GUEST_PL011_SIZE, NULL);
+
+    spin_lock_init(&vpl011->lock);
+
+    rc = alloc_unbound_xen_event_channel(d, 0, info->console_domid,
+                                         vpl011_notification);
+    if ( rc < 0 )
+        goto out2;
+
+    vpl011->evtchn = info->evtchn = rc;
+
+    return 0;
+
+out2:
+    xfree(d->arch.vmmio.handlers);
+    vgic_free_virq(d, GUEST_VPL011_SPI);
+
+out1:
+    destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
+
+out:
+    return rc;
+}
+
+void domain_vpl011_deinit(struct domain *d)
+{
+    struct vpl011 *vpl011 = &d->arch.vpl011;
+
+    if ( !vpl011->ring_buf )
+        return;
+
+    free_xen_event_channel(d, vpl011->evtchn);
+    destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
+    xfree(d->arch.vmmio.handlers);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 6de8082..91d1061 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -11,6 +11,7 @@
 #include <public/hvm/params.h>
 #include <xen/serial.h>
 #include <xen/rbtree.h>
+#include <asm-arm/vpl011.h>
 
 struct hvm_domain
 {
@@ -133,6 +134,11 @@ struct arch_domain
     struct {
         uint8_t privileged_call_enabled : 1;
     } monitor;
+
+#ifdef CONFIG_VPL011_CONSOLE
+    struct vpl011 vpl011;
+#endif
+
 }  __cacheline_aligned;
 
 struct arch_vcpu
diff --git a/xen/include/asm-arm/pl011-uart.h b/xen/include/asm-arm/pl011-uart.h
index 123f477..57e9ec7 100644
--- a/xen/include/asm-arm/pl011-uart.h
+++ b/xen/include/asm-arm/pl011-uart.h
@@ -49,6 +49,8 @@
 /* FR bits */
 #define TXFE   (1<<7) /* TX FIFO empty */
 #define RXFE   (1<<4) /* RX FIFO empty */
+#define TXFF   (1<<5) /* TX FIFO full */
+#define RXFF   (1<<6) /* RX FIFO full */
 #define BUSY   (1<<3) /* Transmit is not complete */
 
 /* LCR_H bits */
diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
new file mode 100644
index 0000000..b3e332d
--- /dev/null
+++ b/xen/include/asm-arm/vpl011.h
@@ -0,0 +1,74 @@
+/*
+ * include/xen/vpl011.h
+ *
+ * Virtual PL011 UART
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _VPL011_H_
+
+#define _VPL011_H_
+
+#include <public/domctl.h>
+#include <public/io/ring.h>
+#include <asm-arm/vreg.h>
+#include <xen/mm.h>
+
+/* helper macros */
+#define VPL011_LOCK(d,flags) spin_lock_irqsave(&(d)->arch.vpl011.lock, flags)
+#define VPL011_UNLOCK(d,flags) spin_unlock_irqrestore(&(d)->arch.vpl011.lock, flags)
+
+struct vpl011 {
+    void *ring_buf;
+    struct page_info *ring_page;
+    uint32_t    uartfr;     /* Flag register */
+    uint32_t    uartcr;     /* Control register */
+    uint32_t    uartimsc;   /* Interrupt mask register*/
+    uint32_t    uarticr;    /* Interrupt clear register */
+    uint32_t    uartris;    /* Raw interrupt status register */
+    uint32_t    uartmis;    /* Masked interrupt register */
+    spinlock_t  lock;
+    evtchn_port_t evtchn;
+};
+
+struct vpl011_init_info {
+    uint32_t console_domid;
+    gfn_t gfn;
+    evtchn_port_t evtchn;
+};
+
+#ifdef CONFIG_VPL011_CONSOLE
+int domain_vpl011_init(struct domain *d,
+                       struct vpl011_init_info *info);
+void domain_vpl011_deinit(struct domain *d);
+#else
+static inline int domain_vpl011_init(struct domain *d,
+                                     struct vpl011_init_info *info)
+{
+    return -ENOSYS;
+}
+
+static inline void domain_vpl011_deinit(struct domain *d) { }
+#endif
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
index bd974fb..85ab665 100644
--- a/xen/include/public/arch-arm.h
+++ b/xen/include/public/arch-arm.h
@@ -410,6 +410,10 @@ typedef uint64_t xen_callback_t;
 #define GUEST_ACPI_BASE 0x20000000ULL
 #define GUEST_ACPI_SIZE 0x02000000ULL
 
+/* PL011 mappings */
+#define GUEST_PL011_BASE    0x22000000ULL
+#define GUEST_PL011_SIZE    0x00001000ULL
+
 /*
  * 16MB == 4096 pages reserved for guest to use as a region to map its
  * grant table in.
@@ -444,6 +448,8 @@ typedef uint64_t xen_callback_t;
 #define GUEST_TIMER_PHYS_NS_PPI 30
 #define GUEST_EVTCHN_PPI        31
 
+#define GUEST_VPL011_SPI        32
+
 /* PSCI functions */
 #define PSCI_cpu_suspend 0
 #define PSCI_cpu_off     1
diff --git a/xen/include/public/io/console.h b/xen/include/public/io/console.h
index e2cd97f..5e45e1c 100644
--- a/xen/include/public/io/console.h
+++ b/xen/include/public/io/console.h
@@ -27,6 +27,8 @@
 #ifndef __XEN_PUBLIC_IO_CONSOLE_H__
 #define __XEN_PUBLIC_IO_CONSOLE_H__
 
+#include "ring.h"
+
 typedef uint32_t XENCONS_RING_IDX;
 
 #define MASK_XENCONS_IDX(idx, ring) ((idx) & (sizeof(ring)-1))
@@ -38,6 +40,8 @@ struct xencons_interface {
     XENCONS_RING_IDX out_cons, out_prod;
 };
 
+DEFINE_XEN_FLEX_RING(xencons);
+
 #endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */
 
 /*
-- 
2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 65+ messages in thread

end of thread, other threads:[~2017-06-23 12:45 UTC | newest]

Thread overview: 65+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-06 17:25 [PATCH 00/14 v4] PL011 emulation support in Xen Bhupinder Thakur
2017-06-06 17:25 ` [PATCH 01/14 v4] xen/arm: vpl011: Move vgic register access functions to vreg.h Bhupinder Thakur
2017-06-09 12:49   ` Julien Grall
2017-06-06 17:25 ` [PATCH 02/14 v4] xen/arm: vpl011: Define generic vreg_reg* access functions in vreg.h Bhupinder Thakur
2017-06-09 12:54   ` Julien Grall
2017-06-19  9:33   ` Andre Przywara
2017-06-19 16:53     ` Bhupinder Thakur
2017-06-19 16:59       ` Andre Przywara
2017-06-06 17:25 ` [PATCH 03/14 v4] xen/arm: vpl011: Add pl011 uart emulation in Xen Bhupinder Thakur
2017-06-06 23:02   ` Stefano Stabellini
2017-06-09 13:15     ` Julien Grall
2017-06-09 18:02       ` Stefano Stabellini
2017-06-13  8:58       ` Bhupinder Thakur
2017-06-13  9:25         ` Julien Grall
2017-06-09 13:54   ` Julien Grall
2017-06-13 10:57     ` Bhupinder Thakur
2017-06-13 12:44       ` Julien Grall
2017-06-13 17:50         ` Stefano Stabellini
2017-06-14  5:47         ` Bhupinder Thakur
2017-06-14  9:33           ` Julien Grall
2017-06-19 10:14   ` Andre Przywara
2017-06-22  5:16     ` Bhupinder Thakur
2017-06-23 12:45     ` Julien Grall
2017-06-06 17:25 ` [PATCH 04/14 v4] xen/arm: vpl011: Add support for vuart in libxl Bhupinder Thakur
2017-06-06 23:07   ` Stefano Stabellini
2017-06-06 17:25 ` [PATCH 05/14 v4] xen/arm: vpl011: Allocate a new GFN in the toolstack for vuart Bhupinder Thakur
2017-06-06 23:17   ` Stefano Stabellini
2017-06-07 16:43   ` Wei Liu
2017-06-06 17:25 ` [PATCH 06/14 v4] xen/arm: vpl011: Add a new domctl API to initialize vpl011 Bhupinder Thakur
2017-06-06 23:26   ` Stefano Stabellini
2017-06-09 14:06     ` Julien Grall
2017-06-09 18:32       ` Stefano Stabellini
2017-06-14  7:35     ` Bhupinder Thakur
2017-06-14  8:34       ` Bhupinder Thakur
2017-06-09 14:13   ` Julien Grall
2017-06-14  9:16     ` Bhupinder Thakur
2017-06-14 10:15       ` Julien Grall
2017-06-15  6:33         ` Bhupinder Thakur
2017-06-19 10:59           ` Bhupinder Thakur
2017-06-19 11:01             ` Julien Grall
2017-06-19 11:47               ` Wei Liu
2017-06-19 13:11                 ` Bhupinder Thakur
2017-06-20 11:16                   ` Julien Grall
2017-06-20 11:42                     ` Wei Liu
2017-06-21 10:18                     ` Bhupinder Thakur
2017-06-06 17:25 ` [PATCH 07/14 v4] xen/arm: vpl011: Add a new vuart node in the xenstore Bhupinder Thakur
2017-06-06 23:38   ` Stefano Stabellini
2017-06-06 17:25 ` [PATCH 08/14 v4] xen/arm: vpl011: Modify xenconsole to define and use a new console structure Bhupinder Thakur
2017-06-07  1:13   ` Stefano Stabellini
2017-06-06 17:25 ` [PATCH 09/14 v4] xen/arm: vpl011: Modify xenconsole functions to take console structure as input Bhupinder Thakur
2017-06-07  0:43   ` Stefano Stabellini
2017-06-06 17:25 ` [PATCH 10/14 v4] xen/arm: vpl011: Modify xenconsole to support multiple consoles Bhupinder Thakur
2017-06-07  1:03   ` Stefano Stabellini
2017-06-07  3:51     ` Bhupinder Thakur
2017-06-07 16:46       ` Wei Liu
2017-06-07 17:54       ` Stefano Stabellini
2017-06-06 17:25 ` [PATCH 11/14 v4] xen/arm: vpl011: Add support for vuart console in xenconsole Bhupinder Thakur
2017-06-07  1:08   ` Stefano Stabellini
2017-06-07 16:44   ` Wei Liu
2017-06-06 17:25 ` [PATCH 12/14 v4] xen/arm: vpl011: Add a new vuart console type to xenconsole client Bhupinder Thakur
2017-06-06 23:41   ` Stefano Stabellini
2017-06-06 17:25 ` [PATCH 13/14 v4] xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree Bhupinder Thakur
2017-06-06 17:25 ` [PATCH 14/14 v4] xen/arm: vpl011: Update documentation for vuart console support Bhupinder Thakur
2017-06-09 13:58 ` [PATCH 00/14 v4] PL011 emulation support in Xen Julien Grall
  -- strict thread matches above, loose matches on Subject: below --
2017-06-06 10:02 [PATCH 03/14 v4] xen/arm: vpl011: Add pl011 uart emulation " Bhupinder Thakur

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).