All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/10 v2] pl011 emulation support in Xen
@ 2017-04-28 16:01 Bhupinder Thakur
  2017-04-28 16:01 ` [PATCH 01/10 v2] xen/arm: vpl011: Add pl011 uart emulation " Bhupinder Thakur
                   ` (10 more replies)
  0 siblings, 11 replies; 54+ messages in thread
From: Bhupinder Thakur @ 2017-04-28 16:01 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich

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.

Note that 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 two new domctl API to set and get pfn and evtchn respectively
    - Allocate a new event channel for sending/receiving events from Xen 
      and return to the toolstack.
    - Map the PFN allocted by the toolstack to be used as IN/OUT ring 
      buffers.

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

Toolstack
==========

1. Create a sbsa uart DT node in the guest device tree. It uses a fixed
   vpl011 SPI IRQ number and MMIO address.

2. Allocate a new PFN and pass it on to Xen though a hvm call to be used 
   as the IN/OUT ring buffers.

3. Add two new keys to the xen store
    - Allocate a PFN to be used as IN/OUT ring buffer by xenconsoled 
    - Read new event channel from Xen using a hvm call to be used by 
      xenconsoled for sending/receiving events.

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. Modfications in domain_create_ring(): 
    - Bind to the vpl011 event channel obtained from the xen store as a new
      parameter
    - Map the PFN to its address space to be used as IN/OUT ring buffers. 
      It obtains the PFN from the xen store as a new parameter

4. Modifications in handle_ring_read() to handle both PV and VUART
   events.

The vpl011 changes available at the following repo:

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

Bhupinder Thakur (10):
  xen/arm: vpl011: Add pl011 uart emulation in Xen
  xen/arm: vpl011: Add new vuart domctl interface to setup pfn and
    evtchn
  xen/arm: vpl011: Enable pl011 emulation for a guest domain in Xen
  xen/arm: vpl011: Add support for vuart in libxl
  xen/arm: vpl011: Allocate a new PFN in the toolstack for vuart
  xen/arm: vpl011: Add vuart ring-buf and evtchn to xenstore
  xen/arm: vpl011: Add support for vuart 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

 docs/man/xl.cfg.pod.5.in         |   8 +
 docs/misc/console.txt            |  14 +-
 tools/console/client/main.c      |   8 +-
 tools/console/daemon/io.c        | 514 +++++++++++++++++++++++++++------------
 tools/libxc/include/xc_dom.h     |   2 +
 tools/libxc/include/xenctrl.h    |  26 ++
 tools/libxc/xc_dom_arm.c         |   7 +-
 tools/libxc/xc_dom_boot.c        |   2 +
 tools/libxc/xc_domain.c          |  39 +++
 tools/libxl/libxl.h              |   6 +
 tools/libxl/libxl_arm.c          |  54 +++-
 tools/libxl/libxl_console.c      |  10 +
 tools/libxl/libxl_create.c       |  10 +
 tools/libxl/libxl_dom.c          |   4 +
 tools/libxl/libxl_internal.h     |   4 +
 tools/libxl/libxl_types.idl      |   2 +
 tools/xl/xl_console.c            |   4 +-
 tools/xl/xl_parse.c              |   3 +
 xen/arch/arm/Kconfig             |   5 +
 xen/arch/arm/Makefile            |   1 +
 xen/arch/arm/domain.c            |   6 +
 xen/arch/arm/domctl.c            |  20 ++
 xen/arch/arm/vpl011.c            | 340 ++++++++++++++++++++++++++
 xen/arch/x86/domctl.c            |   4 +
 xen/common/domctl.c              |   3 +
 xen/include/asm-arm/domain.h     |   3 +
 xen/include/asm-arm/pl011-uart.h |   2 +
 xen/include/public/arch-arm.h    |   8 +
 xen/include/public/domctl.h      |  13 +
 xen/include/xen/sched.h          |   4 +
 xen/include/xen/vpl011.h         |  74 ++++++
 31 files changed, 1045 insertions(+), 155 deletions(-)
 create mode 100644 xen/arch/arm/vpl011.c
 create mode 100644 xen/include/xen/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] 54+ messages in thread

* [PATCH 01/10 v2] xen/arm: vpl011: Add pl011 uart emulation in Xen
  2017-04-28 16:01 [PATCH 00/10 v2] pl011 emulation support in Xen Bhupinder Thakur
@ 2017-04-28 16:01 ` Bhupinder Thakur
  2017-04-28 19:08   ` Stefano Stabellini
                     ` (2 more replies)
  2017-04-28 16:01 ` [PATCH 02/10 v2] xen/arm: vpl011: Add new vuart domctl interface to setup pfn and evtchn Bhupinder Thakur
                   ` (9 subsequent siblings)
  10 siblings, 3 replies; 54+ messages in thread
From: Bhupinder Thakur @ 2017-04-28 16:01 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich

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 v1:

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

 xen/arch/arm/Kconfig             |   5 +
 xen/arch/arm/Makefile            |   1 +
 xen/arch/arm/vpl011.c            | 340 +++++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/domain.h     |   3 +
 xen/include/asm-arm/pl011-uart.h |   2 +
 xen/include/public/arch-arm.h    |   8 +
 xen/include/xen/vpl011.h         |  74 +++++++++
 7 files changed, 433 insertions(+)
 create mode 100644 xen/arch/arm/vpl011.c
 create mode 100644 xen/include/xen/vpl011.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..51abade
--- /dev/null
+++ b/xen/arch/arm/vpl011.c
@@ -0,0 +1,340 @@
+/*
+ * 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/sched.h>
+#include <xen/vpl011.h>
+#include <public/io/console.h>
+#include <asm-arm/pl011-uart.h>
+
+unsigned int vpl011_reg_mask[] = {0xff, 0xffff, 0xffffffff};
+
+static void vgic_inject_vpl011_spi(struct domain *d)
+{
+    struct vpl011_s *vpl011 = &d->arch.vpl011;
+
+    if ( (vpl011->uartris & vpl011->uartimsc) )
+        vgic_vcpu_inject_spi(d, GUEST_VPL011_SPI);
+}
+
+static void vpl011_read_data(struct domain *d, uint8_t *data)
+{
+    unsigned long flags;
+    struct vpl011_s *vpl011 = &d->arch.vpl011;
+    struct xencons_interface *intf = vpl011->ring_buf;
+
+    /*
+     * Initialize the data so that even if there is no data in ring buffer
+     * 0 is returned.
+     */
+    *data = 0;
+
+    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 ( !VPL011_IN_RING_EMPTY(intf) )
+    {
+        uint32_t in_cons = intf->in_cons;
+        *data = intf->in[MASK_XENCONS_IDX(in_cons, intf->in)];
+        smp_mb();
+        intf->in_cons = in_cons + 1;
+    }
+
+    if ( VPL011_IN_RING_EMPTY(intf) )
+    {
+        vpl011->uartfr |= (RXFE);
+        vpl011->uartris &= ~(RXI);
+    }
+    vpl011->uartfr &= ~(RXFF);
+    VPL011_UNLOCK(d, flags);
+
+    notify_via_xen_event_channel(d, vpl011->evtchn);
+}
+
+static void vpl011_write_data(struct domain *d, uint8_t data)
+{
+    unsigned long flags;
+    struct vpl011_s *vpl011 = &d->arch.vpl011;
+    struct xencons_interface *intf = vpl011->ring_buf;
+
+    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 ( !VPL011_OUT_RING_FULL(intf) )
+    {
+        uint32_t out_prod = intf->out_prod;
+        intf->out[MASK_XENCONS_IDX(out_prod, intf->out)] = data;
+        smp_wmb();
+        intf->out_prod = out_prod + 1;
+    }
+
+    if ( VPL011_OUT_RING_FULL(intf) )
+    {
+        vpl011->uartfr |= (TXFF);
+        vpl011->uartris &= ~(TXI);
+    }
+
+    vpl011->uartfr |= (BUSY);
+
+    vpl011->uartfr &= ~(TXFE);
+
+    VPL011_UNLOCK(d, flags);
+
+    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)
+{
+    uint8_t ch;
+    struct hsr_dabt dabt = info->dabt;
+    int vpl011_reg = (int)(info->gpa - GUEST_PL011_BASE);
+    struct vpl011_s *vpl011 = &v->domain->arch.vpl011;
+
+    switch ( vpl011_reg )
+    {
+    case DR:
+        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
+        vpl011_read_data(v->domain, &ch);
+        *r = ch;
+        break;
+
+    case RSR:
+        if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;
+
+        /* It always returns 0 as there are no physical errors. */
+        *r = 0;
+        break;
+
+    case FR:
+        if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;
+        *r = (vpl011->uartfr & vpl011_reg_mask[dabt.size]);
+        break;
+
+    case RIS:
+        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
+        *r = (vpl011->uartris & vpl011_reg_mask[dabt.size]);
+        break;
+
+    case MIS:
+        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
+        *r = (vpl011->uartris &
+                            vpl011->uartimsc & vpl011_reg_mask[dabt.size]);
+        break;
+
+    case IMSC:
+        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
+        *r = (vpl011->uartimsc & vpl011_reg_mask[dabt.size]);
+        break;
+
+    case ICR:
+        if ( !VALID_W_SIZE(dabt.size) ) 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)
+{
+    uint8_t ch = ((struct uartdr_reg *)&r)->data;
+    struct hsr_dabt dabt = info->dabt;
+    int vpl011_reg = (int)(info->gpa - GUEST_PL011_BASE);
+    struct vpl011_s *vpl011 = &v->domain->arch.vpl011;
+
+    switch ( vpl011_reg )
+    {
+    case DR:
+
+        if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;
+        vpl011_write_data(v->domain, ch);
+        break;
+
+    case RSR: /* Nothing to clear. */
+        if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;
+        break;
+
+    case FR:
+        goto write_ignore;
+    case RIS:
+    case MIS:
+        goto word_write_ignore;
+
+    case IMSC:
+        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
+        vpl011->uartimsc = (r & vpl011_reg_mask[dabt.size]);
+        vgic_inject_vpl011_spi(v->domain);
+        break;
+
+    case ICR:
+        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
+        vpl011->uartris &= ~(r & vpl011_reg_mask[dabt.size]);
+        vgic_inject_vpl011_spi(v->domain);
+        break;
+
+    default:
+        gprintk(XENLOG_ERR, "vpl011: unhandled write r%d offset %#08x\n",
+                               dabt.reg, vpl011_reg);
+        return 0;
+    }
+
+    return 1;
+
+write_ignore:
+    if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;
+    return 1;
+
+word_write_ignore:
+    if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
+    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,
+};
+
+int vpl011_map_guest_page(struct domain *d, unsigned long pfn)
+{
+    struct vpl011_s *vpl011 = &d->arch.vpl011;
+
+    /* Map the guest PFN to Xen address space. */
+    return prepare_ring_for_helper(d,
+                                   pfn,
+                                   &vpl011->ring_page,
+                                   &vpl011->ring_buf);
+}
+
+static void vpl011_data_avail(struct domain *d)
+{
+    unsigned long flags;
+    struct vpl011_s *vpl011 = &d->arch.vpl011;
+    struct xencons_interface *intf = vpl011->ring_buf;
+    uint32_t in_ring_depth, out_ring_depth;
+
+    VPL011_LOCK(d, flags);
+
+    in_ring_depth = intf->in_prod - intf->in_cons;
+    out_ring_depth = intf->out_prod - intf->out_cons;
+
+    /* Update the uart rx state if the buffer is not empty. */
+    if ( in_ring_depth != 0 )
+    {
+        vpl011->uartfr &= ~(RXFE);
+        if ( in_ring_depth == VPL011_RING_MAX_DEPTH(intf, in) )
+            vpl011->uartfr |= (RXFF);
+        vpl011->uartris |= (RXI);
+    }
+
+    /* Update the uart tx state if the buffer is not full. */
+    if ( out_ring_depth != VPL011_RING_MAX_DEPTH(intf, out) )
+    {
+        vpl011->uartfr &= ~(TXFF);
+        vpl011->uartris |= (TXI);
+        if ( out_ring_depth == 0 )
+        {
+            vpl011->uartfr &= ~(BUSY);
+            vpl011->uartfr |= (TXFE);
+        }
+    }
+
+    VPL011_UNLOCK(d, flags);
+
+    vgic_inject_vpl011_spi(d);
+}
+
+
+static void vpl011_notification(struct vcpu *v, unsigned int port)
+{
+    vpl011_data_avail(v->domain);
+}
+
+int domain_vpl011_init(struct domain *d, struct xen_arch_domainconfig *config)
+{
+    int rc;
+    struct vpl011_s *vpl011 = &d->arch.vpl011;
+
+    rc = alloc_unbound_xen_event_channel(d, 0, config->console_domid,
+                                         vpl011_notification);
+    if (rc < 0)
+    {
+        return rc;
+    }
+
+    vpl011->evtchn = rc;
+    rc = vgic_reserve_virq(d, GUEST_VPL011_SPI);
+    if ( !rc )
+    {
+        free_xen_event_channel(d, vpl011->evtchn);
+        vpl011->evtchn = -1;
+        return rc;
+    }
+    register_mmio_handler(d, &vpl011_mmio_handler, GUEST_PL011_BASE, GUEST_PL011_SIZE, NULL);
+    spin_lock_init(&vpl011->lock);
+
+    vpl011->initialized = true;
+
+    return 0;
+}
+
+void domain_vpl011_deinit(struct domain *d)
+{
+    struct vpl011_s *vpl011 = &d->arch.vpl011;
+
+    if ( vpl011->initialized )
+    {
+        free_xen_event_channel(d, vpl011->evtchn);
+        destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
+    }
+    vpl011->initialized = false;
+}
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 6de8082..a0f8f89 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 <xen/vpl011.h>
 
 struct hvm_domain
 {
@@ -133,6 +134,8 @@ struct arch_domain
     struct {
         uint8_t privileged_call_enabled : 1;
     } monitor;
+
+    struct vpl011_s vpl011;
 }  __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/public/arch-arm.h b/xen/include/public/arch-arm.h
index bd974fb..5f91207 100644
--- a/xen/include/public/arch-arm.h
+++ b/xen/include/public/arch-arm.h
@@ -322,6 +322,8 @@ struct xen_arch_domainconfig {
      *
      */
     uint32_t clock_frequency;
+
+    uint32_t console_domid;
 };
 #endif /* __XEN__ || __XEN_TOOLS__ */
 
@@ -410,6 +412,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 +450,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/xen/vpl011.h b/xen/include/xen/vpl011.h
new file mode 100644
index 0000000..57d61b4
--- /dev/null
+++ b/xen/include/xen/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_
+
+/* helper macros */
+#define VPL011_RING_DEPTH(intf,dir) (((intf)->dir ## _prod - (intf)->dir ## _cons))
+
+#define VPL011_RING_MAX_DEPTH(intf,dir) (sizeof((intf)->dir)-1)
+
+#define VPL011_IN_RING_EMPTY(intf) (VPL011_RING_DEPTH(intf, in) == 0)
+
+#define VPL011_OUT_RING_EMPTY(intf) (VPL011_RING_DEPTH(intf, out) == 0)
+
+#define VPL011_IN_RING_FULL(intf) (VPL011_RING_DEPTH(intf, in) == VPL011_RING_MAX_DEPTH(intf, in))
+
+#define VPL011_OUT_RING_FULL(intf) (VPL011_RING_DEPTH(intf, out) == VPL011_RING_MAX_DEPTH(intf,out))
+
+#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)
+
+#define VALID_BW_SIZE(size) ( size == DABT_BYTE || size == DABT_HALF_WORD || size == DABT_WORD )
+#define VALID_W_SIZE(size)  ( size == DABT_HALF_WORD || size == DABT_WORD )
+
+struct uartdr_reg {
+    uint8_t data;
+    uint8_t error_status:4;
+    uint8_t reserved1:4;
+    uint16_t reserved2;
+    uint32_t reserved3;
+};
+
+struct vpl011_s {
+    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;
+    bool        initialized; /* Flag which tells whether vpl011 is initialized */
+    uint32_t    evtchn;
+};
+
+#ifdef CONFIG_VPL011_CONSOLE
+int domain_vpl011_init(struct domain *d, struct xen_arch_domainconfig *config);
+void domain_vpl011_deinit(struct domain *d);
+int vpl011_map_guest_page(struct domain *d, unsigned long pfn);
+#else
+static inline int domain_vpl011_init(struct domain *d, struct xen_arch_domainconfig *config) { return -ENOSYS; }
+static inline void domain_vpl011_deinit(struct domain *d) { }
+static inline int vpl011_map_guest_page(struct domain *d, unsigned long pfn) { return -ENOSYS; }
+#endif
+
+#endif
-- 
2.7.4


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

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

* [PATCH 02/10 v2] xen/arm: vpl011: Add new vuart domctl interface to setup pfn and evtchn
  2017-04-28 16:01 [PATCH 00/10 v2] pl011 emulation support in Xen Bhupinder Thakur
  2017-04-28 16:01 ` [PATCH 01/10 v2] xen/arm: vpl011: Add pl011 uart emulation " Bhupinder Thakur
@ 2017-04-28 16:01 ` Bhupinder Thakur
  2017-04-28 19:23   ` Stefano Stabellini
                     ` (2 more replies)
  2017-04-28 16:01 ` [PATCH 03/10 v2] xen/arm: vpl011: Enable pl011 emulation for a guest domain in Xen Bhupinder Thakur
                   ` (8 subsequent siblings)
  10 siblings, 3 replies; 54+ messages in thread
From: Bhupinder Thakur @ 2017-04-28 16:01 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich

1. Add two new domctl API to:
    - Allocate a new event channel for sending/receiving events to/from Xen.
    - Map the PFN allocted by the toolstack to be used as IN/OUT ring buffers.

Xen will communicate with xenconsole over the ring buffer and the event
channel to transmit and receive pl011 data on guest domain's behalf.

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

Changes since v1:

- Replaced the hvm interface with domctl interface

 tools/libxc/include/xenctrl.h | 26 ++++++++++++++++++++++++++
 tools/libxc/xc_domain.c       | 39 +++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/domctl.c         | 20 ++++++++++++++++++++
 xen/arch/x86/domctl.c         |  4 ++++
 xen/include/public/domctl.h   | 11 +++++++++++
 5 files changed, 100 insertions(+)

diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 1629f41..bebfe7d 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -886,6 +886,32 @@ int xc_vcpu_getcontext(xc_interface *xch,
                        vcpu_guest_context_any_t *ctxt);
 
 /**
+ * This function returns information about the pfn and the event channel
+ * to be used for setting up a virtual uart console.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain to get information from
+ * @parm vuart_pfn the pfn to be used for the ring buffer
+ * @return 0 on success, negative error on failure
+ */
+int xc_domain_vuart_set_pfn(xc_interface *xch,
+                            uint32_t domid,
+                            uint32_t vuart_pfn);
+
+/**
+ * This function returns information about the pfn and the event channel
+ * to be used for setting up a virtual console.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain to get information from
+ * @parm vuart_evtchn the event channel to be used for console events
+ * @return 0 on success, negative error on failure
+ */
+int xc_domain_vuart_get_evtchn(xc_interface *xch,
+                               uint32_t domid,
+                               uint32_t *vuart_evtchn);
+
+/**
  * This function returns information about the XSAVE state of a particular
  * vcpu of a domain. If extstate->size and extstate->xfeature_mask are 0,
  * the call is considered a query to retrieve them and the buffer is not
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index 00909ad4..943f202 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -343,6 +343,45 @@ int xc_domain_get_guest_width(xc_interface *xch, uint32_t domid,
     return 0;
 }
 
+int xc_domain_vuart_set_pfn(xc_interface *xch,
+                            uint32_t domid,
+                            uint32_t vuart_pfn)
+{
+    DECLARE_DOMCTL;
+    int rc = 0;
+
+    domctl.cmd = XEN_DOMCTL_vuart_op;
+    domctl.domain = (domid_t)domid;
+    domctl.u.vuart_op.cmd = XEN_DOMCTL_VUART_OP_SET_PFN;
+    domctl.u.vuart_op.pfn = vuart_pfn;
+
+    if ( (rc = do_domctl(xch, &domctl)) < 0 )
+        return rc;
+
+    return rc;
+}
+
+int xc_domain_vuart_get_evtchn(xc_interface *xch,
+                               uint32_t domid,
+                               uint32_t *vuart_evtchn)
+{
+    DECLARE_DOMCTL;
+    int rc = 0;
+
+	*vuart_evtchn = -1;
+
+    domctl.cmd = XEN_DOMCTL_vuart_op;
+    domctl.domain = (domid_t)domid;
+    domctl.u.vuart_op.cmd = XEN_DOMCTL_VUART_OP_GET_EVTCHN;
+
+    if ( (rc = do_domctl(xch, &domctl)) < 0 )
+        return rc;
+
+    *vuart_evtchn = domctl.u.vuart_op.evtchn;
+
+    return rc;
+}
+
 int xc_domain_getinfo(xc_interface *xch,
                       uint32_t first_domid,
                       unsigned int max_doms,
diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
index 971caec..e400f87 100644
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -10,6 +10,7 @@
 #include <xen/sched.h>
 #include <xen/hypercall.h>
 #include <xen/iocap.h>
+#include <xen/guest_access.h>
 #include <xsm/xsm.h>
 #include <public/domctl.h>
 
@@ -119,6 +120,25 @@ long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
         d->disable_migrate = domctl->u.disable_migrate.disable;
         return 0;
 
+    case XEN_DOMCTL_vuart_op:
+    {
+        int rc;
+        if ( d->arch.vpl011.initialized )
+        {
+            if ( domctl->u.vuart_op.cmd == XEN_DOMCTL_VUART_OP_SET_PFN )
+            {
+                rc = vpl011_map_guest_page(d, domctl->u.vuart_op.pfn);
+            }
+            else
+            {
+                domctl->u.vuart_op.evtchn = d->arch.vpl011.evtchn;
+                rc = __copy_to_guest(u_domctl, domctl, 1);
+            }
+            return rc;
+        }
+        else
+            return -EINVAL;
+    }
     default:
     {
         int rc;
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index e104be2..49e907d 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -1465,6 +1465,10 @@ long arch_do_domctl(
         recalculate_cpuid_policy(d);
         break;
 
+    case XEN_DOMCTL_vuart_op:
+        ret = -EOPNOTSUPP;
+        break;
+
     default:
         ret = iommu_do_domctl(domctl, d, u_domctl);
         break;
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index e6cf211..8bee0c3 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -1138,6 +1138,15 @@ struct xen_domctl_psr_cat_op {
     uint32_t target;    /* IN */
     uint64_t data;      /* IN/OUT */
 };
+
+struct xen_domctl_vuart_op {
+#define XEN_DOMCTL_VUART_OP_SET_PFN      0
+#define XEN_DOMCTL_VUART_OP_GET_EVTCHN   1
+        uint32_t cmd;       /* XEN_DOMCTL_VUART_OP_* */
+        uint32_t pfn;       /* IN */
+        uint32_t evtchn;    /* OUT */
+};
+
 typedef struct xen_domctl_psr_cat_op xen_domctl_psr_cat_op_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_psr_cat_op_t);
 
@@ -1218,6 +1227,7 @@ struct xen_domctl {
 #define XEN_DOMCTL_monitor_op                    77
 #define XEN_DOMCTL_psr_cat_op                    78
 #define XEN_DOMCTL_soft_reset                    79
+#define XEN_DOMCTL_vuart_op                      80
 #define XEN_DOMCTL_gdbsx_guestmemio            1000
 #define XEN_DOMCTL_gdbsx_pausevcpu             1001
 #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
@@ -1280,6 +1290,7 @@ struct xen_domctl {
         struct xen_domctl_psr_cmt_op        psr_cmt_op;
         struct xen_domctl_monitor_op        monitor_op;
         struct xen_domctl_psr_cat_op        psr_cat_op;
+        struct xen_domctl_vuart_op          vuart_op;
         uint8_t                             pad[128];
     } u;
 };
-- 
2.7.4


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

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

* [PATCH 03/10 v2] xen/arm: vpl011: Enable pl011 emulation for a guest domain in Xen
  2017-04-28 16:01 [PATCH 00/10 v2] pl011 emulation support in Xen Bhupinder Thakur
  2017-04-28 16:01 ` [PATCH 01/10 v2] xen/arm: vpl011: Add pl011 uart emulation " Bhupinder Thakur
  2017-04-28 16:01 ` [PATCH 02/10 v2] xen/arm: vpl011: Add new vuart domctl interface to setup pfn and evtchn Bhupinder Thakur
@ 2017-04-28 16:01 ` Bhupinder Thakur
  2017-04-28 19:15   ` Stefano Stabellini
  2017-05-02  7:48   ` Jan Beulich
  2017-04-28 16:01 ` [PATCH 04/10 v2] xen/arm: vpl011: Add support for vuart in libxl Bhupinder Thakur
                   ` (7 subsequent siblings)
  10 siblings, 2 replies; 54+ messages in thread
From: Bhupinder Thakur @ 2017-04-28 16:01 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich

Vpl011 emulation is enabled for a guest domain in Xen only when it is
enabled through an option in libxl provided by the user through
guest configuration.

The pl011 enable/disable knob in libxl is introduced in the following
patch:

xen/arm: vpl011: Add support for vuart in libxl

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
---
 xen/arch/arm/domain.c       | 6 ++++++
 xen/common/domctl.c         | 3 +++
 xen/include/public/domctl.h | 2 ++
 xen/include/xen/sched.h     | 4 ++++
 4 files changed, 15 insertions(+)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 76310ed..23baa81 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -36,6 +36,7 @@
 #include <asm/platform.h>
 #include "vtimer.h"
 #include "vuart.h"
+#include <xen/vpl011.h>
 
 DEFINE_PER_CPU(struct vcpu *, curr_vcpu);
 
@@ -631,6 +632,9 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags,
     if ( (rc = domain_vtimer_init(d, config)) != 0 )
         goto fail;
 
+    if ( domcr_flags & DOMCRF_vuart )
+        if ( (rc = domain_vpl011_init(d, config)) != 0 )
+            goto fail;
     update_domain_wallclock_time(d);
 
     /*
@@ -665,6 +669,8 @@ fail:
 
 void arch_domain_destroy(struct domain *d)
 {
+    domain_vpl011_deinit(d);
+
     /* IOMMU page table is shared with P2M, always call
      * iommu_domain_destroy() before p2m_teardown().
      */
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index 951a5dc..902dd71 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -501,6 +501,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
                | XEN_DOMCTL_CDF_hap
                | XEN_DOMCTL_CDF_s3_integrity
                | XEN_DOMCTL_CDF_oos_off
+               | XEN_DOMCTL_VUART_enable
                | XEN_DOMCTL_CDF_xs_domain)) )
             break;
 
@@ -539,6 +540,8 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
             domcr_flags |= DOMCRF_oos_off;
         if ( op->u.createdomain.flags & XEN_DOMCTL_CDF_xs_domain )
             domcr_flags |= DOMCRF_xs_domain;
+        if ( op->u.createdomain.flags & XEN_DOMCTL_VUART_enable )
+            domcr_flags |= DOMCRF_vuart;
 
         d = domain_create(dom, domcr_flags, op->u.createdomain.ssidref,
                           &op->u.createdomain.config);
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index 8bee0c3..c307013 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -63,6 +63,8 @@ struct xen_domctl_createdomain {
  /* Is this a xenstore domain? */
 #define _XEN_DOMCTL_CDF_xs_domain     4
 #define XEN_DOMCTL_CDF_xs_domain      (1U<<_XEN_DOMCTL_CDF_xs_domain)
+#define _XEN_DOMCTL_VUART_enable      6
+#define XEN_DOMCTL_VUART_enable       (1U<<_XEN_DOMCTL_VUART_enable)
     uint32_t flags;
     struct xen_arch_domainconfig config;
 };
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 1127ca9..ee7dc7a 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -555,6 +555,10 @@ struct domain *domain_create(domid_t domid, unsigned int domcr_flags,
 #define _DOMCRF_xs_domain       5
 #define DOMCRF_xs_domain        (1U<<_DOMCRF_xs_domain)
 
+ /* DOMCRF_vuart: enable virtual uart emulation. Used for Aarch64. */
+#define _DOMCRF_vuart  7
+#define DOMCRF_vuart   (1U<<_DOMCRF_vuart)
+
 /*
  * rcu_lock_domain_by_id() is more efficient than get_domain_by_id().
  * This is the preferred function if the returned domain reference
-- 
2.7.4


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

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

* [PATCH 04/10 v2] xen/arm: vpl011: Add support for vuart in libxl
  2017-04-28 16:01 [PATCH 00/10 v2] pl011 emulation support in Xen Bhupinder Thakur
                   ` (2 preceding siblings ...)
  2017-04-28 16:01 ` [PATCH 03/10 v2] xen/arm: vpl011: Enable pl011 emulation for a guest domain in Xen Bhupinder Thakur
@ 2017-04-28 16:01 ` Bhupinder Thakur
  2017-04-28 21:45   ` Stefano Stabellini
  2017-05-03 10:27   ` Julien Grall
  2017-04-28 16:01 ` [PATCH 05/10 v2] xen/arm: vpl011: Allocate a new PFN in the toolstack for vuart Bhupinder Thakur
                   ` (6 subsequent siblings)
  10 siblings, 2 replies; 54+ messages in thread
From: Bhupinder Thakur @ 2017-04-28 16:01 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich

An option is provided in libxl to enable/disable pl011 vuart while
creating a guest domain.

Libxl now suppots a generic vuart console and pl011 is a specific type.
In future support can be added for multiple vuart of different types.

User can enable pl011 vuart by adding the following line in the guest
configuration file:

vuart = "pl011"

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

Changes since v1:
- Modified the syntax for taking the pl011 as a console type in the
  configuration file. Now the syntax is vuart = "pl011".
- Replaced the console type VCON with VUART, as it is more 
  intuitive.

 tools/libxl/libxl.h          |  6 ++++++
 tools/libxl/libxl_create.c   | 10 ++++++++++
 tools/libxl/libxl_internal.h |  4 ++++
 tools/libxl/libxl_types.idl  |  2 ++
 tools/xl/xl_console.c        |  4 +++-
 tools/xl/xl_parse.c          |  3 +++
 6 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index cf8687a..bcfbb6c 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -306,6 +306,12 @@
 #define LIBXL_HAVE_BUILDINFO_HVM_ACPI_LAPTOP_SLATE 1
 
 /*
+ * LIBXL_HAVE_VUART indicates that xenconsole/client supports
+ * virtual uart.
+ */
+#define LIBXL_HAVE_VUART 1
+
+/*
  * libxl ABI compatibility
  *
  * The only guarantee which libxl makes regarding ABI compatibility
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index bffbc45..5d70bc2 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -536,6 +536,9 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config,
         flags |= libxl_defbool_val(info->oos) ? 0 : XEN_DOMCTL_CDF_oos_off;
     }
 
+    if (!strcmp(d_config->b_info.vuart, "pl011"))
+        flags |= XEN_DOMCTL_VUART_enable;
+
     /* Ultimately, handle is an array of 16 uint8_t, same as uuid */
     libxl_uuid_copy(ctx, (libxl_uuid *)handle, &info->uuid);
 
@@ -900,6 +903,11 @@ static void initiate_domain_create(libxl__egc *egc,
         goto error_out;
     }
 
+    if (!strcmp(d_config->b_info.vuart, "pl011"))
+        state->vuart_enabled = true;
+    else
+        state->vuart_enabled = false;
+
     if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM &&
         (libxl_defbool_val(d_config->b_info.u.hvm.nested_hvm) &&
         (libxl_defbool_val(d_config->b_info.u.hvm.altp2m) ||
@@ -918,6 +926,8 @@ static void initiate_domain_create(libxl__egc *egc,
         goto error_out;
     }
 
+    state->config.console_domid = state->console_domid;
+
     ret = libxl__domain_make(gc, d_config, &domid, &state->config);
     if (ret) {
         LOGD(ERROR, domid, "cannot make domain: %d", ret);
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 5d082c5..9dba8e7 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1135,6 +1135,10 @@ typedef struct {
     uint32_t num_vmemranges;
 
     xc_domain_configuration_t config;
+
+    unsigned long vuart_mfn;
+    uint32_t    vuart_port;
+    bool        vuart_enabled;
 } libxl__domain_build_state;
 
 _hidden int libxl__build_pre(libxl__gc *gc, uint32_t domid,
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 2204425..5d53f2c 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -105,6 +105,7 @@ libxl_console_type = Enumeration("console_type", [
     (0, "UNKNOWN"),
     (1, "SERIAL"),
     (2, "PV"),
+    (3, "VUART"),
     ])
 
 libxl_disk_format = Enumeration("disk_format", [
@@ -470,6 +471,7 @@ libxl_domain_build_info = Struct("domain_build_info",[
     ("disable_migrate", libxl_defbool),
     ("cpuid",           libxl_cpuid_policy_list),
     ("blkdev_start",    string),
+    ("vuart",           string),
 
     ("vnuma_nodes", Array(libxl_vnode_info, "num_vnuma_nodes")),
     
diff --git a/tools/xl/xl_console.c b/tools/xl/xl_console.c
index 0508dda..6f3cd7f 100644
--- a/tools/xl/xl_console.c
+++ b/tools/xl/xl_console.c
@@ -34,8 +34,10 @@ int main_console(int argc, char **argv)
             type = LIBXL_CONSOLE_TYPE_PV;
         else if (!strcmp(optarg, "serial"))
             type = LIBXL_CONSOLE_TYPE_SERIAL;
+        else if (!strcmp(optarg, "vuart"))
+            type = LIBXL_CONSOLE_TYPE_VUART;
         else {
-            fprintf(stderr, "console type supported are: pv, serial\n");
+            fprintf(stderr, "console type supported are: pv, serial, vuart\n");
             return EXIT_FAILURE;
         }
         break;
diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
index 856a304..80fd184 100644
--- a/tools/xl/xl_parse.c
+++ b/tools/xl/xl_parse.c
@@ -916,6 +916,9 @@ void parse_config_data(const char *config_source,
     if (!xlu_cfg_get_long (config, "maxvcpus", &l, 0))
         b_info->max_vcpus = l;
 
+    if (xlu_cfg_replace_string(config, "vuart", &b_info->vuart, 0))
+        b_info->vuart = strdup("unknown");
+
     parse_vnuma_config(config, b_info);
 
     /* Set max_memkb to target_memkb and max_vcpus to avail_vcpus if
-- 
2.7.4


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

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

* [PATCH 05/10 v2] xen/arm: vpl011: Allocate a new PFN in the toolstack for vuart
  2017-04-28 16:01 [PATCH 00/10 v2] pl011 emulation support in Xen Bhupinder Thakur
                   ` (3 preceding siblings ...)
  2017-04-28 16:01 ` [PATCH 04/10 v2] xen/arm: vpl011: Add support for vuart in libxl Bhupinder Thakur
@ 2017-04-28 16:01 ` Bhupinder Thakur
  2017-04-28 21:48   ` Stefano Stabellini
  2017-04-28 16:01 ` [PATCH 06/10 v2] xen/arm: vpl011: Add vuart ring-buf and evtchn to xenstore Bhupinder Thakur
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 54+ messages in thread
From: Bhupinder Thakur @ 2017-04-28 16:01 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich

Allocate a new pfn and pass on to Xen using a domctl call.

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

Changes since v1:
- Replaced the hvm call with the domctl call to set the pfn.

 tools/libxc/include/xc_dom.h | 2 ++
 tools/libxc/xc_dom_arm.c     | 7 ++++++-
 tools/libxc/xc_dom_boot.c    | 2 ++
 3 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/tools/libxc/include/xc_dom.h b/tools/libxc/include/xc_dom.h
index ce47058..ca8bc23 100644
--- a/tools/libxc/include/xc_dom.h
+++ b/tools/libxc/include/xc_dom.h
@@ -216,6 +216,8 @@ struct xc_dom_image {
 
     /* Extra SMBIOS structures passed to HVMLOADER */
     struct xc_hvm_firmware_module smbios_module;
+
+    xen_pfn_t vuart_pfn;
 };
 
 /* --- pluggable kernel loader ------------------------------------- */
diff --git a/tools/libxc/xc_dom_arm.c b/tools/libxc/xc_dom_arm.c
index e7d4bd0..ad805d1 100644
--- a/tools/libxc/xc_dom_arm.c
+++ b/tools/libxc/xc_dom_arm.c
@@ -26,10 +26,11 @@
 #include "xg_private.h"
 #include "xc_dom.h"
 
-#define NR_MAGIC_PAGES 3
+#define NR_MAGIC_PAGES 4
 #define CONSOLE_PFN_OFFSET 0
 #define XENSTORE_PFN_OFFSET 1
 #define MEMACCESS_PFN_OFFSET 2
+#define VUART_PFN_OFFSET 3
 
 #define LPAE_SHIFT 9
 
@@ -85,16 +86,20 @@ static int alloc_magic_pages(struct xc_dom_image *dom)
 
     dom->console_pfn = base + CONSOLE_PFN_OFFSET;
     dom->xenstore_pfn = base + XENSTORE_PFN_OFFSET;
+    dom->vuart_pfn = base + VUART_PFN_OFFSET;
 
     xc_clear_domain_page(dom->xch, dom->guest_domid, dom->console_pfn);
     xc_clear_domain_page(dom->xch, dom->guest_domid, dom->xenstore_pfn);
     xc_clear_domain_page(dom->xch, dom->guest_domid, base + MEMACCESS_PFN_OFFSET);
+    xc_clear_domain_page(dom->xch, dom->guest_domid, base + VUART_PFN_OFFSET);
     xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_PFN,
             dom->console_pfn);
     xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_STORE_PFN,
             dom->xenstore_pfn);
     xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_MONITOR_RING_PFN,
             base + MEMACCESS_PFN_OFFSET);
+    xc_domain_vuart_set_pfn(dom->xch, dom->guest_domid, base + VUART_PFN_OFFSET);
+
     /* allocated by toolstack */
     xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_EVTCHN,
             dom->console_evtchn);
diff --git a/tools/libxc/xc_dom_boot.c b/tools/libxc/xc_dom_boot.c
index c3b44dd..5e4b322 100644
--- a/tools/libxc/xc_dom_boot.c
+++ b/tools/libxc/xc_dom_boot.c
@@ -226,6 +226,8 @@ int xc_dom_boot_image(struct xc_dom_image *dom)
         return rc;
     if ( (rc = clear_page(dom, dom->xenstore_pfn)) != 0 )
         return rc;
+    if ( (rc = clear_page(dom, dom->vuart_pfn)) != 0 )
+        return rc;
 
     /* start info page */
     if ( dom->arch_hooks->start_info )
-- 
2.7.4


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

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

* [PATCH 06/10 v2] xen/arm: vpl011: Add vuart ring-buf and evtchn to xenstore
  2017-04-28 16:01 [PATCH 00/10 v2] pl011 emulation support in Xen Bhupinder Thakur
                   ` (4 preceding siblings ...)
  2017-04-28 16:01 ` [PATCH 05/10 v2] xen/arm: vpl011: Allocate a new PFN in the toolstack for vuart Bhupinder Thakur
@ 2017-04-28 16:01 ` Bhupinder Thakur
  2017-04-28 21:57   ` Stefano Stabellini
  2017-04-28 16:01 ` [PATCH 07/10 v2] xen/arm: vpl011: Add support for vuart in xenconsole Bhupinder Thakur
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 54+ messages in thread
From: Bhupinder Thakur @ 2017-04-28 16:01 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich

Add two new parameters to the xen store to be used by xenconsoled:
    - newly allocated PFN to be used as IN/OUT ring buffer
    - get a new event channel allocated by Xen using a domctl call

These paramters are added to xenstore only if vuart console is enabled
by the user.

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

Changes since v1:
- Modified the xenstore key names to /vuart/0/ring-ref and 
  /vuart/0/port.
- Replaced the hvm call with domctl call to get the event channel.

 tools/libxl/libxl_console.c | 10 ++++++++++
 tools/libxl/libxl_dom.c     |  4 ++++
 2 files changed, 14 insertions(+)

diff --git a/tools/libxl/libxl_console.c b/tools/libxl/libxl_console.c
index 446e766..ef3bd44 100644
--- a/tools/libxl/libxl_console.c
+++ b/tools/libxl/libxl_console.c
@@ -67,6 +67,9 @@ int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num,
     case LIBXL_CONSOLE_TYPE_SERIAL:
         cons_type_s = "serial";
         break;
+    case LIBXL_CONSOLE_TYPE_VUART:
+        cons_type_s = "vuart";
+        break;
     default:
         goto out;
     }
@@ -326,6 +329,13 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
         flexarray_append(ro_front, GCSPRINTF("%"PRIu32, state->console_port));
         flexarray_append(ro_front, "ring-ref");
         flexarray_append(ro_front, GCSPRINTF("%lu", state->console_mfn));
+        if (state->vuart_enabled)
+        {
+            flexarray_append(ro_front, "vuart/0/port");
+            flexarray_append(ro_front, GCSPRINTF("%"PRIu32, state->vuart_port));
+            flexarray_append(ro_front, "vuart/0/ring-ref");
+            flexarray_append(ro_front, GCSPRINTF("%lu", state->vuart_mfn));
+        }
     } else {
         flexarray_append(front, "state");
         flexarray_append(front, GCSPRINTF("%d", XenbusStateInitialising));
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 5d914a5..06ff3b7 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -434,6 +434,9 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
     state->store_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->store_domid);
     state->console_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->console_domid);
 
+    if (state->vuart_enabled)
+        xc_domain_vuart_get_evtchn(ctx->xch, domid, &state->vuart_port);
+
     if (info->type == LIBXL_DOMAIN_TYPE_HVM) {
         hvm_set_conf_params(ctx->xch, domid, info);
 #if defined(__i386__) || defined(__x86_64__)
@@ -788,6 +791,7 @@ int libxl__build_pv(libxl__gc *gc, uint32_t domid,
     if (xc_dom_translated(dom)) {
         state->console_mfn = dom->console_pfn;
         state->store_mfn = dom->xenstore_pfn;
+        state->vuart_mfn = dom->vuart_pfn;
     } else {
         state->console_mfn = xc_dom_p2m(dom, dom->console_pfn);
         state->store_mfn = xc_dom_p2m(dom, dom->xenstore_pfn);
-- 
2.7.4


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

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

* [PATCH 07/10 v2] xen/arm: vpl011: Add support for vuart in xenconsole
  2017-04-28 16:01 [PATCH 00/10 v2] pl011 emulation support in Xen Bhupinder Thakur
                   ` (5 preceding siblings ...)
  2017-04-28 16:01 ` [PATCH 06/10 v2] xen/arm: vpl011: Add vuart ring-buf and evtchn to xenstore Bhupinder Thakur
@ 2017-04-28 16:01 ` Bhupinder Thakur
  2017-04-28 23:10   ` Stefano Stabellini
  2017-04-28 16:01 ` [PATCH 08/10 v2] xen/arm: vpl011: Add a new vuart console type to xenconsole client Bhupinder Thakur
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 54+ messages in thread
From: Bhupinder Thakur @ 2017-04-28 16:01 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich

Xenconsole supports only PV console currently. This patch adds support
for vuart, which allows emulated pl011 uart to be accessed as a console.

This patch modifies different data structures and APIs used
in xenconsole to support two console types: PV and VUART.

Change summary:

1. Split the domain structure into a console structure and the
   domain structure. Each PV and VUART will have seprate console
   structures.

2. Modify different APIs such as buffer_append() etc. to take
   console structure as input and perform per console specific
   operations.

3. Modfications in domain_create_ring():
    - Bind to the vpl011 event channel obtained from the xen store as a
      new parameter.
    - Map the PFN to its address space to be used as IN/OUT ring
      buffers.
      It obtains the PFN from the xen store as a new parameter

4. Modifications in handle_ring_read() to handle both PV and VUART
   events.

5. Add a new log_file for VUART console logs.

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

Changes since v1:

- Split the domain struture to a separate console structure
- Modified the functions to operate on the console struture
- Replaced repetitive per console code with generic code

 tools/console/daemon/io.c | 514 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 365 insertions(+), 149 deletions(-)

diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index 7e6a886..55fda37 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -61,6 +61,10 @@
 /* Duration of each time period in ms */
 #define RATE_LIMIT_PERIOD 200
 
+#define MAX_CONSOLE 2
+#define CONSOLE_TYPE_PV 0
+#define CONSOLE_TYPE_VUART 1
+
 extern int log_reload;
 extern int log_guest;
 extern int log_hv;
@@ -89,29 +93,75 @@ struct buffer {
 	size_t max_capacity;
 };
 
-struct domain {
-	int domid;
+struct console {
+	char *name;
+	char *ttyname;
 	int master_fd;
 	int master_pollfd_idx;
 	int slave_fd;
 	int log_fd;
-	bool is_dead;
-	unsigned last_seen;
 	struct buffer buffer;
-	struct domain *next;
-	char *conspath;
 	int ring_ref;
 	xenevtchn_port_or_error_t local_port;
 	xenevtchn_port_or_error_t remote_port;
+	struct xencons_interface *interface;
+	struct domain *d;  /* Reference to the domain it is contained in. */
+};
+
+struct domain {
+	int domid;
+	bool is_dead;
+	unsigned last_seen;
+	struct domain *next;
+	char *conspath;
 	xenevtchn_handle *xce_handle;
 	int xce_pollfd_idx;
-	struct xencons_interface *interface;
 	int event_count;
 	long long next_period;
+	struct console console[MAX_CONSOLE];
 };
 
 static struct domain *dom_head;
 
+static inline bool console_enabled(struct console *con) { return con->local_port != -1; }
+
+static inline void console_iter_no_check(struct domain *d, void (* iter_func)(struct console *))
+{
+	int i = 0;
+	struct console *con = &(d->console[0]);
+
+	for (i=0; i < MAX_CONSOLE; i++, con++)
+	{
+		iter_func(con);
+	}
+}
+
+static inline bool console_iter_bool_check(struct domain *d, bool (* iter_func)(struct console *))
+{
+	int i = 0;
+	struct console *con = &(d->console[0]);
+
+	for (i=0; i < MAX_CONSOLE; i++, con++)
+	{
+		if (iter_func(con))
+			return true;
+	}
+	return false;
+}
+
+static inline int console_iter_err_check(struct domain *d, int (* iter_func)(struct console *))
+{
+	int i = 0;
+	struct console *con = &(d->console[0]);
+
+	for (i=0; i < MAX_CONSOLE; i++, con++)
+	{
+		if (!iter_func(con))
+			return 0;
+	}
+	return 1;
+}
+
 static int write_all(int fd, const char* buf, size_t len)
 {
 	while (len) {
@@ -158,11 +208,24 @@ static int write_with_timestamp(int fd, const char *data, size_t sz,
 	return 0;
 }
 
-static void buffer_append(struct domain *dom)
+static inline bool buffer_available(struct console *con)
+{
+	if (discard_overflowed_data ||
+		!con->buffer.max_capacity ||
+		con->buffer.size < con->buffer.max_capacity)
+		return true;
+	else
+		return false;
+}
+
+static void buffer_append(struct console *con)
 {
-	struct buffer *buffer = &dom->buffer;
+	struct buffer *buffer = &con->buffer;
+	struct xencons_interface *intf = con->interface;
+	xenevtchn_port_or_error_t port = con->local_port;
+	struct domain *dom = con->d;
+
 	XENCONS_RING_IDX cons, prod, size;
-	struct xencons_interface *intf = dom->interface;
 
 	cons = intf->out_cons;
 	prod = intf->out_prod;
@@ -187,22 +250,22 @@ static void buffer_append(struct domain *dom)
 
 	xen_mb();
 	intf->out_cons = cons;
-	xenevtchn_notify(dom->xce_handle, dom->local_port);
+	xenevtchn_notify(dom->xce_handle, port);
 
 	/* Get the data to the logfile as early as possible because if
 	 * no one is listening on the console pty then it will fill up
 	 * and handle_tty_write will stop being called.
 	 */
-	if (dom->log_fd != -1) {
+	if (con->log_fd != -1) {
 		int logret;
 		if (log_time_guest) {
 			logret = write_with_timestamp(
-				dom->log_fd,
+				con->log_fd,
 				buffer->data + buffer->size - size,
 				size, &log_time_guest_needts);
 		} else {
 			logret = write_all(
-				dom->log_fd,
+				con->log_fd,
 				buffer->data + buffer->size - size,
 				size);
 		}
@@ -290,12 +353,13 @@ static int create_hv_log(void)
 	return fd;
 }
 
-static int create_domain_log(struct domain *dom)
+static int create_console_log(struct console *con)
 {
 	char logfile[PATH_MAX];
 	char *namepath, *data, *s;
 	int fd;
 	unsigned int len;
+	struct domain *dom = con->d;
 
 	namepath = xs_get_domain_path(xs, dom->domid);
 	s = realloc(namepath, strlen(namepath) + 6);
@@ -314,7 +378,8 @@ static int create_domain_log(struct domain *dom)
 		return -1;
 	}
 
-	snprintf(logfile, PATH_MAX-1, "%s/guest-%s.log", log_dir, data);
+	snprintf(logfile, PATH_MAX-1, "%s/guest-%s-%s.log",
+			 log_dir, con->name, data);
 	free(data);
 	logfile[PATH_MAX-1] = '\0';
 
@@ -336,19 +401,24 @@ static int create_domain_log(struct domain *dom)
 	return fd;
 }
 
-static void domain_close_tty(struct domain *dom)
+static void console_close_tty(struct console *con)
 {
-	if (dom->master_fd != -1) {
-		close(dom->master_fd);
-		dom->master_fd = -1;
+	if (con->master_fd != -1) {
+		close(con->master_fd);
+		con->master_fd = -1;
 	}
 
-	if (dom->slave_fd != -1) {
-		close(dom->slave_fd);
-		dom->slave_fd = -1;
+	if (con->slave_fd != -1) {
+		close(con->slave_fd);
+		con->slave_fd = -1;
 	}
 }
 
+static void domain_close_tty(struct domain *dom)
+{
+	console_iter_no_check(dom, console_close_tty);
+}
+
 #ifdef __sun__
 static int openpty(int *amaster, int *aslave, char *name,
 		   struct termios *termp, struct winsize *winp)
@@ -409,7 +479,7 @@ void cfmakeraw(struct termios *termios_p)
 }
 #endif /* __sun__ */
 
-static int domain_create_tty(struct domain *dom)
+static int console_create_tty(struct console *con)
 {
 	const char *slave;
 	char *path;
@@ -418,19 +488,23 @@ static int domain_create_tty(struct domain *dom)
 	char *data;
 	unsigned int len;
 	struct termios term;
+	struct domain *dom = con->d;
+
+	if (!console_enabled(con))
+		return 1;
 
-	assert(dom->slave_fd == -1);
-	assert(dom->master_fd == -1);
+	assert(con->master_fd == -1);
+	assert(con->slave_fd == -1);
 
-	if (openpty(&dom->master_fd, &dom->slave_fd, NULL, NULL, NULL) < 0) {
+	if (openpty(&con->master_fd, &con->slave_fd, NULL, NULL, NULL) < 0) {
 		err = errno;
 		dolog(LOG_ERR, "Failed to create tty for domain-%d "
-		      "(errno = %i, %s)",
-		      dom->domid, err, strerror(err));
-		return 0;
+			  "(errno = %i, %s)",
+			  dom->domid, err, strerror(err));
+		goto out;
 	}
 
-	if (tcgetattr(dom->slave_fd, &term) < 0) {
+	if (tcgetattr(con->slave_fd, &term) < 0) {
 		err = errno;
 		dolog(LOG_ERR, "Failed to get tty attributes for domain-%d "
 			"(errno = %i, %s)",
@@ -438,7 +512,7 @@ static int domain_create_tty(struct domain *dom)
 		goto out;
 	}
 	cfmakeraw(&term);
-	if (tcsetattr(dom->slave_fd, TCSANOW, &term) < 0) {
+	if (tcsetattr(con->slave_fd, TCSANOW, &term) < 0) {
 		err = errno;
 		dolog(LOG_ERR, "Failed to set tty attributes for domain-%d "
 			"(errno = %i, %s)",
@@ -446,11 +520,11 @@ static int domain_create_tty(struct domain *dom)
 		goto out;
 	}
 
-	if ((slave = ptsname(dom->master_fd)) == NULL) {
+	if ((slave = ptsname(con->master_fd)) == NULL) {
 		err = errno;
 		dolog(LOG_ERR, "Failed to get slave name for domain-%d "
-		      "(errno = %i, %s)",
-		      dom->domid, err, strerror(err));
+			  "(errno = %i, %s)",
+			  dom->domid, err, strerror(err));
 		goto out;
 	}
 
@@ -460,27 +534,41 @@ static int domain_create_tty(struct domain *dom)
 		goto out;
 	data = xs_read(xs, XBT_NULL, path, &len);
 	if (data) {
-		dom->buffer.max_capacity = strtoul(data, 0, 0);
+		con->buffer.max_capacity = strtoul(data, 0, 0);
 		free(data);
 	}
 	free(path);
 
-	success = (asprintf(&path, "%s/tty", dom->conspath) != -1);
+	success = (asprintf(&path, "%s/%s", dom->conspath, con->ttyname) != -1);
+
 	if (!success)
 		goto out;
 	success = xs_write(xs, XBT_NULL, path, slave, strlen(slave));
 	free(path);
-	if (!success)
+
+	if (fcntl(con->master_fd, F_SETFL, O_NONBLOCK) == -1)
 		goto out;
 
-	if (fcntl(dom->master_fd, F_SETFL, O_NONBLOCK) == -1)
+	if (!success)
 		goto out;
 
 	return 1;
+
 out:
-	domain_close_tty(dom);
 	return 0;
 }
+
+static int domain_create_tty(struct domain *dom)
+{
+	int ret;
+
+	ret = console_iter_err_check(dom, console_create_tty);
+
+	if (!ret)
+		domain_close_tty(dom);
+
+	return ret;
+}
  
 /* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
 static int xs_gather(struct xs_handle *xs, const char *dir, ...)
@@ -517,22 +605,64 @@ static int xs_gather(struct xs_handle *xs, const char *dir, ...)
 	return ret;
 }
 
-static void domain_unmap_interface(struct domain *dom)
+static void console_unmap_interface(struct console *con)
 {
-	if (dom->interface == NULL)
+	if (con->interface == NULL)
 		return;
-	if (xgt_handle && dom->ring_ref == -1)
-		xengnttab_unmap(xgt_handle, dom->interface, 1);
+	if (xgt_handle && con->ring_ref == -1)
+		xengnttab_unmap(xgt_handle, con->interface, 1);
 	else
-		munmap(dom->interface, XC_PAGE_SIZE);
-	dom->interface = NULL;
-	dom->ring_ref = -1;
+		munmap(con->interface, XC_PAGE_SIZE);
+	con->interface = NULL;
+	con->ring_ref = -1;
+}
+
+static void domain_unmap_interface(struct domain *dom)
+{
+	console_iter_no_check(dom, console_unmap_interface);
+}
+
+static int bind_event_channel(struct domain *dom,
+							  int new_rport,
+							  int *lport,
+							  int *rport)
+{
+	int err = 0, rc;
+
+	/* Go no further if port has not changed and we are still bound. */
+	if (new_rport == *rport) {
+		xc_evtchn_status_t status = {
+		.dom = DOMID_SELF,
+		.port = *lport };
+		if ((xc_evtchn_status(xc, &status) == 0) &&
+			(status.status == EVTCHNSTAT_interdomain))
+			goto out;
+	}
+
+	*lport = -1;
+	*rport = -1;
+	rc = xenevtchn_bind_interdomain(dom->xce_handle,
+									dom->domid, new_rport);
+
+	if (rc == -1) {
+		err = errno;
+		xenevtchn_close(dom->xce_handle);
+		dom->xce_handle = NULL;
+		goto out;
+	}
+
+	*lport = rc;
+	*rport = new_rport;
+out:
+	return err;
 }
  
 static int domain_create_ring(struct domain *dom)
 {
-	int err, remote_port, ring_ref, rc;
+	int err, remote_port, ring_ref, vuart_remote_port, vuart_ring_ref;
 	char *type, path[PATH_MAX];
+	struct console *pv_con = &dom->console[CONSOLE_TYPE_PV];
+	struct console *vuart_con = &dom->console[CONSOLE_TYPE_VUART];
 
 	err = xs_gather(xs, dom->conspath,
 			"ring-ref", "%u", &ring_ref,
@@ -541,6 +671,17 @@ static int domain_create_ring(struct domain *dom)
 	if (err)
 		goto out;
 
+	/* vuart is optional. */
+	err = xs_gather(xs, dom->conspath,
+					"vuart/0/ring-ref", "%u", &vuart_ring_ref,
+					"vuart/0/port", "%i", &vuart_remote_port,
+					NULL);
+	if (err)
+	{
+		vuart_remote_port = -1;
+		vuart_ring_ref = -1;
+	}
+
 	snprintf(path, sizeof(path), "%s/type", dom->conspath);
 	type = xs_read(xs, XBT_NULL, path, NULL);
 	if (type && strcmp(type, "xenconsoled") != 0) {
@@ -550,41 +691,50 @@ static int domain_create_ring(struct domain *dom)
 	free(type);
 
 	/* If using ring_ref and it has changed, remap */
-	if (ring_ref != dom->ring_ref && dom->ring_ref != -1)
-		domain_unmap_interface(dom);
+	if (ring_ref != pv_con->ring_ref && pv_con->ring_ref != -1)
+		console_unmap_interface(pv_con);
 
-	if (!dom->interface && xgt_handle) {
+	/* If using vuart ring_ref and it has changed, remap */
+	if (vuart_ring_ref != vuart_con->ring_ref &&
+		vuart_con->ring_ref != -1 )
+		console_unmap_interface(vuart_con);
+
+	if (!pv_con->interface && xgt_handle) {
 		/* Prefer using grant table */
-		dom->interface = xengnttab_map_grant_ref(xgt_handle,
-			dom->domid, GNTTAB_RESERVED_CONSOLE,
-			PROT_READ|PROT_WRITE);
-		dom->ring_ref = -1;
+		pv_con->interface = xengnttab_map_grant_ref(xgt_handle,
+													dom->domid, GNTTAB_RESERVED_CONSOLE,
+													PROT_READ|PROT_WRITE);
+		pv_con->ring_ref = -1;
 	}
-	if (!dom->interface) {
+	if (!pv_con->interface) {
 		/* Fall back to xc_map_foreign_range */
-		dom->interface = xc_map_foreign_range(
+		pv_con->interface = xc_map_foreign_range(
 			xc, dom->domid, XC_PAGE_SIZE,
 			PROT_READ|PROT_WRITE,
 			(unsigned long)ring_ref);
-		if (dom->interface == NULL) {
+		if (pv_con->interface == NULL) {
 			err = EINVAL;
 			goto out;
 		}
-		dom->ring_ref = ring_ref;
+		pv_con->ring_ref = ring_ref;
 	}
 
-	/* Go no further if port has not changed and we are still bound. */
-	if (remote_port == dom->remote_port) {
-		xc_evtchn_status_t status = {
-			.dom = DOMID_SELF,
-			.port = dom->local_port };
-		if ((xc_evtchn_status(xc, &status) == 0) &&
-		    (status.status == EVTCHNSTAT_interdomain))
-			goto out;
+	/* Map vuart console ring buffer. */
+	if ((vuart_remote_port != -1) && !vuart_con->interface) {
+
+		vuart_con->interface = xc_map_foreign_range(xc,
+													dom->domid,
+													XC_PAGE_SIZE,
+													PROT_READ|PROT_WRITE,
+													(unsigned long)vuart_ring_ref);
+
+		if (vuart_con->interface == NULL) {
+			err = EINVAL;
+			goto out1;
+		}
+		vuart_con->ring_ref = vuart_ring_ref;
 	}
 
-	dom->local_port = -1;
-	dom->remote_port = -1;
 	if (dom->xce_handle != NULL)
 		xenevtchn_close(dom->xce_handle);
 
@@ -593,35 +743,55 @@ static int domain_create_ring(struct domain *dom)
 	dom->xce_handle = xenevtchn_open(NULL, 0);
 	if (dom->xce_handle == NULL) {
 		err = errno;
-		goto out;
+		goto out2;
 	}
  
-	rc = xenevtchn_bind_interdomain(dom->xce_handle,
-		dom->domid, remote_port);
-
-	if (rc == -1) {
-		err = errno;
+	err = bind_event_channel(dom, remote_port,
+							 &pv_con->local_port,
+							 &pv_con->remote_port);
+	if (err)
+	{
 		xenevtchn_close(dom->xce_handle);
-		dom->xce_handle = NULL;
-		goto out;
+		goto out2;
+	}
+
+	if (vuart_remote_port != -1)
+	{
+		err = bind_event_channel(dom, vuart_remote_port,
+								 &vuart_con->local_port,
+								 &vuart_con->remote_port);
+		if (err)
+		{
+			xenevtchn_close(dom->xce_handle);
+			goto out2;
+		}
 	}
-	dom->local_port = rc;
-	dom->remote_port = remote_port;
 
-	if (dom->master_fd == -1) {
+	if (pv_con->master_fd == -1) {
 		if (!domain_create_tty(dom)) {
 			err = errno;
 			xenevtchn_close(dom->xce_handle);
 			dom->xce_handle = NULL;
-			dom->local_port = -1;
-			dom->remote_port = -1;
-			goto out;
+			pv_con->local_port = -1;
+			pv_con->remote_port = -1;
+			vuart_con->local_port = -1;
+			vuart_con->remote_port = -1;
+			goto out2;
 		}
 	}
 
-	if (log_guest && (dom->log_fd == -1))
-		dom->log_fd = create_domain_log(dom);
+	if (log_guest && (pv_con->log_fd == -1))
+		pv_con->log_fd = create_console_log(pv_con);
+
+	if (log_guest && (vuart_remote_port != -1) && (vuart_con->log_fd == -1))
+		vuart_con->log_fd = create_console_log(vuart_con);
 
+	return err;
+
+ out2:
+	console_unmap_interface(vuart_con);
+ out1:
+	console_unmap_interface(pv_con);
  out:
 	return err;
 }
@@ -645,6 +815,19 @@ static bool watch_domain(struct domain *dom, bool watch)
 	return success;
 }
 
+static void console_init(struct domain *d, struct console *con, char *name, char *ttyname)
+{
+	con->master_fd = -1;
+	con->master_pollfd_idx = -1;
+	con->slave_fd = -1;
+	con->log_fd = -1;
+	con->ring_ref = -1;
+	con->local_port = -1;
+	con->remote_port = -1;
+	con->name = name;
+	con->ttyname = ttyname;
+	con->d = d;
+}
 
 static struct domain *create_domain(int domid)
 {
@@ -675,18 +858,13 @@ static struct domain *create_domain(int domid)
 	dom->conspath = s;
 	strcat(dom->conspath, "/console");
 
-	dom->master_fd = -1;
-	dom->master_pollfd_idx = -1;
-	dom->slave_fd = -1;
-	dom->log_fd = -1;
+	console_init(dom, &dom->console[CONSOLE_TYPE_PV], "pv", "tty");
+	console_init(dom, &dom->console[CONSOLE_TYPE_VUART], "vuart", "vtty");
+
 	dom->xce_pollfd_idx = -1;
 
 	dom->next_period = ((long long)ts.tv_sec * 1000) + (ts.tv_nsec / 1000000) + RATE_LIMIT_PERIOD;
 
-	dom->ring_ref = -1;
-	dom->local_port = -1;
-	dom->remote_port = -1;
-
 	if (!watch_domain(dom, true))
 		goto out;
 
@@ -727,17 +905,22 @@ static void remove_domain(struct domain *dom)
 	}
 }
 
+
+static void console_cleanup(struct console *con)
+{
+	if (con->log_fd != -1) {
+		close(con->log_fd);
+		con->log_fd = -1;
+	}
+	free(con->buffer.data);
+	con->buffer.data = NULL;
+}
+
 static void cleanup_domain(struct domain *d)
 {
 	domain_close_tty(d);
 
-	if (d->log_fd != -1) {
-		close(d->log_fd);
-		d->log_fd = -1;
-	}
-
-	free(d->buffer.data);
-	d->buffer.data = NULL;
+	console_iter_no_check(d, console_cleanup);
 
 	free(d->conspath);
 	d->conspath = NULL;
@@ -749,7 +932,9 @@ static void shutdown_domain(struct domain *d)
 {
 	d->is_dead = true;
 	watch_domain(d, false);
+
 	domain_unmap_interface(d);
+
 	if (d->xce_handle != NULL)
 		xenevtchn_close(d->xce_handle);
 	d->xce_handle = NULL;
@@ -780,9 +965,9 @@ static void enum_domains(void)
 	}
 }
 
-static int ring_free_bytes(struct domain *dom)
+static int ring_free_bytes(struct console *con)
 {
-	struct xencons_interface *intf = dom->interface;
+	struct xencons_interface *intf = con->interface;
 	XENCONS_RING_IDX cons, prod, space;
 
 	cons = intf->in_cons;
@@ -807,25 +992,27 @@ static void domain_handle_broken_tty(struct domain *dom, int recreate)
 	}
 }
 
-static void handle_tty_read(struct domain *dom)
+static void handle_tty_read(struct console *con)
 {
 	ssize_t len = 0;
 	char msg[80];
 	int i;
-	struct xencons_interface *intf = dom->interface;
 	XENCONS_RING_IDX prod;
+	struct xencons_interface *intf = con->interface;
+	xenevtchn_port_or_error_t port = con->local_port;
+	struct domain *dom = con->d;
 
 	if (dom->is_dead)
 		return;
 
-	len = ring_free_bytes(dom);
+	len = ring_free_bytes(con);
 	if (len == 0)
 		return;
 
 	if (len > sizeof(msg))
 		len = sizeof(msg);
 
-	len = read(dom->master_fd, msg, len);
+	len = read(con->master_fd, msg, len);
 	/*
 	 * Note: on Solaris, len == 0 means the slave closed, and this
 	 * is no problem, but Linux can't handle this usefully, so we
@@ -841,34 +1028,44 @@ static void handle_tty_read(struct domain *dom)
 		}
 		xen_wmb();
 		intf->in_prod = prod;
-		xenevtchn_notify(dom->xce_handle, dom->local_port);
+		xenevtchn_notify(dom->xce_handle, port);
 	} else {
 		domain_close_tty(dom);
 		shutdown_domain(dom);
 	}
 }
 
-static void handle_tty_write(struct domain *dom)
+static void handle_tty_write(struct console *con)
 {
 	ssize_t len;
+	struct domain *dom = con->d;
 
 	if (dom->is_dead)
 		return;
 
-	len = write(dom->master_fd, dom->buffer.data + dom->buffer.consumed,
-		    dom->buffer.size - dom->buffer.consumed);
+	len = write(con->master_fd,
+				con->buffer.data + con->buffer.consumed,
+				con->buffer.size - con->buffer.consumed);
  	if (len < 1) {
 		dolog(LOG_DEBUG, "Write failed on domain %d: %zd, %d\n",
 		      dom->domid, len, errno);
 		domain_handle_broken_tty(dom, domain_is_valid(dom->domid));
 	} else {
-		buffer_advance(&dom->buffer, len);
+		buffer_advance(&con->buffer, len);
 	}
 }
 
+static void console_event_unmask(struct console *con)
+{
+	if (con->local_port != -1)
+		(void)xenevtchn_unmask(con->d->xce_handle, con->local_port);
+}
+
 static void handle_ring_read(struct domain *dom)
 {
 	xenevtchn_port_or_error_t port;
+	struct console *pv_con = &dom->console[CONSOLE_TYPE_PV];
+	struct console *vuart_con = &dom->console[CONSOLE_TYPE_VUART];
 
 	if (dom->is_dead)
 		return;
@@ -878,10 +1075,13 @@ static void handle_ring_read(struct domain *dom)
 
 	dom->event_count++;
 
-	buffer_append(dom);
+	if (port == vuart_con->local_port)
+		buffer_append(vuart_con);
+	else
+		buffer_append(pv_con);
 
 	if (dom->event_count < RATE_LIMIT_ALLOWANCE)
-		(void)xenevtchn_unmask(dom->xce_handle, port);
+		console_iter_no_check(dom, console_event_unmask);
 }
 
 static void handle_xs(void)
@@ -943,14 +1143,22 @@ static void handle_hv_logs(xenevtchn_handle *xce_handle, bool force)
 		(void)xenevtchn_unmask(xce_handle, port);
 }
 
+static void console_open_log(struct console *con)
+{
+	if (console_enabled(con))
+	{
+		if (con->log_fd != -1)
+			close(con->log_fd);
+		con->log_fd = create_console_log(con);
+	}
+}
+
 static void handle_log_reload(void)
 {
 	if (log_guest) {
 		struct domain *d;
 		for (d = dom_head; d; d = d->next) {
-			if (d->log_fd != -1)
-				close(d->log_fd);
-			d->log_fd = create_domain_log(d);
+			console_iter_no_check(d, console_open_log);
 		}
 	}
 
@@ -1002,6 +1210,40 @@ static void reset_fds(void)
 		memset(fds, 0, sizeof(struct pollfd) * current_array_size);
 }
 
+static void add_console_fd(struct console *con)
+{
+	if (con->master_fd != -1) {
+		short events = 0;
+		if (!con->d->is_dead && ring_free_bytes(con))
+			events |= POLLIN;
+
+		if (!buffer_empty(&con->buffer))
+			events |= POLLOUT;
+
+		if (events)
+			con->master_pollfd_idx =
+				set_fds(con->master_fd, events|POLLPRI);
+	}
+}
+
+static void process_console(struct console *con)
+{
+	if (con->master_fd != -1 && con->master_pollfd_idx != -1) {
+		if (fds[con->master_pollfd_idx].revents &
+			~(POLLIN|POLLOUT|POLLPRI))
+			domain_handle_broken_tty(con->d, domain_is_valid(con->d->domid));
+		else {
+			if (fds[con->master_pollfd_idx].revents &
+				POLLIN)
+				handle_tty_read(con);
+			if (fds[con->master_pollfd_idx].revents &
+				POLLOUT)
+				handle_tty_write(con);
+		}
+	}
+	con->master_pollfd_idx = -1;
+}
+
 void handle_io(void)
 {
 	int ret;
@@ -1068,7 +1310,7 @@ void handle_io(void)
 			if ((now+5) > d->next_period) {
 				d->next_period = now + RATE_LIMIT_PERIOD;
 				if (d->event_count >= RATE_LIMIT_ALLOWANCE) {
-					(void)xenevtchn_unmask(d->xce_handle, d->local_port);
+					console_iter_no_check(d, console_event_unmask);
 				}
 				d->event_count = 0;
 			}
@@ -1081,28 +1323,15 @@ void handle_io(void)
 				    d->next_period < next_timeout)
 					next_timeout = d->next_period;
 			} else if (d->xce_handle != NULL) {
-				if (discard_overflowed_data ||
-				    !d->buffer.max_capacity ||
-				    d->buffer.size < d->buffer.max_capacity) {
+				if (console_iter_bool_check(d, buffer_available))
+				{
 					int evtchn_fd = xenevtchn_fd(d->xce_handle);
 					d->xce_pollfd_idx = set_fds(evtchn_fd,
-								    POLLIN|POLLPRI);
+												POLLIN|POLLPRI);
 				}
 			}
 
-			if (d->master_fd != -1) {
-				short events = 0;
-				if (!d->is_dead && ring_free_bytes(d))
-					events |= POLLIN;
-
-				if (!buffer_empty(&d->buffer))
-					events |= POLLOUT;
-
-				if (events)
-					d->master_pollfd_idx =
-						set_fds(d->master_fd,
-							events|POLLPRI);
-			}
+			console_iter_no_check(d, add_console_fd);
 		}
 
 		/* If any domain has been rate limited, we need to work
@@ -1170,22 +1399,9 @@ void handle_io(void)
 				    handle_ring_read(d);
 			}
 
-			if (d->master_fd != -1 && d->master_pollfd_idx != -1) {
-				if (fds[d->master_pollfd_idx].revents &
-				    ~(POLLIN|POLLOUT|POLLPRI))
-					domain_handle_broken_tty(d,
-						   domain_is_valid(d->domid));
-				else {
-					if (fds[d->master_pollfd_idx].revents &
-					    POLLIN)
-						handle_tty_read(d);
-					if (fds[d->master_pollfd_idx].revents &
-					    POLLOUT)
-						handle_tty_write(d);
-				}
-			}
+			console_iter_no_check(d, process_console);
 
-			d->xce_pollfd_idx = d->master_pollfd_idx = -1;
+			d->xce_pollfd_idx = -1;
 
 			if (d->last_seen != enum_pass)
 				shutdown_domain(d);
-- 
2.7.4


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

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

* [PATCH 08/10 v2] xen/arm: vpl011: Add a new vuart console type to xenconsole client
  2017-04-28 16:01 [PATCH 00/10 v2] pl011 emulation support in Xen Bhupinder Thakur
                   ` (6 preceding siblings ...)
  2017-04-28 16:01 ` [PATCH 07/10 v2] xen/arm: vpl011: Add support for vuart in xenconsole Bhupinder Thakur
@ 2017-04-28 16:01 ` Bhupinder Thakur
  2017-04-28 22:01   ` Stefano Stabellini
  2017-04-28 16:01 ` [PATCH 09/10 v2] xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree Bhupinder Thakur
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 54+ messages in thread
From: Bhupinder Thakur @ 2017-04-28 16:01 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich

Add a new console type VUART to connect to guest vuart.

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
---
 tools/console/client/main.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/tools/console/client/main.c b/tools/console/client/main.c
index 977779f..ec5c6e1 100644
--- a/tools/console/client/main.c
+++ b/tools/console/client/main.c
@@ -76,7 +76,7 @@ static void usage(const char *program) {
 	       "\n"
 	       "  -h, --help       display this help and exit\n"
 	       "  -n, --num N      use console number N\n"
-	       "  --type TYPE      console type. must be 'pv' or 'serial'\n"
+	       "  --type TYPE      console type. must be 'pv', 'serial' or 'vuart'\n"
 	       "  --start-notify-fd N file descriptor used to notify parent\n"
 	       , program);
 }
@@ -264,6 +264,7 @@ typedef enum {
        CONSOLE_INVAL,
        CONSOLE_PV,
        CONSOLE_SERIAL,
+       CONSOLE_VUART,
 } console_type;
 
 static struct termios stdin_old_attr;
@@ -361,6 +362,8 @@ int main(int argc, char **argv)
 				type = CONSOLE_SERIAL;
 			else if (!strcmp(optarg, "pv"))
 				type = CONSOLE_PV;
+			else if (!strcmp(optarg, "vuart"))
+				type = CONSOLE_VUART;
 			else {
 				fprintf(stderr, "Invalid type argument\n");
 				fprintf(stderr, "Console types supported are: serial, pv\n");
@@ -436,6 +439,9 @@ int main(int argc, char **argv)
 		else
 			snprintf(path, strlen(dom_path) + strlen("/device/console/%d/tty") + 5, "%s/device/console/%d/tty", dom_path, num);
 	}
+	if (type == CONSOLE_VUART) {
+		snprintf(path, strlen(dom_path) + strlen("/console/vtty") + 1, "%s/console/vtty", dom_path);
+	}
 
 	/* FIXME consoled currently does not assume domain-0 doesn't have a
 	   console which is good when we break domain-0 up.  To keep us
-- 
2.7.4


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

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

* [PATCH 09/10 v2] xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree
  2017-04-28 16:01 [PATCH 00/10 v2] pl011 emulation support in Xen Bhupinder Thakur
                   ` (7 preceding siblings ...)
  2017-04-28 16:01 ` [PATCH 08/10 v2] xen/arm: vpl011: Add a new vuart console type to xenconsole client Bhupinder Thakur
@ 2017-04-28 16:01 ` Bhupinder Thakur
  2017-05-03 10:38   ` Julien Grall
  2017-04-28 16:01 ` [PATCH 10/10 v2] xen/arm: vpl011: Update documentation for vuart console support Bhupinder Thakur
  2017-05-11 10:32 ` [PATCH 00/10 v2] pl011 emulation support in Xen Wei Liu
  10 siblings, 1 reply; 54+ messages in thread
From: Bhupinder Thakur @ 2017-04-28 16:01 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich

The SBSA uart node format is as specified in
Documentation/devicetree/bindings/serial/arm_sbsa_uart.txt and given below:

ARM SBSA defined generic UART
------------------------------
This UART uses a subset of the PL011 registers and consequently lives
in the PL011 driver. It's baudrate and other communication parameters
cannot be adjusted at runtime, so it lacks a clock specifier here.

Required properties:
- compatible: must be "arm,sbsa-uart"
- reg: exactly one register range
- interrupts: exactly one interrupt specifier
- current-speed: the (fixed) baud rate set by the firmware

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
---

Changes since v1:
- Modified the code to increment nr_spis based on the SPI value reserved for
  vpl011.
- Added a check to verify that physical irq assigment is not conflicting with
  vpl011 SPI.
- Fixed minor indentation issues.

 tools/libxl/libxl_arm.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 52 insertions(+), 2 deletions(-)

diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
index d842d88..45a56a8 100644
--- a/tools/libxl/libxl_arm.c
+++ b/tools/libxl/libxl_arm.c
@@ -43,11 +43,25 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
 {
     uint32_t nr_spis = 0;
     unsigned int i;
+    bool vpl011_enabled = !strcmp(d_config->b_info.vuart, "pl011");
+
+    /*
+     * If pl011 vuart is enabled then increment the nr_spis to allow allocation
+     * of SPI VIRQ for pl011.
+     */
+    if (vpl011_enabled)
+        nr_spis += (GUEST_VPL011_SPI - 32)+1;
 
     for (i = 0; i < d_config->b_info.num_irqs; i++) {
         uint32_t irq = d_config->b_info.irqs[i];
         uint32_t spi;
 
+        if (vpl011_enabled && irq == GUEST_VPL011_SPI)
+        {
+            LOG(ERROR, "Physical IRQ %d conflicting with pl011 SPI\n", irq);
+            return ERROR_FAIL;
+        }
+
         if (irq < 32)
             continue;
 
@@ -130,9 +144,10 @@ static struct arch_info {
     const char *guest_type;
     const char *timer_compat;
     const char *cpu_compat;
+    const char *uart_compat;
 } arch_info[] = {
-    {"xen-3.0-armv7l",  "arm,armv7-timer", "arm,cortex-a15" },
-    {"xen-3.0-aarch64", "arm,armv8-timer", "arm,armv8" },
+    {"xen-3.0-armv7l",  "arm,armv7-timer", "arm,cortex-a15", "arm,sbsa-uart" },
+    {"xen-3.0-aarch64", "arm,armv8-timer", "arm,armv8", "arm,sbsa-uart" },
 };
 
 /*
@@ -590,6 +605,38 @@ static int make_hypervisor_node(libxl__gc *gc, void *fdt,
     return 0;
 }
 
+static int make_vpl011_uart_node(libxl__gc *gc, void *fdt,
+                                 const struct arch_info *ainfo,
+                                 struct xc_dom_image *dom)
+{
+    int res;
+    gic_interrupt intr;
+
+    res = fdt_begin_node(fdt, "sbsa-pl011");
+    if (res) return res;
+
+    res = fdt_property_compat(gc, fdt, 1, ainfo->uart_compat);
+    if (res) return res;
+
+    res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
+                            1,
+                            GUEST_PL011_BASE, GUEST_PL011_SIZE);
+    if (res) return res;
+
+    set_interrupt(intr, GUEST_VPL011_SPI, 0xf, DT_IRQ_TYPE_LEVEL_HIGH);
+
+    res = fdt_property_interrupts(gc, fdt, &intr, 1);
+    if (res) return res;
+
+    /* Use a default baud rate of 115200. */
+    fdt_property_u32(fdt, "current-speed", 115200);
+
+    res = fdt_end_node(fdt);
+    if (res) return res;
+
+    return 0;
+}
+
 static const struct arch_info *get_arch_info(libxl__gc *gc,
                                              const struct xc_dom_image *dom)
 {
@@ -889,6 +936,9 @@ next_resize:
         FDT( make_timer_node(gc, fdt, ainfo, xc_config->clock_frequency) );
         FDT( make_hypervisor_node(gc, fdt, vers) );
 
+        if (!strcmp(info->vuart, "pl011"))
+            FDT( make_vpl011_uart_node(gc, fdt, ainfo, dom) );
+
         if (pfdt)
             FDT( copy_partial_fdt(gc, fdt, pfdt) );
 
-- 
2.7.4


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

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

* [PATCH 10/10 v2] xen/arm: vpl011: Update documentation for vuart console support
  2017-04-28 16:01 [PATCH 00/10 v2] pl011 emulation support in Xen Bhupinder Thakur
                   ` (8 preceding siblings ...)
  2017-04-28 16:01 ` [PATCH 09/10 v2] xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree Bhupinder Thakur
@ 2017-04-28 16:01 ` Bhupinder Thakur
  2017-04-28 22:06   ` Stefano Stabellini
  2017-05-11 10:32 ` [PATCH 00/10 v2] pl011 emulation support in Xen Wei Liu
  10 siblings, 1 reply; 54+ messages in thread
From: Bhupinder Thakur @ 2017-04-28 16:01 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich

1. Update documentation for vuart = "pl011" option added.
2. Update documentation about SPI irq reserved for vpl011.

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
---
 docs/man/xl.cfg.pod.5.in |  8 ++++++++
 docs/misc/console.txt    | 14 +++++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/docs/man/xl.cfg.pod.5.in b/docs/man/xl.cfg.pod.5.in
index 13167ff..44118a8 100644
--- a/docs/man/xl.cfg.pod.5.in
+++ b/docs/man/xl.cfg.pod.5.in
@@ -1085,6 +1085,14 @@ Allow a guest to access specific physical IRQs.
 It is recommended to use this option only for trusted VMs under
 administrator control.
 
+If vuart console is enabled then irq 32 is reserved for vuart. By default
+vuart console is disabled. If user specifies the following option in
+the guest config file then vuart console is enabled.
+
+vuart = "pl011"
+
+vuart console is currently enabled only for ARM64.
+
 =item B<max_event_channels=N>
 
 Limit the guest to using at most N event channels (PV interrupts).
diff --git a/docs/misc/console.txt b/docs/misc/console.txt
index 16da805..2455fc7 100644
--- a/docs/misc/console.txt
+++ b/docs/misc/console.txt
@@ -19,7 +19,19 @@ The first PV console path in xenstore remains:
 
 /local/domain/$DOMID/console
 
-the other PV consoles follow the conventional xenstore device path and
+The vuart console path in xenstore is defined as:
+
+/local/domain/$DOMID/console/vuart/0
+
+The vuart console provides access to pl011 UART on ARM64 systems. To
+enable vuart the following line has to be added the guest configuration
+file:
+
+vuart = "pl011"
+
+Also the console should be set to "ttyAMA0" instead of "hvc0".
+
+The other PV consoles follow the conventional xenstore device path and
 live in:
 
 /local/domain/$DOMID/device/console/$DEVID.
-- 
2.7.4


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

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

* Re: [PATCH 01/10 v2] xen/arm: vpl011: Add pl011 uart emulation in Xen
  2017-04-28 16:01 ` [PATCH 01/10 v2] xen/arm: vpl011: Add pl011 uart emulation " Bhupinder Thakur
@ 2017-04-28 19:08   ` Stefano Stabellini
  2017-05-02  7:34   ` Jan Beulich
  2017-05-02 16:02   ` Julien Grall
  2 siblings, 0 replies; 54+ messages in thread
From: Stefano Stabellini @ 2017-04-28 19:08 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich, xen-devel

On Fri, 28 Apr 2017, Bhupinder Thakur wrote:
> 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 v1:
> 
> - Removed the optimiztion related to sendiing events to xenconsole 
> - Use local variables as ring buffer indices while using the ring buffer
> 
>  xen/arch/arm/Kconfig             |   5 +
>  xen/arch/arm/Makefile            |   1 +
>  xen/arch/arm/vpl011.c            | 340 +++++++++++++++++++++++++++++++++++++++
>  xen/include/asm-arm/domain.h     |   3 +
>  xen/include/asm-arm/pl011-uart.h |   2 +
>  xen/include/public/arch-arm.h    |   8 +
>  xen/include/xen/vpl011.h         |  74 +++++++++
>  7 files changed, 433 insertions(+)
>  create mode 100644 xen/arch/arm/vpl011.c
>  create mode 100644 xen/include/xen/vpl011.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..51abade
> --- /dev/null
> +++ b/xen/arch/arm/vpl011.c
> @@ -0,0 +1,340 @@
> +/*
> + * 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/sched.h>
> +#include <xen/vpl011.h>
> +#include <public/io/console.h>
> +#include <asm-arm/pl011-uart.h>
> +
> +unsigned int vpl011_reg_mask[] = {0xff, 0xffff, 0xffffffff};
> +
> +static void vgic_inject_vpl011_spi(struct domain *d)
> +{
> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
> +
> +    if ( (vpl011->uartris & vpl011->uartimsc) )
> +        vgic_vcpu_inject_spi(d, GUEST_VPL011_SPI);
> +}
> +
> +static void vpl011_read_data(struct domain *d, uint8_t *data)
> +{
> +    unsigned long flags;
> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
> +    struct xencons_interface *intf = vpl011->ring_buf;
> +
> +    /*
> +     * Initialize the data so that even if there is no data in ring buffer
> +     * 0 is returned.
> +     */
> +    *data = 0;
> +
> +    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 ( !VPL011_IN_RING_EMPTY(intf) )
> +    {
> +        uint32_t in_cons = intf->in_cons;

Use XENCONS_RING_IDX for the indexes type everywhere in this file.


> +        *data = intf->in[MASK_XENCONS_IDX(in_cons, intf->in)];
> +        smp_mb();
> +        intf->in_cons = in_cons + 1;
> +    }
> +
> +    if ( VPL011_IN_RING_EMPTY(intf) )
> +    {
> +        vpl011->uartfr |= (RXFE);
> +        vpl011->uartris &= ~(RXI);
> +    }
> +    vpl011->uartfr &= ~(RXFF);
> +    VPL011_UNLOCK(d, flags);
> +
> +    notify_via_xen_event_channel(d, vpl011->evtchn);
> +}
> +
> +static void vpl011_write_data(struct domain *d, uint8_t data)
> +{
> +    unsigned long flags;
> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
> +    struct xencons_interface *intf = vpl011->ring_buf;
> +
> +    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 ( !VPL011_OUT_RING_FULL(intf) )
> +    {
> +        uint32_t out_prod = intf->out_prod;
> +        intf->out[MASK_XENCONS_IDX(out_prod, intf->out)] = data;
> +        smp_wmb();
> +        intf->out_prod = out_prod + 1;
> +    }
> +
> +    if ( VPL011_OUT_RING_FULL(intf) )
> +    {
> +        vpl011->uartfr |= (TXFF);
> +        vpl011->uartris &= ~(TXI);
> +    }
> +
> +    vpl011->uartfr |= (BUSY);
> +
> +    vpl011->uartfr &= ~(TXFE);
> +
> +    VPL011_UNLOCK(d, flags);
> +
> +    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)
> +{
> +    uint8_t ch;
> +    struct hsr_dabt dabt = info->dabt;
> +    int vpl011_reg = (int)(info->gpa - GUEST_PL011_BASE);
> +    struct vpl011_s *vpl011 = &v->domain->arch.vpl011;
> +
> +    switch ( vpl011_reg )
> +    {
> +    case DR:
> +        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
> +        vpl011_read_data(v->domain, &ch);
> +        *r = ch;
> +        break;
> +
> +    case RSR:
> +        if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;
> +
> +        /* It always returns 0 as there are no physical errors. */
> +        *r = 0;
> +        break;
> +
> +    case FR:
> +        if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;
> +        *r = (vpl011->uartfr & vpl011_reg_mask[dabt.size]);
> +        break;
> +
> +    case RIS:
> +        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
> +        *r = (vpl011->uartris & vpl011_reg_mask[dabt.size]);
> +        break;
> +
> +    case MIS:
> +        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
> +        *r = (vpl011->uartris &
> +                            vpl011->uartimsc & vpl011_reg_mask[dabt.size]);
> +        break;
> +
> +    case IMSC:
> +        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
> +        *r = (vpl011->uartimsc & vpl011_reg_mask[dabt.size]);
> +        break;
> +
> +    case ICR:
> +        if ( !VALID_W_SIZE(dabt.size) ) 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)
> +{
> +    uint8_t ch = ((struct uartdr_reg *)&r)->data;
> +    struct hsr_dabt dabt = info->dabt;
> +    int vpl011_reg = (int)(info->gpa - GUEST_PL011_BASE);
> +    struct vpl011_s *vpl011 = &v->domain->arch.vpl011;
> +
> +    switch ( vpl011_reg )
> +    {
> +    case DR:
> +
> +        if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;
> +        vpl011_write_data(v->domain, ch);
> +        break;
> +
> +    case RSR: /* Nothing to clear. */
> +        if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;
> +        break;
> +
> +    case FR:
> +        goto write_ignore;
> +    case RIS:
> +    case MIS:
> +        goto word_write_ignore;
> +
> +    case IMSC:
> +        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
> +        vpl011->uartimsc = (r & vpl011_reg_mask[dabt.size]);
> +        vgic_inject_vpl011_spi(v->domain);
> +        break;
> +
> +    case ICR:
> +        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
> +        vpl011->uartris &= ~(r & vpl011_reg_mask[dabt.size]);
> +        vgic_inject_vpl011_spi(v->domain);
> +        break;
> +
> +    default:
> +        gprintk(XENLOG_ERR, "vpl011: unhandled write r%d offset %#08x\n",
> +                               dabt.reg, vpl011_reg);
> +        return 0;
> +    }
> +
> +    return 1;
> +
> +write_ignore:
> +    if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;
> +    return 1;
> +
> +word_write_ignore:
> +    if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
> +    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,
> +};
> +
> +int vpl011_map_guest_page(struct domain *d, unsigned long pfn)
> +{
> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
> +
> +    /* Map the guest PFN to Xen address space. */
> +    return prepare_ring_for_helper(d,
> +                                   pfn,
> +                                   &vpl011->ring_page,
> +                                   &vpl011->ring_buf);
> +}
> +
> +static void vpl011_data_avail(struct domain *d)
> +{
> +    unsigned long flags;
> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
> +    struct xencons_interface *intf = vpl011->ring_buf;
> +    uint32_t in_ring_depth, out_ring_depth;
> +
> +    VPL011_LOCK(d, flags);
> +
> +    in_ring_depth = intf->in_prod - intf->in_cons;
> +    out_ring_depth = intf->out_prod - intf->out_cons;
> +
> +    /* Update the uart rx state if the buffer is not empty. */
> +    if ( in_ring_depth != 0 )
> +    {
> +        vpl011->uartfr &= ~(RXFE);
> +        if ( in_ring_depth == VPL011_RING_MAX_DEPTH(intf, in) )

I don't think you are using VPL011_RING_MAX_DEPTH correctly here: the
size of intf->in is 1024, while VPL011_RING_MAX_DEPTH returns 1023.
However the max size of in_ring_depth should actually be 1024. So this
should be:

  if ( in_ring_depth == sizeof(intf->in) )

But there is another problem: the indexes can wrap around UINT_MAX. If
intf->in_cons is UINT_MAX-1 and intf->in_prod is UINT_MAX+1 the checks
fail. Thus, I would calculate the amount of data on the ring masking the
indexes, see name##_mask and name##_queued in
xen/include/public/io/ring.h. name##_queued is what you need to
calculate the amount of data on the ring. The ring_size parameter is
because that macro can handle variable size rings, in the "in" case it
would always be 1024.

You could either DEFINE_XEN_FLEX_RING for the console, or only import
the two macros you need as static inlines functions in this file.


> +            vpl011->uartfr |= (RXFF);
> +        vpl011->uartris |= (RXI);
> +    }
> +
> +    /* Update the uart tx state if the buffer is not full. */
> +    if ( out_ring_depth != VPL011_RING_MAX_DEPTH(intf, out) )

Same point for out


> +    {
> +        vpl011->uartfr &= ~(TXFF);
> +        vpl011->uartris |= (TXI);
> +        if ( out_ring_depth == 0 )
> +        {
> +            vpl011->uartfr &= ~(BUSY);
> +            vpl011->uartfr |= (TXFE);
> +        }
> +    }
> +
> +    VPL011_UNLOCK(d, flags);
> +
> +    vgic_inject_vpl011_spi(d);
> +}
> +
> +
> +static void vpl011_notification(struct vcpu *v, unsigned int port)
> +{
> +    vpl011_data_avail(v->domain);
> +}
> +
> +int domain_vpl011_init(struct domain *d, struct xen_arch_domainconfig *config)
> +{
> +    int rc;
> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
> +
> +    rc = alloc_unbound_xen_event_channel(d, 0, config->console_domid,
> +                                         vpl011_notification);
> +    if (rc < 0)
> +    {
> +        return rc;
> +    }
> +
> +    vpl011->evtchn = rc;
> +    rc = vgic_reserve_virq(d, GUEST_VPL011_SPI);
> +    if ( !rc )
> +    {
> +        free_xen_event_channel(d, vpl011->evtchn);
> +        vpl011->evtchn = -1;
> +        return rc;
> +    }
> +    register_mmio_handler(d, &vpl011_mmio_handler, GUEST_PL011_BASE, GUEST_PL011_SIZE, NULL);

long line


> +    spin_lock_init(&vpl011->lock);
> +
> +    vpl011->initialized = true;
> +
> +    return 0;
> +}
> +
> +void domain_vpl011_deinit(struct domain *d)
> +{
> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
> +
> +    if ( vpl011->initialized )
> +    {
> +        free_xen_event_channel(d, vpl011->evtchn);
> +        destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
> +    }
> +    vpl011->initialized = false;
> +}
> diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
> index 6de8082..a0f8f89 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 <xen/vpl011.h>
>  
>  struct hvm_domain
>  {
> @@ -133,6 +134,8 @@ struct arch_domain
>      struct {
>          uint8_t privileged_call_enabled : 1;
>      } monitor;
> +
> +    struct vpl011_s vpl011;
>  }  __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/public/arch-arm.h b/xen/include/public/arch-arm.h
> index bd974fb..5f91207 100644
> --- a/xen/include/public/arch-arm.h
> +++ b/xen/include/public/arch-arm.h
> @@ -322,6 +322,8 @@ struct xen_arch_domainconfig {
>       *
>       */
>      uint32_t clock_frequency;
> +
> +    uint32_t console_domid;
>  };
>  #endif /* __XEN__ || __XEN_TOOLS__ */
>  
> @@ -410,6 +412,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 +450,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/xen/vpl011.h b/xen/include/xen/vpl011.h
> new file mode 100644
> index 0000000..57d61b4
> --- /dev/null
> +++ b/xen/include/xen/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_
> +
> +/* helper macros */
> +#define VPL011_RING_DEPTH(intf,dir) (((intf)->dir ## _prod - (intf)->dir ## _cons))
> +
> +#define VPL011_RING_MAX_DEPTH(intf,dir) (sizeof((intf)->dir)-1)
> +
> +#define VPL011_IN_RING_EMPTY(intf) (VPL011_RING_DEPTH(intf, in) == 0)
> +
> +#define VPL011_OUT_RING_EMPTY(intf) (VPL011_RING_DEPTH(intf, out) == 0)
> +
> +#define VPL011_IN_RING_FULL(intf) (VPL011_RING_DEPTH(intf, in) == VPL011_RING_MAX_DEPTH(intf, in))
> +
> +#define VPL011_OUT_RING_FULL(intf) (VPL011_RING_DEPTH(intf, out) == VPL011_RING_MAX_DEPTH(intf,out))
> +
> +#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)
> +
> +#define VALID_BW_SIZE(size) ( size == DABT_BYTE || size == DABT_HALF_WORD || size == DABT_WORD )
> +#define VALID_W_SIZE(size)  ( size == DABT_HALF_WORD || size == DABT_WORD )
> +
> +struct uartdr_reg {
> +    uint8_t data;
> +    uint8_t error_status:4;
> +    uint8_t reserved1:4;
> +    uint16_t reserved2;
> +    uint32_t reserved3;
> +};
> +
> +struct vpl011_s {
> +    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;
> +    bool        initialized; /* Flag which tells whether vpl011 is initialized */
> +    uint32_t    evtchn;
> +};
> +
> +#ifdef CONFIG_VPL011_CONSOLE
> +int domain_vpl011_init(struct domain *d, struct xen_arch_domainconfig *config);
> +void domain_vpl011_deinit(struct domain *d);
> +int vpl011_map_guest_page(struct domain *d, unsigned long pfn);
> +#else
> +static inline int domain_vpl011_init(struct domain *d, struct xen_arch_domainconfig *config) { return -ENOSYS; }
> +static inline void domain_vpl011_deinit(struct domain *d) { }
> +static inline int vpl011_map_guest_page(struct domain *d, unsigned long pfn) { return -ENOSYS; }
> +#endif
> +
> +#endif
> -- 
> 2.7.4
> 

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

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

* Re: [PATCH 03/10 v2] xen/arm: vpl011: Enable pl011 emulation for a guest domain in Xen
  2017-04-28 16:01 ` [PATCH 03/10 v2] xen/arm: vpl011: Enable pl011 emulation for a guest domain in Xen Bhupinder Thakur
@ 2017-04-28 19:15   ` Stefano Stabellini
  2017-05-02  7:48   ` Jan Beulich
  1 sibling, 0 replies; 54+ messages in thread
From: Stefano Stabellini @ 2017-04-28 19:15 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich, xen-devel

On Fri, 28 Apr 2017, Bhupinder Thakur wrote:
> Vpl011 emulation is enabled for a guest domain in Xen only when it is
> enabled through an option in libxl provided by the user through
> guest configuration.
> 
> The pl011 enable/disable knob in libxl is introduced in the following
> patch:
> 
> xen/arm: vpl011: Add support for vuart in libxl
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
> ---
>  xen/arch/arm/domain.c       | 6 ++++++
>  xen/common/domctl.c         | 3 +++
>  xen/include/public/domctl.h | 2 ++
>  xen/include/xen/sched.h     | 4 ++++
>  4 files changed, 15 insertions(+)
> 
> diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
> index 76310ed..23baa81 100644
> --- a/xen/arch/arm/domain.c
> +++ b/xen/arch/arm/domain.c
> @@ -36,6 +36,7 @@
>  #include <asm/platform.h>
>  #include "vtimer.h"
>  #include "vuart.h"
> +#include <xen/vpl011.h>
>  
>  DEFINE_PER_CPU(struct vcpu *, curr_vcpu);
>  
> @@ -631,6 +632,9 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags,
>      if ( (rc = domain_vtimer_init(d, config)) != 0 )
>          goto fail;
>  
> +    if ( domcr_flags & DOMCRF_vuart )
> +        if ( (rc = domain_vpl011_init(d, config)) != 0 )
> +            goto fail;
>      update_domain_wallclock_time(d);
>  
>      /*
> @@ -665,6 +669,8 @@ fail:
>  
>  void arch_domain_destroy(struct domain *d)
>  {
> +    domain_vpl011_deinit(d);
> +
>      /* IOMMU page table is shared with P2M, always call
>       * iommu_domain_destroy() before p2m_teardown().
>       */
> diff --git a/xen/common/domctl.c b/xen/common/domctl.c
> index 951a5dc..902dd71 100644
> --- a/xen/common/domctl.c
> +++ b/xen/common/domctl.c
> @@ -501,6 +501,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
>                 | XEN_DOMCTL_CDF_hap
>                 | XEN_DOMCTL_CDF_s3_integrity
>                 | XEN_DOMCTL_CDF_oos_off
> +               | XEN_DOMCTL_VUART_enable
>                 | XEN_DOMCTL_CDF_xs_domain)) )

Please place XEN_DOMCTL_VUART_enable at last item. Aside from this:

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>


>              break;
>  
> @@ -539,6 +540,8 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
>              domcr_flags |= DOMCRF_oos_off;
>          if ( op->u.createdomain.flags & XEN_DOMCTL_CDF_xs_domain )
>              domcr_flags |= DOMCRF_xs_domain;
> +        if ( op->u.createdomain.flags & XEN_DOMCTL_VUART_enable )
> +            domcr_flags |= DOMCRF_vuart;
>  
>          d = domain_create(dom, domcr_flags, op->u.createdomain.ssidref,
>                            &op->u.createdomain.config);
> diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
> index 8bee0c3..c307013 100644
> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -63,6 +63,8 @@ struct xen_domctl_createdomain {
>   /* Is this a xenstore domain? */
>  #define _XEN_DOMCTL_CDF_xs_domain     4
>  #define XEN_DOMCTL_CDF_xs_domain      (1U<<_XEN_DOMCTL_CDF_xs_domain)
> +#define _XEN_DOMCTL_VUART_enable      6
> +#define XEN_DOMCTL_VUART_enable       (1U<<_XEN_DOMCTL_VUART_enable)
>      uint32_t flags;
>      struct xen_arch_domainconfig config;
>  };
> diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
> index 1127ca9..ee7dc7a 100644
> --- a/xen/include/xen/sched.h
> +++ b/xen/include/xen/sched.h
> @@ -555,6 +555,10 @@ struct domain *domain_create(domid_t domid, unsigned int domcr_flags,
>  #define _DOMCRF_xs_domain       5
>  #define DOMCRF_xs_domain        (1U<<_DOMCRF_xs_domain)
>  
> + /* DOMCRF_vuart: enable virtual uart emulation. Used for Aarch64. */
> +#define _DOMCRF_vuart  7
> +#define DOMCRF_vuart   (1U<<_DOMCRF_vuart)
> +
>  /*
>   * rcu_lock_domain_by_id() is more efficient than get_domain_by_id().
>   * This is the preferred function if the returned domain reference
> -- 
> 2.7.4
> 

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

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

* Re: [PATCH 02/10 v2] xen/arm: vpl011: Add new vuart domctl interface to setup pfn and evtchn
  2017-04-28 16:01 ` [PATCH 02/10 v2] xen/arm: vpl011: Add new vuart domctl interface to setup pfn and evtchn Bhupinder Thakur
@ 2017-04-28 19:23   ` Stefano Stabellini
  2017-05-02  7:39     ` Jan Beulich
  2017-05-02  7:47   ` Jan Beulich
  2017-05-03 10:14   ` Julien Grall
  2 siblings, 1 reply; 54+ messages in thread
From: Stefano Stabellini @ 2017-04-28 19:23 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich, xen-devel

On Fri, 28 Apr 2017, Bhupinder Thakur wrote:
> 1. Add two new domctl API to:
>     - Allocate a new event channel for sending/receiving events to/from Xen.
>     - Map the PFN allocted by the toolstack to be used as IN/OUT ring buffers.
> 
> Xen will communicate with xenconsole over the ring buffer and the event
> channel to transmit and receive pl011 data on guest domain's behalf.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
> ---
> 
> Changes since v1:
> 
> - Replaced the hvm interface with domctl interface
> 
>  tools/libxc/include/xenctrl.h | 26 ++++++++++++++++++++++++++
>  tools/libxc/xc_domain.c       | 39 +++++++++++++++++++++++++++++++++++++++
>  xen/arch/arm/domctl.c         | 20 ++++++++++++++++++++
>  xen/arch/x86/domctl.c         |  4 ++++
>  xen/include/public/domctl.h   | 11 +++++++++++
>  5 files changed, 100 insertions(+)
> 
> diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
> index 1629f41..bebfe7d 100644
> --- a/tools/libxc/include/xenctrl.h
> +++ b/tools/libxc/include/xenctrl.h
> @@ -886,6 +886,32 @@ int xc_vcpu_getcontext(xc_interface *xch,
>                         vcpu_guest_context_any_t *ctxt);
>  
>  /**
> + * This function returns information about the pfn and the event channel
> + * to be used for setting up a virtual uart console.

"and the event channel", shouldn't it be one or the other? The
description should be "This function sets the pfn to be used for vuart
communications."


> + * @parm xch a handle to an open hypervisor interface
> + * @parm domid the domain to get information from
> + * @parm vuart_pfn the pfn to be used for the ring buffer
> + * @return 0 on success, negative error on failure
> + */
> +int xc_domain_vuart_set_pfn(xc_interface *xch,
> +                            uint32_t domid,
> +                            uint32_t vuart_pfn);
> +
> +/**
> + * This function returns information about the pfn and the event channel
> + * to be used for setting up a virtual console.

In this case you should remove the part on the pfn.


> + * @parm xch a handle to an open hypervisor interface
> + * @parm domid the domain to get information from
> + * @parm vuart_evtchn the event channel to be used for console events
> + * @return 0 on success, negative error on failure
> + */
> +int xc_domain_vuart_get_evtchn(xc_interface *xch,
> +                               uint32_t domid,
> +                               uint32_t *vuart_evtchn);
> +
> +/**
>   * This function returns information about the XSAVE state of a particular
>   * vcpu of a domain. If extstate->size and extstate->xfeature_mask are 0,
>   * the call is considered a query to retrieve them and the buffer is not
> diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
> index 00909ad4..943f202 100644
> --- a/tools/libxc/xc_domain.c
> +++ b/tools/libxc/xc_domain.c
> @@ -343,6 +343,45 @@ int xc_domain_get_guest_width(xc_interface *xch, uint32_t domid,
>      return 0;
>  }
>  
> +int xc_domain_vuart_set_pfn(xc_interface *xch,
> +                            uint32_t domid,
> +                            uint32_t vuart_pfn)
> +{
> +    DECLARE_DOMCTL;
> +    int rc = 0;
> +
> +    domctl.cmd = XEN_DOMCTL_vuart_op;
> +    domctl.domain = (domid_t)domid;
> +    domctl.u.vuart_op.cmd = XEN_DOMCTL_VUART_OP_SET_PFN;
> +    domctl.u.vuart_op.pfn = vuart_pfn;
> +
> +    if ( (rc = do_domctl(xch, &domctl)) < 0 )
> +        return rc;
> +
> +    return rc;
> +}
> +
> +int xc_domain_vuart_get_evtchn(xc_interface *xch,
> +                               uint32_t domid,
> +                               uint32_t *vuart_evtchn)
> +{
> +    DECLARE_DOMCTL;
> +    int rc = 0;
> +
> +	*vuart_evtchn = -1;

tabs


> +    domctl.cmd = XEN_DOMCTL_vuart_op;
> +    domctl.domain = (domid_t)domid;
> +    domctl.u.vuart_op.cmd = XEN_DOMCTL_VUART_OP_GET_EVTCHN;
> +
> +    if ( (rc = do_domctl(xch, &domctl)) < 0 )
> +        return rc;
> +
> +    *vuart_evtchn = domctl.u.vuart_op.evtchn;
> +
> +    return rc;
> +}
> +
>  int xc_domain_getinfo(xc_interface *xch,
>                        uint32_t first_domid,
>                        unsigned int max_doms,
> diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
> index 971caec..e400f87 100644
> --- a/xen/arch/arm/domctl.c
> +++ b/xen/arch/arm/domctl.c
> @@ -10,6 +10,7 @@
>  #include <xen/sched.h>
>  #include <xen/hypercall.h>
>  #include <xen/iocap.h>
> +#include <xen/guest_access.h>
>  #include <xsm/xsm.h>
>  #include <public/domctl.h>
>  
> @@ -119,6 +120,25 @@ long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
>          d->disable_migrate = domctl->u.disable_migrate.disable;
>          return 0;
>  
> +    case XEN_DOMCTL_vuart_op:
> +    {
> +        int rc;
> +        if ( d->arch.vpl011.initialized )
> +        {
> +            if ( domctl->u.vuart_op.cmd == XEN_DOMCTL_VUART_OP_SET_PFN )
> +            {
> +                rc = vpl011_map_guest_page(d, domctl->u.vuart_op.pfn);
> +            }
> +            else
> +            {
> +                domctl->u.vuart_op.evtchn = d->arch.vpl011.evtchn;
> +                rc = __copy_to_guest(u_domctl, domctl, 1);
> +            }
> +            return rc;
> +        }
> +        else
> +            return -EINVAL;
> +    }
>      default:
>      {
>          int rc;
> diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
> index e104be2..49e907d 100644
> --- a/xen/arch/x86/domctl.c
> +++ b/xen/arch/x86/domctl.c
> @@ -1465,6 +1465,10 @@ long arch_do_domctl(
>          recalculate_cpuid_policy(d);
>          break;
>  
> +    case XEN_DOMCTL_vuart_op:
> +        ret = -EOPNOTSUPP;
> +        break;
> +
>      default:
>          ret = iommu_do_domctl(domctl, d, u_domctl);
>          break;
> diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
> index e6cf211..8bee0c3 100644
> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -1138,6 +1138,15 @@ struct xen_domctl_psr_cat_op {
>      uint32_t target;    /* IN */
>      uint64_t data;      /* IN/OUT */
>  };
> +
> +struct xen_domctl_vuart_op {
> +#define XEN_DOMCTL_VUART_OP_SET_PFN      0
> +#define XEN_DOMCTL_VUART_OP_GET_EVTCHN   1
> +        uint32_t cmd;       /* XEN_DOMCTL_VUART_OP_* */
> +        uint32_t pfn;       /* IN */

xen_pfn_t


> +        uint32_t evtchn;    /* OUT */

evtchn_port_t


> +};
> +
>  typedef struct xen_domctl_psr_cat_op xen_domctl_psr_cat_op_t;
>  DEFINE_XEN_GUEST_HANDLE(xen_domctl_psr_cat_op_t);
>  
> @@ -1218,6 +1227,7 @@ struct xen_domctl {
>  #define XEN_DOMCTL_monitor_op                    77
>  #define XEN_DOMCTL_psr_cat_op                    78
>  #define XEN_DOMCTL_soft_reset                    79
> +#define XEN_DOMCTL_vuart_op                      80
>  #define XEN_DOMCTL_gdbsx_guestmemio            1000
>  #define XEN_DOMCTL_gdbsx_pausevcpu             1001
>  #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
> @@ -1280,6 +1290,7 @@ struct xen_domctl {
>          struct xen_domctl_psr_cmt_op        psr_cmt_op;
>          struct xen_domctl_monitor_op        monitor_op;
>          struct xen_domctl_psr_cat_op        psr_cat_op;
> +        struct xen_domctl_vuart_op          vuart_op;
>          uint8_t                             pad[128];
>      } u;
>  };
> -- 
> 2.7.4
> 

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

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

* Re: [PATCH 04/10 v2] xen/arm: vpl011: Add support for vuart in libxl
  2017-04-28 16:01 ` [PATCH 04/10 v2] xen/arm: vpl011: Add support for vuart in libxl Bhupinder Thakur
@ 2017-04-28 21:45   ` Stefano Stabellini
  2017-05-03 10:27   ` Julien Grall
  1 sibling, 0 replies; 54+ messages in thread
From: Stefano Stabellini @ 2017-04-28 21:45 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich, xen-devel

On Fri, 28 Apr 2017, Bhupinder Thakur wrote:
> An option is provided in libxl to enable/disable pl011 vuart while
> creating a guest domain.
> 
> Libxl now suppots a generic vuart console and pl011 is a specific type.
> In future support can be added for multiple vuart of different types.
> 
> User can enable pl011 vuart by adding the following line in the guest
> configuration file:
> 
> vuart = "pl011"
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
> ---
> 
> Changes since v1:
> - Modified the syntax for taking the pl011 as a console type in the
>   configuration file. Now the syntax is vuart = "pl011".
> - Replaced the console type VCON with VUART, as it is more 
>   intuitive.
> 
>  tools/libxl/libxl.h          |  6 ++++++
>  tools/libxl/libxl_create.c   | 10 ++++++++++
>  tools/libxl/libxl_internal.h |  4 ++++
>  tools/libxl/libxl_types.idl  |  2 ++
>  tools/xl/xl_console.c        |  4 +++-
>  tools/xl/xl_parse.c          |  3 +++
>  6 files changed, 28 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
> index cf8687a..bcfbb6c 100644
> --- a/tools/libxl/libxl.h
> +++ b/tools/libxl/libxl.h
> @@ -306,6 +306,12 @@
>  #define LIBXL_HAVE_BUILDINFO_HVM_ACPI_LAPTOP_SLATE 1
>  
>  /*
> + * LIBXL_HAVE_VUART indicates that xenconsole/client supports
> + * virtual uart.
> + */
> +#define LIBXL_HAVE_VUART 1
> +
> +/*
>   * libxl ABI compatibility
>   *
>   * The only guarantee which libxl makes regarding ABI compatibility
> diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
> index bffbc45..5d70bc2 100644
> --- a/tools/libxl/libxl_create.c
> +++ b/tools/libxl/libxl_create.c
> @@ -536,6 +536,9 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config,
>          flags |= libxl_defbool_val(info->oos) ? 0 : XEN_DOMCTL_CDF_oos_off;
>      }
>  
> +    if (!strcmp(d_config->b_info.vuart, "pl011"))
> +        flags |= XEN_DOMCTL_VUART_enable;
> +
>      /* Ultimately, handle is an array of 16 uint8_t, same as uuid */
>      libxl_uuid_copy(ctx, (libxl_uuid *)handle, &info->uuid);
>  
> @@ -900,6 +903,11 @@ static void initiate_domain_create(libxl__egc *egc,
>          goto error_out;
>      }
>  
> +    if (!strcmp(d_config->b_info.vuart, "pl011"))
> +        state->vuart_enabled = true;
> +    else
> +        state->vuart_enabled = false;
> +
>      if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM &&
>          (libxl_defbool_val(d_config->b_info.u.hvm.nested_hvm) &&
>          (libxl_defbool_val(d_config->b_info.u.hvm.altp2m) ||
> @@ -918,6 +926,8 @@ static void initiate_domain_create(libxl__egc *egc,
>          goto error_out;
>      }
>  
> +    state->config.console_domid = state->console_domid;
> +
>      ret = libxl__domain_make(gc, d_config, &domid, &state->config);
>      if (ret) {
>          LOGD(ERROR, domid, "cannot make domain: %d", ret);
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index 5d082c5..9dba8e7 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -1135,6 +1135,10 @@ typedef struct {
>      uint32_t num_vmemranges;
>  
>      xc_domain_configuration_t config;
> +
> +    unsigned long vuart_mfn;
> +    uint32_t    vuart_port;
> +    bool        vuart_enabled;
>  } libxl__domain_build_state;
>  
>  _hidden int libxl__build_pre(libxl__gc *gc, uint32_t domid,
> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> index 2204425..5d53f2c 100644
> --- a/tools/libxl/libxl_types.idl
> +++ b/tools/libxl/libxl_types.idl
> @@ -105,6 +105,7 @@ libxl_console_type = Enumeration("console_type", [
>      (0, "UNKNOWN"),
>      (1, "SERIAL"),
>      (2, "PV"),
> +    (3, "VUART"),
>      ])
>  
>  libxl_disk_format = Enumeration("disk_format", [
> @@ -470,6 +471,7 @@ libxl_domain_build_info = Struct("domain_build_info",[
>      ("disable_migrate", libxl_defbool),
>      ("cpuid",           libxl_cpuid_policy_list),
>      ("blkdev_start",    string),
> +    ("vuart",           string),

I think it's best to store the vuart type as an enum rather than a
string, that would remove the strcmp calls from in
tools/libxl/libxl_create.c.


>      ("vnuma_nodes", Array(libxl_vnode_info, "num_vnuma_nodes")),
>      
> diff --git a/tools/xl/xl_console.c b/tools/xl/xl_console.c
> index 0508dda..6f3cd7f 100644
> --- a/tools/xl/xl_console.c
> +++ b/tools/xl/xl_console.c
> @@ -34,8 +34,10 @@ int main_console(int argc, char **argv)
>              type = LIBXL_CONSOLE_TYPE_PV;
>          else if (!strcmp(optarg, "serial"))
>              type = LIBXL_CONSOLE_TYPE_SERIAL;
> +        else if (!strcmp(optarg, "vuart"))
> +            type = LIBXL_CONSOLE_TYPE_VUART;
>          else {
> -            fprintf(stderr, "console type supported are: pv, serial\n");
> +            fprintf(stderr, "console type supported are: pv, serial, vuart\n");
>              return EXIT_FAILURE;
>          }
>          break;
> diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
> index 856a304..80fd184 100644
> --- a/tools/xl/xl_parse.c
> +++ b/tools/xl/xl_parse.c
> @@ -916,6 +916,9 @@ void parse_config_data(const char *config_source,
>      if (!xlu_cfg_get_long (config, "maxvcpus", &l, 0))
>          b_info->max_vcpus = l;
>  
> +    if (xlu_cfg_replace_string(config, "vuart", &b_info->vuart, 0))
> +        b_info->vuart = strdup("unknown");
> +
>      parse_vnuma_config(config, b_info);
>  
>      /* Set max_memkb to target_memkb and max_vcpus to avail_vcpus if
> -- 
> 2.7.4
> 

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

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

* Re: [PATCH 05/10 v2] xen/arm: vpl011: Allocate a new PFN in the toolstack for vuart
  2017-04-28 16:01 ` [PATCH 05/10 v2] xen/arm: vpl011: Allocate a new PFN in the toolstack for vuart Bhupinder Thakur
@ 2017-04-28 21:48   ` Stefano Stabellini
  0 siblings, 0 replies; 54+ messages in thread
From: Stefano Stabellini @ 2017-04-28 21:48 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich, xen-devel

On Fri, 28 Apr 2017, Bhupinder Thakur wrote:
> Allocate a new pfn and pass on to Xen using a domctl call.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>


> 
> Changes since v1:
> - Replaced the hvm call with the domctl call to set the pfn.
> 
>  tools/libxc/include/xc_dom.h | 2 ++
>  tools/libxc/xc_dom_arm.c     | 7 ++++++-
>  tools/libxc/xc_dom_boot.c    | 2 ++
>  3 files changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/libxc/include/xc_dom.h b/tools/libxc/include/xc_dom.h
> index ce47058..ca8bc23 100644
> --- a/tools/libxc/include/xc_dom.h
> +++ b/tools/libxc/include/xc_dom.h
> @@ -216,6 +216,8 @@ struct xc_dom_image {
>  
>      /* Extra SMBIOS structures passed to HVMLOADER */
>      struct xc_hvm_firmware_module smbios_module;
> +
> +    xen_pfn_t vuart_pfn;
>  };
>  
>  /* --- pluggable kernel loader ------------------------------------- */
> diff --git a/tools/libxc/xc_dom_arm.c b/tools/libxc/xc_dom_arm.c
> index e7d4bd0..ad805d1 100644
> --- a/tools/libxc/xc_dom_arm.c
> +++ b/tools/libxc/xc_dom_arm.c
> @@ -26,10 +26,11 @@
>  #include "xg_private.h"
>  #include "xc_dom.h"
>  
> -#define NR_MAGIC_PAGES 3
> +#define NR_MAGIC_PAGES 4
>  #define CONSOLE_PFN_OFFSET 0
>  #define XENSTORE_PFN_OFFSET 1
>  #define MEMACCESS_PFN_OFFSET 2
> +#define VUART_PFN_OFFSET 3
>  
>  #define LPAE_SHIFT 9
>  
> @@ -85,16 +86,20 @@ static int alloc_magic_pages(struct xc_dom_image *dom)
>  
>      dom->console_pfn = base + CONSOLE_PFN_OFFSET;
>      dom->xenstore_pfn = base + XENSTORE_PFN_OFFSET;
> +    dom->vuart_pfn = base + VUART_PFN_OFFSET;
>  
>      xc_clear_domain_page(dom->xch, dom->guest_domid, dom->console_pfn);
>      xc_clear_domain_page(dom->xch, dom->guest_domid, dom->xenstore_pfn);
>      xc_clear_domain_page(dom->xch, dom->guest_domid, base + MEMACCESS_PFN_OFFSET);
> +    xc_clear_domain_page(dom->xch, dom->guest_domid, base + VUART_PFN_OFFSET);
>      xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_PFN,
>              dom->console_pfn);
>      xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_STORE_PFN,
>              dom->xenstore_pfn);
>      xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_MONITOR_RING_PFN,
>              base + MEMACCESS_PFN_OFFSET);
> +    xc_domain_vuart_set_pfn(dom->xch, dom->guest_domid, base + VUART_PFN_OFFSET);
> +
>      /* allocated by toolstack */
>      xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_EVTCHN,
>              dom->console_evtchn);
> diff --git a/tools/libxc/xc_dom_boot.c b/tools/libxc/xc_dom_boot.c
> index c3b44dd..5e4b322 100644
> --- a/tools/libxc/xc_dom_boot.c
> +++ b/tools/libxc/xc_dom_boot.c
> @@ -226,6 +226,8 @@ int xc_dom_boot_image(struct xc_dom_image *dom)
>          return rc;
>      if ( (rc = clear_page(dom, dom->xenstore_pfn)) != 0 )
>          return rc;
> +    if ( (rc = clear_page(dom, dom->vuart_pfn)) != 0 )
> +        return rc;
>  
>      /* start info page */
>      if ( dom->arch_hooks->start_info )
> -- 
> 2.7.4
> 

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

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

* Re: [PATCH 06/10 v2] xen/arm: vpl011: Add vuart ring-buf and evtchn to xenstore
  2017-04-28 16:01 ` [PATCH 06/10 v2] xen/arm: vpl011: Add vuart ring-buf and evtchn to xenstore Bhupinder Thakur
@ 2017-04-28 21:57   ` Stefano Stabellini
  2017-05-01 11:21     ` Bhupinder Thakur
  0 siblings, 1 reply; 54+ messages in thread
From: Stefano Stabellini @ 2017-04-28 21:57 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich, xen-devel

On Fri, 28 Apr 2017, Bhupinder Thakur wrote:
> Add two new parameters to the xen store to be used by xenconsoled:
>     - newly allocated PFN to be used as IN/OUT ring buffer
>     - get a new event channel allocated by Xen using a domctl call
> 
> These paramters are added to xenstore only if vuart console is enabled
> by the user.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
> ---
> 
> Changes since v1:
> - Modified the xenstore key names to /vuart/0/ring-ref and 
>   /vuart/0/port.
> - Replaced the hvm call with domctl call to get the event channel.
> 
>  tools/libxl/libxl_console.c | 10 ++++++++++
>  tools/libxl/libxl_dom.c     |  4 ++++
>  2 files changed, 14 insertions(+)
> 
> diff --git a/tools/libxl/libxl_console.c b/tools/libxl/libxl_console.c
> index 446e766..ef3bd44 100644
> --- a/tools/libxl/libxl_console.c
> +++ b/tools/libxl/libxl_console.c
> @@ -67,6 +67,9 @@ int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num,
>      case LIBXL_CONSOLE_TYPE_SERIAL:
>          cons_type_s = "serial";
>          break;
> +    case LIBXL_CONSOLE_TYPE_VUART:
> +        cons_type_s = "vuart";
> +        break;
>      default:
>          goto out;
>      }
> @@ -326,6 +329,13 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
>          flexarray_append(ro_front, GCSPRINTF("%"PRIu32, state->console_port));
>          flexarray_append(ro_front, "ring-ref");
>          flexarray_append(ro_front, GCSPRINTF("%lu", state->console_mfn));
> +        if (state->vuart_enabled)
> +        {
> +            flexarray_append(ro_front, "vuart/0/port");
> +            flexarray_append(ro_front, GCSPRINTF("%"PRIu32, state->vuart_port));
> +            flexarray_append(ro_front, "vuart/0/ring-ref");
> +            flexarray_append(ro_front, GCSPRINTF("%lu", state->vuart_mfn));
> +        }

It looks like you are reusing the libxl__device_console_add call for the
main PV console for the domain, to also add the vuart nodes to xenstore.

I don't think it is a good idea to mix the two. I suggest to introduce a
new libxl__device call to introduce the vuart nodes to xenstore, given
that they have no relantionship with the principal PV console of the
domain.


>      } else {
>          flexarray_append(front, "state");
>          flexarray_append(front, GCSPRINTF("%d", XenbusStateInitialising));
> diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
> index 5d914a5..06ff3b7 100644
> --- a/tools/libxl/libxl_dom.c
> +++ b/tools/libxl/libxl_dom.c
> @@ -434,6 +434,9 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
>      state->store_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->store_domid);
>      state->console_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->console_domid);
>  
> +    if (state->vuart_enabled)
> +        xc_domain_vuart_get_evtchn(ctx->xch, domid, &state->vuart_port);
> +
>      if (info->type == LIBXL_DOMAIN_TYPE_HVM) {
>          hvm_set_conf_params(ctx->xch, domid, info);
>  #if defined(__i386__) || defined(__x86_64__)
> @@ -788,6 +791,7 @@ int libxl__build_pv(libxl__gc *gc, uint32_t domid,
>      if (xc_dom_translated(dom)) {
>          state->console_mfn = dom->console_pfn;
>          state->store_mfn = dom->xenstore_pfn;
> +        state->vuart_mfn = dom->vuart_pfn;
>      } else {
>          state->console_mfn = xc_dom_p2m(dom, dom->console_pfn);
>          state->store_mfn = xc_dom_p2m(dom, dom->xenstore_pfn);

These two changes to libxl_dom.c probably belong to patch #4

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

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

* Re: [PATCH 08/10 v2] xen/arm: vpl011: Add a new vuart console type to xenconsole client
  2017-04-28 16:01 ` [PATCH 08/10 v2] xen/arm: vpl011: Add a new vuart console type to xenconsole client Bhupinder Thakur
@ 2017-04-28 22:01   ` Stefano Stabellini
  0 siblings, 0 replies; 54+ messages in thread
From: Stefano Stabellini @ 2017-04-28 22:01 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich, xen-devel

On Fri, 28 Apr 2017, Bhupinder Thakur wrote:
> Add a new console type VUART to connect to guest vuart.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
> ---
>  tools/console/client/main.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/console/client/main.c b/tools/console/client/main.c
> index 977779f..ec5c6e1 100644
> --- a/tools/console/client/main.c
> +++ b/tools/console/client/main.c
> @@ -76,7 +76,7 @@ static void usage(const char *program) {
>  	       "\n"
>  	       "  -h, --help       display this help and exit\n"
>  	       "  -n, --num N      use console number N\n"
> -	       "  --type TYPE      console type. must be 'pv' or 'serial'\n"
> +	       "  --type TYPE      console type. must be 'pv', 'serial' or 'vuart'\n"
>  	       "  --start-notify-fd N file descriptor used to notify parent\n"
>  	       , program);
>  }
> @@ -264,6 +264,7 @@ typedef enum {
>         CONSOLE_INVAL,
>         CONSOLE_PV,
>         CONSOLE_SERIAL,
> +       CONSOLE_VUART,
>  } console_type;
>  
>  static struct termios stdin_old_attr;
> @@ -361,6 +362,8 @@ int main(int argc, char **argv)
>  				type = CONSOLE_SERIAL;
>  			else if (!strcmp(optarg, "pv"))
>  				type = CONSOLE_PV;
> +			else if (!strcmp(optarg, "vuart"))
> +				type = CONSOLE_VUART;
>  			else {
>  				fprintf(stderr, "Invalid type argument\n");
>  				fprintf(stderr, "Console types supported are: serial, pv\n");
> @@ -436,6 +439,9 @@ int main(int argc, char **argv)
>  		else
>  			snprintf(path, strlen(dom_path) + strlen("/device/console/%d/tty") + 5, "%s/device/console/%d/tty", dom_path, num);
>  	}
> +	if (type == CONSOLE_VUART) {
> +		snprintf(path, strlen(dom_path) + strlen("/console/vtty") + 1, "%s/console/vtty", dom_path);

It looks like this xenstore path is missing a description in patch #10.


> +	}
>  
>  	/* FIXME consoled currently does not assume domain-0 doesn't have a
>  	   console which is good when we break domain-0 up.  To keep us
> -- 
> 2.7.4
> 

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

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

* Re: [PATCH 10/10 v2] xen/arm: vpl011: Update documentation for vuart console support
  2017-04-28 16:01 ` [PATCH 10/10 v2] xen/arm: vpl011: Update documentation for vuart console support Bhupinder Thakur
@ 2017-04-28 22:06   ` Stefano Stabellini
  0 siblings, 0 replies; 54+ messages in thread
From: Stefano Stabellini @ 2017-04-28 22:06 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich, xen-devel

On Fri, 28 Apr 2017, Bhupinder Thakur wrote:
> 1. Update documentation for vuart = "pl011" option added.
> 2. Update documentation about SPI irq reserved for vpl011.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
> ---
>  docs/man/xl.cfg.pod.5.in |  8 ++++++++
>  docs/misc/console.txt    | 14 +++++++++++++-
>  2 files changed, 21 insertions(+), 1 deletion(-)
> 
> diff --git a/docs/man/xl.cfg.pod.5.in b/docs/man/xl.cfg.pod.5.in
> index 13167ff..44118a8 100644
> --- a/docs/man/xl.cfg.pod.5.in
> +++ b/docs/man/xl.cfg.pod.5.in
> @@ -1085,6 +1085,14 @@ Allow a guest to access specific physical IRQs.
>  It is recommended to use this option only for trusted VMs under
>  administrator control.
>  
> +If vuart console is enabled then irq 32 is reserved for vuart. By default
> +vuart console is disabled. If user specifies the following option in
> +the guest config file then vuart console is enabled.

Please rewrite this as:

  If the virtual uart is enabled then irq 32 is reserved for it. By
  default, it is disabled. If the user specifies the following option in
  the VM config file then the vuart gets enabled. Today, only the
  "pl011" model is supported.


> +vuart = "pl011"
> +
> +vuart console is currently enabled only for ARM64.
                              ^ available


>  =item B<max_event_channels=N>
>  
>  Limit the guest to using at most N event channels (PV interrupts).
> diff --git a/docs/misc/console.txt b/docs/misc/console.txt
> index 16da805..2455fc7 100644
> --- a/docs/misc/console.txt
> +++ b/docs/misc/console.txt
> @@ -19,7 +19,19 @@ The first PV console path in xenstore remains:
>  
>  /local/domain/$DOMID/console
>  
> -the other PV consoles follow the conventional xenstore device path and
> +The vuart console path in xenstore is defined as:
> +
> +/local/domain/$DOMID/console/vuart/0
> +
> +The vuart console provides access to pl011 UART on ARM64 systems. To
                                     ^ to a virtual pl011 UUART

> +enable vuart the following line has to be added the guest configuration
> +file:
> +
> +vuart = "pl011"
> +
> +Also the console should be set to "ttyAMA0" instead of "hvc0".

ttyAMA0 and hvc0 are Linuxims. Please rewrite as follow:

  In Linux you can select the virtual pl011 uart by using the "ttyAMA0"
  console instead of "hvc0".


> +The other PV consoles follow the conventional xenstore device path and
>  live in:
>  
>  /local/domain/$DOMID/device/console/$DEVID.
> -- 
> 2.7.4
> 

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

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

* Re: [PATCH 07/10 v2] xen/arm: vpl011: Add support for vuart in xenconsole
  2017-04-28 16:01 ` [PATCH 07/10 v2] xen/arm: vpl011: Add support for vuart in xenconsole Bhupinder Thakur
@ 2017-04-28 23:10   ` Stefano Stabellini
  2017-05-08  6:18     ` Bhupinder Thakur
  0 siblings, 1 reply; 54+ messages in thread
From: Stefano Stabellini @ 2017-04-28 23:10 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich, xen-devel

On Fri, 28 Apr 2017, Bhupinder Thakur wrote:
> Xenconsole supports only PV console currently. This patch adds support
> for vuart, which allows emulated pl011 uart to be accessed as a console.
> 
> This patch modifies different data structures and APIs used
> in xenconsole to support two console types: PV and VUART.
> 
> Change summary:
> 
> 1. Split the domain structure into a console structure and the
>    domain structure. Each PV and VUART will have seprate console
>    structures.
> 
> 2. Modify different APIs such as buffer_append() etc. to take
>    console structure as input and perform per console specific
>    operations.
> 
> 3. Modfications in domain_create_ring():
>     - Bind to the vpl011 event channel obtained from the xen store as a
>       new parameter.
>     - Map the PFN to its address space to be used as IN/OUT ring
>       buffers.
>       It obtains the PFN from the xen store as a new parameter
> 
> 4. Modifications in handle_ring_read() to handle both PV and VUART
>    events.
> 
> 5. Add a new log_file for VUART console logs.

This patch is too big. It might be best to split this patch in two: one
to refactor the code to introduce struct console, and the other to
introduce the vuart console.  It would make it far easier to review.


> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
> ---
> 
> Changes since v1:
> 
> - Split the domain struture to a separate console structure
> - Modified the functions to operate on the console struture
> - Replaced repetitive per console code with generic code
> 
>  tools/console/daemon/io.c | 514 ++++++++++++++++++++++++++++++++--------------
>  1 file changed, 365 insertions(+), 149 deletions(-)
> 
> diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
> index 7e6a886..55fda37 100644
> --- a/tools/console/daemon/io.c
> +++ b/tools/console/daemon/io.c
> @@ -61,6 +61,10 @@
>  /* Duration of each time period in ms */
>  #define RATE_LIMIT_PERIOD 200
>  
> +#define MAX_CONSOLE 2
> +#define CONSOLE_TYPE_PV 0
> +#define CONSOLE_TYPE_VUART 1

It would be nice to protect this by something like:

#ifdef CONFIG_ARM64 && CONFIG_ACPI

so that we don't waste memory in all other cases. The end result would
be to have an console array of only one element on arm32 and x86 and
when acpi is disabled.


>  extern int log_reload;
>  extern int log_guest;
>  extern int log_hv;
> @@ -89,29 +93,75 @@ struct buffer {
>  	size_t max_capacity;
>  };
>  
> -struct domain {
> -	int domid;
> +struct console {
> +	char *name;
> +	char *ttyname;
>  	int master_fd;
>  	int master_pollfd_idx;
>  	int slave_fd;
>  	int log_fd;
> -	bool is_dead;
> -	unsigned last_seen;
>  	struct buffer buffer;
> -	struct domain *next;
> -	char *conspath;
>  	int ring_ref;
>  	xenevtchn_port_or_error_t local_port;
>  	xenevtchn_port_or_error_t remote_port;
> +	struct xencons_interface *interface;
> +	struct domain *d;  /* Reference to the domain it is contained in. */
> +};
> +
> +struct domain {
> +	int domid;
> +	bool is_dead;
> +	unsigned last_seen;
> +	struct domain *next;
> +	char *conspath;
>  	xenevtchn_handle *xce_handle;
>  	int xce_pollfd_idx;
> -	struct xencons_interface *interface;
>  	int event_count;
>  	long long next_period;
> +	struct console console[MAX_CONSOLE];
>  };
>  
>  static struct domain *dom_head;
>  
> +static inline bool console_enabled(struct console *con) { return con->local_port != -1; }

Long lines through this patch. Max length is supposed to be 80 chars.


> +
> +static inline void console_iter_no_check(struct domain *d, void (* iter_func)(struct console *))
> +{
> +	int i = 0;
> +	struct console *con = &(d->console[0]);
> +
> +	for (i=0; i < MAX_CONSOLE; i++, con++)

code style i = 0


> +	{
> +		iter_func(con);
> +	}
> +}
> +
> +static inline bool console_iter_bool_check(struct domain *d, bool (* iter_func)(struct console *))
> +{
> +	int i = 0;
> +	struct console *con = &(d->console[0]);
> +
> +	for (i=0; i < MAX_CONSOLE; i++, con++)

code style


> +	{
> +		if (iter_func(con))
> +			return true;
> +	}
> +	return false;
> +}
> +
> +static inline int console_iter_err_check(struct domain *d, int (* iter_func)(struct console *))
> +{
> +	int i = 0;
> +	struct console *con = &(d->console[0]);
> +
> +	for (i=0; i < MAX_CONSOLE; i++, con++)

code style


> +	{
> +		if (!iter_func(con))
> +			return 0;
> +	}
> +	return 1;
> +}
> +
>  static int write_all(int fd, const char* buf, size_t len)
>  {
>  	while (len) {
> @@ -158,11 +208,24 @@ static int write_with_timestamp(int fd, const char *data, size_t sz,
>  	return 0;
>  }
>  
> -static void buffer_append(struct domain *dom)
> +static inline bool buffer_available(struct console *con)
> +{
> +	if (discard_overflowed_data ||
> +		!con->buffer.max_capacity ||
> +		con->buffer.size < con->buffer.max_capacity)
> +		return true;
> +	else
> +		return false;
> +}
> +
> +static void buffer_append(struct console *con)
>  {
> -	struct buffer *buffer = &dom->buffer;
> +	struct buffer *buffer = &con->buffer;
> +	struct xencons_interface *intf = con->interface;
> +	xenevtchn_port_or_error_t port = con->local_port;
> +	struct domain *dom = con->d;
> +
>  	XENCONS_RING_IDX cons, prod, size;
> -	struct xencons_interface *intf = dom->interface;
>  
>  	cons = intf->out_cons;
>  	prod = intf->out_prod;
> @@ -187,22 +250,22 @@ static void buffer_append(struct domain *dom)
>  
>  	xen_mb();
>  	intf->out_cons = cons;
> -	xenevtchn_notify(dom->xce_handle, dom->local_port);
> +	xenevtchn_notify(dom->xce_handle, port);
>  
>  	/* Get the data to the logfile as early as possible because if
>  	 * no one is listening on the console pty then it will fill up
>  	 * and handle_tty_write will stop being called.
>  	 */
> -	if (dom->log_fd != -1) {
> +	if (con->log_fd != -1) {
>  		int logret;
>  		if (log_time_guest) {
>  			logret = write_with_timestamp(
> -				dom->log_fd,
> +				con->log_fd,
>  				buffer->data + buffer->size - size,
>  				size, &log_time_guest_needts);
>  		} else {
>  			logret = write_all(
> -				dom->log_fd,
> +				con->log_fd,
>  				buffer->data + buffer->size - size,
>  				size);
>  		}
> @@ -290,12 +353,13 @@ static int create_hv_log(void)
>  	return fd;
>  }
>  
> -static int create_domain_log(struct domain *dom)
> +static int create_console_log(struct console *con)
>  {
>  	char logfile[PATH_MAX];
>  	char *namepath, *data, *s;
>  	int fd;
>  	unsigned int len;
> +	struct domain *dom = con->d;
>  
>  	namepath = xs_get_domain_path(xs, dom->domid);
>  	s = realloc(namepath, strlen(namepath) + 6);
> @@ -314,7 +378,8 @@ static int create_domain_log(struct domain *dom)
>  		return -1;
>  	}
>  
> -	snprintf(logfile, PATH_MAX-1, "%s/guest-%s.log", log_dir, data);
> +	snprintf(logfile, PATH_MAX-1, "%s/guest-%s-%s.log",
> +			 log_dir, con->name, data);

I am OK with this, but I wonder if changing the log name will create any
troubles to existing management software.


>  	free(data);
>  	logfile[PATH_MAX-1] = '\0';
>  
> @@ -336,19 +401,24 @@ static int create_domain_log(struct domain *dom)
>  	return fd;
>  }
>  
> -static void domain_close_tty(struct domain *dom)
> +static void console_close_tty(struct console *con)
>  {
> -	if (dom->master_fd != -1) {
> -		close(dom->master_fd);
> -		dom->master_fd = -1;
> +	if (con->master_fd != -1) {
> +		close(con->master_fd);
> +		con->master_fd = -1;
>  	}
>  
> -	if (dom->slave_fd != -1) {
> -		close(dom->slave_fd);
> -		dom->slave_fd = -1;
> +	if (con->slave_fd != -1) {
> +		close(con->slave_fd);
> +		con->slave_fd = -1;
>  	}
>  }
>  
> +static void domain_close_tty(struct domain *dom)
> +{
> +	console_iter_no_check(dom, console_close_tty);
> +}
> +
>  #ifdef __sun__
>  static int openpty(int *amaster, int *aslave, char *name,
>  		   struct termios *termp, struct winsize *winp)
> @@ -409,7 +479,7 @@ void cfmakeraw(struct termios *termios_p)
>  }
>  #endif /* __sun__ */
>  
> -static int domain_create_tty(struct domain *dom)
> +static int console_create_tty(struct console *con)
>  {
>  	const char *slave;
>  	char *path;
> @@ -418,19 +488,23 @@ static int domain_create_tty(struct domain *dom)
>  	char *data;
>  	unsigned int len;
>  	struct termios term;
> +	struct domain *dom = con->d;
> +
> +	if (!console_enabled(con))
> +		return 1;
>  
> -	assert(dom->slave_fd == -1);
> -	assert(dom->master_fd == -1);
> +	assert(con->master_fd == -1);
> +	assert(con->slave_fd == -1);
>  
> -	if (openpty(&dom->master_fd, &dom->slave_fd, NULL, NULL, NULL) < 0) {
> +	if (openpty(&con->master_fd, &con->slave_fd, NULL, NULL, NULL) < 0) {
>  		err = errno;
>  		dolog(LOG_ERR, "Failed to create tty for domain-%d "
> -		      "(errno = %i, %s)",
> -		      dom->domid, err, strerror(err));
> -		return 0;
> +			  "(errno = %i, %s)",
> +			  dom->domid, err, strerror(err));
> +		goto out;

I noticed that you turned the return into a goto out, why?


>  	}
>  
> -	if (tcgetattr(dom->slave_fd, &term) < 0) {
> +	if (tcgetattr(con->slave_fd, &term) < 0) {
>  		err = errno;
>  		dolog(LOG_ERR, "Failed to get tty attributes for domain-%d "
>  			"(errno = %i, %s)",
> @@ -438,7 +512,7 @@ static int domain_create_tty(struct domain *dom)
>  		goto out;
>  	}
>  	cfmakeraw(&term);
> -	if (tcsetattr(dom->slave_fd, TCSANOW, &term) < 0) {
> +	if (tcsetattr(con->slave_fd, TCSANOW, &term) < 0) {
>  		err = errno;
>  		dolog(LOG_ERR, "Failed to set tty attributes for domain-%d "
>  			"(errno = %i, %s)",
> @@ -446,11 +520,11 @@ static int domain_create_tty(struct domain *dom)
>  		goto out;
>  	}
>  
> -	if ((slave = ptsname(dom->master_fd)) == NULL) {
> +	if ((slave = ptsname(con->master_fd)) == NULL) {
>  		err = errno;
>  		dolog(LOG_ERR, "Failed to get slave name for domain-%d "
> -		      "(errno = %i, %s)",
> -		      dom->domid, err, strerror(err));
> +			  "(errno = %i, %s)",
> +			  dom->domid, err, strerror(err));
>  		goto out;
>  	}
>  
> @@ -460,27 +534,41 @@ static int domain_create_tty(struct domain *dom)
>  		goto out;
>  	data = xs_read(xs, XBT_NULL, path, &len);
>  	if (data) {
> -		dom->buffer.max_capacity = strtoul(data, 0, 0);
> +		con->buffer.max_capacity = strtoul(data, 0, 0);
>  		free(data);
>  	}
>  	free(path);
>  
> -	success = (asprintf(&path, "%s/tty", dom->conspath) != -1);
> +	success = (asprintf(&path, "%s/%s", dom->conspath, con->ttyname) != -1);
> +
>  	if (!success)
>  		goto out;
>  	success = xs_write(xs, XBT_NULL, path, slave, strlen(slave));
>  	free(path);
> -	if (!success)
> +
> +	if (fcntl(con->master_fd, F_SETFL, O_NONBLOCK) == -1)
>  		goto out;
>  
> -	if (fcntl(dom->master_fd, F_SETFL, O_NONBLOCK) == -1)
> +	if (!success)
>  		goto out;
>  
>  	return 1;
> +
>  out:
> -	domain_close_tty(dom);
>  	return 0;
>  }
> +
> +static int domain_create_tty(struct domain *dom)
> +{
> +	int ret;
> +
> +	ret = console_iter_err_check(dom, console_create_tty);
> +
> +	if (!ret)
> +		domain_close_tty(dom);
> +
> +	return ret;
> +}
>   
>  /* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
>  static int xs_gather(struct xs_handle *xs, const char *dir, ...)
> @@ -517,22 +605,64 @@ static int xs_gather(struct xs_handle *xs, const char *dir, ...)
>  	return ret;
>  }
>  
> -static void domain_unmap_interface(struct domain *dom)
> +static void console_unmap_interface(struct console *con)
>  {
> -	if (dom->interface == NULL)
> +	if (con->interface == NULL)
>  		return;
> -	if (xgt_handle && dom->ring_ref == -1)
> -		xengnttab_unmap(xgt_handle, dom->interface, 1);
> +	if (xgt_handle && con->ring_ref == -1)
> +		xengnttab_unmap(xgt_handle, con->interface, 1);
>  	else
> -		munmap(dom->interface, XC_PAGE_SIZE);
> -	dom->interface = NULL;
> -	dom->ring_ref = -1;
> +		munmap(con->interface, XC_PAGE_SIZE);
> +	con->interface = NULL;
> +	con->ring_ref = -1;
> +}
> +
> +static void domain_unmap_interface(struct domain *dom)
> +{
> +	console_iter_no_check(dom, console_unmap_interface);
> +}
> +
> +static int bind_event_channel(struct domain *dom,
> +							  int new_rport,
> +							  int *lport,
> +							  int *rport)
> +{
> +	int err = 0, rc;
> +
> +	/* Go no further if port has not changed and we are still bound. */
> +	if (new_rport == *rport) {
> +		xc_evtchn_status_t status = {
> +		.dom = DOMID_SELF,
> +		.port = *lport };
> +		if ((xc_evtchn_status(xc, &status) == 0) &&
> +			(status.status == EVTCHNSTAT_interdomain))
> +			goto out;
> +	}
> +
> +	*lport = -1;
> +	*rport = -1;
> +	rc = xenevtchn_bind_interdomain(dom->xce_handle,
> +									dom->domid, new_rport);
> +
> +	if (rc == -1) {
> +		err = errno;
> +		xenevtchn_close(dom->xce_handle);
> +		dom->xce_handle = NULL;
> +		goto out;
> +	}
> +
> +	*lport = rc;
> +	*rport = new_rport;
> +out:
> +	return err;
>  }
>   
>  static int domain_create_ring(struct domain *dom)
>  {
> -	int err, remote_port, ring_ref, rc;
> +	int err, remote_port, ring_ref, vuart_remote_port, vuart_ring_ref;
>  	char *type, path[PATH_MAX];
> +	struct console *pv_con = &dom->console[CONSOLE_TYPE_PV];
> +	struct console *vuart_con = &dom->console[CONSOLE_TYPE_VUART];
>  
>  	err = xs_gather(xs, dom->conspath,
>  			"ring-ref", "%u", &ring_ref,
> @@ -541,6 +671,17 @@ static int domain_create_ring(struct domain *dom)
>  	if (err)
>  		goto out;
>  
> +	/* vuart is optional. */
> +	err = xs_gather(xs, dom->conspath,
> +					"vuart/0/ring-ref", "%u", &vuart_ring_ref,
> +					"vuart/0/port", "%i", &vuart_remote_port,
> +					NULL);
> +	if (err)
> +	{
> +		vuart_remote_port = -1;
> +		vuart_ring_ref = -1;
> +	}
> +
>  	snprintf(path, sizeof(path), "%s/type", dom->conspath);
>  	type = xs_read(xs, XBT_NULL, path, NULL);
>  	if (type && strcmp(type, "xenconsoled") != 0) {
> @@ -550,41 +691,50 @@ static int domain_create_ring(struct domain *dom)
>  	free(type);
>  
>  	/* If using ring_ref and it has changed, remap */
> -	if (ring_ref != dom->ring_ref && dom->ring_ref != -1)
> -		domain_unmap_interface(dom);
> +	if (ring_ref != pv_con->ring_ref && pv_con->ring_ref != -1)
> +		console_unmap_interface(pv_con);
>  
> -	if (!dom->interface && xgt_handle) {
> +	/* If using vuart ring_ref and it has changed, remap */
> +	if (vuart_ring_ref != vuart_con->ring_ref &&
> +		vuart_con->ring_ref != -1 )
> +		console_unmap_interface(vuart_con);
> +
> +	if (!pv_con->interface && xgt_handle) {
>  		/* Prefer using grant table */
> -		dom->interface = xengnttab_map_grant_ref(xgt_handle,
> -			dom->domid, GNTTAB_RESERVED_CONSOLE,
> -			PROT_READ|PROT_WRITE);
> -		dom->ring_ref = -1;
> +		pv_con->interface = xengnttab_map_grant_ref(xgt_handle,
> +													dom->domid, GNTTAB_RESERVED_CONSOLE,
> +													PROT_READ|PROT_WRITE);
> +		pv_con->ring_ref = -1;
>  	}
> -	if (!dom->interface) {
> +	if (!pv_con->interface) {
>  		/* Fall back to xc_map_foreign_range */
> -		dom->interface = xc_map_foreign_range(
> +		pv_con->interface = xc_map_foreign_range(
>  			xc, dom->domid, XC_PAGE_SIZE,
>  			PROT_READ|PROT_WRITE,
>  			(unsigned long)ring_ref);
> -		if (dom->interface == NULL) {
> +		if (pv_con->interface == NULL) {
>  			err = EINVAL;
>  			goto out;
>  		}
> -		dom->ring_ref = ring_ref;
> +		pv_con->ring_ref = ring_ref;
>  	}
>  
> -	/* Go no further if port has not changed and we are still bound. */
> -	if (remote_port == dom->remote_port) {
> -		xc_evtchn_status_t status = {
> -			.dom = DOMID_SELF,
> -			.port = dom->local_port };
> -		if ((xc_evtchn_status(xc, &status) == 0) &&
> -		    (status.status == EVTCHNSTAT_interdomain))
> -			goto out;
> +	/* Map vuart console ring buffer. */
> +	if ((vuart_remote_port != -1) && !vuart_con->interface) {
> +
> +		vuart_con->interface = xc_map_foreign_range(xc,
> +													dom->domid,
> +													XC_PAGE_SIZE,
> +													PROT_READ|PROT_WRITE,
> +													(unsigned long)vuart_ring_ref);
> +
> +		if (vuart_con->interface == NULL) {
> +			err = EINVAL;
> +			goto out1;
> +		}
> +		vuart_con->ring_ref = vuart_ring_ref;
>  	}
>  
> -	dom->local_port = -1;
> -	dom->remote_port = -1;
>  	if (dom->xce_handle != NULL)
>  		xenevtchn_close(dom->xce_handle);
>  
> @@ -593,35 +743,55 @@ static int domain_create_ring(struct domain *dom)
>  	dom->xce_handle = xenevtchn_open(NULL, 0);
>  	if (dom->xce_handle == NULL) {
>  		err = errno;
> -		goto out;
> +		goto out2;
>  	}
>   
> -	rc = xenevtchn_bind_interdomain(dom->xce_handle,
> -		dom->domid, remote_port);
> -
> -	if (rc == -1) {
> -		err = errno;
> +	err = bind_event_channel(dom, remote_port,
> +							 &pv_con->local_port,
> +							 &pv_con->remote_port);
> +	if (err)
> +	{
>  		xenevtchn_close(dom->xce_handle);
> -		dom->xce_handle = NULL;
> -		goto out;
> +		goto out2;
> +	}
> +
> +	if (vuart_remote_port != -1)
> +	{
> +		err = bind_event_channel(dom, vuart_remote_port,
> +								 &vuart_con->local_port,
> +								 &vuart_con->remote_port);
> +		if (err)
> +		{
> +			xenevtchn_close(dom->xce_handle);
> +			goto out2;
> +		}
>  	}
> -	dom->local_port = rc;
> -	dom->remote_port = remote_port;
>  
> -	if (dom->master_fd == -1) {
> +	if (pv_con->master_fd == -1) {
>  		if (!domain_create_tty(dom)) {
>  			err = errno;
>  			xenevtchn_close(dom->xce_handle);
>  			dom->xce_handle = NULL;
> -			dom->local_port = -1;
> -			dom->remote_port = -1;
> -			goto out;
> +			pv_con->local_port = -1;
> +			pv_con->remote_port = -1;
> +			vuart_con->local_port = -1;
> +			vuart_con->remote_port = -1;
> +			goto out2;
>  		}
>  	}
>  
> -	if (log_guest && (dom->log_fd == -1))
> -		dom->log_fd = create_domain_log(dom);
> +	if (log_guest && (pv_con->log_fd == -1))
> +		pv_con->log_fd = create_console_log(pv_con);
> +
> +	if (log_guest && (vuart_remote_port != -1) && (vuart_con->log_fd == -1))
> +		vuart_con->log_fd = create_console_log(vuart_con);
>  
> +	return err;
> +
> + out2:
> +	console_unmap_interface(vuart_con);
> + out1:
> +	console_unmap_interface(pv_con);
>   out:
>  	return err;
>  }
> @@ -645,6 +815,19 @@ static bool watch_domain(struct domain *dom, bool watch)
>  	return success;
>  }
>  
> +static void console_init(struct domain *d, struct console *con, char *name, char *ttyname)
> +{
> +	con->master_fd = -1;
> +	con->master_pollfd_idx = -1;
> +	con->slave_fd = -1;
> +	con->log_fd = -1;
> +	con->ring_ref = -1;
> +	con->local_port = -1;
> +	con->remote_port = -1;
> +	con->name = name;
> +	con->ttyname = ttyname;
> +	con->d = d;
> +}
>  
>  static struct domain *create_domain(int domid)
>  {
> @@ -675,18 +858,13 @@ static struct domain *create_domain(int domid)
>  	dom->conspath = s;
>  	strcat(dom->conspath, "/console");
>  
> -	dom->master_fd = -1;
> -	dom->master_pollfd_idx = -1;
> -	dom->slave_fd = -1;
> -	dom->log_fd = -1;
> +	console_init(dom, &dom->console[CONSOLE_TYPE_PV], "pv", "tty");
> +	console_init(dom, &dom->console[CONSOLE_TYPE_VUART], "vuart", "vtty");
> +
>  	dom->xce_pollfd_idx = -1;
>  
>  	dom->next_period = ((long long)ts.tv_sec * 1000) + (ts.tv_nsec / 1000000) + RATE_LIMIT_PERIOD;
>  
> -	dom->ring_ref = -1;
> -	dom->local_port = -1;
> -	dom->remote_port = -1;
> -
>  	if (!watch_domain(dom, true))
>  		goto out;
>  
> @@ -727,17 +905,22 @@ static void remove_domain(struct domain *dom)
>  	}
>  }
>  
> +
> +static void console_cleanup(struct console *con)
> +{
> +	if (con->log_fd != -1) {
> +		close(con->log_fd);
> +		con->log_fd = -1;
> +	}
> +	free(con->buffer.data);
> +	con->buffer.data = NULL;
> +}
> +
>  static void cleanup_domain(struct domain *d)
>  {
>  	domain_close_tty(d);
>  
> -	if (d->log_fd != -1) {
> -		close(d->log_fd);
> -		d->log_fd = -1;
> -	}
> -
> -	free(d->buffer.data);
> -	d->buffer.data = NULL;
> +	console_iter_no_check(d, console_cleanup);
>  
>  	free(d->conspath);
>  	d->conspath = NULL;
> @@ -749,7 +932,9 @@ static void shutdown_domain(struct domain *d)
>  {
>  	d->is_dead = true;
>  	watch_domain(d, false);
> +
>  	domain_unmap_interface(d);
> +

Spurious changes


>  	if (d->xce_handle != NULL)
>  		xenevtchn_close(d->xce_handle);
>  	d->xce_handle = NULL;
> @@ -780,9 +965,9 @@ static void enum_domains(void)
>  	}
>  }
>  
> -static int ring_free_bytes(struct domain *dom)
> +static int ring_free_bytes(struct console *con)
>  {
> -	struct xencons_interface *intf = dom->interface;
> +	struct xencons_interface *intf = con->interface;
>  	XENCONS_RING_IDX cons, prod, space;
>  
>  	cons = intf->in_cons;
> @@ -807,25 +992,27 @@ static void domain_handle_broken_tty(struct domain *dom, int recreate)
>  	}
>  }
>  
> -static void handle_tty_read(struct domain *dom)
> +static void handle_tty_read(struct console *con)
>  {
>  	ssize_t len = 0;
>  	char msg[80];
>  	int i;
> -	struct xencons_interface *intf = dom->interface;
>  	XENCONS_RING_IDX prod;
> +	struct xencons_interface *intf = con->interface;
> +	xenevtchn_port_or_error_t port = con->local_port;
> +	struct domain *dom = con->d;
>  
>  	if (dom->is_dead)
>  		return;
>  
> -	len = ring_free_bytes(dom);
> +	len = ring_free_bytes(con);
>  	if (len == 0)
>  		return;
>  
>  	if (len > sizeof(msg))
>  		len = sizeof(msg);
>  
> -	len = read(dom->master_fd, msg, len);
> +	len = read(con->master_fd, msg, len);
>  	/*
>  	 * Note: on Solaris, len == 0 means the slave closed, and this
>  	 * is no problem, but Linux can't handle this usefully, so we
> @@ -841,34 +1028,44 @@ static void handle_tty_read(struct domain *dom)
>  		}
>  		xen_wmb();
>  		intf->in_prod = prod;
> -		xenevtchn_notify(dom->xce_handle, dom->local_port);
> +		xenevtchn_notify(dom->xce_handle, port);
>  	} else {
>  		domain_close_tty(dom);
>  		shutdown_domain(dom);
>  	}
>  }
>  
> -static void handle_tty_write(struct domain *dom)
> +static void handle_tty_write(struct console *con)
>  {
>  	ssize_t len;
> +	struct domain *dom = con->d;
>  
>  	if (dom->is_dead)
>  		return;
>  
> -	len = write(dom->master_fd, dom->buffer.data + dom->buffer.consumed,
> -		    dom->buffer.size - dom->buffer.consumed);
> +	len = write(con->master_fd,
> +				con->buffer.data + con->buffer.consumed,
> +				con->buffer.size - con->buffer.consumed);
>   	if (len < 1) {
>  		dolog(LOG_DEBUG, "Write failed on domain %d: %zd, %d\n",
>  		      dom->domid, len, errno);
>  		domain_handle_broken_tty(dom, domain_is_valid(dom->domid));
>  	} else {
> -		buffer_advance(&dom->buffer, len);
> +		buffer_advance(&con->buffer, len);
>  	}
>  }
>  
> +static void console_event_unmask(struct console *con)
> +{
> +	if (con->local_port != -1)
> +		(void)xenevtchn_unmask(con->d->xce_handle, con->local_port);
> +}
> +
>  static void handle_ring_read(struct domain *dom)
>  {
>  	xenevtchn_port_or_error_t port;
> +	struct console *pv_con = &dom->console[CONSOLE_TYPE_PV];
> +	struct console *vuart_con = &dom->console[CONSOLE_TYPE_VUART];
>  
>  	if (dom->is_dead)
>  		return;
> @@ -878,10 +1075,13 @@ static void handle_ring_read(struct domain *dom)
>  
>  	dom->event_count++;
>  
> -	buffer_append(dom);
> +	if (port == vuart_con->local_port)
> +		buffer_append(vuart_con);
> +	else
> +		buffer_append(pv_con);

I would do it with a loop, without hardcoding the check:

for (i = 0; i < max_console; i++) {
    if (dom->console[i].local_port == port)
        buffer_append(&dom->console[i]);
}

  
>  	if (dom->event_count < RATE_LIMIT_ALLOWANCE)
> -		(void)xenevtchn_unmask(dom->xce_handle, port);
> +		console_iter_no_check(dom, console_event_unmask);
>  }
>
>  static void handle_xs(void)
> @@ -943,14 +1143,22 @@ static void handle_hv_logs(xenevtchn_handle *xce_handle, bool force)
>  		(void)xenevtchn_unmask(xce_handle, port);
>  }
>  
> +static void console_open_log(struct console *con)
> +{
> +	if (console_enabled(con))
> +	{
> +		if (con->log_fd != -1)
> +			close(con->log_fd);
> +		con->log_fd = create_console_log(con);
> +	}
> +}
> +
>  static void handle_log_reload(void)
>  {
>  	if (log_guest) {
>  		struct domain *d;
>  		for (d = dom_head; d; d = d->next) {
> -			if (d->log_fd != -1)
> -				close(d->log_fd);
> -			d->log_fd = create_domain_log(d);
> +			console_iter_no_check(d, console_open_log);
>  		}
>  	}
>  
> @@ -1002,6 +1210,40 @@ static void reset_fds(void)
>  		memset(fds, 0, sizeof(struct pollfd) * current_array_size);
>  }
>  
> +static void add_console_fd(struct console *con)
> +{
> +	if (con->master_fd != -1) {
> +		short events = 0;
> +		if (!con->d->is_dead && ring_free_bytes(con))
> +			events |= POLLIN;
> +
> +		if (!buffer_empty(&con->buffer))
> +			events |= POLLOUT;
> +
> +		if (events)
> +			con->master_pollfd_idx =
> +				set_fds(con->master_fd, events|POLLPRI);
> +	}
> +}
> +
> +static void process_console(struct console *con)
> +{
> +	if (con->master_fd != -1 && con->master_pollfd_idx != -1) {
> +		if (fds[con->master_pollfd_idx].revents &
> +			~(POLLIN|POLLOUT|POLLPRI))
> +			domain_handle_broken_tty(con->d, domain_is_valid(con->d->domid));
> +		else {
> +			if (fds[con->master_pollfd_idx].revents &
> +				POLLIN)
> +				handle_tty_read(con);
> +			if (fds[con->master_pollfd_idx].revents &
> +				POLLOUT)
> +				handle_tty_write(con);
> +		}
> +	}
> +	con->master_pollfd_idx = -1;
> +}
> +
>  void handle_io(void)
>  {
>  	int ret;
> @@ -1068,7 +1310,7 @@ void handle_io(void)
>  			if ((now+5) > d->next_period) {
>  				d->next_period = now + RATE_LIMIT_PERIOD;
>  				if (d->event_count >= RATE_LIMIT_ALLOWANCE) {
> -					(void)xenevtchn_unmask(d->xce_handle, d->local_port);
> +					console_iter_no_check(d, console_event_unmask);
>  				}
>  				d->event_count = 0;
>  			}
> @@ -1081,28 +1323,15 @@ void handle_io(void)
>  				    d->next_period < next_timeout)
>  					next_timeout = d->next_period;
>  			} else if (d->xce_handle != NULL) {
> -				if (discard_overflowed_data ||
> -				    !d->buffer.max_capacity ||
> -				    d->buffer.size < d->buffer.max_capacity) {
> +				if (console_iter_bool_check(d, buffer_available))
> +				{
>  					int evtchn_fd = xenevtchn_fd(d->xce_handle);
>  					d->xce_pollfd_idx = set_fds(evtchn_fd,
> -								    POLLIN|POLLPRI);
> +												POLLIN|POLLPRI);
>  				}
>  			}
>  
> -			if (d->master_fd != -1) {
> -				short events = 0;
> -				if (!d->is_dead && ring_free_bytes(d))
> -					events |= POLLIN;
> -
> -				if (!buffer_empty(&d->buffer))
> -					events |= POLLOUT;
> -
> -				if (events)
> -					d->master_pollfd_idx =
> -						set_fds(d->master_fd,
> -							events|POLLPRI);
> -			}
> +			console_iter_no_check(d, add_console_fd);
>  		}
>  
>  		/* If any domain has been rate limited, we need to work
> @@ -1170,22 +1399,9 @@ void handle_io(void)
>  				    handle_ring_read(d);
>  			}
>  
> -			if (d->master_fd != -1 && d->master_pollfd_idx != -1) {
> -				if (fds[d->master_pollfd_idx].revents &
> -				    ~(POLLIN|POLLOUT|POLLPRI))
> -					domain_handle_broken_tty(d,
> -						   domain_is_valid(d->domid));
> -				else {
> -					if (fds[d->master_pollfd_idx].revents &
> -					    POLLIN)
> -						handle_tty_read(d);
> -					if (fds[d->master_pollfd_idx].revents &
> -					    POLLOUT)
> -						handle_tty_write(d);
> -				}
> -			}
> +			console_iter_no_check(d, process_console);
>  
> -			d->xce_pollfd_idx = d->master_pollfd_idx = -1;
> +			d->xce_pollfd_idx = -1;
>  
>  			if (d->last_seen != enum_pass)
>  				shutdown_domain(d);
> -- 
> 2.7.4
> 

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

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

* Re: [PATCH 06/10 v2] xen/arm: vpl011: Add vuart ring-buf and evtchn to xenstore
  2017-04-28 21:57   ` Stefano Stabellini
@ 2017-05-01 11:21     ` Bhupinder Thakur
  2017-05-01 17:56       ` Stefano Stabellini
  0 siblings, 1 reply; 54+ messages in thread
From: Bhupinder Thakur @ 2017-05-01 11:21 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Wei Liu, Andrew Cooper, Ian Jackson, Julien Grall, Jan Beulich,
	xen-devel

Hi Stefano,

>> diff --git a/tools/libxl/libxl_console.c b/tools/libxl/libxl_console.c
>> index 446e766..ef3bd44 100644
>> --- a/tools/libxl/libxl_console.c
>> +++ b/tools/libxl/libxl_console.c
>> @@ -67,6 +67,9 @@ int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num,
>>      case LIBXL_CONSOLE_TYPE_SERIAL:
>>          cons_type_s = "serial";
>>          break;
>> +    case LIBXL_CONSOLE_TYPE_VUART:
>> +        cons_type_s = "vuart";
>> +        break;
>>      default:
>>          goto out;
>>      }
>> @@ -326,6 +329,13 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
>>          flexarray_append(ro_front, GCSPRINTF("%"PRIu32, state->console_port));
>>          flexarray_append(ro_front, "ring-ref");
>>          flexarray_append(ro_front, GCSPRINTF("%lu", state->console_mfn));
>> +        if (state->vuart_enabled)
>> +        {
>> +            flexarray_append(ro_front, "vuart/0/port");
>> +            flexarray_append(ro_front, GCSPRINTF("%"PRIu32, state->vuart_port));
>> +            flexarray_append(ro_front, "vuart/0/ring-ref");
>> +            flexarray_append(ro_front, GCSPRINTF("%lu", state->vuart_mfn));
>> +        }
>
> It looks like you are reusing the libxl__device_console_add call for the
> main PV console for the domain, to also add the vuart nodes to xenstore.
>
> I don't think it is a good idea to mix the two. I suggest to introduce a
> new libxl__device call to introduce the vuart nodes to xenstore, given
> that they have no relantionship with the principal PV console of the
> domain.
>
I have a doubt here. Do I have to create a new console device
(libxl__device) to register the vuart console or can I use the
existing console device (which is used for registering the primary
console) to register the vuart nodes to xenstore?

I suspect that if I try to register with the same console device then
libxl__device_generic_add() may fail as it is already added.

>
>>      } else {
>>          flexarray_append(front, "state");
>>          flexarray_append(front, GCSPRINTF("%d", XenbusStateInitialising));
>> diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
>> index 5d914a5..06ff3b7 100644
>> --- a/tools/libxl/libxl_dom.c
>> +++ b/tools/libxl/libxl_dom.c
>> @@ -434,6 +434,9 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
>>      state->store_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->store_domid);
>>      state->console_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->console_domid);
>>
>> +    if (state->vuart_enabled)
>> +        xc_domain_vuart_get_evtchn(ctx->xch, domid, &state->vuart_port);
>> +
>>      if (info->type == LIBXL_DOMAIN_TYPE_HVM) {
>>          hvm_set_conf_params(ctx->xch, domid, info);
>>  #if defined(__i386__) || defined(__x86_64__)
>> @@ -788,6 +791,7 @@ int libxl__build_pv(libxl__gc *gc, uint32_t domid,
>>      if (xc_dom_translated(dom)) {
>>          state->console_mfn = dom->console_pfn;
>>          state->store_mfn = dom->xenstore_pfn;
>> +        state->vuart_mfn = dom->vuart_pfn;
>>      } else {
>>          state->console_mfn = xc_dom_p2m(dom, dom->console_pfn);
>>          state->store_mfn = xc_dom_p2m(dom, dom->xenstore_pfn);
>
> These two changes to libxl_dom.c probably belong to patch #4
Ok. I will move these changes to the patch#4.

Regards,
Bhupinder

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

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

* Re: [PATCH 06/10 v2] xen/arm: vpl011: Add vuart ring-buf and evtchn to xenstore
  2017-05-01 11:21     ` Bhupinder Thakur
@ 2017-05-01 17:56       ` Stefano Stabellini
  2017-05-03 11:00         ` Bhupinder Thakur
  0 siblings, 1 reply; 54+ messages in thread
From: Stefano Stabellini @ 2017-05-01 17:56 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich, xen-devel

On Mon, 1 May 2017, Bhupinder Thakur wrote:
> Hi Stefano,
> 
> >> diff --git a/tools/libxl/libxl_console.c b/tools/libxl/libxl_console.c
> >> index 446e766..ef3bd44 100644
> >> --- a/tools/libxl/libxl_console.c
> >> +++ b/tools/libxl/libxl_console.c
> >> @@ -67,6 +67,9 @@ int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num,
> >>      case LIBXL_CONSOLE_TYPE_SERIAL:
> >>          cons_type_s = "serial";
> >>          break;
> >> +    case LIBXL_CONSOLE_TYPE_VUART:
> >> +        cons_type_s = "vuart";
> >> +        break;
> >>      default:
> >>          goto out;
> >>      }
> >> @@ -326,6 +329,13 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
> >>          flexarray_append(ro_front, GCSPRINTF("%"PRIu32, state->console_port));
> >>          flexarray_append(ro_front, "ring-ref");
> >>          flexarray_append(ro_front, GCSPRINTF("%lu", state->console_mfn));
> >> +        if (state->vuart_enabled)
> >> +        {
> >> +            flexarray_append(ro_front, "vuart/0/port");
> >> +            flexarray_append(ro_front, GCSPRINTF("%"PRIu32, state->vuart_port));
> >> +            flexarray_append(ro_front, "vuart/0/ring-ref");
> >> +            flexarray_append(ro_front, GCSPRINTF("%lu", state->vuart_mfn));
> >> +        }
> >
> > It looks like you are reusing the libxl__device_console_add call for the
> > main PV console for the domain, to also add the vuart nodes to xenstore.
> >
> > I don't think it is a good idea to mix the two. I suggest to introduce a
> > new libxl__device call to introduce the vuart nodes to xenstore, given
> > that they have no relantionship with the principal PV console of the
> > domain.
> >
> I have a doubt here. Do I have to create a new console device
> (libxl__device) to register the vuart console or can I use the
> existing console device (which is used for registering the primary
> console) to register the vuart nodes to xenstore?
> 
> I suspect that if I try to register with the same console device then
> libxl__device_generic_add() may fail as it is already added.

The vuart we are introducing with this patch series is a new and
different console from the existing PV console. So yes, I think we need
to create a new device for it.

We either need to introduce a brand new function to add the vuart to
xenstore, something like libxl__device_vuart_add, or, if we are going
to reuse libxl__device_console_add, then we we need to create both a new
console device (libxl__device_console), and a new libxl__device for it.
For clarity, libxl__device_console is the input parameter of
libxl__device_console_add, while libxl__device is the output parameter.


> >>      } else {
> >>          flexarray_append(front, "state");
> >>          flexarray_append(front, GCSPRINTF("%d", XenbusStateInitialising));
> >> diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
> >> index 5d914a5..06ff3b7 100644
> >> --- a/tools/libxl/libxl_dom.c
> >> +++ b/tools/libxl/libxl_dom.c
> >> @@ -434,6 +434,9 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
> >>      state->store_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->store_domid);
> >>      state->console_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->console_domid);
> >>
> >> +    if (state->vuart_enabled)
> >> +        xc_domain_vuart_get_evtchn(ctx->xch, domid, &state->vuart_port);
> >> +
> >>      if (info->type == LIBXL_DOMAIN_TYPE_HVM) {
> >>          hvm_set_conf_params(ctx->xch, domid, info);
> >>  #if defined(__i386__) || defined(__x86_64__)
> >> @@ -788,6 +791,7 @@ int libxl__build_pv(libxl__gc *gc, uint32_t domid,
> >>      if (xc_dom_translated(dom)) {
> >>          state->console_mfn = dom->console_pfn;
> >>          state->store_mfn = dom->xenstore_pfn;
> >> +        state->vuart_mfn = dom->vuart_pfn;
> >>      } else {
> >>          state->console_mfn = xc_dom_p2m(dom, dom->console_pfn);
> >>          state->store_mfn = xc_dom_p2m(dom, dom->xenstore_pfn);
> >
> > These two changes to libxl_dom.c probably belong to patch #4
> Ok. I will move these changes to the patch#4.
> 
> Regards,
> Bhupinder
> 

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

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

* Re: [PATCH 01/10 v2] xen/arm: vpl011: Add pl011 uart emulation in Xen
  2017-04-28 16:01 ` [PATCH 01/10 v2] xen/arm: vpl011: Add pl011 uart emulation " Bhupinder Thakur
  2017-04-28 19:08   ` Stefano Stabellini
@ 2017-05-02  7:34   ` Jan Beulich
  2017-05-02 16:02   ` Julien Grall
  2 siblings, 0 replies; 54+ messages in thread
From: Jan Beulich @ 2017-05-02  7:34 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, xen-devel

>>> On 28.04.17 at 18:01, <bhupinder.thakur@linaro.org> wrote:
>  xen/arch/arm/Kconfig             |   5 +
>  xen/arch/arm/Makefile            |   1 +
>  xen/arch/arm/vpl011.c            | 340 +++++++++++++++++++++++++++++++++++++++
>  xen/include/asm-arm/domain.h     |   3 +
>  xen/include/asm-arm/pl011-uart.h |   2 +
>  xen/include/public/arch-arm.h    |   8 +
>  xen/include/xen/vpl011.h         |  74 +++++++++
>  7 files changed, 433 insertions(+)
>  create mode 100644 xen/arch/arm/vpl011.c
>  create mode 100644 xen/include/xen/vpl011.h

Considering the implementation is ARM specific (as is pl011 itself)
I consider the header file misplaced - it ought to go under arch-arm/.

With that (and this also applies to other patches in this series)
please make sure you copy all involved maintainers _for a
particular patch_, but not all involved for some patch somewhere
in the series (i.e. you want to have per-patch Cc lists, not a single
one for the entire series).

Jan


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

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

* Re: [PATCH 02/10 v2] xen/arm: vpl011: Add new vuart domctl interface to setup pfn and evtchn
  2017-04-28 19:23   ` Stefano Stabellini
@ 2017-05-02  7:39     ` Jan Beulich
  2017-05-02  9:47       ` Bhupinder Thakur
  0 siblings, 1 reply; 54+ messages in thread
From: Jan Beulich @ 2017-05-02  7:39 UTC (permalink / raw)
  To: Stefano Stabellini, Bhupinder Thakur
  Cc: Andrew Cooper, Julien Grall, Wei Liu, Ian Jackson, xen-devel

>>> On 28.04.17 at 21:23, <sstabellini@kernel.org> wrote:
> On Fri, 28 Apr 2017, Bhupinder Thakur wrote:
>> --- a/xen/include/public/domctl.h
>> +++ b/xen/include/public/domctl.h
>> @@ -1138,6 +1138,15 @@ struct xen_domctl_psr_cat_op {
>>      uint32_t target;    /* IN */
>>      uint64_t data;      /* IN/OUT */
>>  };
>> +
>> +struct xen_domctl_vuart_op {
>> +#define XEN_DOMCTL_VUART_OP_SET_PFN      0
>> +#define XEN_DOMCTL_VUART_OP_GET_EVTCHN   1
>> +        uint32_t cmd;       /* XEN_DOMCTL_VUART_OP_* */
>> +        uint32_t pfn;       /* IN */
> 
> xen_pfn_t

And "pfn" is likely the wrong name: Do you mean an MFN or a GFN?

>> +        uint32_t evtchn;    /* OUT */
> 
> evtchn_port_t

Plus considering their fully separate use, the two should form a
union imo.

Jan


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

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

* Re: [PATCH 02/10 v2] xen/arm: vpl011: Add new vuart domctl interface to setup pfn and evtchn
  2017-04-28 16:01 ` [PATCH 02/10 v2] xen/arm: vpl011: Add new vuart domctl interface to setup pfn and evtchn Bhupinder Thakur
  2017-04-28 19:23   ` Stefano Stabellini
@ 2017-05-02  7:47   ` Jan Beulich
  2017-05-02  9:58     ` Bhupinder Thakur
  2017-05-03 10:14   ` Julien Grall
  2 siblings, 1 reply; 54+ messages in thread
From: Jan Beulich @ 2017-05-02  7:47 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, xen-devel

>>> On 28.04.17 at 18:01, <bhupinder.thakur@linaro.org> wrote:
> --- a/xen/arch/x86/domctl.c
> +++ b/xen/arch/x86/domctl.c
> @@ -1465,6 +1465,10 @@ long arch_do_domctl(
>          recalculate_cpuid_policy(d);
>          break;
>  
> +    case XEN_DOMCTL_vuart_op:
> +        ret = -EOPNOTSUPP;
> +        break;

There should be no need for such an addition.

Jan


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

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

* Re: [PATCH 03/10 v2] xen/arm: vpl011: Enable pl011 emulation for a guest domain in Xen
  2017-04-28 16:01 ` [PATCH 03/10 v2] xen/arm: vpl011: Enable pl011 emulation for a guest domain in Xen Bhupinder Thakur
  2017-04-28 19:15   ` Stefano Stabellini
@ 2017-05-02  7:48   ` Jan Beulich
  2017-05-02 15:20     ` Bhupinder Thakur
  1 sibling, 1 reply; 54+ messages in thread
From: Jan Beulich @ 2017-05-02  7:48 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, xen-devel

>>> On 28.04.17 at 18:01, <bhupinder.thakur@linaro.org> wrote:
> @@ -631,6 +632,9 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags,
>      if ( (rc = domain_vtimer_init(d, config)) != 0 )
>          goto fail;
>  
> +    if ( domcr_flags & DOMCRF_vuart )
> +        if ( (rc = domain_vpl011_init(d, config)) != 0 )
> +            goto fail;
>      update_domain_wallclock_time(d);

This is ARM code, so my opinion may not mean much, but why two
if()s instead of one, and why no blank line after your addition?

> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -63,6 +63,8 @@ struct xen_domctl_createdomain {
>   /* Is this a xenstore domain? */
>  #define _XEN_DOMCTL_CDF_xs_domain     4
>  #define XEN_DOMCTL_CDF_xs_domain      (1U<<_XEN_DOMCTL_CDF_xs_domain)
> +#define _XEN_DOMCTL_VUART_enable      6
> +#define XEN_DOMCTL_VUART_enable       (1U<<_XEN_DOMCTL_VUART_enable)

As expressed before, I object to this addition, as doing things this
way does not scale. I don't think I've seen any proper reply to my
previous objection, and the patch description here certainly does
not justify why an exception should be made in this case. As a
side note, why bit 6 instead of the first available one (5)?

Jan


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

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

* Re: [PATCH 02/10 v2] xen/arm: vpl011: Add new vuart domctl interface to setup pfn and evtchn
  2017-05-02  7:39     ` Jan Beulich
@ 2017-05-02  9:47       ` Bhupinder Thakur
  0 siblings, 0 replies; 54+ messages in thread
From: Bhupinder Thakur @ 2017-05-02  9:47 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, xen-devel

Hi Jan,

On 2 May 2017 at 13:09, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 28.04.17 at 21:23, <sstabellini@kernel.org> wrote:
>> On Fri, 28 Apr 2017, Bhupinder Thakur wrote:
>>> --- a/xen/include/public/domctl.h
>>> +++ b/xen/include/public/domctl.h
>>> @@ -1138,6 +1138,15 @@ struct xen_domctl_psr_cat_op {
>>>      uint32_t target;    /* IN */
>>>      uint64_t data;      /* IN/OUT */
>>>  };
>>> +
>>> +struct xen_domctl_vuart_op {
>>> +#define XEN_DOMCTL_VUART_OP_SET_PFN      0
>>> +#define XEN_DOMCTL_VUART_OP_GET_EVTCHN   1
>>> +        uint32_t cmd;       /* XEN_DOMCTL_VUART_OP_* */
>>> +        uint32_t pfn;       /* IN */
>>
>> xen_pfn_t
>
> And "pfn" is likely the wrong name: Do you mean an MFN or a GFN?
I will rename it to GFN.

>
>>> +        uint32_t evtchn;    /* OUT */
>>
>> evtchn_port_t
>
> Plus considering their fully separate use, the two should form a
> union imo.
Yes. I will define a union of the two.

Regards,
Bhupinder

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

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

* Re: [PATCH 02/10 v2] xen/arm: vpl011: Add new vuart domctl interface to setup pfn and evtchn
  2017-05-02  7:47   ` Jan Beulich
@ 2017-05-02  9:58     ` Bhupinder Thakur
  2017-05-02 11:22       ` Jan Beulich
  0 siblings, 1 reply; 54+ messages in thread
From: Bhupinder Thakur @ 2017-05-02  9:58 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, xen-devel

Hi Jan,

>> +    case XEN_DOMCTL_vuart_op:
>> +        ret = -EOPNOTSUPP;
>> +        break;
>
> There should be no need for such an addition.

This check was added to return a failure if user tries to call the
vuart domctl in case of x86 (wrong user configuration). If this check
is not there will it not end up calling the default case:
iommu_do_domctl()?

Regards,
Bhupinder

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

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

* Re: [PATCH 02/10 v2] xen/arm: vpl011: Add new vuart domctl interface to setup pfn and evtchn
  2017-05-02  9:58     ` Bhupinder Thakur
@ 2017-05-02 11:22       ` Jan Beulich
  0 siblings, 0 replies; 54+ messages in thread
From: Jan Beulich @ 2017-05-02 11:22 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, xen-devel

>>> On 02.05.17 at 11:58, <bhupinder.thakur@linaro.org> wrote:
>>> +    case XEN_DOMCTL_vuart_op:
>>> +        ret = -EOPNOTSUPP;
>>> +        break;
>>
>> There should be no need for such an addition.
> 
> This check was added to return a failure if user tries to call the
> vuart domctl in case of x86 (wrong user configuration). If this check
> is not there will it not end up calling the default case:
> iommu_do_domctl()?

Yes, it will, like for any other unknown/unsupported domctls. The
function is prepared to deal with that.

Jan


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

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

* Re: [PATCH 03/10 v2] xen/arm: vpl011: Enable pl011 emulation for a guest domain in Xen
  2017-05-02  7:48   ` Jan Beulich
@ 2017-05-02 15:20     ` Bhupinder Thakur
  2017-05-02 15:23       ` Julien Grall
  0 siblings, 1 reply; 54+ messages in thread
From: Bhupinder Thakur @ 2017-05-02 15:20 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, xen-devel

Hi Jan,

>> @@ -631,6 +632,9 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags,
>>      if ( (rc = domain_vtimer_init(d, config)) != 0 )
>>          goto fail;
>>
>> +    if ( domcr_flags & DOMCRF_vuart )
>> +        if ( (rc = domain_vpl011_init(d, config)) != 0 )
>> +            goto fail;
>>      update_domain_wallclock_time(d);
>
I am planning to remove the usage of domain creation flag to check
whether vuart is enabled/disabled. Please see my next comment. With
that change, domain_vpl011_init() will be called always. The
domain_vpl011_init() will check whether vuart is enabled or disabled
in the config structure passed. If vuart is enabled then it will go
ahead with vpl011 initialization else it will return without
initializing vpl011.

> This is ARM code, so my opinion may not mean much, but why two
> if()s instead of one, and why no blank line after your addition?
>
>> --- a/xen/include/public/domctl.h
>> +++ b/xen/include/public/domctl.h
>> @@ -63,6 +63,8 @@ struct xen_domctl_createdomain {
>>   /* Is this a xenstore domain? */
>>  #define _XEN_DOMCTL_CDF_xs_domain     4
>>  #define XEN_DOMCTL_CDF_xs_domain      (1U<<_XEN_DOMCTL_CDF_xs_domain)
>> +#define _XEN_DOMCTL_VUART_enable      6
>> +#define XEN_DOMCTL_VUART_enable       (1U<<_XEN_DOMCTL_VUART_enable)
>
> As expressed before, I object to this addition, as doing things this
> way does not scale. I don't think I've seen any proper reply to my
> previous objection, and the patch description here certainly does
> not justify why an exception should be made in this case. As a
> side note, why bit 6 instead of the first available one (5)?
>
Sorry I missed to address this review comment. I will pass the vuart
enable/disable information through the configuration structure
xc_domain_configuration_t, which is passed transparently to
domain_vpl011_init() by the tool stack. With that change, we need not
use domain creation flags.

Regards,
Bhupinder

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

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

* Re: [PATCH 03/10 v2] xen/arm: vpl011: Enable pl011 emulation for a guest domain in Xen
  2017-05-02 15:20     ` Bhupinder Thakur
@ 2017-05-02 15:23       ` Julien Grall
  2017-05-03 10:22         ` Julien Grall
  0 siblings, 1 reply; 54+ messages in thread
From: Julien Grall @ 2017-05-02 15:23 UTC (permalink / raw)
  To: Bhupinder Thakur, Jan Beulich
  Cc: Andrew Cooper, Stefano Stabellini, Wei Liu, Ian Jackson, xen-devel

Hi Bhupinder,

On 02/05/17 16:20, Bhupinder Thakur wrote:
> Hi Jan,
>
>>> @@ -631,6 +632,9 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags,
>>>      if ( (rc = domain_vtimer_init(d, config)) != 0 )
>>>          goto fail;
>>>
>>> +    if ( domcr_flags & DOMCRF_vuart )
>>> +        if ( (rc = domain_vpl011_init(d, config)) != 0 )
>>> +            goto fail;
>>>      update_domain_wallclock_time(d);
>>
> I am planning to remove the usage of domain creation flag to check
> whether vuart is enabled/disabled. Please see my next comment. With
> that change, domain_vpl011_init() will be called always. The
> domain_vpl011_init() will check whether vuart is enabled or disabled
> in the config structure passed. If vuart is enabled then it will go
> ahead with vpl011 initialization else it will return without
> initializing vpl011.

Please don't do that. The arch code decides whether domain_vpl011_init 
not the invert.

I would much prefer if you do:

if ( enable_vuart && ((rc = domain_vpl011_init(d, config) != 0) )
   goto fail;

or
    rc = (enable_vuart) ? domain_vpl011_init(d, config) : 0;
    if ( rc != 0 )
      goto fail;

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 01/10 v2] xen/arm: vpl011: Add pl011 uart emulation in Xen
  2017-04-28 16:01 ` [PATCH 01/10 v2] xen/arm: vpl011: Add pl011 uart emulation " Bhupinder Thakur
  2017-04-28 19:08   ` Stefano Stabellini
  2017-05-02  7:34   ` Jan Beulich
@ 2017-05-02 16:02   ` Julien Grall
  2017-05-05 11:18     ` Bhupinder Thakur
  2 siblings, 1 reply; 54+ messages in thread
From: Julien Grall @ 2017-05-02 16:02 UTC (permalink / raw)
  To: Bhupinder Thakur, xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andre Przywara, Ian Jackson,
	Jan Beulich, Andrew Cooper

Hi Bhupinder,

On 28/04/17 17:01, Bhupinder Thakur wrote:
> 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 v1:
>
> - Removed the optimiztion related to sendiing events to xenconsole
> - Use local variables as ring buffer indices while using the ring buffer
>
>  xen/arch/arm/Kconfig             |   5 +
>  xen/arch/arm/Makefile            |   1 +
>  xen/arch/arm/vpl011.c            | 340 +++++++++++++++++++++++++++++++++++++++
>  xen/include/asm-arm/domain.h     |   3 +
>  xen/include/asm-arm/pl011-uart.h |   2 +
>  xen/include/public/arch-arm.h    |   8 +
>  xen/include/xen/vpl011.h         |  74 +++++++++
>  7 files changed, 433 insertions(+)
>  create mode 100644 xen/arch/arm/vpl011.c
>  create mode 100644 xen/include/xen/vpl011.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..51abade
> --- /dev/null
> +++ b/xen/arch/arm/vpl011.c
> @@ -0,0 +1,340 @@
> +/*
> + * 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/sched.h>
> +#include <xen/vpl011.h>
> +#include <public/io/console.h>
> +#include <asm-arm/pl011-uart.h>
> +
> +unsigned int vpl011_reg_mask[] = {0xff, 0xffff, 0xffffffff};

This should be static. But I don't get what you need that. In the first 
version, I suggested to re-purpose vgic_reg*_{extract,update} so we can 
use it here. It would probably need to be renamed to vreg_reg*.

I don't see any reason to not do that and re-inventing the wheel.

> +
> +static void vgic_inject_vpl011_spi(struct domain *d)
> +{
> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
> +
> +    if ( (vpl011->uartris & vpl011->uartimsc) )
> +        vgic_vcpu_inject_spi(d, GUEST_VPL011_SPI);
> +}

PL011 is using level interrupt which means that you should not inject 
interrupt but instead set or clear the pending interrupt.

However, the problem is because the vGIC is incapable to handle properly 
level interrupt. This is going to be a major problem as the interrupt 
should stay pending until the pl011 emulation says there are no more 
interrupts to handle.

For instance, you may miss character if the guest driver had not enough 
space to read character new one because the interrupt will not get 
re-injected.

I am not asking to modify the vGIC in order to handle level properly 
(Andre in CC is looking at that). But we need to get the code in correct 
shape in order to handle properly pl011 interrupt.

By that I mean, at least the naming of the function (I haven't read the 
rest to know what is missing). I.e I would rename to vpl011_update(...).

> +static int vpl011_mmio_read(struct vcpu *v, mmio_info_t *info, register_t *r, void *priv)
> +{
> +    uint8_t ch;
> +    struct hsr_dabt dabt = info->dabt;
> +    int vpl011_reg = (int)(info->gpa - GUEST_PL011_BASE);
> +    struct vpl011_s *vpl011 = &v->domain->arch.vpl011;
> +
> +    switch ( vpl011_reg )
> +    {
> +    case DR:

As said on the first version, all those registers have specific size. 
Please have a look at how we handle register emulation in the vgic with 
VREG*.

> +        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
> +        vpl011_read_data(v->domain, &ch);
> +        *r = ch;
> +        break;
> +
> +    case RSR:
> +        if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;
> +
> +        /* It always returns 0 as there are no physical errors. */
> +        *r = 0;
> +        break;
> +
> +    case FR:
> +        if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;
> +        *r = (vpl011->uartfr & vpl011_reg_mask[dabt.size]);

Pointless ().

> +        break;
> +
> +    case RIS:
> +        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
> +        *r = (vpl011->uartris & vpl011_reg_mask[dabt.size]);

Pointless ().

> +        break;
> +
> +    case MIS:
> +        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
> +        *r = (vpl011->uartris &
> +                            vpl011->uartimsc & vpl011_reg_mask[dabt.size]);

Pointless ().

> +        break;
> +
> +    case IMSC:
> +        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
> +        *r = (vpl011->uartimsc & vpl011_reg_mask[dabt.size]);

Pointless ().

> +        break;
> +
> +    case ICR:
> +        if ( !VALID_W_SIZE(dabt.size) ) 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);

The indentation looks wrong here.

> +        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);

The indentation looks wrong here.

> +    domain_crash_synchronous();
> +    return 0;
> +
> +}
> +
> +static int vpl011_mmio_write(struct vcpu *v, mmio_info_t *info, register_t r, void *priv)
> +{
> +    uint8_t ch = ((struct uartdr_reg *)&r)->data;
> +    struct hsr_dabt dabt = info->dabt;
> +    int vpl011_reg = (int)(info->gpa - GUEST_PL011_BASE);
> +    struct vpl011_s *vpl011 = &v->domain->arch.vpl011;
> +
> +    switch ( vpl011_reg )
> +    {
> +    case DR:
> +
> +        if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;
> +        vpl011_write_data(v->domain, ch);
> +        break;
> +
> +    case RSR: /* Nothing to clear. */
> +        if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;
> +        break;
> +
> +    case FR:
> +        goto write_ignore;
> +    case RIS:
> +    case MIS:
> +        goto word_write_ignore;
> +
> +    case IMSC:
> +        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
> +        vpl011->uartimsc = (r & vpl011_reg_mask[dabt.size]);
> +        vgic_inject_vpl011_spi(v->domain);
> +        break;
> +
> +    case ICR:
> +        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
> +        vpl011->uartris &= ~(r & vpl011_reg_mask[dabt.size]);
> +        vgic_inject_vpl011_spi(v->domain);
> +        break;
> +
> +    default:
> +        gprintk(XENLOG_ERR, "vpl011: unhandled write r%d offset %#08x\n",
> +                               dabt.reg, vpl011_reg);

The indentation looks wrong here.

> +        return 0;
> +    }
> +
> +    return 1;
> +
> +write_ignore:
> +    if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;

Why? Looking at the spec, write-ignore register does not have specific 
access size.

> +    return 1;
> +
> +word_write_ignore:
> +    if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
> +    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,
> +};
> +
> +int vpl011_map_guest_page(struct domain *d, unsigned long pfn)

Please don't use the term pfn as we don't know whether it refers to the 
guest frame number (GFN) or machine frame number (MFN).

So in this case, I think it is gfn. Also s/unsigned long/gfn_t/

> +{
> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
> +
> +    /* Map the guest PFN to Xen address space. */
> +    return prepare_ring_for_helper(d,
> +                                   pfn,
> +                                   &vpl011->ring_page,
> +                                   &vpl011->ring_buf);
> +}
> +
> +static void vpl011_data_avail(struct domain *d)
> +{
> +    unsigned long flags;
> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
> +    struct xencons_interface *intf = vpl011->ring_buf;
> +    uint32_t in_ring_depth, out_ring_depth;
> +
> +    VPL011_LOCK(d, flags);
> +
> +    in_ring_depth = intf->in_prod - intf->in_cons;
> +    out_ring_depth = intf->out_prod - intf->out_cons;
> +
> +    /* Update the uart rx state if the buffer is not empty. */
> +    if ( in_ring_depth != 0 )
> +    {
> +        vpl011->uartfr &= ~(RXFE);

Pointless ()

> +        if ( in_ring_depth == VPL011_RING_MAX_DEPTH(intf, in) )
> +            vpl011->uartfr |= (RXFF);

Ditto

> +        vpl011->uartris |= (RXI);

Ditto

> +    }
> +
> +    /* Update the uart tx state if the buffer is not full. */
> +    if ( out_ring_depth != VPL011_RING_MAX_DEPTH(intf, out) )
> +    {
> +        vpl011->uartfr &= ~(TXFF);

Ditto

> +        vpl011->uartris |= (TXI);

Ditto

> +        if ( out_ring_depth == 0 )
> +        {
> +            vpl011->uartfr &= ~(BUSY);

Ditto

> +            vpl011->uartfr |= (TXFE);

Ditto

> +        }
> +    }
> +
> +    VPL011_UNLOCK(d, flags);
> +
> +    vgic_inject_vpl011_spi(d);
> +}
> +
> +
> +static void vpl011_notification(struct vcpu *v, unsigned int port)
> +{
> +    vpl011_data_avail(v->domain);
> +}
> +
> +int domain_vpl011_init(struct domain *d, struct xen_arch_domainconfig *config)
> +{
> +    int rc;
> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
> +
> +    rc = alloc_unbound_xen_event_channel(d, 0, config->console_domid,
> +                                         vpl011_notification);
> +    if (rc < 0)
> +    {
> +        return rc;
> +    }
> +
> +    vpl011->evtchn = rc;
> +    rc = vgic_reserve_virq(d, GUEST_VPL011_SPI);
> +    if ( !rc )
> +    {
> +        free_xen_event_channel(d, vpl011->evtchn);
> +        vpl011->evtchn = -1;
> +        return rc;
> +    }
> +    register_mmio_handler(d, &vpl011_mmio_handler, GUEST_PL011_BASE, GUEST_PL011_SIZE, NULL);
> +    spin_lock_init(&vpl011->lock);
> +
> +    vpl011->initialized = true;
> +
> +    return 0;
> +}
> +
> +void domain_vpl011_deinit(struct domain *d)
> +{
> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
> +
> +    if ( vpl011->initialized )
> +    {
> +        free_xen_event_channel(d, vpl011->evtchn);
> +        destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
> +    }
> +    vpl011->initialized = false;
> +}

Missing Emacs magic.

> diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
> index 6de8082..a0f8f89 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 <xen/vpl011.h>
>
>  struct hvm_domain
>  {
> @@ -133,6 +134,8 @@ struct arch_domain
>      struct {
>          uint8_t privileged_call_enabled : 1;
>      } monitor;
> +
> +    struct vpl011_s vpl011;

This should be guard by #ifdef CONFIG_VPL011_CONSOLE.

>  }  __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/public/arch-arm.h b/xen/include/public/arch-arm.h
> index bd974fb..5f91207 100644
> --- a/xen/include/public/arch-arm.h
> +++ b/xen/include/public/arch-arm.h
> @@ -322,6 +322,8 @@ struct xen_arch_domainconfig {
>       *
>       */
>      uint32_t clock_frequency;
> +
> +    uint32_t console_domid;
>  };
>  #endif /* __XEN__ || __XEN_TOOLS__ */
>
> @@ -410,6 +412,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 +450,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/xen/vpl011.h b/xen/include/xen/vpl011.h
> new file mode 100644
> index 0000000..57d61b4
> --- /dev/null
> +++ b/xen/include/xen/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_
> +
> +/* helper macros */
> +#define VPL011_RING_DEPTH(intf,dir) (((intf)->dir ## _prod - (intf)->dir ## _cons))
> +
> +#define VPL011_RING_MAX_DEPTH(intf,dir) (sizeof((intf)->dir)-1)
> +
> +#define VPL011_IN_RING_EMPTY(intf) (VPL011_RING_DEPTH(intf, in) == 0)
> +
> +#define VPL011_OUT_RING_EMPTY(intf) (VPL011_RING_DEPTH(intf, out) == 0)
> +
> +#define VPL011_IN_RING_FULL(intf) (VPL011_RING_DEPTH(intf, in) == VPL011_RING_MAX_DEPTH(intf, in))
> +
> +#define VPL011_OUT_RING_FULL(intf) (VPL011_RING_DEPTH(intf, out) == VPL011_RING_MAX_DEPTH(intf,out))
> +
> +#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)
> +
> +#define VALID_BW_SIZE(size) ( size == DABT_BYTE || size == DABT_HALF_WORD || size == DABT_WORD )
> +#define VALID_W_SIZE(size)  ( size == DABT_HALF_WORD || size == DABT_WORD )

The header should only contain what needs to be used by other code. In 
this case we don't want anyone to use VALID_*_SIZE.

Also, I find the name quite confusing, it is not clear when to use which 
one. Looking at the SBSA (6.2 in ARM-DEN-0029 v3.0): "if an access size 
not listed in the table is used, the results are IMPLEMENTATION DEFINED".

In order to get the code simple I would handle all 32bits register in 
the same way (e.g 8-bits, 16-bits and 32-bits access always allowed).

So I would introduce a static inline helper vpl011_reg32_check_access 
that check the return we don't use 64-bit access.

> +
> +struct uartdr_reg {
> +    uint8_t data;
> +    uint8_t error_status:4;
> +    uint8_t reserved1:4;
> +    uint16_t reserved2;
> +    uint32_t reserved3;
> +};
> +
> +struct vpl011_s {
> +    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;
> +    bool        initialized; /* Flag which tells whether vpl011 is initialized */
> +    uint32_t    evtchn;
> +};
> +
> +#ifdef CONFIG_VPL011_CONSOLE
> +int domain_vpl011_init(struct domain *d, struct xen_arch_domainconfig *config);
> +void domain_vpl011_deinit(struct domain *d);
> +int vpl011_map_guest_page(struct domain *d, unsigned long pfn);
> +#else
> +static inline int domain_vpl011_init(struct domain *d, struct xen_arch_domainconfig *config) { return -ENOSYS; }
> +static inline void domain_vpl011_deinit(struct domain *d) { }
> +static inline int vpl011_map_guest_page(struct domain *d, unsigned long pfn) { return -ENOSYS; }
> +#endif
> +
> +#endif
>

Missing Emacs magic.

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 02/10 v2] xen/arm: vpl011: Add new vuart domctl interface to setup pfn and evtchn
  2017-04-28 16:01 ` [PATCH 02/10 v2] xen/arm: vpl011: Add new vuart domctl interface to setup pfn and evtchn Bhupinder Thakur
  2017-04-28 19:23   ` Stefano Stabellini
  2017-05-02  7:47   ` Jan Beulich
@ 2017-05-03 10:14   ` Julien Grall
  2 siblings, 0 replies; 54+ messages in thread
From: Julien Grall @ 2017-05-03 10:14 UTC (permalink / raw)
  To: Bhupinder Thakur, xen-devel
  Cc: Wei Liu, Stefano Stabellini, Ian Jackson, Jan Beulich, Andrew Cooper

Hi Bhupinder,

Title: Please avoid the term pfn and use gfn or mfn.

On 28/04/17 17:01, Bhupinder Thakur wrote:
> 1. Add two new domctl API to:
>     - Allocate a new event channel for sending/receiving events to/from Xen.
>     - Map the PFN allocted by the toolstack to be used as IN/OUT ring buffers.

Ditto and s/allocted/allocated/

>
> Xen will communicate with xenconsole over the ring buffer and the event
> channel to transmit and receive pl011 data on guest domain's behalf.
>
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
> ---
>
> Changes since v1:
>
> - Replaced the hvm interface with domctl interface
>
>  tools/libxc/include/xenctrl.h | 26 ++++++++++++++++++++++++++
>  tools/libxc/xc_domain.c       | 39 +++++++++++++++++++++++++++++++++++++++
>  xen/arch/arm/domctl.c         | 20 ++++++++++++++++++++
>  xen/arch/x86/domctl.c         |  4 ++++
>  xen/include/public/domctl.h   | 11 +++++++++++
>  5 files changed, 100 insertions(+)
>
> diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
> index 1629f41..bebfe7d 100644
> --- a/tools/libxc/include/xenctrl.h
> +++ b/tools/libxc/include/xenctrl.h
> @@ -886,6 +886,32 @@ int xc_vcpu_getcontext(xc_interface *xch,
>                         vcpu_guest_context_any_t *ctxt);
>
>  /**
> + * This function returns information about the pfn and the event channel

Ditto.

> + * to be used for setting up a virtual uart console.

s/uart/UART/

> + *
> + * @parm xch a handle to an open hypervisor interface
> + * @parm domid the domain to get information from
> + * @parm vuart_pfn the pfn to be used for the ring buffer

Ditto for pfn.

> + * @return 0 on success, negative error on failure
> + */
> +int xc_domain_vuart_set_pfn(xc_interface *xch,

s/pfn/gfn/

> +                            uint32_t domid,
> +                            uint32_t vuart_pfn);

s/pfn/gfn/ also a frame number may not fit in uint32_t. You want to use 
xen_pfn_t.

> +
> +/**
> + * This function returns information about the pfn and the event channel
> + * to be used for setting up a virtual console.
> + *
> + * @parm xch a handle to an open hypervisor interface
> + * @parm domid the domain to get information from
> + * @parm vuart_evtchn the event channel to be used for console events
> + * @return 0 on success, negative error on failure
> + */
> +int xc_domain_vuart_get_evtchn(xc_interface *xch,
> +                               uint32_t domid,
> +                               uint32_t *vuart_evtchn);

You want to use evtchn_port_t here.

> +
> +/**
>   * This function returns information about the XSAVE state of a particular
>   * vcpu of a domain. If extstate->size and extstate->xfeature_mask are 0,
>   * the call is considered a query to retrieve them and the buffer is not
> diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
> index 00909ad4..943f202 100644
> --- a/tools/libxc/xc_domain.c
> +++ b/tools/libxc/xc_domain.c
> @@ -343,6 +343,45 @@ int xc_domain_get_guest_width(xc_interface *xch, uint32_t domid,
>      return 0;
>  }
>
> +int xc_domain_vuart_set_pfn(xc_interface *xch,
> +                            uint32_t domid,
> +                            uint32_t vuart_pfn)

See all my remarks above.

> +{
> +    DECLARE_DOMCTL;
> +    int rc = 0;
> +
> +    domctl.cmd = XEN_DOMCTL_vuart_op;
> +    domctl.domain = (domid_t)domid;
> +    domctl.u.vuart_op.cmd = XEN_DOMCTL_VUART_OP_SET_PFN;
> +    domctl.u.vuart_op.pfn = vuart_pfn;
> +
> +    if ( (rc = do_domctl(xch, &domctl)) < 0 )
> +        return rc;
> +
> +    return rc;
> +}
> +
> +int xc_domain_vuart_get_evtchn(xc_interface *xch,
> +                               uint32_t domid,
> +                               uint32_t *vuart_evtchn)

See all my remarks above.

> +{
> +    DECLARE_DOMCTL;
> +    int rc = 0;
> +
> +	*vuart_evtchn = -1;
> +
> +    domctl.cmd = XEN_DOMCTL_vuart_op;
> +    domctl.domain = (domid_t)domid;
> +    domctl.u.vuart_op.cmd = XEN_DOMCTL_VUART_OP_GET_EVTCHN;
> +
> +    if ( (rc = do_domctl(xch, &domctl)) < 0 )
> +        return rc;
> +
> +    *vuart_evtchn = domctl.u.vuart_op.evtchn;
> +
> +    return rc;
> +}
> +
>  int xc_domain_getinfo(xc_interface *xch,
>                        uint32_t first_domid,
>                        unsigned int max_doms,
> diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
> index 971caec..e400f87 100644
> --- a/xen/arch/arm/domctl.c
> +++ b/xen/arch/arm/domctl.c
> @@ -10,6 +10,7 @@
>  #include <xen/sched.h>
>  #include <xen/hypercall.h>
>  #include <xen/iocap.h>
> +#include <xen/guest_access.h>
>  #include <xsm/xsm.h>
>  #include <public/domctl.h>
>
> @@ -119,6 +120,25 @@ long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
>          d->disable_migrate = domctl->u.disable_migrate.disable;
>          return 0;
>
> +    case XEN_DOMCTL_vuart_op:
> +    {
> +        int rc;
> +        if ( d->arch.vpl011.initialized )

You can avoid one level of "if" if you do:

if ( !d->arch.vpl011.initialized )
   return -EINVAL.

if ( domctl->u.vuart_op.cmd == .. )

> +        {
> +            if ( domctl->u.vuart_op.cmd == XEN_DOMCTL_VUART_OP_SET_PFN )

I would prefer if you use a switch case for the cmd, this would make 
easier to return an error if the command is not correct rather assuming 
that all others commands means "getting the event channel".

> +            {
> +                rc = vpl011_map_guest_page(d, domctl->u.vuart_op.pfn);

There is nothing to prevent vpl011_map_guest_page to be called twice. So 
you would end up to leak memory if XEN_DOMCTL_VUART_OP_SET_PFN is called 
twice.

> +            }
> +            else
> +            {
> +                domctl->u.vuart_op.evtchn = d->arch.vpl011.evtchn;
> +                rc = __copy_to_guest(u_domctl, domctl, 1);
> +            }
> +            return rc;
> +        }
> +        else
> +            return -EINVAL;

I don't think -EINVAL is the correct value if not initialized. It would 
be better to be -ENOSYS.

> +    }
>      default:
>      {
>          int rc;
> diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
> index e104be2..49e907d 100644
> --- a/xen/arch/x86/domctl.c
> +++ b/xen/arch/x86/domctl.c
> @@ -1465,6 +1465,10 @@ long arch_do_domctl(
>          recalculate_cpuid_policy(d);
>          break;
>
> +    case XEN_DOMCTL_vuart_op:
> +        ret = -EOPNOTSUPP;
> +        break;
> +
>      default:
>          ret = iommu_do_domctl(domctl, d, u_domctl);
>          break;
> diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
> index e6cf211..8bee0c3 100644
> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -1138,6 +1138,15 @@ struct xen_domctl_psr_cat_op {
>      uint32_t target;    /* IN */
>      uint64_t data;      /* IN/OUT */
>  };
> +
> +struct xen_domctl_vuart_op {
> +#define XEN_DOMCTL_VUART_OP_SET_PFN      0
> +#define XEN_DOMCTL_VUART_OP_GET_EVTCHN   1
> +        uint32_t cmd;       /* XEN_DOMCTL_VUART_OP_* */
> +        uint32_t pfn;       /* IN */

This should be xen_pfn_t and ...

> +        uint32_t evtchn;    /* OUT */

... evtchn_port_t.

> +};
> +
>  typedef struct xen_domctl_psr_cat_op xen_domctl_psr_cat_op_t;
>  DEFINE_XEN_GUEST_HANDLE(xen_domctl_psr_cat_op_t);
>
> @@ -1218,6 +1227,7 @@ struct xen_domctl {
>  #define XEN_DOMCTL_monitor_op                    77
>  #define XEN_DOMCTL_psr_cat_op                    78
>  #define XEN_DOMCTL_soft_reset                    79
> +#define XEN_DOMCTL_vuart_op                      80
>  #define XEN_DOMCTL_gdbsx_guestmemio            1000
>  #define XEN_DOMCTL_gdbsx_pausevcpu             1001
>  #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
> @@ -1280,6 +1290,7 @@ struct xen_domctl {
>          struct xen_domctl_psr_cmt_op        psr_cmt_op;
>          struct xen_domctl_monitor_op        monitor_op;
>          struct xen_domctl_psr_cat_op        psr_cat_op;
> +        struct xen_domctl_vuart_op          vuart_op;
>          uint8_t                             pad[128];
>      } u;
>  };
>

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 03/10 v2] xen/arm: vpl011: Enable pl011 emulation for a guest domain in Xen
  2017-05-02 15:23       ` Julien Grall
@ 2017-05-03 10:22         ` Julien Grall
  2017-05-03 10:47           ` Jan Beulich
  2017-05-05  7:10           ` Bhupinder Thakur
  0 siblings, 2 replies; 54+ messages in thread
From: Julien Grall @ 2017-05-03 10:22 UTC (permalink / raw)
  To: Bhupinder Thakur, Jan Beulich
  Cc: Andrew Cooper, Stefano Stabellini, Wei Liu, Ian Jackson, xen-devel



On 02/05/17 16:23, Julien Grall wrote:
> Hi Bhupinder,
>
> On 02/05/17 16:20, Bhupinder Thakur wrote:
>> Hi Jan,
>>
>>>> @@ -631,6 +632,9 @@ int arch_domain_create(struct domain *d,
>>>> unsigned int domcr_flags,
>>>>      if ( (rc = domain_vtimer_init(d, config)) != 0 )
>>>>          goto fail;
>>>>
>>>> +    if ( domcr_flags & DOMCRF_vuart )
>>>> +        if ( (rc = domain_vpl011_init(d, config)) != 0 )
>>>> +            goto fail;
>>>>      update_domain_wallclock_time(d);
>>>
>> I am planning to remove the usage of domain creation flag to check
>> whether vuart is enabled/disabled. Please see my next comment. With
>> that change, domain_vpl011_init() will be called always. The
>> domain_vpl011_init() will check whether vuart is enabled or disabled
>> in the config structure passed. If vuart is enabled then it will go
>> ahead with vpl011 initialization else it will return without
>> initializing vpl011.
>
> Please don't do that. The arch code decides whether domain_vpl011_init
> not the invert.

I was wondering whether it would be better to defer the PL011 creation 
to a domctl. This could be called after the domain is created with all 
the information required (MMIO region, Console PFN...).

This would also make the migration support more trivial as the we will 
not need to know in advance whether a UART is been used.

Any opinions?

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 04/10 v2] xen/arm: vpl011: Add support for vuart in libxl
  2017-04-28 16:01 ` [PATCH 04/10 v2] xen/arm: vpl011: Add support for vuart in libxl Bhupinder Thakur
  2017-04-28 21:45   ` Stefano Stabellini
@ 2017-05-03 10:27   ` Julien Grall
  1 sibling, 0 replies; 54+ messages in thread
From: Julien Grall @ 2017-05-03 10:27 UTC (permalink / raw)
  To: Bhupinder Thakur, xen-devel
  Cc: Wei Liu, Stefano Stabellini, Ian Jackson, Jan Beulich, Andrew Cooper

Hi Bhupinder,

On 28/04/17 17:01, Bhupinder Thakur wrote:
> An option is provided in libxl to enable/disable pl011 vuart while
> creating a guest domain.
>
> Libxl now suppots a generic vuart console and pl011 is a specific type.

s/supports/supports/

> In future support can be added for multiple vuart of different types.
>
> User can enable pl011 vuart by adding the following line in the guest
> configuration file:
>
> vuart = "pl011"
>
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
> ---
>
> Changes since v1:
> - Modified the syntax for taking the pl011 as a console type in the
>   configuration file. Now the syntax is vuart = "pl011".
> - Replaced the console type VCON with VUART, as it is more
>   intuitive.
>
>  tools/libxl/libxl.h          |  6 ++++++
>  tools/libxl/libxl_create.c   | 10 ++++++++++
>  tools/libxl/libxl_internal.h |  4 ++++
>  tools/libxl/libxl_types.idl  |  2 ++
>  tools/xl/xl_console.c        |  4 +++-
>  tools/xl/xl_parse.c          |  3 +++
>  6 files changed, 28 insertions(+), 1 deletion(-)
>
> diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
> index cf8687a..bcfbb6c 100644
> --- a/tools/libxl/libxl.h
> +++ b/tools/libxl/libxl.h
> @@ -306,6 +306,12 @@
>  #define LIBXL_HAVE_BUILDINFO_HVM_ACPI_LAPTOP_SLATE 1
>
>  /*
> + * LIBXL_HAVE_VUART indicates that xenconsole/client supports
> + * virtual uart.
> + */
> +#define LIBXL_HAVE_VUART 1
> +
> +/*
>   * libxl ABI compatibility
>   *
>   * The only guarantee which libxl makes regarding ABI compatibility
> diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
> index bffbc45..5d70bc2 100644
> --- a/tools/libxl/libxl_create.c
> +++ b/tools/libxl/libxl_create.c
> @@ -536,6 +536,9 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config,
>          flags |= libxl_defbool_val(info->oos) ? 0 : XEN_DOMCTL_CDF_oos_off;
>      }
>
> +    if (!strcmp(d_config->b_info.vuart, "pl011"))
> +        flags |= XEN_DOMCTL_VUART_enable;

Likely, this would have to be arch specific and not in the common code. 
Have a look to libxl__arch_domain_prepare_config

> +
>      /* Ultimately, handle is an array of 16 uint8_t, same as uuid */
>      libxl_uuid_copy(ctx, (libxl_uuid *)handle, &info->uuid);
>
> @@ -900,6 +903,11 @@ static void initiate_domain_create(libxl__egc *egc,
>          goto error_out;
>      }
>
> +    if (!strcmp(d_config->b_info.vuart, "pl011"))
> +        state->vuart_enabled = true;
> +    else
> +        state->vuart_enabled = false;
> +

Same here, this should be in arch code. Also you don't need if/else to 
set a boolean.

You could simply do:

state->vuart_enable = !strcmp(d_config->b_info.vuart, "pl011");

>      if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM &&
>          (libxl_defbool_val(d_config->b_info.u.hvm.nested_hvm) &&
>          (libxl_defbool_val(d_config->b_info.u.hvm.altp2m) ||
> @@ -918,6 +926,8 @@ static void initiate_domain_create(libxl__egc *egc,
>          goto error_out;
>      }
>
> +    state->config.console_domid = state->console_domid;
> +
>      ret = libxl__domain_make(gc, d_config, &domid, &state->config);
>      if (ret) {
>          LOGD(ERROR, domid, "cannot make domain: %d", ret);
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index 5d082c5..9dba8e7 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -1135,6 +1135,10 @@ typedef struct {
>      uint32_t num_vmemranges;
>
>      xc_domain_configuration_t config;
> +
> +    unsigned long vuart_mfn;

s/unsigned long/xen_pfn_t/ and s/vuart_mfn/vuart_gfn/

Also, what is this frame number for? The MMIO region or the console 
frame number?


> +    uint32_t    vuart_port;

What is port?

> +    bool        vuart_enabled;
>  } libxl__domain_build_state;
>
>  _hidden int libxl__build_pre(libxl__gc *gc, uint32_t domid,
> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> index 2204425..5d53f2c 100644
> --- a/tools/libxl/libxl_types.idl
> +++ b/tools/libxl/libxl_types.idl
> @@ -105,6 +105,7 @@ libxl_console_type = Enumeration("console_type", [
>      (0, "UNKNOWN"),
>      (1, "SERIAL"),
>      (2, "PV"),
> +    (3, "VUART"),
>      ])
>
>  libxl_disk_format = Enumeration("disk_format", [
> @@ -470,6 +471,7 @@ libxl_domain_build_info = Struct("domain_build_info",[
>      ("disable_migrate", libxl_defbool),
>      ("cpuid",           libxl_cpuid_policy_list),
>      ("blkdev_start",    string),
> +    ("vuart",           string),
>
>      ("vnuma_nodes", Array(libxl_vnode_info, "num_vnuma_nodes")),
>
> diff --git a/tools/xl/xl_console.c b/tools/xl/xl_console.c
> index 0508dda..6f3cd7f 100644
> --- a/tools/xl/xl_console.c
> +++ b/tools/xl/xl_console.c
> @@ -34,8 +34,10 @@ int main_console(int argc, char **argv)
>              type = LIBXL_CONSOLE_TYPE_PV;
>          else if (!strcmp(optarg, "serial"))
>              type = LIBXL_CONSOLE_TYPE_SERIAL;
> +        else if (!strcmp(optarg, "vuart"))
> +            type = LIBXL_CONSOLE_TYPE_VUART;
>          else {
> -            fprintf(stderr, "console type supported are: pv, serial\n");
> +            fprintf(stderr, "console type supported are: pv, serial, vuart\n");
>              return EXIT_FAILURE;
>          }
>          break;
> diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
> index 856a304..80fd184 100644
> --- a/tools/xl/xl_parse.c
> +++ b/tools/xl/xl_parse.c
> @@ -916,6 +916,9 @@ void parse_config_data(const char *config_source,
>      if (!xlu_cfg_get_long (config, "maxvcpus", &l, 0))
>          b_info->max_vcpus = l;
>
> +    if (xlu_cfg_replace_string(config, "vuart", &b_info->vuart, 0))
> +        b_info->vuart = strdup("unknown");
> +
>      parse_vnuma_config(config, b_info);
>
>      /* Set max_memkb to target_memkb and max_vcpus to avail_vcpus if
>

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 09/10 v2] xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree
  2017-04-28 16:01 ` [PATCH 09/10 v2] xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree Bhupinder Thakur
@ 2017-05-03 10:38   ` Julien Grall
  2017-05-08  6:43     ` Bhupinder Thakur
  0 siblings, 1 reply; 54+ messages in thread
From: Julien Grall @ 2017-05-03 10:38 UTC (permalink / raw)
  To: Bhupinder Thakur, xen-devel
  Cc: Wei Liu, Stefano Stabellini, Ian Jackson, Jan Beulich, Andrew Cooper

Hi Bhupinder,

On 28/04/17 17:01, Bhupinder Thakur wrote:
> The SBSA uart node format is as specified in
> Documentation/devicetree/bindings/serial/arm_sbsa_uart.txt and given below:
>
> ARM SBSA defined generic UART
> ------------------------------
> This UART uses a subset of the PL011 registers and consequently lives
> in the PL011 driver. It's baudrate and other communication parameters
> cannot be adjusted at runtime, so it lacks a clock specifier here.
>
> Required properties:
> - compatible: must be "arm,sbsa-uart"
> - reg: exactly one register range
> - interrupts: exactly one interrupt specifier
> - current-speed: the (fixed) baud rate set by the firmware

What is the plan for ACPI support?

>
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
> Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
> ---
>
> Changes since v1:
> - Modified the code to increment nr_spis based on the SPI value reserved for
>   vpl011.
> - Added a check to verify that physical irq assigment is not conflicting with
>   vpl011 SPI.

Those 2 changes are usually a call to drop reviewed-by or at least to 
check whether the reviewer (here Stefano) is happy with the changes made.

> - Fixed minor indentation issues.
>
>  tools/libxl/libxl_arm.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 52 insertions(+), 2 deletions(-)
>
> diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
> index d842d88..45a56a8 100644
> --- a/tools/libxl/libxl_arm.c
> +++ b/tools/libxl/libxl_arm.c
> @@ -43,11 +43,25 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
>  {
>      uint32_t nr_spis = 0;
>      unsigned int i;
> +    bool vpl011_enabled = !strcmp(d_config->b_info.vuart, "pl011");
> +
> +    /*
> +     * If pl011 vuart is enabled then increment the nr_spis to allow allocation
> +     * of SPI VIRQ for pl011.
> +     */
> +    if (vpl011_enabled)
> +        nr_spis += (GUEST_VPL011_SPI - 32)+1;

space before and after +.

>
>      for (i = 0; i < d_config->b_info.num_irqs; i++) {
>          uint32_t irq = d_config->b_info.irqs[i];
>          uint32_t spi;
>
> +        if (vpl011_enabled && irq == GUEST_VPL011_SPI)
> +        {
> +            LOG(ERROR, "Physical IRQ %d conflicting with pl011 SPI\n", irq);

s/%d/%u/

> +            return ERROR_FAIL;
> +        }
> +
>          if (irq < 32)
>              continue;
>
> @@ -130,9 +144,10 @@ static struct arch_info {
>      const char *guest_type;
>      const char *timer_compat;
>      const char *cpu_compat;
> +    const char *uart_compat;
>  } arch_info[] = {
> -    {"xen-3.0-armv7l",  "arm,armv7-timer", "arm,cortex-a15" },
> -    {"xen-3.0-aarch64", "arm,armv8-timer", "arm,armv8" },
> +    {"xen-3.0-armv7l",  "arm,armv7-timer", "arm,cortex-a15", "arm,sbsa-uart" },
> +    {"xen-3.0-aarch64", "arm,armv8-timer", "arm,armv8", "arm,sbsa-uart" },
>  };
>
>  /*
> @@ -590,6 +605,38 @@ static int make_hypervisor_node(libxl__gc *gc, void *fdt,
>      return 0;
>  }
>
> +static int make_vpl011_uart_node(libxl__gc *gc, void *fdt,
> +                                 const struct arch_info *ainfo,
> +                                 struct xc_dom_image *dom)
> +{
> +    int res;
> +    gic_interrupt intr;
> +
> +    res = fdt_begin_node(fdt, "sbsa-pl011");
> +    if (res) return res;
> +
> +    res = fdt_property_compat(gc, fdt, 1, ainfo->uart_compat);
> +    if (res) return res;
> +
> +    res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
> +                            1,
> +                            GUEST_PL011_BASE, GUEST_PL011_SIZE);
> +    if (res) return res;
> +
> +    set_interrupt(intr, GUEST_VPL011_SPI, 0xf, DT_IRQ_TYPE_LEVEL_HIGH);
> +
> +    res = fdt_property_interrupts(gc, fdt, &intr, 1);
> +    if (res) return res;
> +
> +    /* Use a default baud rate of 115200. */
> +    fdt_property_u32(fdt, "current-speed", 115200);

Please explain in the commit message why 115200.

> +
> +    res = fdt_end_node(fdt);
> +    if (res) return res;
> +
> +    return 0;
> +}
> +
>  static const struct arch_info *get_arch_info(libxl__gc *gc,
>                                               const struct xc_dom_image *dom)
>  {
> @@ -889,6 +936,9 @@ next_resize:
>          FDT( make_timer_node(gc, fdt, ainfo, xc_config->clock_frequency) );
>          FDT( make_hypervisor_node(gc, fdt, vers) );
>
> +        if (!strcmp(info->vuart, "pl011"))
> +            FDT( make_vpl011_uart_node(gc, fdt, ainfo, dom) );
> +
>          if (pfdt)
>              FDT( copy_partial_fdt(gc, fdt, pfdt) );
>
>

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 03/10 v2] xen/arm: vpl011: Enable pl011 emulation for a guest domain in Xen
  2017-05-03 10:22         ` Julien Grall
@ 2017-05-03 10:47           ` Jan Beulich
  2017-05-05  7:10           ` Bhupinder Thakur
  1 sibling, 0 replies; 54+ messages in thread
From: Jan Beulich @ 2017-05-03 10:47 UTC (permalink / raw)
  To: Julien Grall, Bhupinder Thakur
  Cc: Andrew Cooper, Stefano Stabellini, Wei Liu, Ian Jackson, xen-devel

>>> On 03.05.17 at 12:22, <julien.grall@arm.com> wrote:

> 
> On 02/05/17 16:23, Julien Grall wrote:
>> Hi Bhupinder,
>>
>> On 02/05/17 16:20, Bhupinder Thakur wrote:
>>> Hi Jan,
>>>
>>>>> @@ -631,6 +632,9 @@ int arch_domain_create(struct domain *d,
>>>>> unsigned int domcr_flags,
>>>>>      if ( (rc = domain_vtimer_init(d, config)) != 0 )
>>>>>          goto fail;
>>>>>
>>>>> +    if ( domcr_flags & DOMCRF_vuart )
>>>>> +        if ( (rc = domain_vpl011_init(d, config)) != 0 )
>>>>> +            goto fail;
>>>>>      update_domain_wallclock_time(d);
>>>>
>>> I am planning to remove the usage of domain creation flag to check
>>> whether vuart is enabled/disabled. Please see my next comment. With
>>> that change, domain_vpl011_init() will be called always. The
>>> domain_vpl011_init() will check whether vuart is enabled or disabled
>>> in the config structure passed. If vuart is enabled then it will go
>>> ahead with vpl011 initialization else it will return without
>>> initializing vpl011.
>>
>> Please don't do that. The arch code decides whether domain_vpl011_init
>> not the invert.
> 
> I was wondering whether it would be better to defer the PL011 creation 
> to a domctl. This could be called after the domain is created with all 
> the information required (MMIO region, Console PFN...).
> 
> This would also make the migration support more trivial as the we will 
> not need to know in advance whether a UART is been used.
> 
> Any opinions?

Wasn't that the suggestion given during v1 review?

Jan


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

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

* Re: [PATCH 06/10 v2] xen/arm: vpl011: Add vuart ring-buf and evtchn to xenstore
  2017-05-01 17:56       ` Stefano Stabellini
@ 2017-05-03 11:00         ` Bhupinder Thakur
  2017-05-03 22:35           ` Stefano Stabellini
  0 siblings, 1 reply; 54+ messages in thread
From: Bhupinder Thakur @ 2017-05-03 11:00 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Wei Liu, Andrew Cooper, Ian Jackson, Julien Grall, Jan Beulich,
	xen-devel

Hi,

>> > It looks like you are reusing the libxl__device_console_add call for the
>> > main PV console for the domain, to also add the vuart nodes to xenstore.
>> >
>> > I don't think it is a good idea to mix the two. I suggest to introduce a
>> > new libxl__device call to introduce the vuart nodes to xenstore, given
>> > that they have no relantionship with the principal PV console of the
>> > domain.
>> >
>> I have a doubt here. Do I have to create a new console device
>> (libxl__device) to register the vuart console or can I use the
>> existing console device (which is used for registering the primary
>> console) to register the vuart nodes to xenstore?
>>
>> I suspect that if I try to register with the same console device then
>> libxl__device_generic_add() may fail as it is already added.
>
> The vuart we are introducing with this patch series is a new and
> different console from the existing PV console. So yes, I think we need
> to create a new device for it.
>
> We either need to introduce a brand new function to add the vuart to
> xenstore, something like libxl__device_vuart_add, or, if we are going
> to reuse libxl__device_console_add, then we we need to create both a new
> console device (libxl__device_console), and a new libxl__device for it.
> For clarity, libxl__device_console is the input parameter of
> libxl__device_console_add, while libxl__device is the output parameter.
>
I am trying to add a new vuart device by defining a new device type
LIBXL__DEVICE_KIND_VUART  and a new function
libxl__device_vuart_add().

This function basically adds the vuart ring-ref ("0/ring-ref") and
port ("0/port") to ro_front array and then it registers the device
using the libxl__device_generic_add(). I pass NULL to "back" and
"front" array arguments to  libxl__device_generic_add() as I am adding
parameters only to "ro_front" array.

I am adding the device at /local/domain/<domid>/vuart.

However, xenconsoled fails to read the vuart ring-ref and port saying
"no such directory or file".I verified that
libxl__device_generic_add() is returning successfully.

In xenconsoled, I verified that I am reading
/local/domain/<domid>/vuart/0/ring-ref and
/local/domain/<domid>/vuart/0/port.

It is not clear why xenconsoled fails to read the values.

Regards,
Bhupinder

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

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

* Re: [PATCH 06/10 v2] xen/arm: vpl011: Add vuart ring-buf and evtchn to xenstore
  2017-05-03 11:00         ` Bhupinder Thakur
@ 2017-05-03 22:35           ` Stefano Stabellini
  2017-05-04 19:37             ` Bhupinder Thakur
  0 siblings, 1 reply; 54+ messages in thread
From: Stefano Stabellini @ 2017-05-03 22:35 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich, xen-devel

On Wed, 3 May 2017, Bhupinder Thakur wrote:
> Hi,
> 
> >> > It looks like you are reusing the libxl__device_console_add call for the
> >> > main PV console for the domain, to also add the vuart nodes to xenstore.
> >> >
> >> > I don't think it is a good idea to mix the two. I suggest to introduce a
> >> > new libxl__device call to introduce the vuart nodes to xenstore, given
> >> > that they have no relantionship with the principal PV console of the
> >> > domain.
> >> >
> >> I have a doubt here. Do I have to create a new console device
> >> (libxl__device) to register the vuart console or can I use the
> >> existing console device (which is used for registering the primary
> >> console) to register the vuart nodes to xenstore?
> >>
> >> I suspect that if I try to register with the same console device then
> >> libxl__device_generic_add() may fail as it is already added.
> >
> > The vuart we are introducing with this patch series is a new and
> > different console from the existing PV console. So yes, I think we need
> > to create a new device for it.
> >
> > We either need to introduce a brand new function to add the vuart to
> > xenstore, something like libxl__device_vuart_add, or, if we are going
> > to reuse libxl__device_console_add, then we we need to create both a new
> > console device (libxl__device_console), and a new libxl__device for it.
> > For clarity, libxl__device_console is the input parameter of
> > libxl__device_console_add, while libxl__device is the output parameter.
> >
> I am trying to add a new vuart device by defining a new device type
> LIBXL__DEVICE_KIND_VUART  and a new function
> libxl__device_vuart_add().

I think that is the right way to do it.


> This function basically adds the vuart ring-ref ("0/ring-ref") and
> port ("0/port") to ro_front array and then it registers the device
> using the libxl__device_generic_add(). I pass NULL to "back" and
> "front" array arguments to  libxl__device_generic_add() as I am adding
> parameters only to "ro_front" array.
> 
> I am adding the device at /local/domain/<domid>/vuart.
> 
> However, xenconsoled fails to read the vuart ring-ref and port saying
> "no such directory or file".I verified that
> libxl__device_generic_add() is returning successfully.
> 
> In xenconsoled, I verified that I am reading
> /local/domain/<domid>/vuart/0/ring-ref and
> /local/domain/<domid>/vuart/0/port.
> 
> It is not clear why xenconsoled fails to read the values.

Double check the permissions of those nodes with xenstore-ls -p. Make
sure there are no races between libxl writing the nodes and xenconsoled
reading them.

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

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

* Re: [PATCH 06/10 v2] xen/arm: vpl011: Add vuart ring-buf and evtchn to xenstore
  2017-05-03 22:35           ` Stefano Stabellini
@ 2017-05-04 19:37             ` Bhupinder Thakur
  2017-05-04 20:38               ` Stefano Stabellini
  0 siblings, 1 reply; 54+ messages in thread
From: Bhupinder Thakur @ 2017-05-04 19:37 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Wei Liu, Andrew Cooper, Ian Jackson, Julien Grall, Jan Beulich,
	xen-devel

Hi,


>> >> > It looks like you are reusing the libxl__device_console_add call for the
>> >> > main PV console for the domain, to also add the vuart nodes to xenstore.
>> >> >
>> >> > I don't think it is a good idea to mix the two. I suggest to introduce a
>> >> > new libxl__device call to introduce the vuart nodes to xenstore, given
>> >> > that they have no relantionship with the principal PV console of the
>> >> > domain.
>> >> >
>> >> I have a doubt here. Do I have to create a new console device
>> >> (libxl__device) to register the vuart console or can I use the
>> >> existing console device (which is used for registering the primary
>> >> console) to register the vuart nodes to xenstore?
>> >>
>> >> I suspect that if I try to register with the same console device then
>> >> libxl__device_generic_add() may fail as it is already added.
>> >
>> > The vuart we are introducing with this patch series is a new and
>> > different console from the existing PV console. So yes, I think we need
>> > to create a new device for it.
>> >
>> > We either need to introduce a brand new function to add the vuart to
>> > xenstore, something like libxl__device_vuart_add, or, if we are going
>> > to reuse libxl__device_console_add, then we we need to create both a new
>> > console device (libxl__device_console), and a new libxl__device for it.
>> > For clarity, libxl__device_console is the input parameter of
>> > libxl__device_console_add, while libxl__device is the output parameter.
>> >
>> I am trying to add a new vuart device by defining a new device type
>> LIBXL__DEVICE_KIND_VUART  and a new function
>> libxl__device_vuart_add().
>
> I think that is the right way to do it.
>
>
>> This function basically adds the vuart ring-ref ("0/ring-ref") and
>> port ("0/port") to ro_front array and then it registers the device
>> using the libxl__device_generic_add(). I pass NULL to "back" and
>> "front" array arguments to  libxl__device_generic_add() as I am adding
>> parameters only to "ro_front" array.
>>
>> I am adding the device at /local/domain/<domid>/vuart.
>>
>> However, xenconsoled fails to read the vuart ring-ref and port saying
>> "no such directory or file".I verified that
>> libxl__device_generic_add() is returning successfully.
>>
>> In xenconsoled, I verified that I am reading
>> /local/domain/<domid>/vuart/0/ring-ref and
>> /local/domain/<domid>/vuart/0/port.
>>
>> It is not clear why xenconsoled fails to read the values.
>
> Double check the permissions of those nodes with xenstore-ls -p. Make
> sure there are no races between libxl writing the nodes and xenconsoled
> reading them.

xenstore-ls -p" shows that the vuart node is created successfully. I
have pasted below the relevant part of the command output:

   vuart = ""   (n0,r1)
    backend = "/local/domain/0/backend/vuart/1/0"   (n0,r1)
    0 = ""   (n0,r1)
     port = "1"   (n0,r1)
     ring-ref = "233475"   (n0,r1)
     limit = "1048576"   (n0,r1)
     type = "xenconsoled"   (n0,r1)
   console = ""   (n0,r1)
    backend = "/local/domain/0/backend/console/1/0"   (n0,r1)
    backend-id = "0"   (n1,r0)
    limit = "1048576"   (n0,r1)
    type = "xenconsoled"   (n0,r1)
    output = "pty"   (n0,r1)
    tty = "/dev/pts/0"   (n0,r1)
    port = "3"   (n0,r1)
    ring-ref = "233472"   (n0,r1)

The vuart node exists at /local/domain/1/vuart. I am creating the
vuart node just before the pv console node to make sure that vuart
node becomes visible before the pv console node is created. The values
are populated properly in the vuart node. Still when xenconsoled tries
to read /loca/domain/1/vuart/0/ring-ref or
/loca/domain/1/vuart/0/port, the read fails.

PV console node reads happen properly even though both nodes exist at
the same level and their access permissions are also same.

Regards,
Bhupinder

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

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

* Re: [PATCH 06/10 v2] xen/arm: vpl011: Add vuart ring-buf and evtchn to xenstore
  2017-05-04 19:37             ` Bhupinder Thakur
@ 2017-05-04 20:38               ` Stefano Stabellini
  2017-05-05  9:52                 ` Bhupinder Thakur
  0 siblings, 1 reply; 54+ messages in thread
From: Stefano Stabellini @ 2017-05-04 20:38 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich, xen-devel

On Fri, 5 May 2017, Bhupinder Thakur wrote:
> Hi,
> 
> 
> >> >> > It looks like you are reusing the libxl__device_console_add call for the
> >> >> > main PV console for the domain, to also add the vuart nodes to xenstore.
> >> >> >
> >> >> > I don't think it is a good idea to mix the two. I suggest to introduce a
> >> >> > new libxl__device call to introduce the vuart nodes to xenstore, given
> >> >> > that they have no relantionship with the principal PV console of the
> >> >> > domain.
> >> >> >
> >> >> I have a doubt here. Do I have to create a new console device
> >> >> (libxl__device) to register the vuart console or can I use the
> >> >> existing console device (which is used for registering the primary
> >> >> console) to register the vuart nodes to xenstore?
> >> >>
> >> >> I suspect that if I try to register with the same console device then
> >> >> libxl__device_generic_add() may fail as it is already added.
> >> >
> >> > The vuart we are introducing with this patch series is a new and
> >> > different console from the existing PV console. So yes, I think we need
> >> > to create a new device for it.
> >> >
> >> > We either need to introduce a brand new function to add the vuart to
> >> > xenstore, something like libxl__device_vuart_add, or, if we are going
> >> > to reuse libxl__device_console_add, then we we need to create both a new
> >> > console device (libxl__device_console), and a new libxl__device for it.
> >> > For clarity, libxl__device_console is the input parameter of
> >> > libxl__device_console_add, while libxl__device is the output parameter.
> >> >
> >> I am trying to add a new vuart device by defining a new device type
> >> LIBXL__DEVICE_KIND_VUART  and a new function
> >> libxl__device_vuart_add().
> >
> > I think that is the right way to do it.
> >
> >
> >> This function basically adds the vuart ring-ref ("0/ring-ref") and
> >> port ("0/port") to ro_front array and then it registers the device
> >> using the libxl__device_generic_add(). I pass NULL to "back" and
> >> "front" array arguments to  libxl__device_generic_add() as I am adding
> >> parameters only to "ro_front" array.
> >>
> >> I am adding the device at /local/domain/<domid>/vuart.
> >>
> >> However, xenconsoled fails to read the vuart ring-ref and port saying
> >> "no such directory or file".I verified that
> >> libxl__device_generic_add() is returning successfully.
> >>
> >> In xenconsoled, I verified that I am reading
> >> /local/domain/<domid>/vuart/0/ring-ref and
> >> /local/domain/<domid>/vuart/0/port.
> >>
> >> It is not clear why xenconsoled fails to read the values.
> >
> > Double check the permissions of those nodes with xenstore-ls -p. Make
> > sure there are no races between libxl writing the nodes and xenconsoled
> > reading them.
> 
> xenstore-ls -p" shows that the vuart node is created successfully. I
> have pasted below the relevant part of the command output:
> 
>    vuart = ""   (n0,r1)
>     backend = "/local/domain/0/backend/vuart/1/0"   (n0,r1)

Why is this here instead of under vuart/0?
Also, if these are the frontend nodes, where are the backend vuart nodes?


>     0 = ""   (n0,r1)
>      port = "1"   (n0,r1)
>      ring-ref = "233475"   (n0,r1)
>      limit = "1048576"   (n0,r1)
>      type = "xenconsoled"   (n0,r1)
>    console = ""   (n0,r1)
>     backend = "/local/domain/0/backend/console/1/0"   (n0,r1)
>     backend-id = "0"   (n1,r0)
>     limit = "1048576"   (n0,r1)
>     type = "xenconsoled"   (n0,r1)
>     output = "pty"   (n0,r1)
>     tty = "/dev/pts/0"   (n0,r1)
>     port = "3"   (n0,r1)
>     ring-ref = "233472"   (n0,r1)
> 
> The vuart node exists at /local/domain/1/vuart. I am creating the
> vuart node just before the pv console node to make sure that vuart
> node becomes visible before the pv console node is created. The values
> are populated properly in the vuart node. Still when xenconsoled tries
> to read /loca/domain/1/vuart/0/ring-ref or
> /loca/domain/1/vuart/0/port, the read fails.
> 
> PV console node reads happen properly even though both nodes exist at
> the same level and their access permissions are also same.

I don't know. I would add more debug printfs to the code until I
understood what was going on.


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

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

* Re: [PATCH 03/10 v2] xen/arm: vpl011: Enable pl011 emulation for a guest domain in Xen
  2017-05-03 10:22         ` Julien Grall
  2017-05-03 10:47           ` Jan Beulich
@ 2017-05-05  7:10           ` Bhupinder Thakur
  2017-05-05 13:43             ` Julien Grall
  1 sibling, 1 reply; 54+ messages in thread
From: Bhupinder Thakur @ 2017-05-05  7:10 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Jan Beulich, xen-devel

Hi Julien,

>>> Hi Jan,
>>>
>>>>> @@ -631,6 +632,9 @@ int arch_domain_create(struct domain *d,
>>>>> unsigned int domcr_flags,
>>>>>      if ( (rc = domain_vtimer_init(d, config)) != 0 )
>>>>>          goto fail;
>>>>>
>>>>> +    if ( domcr_flags & DOMCRF_vuart )
>>>>> +        if ( (rc = domain_vpl011_init(d, config)) != 0 )
>>>>> +            goto fail;
>>>>>      update_domain_wallclock_time(d);
>>>>
>>>>
>>> I am planning to remove the usage of domain creation flag to check
>>> whether vuart is enabled/disabled. Please see my next comment. With
>>> that change, domain_vpl011_init() will be called always. The
>>> domain_vpl011_init() will check whether vuart is enabled or disabled
>>> in the config structure passed. If vuart is enabled then it will go
>>> ahead with vpl011 initialization else it will return without
>>> initializing vpl011.
>>
>>
>> Please don't do that. The arch code decides whether domain_vpl011_init
>> not the invert.
>
>
> I was wondering whether it would be better to defer the PL011 creation to a
> domctl. This could be called after the domain is created with all the
> information required (MMIO region, Console PFN...).
>
> This would also make the migration support more trivial as the we will not
> need to know in advance whether a UART is been used.
>
> Any opinions?

Would there be race condition where the guest tries to access the
pl011 mmio region (as the domain has been created) but pl011 is not
initialized yet as domctl is not called? What could be an appropriate
place to call this domctl? It should be before xenstore is populated
with vuart ring-ref/port information.

Regards,
Bhupinder

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

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

* Re: [PATCH 06/10 v2] xen/arm: vpl011: Add vuart ring-buf and evtchn to xenstore
  2017-05-04 20:38               ` Stefano Stabellini
@ 2017-05-05  9:52                 ` Bhupinder Thakur
  2017-05-05 18:59                   ` Stefano Stabellini
  0 siblings, 1 reply; 54+ messages in thread
From: Bhupinder Thakur @ 2017-05-05  9:52 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Wei Liu, Andrew Cooper, Ian Jackson, Julien Grall, Jan Beulich,
	xen-devel

Hi Stefano,

>> >> >> > It looks like you are reusing the libxl__device_console_add call for the
>> >> >> > main PV console for the domain, to also add the vuart nodes to xenstore.
>> >> >> >
>> >> >> > I don't think it is a good idea to mix the two. I suggest to introduce a
>> >> >> > new libxl__device call to introduce the vuart nodes to xenstore, given
>> >> >> > that they have no relantionship with the principal PV console of the
>> >> >> > domain.
>> >> >> >
>> >> >> I have a doubt here. Do I have to create a new console device
>> >> >> (libxl__device) to register the vuart console or can I use the
>> >> >> existing console device (which is used for registering the primary
>> >> >> console) to register the vuart nodes to xenstore?
>> >> >>
>> >> >> I suspect that if I try to register with the same console device then
>> >> >> libxl__device_generic_add() may fail as it is already added.
>> >> >
>> >> > The vuart we are introducing with this patch series is a new and
>> >> > different console from the existing PV console. So yes, I think we need
>> >> > to create a new device for it.
>> >> >
>> >> > We either need to introduce a brand new function to add the vuart to
>> >> > xenstore, something like libxl__device_vuart_add, or, if we are going
>> >> > to reuse libxl__device_console_add, then we we need to create both a new
>> >> > console device (libxl__device_console), and a new libxl__device for it.
>> >> > For clarity, libxl__device_console is the input parameter of
>> >> > libxl__device_console_add, while libxl__device is the output parameter.
>> >> >
>> >> I am trying to add a new vuart device by defining a new device type
>> >> LIBXL__DEVICE_KIND_VUART  and a new function
>> >> libxl__device_vuart_add().
>> >
>> > I think that is the right way to do it.
>> >
>> >
>> >> This function basically adds the vuart ring-ref ("0/ring-ref") and
>> >> port ("0/port") to ro_front array and then it registers the device
>> >> using the libxl__device_generic_add(). I pass NULL to "back" and
>> >> "front" array arguments to  libxl__device_generic_add() as I am adding
>> >> parameters only to "ro_front" array.
>> >>
>> >> I am adding the device at /local/domain/<domid>/vuart.
>> >>
>> >> However, xenconsoled fails to read the vuart ring-ref and port saying
>> >> "no such directory or file".I verified that
>> >> libxl__device_generic_add() is returning successfully.
>> >>
>> >> In xenconsoled, I verified that I am reading
>> >> /local/domain/<domid>/vuart/0/ring-ref and
>> >> /local/domain/<domid>/vuart/0/port.
>> >>
>> >> It is not clear why xenconsoled fails to read the values.
>> >
>> > Double check the permissions of those nodes with xenstore-ls -p. Make
>> > sure there are no races between libxl writing the nodes and xenconsoled
>> > reading them.
>>
>> xenstore-ls -p" shows that the vuart node is created successfully. I
>> have pasted below the relevant part of the command output:
>>
>>    vuart = ""   (n0,r1)
>>     backend = "/local/domain/0/backend/vuart/1/0"   (n0,r1)
>
> Why is this here instead of under vuart/0?
> Also, if these are the frontend nodes, where are the backend vuart nodes?

I created only frontend nodes so that xenconsoled could access
ring-ref/port. I understand that backend nodes are required for guest
domains to access some backend information. Since in this case guest
domain does not need such information I did not create the backend
node. Kindly let me know if my understanding is correct.
>
>
>>     0 = ""   (n0,r1)
>>      port = "1"   (n0,r1)
>>      ring-ref = "233475"   (n0,r1)
>>      limit = "1048576"   (n0,r1)
>>      type = "xenconsoled"   (n0,r1)
>>    console = ""   (n0,r1)
>>     backend = "/local/domain/0/backend/console/1/0"   (n0,r1)
>>     backend-id = "0"   (n1,r0)
>>     limit = "1048576"   (n0,r1)
>>     type = "xenconsoled"   (n0,r1)
>>     output = "pty"   (n0,r1)
>>     tty = "/dev/pts/0"   (n0,r1)
>>     port = "3"   (n0,r1)
>>     ring-ref = "233472"   (n0,r1)
>>
>> The vuart node exists at /local/domain/1/vuart. I am creating the
>> vuart node just before the pv console node to make sure that vuart
>> node becomes visible before the pv console node is created. The values
>> are populated properly in the vuart node. Still when xenconsoled tries
>> to read /loca/domain/1/vuart/0/ring-ref or
>> /loca/domain/1/vuart/0/port, the read fails.
>>
>> PV console node reads happen properly even though both nodes exist at
>> the same level and their access permissions are also same.
>
> I don't know. I would add more debug printfs to the code until I
> understood what was going on.
There was one issue in domain_create_ring() where if the vuart node
was populated later then it was not able to be open the tty session
since the check was based on whether pv tty was initialized (which was
initialized earlier).

Earlier, this was not the case since vuart and pv xenstore parameters
were always available together.

I have defined a new function console_create_ring() which is called
for both consoles. This new function removes lot of duplicate code for
pv and vuart consoles in domain_create_ring(). With this change, both
the consoles are working fine now.

Regards,
Bhupinder

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

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

* Re: [PATCH 01/10 v2] xen/arm: vpl011: Add pl011 uart emulation in Xen
  2017-05-02 16:02   ` Julien Grall
@ 2017-05-05 11:18     ` Bhupinder Thakur
  2017-05-05 13:27       ` Julien Grall
  0 siblings, 1 reply; 54+ messages in thread
From: Bhupinder Thakur @ 2017-05-05 11:18 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Jan Beulich, Andre Przywara, xen-devel

Hi Julien,

>> +
>> +unsigned int vpl011_reg_mask[] = {0xff, 0xffff, 0xffffffff};
>
>
> This should be static. But I don't get what you need that. In the first
> version, I suggested to re-purpose vgic_reg*_{extract,update} so we can use
> it here. It would probably need to be renamed to vreg_reg*.
>
> I don't see any reason to not do that and re-inventing the wheel.

I understand that the vreg_reg* functions are handy in scenarios where
user may want to access the data at some offset from the register base
address. The SBSA spec specifies that the base address of the access
must be same as the base address of the register. So in this case the
offset would always be 0. That is the reason I used a simple mask to
return 8-bit, 16-bit and 32-bit values.
>
>> +
>> +static void vgic_inject_vpl011_spi(struct domain *d)
>> +{
>> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
>> +
>> +    if ( (vpl011->uartris & vpl011->uartimsc) )
>> +        vgic_vcpu_inject_spi(d, GUEST_VPL011_SPI);
>> +}
>
>
> PL011 is using level interrupt which means that you should not inject
> interrupt but instead set or clear the pending interrupt.
>
> However, the problem is because the vGIC is incapable to handle properly
> level interrupt. This is going to be a major problem as the interrupt should
> stay pending until the pl011 emulation says there are no more interrupts to
> handle.
>
> For instance, you may miss character if the guest driver had not enough
> space to read character new one because the interrupt will not get
> re-injected.
>
> I am not asking to modify the vGIC in order to handle level properly (Andre
> in CC is looking at that). But we need to get the code in correct shape in
> order to handle properly pl011 interrupt.
>
> By that I mean, at least the naming of the function (I haven't read the rest
> to know what is missing). I.e I would rename to vpl011_update(...).
Should I define two functions vgic_vpl011_spi_set() and
vgic_vpl011_spi_clear()? For now, I can keep vgic_vpl011_spi_clear()
empty and rename
vgic_inject_vpl011_spi() to vgic_vpl011_spi_set(). I will call
vgic_vpl011_spi_clear() at all places where IN ring buffer has become
empty.

>
>> +static int vpl011_mmio_read(struct vcpu *v, mmio_info_t *info, register_t
>> *r, void *priv)
>> +{
>> +    uint8_t ch;
>> +    struct hsr_dabt dabt = info->dabt;
>> +    int vpl011_reg = (int)(info->gpa - GUEST_PL011_BASE);
>> +    struct vpl011_s *vpl011 = &v->domain->arch.vpl011;
>> +
>> +    switch ( vpl011_reg )
>> +    {
>> +    case DR:
>
>
> As said on the first version, all those registers have specific size. Please
> have a look at how we handle register emulation in the vgic with VREG*.
Since SBSA specs mandate that pl011 register accesses must always be
accessed using the register base address, I am using the register base
address here instead of an address range.
>
>> +        if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
>> +        vpl011_read_data(v->domain, &ch);
>> +        *r = ch;
>> +        break;
>> +
>> +    case RSR:
>> +        if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;
>> +
>> +        /* It always returns 0 as there are no physical errors. */
>> +        *r = 0;
>> +        break;
>> +
>> +    case FR:
>> +        if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;
>> +        *r = (vpl011->uartfr & vpl011_reg_mask[dabt.size]);
>
>
> Pointless ().
>
I will remove () at all relevant places.

>> +
>> +write_ignore:
>> +    if ( !VALID_BW_SIZE(dabt.size) ) goto bad_width;
>
>
> Why? Looking at the spec, write-ignore register does not have specific
> access size.
I will check.

>
>> +    return 1;
>> +
>> +word_write_ignore:
>> +    if ( !VALID_W_SIZE(dabt.size) ) goto bad_width;
>> +    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,
>> +};
>> +
>> +int vpl011_map_guest_page(struct domain *d, unsigned long pfn)
>
>
> Please don't use the term pfn as we don't know whether it refers to the
> guest frame number (GFN) or machine frame number (MFN).
>
> So in this case, I think it is gfn. Also s/unsigned long/gfn_t/
>
ok.
>
>> +{
>> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
>> +
>> +    /* Map the guest PFN to Xen address space. */
>> +    return prepare_ring_for_helper(d,
>> +                                   pfn,
>> +                                   &vpl011->ring_page,
>> +                                   &vpl011->ring_buf);
>> +}
>> +
>> +static void vpl011_data_avail(struct domain *d)
>> +{
>> +    unsigned long flags;
>> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
>> +    struct xencons_interface *intf = vpl011->ring_buf;
>> +    uint32_t in_ring_depth, out_ring_depth;
>> +
>> +    VPL011_LOCK(d, flags);
>> +
>> +    in_ring_depth = intf->in_prod - intf->in_cons;
>> +    out_ring_depth = intf->out_prod - intf->out_cons;
>> +
>> +    /* Update the uart rx state if the buffer is not empty. */
>> +    if ( in_ring_depth != 0 )
>> +    {
>> +        vpl011->uartfr &= ~(RXFE);
>
>
> Pointless ()
>
I will remove () from all relevant places.

>
>> +        }
>> +    }
>> +
>> +    VPL011_UNLOCK(d, flags);
>> +
>> +    vgic_inject_vpl011_spi(d);
>> +}
>> +
>> +
>> +static void vpl011_notification(struct vcpu *v, unsigned int port)
>> +{
>> +    vpl011_data_avail(v->domain);
>> +}
>> +
>> +int domain_vpl011_init(struct domain *d, struct xen_arch_domainconfig
>> *config)
>> +{
>> +    int rc;
>> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
>> +
>> +    rc = alloc_unbound_xen_event_channel(d, 0, config->console_domid,
>> +                                         vpl011_notification);
>> +    if (rc < 0)
>> +    {
>> +        return rc;
>> +    }
>> +
>> +    vpl011->evtchn = rc;
>> +    rc = vgic_reserve_virq(d, GUEST_VPL011_SPI);
>> +    if ( !rc )
>> +    {
>> +        free_xen_event_channel(d, vpl011->evtchn);
>> +        vpl011->evtchn = -1;
>> +        return rc;
>> +    }
>> +    register_mmio_handler(d, &vpl011_mmio_handler, GUEST_PL011_BASE,
>> GUEST_PL011_SIZE, NULL);
>> +    spin_lock_init(&vpl011->lock);
>> +
>> +    vpl011->initialized = true;
>> +
>> +    return 0;
>> +}
>> +
>> +void domain_vpl011_deinit(struct domain *d)
>> +{
>> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
>> +
>> +    if ( vpl011->initialized )
>> +    {
>> +        free_xen_event_channel(d, vpl011->evtchn);
>> +        destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
>> +    }
>> +    vpl011->initialized = false;
>> +}
>
>
> Missing Emacs magic.
Can you please elaborate this comment?

>>
>>  struct hvm_domain
>>  {
>> @@ -133,6 +134,8 @@ struct arch_domain
>>      struct {
>>          uint8_t privileged_call_enabled : 1;
>>      } monitor;
>> +
>> +    struct vpl011_s vpl011;
>
>
> This should be guard by #ifdef CONFIG_VPL011_CONSOLE.
>
ok.

>> +#ifndef _VPL011_H_
>> +
>> +#define _VPL011_H_
>> +
>> +/* helper macros */
>> +#define VPL011_RING_DEPTH(intf,dir) (((intf)->dir ## _prod - (intf)->dir
>> ## _cons))
>> +
>> +#define VPL011_RING_MAX_DEPTH(intf,dir) (sizeof((intf)->dir)-1)
>> +
>> +#define VPL011_IN_RING_EMPTY(intf) (VPL011_RING_DEPTH(intf, in) == 0)
>> +
>> +#define VPL011_OUT_RING_EMPTY(intf) (VPL011_RING_DEPTH(intf, out) == 0)
>> +
>> +#define VPL011_IN_RING_FULL(intf) (VPL011_RING_DEPTH(intf, in) ==
>> VPL011_RING_MAX_DEPTH(intf, in))
>> +
>> +#define VPL011_OUT_RING_FULL(intf) (VPL011_RING_DEPTH(intf, out) ==
>> VPL011_RING_MAX_DEPTH(intf,out))
>> +
>> +#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)
>> +
>> +#define VALID_BW_SIZE(size) ( size == DABT_BYTE || size == DABT_HALF_WORD
>> || size == DABT_WORD )
>> +#define VALID_W_SIZE(size)  ( size == DABT_HALF_WORD || size == DABT_WORD
>> )
>
>
> The header should only contain what needs to be used by other code. In this
> case we don't want anyone to use VALID_*_SIZE.
>
> Also, I find the name quite confusing, it is not clear when to use which
> one. Looking at the SBSA (6.2 in ARM-DEN-0029 v3.0): "if an access size not
> listed in the table is used, the results are IMPLEMENTATION DEFINED".
>
> In order to get the code simple I would handle all 32bits register in the
> same way (e.g 8-bits, 16-bits and 32-bits access always allowed).
>
> So I would introduce a static inline helper vpl011_reg32_check_access that
> check the return we don't use 64-bit access.
>
ok.
>

Regards,
Bhupinder

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

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

* Re: [PATCH 01/10 v2] xen/arm: vpl011: Add pl011 uart emulation in Xen
  2017-05-05 11:18     ` Bhupinder Thakur
@ 2017-05-05 13:27       ` Julien Grall
  2017-05-06  5:20         ` Bhupinder Thakur
  0 siblings, 1 reply; 54+ messages in thread
From: Julien Grall @ 2017-05-05 13:27 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Jan Beulich, Andre Przywara, xen-devel



On 05/05/17 12:18, Bhupinder Thakur wrote:
> Hi Julien,

Hi Bhupinder,

>>> +
>>> +unsigned int vpl011_reg_mask[] = {0xff, 0xffff, 0xffffffff};
>>
>>
>> This should be static. But I don't get what you need that. In the first
>> version, I suggested to re-purpose vgic_reg*_{extract,update} so we can use
>> it here. It would probably need to be renamed to vreg_reg*.
>>
>> I don't see any reason to not do that and re-inventing the wheel.
>
> I understand that the vreg_reg* functions are handy in scenarios where
> user may want to access the data at some offset from the register base
> address. The SBSA spec specifies that the base address of the access
> must be same as the base address of the register. So in this case the
> offset would always be 0. That is the reason I used a simple mask to
> return 8-bit, 16-bit and 32-bit values.

The part "The SBSA spec specifies that the base address of the 
access..." should have been specified in the commit message because 
reading at the PL011 spec, I don't see this limit.

The reason of using vreg_reg* is to have all MMIOs emulation using the 
same helpers and avoid everyone to re-invent the wheel because you can 
"optimize" for your case.

Also, it is also more obvious to read vreg_reg32_update(...) than "& 
vpl011_reg_mask[dabt.size]". This would avoid quite a lot rework if we 
ever decide to modify the reg emulation.

>>
>>> +
>>> +static void vgic_inject_vpl011_spi(struct domain *d)
>>> +{
>>> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
>>> +
>>> +    if ( (vpl011->uartris & vpl011->uartimsc) )
>>> +        vgic_vcpu_inject_spi(d, GUEST_VPL011_SPI);
>>> +}
>>
>>
>> PL011 is using level interrupt which means that you should not inject
>> interrupt but instead set or clear the pending interrupt.
>>
>> However, the problem is because the vGIC is incapable to handle properly
>> level interrupt. This is going to be a major problem as the interrupt should
>> stay pending until the pl011 emulation says there are no more interrupts to
>> handle.
>>
>> For instance, you may miss character if the guest driver had not enough
>> space to read character new one because the interrupt will not get
>> re-injected.
>>
>> I am not asking to modify the vGIC in order to handle level properly (Andre
>> in CC is looking at that). But we need to get the code in correct shape in
>> order to handle properly pl011 interrupt.
>>
>> By that I mean, at least the naming of the function (I haven't read the rest
>> to know what is missing). I.e I would rename to vpl011_update(...).
> Should I define two functions vgic_vpl011_spi_set() and
> vgic_vpl011_spi_clear()? For now, I can keep vgic_vpl011_spi_clear()
> empty and rename
> vgic_inject_vpl011_spi() to vgic_vpl011_spi_set(). I will call
> vgic_vpl011_spi_clear() at all places where IN ring buffer has become
> empty.

The code should only call a function vpl011_update that will clear or 
set the line. I don't see why it would need to specifically call clear/set.

>
>>
>>> +static int vpl011_mmio_read(struct vcpu *v, mmio_info_t *info, register_t
>>> *r, void *priv)
>>> +{
>>> +    uint8_t ch;
>>> +    struct hsr_dabt dabt = info->dabt;
>>> +    int vpl011_reg = (int)(info->gpa - GUEST_PL011_BASE);
>>> +    struct vpl011_s *vpl011 = &v->domain->arch.vpl011;
>>> +
>>> +    switch ( vpl011_reg )
>>> +    {
>>> +    case DR:
>>
>>
>> As said on the first version, all those registers have specific size. Please
>> have a look at how we handle register emulation in the vgic with VREG*.
> Since SBSA specs mandate that pl011 register accesses must always be
> accessed using the register base address, I am using the register base
> address here instead of an address range.

Then it should have been written in the commit message. I made this 
comment on the previous version and didn't see any answer from you. So I 
considered you forgot to address it.

A general rule is to answer on the review e-mail or specify after "---" 
why you didn't address a comment so we know why it has not been done. 
Reviewers may guess wrong why you didn't do it :).

[...]

>> Missing Emacs magic.
> Can you please elaborate this comment?

All files in Xen contains the below lines to help e-macs to load the 
correct format:

/*
  * Local variables:
  * mode: C
  * c-file-style: "BSD"
  * c-basic-offset: 4
  * indent-tabs-mode: nil
  * End:
  */

This should be added on any new files using Xen coding style.

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 03/10 v2] xen/arm: vpl011: Enable pl011 emulation for a guest domain in Xen
  2017-05-05  7:10           ` Bhupinder Thakur
@ 2017-05-05 13:43             ` Julien Grall
  2017-05-08  6:34               ` Bhupinder Thakur
  2017-05-11 10:35               ` Wei Liu
  0 siblings, 2 replies; 54+ messages in thread
From: Julien Grall @ 2017-05-05 13:43 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Jan Beulich, xen-devel

On 05/05/17 08:10, Bhupinder Thakur wrote:
> Hi Julien,

Hi Bhupinder,

>>>> Hi Jan,
>>>>
>>>>>> @@ -631,6 +632,9 @@ int arch_domain_create(struct domain *d,
>>>>>> unsigned int domcr_flags,
>>>>>>      if ( (rc = domain_vtimer_init(d, config)) != 0 )
>>>>>>          goto fail;
>>>>>>
>>>>>> +    if ( domcr_flags & DOMCRF_vuart )
>>>>>> +        if ( (rc = domain_vpl011_init(d, config)) != 0 )
>>>>>> +            goto fail;
>>>>>>      update_domain_wallclock_time(d);
>>>>>
>>>>>
>>>> I am planning to remove the usage of domain creation flag to check
>>>> whether vuart is enabled/disabled. Please see my next comment. With
>>>> that change, domain_vpl011_init() will be called always. The
>>>> domain_vpl011_init() will check whether vuart is enabled or disabled
>>>> in the config structure passed. If vuart is enabled then it will go
>>>> ahead with vpl011 initialization else it will return without
>>>> initializing vpl011.
>>>
>>>
>>> Please don't do that. The arch code decides whether domain_vpl011_init
>>> not the invert.
>>
>>
>> I was wondering whether it would be better to defer the PL011 creation to a
>> domctl. This could be called after the domain is created with all the
>> information required (MMIO region, Console PFN...).
>>
>> This would also make the migration support more trivial as the we will not
>> need to know in advance whether a UART is been used.
>>
>> Any opinions?
>
> Would there be race condition where the guest tries to access the
> pl011 mmio region (as the domain has been created) but pl011 is not
> initialized yet as domctl is not called? What could be an appropriate
> place to call this domctl? It should be before xenstore is populated
> with vuart ring-ref/port information.

There are no race condition. The domain will only be started when 
everything has been created by calling XEN_DOMCTL_unpausedomain.

The DOMCTL createdomain only initialize the basic structure for the 
domain, after the hypercall the domain is not in state to be run 
because, for instance, the vCPUs were not allocated (see 
XEN_DOMCTL_max_vcpus) and the guest RAM were not populated.

I am not very familiar with the libxl code, but I think 
libxl__arch_domain_create should be a good candidate. I will let Ian and 
Wei confirm that.

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 06/10 v2] xen/arm: vpl011: Add vuart ring-buf and evtchn to xenstore
  2017-05-05  9:52                 ` Bhupinder Thakur
@ 2017-05-05 18:59                   ` Stefano Stabellini
  2017-05-08  5:37                     ` Bhupinder Thakur
  0 siblings, 1 reply; 54+ messages in thread
From: Stefano Stabellini @ 2017-05-05 18:59 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich, xen-devel

On Fri, 5 May 2017, Bhupinder Thakur wrote:
> Hi Stefano,
> 
> >> >> >> > It looks like you are reusing the libxl__device_console_add call for the
> >> >> >> > main PV console for the domain, to also add the vuart nodes to xenstore.
> >> >> >> >
> >> >> >> > I don't think it is a good idea to mix the two. I suggest to introduce a
> >> >> >> > new libxl__device call to introduce the vuart nodes to xenstore, given
> >> >> >> > that they have no relantionship with the principal PV console of the
> >> >> >> > domain.
> >> >> >> >
> >> >> >> I have a doubt here. Do I have to create a new console device
> >> >> >> (libxl__device) to register the vuart console or can I use the
> >> >> >> existing console device (which is used for registering the primary
> >> >> >> console) to register the vuart nodes to xenstore?
> >> >> >>
> >> >> >> I suspect that if I try to register with the same console device then
> >> >> >> libxl__device_generic_add() may fail as it is already added.
> >> >> >
> >> >> > The vuart we are introducing with this patch series is a new and
> >> >> > different console from the existing PV console. So yes, I think we need
> >> >> > to create a new device for it.
> >> >> >
> >> >> > We either need to introduce a brand new function to add the vuart to
> >> >> > xenstore, something like libxl__device_vuart_add, or, if we are going
> >> >> > to reuse libxl__device_console_add, then we we need to create both a new
> >> >> > console device (libxl__device_console), and a new libxl__device for it.
> >> >> > For clarity, libxl__device_console is the input parameter of
> >> >> > libxl__device_console_add, while libxl__device is the output parameter.
> >> >> >
> >> >> I am trying to add a new vuart device by defining a new device type
> >> >> LIBXL__DEVICE_KIND_VUART  and a new function
> >> >> libxl__device_vuart_add().
> >> >
> >> > I think that is the right way to do it.
> >> >
> >> >
> >> >> This function basically adds the vuart ring-ref ("0/ring-ref") and
> >> >> port ("0/port") to ro_front array and then it registers the device
> >> >> using the libxl__device_generic_add(). I pass NULL to "back" and
> >> >> "front" array arguments to  libxl__device_generic_add() as I am adding
> >> >> parameters only to "ro_front" array.
> >> >>
> >> >> I am adding the device at /local/domain/<domid>/vuart.
> >> >>
> >> >> However, xenconsoled fails to read the vuart ring-ref and port saying
> >> >> "no such directory or file".I verified that
> >> >> libxl__device_generic_add() is returning successfully.
> >> >>
> >> >> In xenconsoled, I verified that I am reading
> >> >> /local/domain/<domid>/vuart/0/ring-ref and
> >> >> /local/domain/<domid>/vuart/0/port.
> >> >>
> >> >> It is not clear why xenconsoled fails to read the values.
> >> >
> >> > Double check the permissions of those nodes with xenstore-ls -p. Make
> >> > sure there are no races between libxl writing the nodes and xenconsoled
> >> > reading them.
> >>
> >> xenstore-ls -p" shows that the vuart node is created successfully. I
> >> have pasted below the relevant part of the command output:
> >>
> >>    vuart = ""   (n0,r1)
> >>     backend = "/local/domain/0/backend/vuart/1/0"   (n0,r1)
> >
> > Why is this here instead of under vuart/0?
> > Also, if these are the frontend nodes, where are the backend vuart nodes?
> 
> I created only frontend nodes so that xenconsoled could access
> ring-ref/port. I understand that backend nodes are required for guest
> domains to access some backend information. Since in this case guest
> domain does not need such information I did not create the backend
> node. Kindly let me know if my understanding is correct.

If there are no backend xenstore nodes, why do we have:

  backend = "/local/domain/0/backend/vuart/1/0"

on Xenstore?




> >
> >
> >>     0 = ""   (n0,r1)
> >>      port = "1"   (n0,r1)
> >>      ring-ref = "233475"   (n0,r1)
> >>      limit = "1048576"   (n0,r1)
> >>      type = "xenconsoled"   (n0,r1)
> >>    console = ""   (n0,r1)
> >>     backend = "/local/domain/0/backend/console/1/0"   (n0,r1)
> >>     backend-id = "0"   (n1,r0)
> >>     limit = "1048576"   (n0,r1)
> >>     type = "xenconsoled"   (n0,r1)
> >>     output = "pty"   (n0,r1)
> >>     tty = "/dev/pts/0"   (n0,r1)
> >>     port = "3"   (n0,r1)
> >>     ring-ref = "233472"   (n0,r1)


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

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

* Re: [PATCH 01/10 v2] xen/arm: vpl011: Add pl011 uart emulation in Xen
  2017-05-05 13:27       ` Julien Grall
@ 2017-05-06  5:20         ` Bhupinder Thakur
  0 siblings, 0 replies; 54+ messages in thread
From: Bhupinder Thakur @ 2017-05-06  5:20 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Jan Beulich, Andre Przywara, xen-devel

Hi Julien,

>>>> +unsigned int vpl011_reg_mask[] = {0xff, 0xffff, 0xffffffff};
>>>
>>>
>>>
>>> This should be static. But I don't get what you need that. In the first
>>> version, I suggested to re-purpose vgic_reg*_{extract,update} so we can
>>> use
>>> it here. It would probably need to be renamed to vreg_reg*.
>>>
>>> I don't see any reason to not do that and re-inventing the wheel.
>>
>>
>> I understand that the vreg_reg* functions are handy in scenarios where
>> user may want to access the data at some offset from the register base
>> address. The SBSA spec specifies that the base address of the access
>> must be same as the base address of the register. So in this case the
>> offset would always be 0. That is the reason I used a simple mask to
>> return 8-bit, 16-bit and 32-bit values.
>
>
> The part "The SBSA spec specifies that the base address of the access..."
> should have been specified in the commit message because reading at the
> PL011 spec, I don't see this limit.
>
> The reason of using vreg_reg* is to have all MMIOs emulation using the same
> helpers and avoid everyone to re-invent the wheel because you can "optimize"
> for your case.
>
> Also, it is also more obvious to read vreg_reg32_update(...) than "&
> vpl011_reg_mask[dabt.size]". This would avoid quite a lot rework if we ever
> decide to modify the reg emulation.
>
ok. I will redefine the vgic_reg* functions to generic vreg_reg* and
move the definitions to vreg.h, so that those can be used by vpl011
also.
+
>
>>>
>>>> +
>>>> +static void vgic_inject_vpl011_spi(struct domain *d)
>>>> +{
>>>> +    struct vpl011_s *vpl011 = &d->arch.vpl011;
>>>> +
>>>> +    if ( (vpl011->uartris & vpl011->uartimsc) )
>>>> +        vgic_vcpu_inject_spi(d, GUEST_VPL011_SPI);
>>>> +}
>>>
>>>
>>>
>>> PL011 is using level interrupt which means that you should not inject
>>> interrupt but instead set or clear the pending interrupt.
>>>
>>> However, the problem is because the vGIC is incapable to handle properly
>>> level interrupt. This is going to be a major problem as the interrupt
>>> should
>>> stay pending until the pl011 emulation says there are no more interrupts
>>> to
>>> handle.
>>>
>>> For instance, you may miss character if the guest driver had not enough
>>> space to read character new one because the interrupt will not get
>>> re-injected.
>>>
>>> I am not asking to modify the vGIC in order to handle level properly
>>> (Andre
>>> in CC is looking at that). But we need to get the code in correct shape
>>> in
>>> order to handle properly pl011 interrupt.
>>>
>>> By that I mean, at least the naming of the function (I haven't read the
>>> rest
>>> to know what is missing). I.e I would rename to vpl011_update(...).
>>
>> Should I define two functions vgic_vpl011_spi_set() and
>> vgic_vpl011_spi_clear()? For now, I can keep vgic_vpl011_spi_clear()
>> empty and rename
>> vgic_inject_vpl011_spi() to vgic_vpl011_spi_set(). I will call
>> vgic_vpl011_spi_clear() at all places where IN ring buffer has become
>> empty.
>
>
> The code should only call a function vpl011_update that will clear or set
> the line. I don't see why it would need to specifically call clear/set.
>
ok. I will rename vgic_inject_vpl011_spi() to vpl011_update_irq().

>>
>>>
>>>> +static int vpl011_mmio_read(struct vcpu *v, mmio_info_t *info,
>>>> register_t
>>>> *r, void *priv)
>>>> +{
>>>> +    uint8_t ch;
>>>> +    struct hsr_dabt dabt = info->dabt;
>>>> +    int vpl011_reg = (int)(info->gpa - GUEST_PL011_BASE);
>>>> +    struct vpl011_s *vpl011 = &v->domain->arch.vpl011;
>>>> +
>>>> +    switch ( vpl011_reg )
>>>> +    {
>>>> +    case DR:
>>>
>>>
>>>
>>> As said on the first version, all those registers have specific size.
>>> Please
>>> have a look at how we handle register emulation in the vgic with VREG*.
>>
>> Since SBSA specs mandate that pl011 register accesses must always be
>> accessed using the register base address, I am using the register base
>> address here instead of an address range.
>
>
> Then it should have been written in the commit message. I made this comment
> on the previous version and didn't see any answer from you. So I considered
> you forgot to address it.
>
> A general rule is to answer on the review e-mail or specify after "---" why
> you didn't address a comment so we know why it has not been done. Reviewers
> may guess wrong why you didn't do it :).
ok. I will update the commit message accordingly.

>
> [...]
>
>>> Missing Emacs magic.
>>
>> Can you please elaborate this comment?
>
>
> All files in Xen contains the below lines to help e-macs to load the correct
> format:
>
> /*
>  * Local variables:
>  * mode: C
>  * c-file-style: "BSD"
>  * c-basic-offset: 4
>  * indent-tabs-mode: nil
>  * End:
>  */>
> This should be added on any new files using Xen coding style.
>
Thanks. I will add this to the new files.

Regards,
Bhupinder

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

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

* Re: [PATCH 06/10 v2] xen/arm: vpl011: Add vuart ring-buf and evtchn to xenstore
  2017-05-05 18:59                   ` Stefano Stabellini
@ 2017-05-08  5:37                     ` Bhupinder Thakur
  0 siblings, 0 replies; 54+ messages in thread
From: Bhupinder Thakur @ 2017-05-08  5:37 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Wei Liu, Andrew Cooper, Ian Jackson, Julien Grall, Jan Beulich,
	xen-devel

Hi Stefano,

>> >> >> >> > It looks like you are reusing the libxl__device_console_add call for the
>> >> >> >> > main PV console for the domain, to also add the vuart nodes to xenstore.
>> >> >> >> >
>> >> >> >> > I don't think it is a good idea to mix the two. I suggest to introduce a
>> >> >> >> > new libxl__device call to introduce the vuart nodes to xenstore, given
>> >> >> >> > that they have no relantionship with the principal PV console of the
>> >> >> >> > domain.
>> >> >> >> >
>> >> >> >> I have a doubt here. Do I have to create a new console device
>> >> >> >> (libxl__device) to register the vuart console or can I use the
>> >> >> >> existing console device (which is used for registering the primary
>> >> >> >> console) to register the vuart nodes to xenstore?
>> >> >> >>
>> >> >> >> I suspect that if I try to register with the same console device then
>> >> >> >> libxl__device_generic_add() may fail as it is already added.
>> >> >> >
>> >> >> > The vuart we are introducing with this patch series is a new and
>> >> >> > different console from the existing PV console. So yes, I think we need
>> >> >> > to create a new device for it.
>> >> >> >
>> >> >> > We either need to introduce a brand new function to add the vuart to
>> >> >> > xenstore, something like libxl__device_vuart_add, or, if we are going
>> >> >> > to reuse libxl__device_console_add, then we we need to create both a new
>> >> >> > console device (libxl__device_console), and a new libxl__device for it.
>> >> >> > For clarity, libxl__device_console is the input parameter of
>> >> >> > libxl__device_console_add, while libxl__device is the output parameter.
>> >> >> >
>> >> >> I am trying to add a new vuart device by defining a new device type
>> >> >> LIBXL__DEVICE_KIND_VUART  and a new function
>> >> >> libxl__device_vuart_add().
>> >> >
>> >> > I think that is the right way to do it.
>> >> >
>> >> >
>> >> >> This function basically adds the vuart ring-ref ("0/ring-ref") and
>> >> >> port ("0/port") to ro_front array and then it registers the device
>> >> >> using the libxl__device_generic_add(). I pass NULL to "back" and
>> >> >> "front" array arguments to  libxl__device_generic_add() as I am adding
>> >> >> parameters only to "ro_front" array.
>> >> >>
>> >> >> I am adding the device at /local/domain/<domid>/vuart.
>> >> >>
>> >> >> However, xenconsoled fails to read the vuart ring-ref and port saying
>> >> >> "no such directory or file".I verified that
>> >> >> libxl__device_generic_add() is returning successfully.
>> >> >>
>> >> >> In xenconsoled, I verified that I am reading
>> >> >> /local/domain/<domid>/vuart/0/ring-ref and
>> >> >> /local/domain/<domid>/vuart/0/port.
>> >> >>
>> >> >> It is not clear why xenconsoled fails to read the values.
>> >> >
>> >> > Double check the permissions of those nodes with xenstore-ls -p. Make
>> >> > sure there are no races between libxl writing the nodes and xenconsoled
>> >> > reading them.
>> >>
>> >> xenstore-ls -p" shows that the vuart node is created successfully. I
>> >> have pasted below the relevant part of the command output:
>> >>
>> >>    vuart = ""   (n0,r1)
>> >>     backend = "/local/domain/0/backend/vuart/1/0"   (n0,r1)
>> >
>> > Why is this here instead of under vuart/0?
>> > Also, if these are the frontend nodes, where are the backend vuart nodes?
>>
>> I created only frontend nodes so that xenconsoled could access
>> ring-ref/port. I understand that backend nodes are required for guest
>> domains to access some backend information. Since in this case guest
>> domain does not need such information I did not create the backend
>> node. Kindly let me know if my understanding is correct.
>
> If there are no backend xenstore nodes, why do we have:
>
>   backend = "/local/domain/0/backend/vuart/1/0"
>
> on Xenstore?
>
libxl__device_generic_add() creates the references to backend and
frontend even if those nodes are not created (i.e. the node
information passed to the function are null). I will add a check in
libxl__device_generic_add() to add these references only if the
corresponding nodes have been created in xenstore.

Regards,
Bhupinder

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

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

* Re: [PATCH 07/10 v2] xen/arm: vpl011: Add support for vuart in xenconsole
  2017-04-28 23:10   ` Stefano Stabellini
@ 2017-05-08  6:18     ` Bhupinder Thakur
  0 siblings, 0 replies; 54+ messages in thread
From: Bhupinder Thakur @ 2017-05-08  6:18 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Wei Liu, Andrew Cooper, Ian Jackson, Julien Grall, Jan Beulich,
	xen-devel

Hi Stefano,

On 29 April 2017 at 04:40, Stefano Stabellini <sstabellini@kernel.org> wrote:
> On Fri, 28 Apr 2017, Bhupinder Thakur wrote:
>> Xenconsole supports only PV console currently. This patch adds support
>> for vuart, which allows emulated pl011 uart to be accessed as a console.
>>
>> This patch modifies different data structures and APIs used
>> in xenconsole to support two console types: PV and VUART.
>>
>> Change summary:
>>
>> 1. Split the domain structure into a console structure and the
>>    domain structure. Each PV and VUART will have seprate console
>>    structures.
>>
>> 2. Modify different APIs such as buffer_append() etc. to take
>>    console structure as input and perform per console specific
>>    operations.
>>
>> 3. Modfications in domain_create_ring():
>>     - Bind to the vpl011 event channel obtained from the xen store as a
>>       new parameter.
>>     - Map the PFN to its address space to be used as IN/OUT ring
>>       buffers.
>>       It obtains the PFN from the xen store as a new parameter
>>
>> 4. Modifications in handle_ring_read() to handle both PV and VUART
>>    events.
>>
>> 5. Add a new log_file for VUART console logs.
>
> This patch is too big. It might be best to split this patch in two: one
> to refactor the code to introduce struct console, and the other to
> introduce the vuart console.  It would make it far easier to review.
>
Ok. I have split the changes into two patches as suggested.

>
>> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
>> ---
>>
>> Changes since v1:
>>
>> - Split the domain struture to a separate console structure
>> - Modified the functions to operate on the console struture
>> - Replaced repetitive per console code with generic code
>>
>>  tools/console/daemon/io.c | 514 ++++++++++++++++++++++++++++++++--------------
>>  1 file changed, 365 insertions(+), 149 deletions(-)
>>
>> diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
>> index 7e6a886..55fda37 100644
>> --- a/tools/console/daemon/io.c
>> +++ b/tools/console/daemon/io.c
>> @@ -61,6 +61,10 @@
>>  /* Duration of each time period in ms */
>>  #define RATE_LIMIT_PERIOD 200
>>
>> +#define MAX_CONSOLE 2
>> +#define CONSOLE_TYPE_PV 0
>> +#define CONSOLE_TYPE_VUART 1
>
> It would be nice to protect this by something like:
>
> #ifdef CONFIG_ARM64 && CONFIG_ACPI
>
Why is there a dependency on ACPI?

> so that we don't waste memory in all other cases. The end result would
> be to have an console array of only one element on arm32 and x86 and
> when acpi is disabled.
>
>
>>  extern int log_reload;
>>  extern int log_guest;
>>  extern int log_hv;
>> @@ -89,29 +93,75 @@ struct buffer {
>>       size_t max_capacity;
>>  };
>>
>> -struct domain {
>> -     int domid;
>> +struct console {
>> +     char *name;
>> +     char *ttyname;
>>       int master_fd;
>>       int master_pollfd_idx;
>>       int slave_fd;
>>       int log_fd;
>> -     bool is_dead;
>> -     unsigned last_seen;
>>       struct buffer buffer;
>> -     struct domain *next;
>> -     char *conspath;
>>       int ring_ref;
>>       xenevtchn_port_or_error_t local_port;
>>       xenevtchn_port_or_error_t remote_port;
>> +     struct xencons_interface *interface;
>> +     struct domain *d;  /* Reference to the domain it is contained in. */
>> +};
>> +
>> +struct domain {
>> +     int domid;
>> +     bool is_dead;
>> +     unsigned last_seen;
>> +     struct domain *next;
>> +     char *conspath;
>>       xenevtchn_handle *xce_handle;
>>       int xce_pollfd_idx;
>> -     struct xencons_interface *interface;
>>       int event_count;
>>       long long next_period;
>> +     struct console console[MAX_CONSOLE];
>>  };
>>
>>
>> -     snprintf(logfile, PATH_MAX-1, "%s/guest-%s.log", log_dir, data);
>> +     snprintf(logfile, PATH_MAX-1, "%s/guest-%s-%s.log",
>> +                      log_dir, con->name, data);
>
> I am OK with this, but I wonder if changing the log name will create any
> troubles to existing management software.
Ok. i will keep the log filename unchanged for pv logs.
For vuart I will create a new directory /console/vuart where the log
file will be created.

>
>
>>       free(data);
>>       logfile[PATH_MAX-1] = '\0';
>>
>> @@ -336,19 +401,24 @@ static int create_domain_log(struct domain *dom)
>>       return fd;
>>  }
>>
>> -static void domain_close_tty(struct domain *dom)
>> +static void console_close_tty(struct console *con)
>>  {
>> -     if (dom->master_fd != -1) {
>> -             close(dom->master_fd);
>> -             dom->master_fd = -1;
>> +     if (con->master_fd != -1) {
>> +             close(con->master_fd);
>> +             con->master_fd = -1;
>>       }
>>
>> -     if (dom->slave_fd != -1) {
>> -             close(dom->slave_fd);
>> -             dom->slave_fd = -1;
>> +     if (con->slave_fd != -1) {
>> +             close(con->slave_fd);
>> +             con->slave_fd = -1;
>>       }
>>  }
>>
>> +static void domain_close_tty(struct domain *dom)
>> +{
>> +     console_iter_no_check(dom, console_close_tty);
>> +}
>> +
>>  #ifdef __sun__
>>  static int openpty(int *amaster, int *aslave, char *name,
>>                  struct termios *termp, struct winsize *winp)
>> @@ -409,7 +479,7 @@ void cfmakeraw(struct termios *termios_p)
>>  }
>>  #endif /* __sun__ */
>>
>> -static int domain_create_tty(struct domain *dom)
>> +static int console_create_tty(struct console *con)
>>  {
>>       const char *slave;
>>       char *path;
>> @@ -418,19 +488,23 @@ static int domain_create_tty(struct domain *dom)
>>       char *data;
>>       unsigned int len;
>>       struct termios term;
>> +     struct domain *dom = con->d;
>> +
>> +     if (!console_enabled(con))
>> +             return 1;
>>
>> -     assert(dom->slave_fd == -1);
>> -     assert(dom->master_fd == -1);
>> +     assert(con->master_fd == -1);
>> +     assert(con->slave_fd == -1);
>>
>> -     if (openpty(&dom->master_fd, &dom->slave_fd, NULL, NULL, NULL) < 0) {
>> +     if (openpty(&con->master_fd, &con->slave_fd, NULL, NULL, NULL) < 0) {
>>               err = errno;
>>               dolog(LOG_ERR, "Failed to create tty for domain-%d "
>> -                   "(errno = %i, %s)",
>> -                   dom->domid, err, strerror(err));
>> -             return 0;
>> +                       "(errno = %i, %s)",
>> +                       dom->domid, err, strerror(err));
>> +             goto out;
>
> I noticed that you turned the return into a goto out, why?
>
>
I will replace it with a goto.

>> -     buffer_append(dom);
>> +     if (port == vuart_con->local_port)
>> +             buffer_append(vuart_con);
>> +     else
>> +             buffer_append(pv_con);
>
> I would do it with a loop, without hardcoding the check:>
> for (i = 0; i < max_console; i++) {
>     if (dom->console[i].local_port == port)
>         buffer_append(&dom->console[i]);
> }
>
>
ok.

Regards,
Bhupinder

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

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

* Re: [PATCH 03/10 v2] xen/arm: vpl011: Enable pl011 emulation for a guest domain in Xen
  2017-05-05 13:43             ` Julien Grall
@ 2017-05-08  6:34               ` Bhupinder Thakur
  2017-05-11 10:35               ` Wei Liu
  1 sibling, 0 replies; 54+ messages in thread
From: Bhupinder Thakur @ 2017-05-08  6:34 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Jan Beulich, xen-devel

Hi,

>>> I was wondering whether it would be better to defer the PL011 creation to
>>> a
>>> domctl. This could be called after the domain is created with all the
>>> information required (MMIO region, Console PFN...).
>>>
>>> This would also make the migration support more trivial as the we will
>>> not
>>> need to know in advance whether a UART is been used.
>>>
>>> Any opinions?
>>
>>
>> Would there be race condition where the guest tries to access the
>> pl011 mmio region (as the domain has been created) but pl011 is not
>> initialized yet as domctl is not called? What could be an appropriate
>> place to call this domctl? It should be before xenstore is populated
>> with vuart ring-ref/port information.
>
>
> There are no race condition. The domain will only be started when everything
> has been created by calling XEN_DOMCTL_unpausedomain.
>
> The DOMCTL createdomain only initialize the basic structure for the domain,
> after the hypercall the domain is not in state to be run because, for
> instance, the vCPUs were not allocated (see XEN_DOMCTL_max_vcpus) and the
> guest RAM were not populated.
>
> I am not very familiar with the libxl code, but I think
> libxl__arch_domain_create should be a good candidate. I will let Ian and Wei
> confirm that.

I have defined a new DOMCTL xc_dom_vpl011_init() which collects all
the required information such as
ring buffer GFN, console domid and returns the event channel. This
function is being called from libxl__build_dom(), which is called
from inside libxl__build_pv() at the last.

This new function does away with the earlier set of domctls defined
for get/set of gfn/eventchannels. It also does away with the tinkering
of
domain creation flags while creating a domain.

Regards,
Bhupinder

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

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

* Re: [PATCH 09/10 v2] xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree
  2017-05-03 10:38   ` Julien Grall
@ 2017-05-08  6:43     ` Bhupinder Thakur
  0 siblings, 0 replies; 54+ messages in thread
From: Bhupinder Thakur @ 2017-05-08  6:43 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Jan Beulich, xen-devel

Hi Julien,

> On 28/04/17 17:01, Bhupinder Thakur wrote:
>>
>> The SBSA uart node format is as specified in
>> Documentation/devicetree/bindings/serial/arm_sbsa_uart.txt and given
>> below:
>>
>> ARM SBSA defined generic UART
>> ------------------------------
>> This UART uses a subset of the PL011 registers and consequently lives
>> in the PL011 driver. It's baudrate and other communication parameters
>> cannot be adjusted at runtime, so it lacks a clock specifier here.
>>
>> Required properties:
>> - compatible: must be "arm,sbsa-uart"
>> - reg: exactly one register range
>> - interrupts: exactly one interrupt specifier
>> - current-speed: the (fixed) baud rate set by the firmware
>
>
> What is the plan for ACPI support?

We can take that up as a new feature after this patch.

>
>>
>> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
>> Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
>> ---
>>
>> Changes since v1:
>> - Modified the code to increment nr_spis based on the SPI value reserved
>> for
>>   vpl011.
>> - Added a check to verify that physical irq assigment is not conflicting
>> with
>>   vpl011 SPI.
>
>
> Those 2 changes are usually a call to drop reviewed-by or at least to check
> whether the reviewer (here Stefano) is happy with the changes made.

I will drop the reviewed-by tag in the next patch.

>
>> - Fixed minor indentation issues.
>>
>>  tools/libxl/libxl_arm.c | 54
>> +++++++++++++++++++++++++++++++++++++++++++++++--
>>  1 file changed, 52 insertions(+), 2 deletions(-)
>>
>> diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
>> index d842d88..45a56a8 100644
>> --- a/tools/libxl/libxl_arm.c
>> +++ b/tools/libxl/libxl_arm.c
>> @@ -43,11 +43,25 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
>>  {
>>      uint32_t nr_spis = 0;
>>      unsigned int i;
>> +    bool vpl011_enabled = !strcmp(d_config->b_info.vuart, "pl011");
>> +
>> +    /*
>> +     * If pl011 vuart is enabled then increment the nr_spis to allow
>> allocation
>> +     * of SPI VIRQ for pl011.
>> +     */
>> +    if (vpl011_enabled)
>> +        nr_spis += (GUEST_VPL011_SPI - 32)+1;
>
>
> space before and after +.
>
ok.
>>
>>      for (i = 0; i < d_config->b_info.num_irqs; i++) {
>>          uint32_t irq = d_config->b_info.irqs[i];
>>          uint32_t spi;
>>
>> +        if (vpl011_enabled && irq == GUEST_VPL011_SPI)
>> +        {
>> +            LOG(ERROR, "Physical IRQ %d conflicting with pl011 SPI\n",
>> irq);
>
>
> s/%d/%u/
>
ok.
>
>> +            return ERROR_FAIL;
>> +        }
>> +
>>          if (irq < 32)
>>              continue;
>>
>> @@ -130,9 +144,10 @@ static struct arch_info {
>>      const char *guest_type;
>>      const char *timer_compat;
>>      const char *cpu_compat;
>> +    const char *uart_compat;
>>  } arch_info[] = {
>> -    {"xen-3.0-armv7l",  "arm,armv7-timer", "arm,cortex-a15" },
>> -    {"xen-3.0-aarch64", "arm,armv8-timer", "arm,armv8" },
>> +    {"xen-3.0-armv7l",  "arm,armv7-timer", "arm,cortex-a15",
>> "arm,sbsa-uart" },
>> +    {"xen-3.0-aarch64", "arm,armv8-timer", "arm,armv8", "arm,sbsa-uart"
>> },
>>  };
>>
>>  /*
>> @@ -590,6 +605,38 @@ static int make_hypervisor_node(libxl__gc *gc, void
>> *fdt,
>>      return 0;
>>  }
>>
>> +static int make_vpl011_uart_node(libxl__gc *gc, void *fdt,
>> +                                 const struct arch_info *ainfo,
>> +                                 struct xc_dom_image *dom)
>> +{
>> +    int res;
>> +    gic_interrupt intr;
>> +
>> +    res = fdt_begin_node(fdt, "sbsa-pl011");
>> +    if (res) return res;
>> +
>> +    res = fdt_property_compat(gc, fdt, 1, ainfo->uart_compat);
>> +    if (res) return res;
>> +
>> +    res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
>> +                            1,
>> +                            GUEST_PL011_BASE, GUEST_PL011_SIZE);
>> +    if (res) return res;
>> +
>> +    set_interrupt(intr, GUEST_VPL011_SPI, 0xf, DT_IRQ_TYPE_LEVEL_HIGH);
>> +
>> +    res = fdt_property_interrupts(gc, fdt, &intr, 1);
>> +    if (res) return res;
>> +
>> +    /* Use a default baud rate of 115200. */
>> +    fdt_property_u32(fdt, "current-speed", 115200);
>
>
> Please explain in the commit message why 115200.
>
ok.

Regards,
Bhupinder

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

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

* Re: [PATCH 00/10 v2] pl011 emulation support in Xen
  2017-04-28 16:01 [PATCH 00/10 v2] pl011 emulation support in Xen Bhupinder Thakur
                   ` (9 preceding siblings ...)
  2017-04-28 16:01 ` [PATCH 10/10 v2] xen/arm: vpl011: Update documentation for vuart console support Bhupinder Thakur
@ 2017-05-11 10:32 ` Wei Liu
  10 siblings, 0 replies; 54+ messages in thread
From: Wei Liu @ 2017-05-11 10:32 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Julien Grall, Jan Beulich, xen-devel

On Fri, Apr 28, 2017 at 09:31:14PM +0530, Bhupinder Thakur wrote:
> 
> url: ssh://git@git.linaro.org:/people/bhupinder.thakur/xen.git

I'm not sure if a ssh:// url is helpful...

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

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

* Re: [PATCH 03/10 v2] xen/arm: vpl011: Enable pl011 emulation for a guest domain in Xen
  2017-05-05 13:43             ` Julien Grall
  2017-05-08  6:34               ` Bhupinder Thakur
@ 2017-05-11 10:35               ` Wei Liu
  1 sibling, 0 replies; 54+ messages in thread
From: Wei Liu @ 2017-05-11 10:35 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Ian Jackson,
	Jan Beulich, Bhupinder Thakur, xen-devel

On Fri, May 05, 2017 at 02:43:40PM +0100, Julien Grall wrote:
> On 05/05/17 08:10, Bhupinder Thakur wrote:
> > Hi Julien,
> 
> Hi Bhupinder,
> 
> > > > > Hi Jan,
> > > > > 
> > > > > > > @@ -631,6 +632,9 @@ int arch_domain_create(struct domain *d,
> > > > > > > unsigned int domcr_flags,
> > > > > > >      if ( (rc = domain_vtimer_init(d, config)) != 0 )
> > > > > > >          goto fail;
> > > > > > > 
> > > > > > > +    if ( domcr_flags & DOMCRF_vuart )
> > > > > > > +        if ( (rc = domain_vpl011_init(d, config)) != 0 )
> > > > > > > +            goto fail;
> > > > > > >      update_domain_wallclock_time(d);
> > > > > > 
> > > > > > 
> > > > > I am planning to remove the usage of domain creation flag to check
> > > > > whether vuart is enabled/disabled. Please see my next comment. With
> > > > > that change, domain_vpl011_init() will be called always. The
> > > > > domain_vpl011_init() will check whether vuart is enabled or disabled
> > > > > in the config structure passed. If vuart is enabled then it will go
> > > > > ahead with vpl011 initialization else it will return without
> > > > > initializing vpl011.
> > > > 
> > > > 
> > > > Please don't do that. The arch code decides whether domain_vpl011_init
> > > > not the invert.
> > > 
> > > 
> > > I was wondering whether it would be better to defer the PL011 creation to a
> > > domctl. This could be called after the domain is created with all the
> > > information required (MMIO region, Console PFN...).
> > > 
> > > This would also make the migration support more trivial as the we will not
> > > need to know in advance whether a UART is been used.
> > > 
> > > Any opinions?
> > 
> > Would there be race condition where the guest tries to access the
> > pl011 mmio region (as the domain has been created) but pl011 is not
> > initialized yet as domctl is not called? What could be an appropriate
> > place to call this domctl? It should be before xenstore is populated
> > with vuart ring-ref/port information.
> 
> There are no race condition. The domain will only be started when everything
> has been created by calling XEN_DOMCTL_unpausedomain.
> 
> The DOMCTL createdomain only initialize the basic structure for the domain,
> after the hypercall the domain is not in state to be run because, for
> instance, the vCPUs were not allocated (see XEN_DOMCTL_max_vcpus) and the
> guest RAM were not populated.
> 
> I am not very familiar with the libxl code, but I think
> libxl__arch_domain_create should be a good candidate. I will let Ian and Wei
> confirm that.
> 

That sounds reasonable.

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

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

end of thread, other threads:[~2017-05-11 10:35 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-28 16:01 [PATCH 00/10 v2] pl011 emulation support in Xen Bhupinder Thakur
2017-04-28 16:01 ` [PATCH 01/10 v2] xen/arm: vpl011: Add pl011 uart emulation " Bhupinder Thakur
2017-04-28 19:08   ` Stefano Stabellini
2017-05-02  7:34   ` Jan Beulich
2017-05-02 16:02   ` Julien Grall
2017-05-05 11:18     ` Bhupinder Thakur
2017-05-05 13:27       ` Julien Grall
2017-05-06  5:20         ` Bhupinder Thakur
2017-04-28 16:01 ` [PATCH 02/10 v2] xen/arm: vpl011: Add new vuart domctl interface to setup pfn and evtchn Bhupinder Thakur
2017-04-28 19:23   ` Stefano Stabellini
2017-05-02  7:39     ` Jan Beulich
2017-05-02  9:47       ` Bhupinder Thakur
2017-05-02  7:47   ` Jan Beulich
2017-05-02  9:58     ` Bhupinder Thakur
2017-05-02 11:22       ` Jan Beulich
2017-05-03 10:14   ` Julien Grall
2017-04-28 16:01 ` [PATCH 03/10 v2] xen/arm: vpl011: Enable pl011 emulation for a guest domain in Xen Bhupinder Thakur
2017-04-28 19:15   ` Stefano Stabellini
2017-05-02  7:48   ` Jan Beulich
2017-05-02 15:20     ` Bhupinder Thakur
2017-05-02 15:23       ` Julien Grall
2017-05-03 10:22         ` Julien Grall
2017-05-03 10:47           ` Jan Beulich
2017-05-05  7:10           ` Bhupinder Thakur
2017-05-05 13:43             ` Julien Grall
2017-05-08  6:34               ` Bhupinder Thakur
2017-05-11 10:35               ` Wei Liu
2017-04-28 16:01 ` [PATCH 04/10 v2] xen/arm: vpl011: Add support for vuart in libxl Bhupinder Thakur
2017-04-28 21:45   ` Stefano Stabellini
2017-05-03 10:27   ` Julien Grall
2017-04-28 16:01 ` [PATCH 05/10 v2] xen/arm: vpl011: Allocate a new PFN in the toolstack for vuart Bhupinder Thakur
2017-04-28 21:48   ` Stefano Stabellini
2017-04-28 16:01 ` [PATCH 06/10 v2] xen/arm: vpl011: Add vuart ring-buf and evtchn to xenstore Bhupinder Thakur
2017-04-28 21:57   ` Stefano Stabellini
2017-05-01 11:21     ` Bhupinder Thakur
2017-05-01 17:56       ` Stefano Stabellini
2017-05-03 11:00         ` Bhupinder Thakur
2017-05-03 22:35           ` Stefano Stabellini
2017-05-04 19:37             ` Bhupinder Thakur
2017-05-04 20:38               ` Stefano Stabellini
2017-05-05  9:52                 ` Bhupinder Thakur
2017-05-05 18:59                   ` Stefano Stabellini
2017-05-08  5:37                     ` Bhupinder Thakur
2017-04-28 16:01 ` [PATCH 07/10 v2] xen/arm: vpl011: Add support for vuart in xenconsole Bhupinder Thakur
2017-04-28 23:10   ` Stefano Stabellini
2017-05-08  6:18     ` Bhupinder Thakur
2017-04-28 16:01 ` [PATCH 08/10 v2] xen/arm: vpl011: Add a new vuart console type to xenconsole client Bhupinder Thakur
2017-04-28 22:01   ` Stefano Stabellini
2017-04-28 16:01 ` [PATCH 09/10 v2] xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree Bhupinder Thakur
2017-05-03 10:38   ` Julien Grall
2017-05-08  6:43     ` Bhupinder Thakur
2017-04-28 16:01 ` [PATCH 10/10 v2] xen/arm: vpl011: Update documentation for vuart console support Bhupinder Thakur
2017-04-28 22:06   ` Stefano Stabellini
2017-05-11 10:32 ` [PATCH 00/10 v2] pl011 emulation support in Xen Wei Liu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.