All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/17 v5]  SBSA UART emulation support in Xen
@ 2017-06-22  7:38 Bhupinder Thakur
  2017-06-22  7:38 ` [PATCH 01/17 v5] xen/arm: vpl011: Move vgic register access functions to vreg.h Bhupinder Thakur
                   ` (17 more replies)
  0 siblings, 18 replies; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

SBSA UART 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 SBSA UART as a serial console which meets the minimum requirements in 
SBSA UART as defined in appendix B of the following 
ARM Server Base Architecture Document:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Changes summary:

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

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

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

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

Toolstack
==========

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

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

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

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

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

1. Split the domain structure to support multiple consoles.

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

4. Add support for vuart console:

The vpl011 changes available at the following repo:

url: https://git@git.linaro.org:/people/bhupinder.thakur/xen.git
branch: vpl011_v5

Kindly wait for one day to checkout the code from the above URL as
I am not able to push my changes from my office network. I will push
the changes once I am at home.

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

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

3. ACPI support for pl011 device.

CC: Ian Jackson <ian.jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>
CC: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

Bhupinder Thakur (17):
  xen/arm: vpl011: Move vgic register access functions to vreg.h
  xen/arm: vpl011: Rename vgic_reg* functions definitions and calls to
    vreg_reg*
  xen/arm: vpl011: Define common ring buffer helper functions in
    console.h
  xen/arm: vpl011: Add SBSA UART emulation in Xen
  xen/arm: vpl011: Allocate a new GFN in the toolstack for vuart
  xen/arm: vpl011: Add support for vuart in libxl
  xen/arm: vpl011: Rearrange xen header includes in alphabetical order
    in domctl.c
  xen/arm: vpl011: Add a new domctl API to initialize vpl011
  xen/arm: vpl011: Add a new vuart node in the xenstore
  xen/arm: vpl011: Modify xenconsole to define and use a new console    
    structure
  xen/arm: vpl011: Rename the console structure field conspath to xspath
  xen/arm: vpl011: Modify xenconsole functions to take console structure
    as input
  xen/arm: vpl011: Modify xenconsole to support multiple consoles
  xen/arm: vpl011: Add support for vuart console in xenconsole
  xen/arm: vpl011: Add a new vuart console type to xenconsole client
  xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree
  xen/arm: vpl011: Update documentation for vuart console support

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

-- 
2.7.4


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

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

* [PATCH 01/17 v5] xen/arm: vpl011: Move vgic register access functions to vreg.h
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
@ 2017-06-22  7:38 ` Bhupinder Thakur
  2017-06-22  7:38 ` [PATCH 02/17 v5] xen/arm: vpl011: Rename vgic_reg* functions definitions and calls to vreg_reg* Bhupinder Thakur
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Julien Grall, Stefano Stabellini

These functions are generic in nature and can be reused by other emulation
code in Xen. vGICv3 ITS and SBSA UART emulation code, would use these
functions to operate on their registers.

This patch moves the register access function definitions from vgic.h to
vreg.h.

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
Acked-by: Julien Grall <julien.grall@arm.com>
---
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>

Changes since v3:
- Moved the macro call VGIC_REG_HELPERS to vreg.h from vgic.h.

 xen/include/asm-arm/vgic.h | 111 +--------------------------------------------
 xen/include/asm-arm/vreg.h | 110 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 111 insertions(+), 110 deletions(-)

diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index 9ff713c..d4ed23d 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -20,6 +20,7 @@
 
 #include <xen/bitops.h>
 #include <asm/mmio.h>
+#include <asm/vreg.h>
 
 struct pending_irq
 {
@@ -182,116 +183,6 @@ static inline int REG_RANK_NR(int b, uint32_t n)
     }
 }
 
-#define VGIC_REG_MASK(size) ((~0UL) >> (BITS_PER_LONG - ((1 << (size)) * 8)))
-
-/*
- * The check on the size supported by the register has to be done by
- * the caller of vgic_regN_*.
- *
- * vgic_reg_* should never be called directly. Instead use the vgic_regN_*
- * according to size of the emulated register
- *
- * Note that the alignment fault will always be taken in the guest
- * (see B3.12.7 DDI0406.b).
- */
-static inline register_t vgic_reg_extract(unsigned long reg,
-                                          unsigned int offset,
-                                          enum dabt_size size)
-{
-    reg >>= 8 * offset;
-    reg &= VGIC_REG_MASK(size);
-
-    return reg;
-}
-
-static inline void vgic_reg_update(unsigned long *reg, register_t val,
-                                   unsigned int offset,
-                                   enum dabt_size size)
-{
-    unsigned long mask = VGIC_REG_MASK(size);
-    int shift = offset * 8;
-
-    *reg &= ~(mask << shift);
-    *reg |= ((unsigned long)val & mask) << shift;
-}
-
-static inline void vgic_reg_setbits(unsigned long *reg, register_t bits,
-                                    unsigned int offset,
-                                    enum dabt_size size)
-{
-    unsigned long mask = VGIC_REG_MASK(size);
-    int shift = offset * 8;
-
-    *reg |= ((unsigned long)bits & mask) << shift;
-}
-
-static inline void vgic_reg_clearbits(unsigned long *reg, register_t bits,
-                                      unsigned int offset,
-                                      enum dabt_size size)
-{
-    unsigned long mask = VGIC_REG_MASK(size);
-    int shift = offset * 8;
-
-    *reg &= ~(((unsigned long)bits & mask) << shift);
-}
-
-/* N-bit register helpers */
-#define VGIC_REG_HELPERS(sz, offmask)                                   \
-static inline register_t vgic_reg##sz##_extract(uint##sz##_t reg,       \
-                                                const mmio_info_t *info)\
-{                                                                       \
-    return vgic_reg_extract(reg, info->gpa & offmask,                   \
-                            info->dabt.size);                           \
-}                                                                       \
-                                                                        \
-static inline void vgic_reg##sz##_update(uint##sz##_t *reg,             \
-                                         register_t val,                \
-                                         const mmio_info_t *info)       \
-{                                                                       \
-    unsigned long tmp = *reg;                                           \
-                                                                        \
-    vgic_reg_update(&tmp, val, info->gpa & offmask,                     \
-                    info->dabt.size);                                   \
-                                                                        \
-    *reg = tmp;                                                         \
-}                                                                       \
-                                                                        \
-static inline void vgic_reg##sz##_setbits(uint##sz##_t *reg,            \
-                                          register_t bits,              \
-                                          const mmio_info_t *info)      \
-{                                                                       \
-    unsigned long tmp = *reg;                                           \
-                                                                        \
-    vgic_reg_setbits(&tmp, bits, info->gpa & offmask,                   \
-                     info->dabt.size);                                  \
-                                                                        \
-    *reg = tmp;                                                         \
-}                                                                       \
-                                                                        \
-static inline void vgic_reg##sz##_clearbits(uint##sz##_t *reg,          \
-                                            register_t bits,            \
-                                            const mmio_info_t *info)    \
-{                                                                       \
-    unsigned long tmp = *reg;                                           \
-                                                                        \
-    vgic_reg_clearbits(&tmp, bits, info->gpa & offmask,                 \
-                       info->dabt.size);                                \
-                                                                        \
-    *reg = tmp;                                                         \
-}
-
-/*
- * 64 bits registers are only supported on platform with 64-bit long.
- * This is also allow us to optimize the 32 bit case by using
- * unsigned long rather than uint64_t
- */
-#if BITS_PER_LONG == 64
-VGIC_REG_HELPERS(64, 0x7);
-#endif
-VGIC_REG_HELPERS(32, 0x3);
-
-#undef VGIC_REG_HELPERS
-
 enum gic_sgi_mode;
 
 /*
diff --git a/xen/include/asm-arm/vreg.h b/xen/include/asm-arm/vreg.h
index ed2bd6f..348584f 100644
--- a/xen/include/asm-arm/vreg.h
+++ b/xen/include/asm-arm/vreg.h
@@ -107,4 +107,114 @@ static inline bool vreg_emulate_sysreg64(struct cpu_user_regs *regs, union hsr h
 
 #endif
 
+#define VGIC_REG_MASK(size) ((~0UL) >> (BITS_PER_LONG - ((1 << (size)) * 8)))
+
+/*
+ * The check on the size supported by the register has to be done by
+ * the caller of vgic_regN_*.
+ *
+ * vgic_reg_* should never be called directly. Instead use the vgic_regN_*
+ * according to size of the emulated register
+ *
+ * Note that the alignment fault will always be taken in the guest
+ * (see B3.12.7 DDI0406.b).
+ */
+static inline register_t vgic_reg_extract(unsigned long reg,
+                                          unsigned int offset,
+                                          enum dabt_size size)
+{
+    reg >>= 8 * offset;
+    reg &= VGIC_REG_MASK(size);
+
+    return reg;
+}
+
+static inline void vgic_reg_update(unsigned long *reg, register_t val,
+                                   unsigned int offset,
+                                   enum dabt_size size)
+{
+    unsigned long mask = VGIC_REG_MASK(size);
+    int shift = offset * 8;
+
+    *reg &= ~(mask << shift);
+    *reg |= ((unsigned long)val & mask) << shift;
+}
+
+static inline void vgic_reg_setbits(unsigned long *reg, register_t bits,
+                                    unsigned int offset,
+                                    enum dabt_size size)
+{
+    unsigned long mask = VGIC_REG_MASK(size);
+    int shift = offset * 8;
+
+    *reg |= ((unsigned long)bits & mask) << shift;
+}
+
+static inline void vgic_reg_clearbits(unsigned long *reg, register_t bits,
+                                      unsigned int offset,
+                                      enum dabt_size size)
+{
+    unsigned long mask = VGIC_REG_MASK(size);
+    int shift = offset * 8;
+
+    *reg &= ~(((unsigned long)bits & mask) << shift);
+}
+
+/* N-bit register helpers */
+#define VGIC_REG_HELPERS(sz, offmask)                                   \
+static inline register_t vgic_reg##sz##_extract(uint##sz##_t reg,       \
+                                                const mmio_info_t *info)\
+{                                                                       \
+    return vgic_reg_extract(reg, info->gpa & offmask,                   \
+                            info->dabt.size);                           \
+}                                                                       \
+                                                                        \
+static inline void vgic_reg##sz##_update(uint##sz##_t *reg,             \
+                                         register_t val,                \
+                                         const mmio_info_t *info)       \
+{                                                                       \
+    unsigned long tmp = *reg;                                           \
+                                                                        \
+    vgic_reg_update(&tmp, val, info->gpa & offmask,                     \
+                    info->dabt.size);                                   \
+                                                                        \
+    *reg = tmp;                                                         \
+}                                                                       \
+                                                                        \
+static inline void vgic_reg##sz##_setbits(uint##sz##_t *reg,            \
+                                          register_t bits,              \
+                                          const mmio_info_t *info)      \
+{                                                                       \
+    unsigned long tmp = *reg;                                           \
+                                                                        \
+    vgic_reg_setbits(&tmp, bits, info->gpa & offmask,                   \
+                     info->dabt.size);                                  \
+                                                                        \
+    *reg = tmp;                                                         \
+}                                                                       \
+                                                                        \
+static inline void vgic_reg##sz##_clearbits(uint##sz##_t *reg,          \
+                                            register_t bits,            \
+                                            const mmio_info_t *info)    \
+{                                                                       \
+    unsigned long tmp = *reg;                                           \
+                                                                        \
+    vgic_reg_clearbits(&tmp, bits, info->gpa & offmask,                 \
+                       info->dabt.size);                                \
+                                                                        \
+    *reg = tmp;                                                         \
+}
+
+/*
+ * 64 bits registers are only supported on platform with 64-bit long.
+ * This is also allow us to optimize the 32 bit case by using
+ * unsigned long rather than uint64_t
+ */
+#if BITS_PER_LONG == 64
+VGIC_REG_HELPERS(64, 0x7);
+#endif
+VGIC_REG_HELPERS(32, 0x3);
+
+#undef VGIC_REG_HELPERS
+
 #endif /* __ASM_ARM_VREG__ */
-- 
2.7.4


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

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

* [PATCH 02/17 v5] xen/arm: vpl011: Rename vgic_reg* functions definitions and calls to vreg_reg*
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
  2017-06-22  7:38 ` [PATCH 01/17 v5] xen/arm: vpl011: Move vgic register access functions to vreg.h Bhupinder Thakur
@ 2017-06-22  7:38 ` Bhupinder Thakur
  2017-06-23  9:42   ` Julien Grall
  2017-06-22  7:38 ` [PATCH 03/17 v5] xen/arm: vpl011: Define common ring buffer helper functions in console.h Bhupinder Thakur
                   ` (15 subsequent siblings)
  17 siblings, 1 reply; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Andre Przywara, Julien Grall, Stefano Stabellini

This patch renames the vgic_reg* access functions defined in vreg.h to vreg_reg*
and replaces all calls to vgic_reg* functions in vgic/its emulation code to vreg_reg*.

vreg_reg* are generic functions, which can be used to operate on 32/64-bit registers.

SBSA UART emulation code will also use vreg_reg* access functions for
accessing emulated pl011 registers.

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
---
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>
CC: Andre Przywara <andre.przywara@arm.com>

Changes since v4:
- Renamed the vgic_reg* calls in ITS code to vreg_reg*.

Changes since v3:
- Renamed DEFINE_VREG_REG_HELPERS to VREG_REG_HELPERS.

 xen/arch/arm/vgic-v2.c     | 28 +++++++++++++-------------
 xen/arch/arm/vgic-v3-its.c | 28 +++++++++++++-------------
 xen/arch/arm/vgic-v3.c     | 50 +++++++++++++++++++++++-----------------------
 xen/include/asm-arm/vreg.h | 46 +++++++++++++++++++++---------------------
 4 files changed, 76 insertions(+), 76 deletions(-)

diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index eb5f354..cf4ab89 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -179,7 +179,7 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info,
     case VREG32(GICD_CTLR):
         if ( dabt.size != DABT_WORD ) goto bad_width;
         vgic_lock(v);
-        *r = vgic_reg32_extract(v->domain->arch.vgic.ctlr, info);
+        *r = vreg_reg32_extract(v->domain->arch.vgic.ctlr, info);
         vgic_unlock(v);
         return 1;
 
@@ -194,7 +194,7 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info,
             | DIV_ROUND_UP(v->domain->arch.vgic.nr_spis, 32);
         vgic_unlock(v);
 
-        *r = vgic_reg32_extract(typer, info);
+        *r = vreg_reg32_extract(typer, info);
 
         return 1;
     }
@@ -205,7 +205,7 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info,
          * XXX Do we need a JEP106 manufacturer ID?
          * Just use the physical h/w value for now
          */
-        *r = vgic_reg32_extract(0x0000043b, info);
+        *r = vreg_reg32_extract(0x0000043b, info);
         return 1;
 
     case VRANGE32(0x00C, 0x01C):
@@ -226,7 +226,7 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info,
         rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISENABLER, DABT_WORD);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank, flags);
-        *r = vgic_reg32_extract(rank->ienable, info);
+        *r = vreg_reg32_extract(rank->ienable, info);
         vgic_unlock_rank(v, rank, flags);
         return 1;
 
@@ -235,7 +235,7 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info,
         rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICENABLER, DABT_WORD);
         if ( rank == NULL) goto read_as_zero;
         vgic_lock_rank(v, rank, flags);
-        *r = vgic_reg32_extract(rank->ienable, info);
+        *r = vreg_reg32_extract(rank->ienable, info);
         vgic_unlock_rank(v, rank, flags);
         return 1;
 
@@ -262,7 +262,7 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info,
         vgic_lock_rank(v, rank, flags);
         ipriorityr = ACCESS_ONCE(rank->ipriorityr[rank_index]);
         vgic_unlock_rank(v, rank, flags);
-        *r = vgic_reg32_extract(ipriorityr, info);
+        *r = vreg_reg32_extract(ipriorityr, info);
 
         return 1;
     }
@@ -280,7 +280,7 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info,
         vgic_lock_rank(v, rank, flags);
         itargetsr = vgic_fetch_itargetsr(rank, gicd_reg - GICD_ITARGETSR);
         vgic_unlock_rank(v, rank, flags);
-        *r = vgic_reg32_extract(itargetsr, info);
+        *r = vreg_reg32_extract(itargetsr, info);
 
         return 1;
     }
@@ -299,7 +299,7 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info,
         icfgr = rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR, DABT_WORD)];
         vgic_unlock_rank(v, rank, flags);
 
-        *r = vgic_reg32_extract(icfgr, info);
+        *r = vreg_reg32_extract(icfgr, info);
 
         return 1;
     }
@@ -424,7 +424,7 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info,
         if ( dabt.size != DABT_WORD ) goto bad_width;
         /* Ignore all but the enable bit */
         vgic_lock(v);
-        vgic_reg32_update(&v->domain->arch.vgic.ctlr, r, info);
+        vreg_reg32_update(&v->domain->arch.vgic.ctlr, r, info);
         v->domain->arch.vgic.ctlr &= GICD_CTL_ENABLE;
         vgic_unlock(v);
 
@@ -454,7 +454,7 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info,
         if ( rank == NULL) goto write_ignore;
         vgic_lock_rank(v, rank, flags);
         tr = rank->ienable;
-        vgic_reg32_setbits(&rank->ienable, r, info);
+        vreg_reg32_setbits(&rank->ienable, r, info);
         vgic_enable_irqs(v, (rank->ienable) & (~tr), rank->index);
         vgic_unlock_rank(v, rank, flags);
         return 1;
@@ -465,7 +465,7 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info,
         if ( rank == NULL) goto write_ignore;
         vgic_lock_rank(v, rank, flags);
         tr = rank->ienable;
-        vgic_reg32_clearbits(&rank->ienable, r, info);
+        vreg_reg32_clearbits(&rank->ienable, r, info);
         vgic_disable_irqs(v, (~rank->ienable) & tr, rank->index);
         vgic_unlock_rank(v, rank, flags);
         return 1;
@@ -509,7 +509,7 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info,
                                                       gicd_reg - GICD_IPRIORITYR,
                                                       DABT_WORD)];
         priority = ACCESS_ONCE(*ipriorityr);
-        vgic_reg32_update(&priority, r, info);
+        vreg_reg32_update(&priority, r, info);
         ACCESS_ONCE(*ipriorityr) = priority;
 
         vgic_unlock_rank(v, rank, flags);
@@ -532,7 +532,7 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info,
         if ( rank == NULL) goto write_ignore;
         vgic_lock_rank(v, rank, flags);
         itargetsr = vgic_fetch_itargetsr(rank, gicd_reg - GICD_ITARGETSR);
-        vgic_reg32_update(&itargetsr, r, info);
+        vreg_reg32_update(&itargetsr, r, info);
         vgic_store_itargetsr(v->domain, rank, gicd_reg - GICD_ITARGETSR,
                              itargetsr);
         vgic_unlock_rank(v, rank, flags);
@@ -554,7 +554,7 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info,
         rank = vgic_rank_offset(v, 2, gicd_reg - GICD_ICFGR, DABT_WORD);
         if ( rank == NULL) goto write_ignore;
         vgic_lock_rank(v, rank, flags);
-        vgic_reg32_update(&rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR,
+        vreg_reg32_update(&rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR,
                                                      DABT_WORD)],
                           r, info);
         vgic_unlock_rank(v, rank, flags);
diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
index bfc5acc..9ef792f 100644
--- a/xen/arch/arm/vgic-v3-its.c
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -1015,13 +1015,13 @@ static int vgic_v3_its_mmio_read(struct vcpu *v, mmio_info_t *info,
         if ( have_cmd_lock )
             spin_unlock(&its->vcmd_lock);
 
-        *r = vgic_reg32_extract(reg, info);
+        *r = vreg_reg32_extract(reg, info);
         break;
     }
 
     case VREG32(GITS_IIDR):
         if ( info->dabt.size != DABT_WORD ) goto bad_width;
-        *r = vgic_reg32_extract(GITS_IIDR_VALUE, info);
+        *r = vreg_reg32_extract(GITS_IIDR_VALUE, info);
         break;
 
     case VREG64(GITS_TYPER):
@@ -1031,7 +1031,7 @@ static int vgic_v3_its_mmio_read(struct vcpu *v, mmio_info_t *info,
         reg |= (sizeof(struct vits_itte) - 1) << GITS_TYPER_ITT_SIZE_SHIFT;
         reg |= (its->evid_bits - 1) << GITS_TYPER_IDBITS_SHIFT;
         reg |= (its->devid_bits - 1) << GITS_TYPER_DEVIDS_SHIFT;
-        *r = vgic_reg64_extract(reg, info);
+        *r = vreg_reg64_extract(reg, info);
         break;
 
     case VRANGE32(0x0018, 0x001C):
@@ -1044,7 +1044,7 @@ static int vgic_v3_its_mmio_read(struct vcpu *v, mmio_info_t *info,
     case VREG64(GITS_CBASER):
         if ( !vgic_reg64_check_access(info->dabt) ) goto bad_width;
         spin_lock(&its->its_lock);
-        *r = vgic_reg64_extract(its->cbaser, info);
+        *r = vreg_reg64_extract(its->cbaser, info);
         spin_unlock(&its->its_lock);
         break;
 
@@ -1053,7 +1053,7 @@ static int vgic_v3_its_mmio_read(struct vcpu *v, mmio_info_t *info,
 
         /* CWRITER is only written by the guest, so no extra locking here. */
         reg = its->cwriter;
-        *r = vgic_reg64_extract(reg, info);
+        *r = vreg_reg64_extract(reg, info);
         break;
 
     case VREG64(GITS_CREADR):
@@ -1066,7 +1066,7 @@ static int vgic_v3_its_mmio_read(struct vcpu *v, mmio_info_t *info,
          * progress.
          */
         reg = read_u64_atomic(&its->creadr);
-        *r = vgic_reg64_extract(reg, info);
+        *r = vreg_reg64_extract(reg, info);
         break;
 
     case VRANGE64(0x0098, 0x00F8):
@@ -1075,14 +1075,14 @@ static int vgic_v3_its_mmio_read(struct vcpu *v, mmio_info_t *info,
     case VREG64(GITS_BASER0):           /* device table */
         if ( !vgic_reg64_check_access(info->dabt) ) goto bad_width;
         spin_lock(&its->its_lock);
-        *r = vgic_reg64_extract(its->baser_dev, info);
+        *r = vreg_reg64_extract(its->baser_dev, info);
         spin_unlock(&its->its_lock);
         break;
 
     case VREG64(GITS_BASER1):           /* collection table */
         if ( !vgic_reg64_check_access(info->dabt) ) goto bad_width;
         spin_lock(&its->its_lock);
-        *r = vgic_reg64_extract(its->baser_coll, info);
+        *r = vreg_reg64_extract(its->baser_coll, info);
         spin_unlock(&its->its_lock);
         break;
 
@@ -1097,7 +1097,7 @@ static int vgic_v3_its_mmio_read(struct vcpu *v, mmio_info_t *info,
 
     case VREG32(GITS_PIDR2):
         if ( info->dabt.size != DABT_WORD ) goto bad_width;
-        *r = vgic_reg32_extract(GIC_PIDR2_ARCH_GICv3, info);
+        *r = vreg_reg32_extract(GIC_PIDR2_ARCH_GICv3, info);
         break;
 
     case VRANGE32(0xFFEC, 0xFFFC):
@@ -1258,7 +1258,7 @@ static int vgic_v3_its_mmio_write(struct vcpu *v, mmio_info_t *info,
         spin_lock(&its->its_lock);
         ctlr = its->enabled ? GITS_CTLR_ENABLE : 0;
         reg32 = ctlr;
-        vgic_reg32_update(&reg32, r, info);
+        vreg_reg32_update(&reg32, r, info);
 
         if ( ctlr ^ reg32 )
             its->enabled = vgic_v3_verify_its_status(its,
@@ -1295,7 +1295,7 @@ static int vgic_v3_its_mmio_write(struct vcpu *v, mmio_info_t *info,
         }
 
         reg = its->cbaser;
-        vgic_reg64_update(&reg, r, info);
+        vreg_reg64_update(&reg, r, info);
         sanitize_its_base_reg(&reg);
 
         its->cbaser = reg;
@@ -1309,7 +1309,7 @@ static int vgic_v3_its_mmio_write(struct vcpu *v, mmio_info_t *info,
 
         spin_lock(&its->vcmd_lock);
         reg = ITS_CMD_OFFSET(its->cwriter);
-        vgic_reg64_update(&reg, r, info);
+        vreg_reg64_update(&reg, r, info);
         its->cwriter = ITS_CMD_OFFSET(reg);
 
         if ( its->enabled )
@@ -1344,7 +1344,7 @@ static int vgic_v3_its_mmio_write(struct vcpu *v, mmio_info_t *info,
         }
 
         reg = its->baser_dev;
-        vgic_reg64_update(&reg, r, info);
+        vreg_reg64_update(&reg, r, info);
 
         /* We don't support indirect tables for now. */
         reg &= ~(GITS_BASER_RO_MASK | GITS_BASER_INDIRECT);
@@ -1381,7 +1381,7 @@ static int vgic_v3_its_mmio_write(struct vcpu *v, mmio_info_t *info,
         }
 
         reg = its->baser_coll;
-        vgic_reg64_update(&reg, r, info);
+        vreg_reg64_update(&reg, r, info);
         /* No indirect tables for the collection table. */
         reg &= ~(GITS_BASER_RO_MASK | GITS_BASER_INDIRECT);
         reg |= (sizeof(coll_table_entry_t) - 1) << GITS_BASER_ENTRY_SIZE_SHIFT;
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index 4287ae1..48c7682 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -178,7 +178,7 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, mmio_info_t *info,
         if ( dabt.size != DABT_WORD ) goto bad_width;
 
         spin_lock_irqsave(&v->arch.vgic.lock, flags);
-        *r = vgic_reg32_extract(!!(v->arch.vgic.flags & VGIC_V3_LPIS_ENABLED),
+        *r = vreg_reg32_extract(!!(v->arch.vgic.flags & VGIC_V3_LPIS_ENABLED),
                                 info);
         spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
         return 1;
@@ -186,7 +186,7 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, mmio_info_t *info,
 
     case VREG32(GICR_IIDR):
         if ( dabt.size != DABT_WORD ) goto bad_width;
-        *r = vgic_reg32_extract(GICV3_GICR_IIDR_VAL, info);
+        *r = vreg_reg32_extract(GICV3_GICR_IIDR_VAL, info);
         return 1;
 
     case VREG64(GICR_TYPER):
@@ -208,7 +208,7 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, mmio_info_t *info,
         if ( v->domain->arch.vgic.has_its )
             typer |= GICR_TYPER_PLPIS;
 
-        *r = vgic_reg64_extract(typer, info);
+        *r = vreg_reg64_extract(typer, info);
 
         return 1;
     }
@@ -244,7 +244,7 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, mmio_info_t *info,
         if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
 
         vgic_lock(v);
-        *r = vgic_reg64_extract(v->domain->arch.vgic.rdist_propbase, info);
+        *r = vreg_reg64_extract(v->domain->arch.vgic.rdist_propbase, info);
         vgic_unlock(v);
         return 1;
 
@@ -257,7 +257,7 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, mmio_info_t *info,
         if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
 
         spin_lock_irqsave(&v->arch.vgic.lock, flags);
-        *r = vgic_reg64_extract(v->arch.vgic.rdist_pendbase, info);
+        *r = vreg_reg64_extract(v->arch.vgic.rdist_pendbase, info);
         *r &= ~GICR_PENDBASER_PTZ;       /* WO, reads as 0 */
         spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
         return 1;
@@ -283,7 +283,7 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, mmio_info_t *info,
     case VREG32(GICR_SYNCR):
         if ( dabt.size != DABT_WORD ) goto bad_width;
         /* RO . But when read it always returns busy bito bit[0] */
-        *r = vgic_reg32_extract(GICR_SYNCR_NOT_BUSY, info);
+        *r = vreg_reg32_extract(GICR_SYNCR_NOT_BUSY, info);
         return 1;
 
     case 0x00C8:
@@ -310,7 +310,7 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, mmio_info_t *info,
 
     case VREG32(GICR_PIDR2):
         if ( dabt.size != DABT_WORD ) goto bad_width;
-        *r = vgic_reg32_extract(GICV3_GICR_PIDR2, info);
+        *r = vreg_reg32_extract(GICV3_GICR_PIDR2, info);
          return 1;
 
     case 0xFFEC ... 0xFFFC:
@@ -354,7 +354,7 @@ read_reserved:
     return 1;
 
 read_unknown:
-    *r = vgic_reg64_extract(0xdeadbeafdeadbeaf, info);
+    *r = vreg_reg64_extract(0xdeadbeafdeadbeaf, info);
     return 1;
 }
 
@@ -553,7 +553,7 @@ static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu *v, mmio_info_t *info,
         if ( !(v->domain->arch.vgic.rdists_enabled) )
         {
             reg = v->domain->arch.vgic.rdist_propbase;
-            vgic_reg64_update(&reg, r, info);
+            vreg_reg64_update(&reg, r, info);
             reg = sanitize_propbaser(reg);
             v->domain->arch.vgic.rdist_propbase = reg;
         }
@@ -576,7 +576,7 @@ static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu *v, mmio_info_t *info,
         if ( !(v->arch.vgic.flags & VGIC_V3_LPIS_ENABLED) )
         {
             reg = v->arch.vgic.rdist_pendbase;
-            vgic_reg64_update(&reg, r, info);
+            vreg_reg64_update(&reg, r, info);
             reg = sanitize_pendbaser(reg);
             v->arch.vgic.rdist_pendbase = reg;
         }
@@ -690,7 +690,7 @@ static int __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v,
         rank = vgic_rank_offset(v, 1, reg - GICD_ISENABLER, DABT_WORD);
         if ( rank == NULL ) goto read_as_zero;
         vgic_lock_rank(v, rank, flags);
-        *r = vgic_reg32_extract(rank->ienable, info);
+        *r = vreg_reg32_extract(rank->ienable, info);
         vgic_unlock_rank(v, rank, flags);
         return 1;
 
@@ -699,7 +699,7 @@ static int __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v,
         rank = vgic_rank_offset(v, 1, reg - GICD_ICENABLER, DABT_WORD);
         if ( rank == NULL ) goto read_as_zero;
         vgic_lock_rank(v, rank, flags);
-        *r = vgic_reg32_extract(rank->ienable, info);
+        *r = vreg_reg32_extract(rank->ienable, info);
         vgic_unlock_rank(v, rank, flags);
         return 1;
 
@@ -727,7 +727,7 @@ static int __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v,
         ipriorityr = ACCESS_ONCE(rank->ipriorityr[rank_index]);
         vgic_unlock_rank(v, rank, flags);
 
-        *r = vgic_reg32_extract(ipriorityr, info);
+        *r = vreg_reg32_extract(ipriorityr, info);
 
         return 1;
     }
@@ -743,7 +743,7 @@ static int __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v,
         icfgr = rank->icfg[REG_RANK_INDEX(2, reg - GICD_ICFGR, DABT_WORD)];
         vgic_unlock_rank(v, rank, flags);
 
-        *r = vgic_reg32_extract(icfgr, info);
+        *r = vreg_reg32_extract(icfgr, info);
 
         return 1;
     }
@@ -787,7 +787,7 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v,
         if ( rank == NULL ) goto write_ignore;
         vgic_lock_rank(v, rank, flags);
         tr = rank->ienable;
-        vgic_reg32_setbits(&rank->ienable, r, info);
+        vreg_reg32_setbits(&rank->ienable, r, info);
         vgic_enable_irqs(v, (rank->ienable) & (~tr), rank->index);
         vgic_unlock_rank(v, rank, flags);
         return 1;
@@ -798,7 +798,7 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v,
         if ( rank == NULL ) goto write_ignore;
         vgic_lock_rank(v, rank, flags);
         tr = rank->ienable;
-        vgic_reg32_clearbits(&rank->ienable, r, info);
+        vreg_reg32_clearbits(&rank->ienable, r, info);
         vgic_disable_irqs(v, (~rank->ienable) & tr, rank->index);
         vgic_unlock_rank(v, rank, flags);
         return 1;
@@ -841,7 +841,7 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v,
         ipriorityr = &rank->ipriorityr[REG_RANK_INDEX(8, reg - GICD_IPRIORITYR,
                                                       DABT_WORD)];
         priority = ACCESS_ONCE(*ipriorityr);
-        vgic_reg32_update(&priority, r, info);
+        vreg_reg32_update(&priority, r, info);
         ACCESS_ONCE(*ipriorityr) = priority;
         vgic_unlock_rank(v, rank, flags);
         return 1;
@@ -857,7 +857,7 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v,
         rank = vgic_rank_offset(v, 2, reg - GICD_ICFGR, DABT_WORD);
         if ( rank == NULL ) goto write_ignore;
         vgic_lock_rank(v, rank, flags);
-        vgic_reg32_update(&rank->icfg[REG_RANK_INDEX(2, reg - GICD_ICFGR,
+        vreg_reg32_update(&rank->icfg[REG_RANK_INDEX(2, reg - GICD_ICFGR,
                                                      DABT_WORD)],
                           r, info);
         vgic_unlock_rank(v, rank, flags);
@@ -1105,7 +1105,7 @@ static int vgic_v3_distr_mmio_read(struct vcpu *v, mmio_info_t *info,
     case VREG32(GICD_CTLR):
         if ( dabt.size != DABT_WORD ) goto bad_width;
         vgic_lock(v);
-        *r = vgic_reg32_extract(v->domain->arch.vgic.ctlr, info);
+        *r = vreg_reg32_extract(v->domain->arch.vgic.ctlr, info);
         vgic_unlock(v);
         return 1;
 
@@ -1132,14 +1132,14 @@ static int vgic_v3_distr_mmio_read(struct vcpu *v, mmio_info_t *info,
 
         typer |= (v->domain->arch.vgic.intid_bits - 1) << GICD_TYPE_ID_BITS_SHIFT;
 
-        *r = vgic_reg32_extract(typer, info);
+        *r = vreg_reg32_extract(typer, info);
 
         return 1;
     }
 
     case VREG32(GICD_IIDR):
         if ( dabt.size != DABT_WORD ) goto bad_width;
-        *r = vgic_reg32_extract(GICV3_GICD_IIDR_VAL, info);
+        *r = vreg_reg32_extract(GICV3_GICD_IIDR_VAL, info);
         return 1;
 
     case VREG32(0x000C):
@@ -1232,7 +1232,7 @@ static int vgic_v3_distr_mmio_read(struct vcpu *v, mmio_info_t *info,
         irouter = vgic_fetch_irouter(rank, gicd_reg - GICD_IROUTER);
         vgic_unlock_rank(v, rank, flags);
 
-        *r = vgic_reg64_extract(irouter, info);
+        *r = vreg_reg64_extract(irouter, info);
 
         return 1;
     }
@@ -1250,7 +1250,7 @@ static int vgic_v3_distr_mmio_read(struct vcpu *v, mmio_info_t *info,
     case VREG32(GICD_PIDR2):
         /* GICv3 identification value */
         if ( dabt.size != DABT_WORD ) goto bad_width;
-        *r = vgic_reg32_extract(GICV3_GICD_PIDR2, info);
+        *r = vreg_reg32_extract(GICV3_GICD_PIDR2, info);
         return 1;
 
     case VRANGE32(0xFFEC, 0xFFFC):
@@ -1313,7 +1313,7 @@ static int vgic_v3_distr_mmio_write(struct vcpu *v, mmio_info_t *info,
 
         vgic_lock(v);
 
-        vgic_reg32_update(&ctlr, r, info);
+        vreg_reg32_update(&ctlr, r, info);
 
         /* Only EnableGrp1A can be changed */
         if ( ctlr & GICD_CTLR_ENABLE_G1A )
@@ -1419,7 +1419,7 @@ static int vgic_v3_distr_mmio_write(struct vcpu *v, mmio_info_t *info,
         if ( rank == NULL ) goto write_ignore;
         vgic_lock_rank(v, rank, flags);
         irouter = vgic_fetch_irouter(rank, gicd_reg - GICD_IROUTER);
-        vgic_reg64_update(&irouter, r, info);
+        vreg_reg64_update(&irouter, r, info);
         vgic_store_irouter(v->domain, rank, gicd_reg - GICD_IROUTER, irouter);
         vgic_unlock_rank(v, rank, flags);
         return 1;
diff --git a/xen/include/asm-arm/vreg.h b/xen/include/asm-arm/vreg.h
index 348584f..1253753 100644
--- a/xen/include/asm-arm/vreg.h
+++ b/xen/include/asm-arm/vreg.h
@@ -107,99 +107,99 @@ static inline bool vreg_emulate_sysreg64(struct cpu_user_regs *regs, union hsr h
 
 #endif
 
-#define VGIC_REG_MASK(size) ((~0UL) >> (BITS_PER_LONG - ((1 << (size)) * 8)))
+#define VREG_REG_MASK(size) ((~0UL) >> (BITS_PER_LONG - ((1 << (size)) * 8)))
 
 /*
  * The check on the size supported by the register has to be done by
- * the caller of vgic_regN_*.
+ * the caller of vreg_regN_*.
  *
- * vgic_reg_* should never be called directly. Instead use the vgic_regN_*
+ * vreg_reg_* should never be called directly. Instead use the vreg_regN_*
  * according to size of the emulated register
  *
  * Note that the alignment fault will always be taken in the guest
  * (see B3.12.7 DDI0406.b).
  */
-static inline register_t vgic_reg_extract(unsigned long reg,
+static inline register_t vreg_reg_extract(unsigned long reg,
                                           unsigned int offset,
                                           enum dabt_size size)
 {
     reg >>= 8 * offset;
-    reg &= VGIC_REG_MASK(size);
+    reg &= VREG_REG_MASK(size);
 
     return reg;
 }
 
-static inline void vgic_reg_update(unsigned long *reg, register_t val,
+static inline void vreg_reg_update(unsigned long *reg, register_t val,
                                    unsigned int offset,
                                    enum dabt_size size)
 {
-    unsigned long mask = VGIC_REG_MASK(size);
+    unsigned long mask = VREG_REG_MASK(size);
     int shift = offset * 8;
 
     *reg &= ~(mask << shift);
     *reg |= ((unsigned long)val & mask) << shift;
 }
 
-static inline void vgic_reg_setbits(unsigned long *reg, register_t bits,
+static inline void vreg_reg_setbits(unsigned long *reg, register_t bits,
                                     unsigned int offset,
                                     enum dabt_size size)
 {
-    unsigned long mask = VGIC_REG_MASK(size);
+    unsigned long mask = VREG_REG_MASK(size);
     int shift = offset * 8;
 
     *reg |= ((unsigned long)bits & mask) << shift;
 }
 
-static inline void vgic_reg_clearbits(unsigned long *reg, register_t bits,
+static inline void vreg_reg_clearbits(unsigned long *reg, register_t bits,
                                       unsigned int offset,
                                       enum dabt_size size)
 {
-    unsigned long mask = VGIC_REG_MASK(size);
+    unsigned long mask = VREG_REG_MASK(size);
     int shift = offset * 8;
 
     *reg &= ~(((unsigned long)bits & mask) << shift);
 }
 
 /* N-bit register helpers */
-#define VGIC_REG_HELPERS(sz, offmask)                                   \
-static inline register_t vgic_reg##sz##_extract(uint##sz##_t reg,       \
+#define VREG_REG_HELPERS(sz, offmask)                                   \
+static inline register_t vreg_reg##sz##_extract(uint##sz##_t reg,       \
                                                 const mmio_info_t *info)\
 {                                                                       \
-    return vgic_reg_extract(reg, info->gpa & offmask,                   \
+    return vreg_reg_extract(reg, info->gpa & offmask,                   \
                             info->dabt.size);                           \
 }                                                                       \
                                                                         \
-static inline void vgic_reg##sz##_update(uint##sz##_t *reg,             \
+static inline void vreg_reg##sz##_update(uint##sz##_t *reg,             \
                                          register_t val,                \
                                          const mmio_info_t *info)       \
 {                                                                       \
     unsigned long tmp = *reg;                                           \
                                                                         \
-    vgic_reg_update(&tmp, val, info->gpa & offmask,                     \
+    vreg_reg_update(&tmp, val, info->gpa & offmask,                     \
                     info->dabt.size);                                   \
                                                                         \
     *reg = tmp;                                                         \
 }                                                                       \
                                                                         \
-static inline void vgic_reg##sz##_setbits(uint##sz##_t *reg,            \
+static inline void vreg_reg##sz##_setbits(uint##sz##_t *reg,            \
                                           register_t bits,              \
                                           const mmio_info_t *info)      \
 {                                                                       \
     unsigned long tmp = *reg;                                           \
                                                                         \
-    vgic_reg_setbits(&tmp, bits, info->gpa & offmask,                   \
+    vreg_reg_setbits(&tmp, bits, info->gpa & offmask,                   \
                      info->dabt.size);                                  \
                                                                         \
     *reg = tmp;                                                         \
 }                                                                       \
                                                                         \
-static inline void vgic_reg##sz##_clearbits(uint##sz##_t *reg,          \
+static inline void vreg_reg##sz##_clearbits(uint##sz##_t *reg,          \
                                             register_t bits,            \
                                             const mmio_info_t *info)    \
 {                                                                       \
     unsigned long tmp = *reg;                                           \
                                                                         \
-    vgic_reg_clearbits(&tmp, bits, info->gpa & offmask,                 \
+    vreg_reg_clearbits(&tmp, bits, info->gpa & offmask,                 \
                        info->dabt.size);                                \
                                                                         \
     *reg = tmp;                                                         \
@@ -211,10 +211,10 @@ static inline void vgic_reg##sz##_clearbits(uint##sz##_t *reg,          \
  * unsigned long rather than uint64_t
  */
 #if BITS_PER_LONG == 64
-VGIC_REG_HELPERS(64, 0x7);
+VREG_REG_HELPERS(64, 0x7);
 #endif
-VGIC_REG_HELPERS(32, 0x3);
+VREG_REG_HELPERS(32, 0x3);
 
-#undef VGIC_REG_HELPERS
+#undef VREG_REG_HELPERS
 
 #endif /* __ASM_ARM_VREG__ */
-- 
2.7.4


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

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

* [PATCH 03/17 v5] xen/arm: vpl011: Define common ring buffer helper functions in console.h
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
  2017-06-22  7:38 ` [PATCH 01/17 v5] xen/arm: vpl011: Move vgic register access functions to vreg.h Bhupinder Thakur
  2017-06-22  7:38 ` [PATCH 02/17 v5] xen/arm: vpl011: Rename vgic_reg* functions definitions and calls to vreg_reg* Bhupinder Thakur
@ 2017-06-22  7:38 ` Bhupinder Thakur
  2017-06-22 22:36   ` Stefano Stabellini
  2017-06-28 17:16   ` Wei Liu
  2017-06-22  7:38 ` [PATCH 04/17 v5] xen/arm: vpl011: Add SBSA UART emulation in Xen Bhupinder Thakur
                   ` (14 subsequent siblings)
  17 siblings, 2 replies; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

DEFINE_XEN_FLEX_RING(xencons) defines common helper functions such as
xencons_queued() to tell the current size of the ring buffer,
xencons_mask() to mask off the index, which are useful helper functions.
pl011 emulation code will use these helper functions.

io/consol.h includes io/ring.h which defines DEFINE_XEN_FLEX_RING.

In console/daemon/io.c, string.h had to be included before io/console.h
because ring.h uses string functions.

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
---
CC: Ian Jackson <ian.jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>

Changes since v4:
- Split this change in a separate patch.

 tools/console/daemon/io.c       | 2 +-
 xen/include/public/io/console.h | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index 7e474bb..e8033d2 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -21,6 +21,7 @@
 
 #include "utils.h"
 #include "io.h"
+#include <string.h>
 #include <xenevtchn.h>
 #include <xengnttab.h>
 #include <xenstore.h>
@@ -29,7 +30,6 @@
 
 #include <stdlib.h>
 #include <errno.h>
-#include <string.h>
 #include <poll.h>
 #include <fcntl.h>
 #include <unistd.h>
diff --git a/xen/include/public/io/console.h b/xen/include/public/io/console.h
index e2cd97f..5e45e1c 100644
--- a/xen/include/public/io/console.h
+++ b/xen/include/public/io/console.h
@@ -27,6 +27,8 @@
 #ifndef __XEN_PUBLIC_IO_CONSOLE_H__
 #define __XEN_PUBLIC_IO_CONSOLE_H__
 
+#include "ring.h"
+
 typedef uint32_t XENCONS_RING_IDX;
 
 #define MASK_XENCONS_IDX(idx, ring) ((idx) & (sizeof(ring)-1))
@@ -38,6 +40,8 @@ struct xencons_interface {
     XENCONS_RING_IDX out_cons, out_prod;
 };
 
+DEFINE_XEN_FLEX_RING(xencons);
+
 #endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */
 
 /*
-- 
2.7.4


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

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

* [PATCH 04/17 v5] xen/arm: vpl011: Add SBSA UART emulation in Xen
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
                   ` (2 preceding siblings ...)
  2017-06-22  7:38 ` [PATCH 03/17 v5] xen/arm: vpl011: Define common ring buffer helper functions in console.h Bhupinder Thakur
@ 2017-06-22  7:38 ` Bhupinder Thakur
  2017-06-22 22:53   ` Stefano Stabellini
  2017-06-23 13:10   ` Julien Grall
  2017-06-22  7:38 ` [PATCH 05/17 v5] xen/arm: vpl011: Allocate a new GFN in the toolstack for vuart Bhupinder Thakur
                   ` (13 subsequent siblings)
  17 siblings, 2 replies; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Andre Przywara, Julien Grall, Stefano Stabellini

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

This patch implements the SBSA Generic UART which is a subset of ARM
PL011 UART.

The SBSA Generic 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>
---
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>
CC: Andre Przywara <andre.przywara@arm.com>

Changes since v4:
- Renamed vpl011_update() to vpl011_update_interrupt_status() and added logic to avoid
  raising spurious interrupts.
- Used barrier instructions correctly while reading/writing data to the ring buffer.
- Proper lock taken before reading ring buffer indices.

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

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

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

 xen/arch/arm/Kconfig             |   7 +
 xen/arch/arm/Makefile            |   1 +
 xen/arch/arm/vpl011.c            | 449 +++++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/domain.h     |   6 +
 xen/include/asm-arm/pl011-uart.h |   2 +
 xen/include/asm-arm/vpl011.h     |  73 +++++++
 xen/include/public/arch-arm.h    |   6 +
 7 files changed, 544 insertions(+)
 create mode 100644 xen/arch/arm/vpl011.c
 create mode 100644 xen/include/asm-arm/vpl011.h

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


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

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

* [PATCH 05/17 v5] xen/arm: vpl011: Allocate a new GFN in the toolstack for vuart
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
                   ` (3 preceding siblings ...)
  2017-06-22  7:38 ` [PATCH 04/17 v5] xen/arm: vpl011: Add SBSA UART emulation in Xen Bhupinder Thakur
@ 2017-06-22  7:38 ` Bhupinder Thakur
  2017-06-22  7:38 ` [PATCH 06/17 v5] xen/arm: vpl011: Add support for vuart in libxl Bhupinder Thakur
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

Allocate a new gfn to be used as a ring buffer between xenconsole
and Xen for sending/receiving pl011 console data.

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
Acked-by: Stefano Stabellini <sstabellini@kernel.org>
Acked-by: Wei Liu <wei.liu2@citrix.com>
---
CC: Ian Jackson <ian.jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>

Changes since v4:
- Removed xc_get_vuart_gfn() as it is not required since the vpl011 initialization
  function which used this API has been moved to after gfn is allocated.
- I have included the reviewed-by and acked-by tags as there is no change in the
  logic.

Changes since v3:
- Added a new helper function xc_get_vuart_gfn() to return the GFN allocated for
  vpl011.
- Since a new function has been added in this patch, I have not included Stefano's
  reviewed-by and Wei's acked-by tags.

Changes since v2:
- Removed the DOMCTL call to set the GFN as now this information is passed
  in the DOMCTL call to initialize vpl011 emulation.

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

diff --git a/tools/libxc/include/xc_dom.h b/tools/libxc/include/xc_dom.h
index ce47058..6e06ef1 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_gfn;
 };
 
 /* --- pluggable kernel loader ------------------------------------- */
diff --git a/tools/libxc/xc_dom_arm.c b/tools/libxc/xc_dom_arm.c
index e7d4bd0..c981b7a 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,10 +86,12 @@ 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_gfn = 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,
diff --git a/tools/libxc/xc_dom_boot.c b/tools/libxc/xc_dom_boot.c
index c3b44dd..8a376d0 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_gfn)) != 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] 67+ messages in thread

* [PATCH 06/17 v5] xen/arm: vpl011: Add support for vuart in libxl
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
                   ` (4 preceding siblings ...)
  2017-06-22  7:38 ` [PATCH 05/17 v5] xen/arm: vpl011: Allocate a new GFN in the toolstack for vuart Bhupinder Thakur
@ 2017-06-22  7:38 ` Bhupinder Thakur
  2017-06-22 22:57   ` Stefano Stabellini
  2017-06-28 17:16   ` Wei Liu
  2017-06-22  7:38 ` [PATCH 07/17 v5] xen/arm: vpl011: Rearrange xen header includes in alphabetical order in domctl.c Bhupinder Thakur
                   ` (11 subsequent siblings)
  17 siblings, 2 replies; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

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

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

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

vuart = "sbsa_uart"

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
---
CC: Ian Jackson <ian.jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>

Changes since v4:
- Renamed "pl011" to "sbsa_uart".

Changes since v3:
- Added a new config option CONFIG_VUART_CONSOLE to enable/disable vuart console
  support.
- Moved libxl_vuart_type to arch-arm part of libxl_domain_build_info
- Updated xl command help to mention new console type - vuart.

Changes since v2:
- Defined vuart option as an enum instead of a string.
- Removed the domain creation flag defined for vuart and the related code
  to pass on the information while domain creation. Now vpl011 is initialized
  independent of domain creation through new DOMCTL APIs.

 tools/libxl/libxl.h          | 6 ++++++
 tools/libxl/libxl_console.c  | 3 +++
 tools/libxl/libxl_dom.c      | 1 +
 tools/libxl/libxl_internal.h | 3 +++
 tools/libxl/libxl_types.idl  | 7 +++++++
 tools/xl/xl_cmdtable.c       | 2 +-
 tools/xl/xl_console.c        | 5 ++++-
 tools/xl/xl_parse.c          | 8 ++++++++
 8 files changed, 33 insertions(+), 2 deletions(-)

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_console.c b/tools/libxl/libxl_console.c
index 446e766..853be15 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;
     }
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 5d914a5..c98af60 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -788,6 +788,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_gfn = dom->vuart_gfn;
     } else {
         state->console_mfn = xc_dom_p2m(dom, dom->console_pfn);
         state->store_mfn = xc_dom_p2m(dom, dom->xenstore_pfn);
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index afe6652..d0d50c3 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1139,6 +1139,9 @@ typedef struct {
     uint32_t num_vmemranges;
 
     xc_domain_configuration_t config;
+
+    xen_pfn_t vuart_gfn;
+    evtchn_port_t vuart_port;
 } 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..d492b35 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", [
@@ -240,6 +241,11 @@ libxl_checkpointed_stream = Enumeration("checkpointed_stream", [
     (2, "COLO"),
     ])
 
+libxl_vuart_type = Enumeration("vuart_type", [
+    (0, "unknown"),
+    (1, "sbsa_uart"),
+    ])
+
 #
 # Complex libxl types
 #
@@ -580,6 +586,7 @@ libxl_domain_build_info = Struct("domain_build_info",[
 
 
     ("arch_arm", Struct(None, [("gic_version", libxl_gic_version),
+                               ("vuart", libxl_vuart_type),
                               ])),
     # Alternate p2m is not bound to any architecture or guest type, as it is
     # supported by x86 HVM and ARM support is planned.
diff --git a/tools/xl/xl_cmdtable.c b/tools/xl/xl_cmdtable.c
index 30eb93c..9f91651 100644
--- a/tools/xl/xl_cmdtable.c
+++ b/tools/xl/xl_cmdtable.c
@@ -133,7 +133,7 @@ struct cmd_spec cmd_table[] = {
       &main_console, 0, 0,
       "Attach to domain's console",
       "[options] <Domain>\n"
-      "-t <type>       console type, pv or serial\n"
+      "-t <type>       console type, pv , serial or vuart\n"
       "-n <number>     console number"
     },
     { "vncviewer",
diff --git a/tools/xl/xl_console.c b/tools/xl/xl_console.c
index 0508dda..4e65d73 100644
--- a/tools/xl/xl_console.c
+++ b/tools/xl/xl_console.c
@@ -27,6 +27,7 @@ int main_console(int argc, char **argv)
     uint32_t domid;
     int opt = 0, num = 0;
     libxl_console_type type = 0;
+    char *console_names = "pv, serial, vuart";
 
     SWITCH_FOREACH_OPT(opt, "n:t:", NULL, "console", 1) {
     case 't':
@@ -34,8 +35,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: %s\n", console_names);
             return EXIT_FAILURE;
         }
         break;
diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
index 856a304..37581ef 100644
--- a/tools/xl/xl_parse.c
+++ b/tools/xl/xl_parse.c
@@ -916,6 +916,14 @@ 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_get_string(config, "vuart", &buf, 0)) {
+        if (libxl_vuart_type_from_string(buf, &b_info->arch_arm.vuart)) {
+            fprintf(stderr, "ERROR: invalid value \"%s\" for \"vuart\"\n",
+                    buf);
+            exit(1);
+        }
+    }
+
     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] 67+ messages in thread

* [PATCH 07/17 v5] xen/arm: vpl011: Rearrange xen header includes in alphabetical order in domctl.c
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
                   ` (5 preceding siblings ...)
  2017-06-22  7:38 ` [PATCH 06/17 v5] xen/arm: vpl011: Add support for vuart in libxl Bhupinder Thakur
@ 2017-06-22  7:38 ` Bhupinder Thakur
  2017-06-22 22:58   ` Stefano Stabellini
  2017-06-22  7:38 ` [PATCH 08/17 v5] xen/arm: vpl011: Add a new domctl API to initialize vpl011 Bhupinder Thakur
                   ` (10 subsequent siblings)
  17 siblings, 1 reply; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Julien Grall, Stefano Stabellini

Rearrange xen header includes in alphabetical order in domctl.c.

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
---
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>

 xen/arch/arm/domctl.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
index 971caec..86fa102 100644
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -5,11 +5,11 @@
  */
 
 #include <xen/types.h>
-#include <xen/lib.h>
 #include <xen/errno.h>
-#include <xen/sched.h>
 #include <xen/hypercall.h>
 #include <xen/iocap.h>
+#include <xen/lib.h>
+#include <xen/sched.h>
 #include <xsm/xsm.h>
 #include <public/domctl.h>
 
-- 
2.7.4


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

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

* [PATCH 08/17 v5] xen/arm: vpl011: Add a new domctl API to initialize vpl011
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
                   ` (6 preceding siblings ...)
  2017-06-22  7:38 ` [PATCH 07/17 v5] xen/arm: vpl011: Rearrange xen header includes in alphabetical order in domctl.c Bhupinder Thakur
@ 2017-06-22  7:38 ` Bhupinder Thakur
  2017-06-22 23:04   ` Stefano Stabellini
                     ` (2 more replies)
  2017-06-22  7:38 ` [PATCH 09/17 v5] xen/arm: vpl011: Add a new vuart node in the xenstore Bhupinder Thakur
                   ` (9 subsequent siblings)
  17 siblings, 3 replies; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

Add a new domctl API to initialize vpl011. It takes the GFN and console
backend domid as input and returns an event channel to be used for
sending and receiving events from Xen.

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

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
---
CC: Ian Jackson <ian.jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>

Changes since v4:
- Removed libxl__arch_domain_create_finish().
- Added a new function libxl__arch_build_dom_finish(), which is called at the last
  in libxl__build_dom(). This function calls the vpl011 initialization function now.

Changes since v3:
- Added a new arch specific function libxl__arch_domain_create_finish(), which
  calls the vpl011 initialization function. For x86 this function does not do
  anything.
- domain_vpl011_init() takes a pointer to a structure which contains all the 
  required information such as console_domid, gfn instead of passing parameters
  separately.
- Dropped a DOMCTL API defined for de-initializing vpl011 as that should be
  taken care when the domain is destroyed (and not dependent on userspace 
  libraries/applications).

Changes since v2:
- Replaced the DOMCTL APIs defined for get/set of event channel and GFN with 
  a set of DOMCTL APIs for initializing and de-initializing vpl011 emulation.

 tools/libxc/include/xenctrl.h | 20 ++++++++++++++++++++
 tools/libxc/xc_domain.c       | 25 +++++++++++++++++++++++++
 tools/libxl/libxl_arch.h      |  6 ++++++
 tools/libxl/libxl_arm.c       | 22 ++++++++++++++++++++++
 tools/libxl/libxl_dom.c       |  4 ++++
 tools/libxl/libxl_x86.c       |  8 ++++++++
 xen/arch/arm/domain.c         |  5 +++++
 xen/arch/arm/domctl.c         | 37 +++++++++++++++++++++++++++++++++++++
 xen/include/public/domctl.h   | 12 ++++++++++++
 9 files changed, 139 insertions(+)

diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 1629f41..26f3d1e 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -885,6 +885,26 @@ int xc_vcpu_getcontext(xc_interface *xch,
                        uint32_t vcpu,
                        vcpu_guest_context_any_t *ctxt);
 
+#if defined (__arm__) || defined(__aarch64__)
+/**
+ * This function initializes the vpl011 emulation and returns
+ * the event to be used by the backend for communicating with
+ * the emulation code.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain to get information from
+ * @parm console_domid the domid of the backend console
+ * @parm gfn the guest pfn to be used as the ring buffer
+ * @parm evtchn the event channel to be used for events
+ * @return 0 on success, negative error on failure
+ */
+int xc_dom_vpl011_init(xc_interface *xch,
+                       uint32_t domid,
+                       uint32_t console_domid,
+                       xen_pfn_t gfn,
+                       evtchn_port_t *evtchn);
+#endif
+
 /**
  * This function returns information about the XSAVE state of a particular
  * vcpu of a domain. If extstate->size and extstate->xfeature_mask are 0,
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index 5d192ea..55de408 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -343,6 +343,31 @@ int xc_domain_get_guest_width(xc_interface *xch, uint32_t domid,
     return 0;
 }
 
+#if defined (__arm__) || defined(__aarch64__)
+int xc_dom_vpl011_init(xc_interface *xch,
+                       uint32_t domid,
+                       uint32_t console_domid,
+                       xen_pfn_t gfn,
+                       evtchn_port_t *evtchn)
+{
+    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_INIT_VPL011;
+    domctl.u.vuart_op.console_domid = console_domid;
+    domctl.u.vuart_op.gfn = gfn;
+
+    if ( (rc = do_domctl(xch, &domctl)) < 0 )
+        return rc;
+
+    *evtchn = domctl.u.vuart_op.evtchn;
+
+    return rc;
+}
+#endif
+
 int xc_domain_getinfo(xc_interface *xch,
                       uint32_t first_domid,
                       unsigned int max_doms,
diff --git a/tools/libxl/libxl_arch.h b/tools/libxl/libxl_arch.h
index 5e1fc60..118b92c 100644
--- a/tools/libxl/libxl_arch.h
+++ b/tools/libxl/libxl_arch.h
@@ -44,6 +44,12 @@ int libxl__arch_domain_finalise_hw_description(libxl__gc *gc,
                                       libxl_domain_build_info *info,
                                       struct xc_dom_image *dom);
 
+/* perform any pending hardware initialization */
+int libxl__arch_build_dom_finish(libxl__gc *gc,
+                                 libxl_domain_build_info *info,
+                                 struct xc_dom_image *dom,
+                                 libxl__domain_build_state *state);
+
 /* build vNUMA vmemrange with arch specific information */
 _hidden
 int libxl__arch_vnuma_build_vmemrange(libxl__gc *gc,
diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
index d842d88..9d6448e 100644
--- a/tools/libxl/libxl_arm.c
+++ b/tools/libxl/libxl_arm.c
@@ -1038,6 +1038,28 @@ int libxl__arch_domain_finalise_hw_description(libxl__gc *gc,
     return 0;
 }
 
+int libxl__arch_build_dom_finish(libxl__gc *gc,
+                                 libxl_domain_build_info *info,
+                                 struct xc_dom_image *dom,
+                                 libxl__domain_build_state *state)
+{
+    int ret = 0;
+
+    if ( info->arch_arm.vuart ) {
+        ret = xc_dom_vpl011_init(CTX->xch,
+                                 dom->guest_domid,
+                                 dom->console_domid,
+                                 dom->vuart_gfn,
+                                 &state->vuart_port);
+        if ( ret < 0 )
+        {
+            LOG(ERROR, "xc_dom_vpl011_init failed\n");
+        }
+    }
+
+    return ret;
+}
+
 int libxl__arch_vnuma_build_vmemrange(libxl__gc *gc,
                                       uint32_t domid,
                                       libxl_domain_build_info *info,
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index c98af60..9b42205 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -687,6 +687,10 @@ static int libxl__build_dom(libxl__gc *gc, uint32_t domid,
         LOGE(ERROR, "xc_dom_gnttab_init failed");
         goto out;
     }
+    if ( (ret = libxl__arch_build_dom_finish(gc, info, dom, state)) != 0 ) {
+        LOGE(ERROR, "libxl__arch_build_dom_finish failed");
+        goto out;
+    }
 
 out:
     return ret != 0 ? ERROR_FAIL : 0;
diff --git a/tools/libxl/libxl_x86.c b/tools/libxl/libxl_x86.c
index 455f6f0..0aaeded 100644
--- a/tools/libxl/libxl_x86.c
+++ b/tools/libxl/libxl_x86.c
@@ -391,6 +391,14 @@ int libxl__arch_domain_finalise_hw_description(libxl__gc *gc,
     return rc;
 }
 
+int libxl__arch_build_dom_finish(libxl__gc *gc,
+                                 libxl_domain_build_info *info,
+                                 struct xc_dom_image *dom,
+                                 libxl__domain_build_state *state)
+{
+    return 0;
+}
+
 /* Return 0 on success, ERROR_* on failure. */
 int libxl__arch_vnuma_build_vmemrange(libxl__gc *gc,
                                       uint32_t domid,
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 76310ed..f1b24cc 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -665,6 +665,11 @@ fail:
 
 void arch_domain_destroy(struct domain *d)
 {
+    /*
+     * vpl011 is initialized via a DOMCTL call XEN_DOMCTL_vuart_op.
+     */
+    domain_vpl011_deinit(d);
+
     /* IOMMU page table is shared with P2M, always call
      * iommu_domain_destroy() before p2m_teardown().
      */
diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
index 86fa102..280c412 100644
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -6,9 +6,11 @@
 
 #include <xen/types.h>
 #include <xen/errno.h>
+#include <xen/guest_access.h>
 #include <xen/hypercall.h>
 #include <xen/iocap.h>
 #include <xen/lib.h>
+#include <xen/mm.h>
 #include <xen/sched.h>
 #include <xsm/xsm.h>
 #include <public/domctl.h>
@@ -119,6 +121,41 @@ 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;
+        struct xen_domctl_vuart_op *vuart_op = &domctl->u.vuart_op;
+
+        switch(vuart_op->cmd)
+        {
+        case XEN_DOMCTL_VUART_OP_INIT_VPL011:
+
+            if ( !d->creation_finished )
+            {
+                struct vpl011_init_info info;
+
+                info.console_domid = vuart_op->console_domid;
+                info.gfn = _gfn(vuart_op->gfn);
+
+                rc = domain_vpl011_init(d, &info);
+                if ( !rc )
+                {
+                    vuart_op->evtchn = info.evtchn;
+                    rc = __copy_to_guest(u_domctl, domctl, 1);
+                }
+            }
+            else
+                rc = - EPERM;
+
+            break;
+
+        default:
+            rc = -EINVAL;
+            break;
+        }
+
+        return rc;
+    }
     default:
     {
         int rc;
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index f7cbc0a..0da8aa6 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -36,6 +36,7 @@
 #include "grant_table.h"
 #include "hvm/save.h"
 #include "memory.h"
+#include "event_channel.h"
 
 #define XEN_DOMCTL_INTERFACE_VERSION 0x0000000e
 
@@ -1138,6 +1139,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_INIT_VPL011  0
+        uint32_t cmd;           /* XEN_DOMCTL_VUART_OP_* */
+        uint32_t console_domid; /* IN */
+        xen_pfn_t gfn;          /* IN */
+        evtchn_port_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 +1228,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 +1291,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] 67+ messages in thread

* [PATCH 09/17 v5] xen/arm: vpl011: Add a new vuart node in the xenstore
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
                   ` (7 preceding siblings ...)
  2017-06-22  7:38 ` [PATCH 08/17 v5] xen/arm: vpl011: Add a new domctl API to initialize vpl011 Bhupinder Thakur
@ 2017-06-22  7:38 ` Bhupinder Thakur
  2017-06-22 23:06   ` Stefano Stabellini
  2017-06-28 17:16   ` Wei Liu
  2017-06-22  7:38 ` [PATCH 10/17 v5] xen/arm: vpl011: Modify xenconsole to define and use a new console structure Bhupinder Thakur
                   ` (8 subsequent siblings)
  17 siblings, 2 replies; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

Add a new vuart console node to xenstore. This node is added at

/local/domain/$DOMID/vuart/0.

The node contains information such as the ring-ref, event channel,
buffer limit and type of console.

Xenconsole reads the node information to setup the ring buffer and
event channel for sending/receiving vuart data.

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
---
CC: Ian Jackson <ian.jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>

Changes since v4:
-  vuart_device moved inside libxl__device_vuart_add() as a local variable.

Changes since v3:
- Added a backend node for vpl011.
- Removed libxl__device_vuart_add() for HVM guest. It is called only for PV guest.

 tools/libxl/libxl_console.c          | 44 ++++++++++++++++++++++++++++++++++++
 tools/libxl/libxl_create.c           | 10 +++++++-
 tools/libxl/libxl_device.c           |  9 ++++++--
 tools/libxl/libxl_internal.h         |  3 +++
 tools/libxl/libxl_types_internal.idl |  1 +
 5 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/tools/libxl/libxl_console.c b/tools/libxl/libxl_console.c
index 853be15..cdaf7fd 100644
--- a/tools/libxl/libxl_console.c
+++ b/tools/libxl/libxl_console.c
@@ -344,6 +344,50 @@ out:
     return rc;
 }
 
+int libxl__device_vuart_add(libxl__gc *gc, uint32_t domid,
+                            libxl__device_console *console,
+                            libxl__domain_build_state *state)
+{
+    libxl__device device;
+    flexarray_t *ro_front;
+    flexarray_t *back;
+    int rc;
+
+    ro_front = flexarray_make(gc, 16, 1);
+    back = flexarray_make(gc, 16, 1);
+
+    device.backend_devid = console->devid;
+    device.backend_domid = console->backend_domid;
+    device.backend_kind = LIBXL__DEVICE_KIND_VUART;
+    device.devid = console->devid;
+    device.domid = domid;
+    device.kind = LIBXL__DEVICE_KIND_VUART;
+
+    flexarray_append(back, "frontend-id");
+    flexarray_append(back, GCSPRINTF("%d", domid));
+    flexarray_append(back, "online");
+    flexarray_append(back, "1");
+    flexarray_append(back, "state");
+    flexarray_append(back, GCSPRINTF("%d", XenbusStateInitialising));
+    flexarray_append(back, "protocol");
+    flexarray_append(back, LIBXL_XENCONSOLE_PROTOCOL);
+
+    flexarray_append(ro_front, "port");
+    flexarray_append(ro_front, GCSPRINTF("%"PRIu32, state->vuart_port));
+    flexarray_append(ro_front, "ring-ref");
+    flexarray_append(ro_front, GCSPRINTF("%lu", state->vuart_gfn));
+    flexarray_append(ro_front, "limit");
+    flexarray_append(ro_front, GCSPRINTF("%d", LIBXL_XENCONSOLE_LIMIT));
+    flexarray_append(ro_front, "type");
+    flexarray_append(ro_front, "xenconsoled");
+
+    rc = libxl__device_generic_add(gc, XBT_NULL, &device,
+                                   libxl__xs_kvs_of_flexarray(gc, back),
+                                   NULL,
+                                   libxl__xs_kvs_of_flexarray(gc, ro_front));
+    return rc;
+}
+
 int libxl__init_console_from_channel(libxl__gc *gc,
                                      libxl__device_console *console,
                                      int dev_num,
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index bffbc45..cfd85ec 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -1367,7 +1367,7 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev,
     }
     case LIBXL_DOMAIN_TYPE_PV:
     {
-        libxl__device_console console;
+        libxl__device_console console, vuart;
         libxl__device device;
 
         for (i = 0; i < d_config->num_vfbs; i++) {
@@ -1375,6 +1375,14 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev,
             libxl__device_vkb_add(gc, domid, &d_config->vkbs[i]);
         }
 
+        if (d_config->b_info.arch_arm.vuart)
+        {
+            init_console_info(gc, &vuart, 0);
+            vuart.backend_domid = state->console_domid;
+            libxl__device_vuart_add(gc, domid, &vuart, state);
+            libxl__device_console_dispose(&vuart);
+        }
+
         init_console_info(gc, &console, 0);
         console.backend_domid = state->console_domid;
         libxl__device_console_add(gc, domid, &console, state, &device);
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 00356af..3b10c58 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -26,6 +26,9 @@ static char *libxl__device_frontend_path(libxl__gc *gc, libxl__device *device)
     if (device->kind == LIBXL__DEVICE_KIND_CONSOLE && device->devid == 0)
         return GCSPRINTF("%s/console", dom_path);
 
+    if (device->kind == LIBXL__DEVICE_KIND_VUART)
+        return GCSPRINTF("%s/vuart/%d", dom_path, device->devid);
+
     return GCSPRINTF("%s/device/%s/%d", dom_path,
                      libxl__device_kind_to_string(device->kind),
                      device->devid);
@@ -170,7 +173,8 @@ retry_transaction:
          * historically contained other information, such as the
          * vnc-port, which we don't want the guest fiddling with.
          */
-        if (device->kind == LIBXL__DEVICE_KIND_CONSOLE && device->devid == 0)
+        if ((device->kind == LIBXL__DEVICE_KIND_CONSOLE && device->devid == 0) ||
+            (device->kind == LIBXL__DEVICE_KIND_VUART))
             xs_set_permissions(ctx->xsh, t, frontend_path,
                                ro_frontend_perms, ARRAY_SIZE(ro_frontend_perms));
         else
@@ -800,7 +804,8 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
                 dev->domid = domid;
                 dev->kind = kind;
                 dev->devid = atoi(devs[j]);
-                if (dev->backend_kind == LIBXL__DEVICE_KIND_CONSOLE) {
+                if (dev->backend_kind == LIBXL__DEVICE_KIND_CONSOLE ||
+                    dev->backend_kind == LIBXL__DEVICE_KIND_VUART) {
                     /* Currently console devices can be destroyed
                      * synchronously by just removing xenstore entries,
                      * this is what libxl__device_destroy does.
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index d0d50c3..2b3f4e1 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1206,6 +1206,9 @@ _hidden int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
                                       libxl__device_console *console,
                                       libxl__domain_build_state *state,
                                       libxl__device *device);
+_hidden int libxl__device_vuart_add(libxl__gc *gc, uint32_t domid,
+                                    libxl__device_console *console,
+                                    libxl__domain_build_state *state);
 
 /* Returns 1 if device exists, 0 if not, ERROR_* (<0) on error. */
 _hidden int libxl__device_exists(libxl__gc *gc, xs_transaction_t t,
diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl
index 7dc4d0f..c463c33 100644
--- a/tools/libxl/libxl_types_internal.idl
+++ b/tools/libxl/libxl_types_internal.idl
@@ -26,6 +26,7 @@ libxl__device_kind = Enumeration("device_kind", [
     (9, "VUSB"),
     (10, "QUSB"),
     (11, "9PFS"),
+    (12, "VUART"),
     ])
 
 libxl__console_backend = Enumeration("console_backend", [
-- 
2.7.4


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

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

* [PATCH 10/17 v5] xen/arm: vpl011: Modify xenconsole to define and use a new console structure
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
                   ` (8 preceding siblings ...)
  2017-06-22  7:38 ` [PATCH 09/17 v5] xen/arm: vpl011: Add a new vuart node in the xenstore Bhupinder Thakur
@ 2017-06-22  7:38 ` Bhupinder Thakur
  2017-06-22 23:20   ` Stefano Stabellini
  2017-06-28 17:16   ` Wei Liu
  2017-06-22  7:38 ` [PATCH 11/17 v5] xen/arm: vpl011: Rename the console structure field conspath to xspath Bhupinder Thakur
                   ` (7 subsequent siblings)
  17 siblings, 2 replies; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

Xenconsole uses a domain structure which contains console specific fields. This
patch defines a new console structure, which would be used by the xenconsole
functions to perform console specific operations like reading/writing data from/to
the console ring buffer or reading/writing data from/to console tty.

This patch is in preparation to support multiple consoles to support vuart console.

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
---
CC: Ian Jackson <ian.jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>

Changes since v4:
- Moved the following fields from the struct domain to struct console:
  ->xenevtchn_handle *xce_handle;
  ->int xce_pollfd_idx;
  ->int event_count;
  ->long long next_period;

Changes since v3:
- The changes in xenconsole have been split into four patches. This is the first patch
  which modifies the xenconsole to use a new console structure.

Changes since v2:
- Defined a new function console_create_ring() which sets up the ring buffer and 
  event channel a new console. domain_create_ring() uses this function to setup
  a console.
- This patch does not contain vuart specific changes, which would be introduced in
  the next patch.
- Changes for keeping the PV log file name unchanged.

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 | 299 +++++++++++++++++++++++++---------------------
 1 file changed, 165 insertions(+), 134 deletions(-)

diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index e8033d2..30cd167 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -89,25 +89,30 @@ struct buffer {
 	size_t max_capacity;
 };
 
-struct domain {
-	int domid;
+struct console {
 	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;
 	xenevtchn_handle *xce_handle;
 	int xce_pollfd_idx;
-	struct xencons_interface *interface;
 	int event_count;
 	long long next_period;
+	xenevtchn_port_or_error_t local_port;
+	xenevtchn_port_or_error_t remote_port;
+	struct xencons_interface *interface;
+	struct domain *d;
+};
+
+struct domain {
+	int domid;
+	bool is_dead;
+	unsigned last_seen;
+	struct domain *next;
+	struct console console;
 };
 
 static struct domain *dom_head;
@@ -160,9 +165,10 @@ static int write_with_timestamp(int fd, const char *data, size_t sz,
 
 static void buffer_append(struct domain *dom)
 {
-	struct buffer *buffer = &dom->buffer;
+	struct console *con = &dom->console;
+	struct buffer *buffer = &con->buffer;
 	XENCONS_RING_IDX cons, prod, size;
-	struct xencons_interface *intf = dom->interface;
+	struct xencons_interface *intf = con->interface;
 
 	cons = intf->out_cons;
 	prod = intf->out_prod;
@@ -187,22 +193,22 @@ static void buffer_append(struct domain *dom)
 
 	xen_mb();
 	intf->out_cons = cons;
-	xenevtchn_notify(dom->xce_handle, dom->local_port);
+	xenevtchn_notify(con->xce_handle, con->local_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);
 		}
@@ -338,14 +344,16 @@ static int create_domain_log(struct domain *dom)
 
 static void domain_close_tty(struct domain *dom)
 {
-	if (dom->master_fd != -1) {
-		close(dom->master_fd);
-		dom->master_fd = -1;
+	struct console *con = &dom->console;
+
+	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;
 	}
 }
 
@@ -418,11 +426,12 @@ static int domain_create_tty(struct domain *dom)
 	char *data;
 	unsigned int len;
 	struct termios term;
+	struct console *con = &dom->console;
 
-	assert(dom->slave_fd == -1);
-	assert(dom->master_fd == -1);
+	assert(con->slave_fd == -1);
+	assert(con->master_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)",
@@ -430,7 +439,7 @@ static int domain_create_tty(struct domain *dom)
 		return 0;
 	}
 
-	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 +447,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,7 +455,7 @@ 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)",
@@ -454,18 +463,18 @@ static int domain_create_tty(struct domain *dom)
 		goto out;
 	}
 
-	success = asprintf(&path, "%s/limit", dom->conspath) !=
+	success = asprintf(&path, "%s/limit", con->conspath) !=
 		-1;
 	if (!success)
 		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/tty", con->conspath) != -1);
 	if (!success)
 		goto out;
 	success = xs_write(xs, XBT_NULL, path, slave, strlen(slave));
@@ -473,7 +482,7 @@ static int domain_create_tty(struct domain *dom)
 	if (!success)
 		goto out;
 
-	if (fcntl(dom->master_fd, F_SETFL, O_NONBLOCK) == -1)
+	if (fcntl(con->master_fd, F_SETFL, O_NONBLOCK) == -1)
 		goto out;
 
 	return 1;
@@ -519,29 +528,32 @@ static int xs_gather(struct xs_handle *xs, const char *dir, ...)
 
 static void domain_unmap_interface(struct domain *dom)
 {
-	if (dom->interface == NULL)
+	struct console *con = &dom->console;
+
+	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 int domain_create_ring(struct domain *dom)
 {
 	int err, remote_port, ring_ref, rc;
 	char *type, path[PATH_MAX];
+	struct console *con = &dom->console;
 
-	err = xs_gather(xs, dom->conspath,
+	err = xs_gather(xs, con->conspath,
 			"ring-ref", "%u", &ring_ref,
 			"port", "%i", &remote_port,
 			NULL);
 	if (err)
 		goto out;
 
-	snprintf(path, sizeof(path), "%s/type", dom->conspath);
+	snprintf(path, sizeof(path), "%s/type", con->conspath);
 	type = xs_read(xs, XBT_NULL, path, NULL);
 	if (type && strcmp(type, "xenconsoled") != 0) {
 		free(type);
@@ -550,77 +562,77 @@ 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)
+	if (ring_ref != con->ring_ref && con->ring_ref != -1)
 		domain_unmap_interface(dom);
 
-	if (!dom->interface && xgt_handle) {
+	if (!con->interface && xgt_handle) {
 		/* Prefer using grant table */
-		dom->interface = xengnttab_map_grant_ref(xgt_handle,
+		con->interface = xengnttab_map_grant_ref(xgt_handle,
 			dom->domid, GNTTAB_RESERVED_CONSOLE,
 			PROT_READ|PROT_WRITE);
-		dom->ring_ref = -1;
+		con->ring_ref = -1;
 	}
-	if (!dom->interface) {
+	if (!con->interface) {
 		/* Fall back to xc_map_foreign_range */
-		dom->interface = xc_map_foreign_range(
+		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 (con->interface == NULL) {
 			err = EINVAL;
 			goto out;
 		}
-		dom->ring_ref = ring_ref;
+		con->ring_ref = ring_ref;
 	}
 
 	/* Go no further if port has not changed and we are still bound. */
-	if (remote_port == dom->remote_port) {
+	if (remote_port == con->remote_port) {
 		xc_evtchn_status_t status = {
 			.dom = DOMID_SELF,
-			.port = dom->local_port };
+			.port = con->local_port };
 		if ((xc_evtchn_status(xc, &status) == 0) &&
 		    (status.status == EVTCHNSTAT_interdomain))
 			goto out;
 	}
 
-	dom->local_port = -1;
-	dom->remote_port = -1;
-	if (dom->xce_handle != NULL)
-		xenevtchn_close(dom->xce_handle);
+	con->local_port = -1;
+	con->remote_port = -1;
+	if (con->xce_handle != NULL)
+		xenevtchn_close(con->xce_handle);
 
 	/* Opening evtchn independently for each console is a bit
 	 * wasteful, but that's how the code is structured... */
-	dom->xce_handle = xenevtchn_open(NULL, 0);
-	if (dom->xce_handle == NULL) {
+	con->xce_handle = xenevtchn_open(NULL, 0);
+	if (con->xce_handle == NULL) {
 		err = errno;
 		goto out;
 	}
  
-	rc = xenevtchn_bind_interdomain(dom->xce_handle,
+	rc = xenevtchn_bind_interdomain(con->xce_handle,
 		dom->domid, remote_port);
 
 	if (rc == -1) {
 		err = errno;
-		xenevtchn_close(dom->xce_handle);
-		dom->xce_handle = NULL;
+		xenevtchn_close(con->xce_handle);
+		con->xce_handle = NULL;
 		goto out;
 	}
-	dom->local_port = rc;
-	dom->remote_port = remote_port;
+	con->local_port = rc;
+	con->remote_port = remote_port;
 
-	if (dom->master_fd == -1) {
+	if (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;
+			xenevtchn_close(con->xce_handle);
+			con->xce_handle = NULL;
+			con->local_port = -1;
+			con->remote_port = -1;
 			goto out;
 		}
 	}
 
-	if (log_guest && (dom->log_fd == -1))
-		dom->log_fd = create_domain_log(dom);
+	if (log_guest && (con->log_fd == -1))
+		con->log_fd = create_domain_log(dom);
 
  out:
 	return err;
@@ -630,16 +642,17 @@ static bool watch_domain(struct domain *dom, bool watch)
 {
 	char domid_str[3 + MAX_STRLEN(dom->domid)];
 	bool success;
+	struct console *con = &dom->console;
 
 	snprintf(domid_str, sizeof(domid_str), "dom%u", dom->domid);
 	if (watch) {
-		success = xs_watch(xs, dom->conspath, domid_str);
+		success = xs_watch(xs, con->conspath, domid_str);
 		if (success)
 			domain_create_ring(dom);
 		else
-			xs_unwatch(xs, dom->conspath, domid_str);
+			xs_unwatch(xs, con->conspath, domid_str);
 	} else {
-		success = xs_unwatch(xs, dom->conspath, domid_str);
+		success = xs_unwatch(xs, con->conspath, domid_str);
 	}
 
 	return success;
@@ -651,6 +664,7 @@ static struct domain *create_domain(int domid)
 	struct domain *dom;
 	char *s;
 	struct timespec ts;
+	struct console *con;
 
 	if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
 		dolog(LOG_ERR, "Cannot get time of day %s:%s:L%d",
@@ -667,25 +681,26 @@ static struct domain *create_domain(int domid)
 
 	dom->domid = domid;
 
-	dom->conspath = xs_get_domain_path(xs, dom->domid);
-	s = realloc(dom->conspath, strlen(dom->conspath) +
+	con = &dom->console;
+	con->conspath = xs_get_domain_path(xs, dom->domid);
+	s = realloc(con->conspath, strlen(con->conspath) +
 		    strlen("/console") + 1);
 	if (s == NULL)
 		goto out;
-	dom->conspath = s;
-	strcat(dom->conspath, "/console");
+	con->conspath = s;
+	strcat(con->conspath, "/console");
 
-	dom->master_fd = -1;
-	dom->master_pollfd_idx = -1;
-	dom->slave_fd = -1;
-	dom->log_fd = -1;
-	dom->xce_pollfd_idx = -1;
+	con->master_fd = -1;
+	con->master_pollfd_idx = -1;
+	con->slave_fd = -1;
+	con->log_fd = -1;
+	con->xce_pollfd_idx = -1;
 
-	dom->next_period = ((long long)ts.tv_sec * 1000) + (ts.tv_nsec / 1000000) + RATE_LIMIT_PERIOD;
+	con->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;
+	con->ring_ref = -1;
+	con->local_port = -1;
+	con->remote_port = -1;
 
 	if (!watch_domain(dom, true))
 		goto out;
@@ -697,7 +712,7 @@ static struct domain *create_domain(int domid)
 
 	return dom;
  out:
-	free(dom->conspath);
+	free(con->conspath);
 	free(dom);
 	return NULL;
 }
@@ -729,30 +744,34 @@ static void remove_domain(struct domain *dom)
 
 static void cleanup_domain(struct domain *d)
 {
+	struct console *con = &d->console;
+
 	domain_close_tty(d);
 
-	if (d->log_fd != -1) {
-		close(d->log_fd);
-		d->log_fd = -1;
+	if (con->log_fd != -1) {
+		close(con->log_fd);
+		con->log_fd = -1;
 	}
 
-	free(d->buffer.data);
-	d->buffer.data = NULL;
+	free(con->buffer.data);
+	con->buffer.data = NULL;
 
-	free(d->conspath);
-	d->conspath = NULL;
+	free(con->conspath);
+	con->conspath = NULL;
 
 	remove_domain(d);
 }
 
 static void shutdown_domain(struct domain *d)
 {
+	struct console *con = &d->console;
+
 	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;
+	if (con->xce_handle != NULL)
+		xenevtchn_close(con->xce_handle);
+	con->xce_handle = NULL;
 }
 
 static unsigned enum_pass = 0;
@@ -782,7 +801,8 @@ static void enum_domains(void)
 
 static int ring_free_bytes(struct domain *dom)
 {
-	struct xencons_interface *intf = dom->interface;
+	struct console *con = &dom->console;
+	struct xencons_interface *intf = con->interface;
 	XENCONS_RING_IDX cons, prod, space;
 
 	cons = intf->in_cons;
@@ -812,7 +832,8 @@ static void handle_tty_read(struct domain *dom)
 	ssize_t len = 0;
 	char msg[80];
 	int i;
-	struct xencons_interface *intf = dom->interface;
+	struct console *con = &dom->console;
+	struct xencons_interface *intf = con->interface;
 	XENCONS_RING_IDX prod;
 
 	if (dom->is_dead)
@@ -825,7 +846,7 @@ static void handle_tty_read(struct domain *dom)
 	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,7 +862,7 @@ static void handle_tty_read(struct domain *dom)
 		}
 		xen_wmb();
 		intf->in_prod = prod;
-		xenevtchn_notify(dom->xce_handle, dom->local_port);
+		xenevtchn_notify(con->xce_handle, con->local_port);
 	} else {
 		domain_close_tty(dom);
 		shutdown_domain(dom);
@@ -851,37 +872,39 @@ static void handle_tty_read(struct domain *dom)
 static void handle_tty_write(struct domain *dom)
 {
 	ssize_t len;
+	struct console *con = &dom->console;
 
 	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 handle_ring_read(struct domain *dom)
 {
 	xenevtchn_port_or_error_t port;
+	struct console *con = &dom->console;
 
 	if (dom->is_dead)
 		return;
 
-	if ((port = xenevtchn_pending(dom->xce_handle)) == -1)
+	if ((port = xenevtchn_pending(con->xce_handle)) == -1)
 		return;
 
-	dom->event_count++;
+	con->event_count++;
 
 	buffer_append(dom);
 
-	if (dom->event_count < RATE_LIMIT_ALLOWANCE)
-		(void)xenevtchn_unmask(dom->xce_handle, port);
+	if (con->event_count < RATE_LIMIT_ALLOWANCE)
+		(void)xenevtchn_unmask(con->xce_handle, port);
 }
 
 static void handle_xs(void)
@@ -948,9 +971,11 @@ 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);
+			struct console *con = &d->console;
+
+			if (con->log_fd != -1)
+				close(con->log_fd);
+			con->log_fd = create_domain_log(d);
 		}
 	}
 
@@ -1059,48 +1084,52 @@ void handle_io(void)
 		/* Re-calculate any event counter allowances & unblock
 		   domains with new allowance */
 		for (d = dom_head; d; d = d->next) {
+			struct console *con = &d->console;
+
 			/* CS 16257:955ee4fa1345 introduces a 5ms fuzz
 			 * for select(), it is not clear poll() has
 			 * similar behavior (returning a couple of ms
 			 * sooner than requested) as well. Just leave
 			 * the fuzz here. Remove it with a separate
 			 * patch if necessary */
-			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);
+			if ((now+5) > con->next_period) {
+				con->next_period = now + RATE_LIMIT_PERIOD;
+				if (con->event_count >= RATE_LIMIT_ALLOWANCE) {
+					(void)xenevtchn_unmask(con->xce_handle, con->local_port);
 				}
-				d->event_count = 0;
+				con->event_count = 0;
 			}
 		}
 
 		for (d = dom_head; d; d = d->next) {
-			if (d->event_count >= RATE_LIMIT_ALLOWANCE) {
+			struct console *con = &d->console;
+
+			if (con->event_count >= RATE_LIMIT_ALLOWANCE) {
 				/* Determine if we're going to be the next time slice to expire */
 				if (!next_timeout ||
-				    d->next_period < next_timeout)
-					next_timeout = d->next_period;
-			} else if (d->xce_handle != NULL) {
+				    con->next_period < next_timeout)
+					next_timeout = con->next_period;
+			} else if (con->xce_handle != NULL) {
 				if (discard_overflowed_data ||
-				    !d->buffer.max_capacity ||
-				    d->buffer.size < d->buffer.max_capacity) {
-					int evtchn_fd = xenevtchn_fd(d->xce_handle);
-					d->xce_pollfd_idx = set_fds(evtchn_fd,
+				    !con->buffer.max_capacity ||
+				    con->buffer.size < con->buffer.max_capacity) {
+					int evtchn_fd = xenevtchn_fd(con->xce_handle);
+					con->xce_pollfd_idx = set_fds(evtchn_fd,
 								    POLLIN|POLLPRI);
 				}
 			}
 
-			if (d->master_fd != -1) {
+			if (con->master_fd != -1) {
 				short events = 0;
 				if (!d->is_dead && ring_free_bytes(d))
 					events |= POLLIN;
 
-				if (!buffer_empty(&d->buffer))
+				if (!buffer_empty(&con->buffer))
 					events |= POLLOUT;
 
 				if (events)
-					d->master_pollfd_idx =
-						set_fds(d->master_fd,
+					con->master_pollfd_idx =
+						set_fds(con->master_fd,
 							events|POLLPRI);
 			}
 		}
@@ -1163,33 +1192,35 @@ void handle_io(void)
 		}
 
 		for (d = dom_head; d; d = n) {
+			struct console *con = &d->console;
+
 			n = d->next;
-			if (d->event_count < RATE_LIMIT_ALLOWANCE) {
-				if (d->xce_handle != NULL &&
-				    d->xce_pollfd_idx != -1 &&
-				    !(fds[d->xce_pollfd_idx].revents &
+			if (con->event_count < RATE_LIMIT_ALLOWANCE) {
+				if (con->xce_handle != NULL &&
+				    con->xce_pollfd_idx != -1 &&
+				    !(fds[con->xce_pollfd_idx].revents &
 				      ~(POLLIN|POLLOUT|POLLPRI)) &&
-				      (fds[d->xce_pollfd_idx].revents &
+				      (fds[con->xce_pollfd_idx].revents &
 				       POLLIN))
 				    handle_ring_read(d);
 			}
 
-			if (d->master_fd != -1 && d->master_pollfd_idx != -1) {
-				if (fds[d->master_pollfd_idx].revents &
+			if (con->master_fd != -1 && con->master_pollfd_idx != -1) {
+				if (fds[con->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 &
+					if (fds[con->master_pollfd_idx].revents &
 					    POLLIN)
 						handle_tty_read(d);
-					if (fds[d->master_pollfd_idx].revents &
+					if (fds[con->master_pollfd_idx].revents &
 					    POLLOUT)
 						handle_tty_write(d);
 				}
 			}
 
-			d->xce_pollfd_idx = d->master_pollfd_idx = -1;
+			con->xce_pollfd_idx = con->master_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] 67+ messages in thread

* [PATCH 11/17 v5] xen/arm: vpl011: Rename the console structure field conspath to xspath
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
                   ` (9 preceding siblings ...)
  2017-06-22  7:38 ` [PATCH 10/17 v5] xen/arm: vpl011: Modify xenconsole to define and use a new console structure Bhupinder Thakur
@ 2017-06-22  7:38 ` Bhupinder Thakur
  2017-06-22 23:21   ` Stefano Stabellini
  2017-06-28 17:16   ` Wei Liu
  2017-06-22  7:38 ` [PATCH 12/17 v5] xen/arm: vpl011: Modify xenconsole functions to take console structure as input Bhupinder Thakur
                   ` (6 subsequent siblings)
  17 siblings, 2 replies; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

The console->conspath name is changed to console->xspath as it is
clear from the name that it is referring to xenstore path.

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
---
CC: Ian Jackson <ian.jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>

Changes since v4:
- Split this change in a separate patch.

 tools/console/daemon/io.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index 30cd167..6f5c69c 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -95,7 +95,7 @@ struct console {
 	int slave_fd;
 	int log_fd;
 	struct buffer buffer;
-	char *conspath;
+	char *xspath;
 	int ring_ref;
 	xenevtchn_handle *xce_handle;
 	int xce_pollfd_idx;
@@ -463,7 +463,7 @@ static int domain_create_tty(struct domain *dom)
 		goto out;
 	}
 
-	success = asprintf(&path, "%s/limit", con->conspath) !=
+	success = asprintf(&path, "%s/limit", con->xspath) !=
 		-1;
 	if (!success)
 		goto out;
@@ -474,7 +474,7 @@ static int domain_create_tty(struct domain *dom)
 	}
 	free(path);
 
-	success = (asprintf(&path, "%s/tty", con->conspath) != -1);
+	success = (asprintf(&path, "%s/tty", con->xspath) != -1);
 	if (!success)
 		goto out;
 	success = xs_write(xs, XBT_NULL, path, slave, strlen(slave));
@@ -546,14 +546,14 @@ static int domain_create_ring(struct domain *dom)
 	char *type, path[PATH_MAX];
 	struct console *con = &dom->console;
 
-	err = xs_gather(xs, con->conspath,
+	err = xs_gather(xs, con->xspath,
 			"ring-ref", "%u", &ring_ref,
 			"port", "%i", &remote_port,
 			NULL);
 	if (err)
 		goto out;
 
-	snprintf(path, sizeof(path), "%s/type", con->conspath);
+	snprintf(path, sizeof(path), "%s/type", con->xspath);
 	type = xs_read(xs, XBT_NULL, path, NULL);
 	if (type && strcmp(type, "xenconsoled") != 0) {
 		free(type);
@@ -646,13 +646,13 @@ static bool watch_domain(struct domain *dom, bool watch)
 
 	snprintf(domid_str, sizeof(domid_str), "dom%u", dom->domid);
 	if (watch) {
-		success = xs_watch(xs, con->conspath, domid_str);
+		success = xs_watch(xs, con->xspath, domid_str);
 		if (success)
 			domain_create_ring(dom);
 		else
-			xs_unwatch(xs, con->conspath, domid_str);
+			xs_unwatch(xs, con->xspath, domid_str);
 	} else {
-		success = xs_unwatch(xs, con->conspath, domid_str);
+		success = xs_unwatch(xs, con->xspath, domid_str);
 	}
 
 	return success;
@@ -682,13 +682,13 @@ static struct domain *create_domain(int domid)
 	dom->domid = domid;
 
 	con = &dom->console;
-	con->conspath = xs_get_domain_path(xs, dom->domid);
-	s = realloc(con->conspath, strlen(con->conspath) +
+	con->xspath = xs_get_domain_path(xs, dom->domid);
+	s = realloc(con->xspath, strlen(con->xspath) +
 		    strlen("/console") + 1);
 	if (s == NULL)
 		goto out;
-	con->conspath = s;
-	strcat(con->conspath, "/console");
+	con->xspath = s;
+	strcat(con->xspath, "/console");
 
 	con->master_fd = -1;
 	con->master_pollfd_idx = -1;
@@ -712,7 +712,7 @@ static struct domain *create_domain(int domid)
 
 	return dom;
  out:
-	free(con->conspath);
+	free(con->xspath);
 	free(dom);
 	return NULL;
 }
@@ -756,8 +756,8 @@ static void cleanup_domain(struct domain *d)
 	free(con->buffer.data);
 	con->buffer.data = NULL;
 
-	free(con->conspath);
-	con->conspath = NULL;
+	free(con->xspath);
+	con->xspath = NULL;
 
 	remove_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] 67+ messages in thread

* [PATCH 12/17 v5] xen/arm: vpl011: Modify xenconsole functions to take console structure as input
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
                   ` (10 preceding siblings ...)
  2017-06-22  7:38 ` [PATCH 11/17 v5] xen/arm: vpl011: Rename the console structure field conspath to xspath Bhupinder Thakur
@ 2017-06-22  7:38 ` Bhupinder Thakur
  2017-06-28 17:16   ` Wei Liu
  2017-06-22  7:38 ` [PATCH 13/17 v5] xen/arm: vpl011: Modify xenconsole to support multiple consoles Bhupinder Thakur
                   ` (5 subsequent siblings)
  17 siblings, 1 reply; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

Xenconsole functions take domain structure as input. These functions shall be
modified to take console structure as input since these functions typically perform
console specific operations.

Also the console specific functions starting with prefix "domain_" shall be modified
to "console_" to indicate that these are console specific functions.

This patch is in preparation to support multiple consoles to support vuart console.

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
Acked-by: Stefano Stabellini <sstabellini@kernel.org>
---
CC: Ian Jackson <ian.jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>

Changes since v3:
- The changes in xenconsole have been split into four patches. This is the second patch.

 tools/console/daemon/io.c | 79 +++++++++++++++++++++++------------------------
 1 file changed, 38 insertions(+), 41 deletions(-)

diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index 6f5c69c..a2a3496 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -163,10 +163,10 @@ static int write_with_timestamp(int fd, const char *data, size_t sz,
 	return 0;
 }
 
-static void buffer_append(struct domain *dom)
+static void buffer_append(struct console *con)
 {
-	struct console *con = &dom->console;
 	struct buffer *buffer = &con->buffer;
+	struct domain *dom = con->d;
 	XENCONS_RING_IDX cons, prod, size;
 	struct xencons_interface *intf = con->interface;
 
@@ -296,12 +296,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);
@@ -342,10 +343,8 @@ 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)
 {
-	struct console *con = &dom->console;
-
 	if (con->master_fd != -1) {
 		close(con->master_fd);
 		con->master_fd = -1;
@@ -417,7 +416,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;
@@ -426,7 +425,7 @@ static int domain_create_tty(struct domain *dom)
 	char *data;
 	unsigned int len;
 	struct termios term;
-	struct console *con = &dom->console;
+	struct domain *dom = con->d;
 
 	assert(con->slave_fd == -1);
 	assert(con->master_fd == -1);
@@ -487,7 +486,7 @@ static int domain_create_tty(struct domain *dom)
 
 	return 1;
 out:
-	domain_close_tty(dom);
+	console_close_tty(con);
 	return 0;
 }
  
@@ -526,10 +525,8 @@ 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)
 {
-	struct console *con = &dom->console;
-
 	if (con->interface == NULL)
 		return;
 	if (xgt_handle && con->ring_ref == -1)
@@ -540,11 +537,11 @@ static void domain_unmap_interface(struct domain *dom)
 	con->ring_ref = -1;
 }
  
-static int domain_create_ring(struct domain *dom)
+static int console_create_ring(struct console *con)
 {
 	int err, remote_port, ring_ref, rc;
 	char *type, path[PATH_MAX];
-	struct console *con = &dom->console;
+	struct domain *dom = con->d;
 
 	err = xs_gather(xs, con->xspath,
 			"ring-ref", "%u", &ring_ref,
@@ -563,7 +560,7 @@ static int domain_create_ring(struct domain *dom)
 
 	/* If using ring_ref and it has changed, remap */
 	if (ring_ref != con->ring_ref && con->ring_ref != -1)
-		domain_unmap_interface(dom);
+		console_unmap_interface(con);
 
 	if (!con->interface && xgt_handle) {
 		/* Prefer using grant table */
@@ -621,7 +618,7 @@ static int domain_create_ring(struct domain *dom)
 	con->remote_port = remote_port;
 
 	if (con->master_fd == -1) {
-		if (!domain_create_tty(dom)) {
+		if (!console_create_tty(con)) {
 			err = errno;
 			xenevtchn_close(con->xce_handle);
 			con->xce_handle = NULL;
@@ -632,7 +629,7 @@ static int domain_create_ring(struct domain *dom)
 	}
 
 	if (log_guest && (con->log_fd == -1))
-		con->log_fd = create_domain_log(dom);
+		con->log_fd = create_console_log(con);
 
  out:
 	return err;
@@ -648,7 +645,7 @@ static bool watch_domain(struct domain *dom, bool watch)
 	if (watch) {
 		success = xs_watch(xs, con->xspath, domid_str);
 		if (success)
-			domain_create_ring(dom);
+			console_create_ring(con);
 		else
 			xs_unwatch(xs, con->xspath, domid_str);
 	} else {
@@ -695,6 +692,7 @@ static struct domain *create_domain(int domid)
 	con->slave_fd = -1;
 	con->log_fd = -1;
 	con->xce_pollfd_idx = -1;
+	con->d = dom;
 
 	con->next_period = ((long long)ts.tv_sec * 1000) + (ts.tv_nsec / 1000000) + RATE_LIMIT_PERIOD;
 
@@ -746,7 +744,7 @@ static void cleanup_domain(struct domain *d)
 {
 	struct console *con = &d->console;
 
-	domain_close_tty(d);
+	console_close_tty(con);
 
 	if (con->log_fd != -1) {
 		close(con->log_fd);
@@ -768,7 +766,7 @@ static void shutdown_domain(struct domain *d)
 
 	d->is_dead = true;
 	watch_domain(d, false);
-	domain_unmap_interface(d);
+	console_unmap_interface(con);
 	if (con->xce_handle != NULL)
 		xenevtchn_close(con->xce_handle);
 	con->xce_handle = NULL;
@@ -799,9 +797,8 @@ static void enum_domains(void)
 	}
 }
 
-static int ring_free_bytes(struct domain *dom)
+static int ring_free_bytes(struct console *con)
 {
-	struct console *con = &dom->console;
 	struct xencons_interface *intf = con->interface;
 	XENCONS_RING_IDX cons, prod, space;
 
@@ -816,30 +813,30 @@ static int ring_free_bytes(struct domain *dom)
 	return (sizeof(intf->in) - space);
 }
 
-static void domain_handle_broken_tty(struct domain *dom, int recreate)
+static void console_handle_broken_tty(struct console *con, int recreate)
 {
-	domain_close_tty(dom);
+	console_close_tty(con);
 
 	if (recreate) {
-		domain_create_tty(dom);
+		console_create_tty(con);
 	} else {
-		shutdown_domain(dom);
+		shutdown_domain(con->d);
 	}
 }
 
-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 console *con = &dom->console;
 	struct xencons_interface *intf = con->interface;
+	struct domain *dom = con->d;
 	XENCONS_RING_IDX prod;
 
 	if (dom->is_dead)
 		return;
 
-	len = ring_free_bytes(dom);
+	len = ring_free_bytes(con);
 	if (len == 0)
 		return;
 
@@ -853,7 +850,7 @@ static void handle_tty_read(struct domain *dom)
 	 * keep the slave open for the duration.
 	 */
 	if (len < 0) {
-		domain_handle_broken_tty(dom, domain_is_valid(dom->domid));
+		console_handle_broken_tty(con, domain_is_valid(dom->domid));
 	} else if (domain_is_valid(dom->domid)) {
 		prod = intf->in_prod;
 		for (i = 0; i < len; i++) {
@@ -864,15 +861,15 @@ static void handle_tty_read(struct domain *dom)
 		intf->in_prod = prod;
 		xenevtchn_notify(con->xce_handle, con->local_port);
 	} else {
-		domain_close_tty(dom);
+		console_close_tty(con);
 		shutdown_domain(dom);
 	}
 }
 
-static void handle_tty_write(struct domain *dom)
+static void handle_tty_write(struct console *con)
 {
 	ssize_t len;
-	struct console *con = &dom->console;
+	struct domain *dom = con->d;
 
 	if (dom->is_dead)
 		return;
@@ -882,7 +879,7 @@ static void handle_tty_write(struct domain *dom)
  	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));
+		console_handle_broken_tty(con, domain_is_valid(dom->domid));
 	} else {
 		buffer_advance(&con->buffer, len);
 	}
@@ -901,7 +898,7 @@ static void handle_ring_read(struct domain *dom)
 
 	con->event_count++;
 
-	buffer_append(dom);
+	buffer_append(con);
 
 	if (con->event_count < RATE_LIMIT_ALLOWANCE)
 		(void)xenevtchn_unmask(con->xce_handle, port);
@@ -925,7 +922,7 @@ static void handle_xs(void)
 		/* We may get watches firing for domains that have recently
 		   been removed, so dom may be NULL here. */
 		if (dom && dom->is_dead == false)
-			domain_create_ring(dom);
+			console_create_ring(&dom->console);
 	}
 
 	free(vec);
@@ -975,7 +972,7 @@ static void handle_log_reload(void)
 
 			if (con->log_fd != -1)
 				close(con->log_fd);
-			con->log_fd = create_domain_log(d);
+			con->log_fd = create_console_log(con);
 		}
 	}
 
@@ -1121,7 +1118,7 @@ void handle_io(void)
 
 			if (con->master_fd != -1) {
 				short events = 0;
-				if (!d->is_dead && ring_free_bytes(d))
+				if (!d->is_dead && ring_free_bytes(con))
 					events |= POLLIN;
 
 				if (!buffer_empty(&con->buffer))
@@ -1208,15 +1205,15 @@ void handle_io(void)
 			if (con->master_fd != -1 && con->master_pollfd_idx != -1) {
 				if (fds[con->master_pollfd_idx].revents &
 				    ~(POLLIN|POLLOUT|POLLPRI))
-					domain_handle_broken_tty(d,
+					console_handle_broken_tty(con,
 						   domain_is_valid(d->domid));
 				else {
 					if (fds[con->master_pollfd_idx].revents &
 					    POLLIN)
-						handle_tty_read(d);
+						handle_tty_read(con);
 					if (fds[con->master_pollfd_idx].revents &
 					    POLLOUT)
-						handle_tty_write(d);
+						handle_tty_write(con);
 				}
 			}
 
-- 
2.7.4


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

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

* [PATCH 13/17 v5] xen/arm: vpl011: Modify xenconsole to support multiple consoles
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
                   ` (11 preceding siblings ...)
  2017-06-22  7:38 ` [PATCH 12/17 v5] xen/arm: vpl011: Modify xenconsole functions to take console structure as input Bhupinder Thakur
@ 2017-06-22  7:38 ` Bhupinder Thakur
  2017-06-22 23:51   ` Stefano Stabellini
  2017-06-28 17:16   ` Wei Liu
  2017-06-22  7:38 ` [PATCH 14/17 v5] xen/arm: vpl011: Add support for vuart console in xenconsole Bhupinder Thakur
                   ` (4 subsequent siblings)
  17 siblings, 2 replies; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

This patch adds the support for multiple consoles and introduces the iterator
functions to operate on multiple consoles.

This patch is in preparation to support a new vuart console.

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
---
CC: Ian Jackson <ian.jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>

Changes since v4:
- Changes to make event channel handling per console rather than per domain.

Changes since v3:
- The changes in xenconsole have been split into four patches. This is the third patch.

 tools/console/daemon/io.c | 435 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 302 insertions(+), 133 deletions(-)

diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index a2a3496..baf0e2e 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -90,12 +90,14 @@ struct buffer {
 };
 
 struct console {
+	char *ttyname;
 	int master_fd;
 	int master_pollfd_idx;
 	int slave_fd;
 	int log_fd;
 	struct buffer buffer;
 	char *xspath;
+	char *log_suffix;
 	int ring_ref;
 	xenevtchn_handle *xce_handle;
 	int xce_pollfd_idx;
@@ -107,16 +109,112 @@ struct console {
 	struct domain *d;
 };
 
+struct console_data {
+	char *xsname;
+	char *ttyname;
+	char *log_suffix;
+};
+
+static struct console_data console_data[] = {
+
+	{
+		.xsname = "/console",
+		.ttyname = "tty",
+		.log_suffix = "",
+	},
+};
+
+#define MAX_CONSOLE (sizeof(console_data)/sizeof(struct console_data))
+
 struct domain {
 	int domid;
 	bool is_dead;
 	unsigned last_seen;
 	struct domain *next;
-	struct console console;
+	struct console console[MAX_CONSOLE];
 };
 
 static struct domain *dom_head;
 
+typedef void (*VOID_ITER_FUNC_ARG1)(struct console *);
+typedef bool (*BOOL_ITER_FUNC_ARG1)(struct console *);
+typedef int (*INT_ITER_FUNC_ARG1)(struct console *);
+typedef void (*VOID_ITER_FUNC_ARG2)(struct console *,  void *);
+typedef int (*INT_ITER_FUNC_ARG3)(struct console *,
+			 struct domain *dom, void **);
+
+static inline bool console_enabled(struct console *con)
+{
+	return con->local_port != -1;
+}
+
+static inline void console_iter_void_arg1(struct domain *d,
+										  VOID_ITER_FUNC_ARG1 iter_func)
+{
+	int i = 0;
+	struct console *con = &(d->console[0]);
+
+	for (i = 0; i < MAX_CONSOLE; i++, con++)
+	{
+		iter_func(con);
+	}
+}
+
+static inline void console_iter_void_arg2(struct domain *d,
+										  VOID_ITER_FUNC_ARG2 iter_func,
+										  void *iter_data)
+{
+	int i = 0;
+	struct console *con = &(d->console[0]);
+
+	for (i = 0; i < MAX_CONSOLE; i++, con++)
+	{
+		iter_func(con, iter_data);
+	}
+}
+
+static inline bool console_iter_bool_arg1(struct domain *d,
+										  BOOL_ITER_FUNC_ARG1 iter_func)
+{
+	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_int_arg1(struct domain *d,
+										INT_ITER_FUNC_ARG1 iter_func)
+{
+	int i = 0;
+	struct console *con = &(d->console[0]);
+
+	for (i = 0; i < MAX_CONSOLE; i++, con++)
+	{
+		if (iter_func(con))
+			return 1;
+	}
+	return 0;
+}
+
+static inline int console_iter_int_arg3(struct domain *d,
+										INT_ITER_FUNC_ARG3 iter_func,
+										void **iter_data)
+{
+	int i = 0;
+	struct console *con = &(d->console[0]);
+
+	for (i = 0; i < MAX_CONSOLE; i++, con++)
+	{
+		if (iter_func(con, d, iter_data))
+			return 1;
+	}
+	return 0;
+}
 static int write_all(int fd, const char* buf, size_t len)
 {
 	while (len) {
@@ -163,12 +261,22 @@ static int write_with_timestamp(int fd, const char *data, size_t sz,
 	return 0;
 }
 
-static void buffer_append(struct console *con)
+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, xenevtchn_port_or_error_t port)
 {
 	struct buffer *buffer = &con->buffer;
+	struct xencons_interface *intf = con->interface;
 	struct domain *dom = con->d;
 	XENCONS_RING_IDX cons, prod, size;
-	struct xencons_interface *intf = con->interface;
 
 	cons = intf->out_cons;
 	prod = intf->out_prod;
@@ -321,7 +429,7 @@ static int create_console_log(struct console *con)
 		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, data, con->log_suffix);
 	free(data);
 	logfile[PATH_MAX-1] = '\0';
 
@@ -473,7 +581,7 @@ static int console_create_tty(struct console *con)
 	}
 	free(path);
 
-	success = (asprintf(&path, "%s/tty", con->xspath) != -1);
+	success = (asprintf(&path, "%s/%s", con->xspath, con->ttyname) != -1);
 	if (!success)
 		goto out;
 	success = xs_write(xs, XBT_NULL, path, slave, strlen(slave));
@@ -594,6 +702,7 @@ static int console_create_ring(struct console *con)
 
 	con->local_port = -1;
 	con->remote_port = -1;
+
 	if (con->xce_handle != NULL)
 		xenevtchn_close(con->xce_handle);
 
@@ -639,13 +748,13 @@ static bool watch_domain(struct domain *dom, bool watch)
 {
 	char domid_str[3 + MAX_STRLEN(dom->domid)];
 	bool success;
-	struct console *con = &dom->console;
+	struct console *con = &dom->console[0];
 
 	snprintf(domid_str, sizeof(domid_str), "dom%u", dom->domid);
 	if (watch) {
 		success = xs_watch(xs, con->xspath, domid_str);
 		if (success)
-			console_create_ring(con);
+			console_iter_int_arg1(dom, console_create_ring);
 		else
 			xs_unwatch(xs, con->xspath, domid_str);
 	} else {
@@ -655,20 +764,59 @@ static bool watch_domain(struct domain *dom, bool watch)
 	return success;
 }
 
-
-static struct domain *create_domain(int domid)
+static int console_init(struct console *con, struct domain *dom, void **data)
 {
-	struct domain *dom;
 	char *s;
+	int err = -1;
 	struct timespec ts;
-	struct console *con;
+	struct console_data **con_data = (struct console_data **)data;
+	char *xsname;
 
 	if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
 		dolog(LOG_ERR, "Cannot get time of day %s:%s:L%d",
 		      __FILE__, __FUNCTION__, __LINE__);
-		return NULL;
+		return err;
+	}
+
+	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->xce_pollfd_idx = -1;
+	con->next_period = ((long long)ts.tv_sec * 1000) + (ts.tv_nsec / 1000000) + RATE_LIMIT_PERIOD;
+	con->d = dom;
+	con->ttyname = (*con_data)->ttyname;
+	con->log_suffix = (*con_data)->log_suffix;
+	xsname = (*con_data)->xsname;
+	con->xspath = xs_get_domain_path(xs, dom->domid);
+	s = realloc(con->xspath, strlen(con->xspath) +
+				strlen(xsname) + 1);
+	if (s)
+	{
+		con->xspath = s;
+		strcat(con->xspath, xsname);
+		err = 0;
 	}
 
+	(*con_data)++;
+
+	return err;
+}
+
+static void console_free(struct console *con)
+{
+	if (con->xspath)
+		free(con->xspath);
+}
+
+static struct domain *create_domain(int domid)
+{
+	struct domain *dom;
+	struct console_data *con_data = &console_data[0];
+
 	dom = calloc(1, sizeof *dom);
 	if (dom == NULL) {
 		dolog(LOG_ERR, "Out of memory %s:%s():L%d",
@@ -678,27 +826,8 @@ static struct domain *create_domain(int domid)
 
 	dom->domid = domid;
 
-	con = &dom->console;
-	con->xspath = xs_get_domain_path(xs, dom->domid);
-	s = realloc(con->xspath, strlen(con->xspath) +
-		    strlen("/console") + 1);
-	if (s == NULL)
+	if (console_iter_int_arg3(dom, console_init, (void **)&con_data))
 		goto out;
-	con->xspath = s;
-	strcat(con->xspath, "/console");
-
-	con->master_fd = -1;
-	con->master_pollfd_idx = -1;
-	con->slave_fd = -1;
-	con->log_fd = -1;
-	con->xce_pollfd_idx = -1;
-	con->d = dom;
-
-	con->next_period = ((long long)ts.tv_sec * 1000) + (ts.tv_nsec / 1000000) + RATE_LIMIT_PERIOD;
-
-	con->ring_ref = -1;
-	con->local_port = -1;
-	con->remote_port = -1;
 
 	if (!watch_domain(dom, true))
 		goto out;
@@ -710,7 +839,7 @@ static struct domain *create_domain(int domid)
 
 	return dom;
  out:
-	free(con->xspath);
+	console_iter_void_arg1(dom, console_free);
 	free(dom);
 	return NULL;
 }
@@ -740,38 +869,51 @@ static void remove_domain(struct domain *dom)
 	}
 }
 
-static void cleanup_domain(struct domain *d)
+static void console_cleanup(struct console *con)
 {
-	struct console *con = &d->console;
-
-	console_close_tty(con);
-
 	if (con->log_fd != -1) {
 		close(con->log_fd);
 		con->log_fd = -1;
 	}
 
-	free(con->buffer.data);
-	con->buffer.data = NULL;
+	if (con->buffer.data)
+	{
+		free(con->buffer.data);
+		con->buffer.data = NULL;
+	}
+
+	if (con->xspath)
+	{
+		free(con->xspath);
+		con->xspath = NULL;
+	}
+}
+
+static void cleanup_domain(struct domain *d)
+{
+	console_iter_void_arg1(d, console_close_tty);
 
-	free(con->xspath);
-	con->xspath = NULL;
+	console_iter_void_arg1(d, console_cleanup);
 
 	remove_domain(d);
 }
 
-static void shutdown_domain(struct domain *d)
+static void console_close_evtchn(struct console *con)
 {
-	struct console *con = &d->console;
-
-	d->is_dead = true;
-	watch_domain(d, false);
-	console_unmap_interface(con);
 	if (con->xce_handle != NULL)
 		xenevtchn_close(con->xce_handle);
+
 	con->xce_handle = NULL;
 }
 
+static void shutdown_domain(struct domain *d)
+{
+	d->is_dead = true;
+	watch_domain(d, false);
+	console_iter_void_arg1(d, console_unmap_interface);
+	console_iter_void_arg1(d, console_close_evtchn);
+}
+
 static unsigned enum_pass = 0;
 
 static void enum_domains(void)
@@ -885,12 +1027,32 @@ static void handle_tty_write(struct console *con)
 	}
 }
 
-static void handle_ring_read(struct domain *dom)
+static void console_evtchn_unmask(struct console *con, void *data)
+{
+	long long now = (long long)data;
+
+	if (!console_enabled(con))
+		return;
+
+	/* CS 16257:955ee4fa1345 introduces a 5ms fuzz
+	 * for select(), it is not clear poll() has
+	 * similar behavior (returning a couple of ms
+	 * sooner than requested) as well. Just leave
+	 * the fuzz here. Remove it with a separate
+	 * patch if necessary */
+	if ((now+5) > con->next_period) {
+		con->next_period = now + RATE_LIMIT_PERIOD;
+		if (con->event_count >= RATE_LIMIT_ALLOWANCE)
+				(void)xenevtchn_unmask(con->xce_handle, con->local_port);
+		con->event_count = 0;
+	}
+}
+
+static void handle_ring_read(struct console *con)
 {
 	xenevtchn_port_or_error_t port;
-	struct console *con = &dom->console;
 
-	if (dom->is_dead)
+	if (con->d->is_dead)
 		return;
 
 	if ((port = xenevtchn_pending(con->xce_handle)) == -1)
@@ -898,10 +1060,23 @@ static void handle_ring_read(struct domain *dom)
 
 	con->event_count++;
 
-	buffer_append(con);
+	buffer_append(con, port);
 
 	if (con->event_count < RATE_LIMIT_ALLOWANCE)
-		(void)xenevtchn_unmask(con->xce_handle, port);
+		(void)xenevtchn_unmask(con->xce_handle, con->local_port);
+}
+
+static void handle_console_ring(struct console *con)
+{
+	if (con->event_count < RATE_LIMIT_ALLOWANCE) {
+		if (con->xce_handle != NULL &&
+			con->xce_pollfd_idx != -1 &&
+			!(fds[con->xce_pollfd_idx].revents &
+			  ~(POLLIN|POLLOUT|POLLPRI)) &&
+			  (fds[con->xce_pollfd_idx].revents &
+			   POLLIN))
+			handle_ring_read(con);
+	}
 }
 
 static void handle_xs(void)
@@ -922,7 +1097,7 @@ static void handle_xs(void)
 		/* We may get watches firing for domains that have recently
 		   been removed, so dom may be NULL here. */
 		if (dom && dom->is_dead == false)
-			console_create_ring(&dom->console);
+			console_iter_int_arg1(dom, console_create_ring);
 	}
 
 	free(vec);
@@ -963,16 +1138,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) {
-			struct console *con = &d->console;
-
-			if (con->log_fd != -1)
-				close(con->log_fd);
-			con->log_fd = create_console_log(con);
+			console_iter_void_arg1(d, console_open_log);
 		}
 	}
 
@@ -1024,6 +1205,62 @@ static void reset_fds(void)
 		memset(fds, 0, sizeof(struct pollfd) * current_array_size);
 }
 
+static void add_console_evtchn_fd(struct console *con, void *data)
+{
+	long long next_timeout = *((long long *)data);
+
+	if (con->event_count >= RATE_LIMIT_ALLOWANCE) {
+		/* Determine if we're going to be the next time slice to expire */
+		if (!next_timeout ||
+			con->next_period < next_timeout)
+			next_timeout = con->next_period;
+	} else if (con->xce_handle != NULL) {
+			if (buffer_available(con))
+			{
+				int evtchn_fd = xenevtchn_fd(con->xce_handle);
+				con->xce_pollfd_idx = set_fds(evtchn_fd,
+											  POLLIN|POLLPRI);
+			}
+		}
+
+	*((long long *)data) = next_timeout;
+}
+
+static void add_console_tty_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 handle_console_tty(struct console *con)
+{
+	if (con->master_fd != -1 && con->master_pollfd_idx != -1) {
+		if (fds[con->master_pollfd_idx].revents &
+			~(POLLIN|POLLOUT|POLLPRI))
+			console_handle_broken_tty(con, 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;
+	con->xce_pollfd_idx = -1;
+}
+
 void handle_io(void)
 {
 	int ret;
@@ -1081,55 +1318,11 @@ void handle_io(void)
 		/* Re-calculate any event counter allowances & unblock
 		   domains with new allowance */
 		for (d = dom_head; d; d = d->next) {
-			struct console *con = &d->console;
-
-			/* CS 16257:955ee4fa1345 introduces a 5ms fuzz
-			 * for select(), it is not clear poll() has
-			 * similar behavior (returning a couple of ms
-			 * sooner than requested) as well. Just leave
-			 * the fuzz here. Remove it with a separate
-			 * patch if necessary */
-			if ((now+5) > con->next_period) {
-				con->next_period = now + RATE_LIMIT_PERIOD;
-				if (con->event_count >= RATE_LIMIT_ALLOWANCE) {
-					(void)xenevtchn_unmask(con->xce_handle, con->local_port);
-				}
-				con->event_count = 0;
-			}
-		}
 
-		for (d = dom_head; d; d = d->next) {
-			struct console *con = &d->console;
-
-			if (con->event_count >= RATE_LIMIT_ALLOWANCE) {
-				/* Determine if we're going to be the next time slice to expire */
-				if (!next_timeout ||
-				    con->next_period < next_timeout)
-					next_timeout = con->next_period;
-			} else if (con->xce_handle != NULL) {
-				if (discard_overflowed_data ||
-				    !con->buffer.max_capacity ||
-				    con->buffer.size < con->buffer.max_capacity) {
-					int evtchn_fd = xenevtchn_fd(con->xce_handle);
-					con->xce_pollfd_idx = set_fds(evtchn_fd,
-								    POLLIN|POLLPRI);
-				}
-			}
-
-			if (con->master_fd != -1) {
-				short events = 0;
-				if (!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);
-			}
-		}
+			console_iter_void_arg2(d, console_evtchn_unmask, (void *)now);
+			console_iter_void_arg2(d, add_console_evtchn_fd, (void *)&next_timeout);
+			console_iter_void_arg1(d, add_console_tty_fd);
+        }
 
 		/* If any domain has been rate limited, we need to work
 		   out what timeout to supply to poll */
@@ -1189,35 +1382,11 @@ void handle_io(void)
 		}
 
 		for (d = dom_head; d; d = n) {
-			struct console *con = &d->console;
 
 			n = d->next;
-			if (con->event_count < RATE_LIMIT_ALLOWANCE) {
-				if (con->xce_handle != NULL &&
-				    con->xce_pollfd_idx != -1 &&
-				    !(fds[con->xce_pollfd_idx].revents &
-				      ~(POLLIN|POLLOUT|POLLPRI)) &&
-				      (fds[con->xce_pollfd_idx].revents &
-				       POLLIN))
-				    handle_ring_read(d);
-			}
-
-			if (con->master_fd != -1 && con->master_pollfd_idx != -1) {
-				if (fds[con->master_pollfd_idx].revents &
-				    ~(POLLIN|POLLOUT|POLLPRI))
-					console_handle_broken_tty(con,
-						   domain_is_valid(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->xce_pollfd_idx = con->master_pollfd_idx = -1;
+			console_iter_void_arg1(d, handle_console_ring);
+			console_iter_void_arg1(d, handle_console_tty);
 
 			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] 67+ messages in thread

* [PATCH 14/17 v5] xen/arm: vpl011: Add support for vuart console in xenconsole
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
                   ` (12 preceding siblings ...)
  2017-06-22  7:38 ` [PATCH 13/17 v5] xen/arm: vpl011: Modify xenconsole to support multiple consoles Bhupinder Thakur
@ 2017-06-22  7:38 ` Bhupinder Thakur
  2017-06-23  0:02   ` Stefano Stabellini
  2017-06-28 17:17   ` Wei Liu
  2017-06-22  7:38 ` [PATCH 15/17 v5] xen/arm: vpl011: Add a new vuart console type to xenconsole client Bhupinder Thakur
                   ` (3 subsequent siblings)
  17 siblings, 2 replies; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

This patch finally adds the support for vuart console.

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
---
CC: Ian Jackson <ian.jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>

Changes since v4:
- Renamed VUART_CFLAGS- to CFLAGS_vuart- in the Makefile as per the convention.

 config/arm32.mk           |  1 +
 config/arm64.mk           |  1 +
 tools/console/Makefile    |  3 ++-
 tools/console/daemon/io.c | 31 ++++++++++++++++++++++++++++++-
 4 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/config/arm32.mk b/config/arm32.mk
index f95228e..b9f23fe 100644
--- a/config/arm32.mk
+++ b/config/arm32.mk
@@ -1,5 +1,6 @@
 CONFIG_ARM := y
 CONFIG_ARM_32 := y
+CONFIG_VUART_CONSOLE := y
 CONFIG_ARM_$(XEN_OS) := y
 
 CONFIG_XEN_INSTALL_SUFFIX :=
diff --git a/config/arm64.mk b/config/arm64.mk
index aa45772..861d0a4 100644
--- a/config/arm64.mk
+++ b/config/arm64.mk
@@ -1,5 +1,6 @@
 CONFIG_ARM := y
 CONFIG_ARM_64 := y
+CONFIG_VUART_CONSOLE := y
 CONFIG_ARM_$(XEN_OS) := y
 
 CONFIG_XEN_INSTALL_SUFFIX :=
diff --git a/tools/console/Makefile b/tools/console/Makefile
index c8b0300..1cddb6e 100644
--- a/tools/console/Makefile
+++ b/tools/console/Makefile
@@ -11,6 +11,7 @@ LDLIBS += $(SOCKET_LIBS)
 
 LDLIBS_xenconsoled += $(UTIL_LIBS)
 LDLIBS_xenconsoled += -lrt
+CFLAGS_vuart-$(CONFIG_VUART_CONSOLE) = -DCONFIG_VUART_CONSOLE
 
 BIN      = xenconsoled xenconsole
 
@@ -28,7 +29,7 @@ clean:
 distclean: clean
 
 daemon/main.o: daemon/_paths.h
-daemon/io.o: CFLAGS += $(CFLAGS_libxenevtchn) $(CFLAGS_libxengnttab)
+daemon/io.o: CFLAGS += $(CFLAGS_libxenevtchn) $(CFLAGS_libxengnttab) $(CFLAGS_vuart-y)
 xenconsoled: $(patsubst %.c,%.o,$(wildcard daemon/*.c))
 	$(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_xenconsoled) $(APPEND_LDFLAGS)
 
diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index baf0e2e..6b0114e 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -107,12 +107,16 @@ struct console {
 	xenevtchn_port_or_error_t remote_port;
 	struct xencons_interface *interface;
 	struct domain *d;
+	bool optional;
+	bool prefer_gnttab;
 };
 
 struct console_data {
 	char *xsname;
 	char *ttyname;
 	char *log_suffix;
+	bool optional;
+	bool prefer_gnttab;
 };
 
 static struct console_data console_data[] = {
@@ -121,7 +125,18 @@ static struct console_data console_data[] = {
 		.xsname = "/console",
 		.ttyname = "tty",
 		.log_suffix = "",
+		.optional = false,
+		.prefer_gnttab = true,
 	},
+#if defined(CONFIG_VUART_CONSOLE)
+	{
+		.xsname = "/vuart/0",
+		.ttyname = "tty",
+		.log_suffix = "-vuart0",
+		.optional = true,
+		.prefer_gnttab = false,
+	},
+#endif
 };
 
 #define MAX_CONSOLE (sizeof(console_data)/sizeof(struct console_data))
@@ -655,8 +670,18 @@ static int console_create_ring(struct console *con)
 			"ring-ref", "%u", &ring_ref,
 			"port", "%i", &remote_port,
 			NULL);
+
 	if (err)
+	{
+		/*
+		 * This is a normal condition for optional consoles: they might not be
+		 * present on xenstore at all. In that case, just return without error.
+		*/
+		if (con->optional)
+			err = 0;
+
 		goto out;
+	}
 
 	snprintf(path, sizeof(path), "%s/type", con->xspath);
 	type = xs_read(xs, XBT_NULL, path, NULL);
@@ -670,7 +695,9 @@ static int console_create_ring(struct console *con)
 	if (ring_ref != con->ring_ref && con->ring_ref != -1)
 		console_unmap_interface(con);
 
-	if (!con->interface && xgt_handle) {
+	if (!con->interface && 
+		xgt_handle &&
+		con->prefer_gnttab) {
 		/* Prefer using grant table */
 		con->interface = xengnttab_map_grant_ref(xgt_handle,
 			dom->domid, GNTTAB_RESERVED_CONSOLE,
@@ -790,6 +817,8 @@ static int console_init(struct console *con, struct domain *dom, void **data)
 	con->d = dom;
 	con->ttyname = (*con_data)->ttyname;
 	con->log_suffix = (*con_data)->log_suffix;
+	con->optional = (*con_data)->optional;
+	con->prefer_gnttab = (*con_data)->prefer_gnttab;
 	xsname = (*con_data)->xsname;
 	con->xspath = xs_get_domain_path(xs, dom->domid);
 	s = realloc(con->xspath, strlen(con->xspath) +
-- 
2.7.4


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

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

* [PATCH 15/17 v5] xen/arm: vpl011: Add a new vuart console type to xenconsole client
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
                   ` (13 preceding siblings ...)
  2017-06-22  7:38 ` [PATCH 14/17 v5] xen/arm: vpl011: Add support for vuart console in xenconsole Bhupinder Thakur
@ 2017-06-22  7:38 ` Bhupinder Thakur
  2017-06-22 23:09   ` Stefano Stabellini
  2017-06-28 17:17   ` Wei Liu
  2017-06-22  7:38 ` [PATCH 16/17 v5] xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree Bhupinder Thakur
                   ` (2 subsequent siblings)
  17 siblings, 2 replies; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

Add a new console type VUART to connect to guest's emualated vuart
console.

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
---
CC: Ian Jackson <ian.jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>

Changes since v4:
- Removed the vuart compile time flag so that vuart code is compiled always.

Changes since v3:
- The vuart console support is under CONFIG_VUART_CONSOLE option.
- Since there is a change from last review, I have not included
  reviewed-by tag from Stefano and acked-by tag from Wei.

 tools/console/client/main.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/tools/console/client/main.c b/tools/console/client/main.c
index 977779f..3dbb06f 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;
@@ -343,6 +344,7 @@ int main(int argc, char **argv)
 	char *end;
 	console_type type = CONSOLE_INVAL;
 	bool interactive = 0;
+	char *console_names = "serial, pv, vuart";
 
 	if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO))
 		interactive = 1;
@@ -361,9 +363,12 @@ 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");
+				fprintf(stderr, "Console types supported are: %s\n",
+						console_names);
 				exit(EINVAL);
 			}
 			break;
@@ -436,6 +441,10 @@ 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("/vuart/0/tty") + 1,
+				 "%s/vuart/0/tty", 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] 67+ messages in thread

* [PATCH 16/17 v5] xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
                   ` (14 preceding siblings ...)
  2017-06-22  7:38 ` [PATCH 15/17 v5] xen/arm: vpl011: Add a new vuart console type to xenconsole client Bhupinder Thakur
@ 2017-06-22  7:38 ` Bhupinder Thakur
  2017-06-28 17:17   ` Wei Liu
  2017-06-22  7:38 ` [PATCH 17/17 v5] xen/arm: vpl011: Update documentation for vuart console support Bhupinder Thakur
  2017-06-23 10:42 ` [PATCH 00/17 v5] SBSA UART emulation support in Xen Julien Grall
  17 siblings, 1 reply; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

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

Currently the baud rate of 115200 has been selected as a default value,
which is one of the valid baud rate setttings. Higher baud rate was
selected since an emulated pl011 can support any valid baud rate without
any limitation of the hardware.

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
---
CC: Ian Jackson <ian.jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>

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

diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
index 9d6448e..cf3de01 100644
--- a/tools/libxl/libxl_arm.c
+++ b/tools/libxl/libxl_arm.c
@@ -44,10 +44,22 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
     uint32_t nr_spis = 0;
     unsigned int i;
 
+    /*
+     * If pl011 vuart is enabled then increment the nr_spis to allow allocation
+     * of SPI VIRQ for pl011.
+     */
+    if (d_config->b_info.arch_arm.vuart)
+        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 (d_config->b_info.arch_arm.vuart && (irq == GUEST_VPL011_SPI)) {
+            LOG(ERROR, "Physical IRQ %u conflicting with pl011 SPI\n", irq);
+            return ERROR_FAIL;
+        }
+
         if (irq < 32)
             continue;
 
@@ -130,9 +142,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 +603,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 +934,9 @@ next_resize:
         FDT( make_timer_node(gc, fdt, ainfo, xc_config->clock_frequency) );
         FDT( make_hypervisor_node(gc, fdt, vers) );
 
+        if (info->arch_arm.vuart)
+            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] 67+ messages in thread

* [PATCH 17/17 v5] xen/arm: vpl011: Update documentation for vuart console support
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
                   ` (15 preceding siblings ...)
  2017-06-22  7:38 ` [PATCH 16/17 v5] xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree Bhupinder Thakur
@ 2017-06-22  7:38 ` Bhupinder Thakur
  2017-06-23 10:42 ` [PATCH 00/17 v5] SBSA UART emulation support in Xen Julien Grall
  17 siblings, 0 replies; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-22  7:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, Julien Grall, Stefano Stabellini, Ian Jackson

1. Update documentation for a new vuart option added.
2. Update documentation about SPI irq reserved for vuart.

Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
Acked-by: Wei Liu <wei.liu2@citrix.com>
---
CC: Ian Jackson <ian.jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>

Changes since v4:
- Minor change to rename "pl011" to "sbsa_uart". Since it is a minor change I have
  retained the reviewed-by and acked-by tags.

 docs/man/xl.cfg.pod.5.in |  9 +++++++++
 docs/misc/console.txt    | 44 +++++++++++++++++++++++++++++++++-----------
 2 files changed, 42 insertions(+), 11 deletions(-)

diff --git a/docs/man/xl.cfg.pod.5.in b/docs/man/xl.cfg.pod.5.in
index 38084c7..0737ed1 100644
--- a/docs/man/xl.cfg.pod.5.in
+++ b/docs/man/xl.cfg.pod.5.in
@@ -1105,6 +1105,15 @@ Allow a guest to access specific physical IRQs.
 It is recommended to only use this option for trusted VMs under
 administrator's control.
 
+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
+"sbsa_uart" model is supported.
+
+vuart = "sbsa_uart"
+
+Currently vuart console is available 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..d081acc 100644
--- a/docs/misc/console.txt
+++ b/docs/misc/console.txt
@@ -19,7 +19,20 @@ The first PV console path in xenstore remains:
 
 /local/domain/$DOMID/console
 
-the other PV consoles follow the conventional xenstore device path and
+The virtual UART console path in xenstore is defined as:
+
+/local/domain/$DOMID/vuart/0
+
+The vuart console provides access to a virtual SBSA UART on ARM64 systems.
+To enable vuart the following line has to be added to the guest configuration
+file:
+
+vuart = "sbsa_uart"
+
+In Linux you can select the virtual SBSA 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.
@@ -61,6 +74,14 @@ output = pty
 The backend will write the pty device name to the "tty" node in the
 console frontend.
 
+For the PV console the tty node is added at
+
+/local/domain/$DOMID/console/tty
+
+For the virtual UART console the tty node is added at
+
+/local/domain/$DOMID/vuart/0/tty
+
 If the toolstack wants a listening Unix domain socket to be created at path
 <path>, a connection accepted and data proxied to the console, it will write:
 
@@ -79,8 +100,8 @@ For example:
 ioemu
 
 The supported values are only xenconsoled or ioemu; xenconsoled has
-several limitations: it can only be used for the first PV console and it
-can only connect to a pty.
+several limitations: it can only be used for the first PV or virtual UART
+console and it can only connect to a pty.
 
 Emulated serials are provided by qemu-dm only to hvm guests; the number
 of emulated serials depends on how many "-serial" command line options
@@ -90,14 +111,15 @@ xenstore in the following path:
 
 /local/domain/$DOMID/serial/$SERIAL_NUM/tty
 
-xenconsole is the tool to connect to a PV console or an emulated serial
-that has a pty as output. Xenconsole takes a domid as parameter plus an
-optional console type (pv for PV consoles or serial for emulated
-serials) and console number. Depending on the type and console
-number, xenconsole will look for the tty node in different xenstore
-paths, as described above.  If the user doesn't specify the console type
-xenconsole will try to guess: if the guest is a pv guest it defaults to
-PV console, if the guest is an hvm guest it defaults to emulated serial.
+xenconsole is the tool to connect to a PV or virtual UART console or an
+emulated serial that has a pty as output. Xenconsole takes a domid as
+parameter plus an optional console type (pv for PV consoles, vuart for
+virtual UART or serial for emulated serials) and console number.
+Depending on the type and console number, xenconsole will look for the tty
+node in different xenstore paths, as described above.  If the user doesn't
+specify the console type xenconsole will try to guess: if the guest is a pv
+guest it defaults to PV console, if the guest is an hvm guest it defaults to
+emulated serial.
 
 By default xl creates a pv console for hvm guests, plus an emulated
 serial if the user specified 'serial = "pty"' in the VM config file.
-- 
2.7.4


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

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

* Re: [PATCH 03/17 v5] xen/arm: vpl011: Define common ring buffer helper functions in console.h
  2017-06-22  7:38 ` [PATCH 03/17 v5] xen/arm: vpl011: Define common ring buffer helper functions in console.h Bhupinder Thakur
@ 2017-06-22 22:36   ` Stefano Stabellini
  2017-06-28 17:16   ` Wei Liu
  1 sibling, 0 replies; 67+ messages in thread
From: Stefano Stabellini @ 2017-06-22 22:36 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Ian Jackson, Julien Grall, xen-devel

On Thu, 22 Jun 2017, Bhupinder Thakur wrote:
> DEFINE_XEN_FLEX_RING(xencons) defines common helper functions such as
> xencons_queued() to tell the current size of the ring buffer,
> xencons_mask() to mask off the index, which are useful helper functions.
> pl011 emulation code will use these helper functions.
> 
> io/consol.h includes io/ring.h which defines DEFINE_XEN_FLEX_RING.

io/console.h


> In console/daemon/io.c, string.h had to be included before io/console.h
> because ring.h uses string functions.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>

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


> ---
> CC: Ian Jackson <ian.jackson@eu.citrix.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> CC: Stefano Stabellini <sstabellini@kernel.org>
> CC: Julien Grall <julien.grall@arm.com>
> 
> Changes since v4:
> - Split this change in a separate patch.
> 
>  tools/console/daemon/io.c       | 2 +-
>  xen/include/public/io/console.h | 4 ++++
>  2 files changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
> index 7e474bb..e8033d2 100644
> --- a/tools/console/daemon/io.c
> +++ b/tools/console/daemon/io.c
> @@ -21,6 +21,7 @@
>  
>  #include "utils.h"
>  #include "io.h"
> +#include <string.h>
>  #include <xenevtchn.h>
>  #include <xengnttab.h>
>  #include <xenstore.h>
> @@ -29,7 +30,6 @@
>  
>  #include <stdlib.h>
>  #include <errno.h>
> -#include <string.h>
>  #include <poll.h>
>  #include <fcntl.h>
>  #include <unistd.h>
> diff --git a/xen/include/public/io/console.h b/xen/include/public/io/console.h
> index e2cd97f..5e45e1c 100644
> --- a/xen/include/public/io/console.h
> +++ b/xen/include/public/io/console.h
> @@ -27,6 +27,8 @@
>  #ifndef __XEN_PUBLIC_IO_CONSOLE_H__
>  #define __XEN_PUBLIC_IO_CONSOLE_H__
>  
> +#include "ring.h"
> +
>  typedef uint32_t XENCONS_RING_IDX;
>  
>  #define MASK_XENCONS_IDX(idx, ring) ((idx) & (sizeof(ring)-1))
> @@ -38,6 +40,8 @@ struct xencons_interface {
>      XENCONS_RING_IDX out_cons, out_prod;
>  };
>  
> +DEFINE_XEN_FLEX_RING(xencons);
> +
>  #endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */
>  
>  /*

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

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

* Re: [PATCH 04/17 v5] xen/arm: vpl011: Add SBSA UART emulation in Xen
  2017-06-22  7:38 ` [PATCH 04/17 v5] xen/arm: vpl011: Add SBSA UART emulation in Xen Bhupinder Thakur
@ 2017-06-22 22:53   ` Stefano Stabellini
  2017-06-23 12:33     ` Julien Grall
  2017-06-23 13:10   ` Julien Grall
  1 sibling, 1 reply; 67+ messages in thread
From: Stefano Stabellini @ 2017-06-22 22:53 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Andre Przywara

On Thu, 22 Jun 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
> 
> This patch implements the SBSA Generic UART which is a subset of ARM
> PL011 UART.
> 
> The SBSA Generic 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>
> ---
> CC: Stefano Stabellini <sstabellini@kernel.org>
> CC: Julien Grall <julien.grall@arm.com>
> CC: Andre Przywara <andre.przywara@arm.com>
> 
> Changes since v4:
> - Renamed vpl011_update() to vpl011_update_interrupt_status() and added logic to avoid
>   raising spurious interrupts.
> - Used barrier instructions correctly while reading/writing data to the ring buffer.
> - Proper lock taken before reading ring buffer indices.
> 
> Changes since v3:
> - Moved the call to DEFINE_XEN_FLEX_RING from vpl011.h to public/console.h. This macro defines
>   standard functions to operate on the ring buffer.
> - Lock taken while updating the interrupt mask and clear registers in mmio_write.
> - Use gfn_t instead of xen_pfn_t.
> - vgic_free_virq called if there is any error in vpl011 initialization.
> - mmio handlers freed if there is any error in vpl011 initialization.
> - Removed vpl011->initialized flag usage as the same check could be done 
>   using vpl011->ring-ref.
> - Used return instead of break in the switch handling of emulation of different pl011 registers.
> - Renamed vpl011_update_spi() to vpl011_update().
> 
> Changes since v2:
> - Use generic vreg_reg* for read/write of registers emulating pl011.
> - Use generic ring buffer functions defined using DEFINE_XEN_FLEX_RING.
> - Renamed the SPI injection function to vpl011_update_spi() to reflect level 
>   triggered nature of pl011 interrupts.
> - The pl011 register access address should always be the base address of the
>   corresponding register as per section B of the SBSA document. For this reason,
>   the register range address access is not allowed.
> 
> Changes since v1:
> - Removed the optimiztion related to sendiing events to xenconsole 
> - Use local variables as ring buffer indices while using the ring buffer
> 
>  xen/arch/arm/Kconfig             |   7 +
>  xen/arch/arm/Makefile            |   1 +
>  xen/arch/arm/vpl011.c            | 449 +++++++++++++++++++++++++++++++++++++++
>  xen/include/asm-arm/domain.h     |   6 +
>  xen/include/asm-arm/pl011-uart.h |   2 +
>  xen/include/asm-arm/vpl011.h     |  73 +++++++
>  xen/include/public/arch-arm.h    |   6 +
>  7 files changed, 544 insertions(+)
>  create mode 100644 xen/arch/arm/vpl011.c
>  create mode 100644 xen/include/asm-arm/vpl011.h
> 
> diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
> index d46b98c..f58019d 100644
> --- a/xen/arch/arm/Kconfig
> +++ b/xen/arch/arm/Kconfig
> @@ -50,6 +50,13 @@ config HAS_ITS
>          prompt "GICv3 ITS MSI controller support" if EXPERT = "y"
>          depends on HAS_GICV3
>  
> +config SBSA_VUART_CONSOLE
> +	bool "Emulated SBSA UART console support"
> +	default y
> +	---help---
> +	  Allows a guest to use SBSA Generic UART as a console. The
> +	  SBSA Generic UART implements a subset of ARM PL011 UART.
> +
>  endmenu
>  
>  menu "ARM errata workaround via the alternative framework"
> diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
> index 49e1fb2..d9c6ebf 100644
> --- a/xen/arch/arm/Makefile
> +++ b/xen/arch/arm/Makefile
> @@ -50,6 +50,7 @@ obj-$(CONFIG_HAS_GICV3) += vgic-v3.o
>  obj-$(CONFIG_HAS_ITS) += vgic-v3-its.o
>  obj-y += vm_event.o
>  obj-y += vtimer.o
> +obj-$(CONFIG_SBSA_VUART_CONSOLE) += vpl011.o
>  obj-y += vpsci.o
>  obj-y += vuart.o
>  
> diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> new file mode 100644
> index 0000000..db8651c
> --- /dev/null
> +++ b/xen/arch/arm/vpl011.c
> @@ -0,0 +1,449 @@
> +/*
> + * arch/arm/vpl011.c
> + *
> + * Virtual PL011 UART
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <xen/errno.h>
> +#include <xen/event.h>
> +#include <xen/guest_access.h>
> +#include <xen/init.h>
> +#include <xen/lib.h>
> +#include <xen/mm.h>
> +#include <xen/sched.h>
> +#include <public/domctl.h>
> +#include <public/io/console.h>
> +#include <asm-arm/pl011-uart.h>
> +#include <asm-arm/vgic-emul.h>
> +#include <asm/vpl011.h>
> +
> +/*
> + * Since pl011 registers are 32-bit registers, all registers
> + * are handled similarly allowing 8-bit, 16-bit and 32-bit
> + * accesses except 64-bit access.
> + */
> +static bool vpl011_reg32_check_access(struct hsr_dabt dabt)
> +{
> +    return (dabt.size != DABT_DOUBLE_WORD);
> +}
> +
> +static void vpl011_update_interrupt_status(struct domain *d)
> +{
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +    uint32_t interrupt_status = vpl011->uartris & vpl011->uartimsc;
> +
> +    /*
> +     * TODO: PL011 interrupts are level triggered which means
> +     * that interrupt needs to be set/clear instead of being
> +     * injected. However, currently vGIC does not handle level
> +     * triggered interrupts properly. This function needs to be
> +     * revisited once vGIC starts handling level triggered
> +     * interrupts.
> +     */
> +
> +    /*
> +     * Raise an interrupt only if any additional interrupt
> +     * status bit has been set since the last time.
> +     */
> +    if ( interrupt_status & ~vpl011->shadow_uartris )
> +        vgic_vcpu_inject_spi(d, GUEST_VPL011_SPI);
> +
> +    vpl011->shadow_uartris = interrupt_status;
> +}
> +
> +static uint8_t vpl011_read_data(struct domain *d)
> +{
> +    unsigned long flags;
> +    uint8_t data = 0;
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +    struct xencons_interface *intf = vpl011->ring_buf;
> +    XENCONS_RING_IDX in_cons, in_prod;
> +
> +    VPL011_LOCK(d, flags);
> +
> +    in_cons = intf->in_cons;
> +    in_prod = intf->in_prod;
> +
> +    smp_rmb();
> +
> +    /*
> +     * It is expected that there will be data in the ring buffer when this
> +     * function is called since the guest is expected to read the data register
> +     * only if the TXFE flag is not set.
> +     * If the guest still does read when TXFE bit is set then 0 will be returned.
> +     */
> +    if ( xencons_queued(in_prod, in_cons, sizeof(intf->in)) > 0 )
> +    {
> +        data = intf->in[xencons_mask(in_cons, sizeof(intf->in))];
> +        in_cons += 1;
> +        smp_mb();
> +        intf->in_cons = in_cons;
> +    }
> +    else
> +        gprintk(XENLOG_ERR, "vpl011: Unexpected IN ring buffer empty\n");
> +
> +    if ( xencons_queued(in_prod, in_cons, sizeof(intf->in)) == 0 )
> +    {
> +        vpl011->uartfr |= RXFE;
> +        vpl011->uartris &= ~RXI;
> +    }
> +
> +    vpl011->uartfr &= ~RXFF;
> +
> +    vpl011_update_interrupt_status(d);
> +
> +    VPL011_UNLOCK(d, flags);
> +
> +    /*
> +     * Send an event to console backend to indicate that data has been
> +     * read from the IN ring buffer.
> +     */
> +    notify_via_xen_event_channel(d, vpl011->evtchn);
> +
> +    return data;
> +}
> +
> +static void vpl011_write_data(struct domain *d, uint8_t data)
> +{
> +    unsigned long flags;
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +    struct xencons_interface *intf = vpl011->ring_buf;
> +    XENCONS_RING_IDX out_cons, out_prod;
> +
> +    VPL011_LOCK(d, flags);
> +
> +    out_cons = intf->out_cons;
> +    out_prod = intf->out_prod;
> +
> +    smp_rmb();

This should be
       smp_mb();

Aside from this, the patch looks good to me.


> +    /*
> +     * It is expected that the ring is not full when this function is called
> +     * as the guest is expected to write to the data register only when the
> +     * TXFF flag is not set.
> +     * In case the guest does write even when the TXFF flag is set then the
> +     * data will be silently dropped.
> +     */
> +    if ( xencons_queued(out_prod, out_cons, sizeof(intf->out)) !=
> +         sizeof (intf->out) )
> +    {
> +        intf->out[xencons_mask(out_prod, sizeof(intf->out))] = data;
> +        out_prod += 1;
> +        smp_wmb();
> +        intf->out_prod = out_prod;
> +    }
> +    else
> +        gprintk(XENLOG_ERR, "vpl011: Unexpected OUT ring buffer full\n");
> +
> +    if ( xencons_queued(out_prod, out_cons, sizeof(intf->out)) ==
> +         sizeof (intf->out) )
> +    {
> +        vpl011->uartfr |= TXFF;
> +        vpl011->uartris &= ~TXI;
> +    }
> +
> +    vpl011->uartfr |= BUSY;
> +
> +    vpl011->uartfr &= ~TXFE;
> +
> +    vpl011_update_interrupt_status(d);
> +
> +    VPL011_UNLOCK(d, flags);
> +
> +    /*
> +     * Send an event to console backend to indicate that there is
> +     * data in the OUT ring buffer.
> +     */
> +    notify_via_xen_event_channel(d, vpl011->evtchn);
> +}
> +
> +static int vpl011_mmio_read(struct vcpu *v,
> +                            mmio_info_t *info,
> +                            register_t *r,
> +                            void *priv)
> +{
> +    struct hsr_dabt dabt = info->dabt;
> +    uint32_t vpl011_reg = (uint32_t)(info->gpa - GUEST_PL011_BASE);
> +    struct vpl011 *vpl011 = &v->domain->arch.vpl011;
> +    struct domain *d = v->domain;
> +    unsigned long flags;
> +
> +    switch ( vpl011_reg )
> +    {
> +    case DR:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        *r = vreg_reg32_extract(vpl011_read_data(d), info);
> +        return 1;
> +
> +    case RSR:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        /* It always returns 0 as there are no physical errors. */
> +        *r = 0;
> +        return 1;
> +
> +    case FR:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        VPL011_LOCK(d, flags);
> +        *r = vreg_reg32_extract(vpl011->uartfr, info);
> +        VPL011_UNLOCK(d, flags);
> +        return 1;
> +
> +    case RIS:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        VPL011_LOCK(d, flags);
> +        *r = vreg_reg32_extract(vpl011->uartris, info);
> +        VPL011_UNLOCK(d, flags);
> +        return 1;
> +
> +    case MIS:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        VPL011_LOCK(d, flags);
> +        *r = vreg_reg32_extract(vpl011->uartris & vpl011->uartimsc,
> +                                info);
> +        VPL011_UNLOCK(d, flags);
> +        return 1;
> +
> +    case IMSC:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        VPL011_LOCK(d, flags);
> +        *r = vreg_reg32_extract(vpl011->uartimsc, info);
> +        VPL011_UNLOCK(d, flags);
> +        return 1;
> +
> +    case ICR:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        /* Only write is valid. */
> +        return 0;
> +
> +    default:
> +        gprintk(XENLOG_ERR, "vpl011: unhandled read r%d offset %#08x\n",
> +                dabt.reg, vpl011_reg);
> +        return 0;
> +    }
> +
> +    return 1;
> +
> +bad_width:
> +    gprintk(XENLOG_ERR, "vpl011: bad read width %d r%d offset %#08x\n",
> +            dabt.size, dabt.reg, vpl011_reg);
> +    domain_crash_synchronous();
> +    return 0;
> +
> +}
> +
> +static int vpl011_mmio_write(struct vcpu *v,
> +                             mmio_info_t *info,
> +                             register_t r,
> +                             void *priv)
> +{
> +    struct hsr_dabt dabt = info->dabt;
> +    uint32_t vpl011_reg = (uint32_t)(info->gpa - GUEST_PL011_BASE);
> +    struct vpl011 *vpl011 = &v->domain->arch.vpl011;
> +    struct domain *d = v->domain;
> +    unsigned long flags;
> +
> +    switch ( vpl011_reg )
> +    {
> +    case DR:
> +    {
> +        uint32_t data = 0;
> +
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        vreg_reg32_update(&data, r, info);
> +        vpl011_write_data(v->domain, data);
> +        return 1;
> +    }
> +    case RSR: /* Nothing to clear. */
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        return 1;
> +
> +    case FR:
> +    case RIS:
> +    case MIS:
> +        goto write_ignore;
> +
> +    case IMSC:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        VPL011_LOCK(d, flags);
> +        vreg_reg32_update(&vpl011->uartimsc, r, info);
> +        vpl011_update_interrupt_status(v->domain);
> +        VPL011_UNLOCK(d, flags);
> +        return 1;
> +
> +    case ICR:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        VPL011_LOCK(d, flags);
> +        vreg_reg32_clearbits(&vpl011->uartris, r, info);
> +        vpl011_update_interrupt_status(d);
> +        VPL011_UNLOCK(d, flags);
> +        return 1;
> +
> +    default:
> +        gprintk(XENLOG_ERR, "vpl011: unhandled write r%d offset %#08x\n",
> +                dabt.reg, vpl011_reg);
> +        return 0;
> +    }
> +
> +write_ignore:
> +    return 1;
> +
> +bad_width:
> +    gprintk(XENLOG_ERR, "vpl011: bad write width %d r%d offset %#08x\n",
> +            dabt.size, dabt.reg, vpl011_reg);
> +    domain_crash_synchronous();
> +    return 0;
> +
> +}
> +
> +static const struct mmio_handler_ops vpl011_mmio_handler = {
> +    .read = vpl011_mmio_read,
> +    .write = vpl011_mmio_write,
> +};
> +
> +static void vpl011_data_avail(struct domain *d)
> +{
> +    unsigned long flags;
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +    struct xencons_interface *intf = vpl011->ring_buf;
> +    XENCONS_RING_IDX in_cons, in_prod, out_cons, out_prod;
> +    XENCONS_RING_IDX in_ring_qsize, out_ring_qsize;
> +
> +    VPL011_LOCK(d, flags);
> +
> +    in_cons = intf->in_cons;
> +    in_prod = intf->in_prod;
> +    out_cons = intf->out_cons;
> +    out_prod = intf->out_prod;
> +
> +    smp_rmb();
> +
> +    in_ring_qsize = xencons_queued(in_prod,
> +                                   in_cons,
> +                                   sizeof(intf->in));
> +
> +    out_ring_qsize = xencons_queued(out_prod,
> +                                    out_cons,
> +                                    sizeof(intf->out));
> +
> +    /* Update the uart rx state if the buffer is not empty. */
> +    if ( in_ring_qsize != 0 )
> +    {
> +        vpl011->uartfr &= ~RXFE;
> +        if ( in_ring_qsize == sizeof(intf->in) )
> +            vpl011->uartfr |= RXFF;
> +        vpl011->uartris |= RXI;
> +    }
> +
> +    /* Update the uart tx state if the buffer is not full. */
> +    if ( out_ring_qsize != sizeof(intf->out) )
> +    {
> +        vpl011->uartfr &= ~TXFF;
> +        vpl011->uartris |= TXI;
> +        if ( out_ring_qsize == 0 )
> +        {
> +            vpl011->uartfr &= ~BUSY;
> +            vpl011->uartfr |= TXFE;
> +        }
> +    }
> +
> +    vpl011_update_interrupt_status(d);
> +
> +    VPL011_UNLOCK(d, flags);
> +}
> +
> +
> +static void vpl011_notification(struct vcpu *v, unsigned int port)
> +{
> +    vpl011_data_avail(v->domain);
> +}
> +
> +int domain_vpl011_init(struct domain *d, struct vpl011_init_info *info)
> +{
> +    int rc;
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +
> +    if ( vpl011->ring_buf )
> +        return -EINVAL;
> +
> +    /* Map the guest PFN to Xen address space. */
> +    rc =  prepare_ring_for_helper(d,
> +                                  gfn_x(info->gfn),
> +                                  &vpl011->ring_page,
> +                                  &vpl011->ring_buf);
> +    if ( rc < 0 )
> +        goto out;
> +
> +    rc = vgic_reserve_virq(d, GUEST_VPL011_SPI);
> +    if ( !rc )
> +    {
> +        rc = -EINVAL;
> +        goto out1;
> +    }
> +
> +    rc = alloc_unbound_xen_event_channel(d, 0, info->console_domid,
> +                                         vpl011_notification);
> +    if ( rc < 0 )
> +        goto out2;
> +
> +    vpl011->evtchn = info->evtchn = rc;
> +
> +    spin_lock_init(&vpl011->lock);
> +
> +    register_mmio_handler(d, &vpl011_mmio_handler,
> +                          GUEST_PL011_BASE, GUEST_PL011_SIZE, NULL);
> +
> +    return 0;
> +
> +out2:
> +    vgic_free_virq(d, GUEST_VPL011_SPI);
> +
> +out1:
> +    destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
> +
> +out:
> +    return rc;
> +}
> +
> +void domain_vpl011_deinit(struct domain *d)
> +{
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +
> +    if ( !vpl011->ring_buf )
> +        return;
> +
> +    free_xen_event_channel(d, vpl011->evtchn);
> +    destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
> +    xfree(d->arch.vmmio.handlers);
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
> index 8dfc1d1..1a1145d 100644
> --- a/xen/include/asm-arm/domain.h
> +++ b/xen/include/asm-arm/domain.h
> @@ -11,6 +11,7 @@
>  #include <public/hvm/params.h>
>  #include <xen/serial.h>
>  #include <xen/rbtree.h>
> +#include <asm-arm/vpl011.h>
>  
>  struct hvm_domain
>  {
> @@ -145,6 +146,11 @@ struct arch_domain
>      struct {
>          uint8_t privileged_call_enabled : 1;
>      } monitor;
> +
> +#ifdef CONFIG_SBSA_VUART_CONSOLE
> +    struct vpl011 vpl011;
> +#endif
> +
>  }  __cacheline_aligned;
>  
>  struct arch_vcpu
> diff --git a/xen/include/asm-arm/pl011-uart.h b/xen/include/asm-arm/pl011-uart.h
> index 123f477..57e9ec7 100644
> --- a/xen/include/asm-arm/pl011-uart.h
> +++ b/xen/include/asm-arm/pl011-uart.h
> @@ -49,6 +49,8 @@
>  /* FR bits */
>  #define TXFE   (1<<7) /* TX FIFO empty */
>  #define RXFE   (1<<4) /* RX FIFO empty */
> +#define TXFF   (1<<5) /* TX FIFO full */
> +#define RXFF   (1<<6) /* RX FIFO full */
>  #define BUSY   (1<<3) /* Transmit is not complete */
>  
>  /* LCR_H bits */
> diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
> new file mode 100644
> index 0000000..f1c6716
> --- /dev/null
> +++ b/xen/include/asm-arm/vpl011.h
> @@ -0,0 +1,73 @@
> +/*
> + * include/xen/vpl011.h
> + *
> + * Virtual PL011 UART
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef _VPL011_H_
> +#define _VPL011_H_
> +
> +#include <public/domctl.h>
> +#include <public/io/ring.h>
> +#include <asm-arm/vreg.h>
> +#include <xen/mm.h>
> +
> +/* helper macros */
> +#define VPL011_LOCK(d,flags) spin_lock_irqsave(&(d)->arch.vpl011.lock, flags)
> +#define VPL011_UNLOCK(d,flags) spin_unlock_irqrestore(&(d)->arch.vpl011.lock, flags)
> +
> +struct vpl011 {
> +    void *ring_buf;
> +    struct page_info *ring_page;
> +    uint32_t    uartfr;         /* Flag register */
> +    uint32_t    uartcr;         /* Control register */
> +    uint32_t    uartimsc;       /* Interrupt mask register*/
> +    uint32_t    uarticr;        /* Interrupt clear register */
> +    uint32_t    uartris;        /* Raw interrupt status register */
> +    uint32_t    shadow_uartris; /* shadowed Raw interrupt status register */
> +    uint32_t    uartmis;        /* Masked interrupt register */
> +    spinlock_t  lock;
> +    evtchn_port_t evtchn;
> +};
> +
> +struct vpl011_init_info {
> +    uint32_t console_domid;
> +    gfn_t gfn;
> +    evtchn_port_t evtchn;
> +};
> +
> +#ifdef CONFIG_SBSA_VUART_CONSOLE
> +int domain_vpl011_init(struct domain *d,
> +                       struct vpl011_init_info *info);
> +void domain_vpl011_deinit(struct domain *d);
> +#else
> +static inline int domain_vpl011_init(struct domain *d,
> +                                     struct vpl011_init_info *info)
> +{
> +    return -ENOSYS;
> +}
> +
> +static inline void domain_vpl011_deinit(struct domain *d) { }
> +#endif
> +#endif
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
> index bd974fb..85ab665 100644
> --- a/xen/include/public/arch-arm.h
> +++ b/xen/include/public/arch-arm.h
> @@ -410,6 +410,10 @@ typedef uint64_t xen_callback_t;
>  #define GUEST_ACPI_BASE 0x20000000ULL
>  #define GUEST_ACPI_SIZE 0x02000000ULL
>  
> +/* PL011 mappings */
> +#define GUEST_PL011_BASE    0x22000000ULL
> +#define GUEST_PL011_SIZE    0x00001000ULL
> +
>  /*
>   * 16MB == 4096 pages reserved for guest to use as a region to map its
>   * grant table in.
> @@ -444,6 +448,8 @@ typedef uint64_t xen_callback_t;
>  #define GUEST_TIMER_PHYS_NS_PPI 30
>  #define GUEST_EVTCHN_PPI        31
>  
> +#define GUEST_VPL011_SPI        32
> +
>  /* PSCI functions */
>  #define PSCI_cpu_suspend 0
>  #define PSCI_cpu_off     1
> -- 
> 2.7.4
> 

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

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

* Re: [PATCH 06/17 v5] xen/arm: vpl011: Add support for vuart in libxl
  2017-06-22  7:38 ` [PATCH 06/17 v5] xen/arm: vpl011: Add support for vuart in libxl Bhupinder Thakur
@ 2017-06-22 22:57   ` Stefano Stabellini
  2017-06-28 17:16   ` Wei Liu
  1 sibling, 0 replies; 67+ messages in thread
From: Stefano Stabellini @ 2017-06-22 22:57 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, 22 Jun 2017, Bhupinder Thakur wrote:
> An option is provided in libxl to enable/disable sbsa vuart while
> creating a guest domain.
> 
> Libxl now suppots a generic vuart console and sbsa uart is a specific type.
> In future support can be added for multiple vuart of different types.
> 
> User can enable sbsa vuart by adding the following line in the guest
> configuration file:
> 
> vuart = "sbsa_uart"
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>

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


> ---
> CC: Ian Jackson <ian.jackson@eu.citrix.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Stefano Stabellini <sstabellini@kernel.org>
> CC: Julien Grall <julien.grall@arm.com>
> 
> Changes since v4:
> - Renamed "pl011" to "sbsa_uart".
> 
> Changes since v3:
> - Added a new config option CONFIG_VUART_CONSOLE to enable/disable vuart console
>   support.
> - Moved libxl_vuart_type to arch-arm part of libxl_domain_build_info
> - Updated xl command help to mention new console type - vuart.
> 
> Changes since v2:
> - Defined vuart option as an enum instead of a string.
> - Removed the domain creation flag defined for vuart and the related code
>   to pass on the information while domain creation. Now vpl011 is initialized
>   independent of domain creation through new DOMCTL APIs.
> 
>  tools/libxl/libxl.h          | 6 ++++++
>  tools/libxl/libxl_console.c  | 3 +++
>  tools/libxl/libxl_dom.c      | 1 +
>  tools/libxl/libxl_internal.h | 3 +++
>  tools/libxl/libxl_types.idl  | 7 +++++++
>  tools/xl/xl_cmdtable.c       | 2 +-
>  tools/xl/xl_console.c        | 5 ++++-
>  tools/xl/xl_parse.c          | 8 ++++++++
>  8 files changed, 33 insertions(+), 2 deletions(-)
> 
> 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_console.c b/tools/libxl/libxl_console.c
> index 446e766..853be15 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;
>      }
> diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
> index 5d914a5..c98af60 100644
> --- a/tools/libxl/libxl_dom.c
> +++ b/tools/libxl/libxl_dom.c
> @@ -788,6 +788,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_gfn = dom->vuart_gfn;
>      } else {
>          state->console_mfn = xc_dom_p2m(dom, dom->console_pfn);
>          state->store_mfn = xc_dom_p2m(dom, dom->xenstore_pfn);
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index afe6652..d0d50c3 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -1139,6 +1139,9 @@ typedef struct {
>      uint32_t num_vmemranges;
>  
>      xc_domain_configuration_t config;
> +
> +    xen_pfn_t vuart_gfn;
> +    evtchn_port_t vuart_port;
>  } 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..d492b35 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", [
> @@ -240,6 +241,11 @@ libxl_checkpointed_stream = Enumeration("checkpointed_stream", [
>      (2, "COLO"),
>      ])
>  
> +libxl_vuart_type = Enumeration("vuart_type", [
> +    (0, "unknown"),
> +    (1, "sbsa_uart"),
> +    ])
> +
>  #
>  # Complex libxl types
>  #
> @@ -580,6 +586,7 @@ libxl_domain_build_info = Struct("domain_build_info",[
>  
>  
>      ("arch_arm", Struct(None, [("gic_version", libxl_gic_version),
> +                               ("vuart", libxl_vuart_type),
>                                ])),
>      # Alternate p2m is not bound to any architecture or guest type, as it is
>      # supported by x86 HVM and ARM support is planned.
> diff --git a/tools/xl/xl_cmdtable.c b/tools/xl/xl_cmdtable.c
> index 30eb93c..9f91651 100644
> --- a/tools/xl/xl_cmdtable.c
> +++ b/tools/xl/xl_cmdtable.c
> @@ -133,7 +133,7 @@ struct cmd_spec cmd_table[] = {
>        &main_console, 0, 0,
>        "Attach to domain's console",
>        "[options] <Domain>\n"
> -      "-t <type>       console type, pv or serial\n"
> +      "-t <type>       console type, pv , serial or vuart\n"
>        "-n <number>     console number"
>      },
>      { "vncviewer",
> diff --git a/tools/xl/xl_console.c b/tools/xl/xl_console.c
> index 0508dda..4e65d73 100644
> --- a/tools/xl/xl_console.c
> +++ b/tools/xl/xl_console.c
> @@ -27,6 +27,7 @@ int main_console(int argc, char **argv)
>      uint32_t domid;
>      int opt = 0, num = 0;
>      libxl_console_type type = 0;
> +    char *console_names = "pv, serial, vuart";
>  
>      SWITCH_FOREACH_OPT(opt, "n:t:", NULL, "console", 1) {
>      case 't':
> @@ -34,8 +35,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: %s\n", console_names);
>              return EXIT_FAILURE;
>          }
>          break;
> diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
> index 856a304..37581ef 100644
> --- a/tools/xl/xl_parse.c
> +++ b/tools/xl/xl_parse.c
> @@ -916,6 +916,14 @@ 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_get_string(config, "vuart", &buf, 0)) {
> +        if (libxl_vuart_type_from_string(buf, &b_info->arch_arm.vuart)) {
> +            fprintf(stderr, "ERROR: invalid value \"%s\" for \"vuart\"\n",
> +                    buf);
> +            exit(1);
> +        }
> +    }
> +
>      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] 67+ messages in thread

* Re: [PATCH 07/17 v5] xen/arm: vpl011: Rearrange xen header includes in alphabetical order in domctl.c
  2017-06-22  7:38 ` [PATCH 07/17 v5] xen/arm: vpl011: Rearrange xen header includes in alphabetical order in domctl.c Bhupinder Thakur
@ 2017-06-22 22:58   ` Stefano Stabellini
  2017-06-23 13:14     ` Julien Grall
  0 siblings, 1 reply; 67+ messages in thread
From: Stefano Stabellini @ 2017-06-22 22:58 UTC (permalink / raw)
  To: Bhupinder Thakur; +Cc: xen-devel, Julien Grall, Stefano Stabellini

On Thu, 22 Jun 2017, Bhupinder Thakur wrote:
> Rearrange xen header includes in alphabetical order in domctl.c.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>

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

> ---
> CC: Stefano Stabellini <sstabellini@kernel.org>
> CC: Julien Grall <julien.grall@arm.com>
> 
>  xen/arch/arm/domctl.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
> index 971caec..86fa102 100644
> --- a/xen/arch/arm/domctl.c
> +++ b/xen/arch/arm/domctl.c
> @@ -5,11 +5,11 @@
>   */
>  
>  #include <xen/types.h>
> -#include <xen/lib.h>
>  #include <xen/errno.h>
> -#include <xen/sched.h>
>  #include <xen/hypercall.h>
>  #include <xen/iocap.h>
> +#include <xen/lib.h>
> +#include <xen/sched.h>
>  #include <xsm/xsm.h>
>  #include <public/domctl.h>
>  
> -- 
> 2.7.4
> 

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

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

* Re: [PATCH 08/17 v5] xen/arm: vpl011: Add a new domctl API to initialize vpl011
  2017-06-22  7:38 ` [PATCH 08/17 v5] xen/arm: vpl011: Add a new domctl API to initialize vpl011 Bhupinder Thakur
@ 2017-06-22 23:04   ` Stefano Stabellini
  2017-06-23 13:17     ` Julien Grall
  2017-06-23 13:26   ` Julien Grall
  2017-06-28 17:16   ` Wei Liu
  2 siblings, 1 reply; 67+ messages in thread
From: Stefano Stabellini @ 2017-06-22 23:04 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, 22 Jun 2017, Bhupinder Thakur wrote:
> Add a new domctl API to initialize vpl011. It takes the GFN and console
> backend domid as input and returns an event channel to be used for
> sending and receiving events from Xen.
> 
> Xen will communicate with xenconsole using GFN as the ring buffer and
> the event channel to transmit and receive pl011 data on the guest domain's
> behalf.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
> ---
> CC: Ian Jackson <ian.jackson@eu.citrix.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Stefano Stabellini <sstabellini@kernel.org>
> CC: Julien Grall <julien.grall@arm.com>
> 
> Changes since v4:
> - Removed libxl__arch_domain_create_finish().
> - Added a new function libxl__arch_build_dom_finish(), which is called at the last
>   in libxl__build_dom(). This function calls the vpl011 initialization function now.
> 
> Changes since v3:
> - Added a new arch specific function libxl__arch_domain_create_finish(), which
>   calls the vpl011 initialization function. For x86 this function does not do
>   anything.
> - domain_vpl011_init() takes a pointer to a structure which contains all the 
>   required information such as console_domid, gfn instead of passing parameters
>   separately.
> - Dropped a DOMCTL API defined for de-initializing vpl011 as that should be
>   taken care when the domain is destroyed (and not dependent on userspace 
>   libraries/applications).
> 
> Changes since v2:
> - Replaced the DOMCTL APIs defined for get/set of event channel and GFN with 
>   a set of DOMCTL APIs for initializing and de-initializing vpl011 emulation.
> 
>  tools/libxc/include/xenctrl.h | 20 ++++++++++++++++++++
>  tools/libxc/xc_domain.c       | 25 +++++++++++++++++++++++++
>  tools/libxl/libxl_arch.h      |  6 ++++++
>  tools/libxl/libxl_arm.c       | 22 ++++++++++++++++++++++
>  tools/libxl/libxl_dom.c       |  4 ++++
>  tools/libxl/libxl_x86.c       |  8 ++++++++
>  xen/arch/arm/domain.c         |  5 +++++
>  xen/arch/arm/domctl.c         | 37 +++++++++++++++++++++++++++++++++++++
>  xen/include/public/domctl.h   | 12 ++++++++++++
>  9 files changed, 139 insertions(+)
> 
> diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
> index 1629f41..26f3d1e 100644
> --- a/tools/libxc/include/xenctrl.h
> +++ b/tools/libxc/include/xenctrl.h
> @@ -885,6 +885,26 @@ int xc_vcpu_getcontext(xc_interface *xch,
>                         uint32_t vcpu,
>                         vcpu_guest_context_any_t *ctxt);
>  
> +#if defined (__arm__) || defined(__aarch64__)
> +/**
> + * This function initializes the vpl011 emulation and returns
> + * the event to be used by the backend for communicating with
> + * the emulation code.
> + *
> + * @parm xch a handle to an open hypervisor interface
> + * @parm domid the domain to get information from
> + * @parm console_domid the domid of the backend console
> + * @parm gfn the guest pfn to be used as the ring buffer
> + * @parm evtchn the event channel to be used for events
> + * @return 0 on success, negative error on failure
> + */
> +int xc_dom_vpl011_init(xc_interface *xch,
> +                       uint32_t domid,
> +                       uint32_t console_domid,
> +                       xen_pfn_t gfn,
> +                       evtchn_port_t *evtchn);
> +#endif

Actually, the pattern is to define the xc_ function on all architecture
but only return ENOSYS where it's not implemented, see
xc_vcpu_get_extstate.


>  /**
>   * This function returns information about the XSAVE state of a particular
>   * vcpu of a domain. If extstate->size and extstate->xfeature_mask are 0,
> diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
> index 5d192ea..55de408 100644
> --- a/tools/libxc/xc_domain.c
> +++ b/tools/libxc/xc_domain.c
> @@ -343,6 +343,31 @@ int xc_domain_get_guest_width(xc_interface *xch, uint32_t domid,
>      return 0;
>  }
>  
> +#if defined (__arm__) || defined(__aarch64__)
> +int xc_dom_vpl011_init(xc_interface *xch,
> +                       uint32_t domid,
> +                       uint32_t console_domid,
> +                       xen_pfn_t gfn,
> +                       evtchn_port_t *evtchn)
> +{

See other comment.


> +    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_INIT_VPL011;
> +    domctl.u.vuart_op.console_domid = console_domid;
> +    domctl.u.vuart_op.gfn = gfn;
> +
> +    if ( (rc = do_domctl(xch, &domctl)) < 0 )
> +        return rc;
> +
> +    *evtchn = domctl.u.vuart_op.evtchn;
> +
> +    return rc;
> +}
> +#endif
> +
>  int xc_domain_getinfo(xc_interface *xch,
>                        uint32_t first_domid,
>                        unsigned int max_doms,
> diff --git a/tools/libxl/libxl_arch.h b/tools/libxl/libxl_arch.h
> index 5e1fc60..118b92c 100644
> --- a/tools/libxl/libxl_arch.h
> +++ b/tools/libxl/libxl_arch.h
> @@ -44,6 +44,12 @@ int libxl__arch_domain_finalise_hw_description(libxl__gc *gc,
>                                        libxl_domain_build_info *info,
>                                        struct xc_dom_image *dom);
>  
> +/* perform any pending hardware initialization */
> +int libxl__arch_build_dom_finish(libxl__gc *gc,
> +                                 libxl_domain_build_info *info,
> +                                 struct xc_dom_image *dom,
> +                                 libxl__domain_build_state *state);
> +
>  /* build vNUMA vmemrange with arch specific information */
>  _hidden
>  int libxl__arch_vnuma_build_vmemrange(libxl__gc *gc,
> diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
> index d842d88..9d6448e 100644
> --- a/tools/libxl/libxl_arm.c
> +++ b/tools/libxl/libxl_arm.c
> @@ -1038,6 +1038,28 @@ int libxl__arch_domain_finalise_hw_description(libxl__gc *gc,
>      return 0;
>  }
>  
> +int libxl__arch_build_dom_finish(libxl__gc *gc,
> +                                 libxl_domain_build_info *info,
> +                                 struct xc_dom_image *dom,
> +                                 libxl__domain_build_state *state)
> +{
> +    int ret = 0;
> +
> +    if ( info->arch_arm.vuart ) {
> +        ret = xc_dom_vpl011_init(CTX->xch,
> +                                 dom->guest_domid,
> +                                 dom->console_domid,
> +                                 dom->vuart_gfn,
> +                                 &state->vuart_port);
> +        if ( ret < 0 )
> +        {
> +            LOG(ERROR, "xc_dom_vpl011_init failed\n");
> +        }
> +    }
> +
> +    return ret;
> +}
> +
>  int libxl__arch_vnuma_build_vmemrange(libxl__gc *gc,
>                                        uint32_t domid,
>                                        libxl_domain_build_info *info,
> diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
> index c98af60..9b42205 100644
> --- a/tools/libxl/libxl_dom.c
> +++ b/tools/libxl/libxl_dom.c
> @@ -687,6 +687,10 @@ static int libxl__build_dom(libxl__gc *gc, uint32_t domid,
>          LOGE(ERROR, "xc_dom_gnttab_init failed");
>          goto out;
>      }
> +    if ( (ret = libxl__arch_build_dom_finish(gc, info, dom, state)) != 0 ) {
> +        LOGE(ERROR, "libxl__arch_build_dom_finish failed");
> +        goto out;
> +    }
>  
>  out:
>      return ret != 0 ? ERROR_FAIL : 0;
> diff --git a/tools/libxl/libxl_x86.c b/tools/libxl/libxl_x86.c
> index 455f6f0..0aaeded 100644
> --- a/tools/libxl/libxl_x86.c
> +++ b/tools/libxl/libxl_x86.c
> @@ -391,6 +391,14 @@ int libxl__arch_domain_finalise_hw_description(libxl__gc *gc,
>      return rc;
>  }
>  
> +int libxl__arch_build_dom_finish(libxl__gc *gc,
> +                                 libxl_domain_build_info *info,
> +                                 struct xc_dom_image *dom,
> +                                 libxl__domain_build_state *state)
> +{
> +    return 0;
> +}
> +
>  /* Return 0 on success, ERROR_* on failure. */
>  int libxl__arch_vnuma_build_vmemrange(libxl__gc *gc,
>                                        uint32_t domid,
> diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
> index 76310ed..f1b24cc 100644
> --- a/xen/arch/arm/domain.c
> +++ b/xen/arch/arm/domain.c
> @@ -665,6 +665,11 @@ fail:
>  
>  void arch_domain_destroy(struct domain *d)
>  {
> +    /*
> +     * vpl011 is initialized via a DOMCTL call XEN_DOMCTL_vuart_op.
> +     */
> +    domain_vpl011_deinit(d);
> +
>      /* IOMMU page table is shared with P2M, always call
>       * iommu_domain_destroy() before p2m_teardown().
>       */
> diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
> index 86fa102..280c412 100644
> --- a/xen/arch/arm/domctl.c
> +++ b/xen/arch/arm/domctl.c
> @@ -6,9 +6,11 @@
>  
>  #include <xen/types.h>
>  #include <xen/errno.h>
> +#include <xen/guest_access.h>
>  #include <xen/hypercall.h>
>  #include <xen/iocap.h>
>  #include <xen/lib.h>
> +#include <xen/mm.h>
>  #include <xen/sched.h>
>  #include <xsm/xsm.h>
>  #include <public/domctl.h>
> @@ -119,6 +121,41 @@ 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;
> +        struct xen_domctl_vuart_op *vuart_op = &domctl->u.vuart_op;
> +
> +        switch(vuart_op->cmd)
> +        {
> +        case XEN_DOMCTL_VUART_OP_INIT_VPL011:
> +
> +            if ( !d->creation_finished )
> +            {
> +                struct vpl011_init_info info;
> +
> +                info.console_domid = vuart_op->console_domid;
> +                info.gfn = _gfn(vuart_op->gfn);
> +
> +                rc = domain_vpl011_init(d, &info);
> +                if ( !rc )
> +                {
> +                    vuart_op->evtchn = info.evtchn;
> +                    rc = __copy_to_guest(u_domctl, domctl, 1);
> +                }
> +            }
> +            else
> +                rc = - EPERM;
> +
> +            break;
> +
> +        default:
> +            rc = -EINVAL;
> +            break;
> +        }
> +
> +        return rc;
> +    }
>      default:
>      {
>          int rc;
> diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
> index f7cbc0a..0da8aa6 100644
> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -36,6 +36,7 @@
>  #include "grant_table.h"
>  #include "hvm/save.h"
>  #include "memory.h"
> +#include "event_channel.h"
>  
>  #define XEN_DOMCTL_INTERFACE_VERSION 0x0000000e
>  
> @@ -1138,6 +1139,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_INIT_VPL011  0
> +        uint32_t cmd;           /* XEN_DOMCTL_VUART_OP_* */
> +        uint32_t console_domid; /* IN */
> +        xen_pfn_t gfn;          /* IN */
> +        evtchn_port_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 +1228,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 +1291,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] 67+ messages in thread

* Re: [PATCH 09/17 v5] xen/arm: vpl011: Add a new vuart node in the xenstore
  2017-06-22  7:38 ` [PATCH 09/17 v5] xen/arm: vpl011: Add a new vuart node in the xenstore Bhupinder Thakur
@ 2017-06-22 23:06   ` Stefano Stabellini
  2017-06-28 17:16   ` Wei Liu
  1 sibling, 0 replies; 67+ messages in thread
From: Stefano Stabellini @ 2017-06-22 23:06 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, 22 Jun 2017, Bhupinder Thakur wrote:
> Add a new vuart console node to xenstore. This node is added at
> 
> /local/domain/$DOMID/vuart/0.
> 
> The node contains information such as the ring-ref, event channel,
> buffer limit and type of console.
> 
> Xenconsole reads the node information to setup the ring buffer and
> event channel for sending/receiving vuart data.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>

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


> ---
> CC: Ian Jackson <ian.jackson@eu.citrix.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Stefano Stabellini <sstabellini@kernel.org>
> CC: Julien Grall <julien.grall@arm.com>
> 
> Changes since v4:
> -  vuart_device moved inside libxl__device_vuart_add() as a local variable.
> 
> Changes since v3:
> - Added a backend node for vpl011.
> - Removed libxl__device_vuart_add() for HVM guest. It is called only for PV guest.
> 
>  tools/libxl/libxl_console.c          | 44 ++++++++++++++++++++++++++++++++++++
>  tools/libxl/libxl_create.c           | 10 +++++++-
>  tools/libxl/libxl_device.c           |  9 ++++++--
>  tools/libxl/libxl_internal.h         |  3 +++
>  tools/libxl/libxl_types_internal.idl |  1 +
>  5 files changed, 64 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/libxl/libxl_console.c b/tools/libxl/libxl_console.c
> index 853be15..cdaf7fd 100644
> --- a/tools/libxl/libxl_console.c
> +++ b/tools/libxl/libxl_console.c
> @@ -344,6 +344,50 @@ out:
>      return rc;
>  }
>  
> +int libxl__device_vuart_add(libxl__gc *gc, uint32_t domid,
> +                            libxl__device_console *console,
> +                            libxl__domain_build_state *state)
> +{
> +    libxl__device device;
> +    flexarray_t *ro_front;
> +    flexarray_t *back;
> +    int rc;
> +
> +    ro_front = flexarray_make(gc, 16, 1);
> +    back = flexarray_make(gc, 16, 1);
> +
> +    device.backend_devid = console->devid;
> +    device.backend_domid = console->backend_domid;
> +    device.backend_kind = LIBXL__DEVICE_KIND_VUART;
> +    device.devid = console->devid;
> +    device.domid = domid;
> +    device.kind = LIBXL__DEVICE_KIND_VUART;
> +
> +    flexarray_append(back, "frontend-id");
> +    flexarray_append(back, GCSPRINTF("%d", domid));
> +    flexarray_append(back, "online");
> +    flexarray_append(back, "1");
> +    flexarray_append(back, "state");
> +    flexarray_append(back, GCSPRINTF("%d", XenbusStateInitialising));
> +    flexarray_append(back, "protocol");
> +    flexarray_append(back, LIBXL_XENCONSOLE_PROTOCOL);
> +
> +    flexarray_append(ro_front, "port");
> +    flexarray_append(ro_front, GCSPRINTF("%"PRIu32, state->vuart_port));
> +    flexarray_append(ro_front, "ring-ref");
> +    flexarray_append(ro_front, GCSPRINTF("%lu", state->vuart_gfn));
> +    flexarray_append(ro_front, "limit");
> +    flexarray_append(ro_front, GCSPRINTF("%d", LIBXL_XENCONSOLE_LIMIT));
> +    flexarray_append(ro_front, "type");
> +    flexarray_append(ro_front, "xenconsoled");
> +
> +    rc = libxl__device_generic_add(gc, XBT_NULL, &device,
> +                                   libxl__xs_kvs_of_flexarray(gc, back),
> +                                   NULL,
> +                                   libxl__xs_kvs_of_flexarray(gc, ro_front));
> +    return rc;
> +}
> +
>  int libxl__init_console_from_channel(libxl__gc *gc,
>                                       libxl__device_console *console,
>                                       int dev_num,
> diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
> index bffbc45..cfd85ec 100644
> --- a/tools/libxl/libxl_create.c
> +++ b/tools/libxl/libxl_create.c
> @@ -1367,7 +1367,7 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev,
>      }
>      case LIBXL_DOMAIN_TYPE_PV:
>      {
> -        libxl__device_console console;
> +        libxl__device_console console, vuart;
>          libxl__device device;
>  
>          for (i = 0; i < d_config->num_vfbs; i++) {
> @@ -1375,6 +1375,14 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev,
>              libxl__device_vkb_add(gc, domid, &d_config->vkbs[i]);
>          }
>  
> +        if (d_config->b_info.arch_arm.vuart)
> +        {
> +            init_console_info(gc, &vuart, 0);
> +            vuart.backend_domid = state->console_domid;
> +            libxl__device_vuart_add(gc, domid, &vuart, state);
> +            libxl__device_console_dispose(&vuart);
> +        }
> +
>          init_console_info(gc, &console, 0);
>          console.backend_domid = state->console_domid;
>          libxl__device_console_add(gc, domid, &console, state, &device);
> diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
> index 00356af..3b10c58 100644
> --- a/tools/libxl/libxl_device.c
> +++ b/tools/libxl/libxl_device.c
> @@ -26,6 +26,9 @@ static char *libxl__device_frontend_path(libxl__gc *gc, libxl__device *device)
>      if (device->kind == LIBXL__DEVICE_KIND_CONSOLE && device->devid == 0)
>          return GCSPRINTF("%s/console", dom_path);
>  
> +    if (device->kind == LIBXL__DEVICE_KIND_VUART)
> +        return GCSPRINTF("%s/vuart/%d", dom_path, device->devid);
> +
>      return GCSPRINTF("%s/device/%s/%d", dom_path,
>                       libxl__device_kind_to_string(device->kind),
>                       device->devid);
> @@ -170,7 +173,8 @@ retry_transaction:
>           * historically contained other information, such as the
>           * vnc-port, which we don't want the guest fiddling with.
>           */
> -        if (device->kind == LIBXL__DEVICE_KIND_CONSOLE && device->devid == 0)
> +        if ((device->kind == LIBXL__DEVICE_KIND_CONSOLE && device->devid == 0) ||
> +            (device->kind == LIBXL__DEVICE_KIND_VUART))
>              xs_set_permissions(ctx->xsh, t, frontend_path,
>                                 ro_frontend_perms, ARRAY_SIZE(ro_frontend_perms));
>          else
> @@ -800,7 +804,8 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
>                  dev->domid = domid;
>                  dev->kind = kind;
>                  dev->devid = atoi(devs[j]);
> -                if (dev->backend_kind == LIBXL__DEVICE_KIND_CONSOLE) {
> +                if (dev->backend_kind == LIBXL__DEVICE_KIND_CONSOLE ||
> +                    dev->backend_kind == LIBXL__DEVICE_KIND_VUART) {
>                      /* Currently console devices can be destroyed
>                       * synchronously by just removing xenstore entries,
>                       * this is what libxl__device_destroy does.
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index d0d50c3..2b3f4e1 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -1206,6 +1206,9 @@ _hidden int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
>                                        libxl__device_console *console,
>                                        libxl__domain_build_state *state,
>                                        libxl__device *device);
> +_hidden int libxl__device_vuart_add(libxl__gc *gc, uint32_t domid,
> +                                    libxl__device_console *console,
> +                                    libxl__domain_build_state *state);
>  
>  /* Returns 1 if device exists, 0 if not, ERROR_* (<0) on error. */
>  _hidden int libxl__device_exists(libxl__gc *gc, xs_transaction_t t,
> diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl
> index 7dc4d0f..c463c33 100644
> --- a/tools/libxl/libxl_types_internal.idl
> +++ b/tools/libxl/libxl_types_internal.idl
> @@ -26,6 +26,7 @@ libxl__device_kind = Enumeration("device_kind", [
>      (9, "VUSB"),
>      (10, "QUSB"),
>      (11, "9PFS"),
> +    (12, "VUART"),
>      ])
>  
>  libxl__console_backend = Enumeration("console_backend", [
> -- 
> 2.7.4
> 

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

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

* Re: [PATCH 15/17 v5] xen/arm: vpl011: Add a new vuart console type to xenconsole client
  2017-06-22  7:38 ` [PATCH 15/17 v5] xen/arm: vpl011: Add a new vuart console type to xenconsole client Bhupinder Thakur
@ 2017-06-22 23:09   ` Stefano Stabellini
  2017-06-28 17:17   ` Wei Liu
  1 sibling, 0 replies; 67+ messages in thread
From: Stefano Stabellini @ 2017-06-22 23:09 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, 22 Jun 2017, Bhupinder Thakur wrote:
> Add a new console type VUART to connect to guest's emualated vuart
> console.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>

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


> ---
> CC: Ian Jackson <ian.jackson@eu.citrix.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Stefano Stabellini <sstabellini@kernel.org>
> CC: Julien Grall <julien.grall@arm.com>
> 
> Changes since v4:
> - Removed the vuart compile time flag so that vuart code is compiled always.
> 
> Changes since v3:
> - The vuart console support is under CONFIG_VUART_CONSOLE option.
> - Since there is a change from last review, I have not included
>   reviewed-by tag from Stefano and acked-by tag from Wei.
> 
>  tools/console/client/main.c | 13 +++++++++++--
>  1 file changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/console/client/main.c b/tools/console/client/main.c
> index 977779f..3dbb06f 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;
> @@ -343,6 +344,7 @@ int main(int argc, char **argv)
>  	char *end;
>  	console_type type = CONSOLE_INVAL;
>  	bool interactive = 0;
> +	char *console_names = "serial, pv, vuart";
>  
>  	if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO))
>  		interactive = 1;
> @@ -361,9 +363,12 @@ 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");
> +				fprintf(stderr, "Console types supported are: %s\n",
> +						console_names);
>  				exit(EINVAL);
>  			}
>  			break;
> @@ -436,6 +441,10 @@ 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("/vuart/0/tty") + 1,
> +				 "%s/vuart/0/tty", 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	[flat|nested] 67+ messages in thread

* Re: [PATCH 10/17 v5] xen/arm: vpl011: Modify xenconsole to define and use a new console structure
  2017-06-22  7:38 ` [PATCH 10/17 v5] xen/arm: vpl011: Modify xenconsole to define and use a new console structure Bhupinder Thakur
@ 2017-06-22 23:20   ` Stefano Stabellini
  2017-06-28 17:16   ` Wei Liu
  1 sibling, 0 replies; 67+ messages in thread
From: Stefano Stabellini @ 2017-06-22 23:20 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, 22 Jun 2017, Bhupinder Thakur wrote:
> Xenconsole uses a domain structure which contains console specific fields. This
> patch defines a new console structure, which would be used by the xenconsole
> functions to perform console specific operations like reading/writing data from/to
> the console ring buffer or reading/writing data from/to console tty.
> 
> This patch is in preparation to support multiple consoles to support vuart console.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>

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


> ---
> CC: Ian Jackson <ian.jackson@eu.citrix.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Stefano Stabellini <sstabellini@kernel.org>
> CC: Julien Grall <julien.grall@arm.com>
> 
> Changes since v4:
> - Moved the following fields from the struct domain to struct console:
>   ->xenevtchn_handle *xce_handle;
>   ->int xce_pollfd_idx;
>   ->int event_count;
>   ->long long next_period;
> 
> Changes since v3:
> - The changes in xenconsole have been split into four patches. This is the first patch
>   which modifies the xenconsole to use a new console structure.
> 
> Changes since v2:
> - Defined a new function console_create_ring() which sets up the ring buffer and 
>   event channel a new console. domain_create_ring() uses this function to setup
>   a console.
> - This patch does not contain vuart specific changes, which would be introduced in
>   the next patch.
> - Changes for keeping the PV log file name unchanged.
> 
> 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 | 299 +++++++++++++++++++++++++---------------------
>  1 file changed, 165 insertions(+), 134 deletions(-)
> 
> diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
> index e8033d2..30cd167 100644
> --- a/tools/console/daemon/io.c
> +++ b/tools/console/daemon/io.c
> @@ -89,25 +89,30 @@ struct buffer {
>  	size_t max_capacity;
>  };
>  
> -struct domain {
> -	int domid;
> +struct console {
>  	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;
>  	xenevtchn_handle *xce_handle;
>  	int xce_pollfd_idx;
> -	struct xencons_interface *interface;
>  	int event_count;
>  	long long next_period;
> +	xenevtchn_port_or_error_t local_port;
> +	xenevtchn_port_or_error_t remote_port;
> +	struct xencons_interface *interface;
> +	struct domain *d;
> +};
> +
> +struct domain {
> +	int domid;
> +	bool is_dead;
> +	unsigned last_seen;
> +	struct domain *next;
> +	struct console console;
>  };
>  
>  static struct domain *dom_head;
> @@ -160,9 +165,10 @@ static int write_with_timestamp(int fd, const char *data, size_t sz,
>  
>  static void buffer_append(struct domain *dom)
>  {
> -	struct buffer *buffer = &dom->buffer;
> +	struct console *con = &dom->console;
> +	struct buffer *buffer = &con->buffer;
>  	XENCONS_RING_IDX cons, prod, size;
> -	struct xencons_interface *intf = dom->interface;
> +	struct xencons_interface *intf = con->interface;
>  
>  	cons = intf->out_cons;
>  	prod = intf->out_prod;
> @@ -187,22 +193,22 @@ static void buffer_append(struct domain *dom)
>  
>  	xen_mb();
>  	intf->out_cons = cons;
> -	xenevtchn_notify(dom->xce_handle, dom->local_port);
> +	xenevtchn_notify(con->xce_handle, con->local_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);
>  		}
> @@ -338,14 +344,16 @@ static int create_domain_log(struct domain *dom)
>  
>  static void domain_close_tty(struct domain *dom)
>  {
> -	if (dom->master_fd != -1) {
> -		close(dom->master_fd);
> -		dom->master_fd = -1;
> +	struct console *con = &dom->console;
> +
> +	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;
>  	}
>  }
>  
> @@ -418,11 +426,12 @@ static int domain_create_tty(struct domain *dom)
>  	char *data;
>  	unsigned int len;
>  	struct termios term;
> +	struct console *con = &dom->console;
>  
> -	assert(dom->slave_fd == -1);
> -	assert(dom->master_fd == -1);
> +	assert(con->slave_fd == -1);
> +	assert(con->master_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)",
> @@ -430,7 +439,7 @@ static int domain_create_tty(struct domain *dom)
>  		return 0;
>  	}
>  
> -	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 +447,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,7 +455,7 @@ 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)",
> @@ -454,18 +463,18 @@ static int domain_create_tty(struct domain *dom)
>  		goto out;
>  	}
>  
> -	success = asprintf(&path, "%s/limit", dom->conspath) !=
> +	success = asprintf(&path, "%s/limit", con->conspath) !=
>  		-1;
>  	if (!success)
>  		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/tty", con->conspath) != -1);
>  	if (!success)
>  		goto out;
>  	success = xs_write(xs, XBT_NULL, path, slave, strlen(slave));
> @@ -473,7 +482,7 @@ static int domain_create_tty(struct domain *dom)
>  	if (!success)
>  		goto out;
>  
> -	if (fcntl(dom->master_fd, F_SETFL, O_NONBLOCK) == -1)
> +	if (fcntl(con->master_fd, F_SETFL, O_NONBLOCK) == -1)
>  		goto out;
>  
>  	return 1;
> @@ -519,29 +528,32 @@ static int xs_gather(struct xs_handle *xs, const char *dir, ...)
>  
>  static void domain_unmap_interface(struct domain *dom)
>  {
> -	if (dom->interface == NULL)
> +	struct console *con = &dom->console;
> +
> +	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 int domain_create_ring(struct domain *dom)
>  {
>  	int err, remote_port, ring_ref, rc;
>  	char *type, path[PATH_MAX];
> +	struct console *con = &dom->console;
>  
> -	err = xs_gather(xs, dom->conspath,
> +	err = xs_gather(xs, con->conspath,
>  			"ring-ref", "%u", &ring_ref,
>  			"port", "%i", &remote_port,
>  			NULL);
>  	if (err)
>  		goto out;
>  
> -	snprintf(path, sizeof(path), "%s/type", dom->conspath);
> +	snprintf(path, sizeof(path), "%s/type", con->conspath);
>  	type = xs_read(xs, XBT_NULL, path, NULL);
>  	if (type && strcmp(type, "xenconsoled") != 0) {
>  		free(type);
> @@ -550,77 +562,77 @@ 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)
> +	if (ring_ref != con->ring_ref && con->ring_ref != -1)
>  		domain_unmap_interface(dom);
>  
> -	if (!dom->interface && xgt_handle) {
> +	if (!con->interface && xgt_handle) {
>  		/* Prefer using grant table */
> -		dom->interface = xengnttab_map_grant_ref(xgt_handle,
> +		con->interface = xengnttab_map_grant_ref(xgt_handle,
>  			dom->domid, GNTTAB_RESERVED_CONSOLE,
>  			PROT_READ|PROT_WRITE);
> -		dom->ring_ref = -1;
> +		con->ring_ref = -1;
>  	}
> -	if (!dom->interface) {
> +	if (!con->interface) {
>  		/* Fall back to xc_map_foreign_range */
> -		dom->interface = xc_map_foreign_range(
> +		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 (con->interface == NULL) {
>  			err = EINVAL;
>  			goto out;
>  		}
> -		dom->ring_ref = ring_ref;
> +		con->ring_ref = ring_ref;
>  	}
>  
>  	/* Go no further if port has not changed and we are still bound. */
> -	if (remote_port == dom->remote_port) {
> +	if (remote_port == con->remote_port) {
>  		xc_evtchn_status_t status = {
>  			.dom = DOMID_SELF,
> -			.port = dom->local_port };
> +			.port = con->local_port };
>  		if ((xc_evtchn_status(xc, &status) == 0) &&
>  		    (status.status == EVTCHNSTAT_interdomain))
>  			goto out;
>  	}
>  
> -	dom->local_port = -1;
> -	dom->remote_port = -1;
> -	if (dom->xce_handle != NULL)
> -		xenevtchn_close(dom->xce_handle);
> +	con->local_port = -1;
> +	con->remote_port = -1;
> +	if (con->xce_handle != NULL)
> +		xenevtchn_close(con->xce_handle);
>  
>  	/* Opening evtchn independently for each console is a bit
>  	 * wasteful, but that's how the code is structured... */
> -	dom->xce_handle = xenevtchn_open(NULL, 0);
> -	if (dom->xce_handle == NULL) {
> +	con->xce_handle = xenevtchn_open(NULL, 0);
> +	if (con->xce_handle == NULL) {
>  		err = errno;
>  		goto out;
>  	}
>   
> -	rc = xenevtchn_bind_interdomain(dom->xce_handle,
> +	rc = xenevtchn_bind_interdomain(con->xce_handle,
>  		dom->domid, remote_port);
>  
>  	if (rc == -1) {
>  		err = errno;
> -		xenevtchn_close(dom->xce_handle);
> -		dom->xce_handle = NULL;
> +		xenevtchn_close(con->xce_handle);
> +		con->xce_handle = NULL;
>  		goto out;
>  	}
> -	dom->local_port = rc;
> -	dom->remote_port = remote_port;
> +	con->local_port = rc;
> +	con->remote_port = remote_port;
>  
> -	if (dom->master_fd == -1) {
> +	if (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;
> +			xenevtchn_close(con->xce_handle);
> +			con->xce_handle = NULL;
> +			con->local_port = -1;
> +			con->remote_port = -1;
>  			goto out;
>  		}
>  	}
>  
> -	if (log_guest && (dom->log_fd == -1))
> -		dom->log_fd = create_domain_log(dom);
> +	if (log_guest && (con->log_fd == -1))
> +		con->log_fd = create_domain_log(dom);
>  
>   out:
>  	return err;
> @@ -630,16 +642,17 @@ static bool watch_domain(struct domain *dom, bool watch)
>  {
>  	char domid_str[3 + MAX_STRLEN(dom->domid)];
>  	bool success;
> +	struct console *con = &dom->console;
>  
>  	snprintf(domid_str, sizeof(domid_str), "dom%u", dom->domid);
>  	if (watch) {
> -		success = xs_watch(xs, dom->conspath, domid_str);
> +		success = xs_watch(xs, con->conspath, domid_str);
>  		if (success)
>  			domain_create_ring(dom);
>  		else
> -			xs_unwatch(xs, dom->conspath, domid_str);
> +			xs_unwatch(xs, con->conspath, domid_str);
>  	} else {
> -		success = xs_unwatch(xs, dom->conspath, domid_str);
> +		success = xs_unwatch(xs, con->conspath, domid_str);
>  	}
>  
>  	return success;
> @@ -651,6 +664,7 @@ static struct domain *create_domain(int domid)
>  	struct domain *dom;
>  	char *s;
>  	struct timespec ts;
> +	struct console *con;
>  
>  	if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
>  		dolog(LOG_ERR, "Cannot get time of day %s:%s:L%d",
> @@ -667,25 +681,26 @@ static struct domain *create_domain(int domid)
>  
>  	dom->domid = domid;
>  
> -	dom->conspath = xs_get_domain_path(xs, dom->domid);
> -	s = realloc(dom->conspath, strlen(dom->conspath) +
> +	con = &dom->console;
> +	con->conspath = xs_get_domain_path(xs, dom->domid);
> +	s = realloc(con->conspath, strlen(con->conspath) +
>  		    strlen("/console") + 1);
>  	if (s == NULL)
>  		goto out;
> -	dom->conspath = s;
> -	strcat(dom->conspath, "/console");
> +	con->conspath = s;
> +	strcat(con->conspath, "/console");
>  
> -	dom->master_fd = -1;
> -	dom->master_pollfd_idx = -1;
> -	dom->slave_fd = -1;
> -	dom->log_fd = -1;
> -	dom->xce_pollfd_idx = -1;
> +	con->master_fd = -1;
> +	con->master_pollfd_idx = -1;
> +	con->slave_fd = -1;
> +	con->log_fd = -1;
> +	con->xce_pollfd_idx = -1;
>  
> -	dom->next_period = ((long long)ts.tv_sec * 1000) + (ts.tv_nsec / 1000000) + RATE_LIMIT_PERIOD;
> +	con->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;
> +	con->ring_ref = -1;
> +	con->local_port = -1;
> +	con->remote_port = -1;
>  
>  	if (!watch_domain(dom, true))
>  		goto out;
> @@ -697,7 +712,7 @@ static struct domain *create_domain(int domid)
>  
>  	return dom;
>   out:
> -	free(dom->conspath);
> +	free(con->conspath);
>  	free(dom);
>  	return NULL;
>  }
> @@ -729,30 +744,34 @@ static void remove_domain(struct domain *dom)
>  
>  static void cleanup_domain(struct domain *d)
>  {
> +	struct console *con = &d->console;
> +
>  	domain_close_tty(d);
>  
> -	if (d->log_fd != -1) {
> -		close(d->log_fd);
> -		d->log_fd = -1;
> +	if (con->log_fd != -1) {
> +		close(con->log_fd);
> +		con->log_fd = -1;
>  	}
>  
> -	free(d->buffer.data);
> -	d->buffer.data = NULL;
> +	free(con->buffer.data);
> +	con->buffer.data = NULL;
>  
> -	free(d->conspath);
> -	d->conspath = NULL;
> +	free(con->conspath);
> +	con->conspath = NULL;
>  
>  	remove_domain(d);
>  }
>  
>  static void shutdown_domain(struct domain *d)
>  {
> +	struct console *con = &d->console;
> +
>  	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;
> +	if (con->xce_handle != NULL)
> +		xenevtchn_close(con->xce_handle);
> +	con->xce_handle = NULL;
>  }
>  
>  static unsigned enum_pass = 0;
> @@ -782,7 +801,8 @@ static void enum_domains(void)
>  
>  static int ring_free_bytes(struct domain *dom)
>  {
> -	struct xencons_interface *intf = dom->interface;
> +	struct console *con = &dom->console;
> +	struct xencons_interface *intf = con->interface;
>  	XENCONS_RING_IDX cons, prod, space;
>  
>  	cons = intf->in_cons;
> @@ -812,7 +832,8 @@ static void handle_tty_read(struct domain *dom)
>  	ssize_t len = 0;
>  	char msg[80];
>  	int i;
> -	struct xencons_interface *intf = dom->interface;
> +	struct console *con = &dom->console;
> +	struct xencons_interface *intf = con->interface;
>  	XENCONS_RING_IDX prod;
>  
>  	if (dom->is_dead)
> @@ -825,7 +846,7 @@ static void handle_tty_read(struct domain *dom)
>  	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,7 +862,7 @@ static void handle_tty_read(struct domain *dom)
>  		}
>  		xen_wmb();
>  		intf->in_prod = prod;
> -		xenevtchn_notify(dom->xce_handle, dom->local_port);
> +		xenevtchn_notify(con->xce_handle, con->local_port);
>  	} else {
>  		domain_close_tty(dom);
>  		shutdown_domain(dom);
> @@ -851,37 +872,39 @@ static void handle_tty_read(struct domain *dom)
>  static void handle_tty_write(struct domain *dom)
>  {
>  	ssize_t len;
> +	struct console *con = &dom->console;
>  
>  	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 handle_ring_read(struct domain *dom)
>  {
>  	xenevtchn_port_or_error_t port;
> +	struct console *con = &dom->console;
>  
>  	if (dom->is_dead)
>  		return;
>  
> -	if ((port = xenevtchn_pending(dom->xce_handle)) == -1)
> +	if ((port = xenevtchn_pending(con->xce_handle)) == -1)
>  		return;
>  
> -	dom->event_count++;
> +	con->event_count++;
>  
>  	buffer_append(dom);
>  
> -	if (dom->event_count < RATE_LIMIT_ALLOWANCE)
> -		(void)xenevtchn_unmask(dom->xce_handle, port);
> +	if (con->event_count < RATE_LIMIT_ALLOWANCE)
> +		(void)xenevtchn_unmask(con->xce_handle, port);
>  }
>  
>  static void handle_xs(void)
> @@ -948,9 +971,11 @@ 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);
> +			struct console *con = &d->console;
> +
> +			if (con->log_fd != -1)
> +				close(con->log_fd);
> +			con->log_fd = create_domain_log(d);
>  		}
>  	}
>  
> @@ -1059,48 +1084,52 @@ void handle_io(void)
>  		/* Re-calculate any event counter allowances & unblock
>  		   domains with new allowance */
>  		for (d = dom_head; d; d = d->next) {
> +			struct console *con = &d->console;
> +
>  			/* CS 16257:955ee4fa1345 introduces a 5ms fuzz
>  			 * for select(), it is not clear poll() has
>  			 * similar behavior (returning a couple of ms
>  			 * sooner than requested) as well. Just leave
>  			 * the fuzz here. Remove it with a separate
>  			 * patch if necessary */
> -			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);
> +			if ((now+5) > con->next_period) {
> +				con->next_period = now + RATE_LIMIT_PERIOD;
> +				if (con->event_count >= RATE_LIMIT_ALLOWANCE) {
> +					(void)xenevtchn_unmask(con->xce_handle, con->local_port);
>  				}
> -				d->event_count = 0;
> +				con->event_count = 0;
>  			}
>  		}
>  
>  		for (d = dom_head; d; d = d->next) {
> -			if (d->event_count >= RATE_LIMIT_ALLOWANCE) {
> +			struct console *con = &d->console;
> +
> +			if (con->event_count >= RATE_LIMIT_ALLOWANCE) {
>  				/* Determine if we're going to be the next time slice to expire */
>  				if (!next_timeout ||
> -				    d->next_period < next_timeout)
> -					next_timeout = d->next_period;
> -			} else if (d->xce_handle != NULL) {
> +				    con->next_period < next_timeout)
> +					next_timeout = con->next_period;
> +			} else if (con->xce_handle != NULL) {
>  				if (discard_overflowed_data ||
> -				    !d->buffer.max_capacity ||
> -				    d->buffer.size < d->buffer.max_capacity) {
> -					int evtchn_fd = xenevtchn_fd(d->xce_handle);
> -					d->xce_pollfd_idx = set_fds(evtchn_fd,
> +				    !con->buffer.max_capacity ||
> +				    con->buffer.size < con->buffer.max_capacity) {
> +					int evtchn_fd = xenevtchn_fd(con->xce_handle);
> +					con->xce_pollfd_idx = set_fds(evtchn_fd,
>  								    POLLIN|POLLPRI);
>  				}
>  			}
>  
> -			if (d->master_fd != -1) {
> +			if (con->master_fd != -1) {
>  				short events = 0;
>  				if (!d->is_dead && ring_free_bytes(d))
>  					events |= POLLIN;
>  
> -				if (!buffer_empty(&d->buffer))
> +				if (!buffer_empty(&con->buffer))
>  					events |= POLLOUT;
>  
>  				if (events)
> -					d->master_pollfd_idx =
> -						set_fds(d->master_fd,
> +					con->master_pollfd_idx =
> +						set_fds(con->master_fd,
>  							events|POLLPRI);
>  			}
>  		}
> @@ -1163,33 +1192,35 @@ void handle_io(void)
>  		}
>  
>  		for (d = dom_head; d; d = n) {
> +			struct console *con = &d->console;
> +
>  			n = d->next;
> -			if (d->event_count < RATE_LIMIT_ALLOWANCE) {
> -				if (d->xce_handle != NULL &&
> -				    d->xce_pollfd_idx != -1 &&
> -				    !(fds[d->xce_pollfd_idx].revents &
> +			if (con->event_count < RATE_LIMIT_ALLOWANCE) {
> +				if (con->xce_handle != NULL &&
> +				    con->xce_pollfd_idx != -1 &&
> +				    !(fds[con->xce_pollfd_idx].revents &
>  				      ~(POLLIN|POLLOUT|POLLPRI)) &&
> -				      (fds[d->xce_pollfd_idx].revents &
> +				      (fds[con->xce_pollfd_idx].revents &
>  				       POLLIN))
>  				    handle_ring_read(d);
>  			}
>  
> -			if (d->master_fd != -1 && d->master_pollfd_idx != -1) {
> -				if (fds[d->master_pollfd_idx].revents &
> +			if (con->master_fd != -1 && con->master_pollfd_idx != -1) {
> +				if (fds[con->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 &
> +					if (fds[con->master_pollfd_idx].revents &
>  					    POLLIN)
>  						handle_tty_read(d);
> -					if (fds[d->master_pollfd_idx].revents &
> +					if (fds[con->master_pollfd_idx].revents &
>  					    POLLOUT)
>  						handle_tty_write(d);
>  				}
>  			}
>  
> -			d->xce_pollfd_idx = d->master_pollfd_idx = -1;
> +			con->xce_pollfd_idx = con->master_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] 67+ messages in thread

* Re: [PATCH 11/17 v5] xen/arm: vpl011: Rename the console structure field conspath to xspath
  2017-06-22  7:38 ` [PATCH 11/17 v5] xen/arm: vpl011: Rename the console structure field conspath to xspath Bhupinder Thakur
@ 2017-06-22 23:21   ` Stefano Stabellini
  2017-06-28 17:16   ` Wei Liu
  1 sibling, 0 replies; 67+ messages in thread
From: Stefano Stabellini @ 2017-06-22 23:21 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, 22 Jun 2017, Bhupinder Thakur wrote:
> The console->conspath name is changed to console->xspath as it is
> clear from the name that it is referring to xenstore path.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>

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


> ---
> CC: Ian Jackson <ian.jackson@eu.citrix.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Stefano Stabellini <sstabellini@kernel.org>
> CC: Julien Grall <julien.grall@arm.com>
> 
> Changes since v4:
> - Split this change in a separate patch.
> 
>  tools/console/daemon/io.c | 30 +++++++++++++++---------------
>  1 file changed, 15 insertions(+), 15 deletions(-)
> 
> diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
> index 30cd167..6f5c69c 100644
> --- a/tools/console/daemon/io.c
> +++ b/tools/console/daemon/io.c
> @@ -95,7 +95,7 @@ struct console {
>  	int slave_fd;
>  	int log_fd;
>  	struct buffer buffer;
> -	char *conspath;
> +	char *xspath;
>  	int ring_ref;
>  	xenevtchn_handle *xce_handle;
>  	int xce_pollfd_idx;
> @@ -463,7 +463,7 @@ static int domain_create_tty(struct domain *dom)
>  		goto out;
>  	}
>  
> -	success = asprintf(&path, "%s/limit", con->conspath) !=
> +	success = asprintf(&path, "%s/limit", con->xspath) !=
>  		-1;
>  	if (!success)
>  		goto out;
> @@ -474,7 +474,7 @@ static int domain_create_tty(struct domain *dom)
>  	}
>  	free(path);
>  
> -	success = (asprintf(&path, "%s/tty", con->conspath) != -1);
> +	success = (asprintf(&path, "%s/tty", con->xspath) != -1);
>  	if (!success)
>  		goto out;
>  	success = xs_write(xs, XBT_NULL, path, slave, strlen(slave));
> @@ -546,14 +546,14 @@ static int domain_create_ring(struct domain *dom)
>  	char *type, path[PATH_MAX];
>  	struct console *con = &dom->console;
>  
> -	err = xs_gather(xs, con->conspath,
> +	err = xs_gather(xs, con->xspath,
>  			"ring-ref", "%u", &ring_ref,
>  			"port", "%i", &remote_port,
>  			NULL);
>  	if (err)
>  		goto out;
>  
> -	snprintf(path, sizeof(path), "%s/type", con->conspath);
> +	snprintf(path, sizeof(path), "%s/type", con->xspath);
>  	type = xs_read(xs, XBT_NULL, path, NULL);
>  	if (type && strcmp(type, "xenconsoled") != 0) {
>  		free(type);
> @@ -646,13 +646,13 @@ static bool watch_domain(struct domain *dom, bool watch)
>  
>  	snprintf(domid_str, sizeof(domid_str), "dom%u", dom->domid);
>  	if (watch) {
> -		success = xs_watch(xs, con->conspath, domid_str);
> +		success = xs_watch(xs, con->xspath, domid_str);
>  		if (success)
>  			domain_create_ring(dom);
>  		else
> -			xs_unwatch(xs, con->conspath, domid_str);
> +			xs_unwatch(xs, con->xspath, domid_str);
>  	} else {
> -		success = xs_unwatch(xs, con->conspath, domid_str);
> +		success = xs_unwatch(xs, con->xspath, domid_str);
>  	}
>  
>  	return success;
> @@ -682,13 +682,13 @@ static struct domain *create_domain(int domid)
>  	dom->domid = domid;
>  
>  	con = &dom->console;
> -	con->conspath = xs_get_domain_path(xs, dom->domid);
> -	s = realloc(con->conspath, strlen(con->conspath) +
> +	con->xspath = xs_get_domain_path(xs, dom->domid);
> +	s = realloc(con->xspath, strlen(con->xspath) +
>  		    strlen("/console") + 1);
>  	if (s == NULL)
>  		goto out;
> -	con->conspath = s;
> -	strcat(con->conspath, "/console");
> +	con->xspath = s;
> +	strcat(con->xspath, "/console");
>  
>  	con->master_fd = -1;
>  	con->master_pollfd_idx = -1;
> @@ -712,7 +712,7 @@ static struct domain *create_domain(int domid)
>  
>  	return dom;
>   out:
> -	free(con->conspath);
> +	free(con->xspath);
>  	free(dom);
>  	return NULL;
>  }
> @@ -756,8 +756,8 @@ static void cleanup_domain(struct domain *d)
>  	free(con->buffer.data);
>  	con->buffer.data = NULL;
>  
> -	free(con->conspath);
> -	con->conspath = NULL;
> +	free(con->xspath);
> +	con->xspath = NULL;
>  
>  	remove_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] 67+ messages in thread

* Re: [PATCH 13/17 v5] xen/arm: vpl011: Modify xenconsole to support multiple consoles
  2017-06-22  7:38 ` [PATCH 13/17 v5] xen/arm: vpl011: Modify xenconsole to support multiple consoles Bhupinder Thakur
@ 2017-06-22 23:51   ` Stefano Stabellini
  2017-06-28 17:16   ` Wei Liu
  1 sibling, 0 replies; 67+ messages in thread
From: Stefano Stabellini @ 2017-06-22 23:51 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, 22 Jun 2017, Bhupinder Thakur wrote:
> This patch adds the support for multiple consoles and introduces the iterator
> functions to operate on multiple consoles.
> 
> This patch is in preparation to support a new vuart console.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
> ---
> CC: Ian Jackson <ian.jackson@eu.citrix.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Stefano Stabellini <sstabellini@kernel.org>
> CC: Julien Grall <julien.grall@arm.com>
> 
> Changes since v4:
> - Changes to make event channel handling per console rather than per domain.
> 
> Changes since v3:
> - The changes in xenconsole have been split into four patches. This is the third patch.
> 
>  tools/console/daemon/io.c | 435 ++++++++++++++++++++++++++++++++--------------
>  1 file changed, 302 insertions(+), 133 deletions(-)
> 
> diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
> index a2a3496..baf0e2e 100644
> --- a/tools/console/daemon/io.c
> +++ b/tools/console/daemon/io.c
> @@ -90,12 +90,14 @@ struct buffer {
>  };
>  
>  struct console {
> +	char *ttyname;
>  	int master_fd;
>  	int master_pollfd_idx;
>  	int slave_fd;
>  	int log_fd;
>  	struct buffer buffer;
>  	char *xspath;
> +	char *log_suffix;
>  	int ring_ref;
>  	xenevtchn_handle *xce_handle;
>  	int xce_pollfd_idx;
> @@ -107,16 +109,112 @@ struct console {
>  	struct domain *d;
>  };
>  
> +struct console_data {
> +	char *xsname;
> +	char *ttyname;
> +	char *log_suffix;
> +};
> +
> +static struct console_data console_data[] = {
> +
> +	{
> +		.xsname = "/console",
> +		.ttyname = "tty",
> +		.log_suffix = "",
> +	},
> +};
> +
> +#define MAX_CONSOLE (sizeof(console_data)/sizeof(struct console_data))
> +
>  struct domain {
>  	int domid;
>  	bool is_dead;
>  	unsigned last_seen;
>  	struct domain *next;
> -	struct console console;
> +	struct console console[MAX_CONSOLE];
>  };
>  
>  static struct domain *dom_head;
>  
> +typedef void (*VOID_ITER_FUNC_ARG1)(struct console *);
> +typedef bool (*BOOL_ITER_FUNC_ARG1)(struct console *);
> +typedef int (*INT_ITER_FUNC_ARG1)(struct console *);
> +typedef void (*VOID_ITER_FUNC_ARG2)(struct console *,  void *);
> +typedef int (*INT_ITER_FUNC_ARG3)(struct console *,
> +			 struct domain *dom, void **);
> +
> +static inline bool console_enabled(struct console *con)
> +{
> +	return con->local_port != -1;
> +}
> +
> +static inline void console_iter_void_arg1(struct domain *d,
> +										  VOID_ITER_FUNC_ARG1 iter_func)
> +{
> +	int i = 0;
> +	struct console *con = &(d->console[0]);
> +
> +	for (i = 0; i < MAX_CONSOLE; i++, con++)
> +	{
> +		iter_func(con);
> +	}
> +}
> +
> +static inline void console_iter_void_arg2(struct domain *d,
> +										  VOID_ITER_FUNC_ARG2 iter_func,
> +										  void *iter_data)
> +{
> +	int i = 0;
> +	struct console *con = &(d->console[0]);
> +
> +	for (i = 0; i < MAX_CONSOLE; i++, con++)
> +	{
> +		iter_func(con, iter_data);
> +	}
> +}
> +
> +static inline bool console_iter_bool_arg1(struct domain *d,
> +										  BOOL_ITER_FUNC_ARG1 iter_func)
> +{
> +	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_int_arg1(struct domain *d,
> +										INT_ITER_FUNC_ARG1 iter_func)
> +{
> +	int i = 0;
> +	struct console *con = &(d->console[0]);
> +
> +	for (i = 0; i < MAX_CONSOLE; i++, con++)
> +	{
> +		if (iter_func(con))
> +			return 1;
> +	}
> +	return 0;
> +}
> +
> +static inline int console_iter_int_arg3(struct domain *d,
> +										INT_ITER_FUNC_ARG3 iter_func,
> +										void **iter_data)
> +{
> +	int i = 0;
> +	struct console *con = &(d->console[0]);
> +
> +	for (i = 0; i < MAX_CONSOLE; i++, con++)
> +	{
> +		if (iter_func(con, d, iter_data))
> +			return 1;
> +	}
> +	return 0;
> +}
>  static int write_all(int fd, const char* buf, size_t len)
>  {
>  	while (len) {
> @@ -163,12 +261,22 @@ static int write_with_timestamp(int fd, const char *data, size_t sz,
>  	return 0;
>  }
>  
> -static void buffer_append(struct console *con)
> +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, xenevtchn_port_or_error_t port)
>  {

it doesn't look like port is used anywhere here


>  	struct buffer *buffer = &con->buffer;
> +	struct xencons_interface *intf = con->interface;
>  	struct domain *dom = con->d;
>  	XENCONS_RING_IDX cons, prod, size;
> -	struct xencons_interface *intf = con->interface;

Spurious change?


>  	cons = intf->out_cons;
>  	prod = intf->out_prod;
> @@ -321,7 +429,7 @@ static int create_console_log(struct console *con)
>  		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, data, con->log_suffix);
>  	free(data);
>  	logfile[PATH_MAX-1] = '\0';
>  
> @@ -473,7 +581,7 @@ static int console_create_tty(struct console *con)
>  	}
>  	free(path);
>  
> -	success = (asprintf(&path, "%s/tty", con->xspath) != -1);
> +	success = (asprintf(&path, "%s/%s", con->xspath, con->ttyname) != -1);
>  	if (!success)
>  		goto out;
>  	success = xs_write(xs, XBT_NULL, path, slave, strlen(slave));
> @@ -594,6 +702,7 @@ static int console_create_ring(struct console *con)
>  
>  	con->local_port = -1;
>  	con->remote_port = -1;
> +
>  	if (con->xce_handle != NULL)
>  		xenevtchn_close(con->xce_handle);

Spurious change


> @@ -639,13 +748,13 @@ static bool watch_domain(struct domain *dom, bool watch)
>  {
>  	char domid_str[3 + MAX_STRLEN(dom->domid)];
>  	bool success;
> -	struct console *con = &dom->console;
> +	struct console *con = &dom->console[0];
>  
>  	snprintf(domid_str, sizeof(domid_str), "dom%u", dom->domid);
>  	if (watch) {
>  		success = xs_watch(xs, con->xspath, domid_str);
>  		if (success)
> -			console_create_ring(con);
> +			console_iter_int_arg1(dom, console_create_ring);
>  		else
>  			xs_unwatch(xs, con->xspath, domid_str);
>  	} else {
> @@ -655,20 +764,59 @@ static bool watch_domain(struct domain *dom, bool watch)
>  	return success;
>  }
>  
> -
> -static struct domain *create_domain(int domid)
> +static int console_init(struct console *con, struct domain *dom, void **data)
>  {
> -	struct domain *dom;
>  	char *s;
> +	int err = -1;
>  	struct timespec ts;
> -	struct console *con;
> +	struct console_data **con_data = (struct console_data **)data;
> +	char *xsname;
>  
>  	if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
>  		dolog(LOG_ERR, "Cannot get time of day %s:%s:L%d",
>  		      __FILE__, __FUNCTION__, __LINE__);
> -		return NULL;
> +		return err;
> +	}
> +
> +	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->xce_pollfd_idx = -1;
> +	con->next_period = ((long long)ts.tv_sec * 1000) + (ts.tv_nsec / 1000000) + RATE_LIMIT_PERIOD;
> +	con->d = dom;
> +	con->ttyname = (*con_data)->ttyname;
> +	con->log_suffix = (*con_data)->log_suffix;
> +	xsname = (*con_data)->xsname;
> +	con->xspath = xs_get_domain_path(xs, dom->domid);
> +	s = realloc(con->xspath, strlen(con->xspath) +
> +				strlen(xsname) + 1);
> +	if (s)
> +	{
> +		con->xspath = s;
> +		strcat(con->xspath, xsname);
> +		err = 0;
>  	}
>  
> +	(*con_data)++;
> +
> +	return err;
> +}
> +
> +static void console_free(struct console *con)
> +{
> +	if (con->xspath)
> +		free(con->xspath);
> +}
> +
> +static struct domain *create_domain(int domid)
> +{
> +	struct domain *dom;
> +	struct console_data *con_data = &console_data[0];
> +
>  	dom = calloc(1, sizeof *dom);
>  	if (dom == NULL) {
>  		dolog(LOG_ERR, "Out of memory %s:%s():L%d",
> @@ -678,27 +826,8 @@ static struct domain *create_domain(int domid)
>  
>  	dom->domid = domid;
>  
> -	con = &dom->console;
> -	con->xspath = xs_get_domain_path(xs, dom->domid);
> -	s = realloc(con->xspath, strlen(con->xspath) +
> -		    strlen("/console") + 1);
> -	if (s == NULL)
> +	if (console_iter_int_arg3(dom, console_init, (void **)&con_data))
>  		goto out;
> -	con->xspath = s;
> -	strcat(con->xspath, "/console");
> -
> -	con->master_fd = -1;
> -	con->master_pollfd_idx = -1;
> -	con->slave_fd = -1;
> -	con->log_fd = -1;
> -	con->xce_pollfd_idx = -1;
> -	con->d = dom;
> -
> -	con->next_period = ((long long)ts.tv_sec * 1000) + (ts.tv_nsec / 1000000) + RATE_LIMIT_PERIOD;
> -
> -	con->ring_ref = -1;
> -	con->local_port = -1;
> -	con->remote_port = -1;
>  
>  	if (!watch_domain(dom, true))
>  		goto out;
> @@ -710,7 +839,7 @@ static struct domain *create_domain(int domid)
>  
>  	return dom;
>   out:
> -	free(con->xspath);
> +	console_iter_void_arg1(dom, console_free);
>  	free(dom);
>  	return NULL;
>  }
> @@ -740,38 +869,51 @@ static void remove_domain(struct domain *dom)
>  	}
>  }
>  
> -static void cleanup_domain(struct domain *d)
> +static void console_cleanup(struct console *con)
>  {
> -	struct console *con = &d->console;
> -
> -	console_close_tty(con);
> -
>  	if (con->log_fd != -1) {
>  		close(con->log_fd);
>  		con->log_fd = -1;
>  	}
>  
> -	free(con->buffer.data);
> -	con->buffer.data = NULL;
> +	if (con->buffer.data)
> +	{
> +		free(con->buffer.data);
> +		con->buffer.data = NULL;
> +	}
> +
> +	if (con->xspath)
> +	{
> +		free(con->xspath);
> +		con->xspath = NULL;
> +	}
> +}
> +
> +static void cleanup_domain(struct domain *d)
> +{
> +	console_iter_void_arg1(d, console_close_tty);
>  
> -	free(con->xspath);
> -	con->xspath = NULL;
> +	console_iter_void_arg1(d, console_cleanup);
>  
>  	remove_domain(d);
>  }
>  
> -static void shutdown_domain(struct domain *d)
> +static void console_close_evtchn(struct console *con)
>  {
> -	struct console *con = &d->console;
> -
> -	d->is_dead = true;
> -	watch_domain(d, false);
> -	console_unmap_interface(con);
>  	if (con->xce_handle != NULL)
>  		xenevtchn_close(con->xce_handle);
> +
>  	con->xce_handle = NULL;
>  }
>  
> +static void shutdown_domain(struct domain *d)
> +{
> +	d->is_dead = true;
> +	watch_domain(d, false);
> +	console_iter_void_arg1(d, console_unmap_interface);
> +	console_iter_void_arg1(d, console_close_evtchn);
> +}
> +
>  static unsigned enum_pass = 0;
>  
>  static void enum_domains(void)
> @@ -885,12 +1027,32 @@ static void handle_tty_write(struct console *con)
>  	}
>  }
>  
> -static void handle_ring_read(struct domain *dom)
> +static void console_evtchn_unmask(struct console *con, void *data)
> +{
> +	long long now = (long long)data;
> +
> +	if (!console_enabled(con))
> +		return;
> +
> +	/* CS 16257:955ee4fa1345 introduces a 5ms fuzz
> +	 * for select(), it is not clear poll() has
> +	 * similar behavior (returning a couple of ms
> +	 * sooner than requested) as well. Just leave
> +	 * the fuzz here. Remove it with a separate
> +	 * patch if necessary */
> +	if ((now+5) > con->next_period) {
> +		con->next_period = now + RATE_LIMIT_PERIOD;
> +		if (con->event_count >= RATE_LIMIT_ALLOWANCE)
> +				(void)xenevtchn_unmask(con->xce_handle, con->local_port);
> +		con->event_count = 0;
> +	}
> +}
> +
> +static void handle_ring_read(struct console *con)
>  {
>  	xenevtchn_port_or_error_t port;
> -	struct console *con = &dom->console;
>  
> -	if (dom->is_dead)
> +	if (con->d->is_dead)
>  		return;
>  
>  	if ((port = xenevtchn_pending(con->xce_handle)) == -1)
> @@ -898,10 +1060,23 @@ static void handle_ring_read(struct domain *dom)
>  
>  	con->event_count++;
>  
> -	buffer_append(con);
> +	buffer_append(con, port);
>  
>  	if (con->event_count < RATE_LIMIT_ALLOWANCE)
> -		(void)xenevtchn_unmask(con->xce_handle, port);
> +		(void)xenevtchn_unmask(con->xce_handle, con->local_port);
> +}
> +
> +static void handle_console_ring(struct console *con)
> +{
> +	if (con->event_count < RATE_LIMIT_ALLOWANCE) {
> +		if (con->xce_handle != NULL &&
> +			con->xce_pollfd_idx != -1 &&
> +			!(fds[con->xce_pollfd_idx].revents &
> +			  ~(POLLIN|POLLOUT|POLLPRI)) &&
> +			  (fds[con->xce_pollfd_idx].revents &
> +			   POLLIN))
> +			handle_ring_read(con);
> +	}
>  }
>  
>  static void handle_xs(void)
> @@ -922,7 +1097,7 @@ static void handle_xs(void)
>  		/* We may get watches firing for domains that have recently
>  		   been removed, so dom may be NULL here. */
>  		if (dom && dom->is_dead == false)
> -			console_create_ring(&dom->console);
> +			console_iter_int_arg1(dom, console_create_ring);
>  	}
>  
>  	free(vec);
> @@ -963,16 +1138,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) {
> -			struct console *con = &d->console;
> -
> -			if (con->log_fd != -1)
> -				close(con->log_fd);
> -			con->log_fd = create_console_log(con);
> +			console_iter_void_arg1(d, console_open_log);
>  		}
>  	}
>  
> @@ -1024,6 +1205,62 @@ static void reset_fds(void)
>  		memset(fds, 0, sizeof(struct pollfd) * current_array_size);
>  }
>  
> +static void add_console_evtchn_fd(struct console *con, void *data)
> +{
> +	long long next_timeout = *((long long *)data);
> +
> +	if (con->event_count >= RATE_LIMIT_ALLOWANCE) {
> +		/* Determine if we're going to be the next time slice to expire */
> +		if (!next_timeout ||
> +			con->next_period < next_timeout)
> +			next_timeout = con->next_period;
> +	} else if (con->xce_handle != NULL) {
> +			if (buffer_available(con))
> +			{
> +				int evtchn_fd = xenevtchn_fd(con->xce_handle);
> +				con->xce_pollfd_idx = set_fds(evtchn_fd,
> +											  POLLIN|POLLPRI);
> +			}
> +		}
> +
> +	*((long long *)data) = next_timeout;
> +}
> +
> +static void add_console_tty_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 handle_console_tty(struct console *con)
> +{
> +	if (con->master_fd != -1 && con->master_pollfd_idx != -1) {
> +		if (fds[con->master_pollfd_idx].revents &
> +			~(POLLIN|POLLOUT|POLLPRI))
> +			console_handle_broken_tty(con, 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;
> +	con->xce_pollfd_idx = -1;
> +}
> +
>  void handle_io(void)
>  {
>  	int ret;
> @@ -1081,55 +1318,11 @@ void handle_io(void)
>  		/* Re-calculate any event counter allowances & unblock
>  		   domains with new allowance */
>  		for (d = dom_head; d; d = d->next) {
> -			struct console *con = &d->console;
> -
> -			/* CS 16257:955ee4fa1345 introduces a 5ms fuzz
> -			 * for select(), it is not clear poll() has
> -			 * similar behavior (returning a couple of ms
> -			 * sooner than requested) as well. Just leave
> -			 * the fuzz here. Remove it with a separate
> -			 * patch if necessary */
> -			if ((now+5) > con->next_period) {
> -				con->next_period = now + RATE_LIMIT_PERIOD;
> -				if (con->event_count >= RATE_LIMIT_ALLOWANCE) {
> -					(void)xenevtchn_unmask(con->xce_handle, con->local_port);
> -				}
> -				con->event_count = 0;
> -			}
> -		}
>  
> -		for (d = dom_head; d; d = d->next) {
> -			struct console *con = &d->console;
> -
> -			if (con->event_count >= RATE_LIMIT_ALLOWANCE) {
> -				/* Determine if we're going to be the next time slice to expire */
> -				if (!next_timeout ||
> -				    con->next_period < next_timeout)
> -					next_timeout = con->next_period;
> -			} else if (con->xce_handle != NULL) {
> -				if (discard_overflowed_data ||
> -				    !con->buffer.max_capacity ||
> -				    con->buffer.size < con->buffer.max_capacity) {
> -					int evtchn_fd = xenevtchn_fd(con->xce_handle);
> -					con->xce_pollfd_idx = set_fds(evtchn_fd,
> -								    POLLIN|POLLPRI);
> -				}
> -			}
> -
> -			if (con->master_fd != -1) {
> -				short events = 0;
> -				if (!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);
> -			}
> -		}
> +			console_iter_void_arg2(d, console_evtchn_unmask, (void *)now);
> +			console_iter_void_arg2(d, add_console_evtchn_fd, (void *)&next_timeout);
> +			console_iter_void_arg1(d, add_console_tty_fd);
> +        }
>  
>  		/* If any domain has been rate limited, we need to work
>  		   out what timeout to supply to poll */
> @@ -1189,35 +1382,11 @@ void handle_io(void)
>  		}
>  
>  		for (d = dom_head; d; d = n) {
> -			struct console *con = &d->console;
>  
>  			n = d->next;
> -			if (con->event_count < RATE_LIMIT_ALLOWANCE) {
> -				if (con->xce_handle != NULL &&
> -				    con->xce_pollfd_idx != -1 &&
> -				    !(fds[con->xce_pollfd_idx].revents &
> -				      ~(POLLIN|POLLOUT|POLLPRI)) &&
> -				      (fds[con->xce_pollfd_idx].revents &
> -				       POLLIN))
> -				    handle_ring_read(d);
> -			}
> -
> -			if (con->master_fd != -1 && con->master_pollfd_idx != -1) {
> -				if (fds[con->master_pollfd_idx].revents &
> -				    ~(POLLIN|POLLOUT|POLLPRI))
> -					console_handle_broken_tty(con,
> -						   domain_is_valid(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->xce_pollfd_idx = con->master_pollfd_idx = -1;
> +			console_iter_void_arg1(d, handle_console_ring);
> +			console_iter_void_arg1(d, handle_console_tty);
>  
>  			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] 67+ messages in thread

* Re: [PATCH 14/17 v5] xen/arm: vpl011: Add support for vuart console in xenconsole
  2017-06-22  7:38 ` [PATCH 14/17 v5] xen/arm: vpl011: Add support for vuart console in xenconsole Bhupinder Thakur
@ 2017-06-23  0:02   ` Stefano Stabellini
  2017-06-28 17:17   ` Wei Liu
  1 sibling, 0 replies; 67+ messages in thread
From: Stefano Stabellini @ 2017-06-23  0:02 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, 22 Jun 2017, Bhupinder Thakur wrote:
> This patch finally adds the support for vuart console.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
> ---
> CC: Ian Jackson <ian.jackson@eu.citrix.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Stefano Stabellini <sstabellini@kernel.org>
> CC: Julien Grall <julien.grall@arm.com>
> 
> Changes since v4:
> - Renamed VUART_CFLAGS- to CFLAGS_vuart- in the Makefile as per the convention.
> 
>  config/arm32.mk           |  1 +
>  config/arm64.mk           |  1 +
>  tools/console/Makefile    |  3 ++-
>  tools/console/daemon/io.c | 31 ++++++++++++++++++++++++++++++-
>  4 files changed, 34 insertions(+), 2 deletions(-)
> 
> diff --git a/config/arm32.mk b/config/arm32.mk
> index f95228e..b9f23fe 100644
> --- a/config/arm32.mk
> +++ b/config/arm32.mk
> @@ -1,5 +1,6 @@
>  CONFIG_ARM := y
>  CONFIG_ARM_32 := y
> +CONFIG_VUART_CONSOLE := y
>  CONFIG_ARM_$(XEN_OS) := y

I am tempted to disable this by default on arm32 (but leaving it
configurable via Kconfig maybe). Tipically arm32 cpus are not found on
server platforms, where SBSA compliance is important. Julien, what do
you think?


>  CONFIG_XEN_INSTALL_SUFFIX :=
> diff --git a/config/arm64.mk b/config/arm64.mk
> index aa45772..861d0a4 100644
> --- a/config/arm64.mk
> +++ b/config/arm64.mk
> @@ -1,5 +1,6 @@
>  CONFIG_ARM := y
>  CONFIG_ARM_64 := y
> +CONFIG_VUART_CONSOLE := y
>  CONFIG_ARM_$(XEN_OS) := y
>  
>  CONFIG_XEN_INSTALL_SUFFIX :=
> diff --git a/tools/console/Makefile b/tools/console/Makefile
> index c8b0300..1cddb6e 100644
> --- a/tools/console/Makefile
> +++ b/tools/console/Makefile
> @@ -11,6 +11,7 @@ LDLIBS += $(SOCKET_LIBS)
>  
>  LDLIBS_xenconsoled += $(UTIL_LIBS)
>  LDLIBS_xenconsoled += -lrt
> +CFLAGS_vuart-$(CONFIG_VUART_CONSOLE) = -DCONFIG_VUART_CONSOLE
>  
>  BIN      = xenconsoled xenconsole
>  
> @@ -28,7 +29,7 @@ clean:
>  distclean: clean
>  
>  daemon/main.o: daemon/_paths.h
> -daemon/io.o: CFLAGS += $(CFLAGS_libxenevtchn) $(CFLAGS_libxengnttab)
> +daemon/io.o: CFLAGS += $(CFLAGS_libxenevtchn) $(CFLAGS_libxengnttab) $(CFLAGS_vuart-y)
>  xenconsoled: $(patsubst %.c,%.o,$(wildcard daemon/*.c))
>  	$(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS) $(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_xenconsoled) $(APPEND_LDFLAGS)
>  
> diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
> index baf0e2e..6b0114e 100644
> --- a/tools/console/daemon/io.c
> +++ b/tools/console/daemon/io.c
> @@ -107,12 +107,16 @@ struct console {
>  	xenevtchn_port_or_error_t remote_port;
>  	struct xencons_interface *interface;
>  	struct domain *d;
> +	bool optional;
> +	bool prefer_gnttab;
>  };
>  
>  struct console_data {
>  	char *xsname;
>  	char *ttyname;
>  	char *log_suffix;
> +	bool optional;
> +	bool prefer_gnttab;
>  };
>  
>  static struct console_data console_data[] = {
> @@ -121,7 +125,18 @@ static struct console_data console_data[] = {
>  		.xsname = "/console",
>  		.ttyname = "tty",
>  		.log_suffix = "",
> +		.optional = false,
> +		.prefer_gnttab = true,
>  	},
> +#if defined(CONFIG_VUART_CONSOLE)
> +	{
> +		.xsname = "/vuart/0",
> +		.ttyname = "tty",
> +		.log_suffix = "-vuart0",
> +		.optional = true,
> +		.prefer_gnttab = false,
> +	},
> +#endif
>  };
>  
>  #define MAX_CONSOLE (sizeof(console_data)/sizeof(struct console_data))
> @@ -655,8 +670,18 @@ static int console_create_ring(struct console *con)
>  			"ring-ref", "%u", &ring_ref,
>  			"port", "%i", &remote_port,
>  			NULL);
> +
>  	if (err)
> +	{
> +		/*
> +		 * This is a normal condition for optional consoles: they might not be
> +		 * present on xenstore at all. In that case, just return without error.
> +		*/
> +		if (con->optional)
> +			err = 0;
> +
>  		goto out;
> +	}
>  
>  	snprintf(path, sizeof(path), "%s/type", con->xspath);
>  	type = xs_read(xs, XBT_NULL, path, NULL);
> @@ -670,7 +695,9 @@ static int console_create_ring(struct console *con)
>  	if (ring_ref != con->ring_ref && con->ring_ref != -1)
>  		console_unmap_interface(con);
>  
> -	if (!con->interface && xgt_handle) {
> +	if (!con->interface && 
> +		xgt_handle &&
> +		con->prefer_gnttab) {
>  		/* Prefer using grant table */
>  		con->interface = xengnttab_map_grant_ref(xgt_handle,
>  			dom->domid, GNTTAB_RESERVED_CONSOLE,
> @@ -790,6 +817,8 @@ static int console_init(struct console *con, struct domain *dom, void **data)
>  	con->d = dom;
>  	con->ttyname = (*con_data)->ttyname;
>  	con->log_suffix = (*con_data)->log_suffix;
> +	con->optional = (*con_data)->optional;
> +	con->prefer_gnttab = (*con_data)->prefer_gnttab;
>  	xsname = (*con_data)->xsname;
>  	con->xspath = xs_get_domain_path(xs, dom->domid);
>  	s = realloc(con->xspath, strlen(con->xspath) +
> -- 
> 2.7.4
> 

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

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

* Re: [PATCH 02/17 v5] xen/arm: vpl011: Rename vgic_reg* functions definitions and calls to vreg_reg*
  2017-06-22  7:38 ` [PATCH 02/17 v5] xen/arm: vpl011: Rename vgic_reg* functions definitions and calls to vreg_reg* Bhupinder Thakur
@ 2017-06-23  9:42   ` Julien Grall
  0 siblings, 0 replies; 67+ messages in thread
From: Julien Grall @ 2017-06-23  9:42 UTC (permalink / raw)
  To: Bhupinder Thakur, xen-devel; +Cc: Andre Przywara, Stefano Stabellini

Hi Bhupinder,

NIT: You could drop vpl011 in the commit message as this is not related 
to vpl011.

On 22/06/17 08:38, Bhupinder Thakur wrote:
> This patch renames the vgic_reg* access functions defined in vreg.h to vreg_reg*
> and replaces all calls to vgic_reg* functions in vgic/its emulation code to vreg_reg*.
>
> vreg_reg* are generic functions, which can be used to operate on 32/64-bit registers.
>
> SBSA UART emulation code will also use vreg_reg* access functions for
> accessing emulated pl011 registers.
>
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>

With the change in the commit title:

Reviewed-by: Julien Grall <julien.grall@arm.com>

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 00/17 v5] SBSA UART emulation support in Xen
  2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
                   ` (16 preceding siblings ...)
  2017-06-22  7:38 ` [PATCH 17/17 v5] xen/arm: vpl011: Update documentation for vuart console support Bhupinder Thakur
@ 2017-06-23 10:42 ` Julien Grall
  2017-06-23 17:58   ` Stefano Stabellini
  2017-07-04  7:31   ` Bhupinder Thakur
  17 siblings, 2 replies; 67+ messages in thread
From: Julien Grall @ 2017-06-23 10:42 UTC (permalink / raw)
  To: Bhupinder Thakur, xen-devel; +Cc: Wei Liu, Stefano Stabellini, Ian Jackson

Hi Bhupinder,

On 22/06/17 08:38, Bhupinder Thakur wrote:
> There are some TBD items which need to be looked at in the future:
>
> 1. Currently UEFI firmware logs the output to hvc console only. How can
>    UEFI firmware be made aware of pl011 console and how it can use it
>    as a console instead of hvc.

Would it be possible to summarize the discussions we had a couple of 
weeks ago here?

> 2. Linux seems to have hvc console as the default console i.e. if no
>    console is specified then it uses hvc as the console. How can an
>    option be provided in Linux to select either hvc or pl011 as the
>    default console.

I am wondering what would happen if you use stdout-path in the 
device-tree. Does it override the default console?

IHMO, the best way to select the default console would be using either 
the SPCR (for ACPI) or stdout-path (for DT). But the HVC console does 
not have any description in the firmware. It might be worth considering 
adding description.

The drawback is the user would always have to specify the console on the 
command line. I think this is not too bad for a first approach.

>
> 3. ACPI support for pl011 device.

I would be ok to defer this after PL011 series is merged.

> Bhupinder Thakur (17):
>   xen/arm: vpl011: Move vgic register access functions to vreg.h
>   xen/arm: vpl011: Rename vgic_reg* functions definitions and calls to
>     vreg_reg*

Stefano, would it be possible to commit those patches? They are both 
acked and it would avoid Bhupinder to carry them and rebase them if the 
vGIC code has changed.

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 04/17 v5] xen/arm: vpl011: Add SBSA UART emulation in Xen
  2017-06-22 22:53   ` Stefano Stabellini
@ 2017-06-23 12:33     ` Julien Grall
  2017-06-23 18:28       ` Stefano Stabellini
  0 siblings, 1 reply; 67+ messages in thread
From: Julien Grall @ 2017-06-23 12:33 UTC (permalink / raw)
  To: Stefano Stabellini, Bhupinder Thakur; +Cc: xen-devel, Andre Przywara

Hi Stefano,

On 22/06/17 23:53, Stefano Stabellini wrote:
> On Thu, 22 Jun 2017, Bhupinder Thakur wrote:
>> +static void vpl011_write_data(struct domain *d, uint8_t data)
>> +{
>> +    unsigned long flags;
>> +    struct vpl011 *vpl011 = &d->arch.vpl011;
>> +    struct xencons_interface *intf = vpl011->ring_buf;
>> +    XENCONS_RING_IDX out_cons, out_prod;
>> +
>> +    VPL011_LOCK(d, flags);
>> +
>> +    out_cons = intf->out_cons;
>> +    out_prod = intf->out_prod;
>> +
>> +    smp_rmb();
>
> This should be
>        smp_mb();

To speed up discussion, it would have been nice to give a bit more 
details why you think smp_rmb() is not enough.

In this case, I think smp_rmb() is fine because all the write we care 
depends on out_cons and out_prod. So the processor cannot re-order it.

>> +    /*
>> +     * It is expected that the ring is not full when this function is called
>> +     * as the guest is expected to write to the data register only when the
>> +     * TXFF flag is not set.
>> +     * In case the guest does write even when the TXFF flag is set then the
>> +     * data will be silently dropped.
>> +     */
>> +    if ( xencons_queued(out_prod, out_cons, sizeof(intf->out)) !=
>> +         sizeof (intf->out) )
>> +    {
>> +        intf->out[xencons_mask(out_prod, sizeof(intf->out))] = data;
>> +        out_prod += 1;
>> +        smp_wmb();
>> +        intf->out_prod = out_prod;
>> +    }
>> +    else
>> +        gprintk(XENLOG_ERR, "vpl011: Unexpected OUT ring buffer full\n");
>> +
>> +    if ( xencons_queued(out_prod, out_cons, sizeof(intf->out)) ==
>> +         sizeof (intf->out) )
>> +    {
>> +        vpl011->uartfr |= TXFF;
>> +        vpl011->uartris &= ~TXI;
>> +    }
>> +
>> +    vpl011->uartfr |= BUSY;
>> +
>> +    vpl011->uartfr &= ~TXFE;
>> +
>> +    vpl011_update_interrupt_status(d);
>> +
>> +    VPL011_UNLOCK(d, flags);
>> +
>> +    /*
>> +     * Send an event to console backend to indicate that there is
>> +     * data in the OUT ring buffer.
>> +     */
>> +    notify_via_xen_event_channel(d, vpl011->evtchn);
>> +}

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 04/17 v5] xen/arm: vpl011: Add SBSA UART emulation in Xen
  2017-06-22  7:38 ` [PATCH 04/17 v5] xen/arm: vpl011: Add SBSA UART emulation in Xen Bhupinder Thakur
  2017-06-22 22:53   ` Stefano Stabellini
@ 2017-06-23 13:10   ` Julien Grall
  1 sibling, 0 replies; 67+ messages in thread
From: Julien Grall @ 2017-06-23 13:10 UTC (permalink / raw)
  To: Bhupinder Thakur, xen-devel; +Cc: Andre Przywara, Stefano Stabellini

Hi Bhupinder,

On 22/06/17 08:38, 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
>
> This patch implements the SBSA Generic UART which is a subset of ARM
> PL011 UART.
>
> The SBSA Generic 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>
> ---
> CC: Stefano Stabellini <sstabellini@kernel.org>
> CC: Julien Grall <julien.grall@arm.com>
> CC: Andre Przywara <andre.przywara@arm.com>
>
> Changes since v4:
> - Renamed vpl011_update() to vpl011_update_interrupt_status() and added logic to avoid
>   raising spurious interrupts.
> - Used barrier instructions correctly while reading/writing data to the ring buffer.
> - Proper lock taken before reading ring buffer indices.
>
> Changes since v3:
> - Moved the call to DEFINE_XEN_FLEX_RING from vpl011.h to public/console.h. This macro defines
>   standard functions to operate on the ring buffer.
> - Lock taken while updating the interrupt mask and clear registers in mmio_write.
> - Use gfn_t instead of xen_pfn_t.
> - vgic_free_virq called if there is any error in vpl011 initialization.
> - mmio handlers freed if there is any error in vpl011 initialization.
> - Removed vpl011->initialized flag usage as the same check could be done
>   using vpl011->ring-ref.
> - Used return instead of break in the switch handling of emulation of different pl011 registers.
> - Renamed vpl011_update_spi() to vpl011_update().
>
> Changes since v2:
> - Use generic vreg_reg* for read/write of registers emulating pl011.
> - Use generic ring buffer functions defined using DEFINE_XEN_FLEX_RING.
> - Renamed the SPI injection function to vpl011_update_spi() to reflect level
>   triggered nature of pl011 interrupts.
> - The pl011 register access address should always be the base address of the
>   corresponding register as per section B of the SBSA document. For this reason,
>   the register range address access is not allowed.
>
> Changes since v1:
> - Removed the optimiztion related to sendiing events to xenconsole
> - Use local variables as ring buffer indices while using the ring buffer
>
>  xen/arch/arm/Kconfig             |   7 +
>  xen/arch/arm/Makefile            |   1 +
>  xen/arch/arm/vpl011.c            | 449 +++++++++++++++++++++++++++++++++++++++
>  xen/include/asm-arm/domain.h     |   6 +
>  xen/include/asm-arm/pl011-uart.h |   2 +
>  xen/include/asm-arm/vpl011.h     |  73 +++++++
>  xen/include/public/arch-arm.h    |   6 +
>  7 files changed, 544 insertions(+)
>  create mode 100644 xen/arch/arm/vpl011.c
>  create mode 100644 xen/include/asm-arm/vpl011.h
>
> diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
> index d46b98c..f58019d 100644
> --- a/xen/arch/arm/Kconfig
> +++ b/xen/arch/arm/Kconfig
> @@ -50,6 +50,13 @@ config HAS_ITS
>          prompt "GICv3 ITS MSI controller support" if EXPERT = "y"
>          depends on HAS_GICV3
>
> +config SBSA_VUART_CONSOLE
> +	bool "Emulated SBSA UART console support"
> +	default y
> +	---help---
> +	  Allows a guest to use SBSA Generic UART as a console. The
> +	  SBSA Generic UART implements a subset of ARM PL011 UART.
> +
>  endmenu
>
>  menu "ARM errata workaround via the alternative framework"
> diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
> index 49e1fb2..d9c6ebf 100644
> --- a/xen/arch/arm/Makefile
> +++ b/xen/arch/arm/Makefile
> @@ -50,6 +50,7 @@ obj-$(CONFIG_HAS_GICV3) += vgic-v3.o
>  obj-$(CONFIG_HAS_ITS) += vgic-v3-its.o
>  obj-y += vm_event.o
>  obj-y += vtimer.o
> +obj-$(CONFIG_SBSA_VUART_CONSOLE) += vpl011.o
>  obj-y += vpsci.o
>  obj-y += vuart.o
>
> diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> new file mode 100644
> index 0000000..db8651c
> --- /dev/null
> +++ b/xen/arch/arm/vpl011.c
> @@ -0,0 +1,449 @@
> +/*
> + * arch/arm/vpl011.c
> + *
> + * Virtual PL011 UART
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <xen/errno.h>
> +#include <xen/event.h>
> +#include <xen/guest_access.h>
> +#include <xen/init.h>
> +#include <xen/lib.h>
> +#include <xen/mm.h>
> +#include <xen/sched.h>
> +#include <public/domctl.h>
> +#include <public/io/console.h>
> +#include <asm-arm/pl011-uart.h>
> +#include <asm-arm/vgic-emul.h>

For both, you should use asm/ and not asm-arm/ as you did below.

> +#include <asm/vpl011.h>
> +
> +/*
> + * Since pl011 registers are 32-bit registers, all registers
> + * are handled similarly allowing 8-bit, 16-bit and 32-bit
> + * accesses except 64-bit access.
> + */
> +static bool vpl011_reg32_check_access(struct hsr_dabt dabt)
> +{
> +    return (dabt.size != DABT_DOUBLE_WORD);
> +}
> +
> +static void vpl011_update_interrupt_status(struct domain *d)
> +{
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +    uint32_t interrupt_status = vpl011->uartris & vpl011->uartimsc;

This function has to be called with the vuart lock taken, right? If so, 
please document it and add an ASSERT to check the lock has been taken.

> +
> +    /*
> +     * TODO: PL011 interrupts are level triggered which means
> +     * that interrupt needs to be set/clear instead of being
> +     * injected. However, currently vGIC does not handle level
> +     * triggered interrupts properly. This function needs to be
> +     * revisited once vGIC starts handling level triggered
> +     * interrupts.
> +     */
> +
> +    /*
> +     * Raise an interrupt only if any additional interrupt
> +     * status bit has been set since the last time.
> +     */
> +    if ( interrupt_status & ~vpl011->shadow_uartris )
> +        vgic_vcpu_inject_spi(d, GUEST_VPL011_SPI);
> +
> +    vpl011->shadow_uartris = interrupt_status;
> +}
> +
> +static uint8_t vpl011_read_data(struct domain *d)
> +{
> +    unsigned long flags;
> +    uint8_t data = 0;
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +    struct xencons_interface *intf = vpl011->ring_buf;
> +    XENCONS_RING_IDX in_cons, in_prod;
> +
> +    VPL011_LOCK(d, flags);
> +
> +    in_cons = intf->in_cons;
> +    in_prod = intf->in_prod;
> +
> +    smp_rmb();
> +
> +    /*
> +     * It is expected that there will be data in the ring buffer when this
> +     * function is called since the guest is expected to read the data register
> +     * only if the TXFE flag is not set.
> +     * If the guest still does read when TXFE bit is set then 0 will be returned.
> +     */
> +    if ( xencons_queued(in_prod, in_cons, sizeof(intf->in)) > 0 )
> +    {
> +        data = intf->in[xencons_mask(in_cons, sizeof(intf->in))];
> +        in_cons += 1;
> +        smp_mb();
> +        intf->in_cons = in_cons;
> +    }
> +    else
> +        gprintk(XENLOG_ERR, "vpl011: Unexpected IN ring buffer empty\n");
> +
> +    if ( xencons_queued(in_prod, in_cons, sizeof(intf->in)) == 0 )
> +    {
> +        vpl011->uartfr |= RXFE;
> +        vpl011->uartris &= ~RXI;
> +    }
> +
> +    vpl011->uartfr &= ~RXFF;
> +
> +    vpl011_update_interrupt_status(d);
> +
> +    VPL011_UNLOCK(d, flags);
> +
> +    /*
> +     * Send an event to console backend to indicate that data has been
> +     * read from the IN ring buffer.
> +     */
> +    notify_via_xen_event_channel(d, vpl011->evtchn);
> +
> +    return data;
> +}
> +
> +static void vpl011_write_data(struct domain *d, uint8_t data)
> +{
> +    unsigned long flags;
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +    struct xencons_interface *intf = vpl011->ring_buf;
> +    XENCONS_RING_IDX out_cons, out_prod;
> +
> +    VPL011_LOCK(d, flags);
> +
> +    out_cons = intf->out_cons;
> +    out_prod = intf->out_prod;
> +
> +    smp_rmb();
> +
> +    /*
> +     * It is expected that the ring is not full when this function is called
> +     * as the guest is expected to write to the data register only when the
> +     * TXFF flag is not set.
> +     * In case the guest does write even when the TXFF flag is set then the
> +     * data will be silently dropped.
> +     */
> +    if ( xencons_queued(out_prod, out_cons, sizeof(intf->out)) !=
> +         sizeof (intf->out) )
> +    {
> +        intf->out[xencons_mask(out_prod, sizeof(intf->out))] = data;
> +        out_prod += 1;
> +        smp_wmb();
> +        intf->out_prod = out_prod;
> +    }
> +    else
> +        gprintk(XENLOG_ERR, "vpl011: Unexpected OUT ring buffer full\n");
> +
> +    if ( xencons_queued(out_prod, out_cons, sizeof(intf->out)) ==
> +         sizeof (intf->out) )
> +    {
> +        vpl011->uartfr |= TXFF;
> +        vpl011->uartris &= ~TXI;
> +    }
> +
> +    vpl011->uartfr |= BUSY;
> +
> +    vpl011->uartfr &= ~TXFE;
> +
> +    vpl011_update_interrupt_status(d);
> +
> +    VPL011_UNLOCK(d, flags);
> +
> +    /*
> +     * Send an event to console backend to indicate that there is
> +     * data in the OUT ring buffer.
> +     */
> +    notify_via_xen_event_channel(d, vpl011->evtchn);
> +}
> +
> +static int vpl011_mmio_read(struct vcpu *v,
> +                            mmio_info_t *info,
> +                            register_t *r,
> +                            void *priv)
> +{
> +    struct hsr_dabt dabt = info->dabt;
> +    uint32_t vpl011_reg = (uint32_t)(info->gpa - GUEST_PL011_BASE);
> +    struct vpl011 *vpl011 = &v->domain->arch.vpl011;
> +    struct domain *d = v->domain;
> +    unsigned long flags;
> +
> +    switch ( vpl011_reg )
> +    {
> +    case DR:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        *r = vreg_reg32_extract(vpl011_read_data(d), info);
> +        return 1;
> +
> +    case RSR:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        /* It always returns 0 as there are no physical errors. */
> +        *r = 0;
> +        return 1;
> +
> +    case FR:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        VPL011_LOCK(d, flags);
> +        *r = vreg_reg32_extract(vpl011->uartfr, info);
> +        VPL011_UNLOCK(d, flags);
> +        return 1;
> +
> +    case RIS:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        VPL011_LOCK(d, flags);
> +        *r = vreg_reg32_extract(vpl011->uartris, info);
> +        VPL011_UNLOCK(d, flags);
> +        return 1;
> +
> +    case MIS:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        VPL011_LOCK(d, flags);
> +        *r = vreg_reg32_extract(vpl011->uartris & vpl011->uartimsc,
> +                                info);
> +        VPL011_UNLOCK(d, flags);
> +        return 1;
> +
> +    case IMSC:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        VPL011_LOCK(d, flags);
> +        *r = vreg_reg32_extract(vpl011->uartimsc, info);
> +        VPL011_UNLOCK(d, flags);
> +        return 1;
> +
> +    case ICR:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        /* Only write is valid. */
> +        return 0;
> +
> +    default:
> +        gprintk(XENLOG_ERR, "vpl011: unhandled read r%d offset %#08x\n",
> +                dabt.reg, vpl011_reg);
> +        return 0;
> +    }
> +
> +    return 1;
> +
> +bad_width:
> +    gprintk(XENLOG_ERR, "vpl011: bad read width %d r%d offset %#08x\n",
> +            dabt.size, dabt.reg, vpl011_reg);
> +    domain_crash_synchronous();
> +    return 0;
> +
> +}
> +
> +static int vpl011_mmio_write(struct vcpu *v,
> +                             mmio_info_t *info,
> +                             register_t r,
> +                             void *priv)
> +{
> +    struct hsr_dabt dabt = info->dabt;
> +    uint32_t vpl011_reg = (uint32_t)(info->gpa - GUEST_PL011_BASE);
> +    struct vpl011 *vpl011 = &v->domain->arch.vpl011;
> +    struct domain *d = v->domain;
> +    unsigned long flags;
> +
> +    switch ( vpl011_reg )
> +    {
> +    case DR:
> +    {
> +        uint32_t data = 0;
> +
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        vreg_reg32_update(&data, r, info);

I dislike the idea of relying on implicit cast between function. This is 
a call for error. Please retain the data &= 0xFF here.

> +        vpl011_write_data(v->domain, data);
> +        return 1;
> +    }

NIT: newline here.

> +    case RSR: /* Nothing to clear. */
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        return 1;
> +
> +    case FR:
> +    case RIS:
> +    case MIS:
> +        goto write_ignore;
> +
> +    case IMSC:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        VPL011_LOCK(d, flags);
> +        vreg_reg32_update(&vpl011->uartimsc, r, info);
> +        vpl011_update_interrupt_status(v->domain);
> +        VPL011_UNLOCK(d, flags);
> +        return 1;
> +
> +    case ICR:
> +        if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> +
> +        VPL011_LOCK(d, flags);
> +        vreg_reg32_clearbits(&vpl011->uartris, r, info);
> +        vpl011_update_interrupt_status(d);
> +        VPL011_UNLOCK(d, flags);
> +        return 1;
> +
> +    default:
> +        gprintk(XENLOG_ERR, "vpl011: unhandled write r%d offset %#08x\n",
> +                dabt.reg, vpl011_reg);
> +        return 0;
> +    }
> +
> +write_ignore:
> +    return 1;
> +
> +bad_width:
> +    gprintk(XENLOG_ERR, "vpl011: bad write width %d r%d offset %#08x\n",
> +            dabt.size, dabt.reg, vpl011_reg);
> +    domain_crash_synchronous();
> +    return 0;
> +
> +}
> +
> +static const struct mmio_handler_ops vpl011_mmio_handler = {
> +    .read = vpl011_mmio_read,
> +    .write = vpl011_mmio_write,
> +};
> +
> +static void vpl011_data_avail(struct domain *d)
> +{
> +    unsigned long flags;
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +    struct xencons_interface *intf = vpl011->ring_buf;
> +    XENCONS_RING_IDX in_cons, in_prod, out_cons, out_prod;
> +    XENCONS_RING_IDX in_ring_qsize, out_ring_qsize;
> +
> +    VPL011_LOCK(d, flags);
> +
> +    in_cons = intf->in_cons;
> +    in_prod = intf->in_prod;
> +    out_cons = intf->out_cons;
> +    out_prod = intf->out_prod;
> +
> +    smp_rmb();
> +
> +    in_ring_qsize = xencons_queued(in_prod,
> +                                   in_cons,
> +                                   sizeof(intf->in));
> +
> +    out_ring_qsize = xencons_queued(out_prod,
> +                                    out_cons,
> +                                    sizeof(intf->out));
> +
> +    /* Update the uart rx state if the buffer is not empty. */
> +    if ( in_ring_qsize != 0 )
> +    {
> +        vpl011->uartfr &= ~RXFE;
> +        if ( in_ring_qsize == sizeof(intf->in) )
> +            vpl011->uartfr |= RXFF;
> +        vpl011->uartris |= RXI;
> +    }
> +
> +    /* Update the uart tx state if the buffer is not full. */
> +    if ( out_ring_qsize != sizeof(intf->out) )
> +    {
> +        vpl011->uartfr &= ~TXFF;
> +        vpl011->uartris |= TXI;
> +        if ( out_ring_qsize == 0 )
> +        {
> +            vpl011->uartfr &= ~BUSY;
> +            vpl011->uartfr |= TXFE;
> +        }
> +    }
> +
> +    vpl011_update_interrupt_status(d);
> +
> +    VPL011_UNLOCK(d, flags);
> +}
> +
> +

NIT: One newline is enough. Please drop one.

> +static void vpl011_notification(struct vcpu *v, unsigned int port)
> +{
> +    vpl011_data_avail(v->domain);
> +}
> +
> +int domain_vpl011_init(struct domain *d, struct vpl011_init_info *info)
> +{
> +    int rc;
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +
> +    if ( vpl011->ring_buf )
> +        return -EINVAL;
> +
> +    /* Map the guest PFN to Xen address space. */
> +    rc =  prepare_ring_for_helper(d,
> +                                  gfn_x(info->gfn),
> +                                  &vpl011->ring_page,
> +                                  &vpl011->ring_buf);
> +    if ( rc < 0 )
> +        goto out;
> +
> +    rc = vgic_reserve_virq(d, GUEST_VPL011_SPI);
> +    if ( !rc )
> +    {
> +        rc = -EINVAL;
> +        goto out1;
> +    }
> +
> +    rc = alloc_unbound_xen_event_channel(d, 0, info->console_domid,
> +                                         vpl011_notification);
> +    if ( rc < 0 )
> +        goto out2;
> +
> +    vpl011->evtchn = info->evtchn = rc;
> +
> +    spin_lock_init(&vpl011->lock);
> +
> +    register_mmio_handler(d, &vpl011_mmio_handler,
> +                          GUEST_PL011_BASE, GUEST_PL011_SIZE, NULL);
> +
> +    return 0;
> +
> +out2:
> +    vgic_free_virq(d, GUEST_VPL011_SPI);
> +
> +out1:
> +    destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
> +
> +out:
> +    return rc;
> +}
> +
> +void domain_vpl011_deinit(struct domain *d)
> +{
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +
> +    if ( !vpl011->ring_buf )
> +        return;
> +
> +    free_xen_event_channel(d, vpl011->evtchn);
> +    destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
> +    xfree(d->arch.vmmio.handlers);
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
> index 8dfc1d1..1a1145d 100644
> --- a/xen/include/asm-arm/domain.h
> +++ b/xen/include/asm-arm/domain.h
> @@ -11,6 +11,7 @@
>  #include <public/hvm/params.h>
>  #include <xen/serial.h>
>  #include <xen/rbtree.h>
> +#include <asm-arm/vpl011.h>
>
>  struct hvm_domain
>  {
> @@ -145,6 +146,11 @@ struct arch_domain
>      struct {
>          uint8_t privileged_call_enabled : 1;
>      } monitor;
> +
> +#ifdef CONFIG_SBSA_VUART_CONSOLE
> +    struct vpl011 vpl011;
> +#endif
> +
>  }  __cacheline_aligned;
>
>  struct arch_vcpu
> diff --git a/xen/include/asm-arm/pl011-uart.h b/xen/include/asm-arm/pl011-uart.h
> index 123f477..57e9ec7 100644
> --- a/xen/include/asm-arm/pl011-uart.h
> +++ b/xen/include/asm-arm/pl011-uart.h
> @@ -49,6 +49,8 @@
>  /* FR bits */
>  #define TXFE   (1<<7) /* TX FIFO empty */
>  #define RXFE   (1<<4) /* RX FIFO empty */
> +#define TXFF   (1<<5) /* TX FIFO full */
> +#define RXFF   (1<<6) /* RX FIFO full */
>  #define BUSY   (1<<3) /* Transmit is not complete */
>
>  /* LCR_H bits */
> diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
> new file mode 100644
> index 0000000..f1c6716
> --- /dev/null
> +++ b/xen/include/asm-arm/vpl011.h
> @@ -0,0 +1,73 @@
> +/*
> + * include/xen/vpl011.h
> + *
> + * Virtual PL011 UART
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef _VPL011_H_
> +#define _VPL011_H_
> +
> +#include <public/domctl.h>
> +#include <public/io/ring.h>
> +#include <asm-arm/vreg.h>

#include <asm/vreg.h>

> +#include <xen/mm.h>
> +
> +/* helper macros */
> +#define VPL011_LOCK(d,flags) spin_lock_irqsave(&(d)->arch.vpl011.lock, flags)
> +#define VPL011_UNLOCK(d,flags) spin_unlock_irqrestore(&(d)->arch.vpl011.lock, flags)
> +
> +struct vpl011 {
> +    void *ring_buf;
> +    struct page_info *ring_page;
> +    uint32_t    uartfr;         /* Flag register */
> +    uint32_t    uartcr;         /* Control register */
> +    uint32_t    uartimsc;       /* Interrupt mask register*/
> +    uint32_t    uarticr;        /* Interrupt clear register */
> +    uint32_t    uartris;        /* Raw interrupt status register */
> +    uint32_t    shadow_uartris; /* shadowed Raw interrupt status register */

I think this comment is wrong and the name. You don't store uartris but 
uartis & uartimsc.

> +    uint32_t    uartmis;        /* Masked interrupt register */

> +    spinlock_t  lock;
> +    evtchn_port_t evtchn;
> +};
> +
> +struct vpl011_init_info {
> +    uint32_t console_domid;
> +    gfn_t gfn;
> +    evtchn_port_t evtchn;
> +};
> +
> +#ifdef CONFIG_SBSA_VUART_CONSOLE
> +int domain_vpl011_init(struct domain *d,
> +                       struct vpl011_init_info *info);
> +void domain_vpl011_deinit(struct domain *d);
> +#else
> +static inline int domain_vpl011_init(struct domain *d,
> +                                     struct vpl011_init_info *info)
> +{
> +    return -ENOSYS;
> +}
> +
> +static inline void domain_vpl011_deinit(struct domain *d) { }
> +#endif
> +#endif

NIT: #endif /* _VPL011_H_ */

> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
> index bd974fb..85ab665 100644
> --- a/xen/include/public/arch-arm.h
> +++ b/xen/include/public/arch-arm.h
> @@ -410,6 +410,10 @@ typedef uint64_t xen_callback_t;
>  #define GUEST_ACPI_BASE 0x20000000ULL
>  #define GUEST_ACPI_SIZE 0x02000000ULL
>
> +/* PL011 mappings */
> +#define GUEST_PL011_BASE    0x22000000ULL
> +#define GUEST_PL011_SIZE    0x00001000ULL
> +
>  /*
>   * 16MB == 4096 pages reserved for guest to use as a region to map its
>   * grant table in.
> @@ -444,6 +448,8 @@ typedef uint64_t xen_callback_t;
>  #define GUEST_TIMER_PHYS_NS_PPI 30
>  #define GUEST_EVTCHN_PPI        31
>
> +#define GUEST_VPL011_SPI        32
> +
>  /* PSCI functions */
>  #define PSCI_cpu_suspend 0
>  #define PSCI_cpu_off     1
>

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 07/17 v5] xen/arm: vpl011: Rearrange xen header includes in alphabetical order in domctl.c
  2017-06-22 22:58   ` Stefano Stabellini
@ 2017-06-23 13:14     ` Julien Grall
  0 siblings, 0 replies; 67+ messages in thread
From: Julien Grall @ 2017-06-23 13:14 UTC (permalink / raw)
  To: Stefano Stabellini, Bhupinder Thakur; +Cc: xen-devel

Hi,

On 22/06/17 23:58, Stefano Stabellini wrote:
> On Thu, 22 Jun 2017, Bhupinder Thakur wrote:
>> Rearrange xen header includes in alphabetical order in domctl.c.
>>
>> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
>
> Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
>
>> ---
>> CC: Stefano Stabellini <sstabellini@kernel.org>
>> CC: Julien Grall <julien.grall@arm.com>
>>
>>  xen/arch/arm/domctl.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
>> index 971caec..86fa102 100644
>> --- a/xen/arch/arm/domctl.c
>> +++ b/xen/arch/arm/domctl.c
>> @@ -5,11 +5,11 @@
>>   */
>>
>>  #include <xen/types.h>

The headers still not in alphabetical order. xen/types.h is not at the 
correct place. If there is any reason why it is not done, it should be 
said in the commit message.

>> -#include <xen/lib.h>
>>  #include <xen/errno.h>
>> -#include <xen/sched.h>
>>  #include <xen/hypercall.h>
>>  #include <xen/iocap.h>
>> +#include <xen/lib.h>
>> +#include <xen/sched.h>
>>  #include <xsm/xsm.h>
>>  #include <public/domctl.h>
>>
>> --
>> 2.7.4
>>

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 08/17 v5] xen/arm: vpl011: Add a new domctl API to initialize vpl011
  2017-06-22 23:04   ` Stefano Stabellini
@ 2017-06-23 13:17     ` Julien Grall
  2017-06-23 13:25       ` Julien Grall
  0 siblings, 1 reply; 67+ messages in thread
From: Julien Grall @ 2017-06-23 13:17 UTC (permalink / raw)
  To: Stefano Stabellini, Bhupinder Thakur; +Cc: xen-devel, Ian Jackson, Wei Liu



On 23/06/17 00:04, Stefano Stabellini wrote:
>> diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
>> index 1629f41..26f3d1e 100644
>> --- a/tools/libxc/include/xenctrl.h
>> +++ b/tools/libxc/include/xenctrl.h
>> @@ -885,6 +885,26 @@ int xc_vcpu_getcontext(xc_interface *xch,
>>                         uint32_t vcpu,
>>                         vcpu_guest_context_any_t *ctxt);
>>
>> +#if defined (__arm__) || defined(__aarch64__)
>> +/**
>> + * This function initializes the vpl011 emulation and returns
>> + * the event to be used by the backend for communicating with
>> + * the emulation code.
>> + *
>> + * @parm xch a handle to an open hypervisor interface
>> + * @parm domid the domain to get information from
>> + * @parm console_domid the domid of the backend console
>> + * @parm gfn the guest pfn to be used as the ring buffer
>> + * @parm evtchn the event channel to be used for events
>> + * @return 0 on success, negative error on failure
>> + */
>> +int xc_dom_vpl011_init(xc_interface *xch,
>> +                       uint32_t domid,
>> +                       uint32_t console_domid,
>> +                       xen_pfn_t gfn,
>> +                       evtchn_port_t *evtchn);
>> +#endif
>
> Actually, the pattern is to define the xc_ function on all architecture
> but only return ENOSYS where it's not implemented, see
> xc_vcpu_get_extstate.

Well, I think the main reason behind if to avoid dummy call to the 
hypervisor. But effectively the hypervisor will return a proper error.

As the call is not made in common code, I would make this function 
compile on all the platform (there are nothing arch specific in it).

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 08/17 v5] xen/arm: vpl011: Add a new domctl API to initialize vpl011
  2017-06-23 13:17     ` Julien Grall
@ 2017-06-23 13:25       ` Julien Grall
  2017-06-23 17:57         ` Stefano Stabellini
  2017-06-27 13:43         ` Bhupinder Thakur
  0 siblings, 2 replies; 67+ messages in thread
From: Julien Grall @ 2017-06-23 13:25 UTC (permalink / raw)
  To: Stefano Stabellini, Bhupinder Thakur; +Cc: xen-devel, Ian Jackson, Wei Liu



On 23/06/17 14:17, Julien Grall wrote:
>
>
> On 23/06/17 00:04, Stefano Stabellini wrote:
>>> diff --git a/tools/libxc/include/xenctrl.h
>>> b/tools/libxc/include/xenctrl.h
>>> index 1629f41..26f3d1e 100644
>>> --- a/tools/libxc/include/xenctrl.h
>>> +++ b/tools/libxc/include/xenctrl.h
>>> @@ -885,6 +885,26 @@ int xc_vcpu_getcontext(xc_interface *xch,
>>>                         uint32_t vcpu,
>>>                         vcpu_guest_context_any_t *ctxt);
>>>
>>> +#if defined (__arm__) || defined(__aarch64__)
>>> +/**
>>> + * This function initializes the vpl011 emulation and returns
>>> + * the event to be used by the backend for communicating with
>>> + * the emulation code.
>>> + *
>>> + * @parm xch a handle to an open hypervisor interface
>>> + * @parm domid the domain to get information from
>>> + * @parm console_domid the domid of the backend console
>>> + * @parm gfn the guest pfn to be used as the ring buffer
>>> + * @parm evtchn the event channel to be used for events
>>> + * @return 0 on success, negative error on failure
>>> + */
>>> +int xc_dom_vpl011_init(xc_interface *xch,
>>> +                       uint32_t domid,
>>> +                       uint32_t console_domid,
>>> +                       xen_pfn_t gfn,
>>> +                       evtchn_port_t *evtchn);
>>> +#endif
>>
>> Actually, the pattern is to define the xc_ function on all architecture
>> but only return ENOSYS where it's not implemented, see
>> xc_vcpu_get_extstate.
>
> Well, I think the main reason behind if to avoid dummy call to the
> hypervisor. But effectively the hypervisor will return a proper error.

Actually, looking at the public header. This is because 
vcpu_get_extstate structure is only available on x86. Whereas 
vpl011_init is available for all the architecture even though only ARM 
effectively implementing it.

But my point stands below, there is no harm to implement it for x86 as 
it would compile on any platform.

>
> As the call is not made in common code, I would make this function
> compile on all the platform (there are nothing arch specific in it).

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 08/17 v5] xen/arm: vpl011: Add a new domctl API to initialize vpl011
  2017-06-22  7:38 ` [PATCH 08/17 v5] xen/arm: vpl011: Add a new domctl API to initialize vpl011 Bhupinder Thakur
  2017-06-22 23:04   ` Stefano Stabellini
@ 2017-06-23 13:26   ` Julien Grall
  2017-06-28 17:16   ` Wei Liu
  2 siblings, 0 replies; 67+ messages in thread
From: Julien Grall @ 2017-06-23 13:26 UTC (permalink / raw)
  To: Bhupinder Thakur, xen-devel; +Cc: Wei Liu, Stefano Stabellini, Ian Jackson

Hi Bhupinder,

On 22/06/17 08:38, Bhupinder Thakur wrote:
> diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
> index f7cbc0a..0da8aa6 100644
> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -36,6 +36,7 @@
>  #include "grant_table.h"
>  #include "hvm/save.h"
>  #include "memory.h"
> +#include "event_channel.h"
>
>  #define XEN_DOMCTL_INTERFACE_VERSION 0x0000000e
>
> @@ -1138,6 +1139,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_INIT_VPL011  0

Sorry, it just occurred to me that you are using VPL011 in the command 
name. I think requiring a command per new uart is a bit too much.

If we were to support new UART, I would expect a field to tell the type 
of the UART. Otherwise every time we add a new command, we would have 
one per UART.

DOMCTL can be modified later one. But I would like to get the interface 
right as we did in other place.

> +        uint32_t cmd;           /* XEN_DOMCTL_VUART_OP_* */
> +        uint32_t console_domid; /* IN */
> +        xen_pfn_t gfn;          /* IN */
> +        evtchn_port_t evtchn;   /* OUT */

I would be useful if you document the structure. The first two are 
pretty much straightforward, but gfn and evtchn are less.

> +};
> +
>  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 +1228,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 +1291,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] 67+ messages in thread

* Re: [PATCH 08/17 v5] xen/arm: vpl011: Add a new domctl API to initialize vpl011
  2017-06-23 13:25       ` Julien Grall
@ 2017-06-23 17:57         ` Stefano Stabellini
  2017-06-27 13:43         ` Bhupinder Thakur
  1 sibling, 0 replies; 67+ messages in thread
From: Stefano Stabellini @ 2017-06-23 17:57 UTC (permalink / raw)
  To: Julien Grall
  Cc: Bhupinder Thakur, xen-devel, Stefano Stabellini, Ian Jackson, Wei Liu

On Fri, 23 Jun 2017, Julien Grall wrote:
> On 23/06/17 14:17, Julien Grall wrote:
> > 
> > 
> > On 23/06/17 00:04, Stefano Stabellini wrote:
> > > > diff --git a/tools/libxc/include/xenctrl.h
> > > > b/tools/libxc/include/xenctrl.h
> > > > index 1629f41..26f3d1e 100644
> > > > --- a/tools/libxc/include/xenctrl.h
> > > > +++ b/tools/libxc/include/xenctrl.h
> > > > @@ -885,6 +885,26 @@ int xc_vcpu_getcontext(xc_interface *xch,
> > > >                         uint32_t vcpu,
> > > >                         vcpu_guest_context_any_t *ctxt);
> > > > 
> > > > +#if defined (__arm__) || defined(__aarch64__)
> > > > +/**
> > > > + * This function initializes the vpl011 emulation and returns
> > > > + * the event to be used by the backend for communicating with
> > > > + * the emulation code.
> > > > + *
> > > > + * @parm xch a handle to an open hypervisor interface
> > > > + * @parm domid the domain to get information from
> > > > + * @parm console_domid the domid of the backend console
> > > > + * @parm gfn the guest pfn to be used as the ring buffer
> > > > + * @parm evtchn the event channel to be used for events
> > > > + * @return 0 on success, negative error on failure
> > > > + */
> > > > +int xc_dom_vpl011_init(xc_interface *xch,
> > > > +                       uint32_t domid,
> > > > +                       uint32_t console_domid,
> > > > +                       xen_pfn_t gfn,
> > > > +                       evtchn_port_t *evtchn);
> > > > +#endif
> > > 
> > > Actually, the pattern is to define the xc_ function on all architecture
> > > but only return ENOSYS where it's not implemented, see
> > > xc_vcpu_get_extstate.
> > 
> > Well, I think the main reason behind if to avoid dummy call to the
> > hypervisor. But effectively the hypervisor will return a proper error.
> 
> Actually, looking at the public header. This is because vcpu_get_extstate
> structure is only available on x86. Whereas vpl011_init is available for all
> the architecture even though only ARM effectively implementing it.
> 
> But my point stands below, there is no harm to implement it for x86 as it
> would compile on any platform.

Sounds good to me


> > 
> > As the call is not made in common code, I would make this function
> > compile on all the platform (there are nothing arch specific in it).
 

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

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

* Re: [PATCH 00/17 v5] SBSA UART emulation support in Xen
  2017-06-23 10:42 ` [PATCH 00/17 v5] SBSA UART emulation support in Xen Julien Grall
@ 2017-06-23 17:58   ` Stefano Stabellini
  2017-07-04  7:31   ` Bhupinder Thakur
  1 sibling, 0 replies; 67+ messages in thread
From: Stefano Stabellini @ 2017-06-23 17:58 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Wei Liu, Ian Jackson, Bhupinder Thakur, xen-devel

On Fri, 23 Jun 2017, Julien Grall wrote:
> Hi Bhupinder,
> 
> On 22/06/17 08:38, Bhupinder Thakur wrote:
> > There are some TBD items which need to be looked at in the future:
> > 
> > 1. Currently UEFI firmware logs the output to hvc console only. How can
> >    UEFI firmware be made aware of pl011 console and how it can use it
> >    as a console instead of hvc.
> 
> Would it be possible to summarize the discussions we had a couple of weeks ago
> here?
> 
> > 2. Linux seems to have hvc console as the default console i.e. if no
> >    console is specified then it uses hvc as the console. How can an
> >    option be provided in Linux to select either hvc or pl011 as the
> >    default console.
> 
> I am wondering what would happen if you use stdout-path in the device-tree.
> Does it override the default console?
> 
> IHMO, the best way to select the default console would be using either the
> SPCR (for ACPI) or stdout-path (for DT). But the HVC console does not have any
> description in the firmware. It might be worth considering adding description.
> 
> The drawback is the user would always have to specify the console on the
> command line. I think this is not too bad for a first approach.
> 
> > 
> > 3. ACPI support for pl011 device.
> 
> I would be ok to defer this after PL011 series is merged.
> 
> > Bhupinder Thakur (17):
> >   xen/arm: vpl011: Move vgic register access functions to vreg.h
> >   xen/arm: vpl011: Rename vgic_reg* functions definitions and calls to
> >     vreg_reg*
> 
> Stefano, would it be possible to commit those patches? They are both acked and
> it would avoid Bhupinder to carry them and rebase them if the vGIC code has
> changed.

Sure

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

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

* Re: [PATCH 04/17 v5] xen/arm: vpl011: Add SBSA UART emulation in Xen
  2017-06-23 12:33     ` Julien Grall
@ 2017-06-23 18:28       ` Stefano Stabellini
  2017-06-23 19:58         ` Julien Grall
  0 siblings, 1 reply; 67+ messages in thread
From: Stefano Stabellini @ 2017-06-23 18:28 UTC (permalink / raw)
  To: Julien Grall
  Cc: Bhupinder Thakur, xen-devel, Stefano Stabellini, Andre Przywara

On Fri, 23 Jun 2017, Julien Grall wrote:
> Hi Stefano,
> 
> On 22/06/17 23:53, Stefano Stabellini wrote:
> > On Thu, 22 Jun 2017, Bhupinder Thakur wrote:
> > > +static void vpl011_write_data(struct domain *d, uint8_t data)
> > > +{
> > > +    unsigned long flags;
> > > +    struct vpl011 *vpl011 = &d->arch.vpl011;
> > > +    struct xencons_interface *intf = vpl011->ring_buf;
> > > +    XENCONS_RING_IDX out_cons, out_prod;
> > > +
> > > +    VPL011_LOCK(d, flags);
> > > +
> > > +    out_cons = intf->out_cons;
> > > +    out_prod = intf->out_prod;
> > > +
> > > +    smp_rmb();
> > 
> > This should be
> >        smp_mb();
> 
> To speed up discussion, it would have been nice to give a bit more details why
> you think smp_rmb() is not enough.
> 
> In this case, I think smp_rmb() is fine because all the write we care depends
> on out_cons and out_prod. So the processor cannot re-order it.

We discussed these barriers at length when I published the pvcalls and
xen 9pfs protocols, see for example
alpine.DEB.2.10.1612021318340.2777@sstabellini-ThinkPad-X260. Please
refer to "Ring Usage" in docs/misc/9pfs.markdown and "Workflow" in
docs/misc/pvcalls.markdown. I would like to keep them consistent across
protocols (the console protocol works exactly like pvcalls and xen 9pfs
in that respect).


> > > +    /*
> > > +     * It is expected that the ring is not full when this function is
> > > called
> > > +     * as the guest is expected to write to the data register only when
> > > the
> > > +     * TXFF flag is not set.
> > > +     * In case the guest does write even when the TXFF flag is set then
> > > the
> > > +     * data will be silently dropped.
> > > +     */
> > > +    if ( xencons_queued(out_prod, out_cons, sizeof(intf->out)) !=
> > > +         sizeof (intf->out) )
> > > +    {
> > > +        intf->out[xencons_mask(out_prod, sizeof(intf->out))] = data;
> > > +        out_prod += 1;
> > > +        smp_wmb();
> > > +        intf->out_prod = out_prod;
> > > +    }
> > > +    else
> > > +        gprintk(XENLOG_ERR, "vpl011: Unexpected OUT ring buffer full\n");
> > > +
> > > +    if ( xencons_queued(out_prod, out_cons, sizeof(intf->out)) ==
> > > +         sizeof (intf->out) )
> > > +    {
> > > +        vpl011->uartfr |= TXFF;
> > > +        vpl011->uartris &= ~TXI;
> > > +    }
> > > +
> > > +    vpl011->uartfr |= BUSY;
> > > +
> > > +    vpl011->uartfr &= ~TXFE;
> > > +
> > > +    vpl011_update_interrupt_status(d);
> > > +
> > > +    VPL011_UNLOCK(d, flags);
> > > +
> > > +    /*
> > > +     * Send an event to console backend to indicate that there is
> > > +     * data in the OUT ring buffer.
> > > +     */
> > > +    notify_via_xen_event_channel(d, vpl011->evtchn);
> > > +}
> 
> Cheers,
> 
> -- 
> Julien Grall
> 

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

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

* Re: [PATCH 04/17 v5] xen/arm: vpl011: Add SBSA UART emulation in Xen
  2017-06-23 18:28       ` Stefano Stabellini
@ 2017-06-23 19:58         ` Julien Grall
  0 siblings, 0 replies; 67+ messages in thread
From: Julien Grall @ 2017-06-23 19:58 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Bhupinder Thakur, xen-devel, Andre Przywara

Hi,

On 06/23/2017 07:28 PM, Stefano Stabellini wrote:
> On Fri, 23 Jun 2017, Julien Grall wrote:
>> Hi Stefano,
>>
>> On 22/06/17 23:53, Stefano Stabellini wrote:
>>> On Thu, 22 Jun 2017, Bhupinder Thakur wrote:
>>>> +static void vpl011_write_data(struct domain *d, uint8_t data)
>>>> +{
>>>> +    unsigned long flags;
>>>> +    struct vpl011 *vpl011 = &d->arch.vpl011;
>>>> +    struct xencons_interface *intf = vpl011->ring_buf;
>>>> +    XENCONS_RING_IDX out_cons, out_prod;
>>>> +
>>>> +    VPL011_LOCK(d, flags);
>>>> +
>>>> +    out_cons = intf->out_cons;
>>>> +    out_prod = intf->out_prod;
>>>> +
>>>> +    smp_rmb();
>>>
>>> This should be
>>>         smp_mb();
>>
>> To speed up discussion, it would have been nice to give a bit more details why
>> you think smp_rmb() is not enough.
>>
>> In this case, I think smp_rmb() is fine because all the write we care depends
>> on out_cons and out_prod. So the processor cannot re-order it.
> 
> We discussed these barriers at length when I published the pvcalls and
> xen 9pfs protocols, see for example
> alpine.DEB.2.10.1612021318340.2777@sstabellini-ThinkPad-X260. Please
> refer to "Ring Usage" in docs/misc/9pfs.markdown and "Workflow" in
> docs/misc/pvcalls.markdown. I would like to keep them consistent across
> protocols (the console protocol works exactly like pvcalls and xen 9pfs
> in that respect).

None of the people involved in this series were CCed on this thread and 
looking at docs/misc/9pfs.markdown or docs/misc/pvcalls.markdown to 
check what barrier usage for all the PV protocols seem a bit odd...

Anyway, you should probably think of writing a common PV document to 
avoid similar question in the future.

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 08/17 v5] xen/arm: vpl011: Add a new domctl API to initialize vpl011
  2017-06-23 13:25       ` Julien Grall
  2017-06-23 17:57         ` Stefano Stabellini
@ 2017-06-27 13:43         ` Bhupinder Thakur
  2017-06-27 13:57           ` Julien Grall
  1 sibling, 1 reply; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-27 13:43 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, Stefano Stabellini, Ian Jackson, Wei Liu

Hi Julien,

>>>> +#if defined (__arm__) || defined(__aarch64__)
>>>> +/**
>>>> + * This function initializes the vpl011 emulation and returns
>>>> + * the event to be used by the backend for communicating with
>>>> + * the emulation code.
>>>> + *
>>>> + * @parm xch a handle to an open hypervisor interface
>>>> + * @parm domid the domain to get information from
>>>> + * @parm console_domid the domid of the backend console
>>>> + * @parm gfn the guest pfn to be used as the ring buffer
>>>> + * @parm evtchn the event channel to be used for events
>>>> + * @return 0 on success, negative error on failure
>>>> + */
>>>> +int xc_dom_vpl011_init(xc_interface *xch,
>>>> +                       uint32_t domid,
>>>> +                       uint32_t console_domid,
>>>> +                       xen_pfn_t gfn,
>>>> +                       evtchn_port_t *evtchn);
>>>> +#endif
>>>
>>>
>>> Actually, the pattern is to define the xc_ function on all architecture
>>> but only return ENOSYS where it's not implemented, see
>>> xc_vcpu_get_extstate.
>>
>>
>> Well, I think the main reason behind if to avoid dummy call to the
>> hypervisor. But effectively the hypervisor will return a proper error.
>
>
> Actually, looking at the public header. This is because vcpu_get_extstate
> structure is only available on x86. Whereas vpl011_init is available for all
> the architecture even though only ARM effectively implementing it.
>
> But my point stands below, there is no harm to implement it for x86 as it
> would compile on any platform.
>
>
>>
>> As the call is not made in common code, I would make this function
>> compile on all the platform (there are nothing arch specific in it).

Currently, xc_dom_vpl011_init() is called only if info->arch_arm.vuart
flag is true. This check may look a bit odd in the
common code.

Regards,
Bhupinder

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

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

* Re: [PATCH 08/17 v5] xen/arm: vpl011: Add a new domctl API to initialize vpl011
  2017-06-27 13:43         ` Bhupinder Thakur
@ 2017-06-27 13:57           ` Julien Grall
  0 siblings, 0 replies; 67+ messages in thread
From: Julien Grall @ 2017-06-27 13:57 UTC (permalink / raw)
  To: Bhupinder Thakur; +Cc: xen-devel, Stefano Stabellini, Ian Jackson, Wei Liu



On 27/06/17 14:43, Bhupinder Thakur wrote:
> Hi Julien,

Hi Bhupinder,

>
>>>>> +#if defined (__arm__) || defined(__aarch64__)
>>>>> +/**
>>>>> + * This function initializes the vpl011 emulation and returns
>>>>> + * the event to be used by the backend for communicating with
>>>>> + * the emulation code.
>>>>> + *
>>>>> + * @parm xch a handle to an open hypervisor interface
>>>>> + * @parm domid the domain to get information from
>>>>> + * @parm console_domid the domid of the backend console
>>>>> + * @parm gfn the guest pfn to be used as the ring buffer
>>>>> + * @parm evtchn the event channel to be used for events
>>>>> + * @return 0 on success, negative error on failure
>>>>> + */
>>>>> +int xc_dom_vpl011_init(xc_interface *xch,
>>>>> +                       uint32_t domid,
>>>>> +                       uint32_t console_domid,
>>>>> +                       xen_pfn_t gfn,
>>>>> +                       evtchn_port_t *evtchn);
>>>>> +#endif
>>>>
>>>>
>>>> Actually, the pattern is to define the xc_ function on all architecture
>>>> but only return ENOSYS where it's not implemented, see
>>>> xc_vcpu_get_extstate.
>>>
>>>
>>> Well, I think the main reason behind if to avoid dummy call to the
>>> hypervisor. But effectively the hypervisor will return a proper error.
>>
>>
>> Actually, looking at the public header. This is because vcpu_get_extstate
>> structure is only available on x86. Whereas vpl011_init is available for all
>> the architecture even though only ARM effectively implementing it.
>>
>> But my point stands below, there is no harm to implement it for x86 as it
>> would compile on any platform.
>>
>>
>>>
>>> As the call is not made in common code, I would make this function
>>> compile on all the platform (there are nothing arch specific in it).
>
> Currently, xc_dom_vpl011_init() is called only if info->arch_arm.vuart
> flag is true. This check may look a bit odd in the
> common code.

I am not asking to call xc_dom_vpl011_init from common code. I am only 
asking to make this function available for anyone.

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 03/17 v5] xen/arm: vpl011: Define common ring buffer helper functions in console.h
  2017-06-22  7:38 ` [PATCH 03/17 v5] xen/arm: vpl011: Define common ring buffer helper functions in console.h Bhupinder Thakur
  2017-06-22 22:36   ` Stefano Stabellini
@ 2017-06-28 17:16   ` Wei Liu
  1 sibling, 0 replies; 67+ messages in thread
From: Wei Liu @ 2017-06-28 17:16 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: Stefano Stabellini, Wei Liu, Ian Jackson, Julien Grall, xen-devel

On Thu, Jun 22, 2017 at 01:08:38PM +0530, Bhupinder Thakur wrote:
> DEFINE_XEN_FLEX_RING(xencons) defines common helper functions such as
> xencons_queued() to tell the current size of the ring buffer,
> xencons_mask() to mask off the index, which are useful helper functions.
> pl011 emulation code will use these helper functions.
> 
> io/consol.h includes io/ring.h which defines DEFINE_XEN_FLEX_RING.
> 
> In console/daemon/io.c, string.h had to be included before io/console.h
> because ring.h uses string functions.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>

Acked-by: Wei Liu <wei.liu2@citrix.com>

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

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

* Re: [PATCH 06/17 v5] xen/arm: vpl011: Add support for vuart in libxl
  2017-06-22  7:38 ` [PATCH 06/17 v5] xen/arm: vpl011: Add support for vuart in libxl Bhupinder Thakur
  2017-06-22 22:57   ` Stefano Stabellini
@ 2017-06-28 17:16   ` Wei Liu
  1 sibling, 0 replies; 67+ messages in thread
From: Wei Liu @ 2017-06-28 17:16 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, Jun 22, 2017 at 01:08:41PM +0530, Bhupinder Thakur wrote:
> An option is provided in libxl to enable/disable sbsa vuart while
> creating a guest domain.
> 
> Libxl now suppots a generic vuart console and sbsa uart is a specific type.
> In future support can be added for multiple vuart of different types.
> 
> User can enable sbsa vuart by adding the following line in the guest
> configuration file:
> 
> vuart = "sbsa_uart"
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>

Acked-by: Wei Liu <wei.liu2@citrix.com>

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

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

* Re: [PATCH 08/17 v5] xen/arm: vpl011: Add a new domctl API to initialize vpl011
  2017-06-22  7:38 ` [PATCH 08/17 v5] xen/arm: vpl011: Add a new domctl API to initialize vpl011 Bhupinder Thakur
  2017-06-22 23:04   ` Stefano Stabellini
  2017-06-23 13:26   ` Julien Grall
@ 2017-06-28 17:16   ` Wei Liu
  2 siblings, 0 replies; 67+ messages in thread
From: Wei Liu @ 2017-06-28 17:16 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, Jun 22, 2017 at 01:08:43PM +0530, Bhupinder Thakur wrote:
[...]
> +#if defined (__arm__) || defined(__aarch64__)
> +/**
> + * This function initializes the vpl011 emulation and returns
> + * the event to be used by the backend for communicating with
> + * the emulation code.
> + *
> + * @parm xch a handle to an open hypervisor interface
> + * @parm domid the domain to get information from
> + * @parm console_domid the domid of the backend console
> + * @parm gfn the guest pfn to be used as the ring buffer
> + * @parm evtchn the event channel to be used for events
> + * @return 0 on success, negative error on failure
> + */
> +int xc_dom_vpl011_init(xc_interface *xch,
> +                       uint32_t domid,
> +                       uint32_t console_domid,

Use domid_t please.

> +                       xen_pfn_t gfn,
> +                       evtchn_port_t *evtchn);
> +#endif
> +
[...]
>  }
>  
> +int libxl__arch_build_dom_finish(libxl__gc *gc,
> +                                 libxl_domain_build_info *info,
> +                                 struct xc_dom_image *dom,
> +                                 libxl__domain_build_state *state)
> +{
> +    int ret = 0;
> +
> +    if ( info->arch_arm.vuart ) {

Coding style issues here and in a lot of other places in libxl.

> +        ret = xc_dom_vpl011_init(CTX->xch,
> +                                 dom->guest_domid,
> +                                 dom->console_domid,
> +                                 dom->vuart_gfn,
> +                                 &state->vuart_port);
> +        if ( ret < 0 )
> +        {
> +            LOG(ERROR, "xc_dom_vpl011_init failed\n");
> +        }

It is just one line so you can omit {}.

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

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

* Re: [PATCH 09/17 v5] xen/arm: vpl011: Add a new vuart node in the xenstore
  2017-06-22  7:38 ` [PATCH 09/17 v5] xen/arm: vpl011: Add a new vuart node in the xenstore Bhupinder Thakur
  2017-06-22 23:06   ` Stefano Stabellini
@ 2017-06-28 17:16   ` Wei Liu
  1 sibling, 0 replies; 67+ messages in thread
From: Wei Liu @ 2017-06-28 17:16 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, Jun 22, 2017 at 01:08:44PM +0530, Bhupinder Thakur wrote:
> Add a new vuart console node to xenstore. This node is added at
> 
> /local/domain/$DOMID/vuart/0.
> 
> The node contains information such as the ring-ref, event channel,
> buffer limit and type of console.
> 
> Xenconsole reads the node information to setup the ring buffer and
> event channel for sending/receiving vuart data.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>

Acked-by: Wei Liu <wei.liu2@citrix.com>

Only one nit below.

[...]
> diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
> index bffbc45..cfd85ec 100644
> --- a/tools/libxl/libxl_create.c
> +++ b/tools/libxl/libxl_create.c
> @@ -1367,7 +1367,7 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev,
>      }
>      case LIBXL_DOMAIN_TYPE_PV:
>      {
> -        libxl__device_console console;
> +        libxl__device_console console, vuart;
>          libxl__device device;
>  
>          for (i = 0; i < d_config->num_vfbs; i++) {
> @@ -1375,6 +1375,14 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev,
>              libxl__device_vkb_add(gc, domid, &d_config->vkbs[i]);
>          }
>  
> +        if (d_config->b_info.arch_arm.vuart)
> +        {

Please move this to previous line.

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

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

* Re: [PATCH 10/17 v5] xen/arm: vpl011: Modify xenconsole to define and use a new console structure
  2017-06-22  7:38 ` [PATCH 10/17 v5] xen/arm: vpl011: Modify xenconsole to define and use a new console structure Bhupinder Thakur
  2017-06-22 23:20   ` Stefano Stabellini
@ 2017-06-28 17:16   ` Wei Liu
  1 sibling, 0 replies; 67+ messages in thread
From: Wei Liu @ 2017-06-28 17:16 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, Jun 22, 2017 at 01:08:45PM +0530, Bhupinder Thakur wrote:
> Xenconsole uses a domain structure which contains console specific fields. This
> patch defines a new console structure, which would be used by the xenconsole
> functions to perform console specific operations like reading/writing data from/to
> the console ring buffer or reading/writing data from/to console tty.
> 
> This patch is in preparation to support multiple consoles to support vuart console.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>

Acked-by: Wei Liu <wei.liu2@citrix.com>

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

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

* Re: [PATCH 11/17 v5] xen/arm: vpl011: Rename the console structure field conspath to xspath
  2017-06-22  7:38 ` [PATCH 11/17 v5] xen/arm: vpl011: Rename the console structure field conspath to xspath Bhupinder Thakur
  2017-06-22 23:21   ` Stefano Stabellini
@ 2017-06-28 17:16   ` Wei Liu
  1 sibling, 0 replies; 67+ messages in thread
From: Wei Liu @ 2017-06-28 17:16 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, Jun 22, 2017 at 01:08:46PM +0530, Bhupinder Thakur wrote:
> The console->conspath name is changed to console->xspath as it is
> clear from the name that it is referring to xenstore path.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>

Acked-by: Wei Liu <wei.liu2@citrix.com>

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

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

* Re: [PATCH 12/17 v5] xen/arm: vpl011: Modify xenconsole functions to take console structure as input
  2017-06-22  7:38 ` [PATCH 12/17 v5] xen/arm: vpl011: Modify xenconsole functions to take console structure as input Bhupinder Thakur
@ 2017-06-28 17:16   ` Wei Liu
  0 siblings, 0 replies; 67+ messages in thread
From: Wei Liu @ 2017-06-28 17:16 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, Jun 22, 2017 at 01:08:47PM +0530, Bhupinder Thakur wrote:
> Xenconsole functions take domain structure as input. These functions shall be
> modified to take console structure as input since these functions typically perform
> console specific operations.
> 
> Also the console specific functions starting with prefix "domain_" shall be modified
> to "console_" to indicate that these are console specific functions.
> 
> This patch is in preparation to support multiple consoles to support vuart console.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
> Acked-by: Stefano Stabellini <sstabellini@kernel.org>

Acked-by: Wei Liu <wei.liu2@citrix.com>

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

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

* Re: [PATCH 13/17 v5] xen/arm: vpl011: Modify xenconsole to support multiple consoles
  2017-06-22  7:38 ` [PATCH 13/17 v5] xen/arm: vpl011: Modify xenconsole to support multiple consoles Bhupinder Thakur
  2017-06-22 23:51   ` Stefano Stabellini
@ 2017-06-28 17:16   ` Wei Liu
  2017-07-07 13:52     ` Bhupinder Thakur
  1 sibling, 1 reply; 67+ messages in thread
From: Wei Liu @ 2017-06-28 17:16 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, Jun 22, 2017 at 01:08:48PM +0530, Bhupinder Thakur wrote:
> This patch adds the support for multiple consoles and introduces the iterator
> functions to operate on multiple consoles.
> 
> This patch is in preparation to support a new vuart console.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
> ---
> CC: Ian Jackson <ian.jackson@eu.citrix.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Stefano Stabellini <sstabellini@kernel.org>
> CC: Julien Grall <julien.grall@arm.com>
> 
> Changes since v4:
> - Changes to make event channel handling per console rather than per domain.
> 
> Changes since v3:
> - The changes in xenconsole have been split into four patches. This is the third patch.
> 
>  tools/console/daemon/io.c | 435 ++++++++++++++++++++++++++++++++--------------
>  1 file changed, 302 insertions(+), 133 deletions(-)
> 
> diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
> index a2a3496..baf0e2e 100644
> --- a/tools/console/daemon/io.c
> +++ b/tools/console/daemon/io.c
> @@ -90,12 +90,14 @@ struct buffer {
>  };
>  
>  struct console {
> +	char *ttyname;
>  	int master_fd;
>  	int master_pollfd_idx;
>  	int slave_fd;
>  	int log_fd;
>  	struct buffer buffer;
>  	char *xspath;
> +	char *log_suffix;

I suppose both new fields can be const.

>  	int ring_ref;
>  	xenevtchn_handle *xce_handle;
>  	int xce_pollfd_idx;
> @@ -107,16 +109,112 @@ struct console {
>  	struct domain *d;
>  };
>  
> +struct console_data {
> +	char *xsname;
> +	char *ttyname;
> +	char *log_suffix;

const for all three.

> +};
> +
> +static struct console_data console_data[] = {
> +

Stray line.

> +	{
> +		.xsname = "/console",
> +		.ttyname = "tty",
> +		.log_suffix = "",
> +	},
> +};
> +
> +#define MAX_CONSOLE (sizeof(console_data)/sizeof(struct console_data))
> +
>  struct domain {
>  	int domid;
>  	bool is_dead;
>  	unsigned last_seen;
>  	struct domain *next;
> -	struct console console;
> +	struct console console[MAX_CONSOLE];
>  };
>  
>  static struct domain *dom_head;
>  
> +typedef void (*VOID_ITER_FUNC_ARG1)(struct console *);
> +typedef bool (*BOOL_ITER_FUNC_ARG1)(struct console *);
> +typedef int (*INT_ITER_FUNC_ARG1)(struct console *);
> +typedef void (*VOID_ITER_FUNC_ARG2)(struct console *,  void *);
> +typedef int (*INT_ITER_FUNC_ARG3)(struct console *,
> +			 struct domain *dom, void **);
> +
> +static inline bool console_enabled(struct console *con)
> +{
> +	return con->local_port != -1;
> +}
> +
> +static inline void console_iter_void_arg1(struct domain *d,
> +										  VOID_ITER_FUNC_ARG1 iter_func)

Too many tabs here and below?

You might want to configure your editor to display tab as 8 spaces.

> +{
> +	int i = 0;
> +	struct console *con = &(d->console[0]);
> +

No need to have the (), I think.

> -static struct domain *create_domain(int domid)
> +static int console_init(struct console *con, struct domain *dom, void **data)
>  {
> -	struct domain *dom;
>  	char *s;
> +	int err = -1;
>  	struct timespec ts;
> -	struct console *con;
> +	struct console_data **con_data = (struct console_data **)data;
> +	char *xsname;
>  
>  	if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
>  		dolog(LOG_ERR, "Cannot get time of day %s:%s:L%d",
>  		      __FILE__, __FUNCTION__, __LINE__);
> -		return NULL;
> +		return err;
> +	}
> +

There is a danger that you return at this point, the cleanup path in
caller will free garbage.

I suggest you at least initialise all pointers to NULL at the beginning.

> +	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->xce_pollfd_idx = -1;
> +	con->next_period = ((long long)ts.tv_sec * 1000) + (ts.tv_nsec / 1000000) + RATE_LIMIT_PERIOD;
> +	con->d = dom;
> +	con->ttyname = (*con_data)->ttyname;
> +	con->log_suffix = (*con_data)->log_suffix;
> +	xsname = (*con_data)->xsname;
> +	con->xspath = xs_get_domain_path(xs, dom->domid);
> +	s = realloc(con->xspath, strlen(con->xspath) +
> +				strlen(xsname) + 1);
> +	if (s)
> +	{
> +		con->xspath = s;
> +		strcat(con->xspath, xsname);
> +		err = 0;
>  	}
>  
> +	(*con_data)++;
> +
> +	return err;
> +}
> +
> +
[...]
> +static void handle_console_ring(struct console *con)
> +{
> +	if (con->event_count < RATE_LIMIT_ALLOWANCE) {
> +		if (con->xce_handle != NULL &&
> +			con->xce_pollfd_idx != -1 &&
> +			!(fds[con->xce_pollfd_idx].revents &
> +			  ~(POLLIN|POLLOUT|POLLPRI)) &&
> +			  (fds[con->xce_pollfd_idx].revents &
> +			   POLLIN))
> +			handle_ring_read(con);
> +	}

Refactoring like this should go to its own patch(es).

It is currently very hard to review this patch because refactoring is
mixed with all the iterator changes.

I can't really continue at this point. Sorry. Please split the
refactoring of all the buffer_* and handle_console_* functions to
separate patches.

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

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

* Re: [PATCH 14/17 v5] xen/arm: vpl011: Add support for vuart console in xenconsole
  2017-06-22  7:38 ` [PATCH 14/17 v5] xen/arm: vpl011: Add support for vuart console in xenconsole Bhupinder Thakur
  2017-06-23  0:02   ` Stefano Stabellini
@ 2017-06-28 17:17   ` Wei Liu
  1 sibling, 0 replies; 67+ messages in thread
From: Wei Liu @ 2017-06-28 17:17 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, Jun 22, 2017 at 01:08:49PM +0530, Bhupinder Thakur wrote:
> This patch finally adds the support for vuart console.
> 
[...]
>  
> diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
> index baf0e2e..6b0114e 100644
> --- a/tools/console/daemon/io.c
> +++ b/tools/console/daemon/io.c
> @@ -107,12 +107,16 @@ struct console {
>  	xenevtchn_port_or_error_t remote_port;
>  	struct xencons_interface *interface;
>  	struct domain *d;
> +	bool optional;
> +	bool prefer_gnttab;

Please state in commit message or code comment what these two fields do
and how they are supposed to be set?

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

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

* Re: [PATCH 15/17 v5] xen/arm: vpl011: Add a new vuart console type to xenconsole client
  2017-06-22  7:38 ` [PATCH 15/17 v5] xen/arm: vpl011: Add a new vuart console type to xenconsole client Bhupinder Thakur
  2017-06-22 23:09   ` Stefano Stabellini
@ 2017-06-28 17:17   ` Wei Liu
  2017-06-29  9:33     ` Bhupinder Thakur
  1 sibling, 1 reply; 67+ messages in thread
From: Wei Liu @ 2017-06-28 17:17 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, Jun 22, 2017 at 01:08:50PM +0530, Bhupinder Thakur wrote:
[...]
>  static struct termios stdin_old_attr;
> @@ -343,6 +344,7 @@ int main(int argc, char **argv)
>  	char *end;
>  	console_type type = CONSOLE_INVAL;
>  	bool interactive = 0;
> +	char *console_names = "serial, pv, vuart";
>  
>  	if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO))
>  		interactive = 1;
> @@ -361,9 +363,12 @@ 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");
> +				fprintf(stderr, "Console types supported are: %s\n",
> +						console_names);

Coding style.

>  				exit(EINVAL);
>  			}
>  			break;
> @@ -436,6 +441,10 @@ 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("/vuart/0/tty") + 1,
> +				 "%s/vuart/0/tty", dom_path);

Ditto.

Fix them and:

Acked-by: Wei Liu <wei.liu2@citrix.com>

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

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

* Re: [PATCH 16/17 v5] xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree
  2017-06-22  7:38 ` [PATCH 16/17 v5] xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree Bhupinder Thakur
@ 2017-06-28 17:17   ` Wei Liu
  0 siblings, 0 replies; 67+ messages in thread
From: Wei Liu @ 2017-06-28 17:17 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson, Wei Liu

On Thu, Jun 22, 2017 at 01:08:51PM +0530, 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
> 
> Currently the baud rate of 115200 has been selected as a default value,
> which is one of the valid baud rate setttings. Higher baud rate was
> selected since an emulated pl011 can support any valid baud rate without
> any limitation of the hardware.
> 
> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@linaro.org>
> Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>

Acked-by: Wei Liu <wei.liu2@citrix.com>

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

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

* Re: [PATCH 15/17 v5] xen/arm: vpl011: Add a new vuart console type to xenconsole client
  2017-06-28 17:17   ` Wei Liu
@ 2017-06-29  9:33     ` Bhupinder Thakur
  2017-06-29 10:11       ` Wei Liu
  0 siblings, 1 reply; 67+ messages in thread
From: Bhupinder Thakur @ 2017-06-29  9:33 UTC (permalink / raw)
  To: Wei Liu; +Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson

Hi Wei,

On 28 June 2017 at 22:47, Wei Liu <wei.liu2@citrix.com> wrote:
> On Thu, Jun 22, 2017 at 01:08:50PM +0530, Bhupinder Thakur wrote:
> [...]
>>  static struct termios stdin_old_attr;
>> @@ -343,6 +344,7 @@ int main(int argc, char **argv)
>>       char *end;
>>       console_type type = CONSOLE_INVAL;
>>       bool interactive = 0;
>> +     char *console_names = "serial, pv, vuart";
>>
>>       if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO))
>>               interactive = 1;
>> @@ -361,9 +363,12 @@ 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");
>> +                             fprintf(stderr, "Console types supported are: %s\n",
>> +                                             console_names);
>
> Coding style.
I believe you are referring to the alignment of console_names with
stderr above? Since in this file, tabs are used for indentation and
preserved, I am using tabs to align them but for some reason it is
showing as unaligned here. If I open the patch file in vim with a tab
setting of 4 then it is displayed correctly aligned.

Is it my gmail setting which is making them unaligned?

Regards,
Bhupinder

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

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

* Re: [PATCH 15/17 v5] xen/arm: vpl011: Add a new vuart console type to xenconsole client
  2017-06-29  9:33     ` Bhupinder Thakur
@ 2017-06-29 10:11       ` Wei Liu
  0 siblings, 0 replies; 67+ messages in thread
From: Wei Liu @ 2017-06-29 10:11 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Wei Liu, Ian Jackson

On Thu, Jun 29, 2017 at 03:03:45PM +0530, Bhupinder Thakur wrote:
> Hi Wei,
> 
> On 28 June 2017 at 22:47, Wei Liu <wei.liu2@citrix.com> wrote:
> > On Thu, Jun 22, 2017 at 01:08:50PM +0530, Bhupinder Thakur wrote:
> > [...]
> >>  static struct termios stdin_old_attr;
> >> @@ -343,6 +344,7 @@ int main(int argc, char **argv)
> >>       char *end;
> >>       console_type type = CONSOLE_INVAL;
> >>       bool interactive = 0;
> >> +     char *console_names = "serial, pv, vuart";
> >>
> >>       if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO))
> >>               interactive = 1;
> >> @@ -361,9 +363,12 @@ 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");
> >> +                             fprintf(stderr, "Console types supported are: %s\n",
> >> +                                             console_names);
> >
> > Coding style.
> I believe you are referring to the alignment of console_names with
> stderr above? Since in this file, tabs are used for indentation and

Yes.

> preserved, I am using tabs to align them but for some reason it is
> showing as unaligned here. If I open the patch file in vim with a tab
> setting of 4 then it is displayed correctly aligned.
> 

That's the problem. We all use 8 spaces for tab. :-)

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

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

* Re: [PATCH 00/17 v5] SBSA UART emulation support in Xen
  2017-06-23 10:42 ` [PATCH 00/17 v5] SBSA UART emulation support in Xen Julien Grall
  2017-06-23 17:58   ` Stefano Stabellini
@ 2017-07-04  7:31   ` Bhupinder Thakur
  2017-07-05  8:36     ` Julien Grall
  1 sibling, 1 reply; 67+ messages in thread
From: Bhupinder Thakur @ 2017-07-04  7:31 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, Stefano Stabellini, Ian Jackson, Wei Liu

Hi Julien,

On 23 June 2017 at 16:12, Julien Grall <julien.grall@arm.com> wrote:
> Hi Bhupinder,
>
> On 22/06/17 08:38, Bhupinder Thakur wrote:
>>
>> There are some TBD items which need to be looked at in the future:
>>
>> 1. Currently UEFI firmware logs the output to hvc console only. How can
>>    UEFI firmware be made aware of pl011 console and how it can use it
>>    as a console instead of hvc.
>
>
> Would it be possible to summarize the discussions we had a couple of weeks
> ago here?

Currently, UEFI firmware uses hvc as the console for input/output. Now
with the support
of SBSA UART in Xen, it is preferrable that UEFI firmware should be
able to the uart
as well.

One option which was discussed was to use pl011 purely as a debug
port. Currently the debug
prints are intermixed with the normal console output. Now with uart
port becoming available
the debug prints can be redirected to pl011 thus cleaning up the console output.

Other option is to output everything on both HVC and pl011 both but it
takes away the advantage
of separating out the debug and normal console prints. However, pl011
can be used as debug
port based on a compile time flag. If this compile-time is off, then
the output can be sent to both
HVC and pl011.

Based on this discussion I feel that:
- the default behaviour should be writing the output to both HVC and pl011.
- pl011 can be used as a pure debug port based on a compile-time flag.

>
>> 2. Linux seems to have hvc console as the default console i.e. if no
>>    console is specified then it uses hvc as the console. How can an
>>    option be provided in Linux to select either hvc or pl011 as the
>>    default console.
>
>
> I am wondering what would happen if you use stdout-path in the device-tree.
> Does it override the default console?
>
I tried adding a "chosen" node in the DT to select "sbsa-pl011" as the
stdout-path. I added the
 following code in make_chosen_node() function:

 fdt_property_string(fdt, "stdout-path", "sbsa-pl011");

However, I still see the initial console output going to hvc only.

> IHMO, the best way to select the default console would be using either the
> SPCR (for ACPI) or stdout-path (for DT). But the HVC console does not have
> any description in the firmware. It might be worth considering adding
> description.
>
> The drawback is the user would always have to specify the console on the
> command line. I think this is not too bad for a first approach.
>
Do we plan to address this requirement in the current patch series?

>>
>> 3. ACPI support for pl011 device.
>
>
> I would be ok to defer this after PL011 series is merged.
>

Regards,
Bhupinder

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

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

* Re: [PATCH 00/17 v5] SBSA UART emulation support in Xen
  2017-07-04  7:31   ` Bhupinder Thakur
@ 2017-07-05  8:36     ` Julien Grall
  2017-07-05 19:06       ` Stefano Stabellini
  0 siblings, 1 reply; 67+ messages in thread
From: Julien Grall @ 2017-07-05  8:36 UTC (permalink / raw)
  To: Bhupinder Thakur; +Cc: xen-devel, Stefano Stabellini, Ian Jackson, Wei Liu

On 07/04/2017 08:31 AM, Bhupinder Thakur wrote:
> Hi Julien,

Hi Bhupinder,

Thank you for the summary!

[...]
> 
> Currently, UEFI firmware uses hvc as the console for input/output. Now
> with the support
> of SBSA UART in Xen, it is preferrable that UEFI firmware should be
> able to the uart
> as well.
> 
> One option which was discussed was to use pl011 purely as a debug
> port. Currently the debug
> prints are intermixed with the normal console output. Now with uart
> port becoming available
> the debug prints can be redirected to pl011 thus cleaning up the console output.
> 
> Other option is to output everything on both HVC and pl011 both but it
> takes away the advantage
> of separating out the debug and normal console prints. However, pl011
> can be used as debug
> port based on a compile time flag. If this compile-time is off, then
> the output can be sent to both
> HVC and pl011.
> 
> Based on this discussion I feel that:
> - the default behaviour should be writing the output to both HVC and pl011.

Hmmm. If I remember correctly this was suggested but ruled out. It was 
considered that pl011 and PV console should not be treated equal. PL011 
would be used for boot diagnostics (i.e imagine an Image with no Xen 
support).

So we would continue to use Xen PV console for UEFI console and let the 
choice for the debug at compile to be either on PL011 or PV console.

Stefano, any opinions?

> - pl011 can be used as a pure debug port based on a compile-time flag.

Agree.

> 
>>
>>> 2. Linux seems to have hvc console as the default console i.e. if no
>>>     console is specified then it uses hvc as the console. How can an
>>>     option be provided in Linux to select either hvc or pl011 as the
>>>     default console.
>>
>>
>> I am wondering what would happen if you use stdout-path in the device-tree.
>> Does it override the default console?
>>
> I tried adding a "chosen" node in the DT to select "sbsa-pl011" as the
> stdout-path. I added the
>   following code in make_chosen_node() function:
> 
>   fdt_property_string(fdt, "stdout-path", "sbsa-pl011");
> 
> However, I still see the initial console output going to hvc only.

What do you mean by inital console output? You mean the bootconsole?

> 
>> IHMO, the best way to select the default console would be using either the
>> SPCR (for ACPI) or stdout-path (for DT). But the HVC console does not have
>> any description in the firmware. It might be worth considering adding
>> description.
>>
>> The drawback is the user would always have to specify the console on the
>> command line. I think this is not too bad for a first approach.
>>
> Do we plan to address this requirement in the current patch series?

I am ok with this to be deferred. This is not highly critical. We should 
probably log it on xenproject.atlassian.net to avoid loosing the item.

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 00/17 v5] SBSA UART emulation support in Xen
  2017-07-05  8:36     ` Julien Grall
@ 2017-07-05 19:06       ` Stefano Stabellini
  2017-07-05 19:43         ` Julien Grall
  0 siblings, 1 reply; 67+ messages in thread
From: Stefano Stabellini @ 2017-07-05 19:06 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Wei Liu, Ian Jackson, Bhupinder Thakur, xen-devel

On Wed, 5 Jul 2017, Julien Grall wrote:
> On 07/04/2017 08:31 AM, Bhupinder Thakur wrote:
> > Hi Julien,
> 
> Hi Bhupinder,
> 
> Thank you for the summary!
> 
> [...]
> > 
> > Currently, UEFI firmware uses hvc as the console for input/output. Now
> > with the support
> > of SBSA UART in Xen, it is preferrable that UEFI firmware should be
> > able to the uart
> > as well.
> > 
> > One option which was discussed was to use pl011 purely as a debug
> > port. Currently the debug
> > prints are intermixed with the normal console output. Now with uart
> > port becoming available
> > the debug prints can be redirected to pl011 thus cleaning up the console
> > output.
> > 
> > Other option is to output everything on both HVC and pl011 both but it
> > takes away the advantage
> > of separating out the debug and normal console prints. However, pl011
> > can be used as debug
> > port based on a compile time flag. If this compile-time is off, then
> > the output can be sent to both
> > HVC and pl011.
> > 
> > Based on this discussion I feel that:
> > - the default behaviour should be writing the output to both HVC and pl011.
> 
> Hmmm. If I remember correctly this was suggested but ruled out. It was
> considered that pl011 and PV console should not be treated equal. PL011 would
> be used for boot diagnostics (i.e imagine an Image with no Xen support).

Actually I remember the opposite:
afd2e931-706b-6e25-1f0e-feee16e83c88@redhat.com (this was a private
reply though).


> So we would continue to use Xen PV console for UEFI console and let the choice
> for the debug at compile to be either on PL011 or PV console.
> 
> Stefano, any opinions?

I would approach this issue by asking the following question: "what
behavior would be more beneficial to users?" Given the lack of concrete
data, we have to make guesses.

I think it would least suprise users if the output went to both
consoles. Also, it would be more beneficial, because one could fully run
operating systems without Xen support (think of a small baremetal app)
without having to switch back and forth between PV console (for the
firmware) and PL011 (for the app).

However, as I wrote before on this topic, baremetal apps are unlikely to
boot from UEFI in the near future, so I admit this is not a very strong
use-case.


> > - pl011 can be used as a pure debug port based on a compile-time flag.
> 
> Agree.
> 
> > 
> > > 
> > > > 2. Linux seems to have hvc console as the default console i.e. if no
> > > >     console is specified then it uses hvc as the console. How can an
> > > >     option be provided in Linux to select either hvc or pl011 as the
> > > >     default console.
> > > 
> > > 
> > > I am wondering what would happen if you use stdout-path in the
> > > device-tree.
> > > Does it override the default console?
> > > 
> > I tried adding a "chosen" node in the DT to select "sbsa-pl011" as the
> > stdout-path. I added the
> >   following code in make_chosen_node() function:
> > 
> >   fdt_property_string(fdt, "stdout-path", "sbsa-pl011");
> > 
> > However, I still see the initial console output going to hvc only.
> 
> What do you mean by inital console output? You mean the bootconsole?
> 
> > 
> > > IHMO, the best way to select the default console would be using either the
> > > SPCR (for ACPI) or stdout-path (for DT). But the HVC console does not have
> > > any description in the firmware. It might be worth considering adding
> > > description.
> > > 
> > > The drawback is the user would always have to specify the console on the
> > > command line. I think this is not too bad for a first approach.
> > > 
> > Do we plan to address this requirement in the current patch series?
> 
> I am ok with this to be deferred. This is not highly critical. We should
> probably log it on xenproject.atlassian.net to avoid loosing the item.
> 
> Cheers,
> 
> -- 
> Julien Grall
> 

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

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

* Re: [PATCH 00/17 v5] SBSA UART emulation support in Xen
  2017-07-05 19:06       ` Stefano Stabellini
@ 2017-07-05 19:43         ` Julien Grall
  2017-07-05 19:51           ` Julien Grall
  2017-07-05 20:05           ` Stefano Stabellini
  0 siblings, 2 replies; 67+ messages in thread
From: Julien Grall @ 2017-07-05 19:43 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Wei Liu, Ian Jackson, Bhupinder Thakur, xen-devel, nd



On 05/07/2017 20:06, Stefano Stabellini wrote:
> On Wed, 5 Jul 2017, Julien Grall wrote:
>> On 07/04/2017 08:31 AM, Bhupinder Thakur wrote:
>>> Hi Julien,
>>
>> Hi Bhupinder,
>>
>> Thank you for the summary!
>>
>> [...]
>>>
>>> Currently, UEFI firmware uses hvc as the console for input/output. Now
>>> with the support
>>> of SBSA UART in Xen, it is preferrable that UEFI firmware should be
>>> able to the uart
>>> as well.
>>>
>>> One option which was discussed was to use pl011 purely as a debug
>>> port. Currently the debug
>>> prints are intermixed with the normal console output. Now with uart
>>> port becoming available
>>> the debug prints can be redirected to pl011 thus cleaning up the console
>>> output.
>>>
>>> Other option is to output everything on both HVC and pl011 both but it
>>> takes away the advantage
>>> of separating out the debug and normal console prints. However, pl011
>>> can be used as debug
>>> port based on a compile time flag. If this compile-time is off, then
>>> the output can be sent to both
>>> HVC and pl011.
>>>
>>> Based on this discussion I feel that:
>>> - the default behaviour should be writing the output to both HVC and pl011.
>>
>> Hmmm. If I remember correctly this was suggested but ruled out. It was
>> considered that pl011 and PV console should not be treated equal. PL011 would
>> be used for boot diagnostics (i.e imagine an Image with no Xen support).
>
> Actually I remember the opposite:
> afd2e931-706b-6e25-1f0e-feee16e83c88@redhat.com (this was a private
> reply though).

This was an answer to my question whether a user could select the serial 
by himself. To this reply, you asked whether it was feasible to output 
on all the serials console, but I don't see any yes/no answer.

On the rest of the thread, it has been mentioned it was difficult to 
multiplex to serial console (I forwarded you the thread). Christoffer, 
Laszlo and Ard agreed that PL011 should only be used as boot diagnostics 
and debug (if selected at compile time).

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 00/17 v5] SBSA UART emulation support in Xen
  2017-07-05 19:43         ` Julien Grall
@ 2017-07-05 19:51           ` Julien Grall
  2017-07-05 20:05           ` Stefano Stabellini
  1 sibling, 0 replies; 67+ messages in thread
From: Julien Grall @ 2017-07-05 19:51 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Wei Liu, Ard Biesheuvel, Ian Jackson, Bhupinder Thakur,
	xen-devel, nd, lersek, Christoffer Dall

On 05/07/2017 20:43, Julien Grall wrote:
>
>
> On 05/07/2017 20:06, Stefano Stabellini wrote:
>> On Wed, 5 Jul 2017, Julien Grall wrote:
>>> On 07/04/2017 08:31 AM, Bhupinder Thakur wrote:
>>>> Hi Julien,
>>>
>>> Hi Bhupinder,
>>>
>>> Thank you for the summary!
>>>
>>> [...]
>>>>
>>>> Currently, UEFI firmware uses hvc as the console for input/output. Now
>>>> with the support
>>>> of SBSA UART in Xen, it is preferrable that UEFI firmware should be
>>>> able to the uart
>>>> as well.
>>>>
>>>> One option which was discussed was to use pl011 purely as a debug
>>>> port. Currently the debug
>>>> prints are intermixed with the normal console output. Now with uart
>>>> port becoming available
>>>> the debug prints can be redirected to pl011 thus cleaning up the
>>>> console
>>>> output.
>>>>
>>>> Other option is to output everything on both HVC and pl011 both but it
>>>> takes away the advantage
>>>> of separating out the debug and normal console prints. However, pl011
>>>> can be used as debug
>>>> port based on a compile time flag. If this compile-time is off, then
>>>> the output can be sent to both
>>>> HVC and pl011.
>>>>
>>>> Based on this discussion I feel that:
>>>> - the default behaviour should be writing the output to both HVC and
>>>> pl011.
>>>
>>> Hmmm. If I remember correctly this was suggested but ruled out. It was
>>> considered that pl011 and PV console should not be treated equal.
>>> PL011 would
>>> be used for boot diagnostics (i.e imagine an Image with no Xen support).
>>
>> Actually I remember the opposite:
>> afd2e931-706b-6e25-1f0e-feee16e83c88@redhat.com (this was a private
>> reply though).
>
> This was an answer to my question whether a user could select the serial
> by himself. To this reply, you asked whether it was feasible to output
> on all the serials console, but I don't see any yes/no answer.
>
> On the rest of the thread, it has been mentioned it was difficult to
> multiplex to serial console (I forwarded you the thread). Christoffer,
> Laszlo and Ard agreed that PL011 should only be used as boot diagnostics
> and debug (if selected at compile time).

Actually copying here as answer as Laszlo was happy to forward the 
answer on public list: (+CC Christoffer and Ard)

* So, first of all, the debug port must be a super dumb device,
   available to the earliest firmware phases. It basically has to be a
   platform device, whose location and attributes can be figured out
   without hw discovery or enumeration. (Scanning the DTB is fine, albeit
   already quite laborious in the earliest phases.) PCI, virtio, or XenPV
   devices are unsuitable for this.

* In OVMF (x86), we use the QEMU debug port for this purpose
   (hard-coding the accesses to IO port 0x402). For this, we have a
   specialized DebugLib instance, under
   "OvmfPkg/Library/PlatformDebugLibIoPort".

* The serial port ("COM1") is used equivalently with the graphical
   display and the USB and PS/2 keyboard(s), for console purposes. The
   console(s) become available much later during firmware boot (only in
   the BDS phase).

* In order for a device to be usable as a console, the driver stack must
   (recursively) provide the following two "higher level abstractions" on
   top of the device:

   - EfiSimpleTextInProtocol OR EfiSimpleTextInputExProtocol,
   - AND EfiSimpleTextOutProtocol

   If these are provided, then the console splitter / multiplexer
   mentioned by Ard will take care of the rest.

* In OVMF (x86), this is the relevant protocol and driver stack for the
   "COM1" serial port (note that the necessary "high level abstractions"
   I mentioned above are at the bottom):

             MdeModulePkg/Bus/Pci/PciBusDxe
                           ^
                           |
                   [EfiPciIoProtocol]
                           ^
                           |
               PcAtChipsetPkg/IsaAcpiDxe
                           ^
                           |
                 [EfiIsaAcpiProtocol]
                           ^
                           |
       IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe
                           ^
                           |
                  [EfiIsaIoProtocol]
                           ^
                           |
     IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe
                           ^
                           |
                 [EfiSerialIoProtocol]
                           ^
                           |
             Universal/Console/TerminalDxe
                           ^
                           |
              [EfiSimpleTextInProtocol,
               EfiSimpleTextInputExProtocol,
               EfiSimpleTextOutProtocol]

   Most of this stack is platform dependent (up to and including
   IsaSerialDxe, which produces [EfiSerialIoProtocol]). The universal
   part starts only with TerminalDxe, which consumes
   [EfiSerialIoProtocol], and produces the needed higher level
   abstractions on top.

* OVMF can be built (with -D DEBUG_ON_SERIAL_PORT) to ignore the QEMU
   debug port and to direct debug messages to the serial port instead. In
   that case, we use the following library instances, for directing debug
   messages to the serial port:

   - SerialPortLib: PcAtChipsetPkg/Library/SerialIoLib
   - DebugLib: MdePkg/Library/BaseDebugLibSerialPort

   The DebugLib instance uses SerialPortLib interfaces to print
   characters, and the SerialPortLib instance mentioned above hardcodes
   0x3F8 as the "COM1" UART base address.

   This debug-on-serial build works, but once we're in the BDS phase, the
   serial output will be a mixture of console stuff and debug messages,
   because the two separate paths described above dump output to the
   exact same device.

   So the recommended (and default) build is to send DEBUGs to the QEMU
   debug port (redirecting them to a host side file), and to use "COM1"
   only for console purposes.

* qemu-system-aarch64 has no "debug port", so in ArmVirtQemu we have
   something that can be compared to the (sub-optimal) "-D
   DEBUG_ON_SERIAL_PORT" build of OVMF. Namely, debug messages and
   console output are intermixed.

* In particular, for the DEBUG messages, we use the following library
   instances:

   - PL011UartLib: ArmPlatformPkg/Drivers/PL011Uart/PL011Uart.inf

   - SerialPortLib [1]:
     ArmVirtPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.inf
     (in early firmware phases with no writeable RAM)

   - SerialPortLib [2]:
     ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf
     (later firmware phases with writeable RAM)

   - DebugLib: MdePkg/Library/BaseDebugLibSerialPort

   The DebugLib instance is the same as in OVMF's -D DEBUG_ON_SERIAL_PORT
   build, but the serial port APIs are filled in by different library
   instances.

   For the early firmware phases, we use EarlyFdtPL011SerialPortLib,
   which parses the PL011 location from the DTB on every single serial
   port API invocation. In later firmware phases, we use
   FdtPL011SerialPortLib, which can cache the parsed location in static
   variables.

   Finally, both SerialPortLib instances ask the same PL011UartLib to
   perform the actual PL011 accesses.

* Now that we got the DEBUG message printing for ArmVirtQemu out of the
   way, let's look at how PL011 is used for console purposes. (Again,
   sharing the same PL011 between console and DEBUG messages is not
   optimal, but there is no separate debug port for the aarch64 target.)

            MdeModulePkg/Universal/SerialDxe
                           ^
                           |
                 [EfiSerialIoProtocol]
                           ^
                           |
             Universal/Console/TerminalDxe
                           ^
                           |
              [EfiSimpleTextInProtocol,
               EfiSimpleTextInputExProtocol,
               EfiSimpleTextOutProtocol]

   All the drivers in this stack are universal, and SerialDxe produces
   exactly one [EfiSerialIoProtocol] instance without consuming other
   protocol instances. The trick is that it delegates the actual work to
   the platform's SerialPortLib instance (which is linked into the
   SerialDxe executable).

   In ArmVirtQemu's case, this instance is the one marked above as
   "SerialPortLib [2]", which in turn pulls in PL011UartLib as well.

* Considering the ArmVirtXen case. Both paths (DEBUG messages and
   console IO) are identical to those in ArmVirtQemu, except we use the
   following serial port library instance:

   - SerialPortLib: OvmfPkg/Library/XenConsoleSerialPortLib

   You might notice that we don't have two SerialPortLib instances here,
   one for "early" (RAM-less) phases and another for "late" (RAM-ful)
   phases, like we have in ArmVirtQemu. As far as I understand, the
   reason is that Xen guests lack the "early" (RAM-less) phases totally,
   and so we can get away with just a SerialPortLib instance that
   requires writeable RAM.

   This library instance performs Xen hypercalls. But, that makes no
   difference that the same SerialPortLib instance is used for *both*
   paths, namely console IO and DEBUG messages.

* Now, assuming Xen gets another serial port, i.e. it'll have both
   emulated PL011 and the paravirt console device. Based on my experience
   with OVMF (where DEBUGs and console IO use different devices), I'd
   recommend to dedicate one device to DEBUG messages, and another to
   console IO. I would *not* recommend multiplexing UEFI console IO to
   both PL011 and the XenPV console -- simply because separating DEBUGs
   from console IO is much more important than that. So if you gain
   another, primitive enough serial port-like device, definitely dedicate
   it to this separation, IMHO!

   Whether you assign PL011 to DEBUGs and keep UEFI console IO (including
   grub2 IO, for example) on XenPV, or assign them the other way around,
   is a matter of taste (or standards), I guess.

   - For keeping the UEFI console IO on XenPV, and moving the DEBUG
     messages to the new PL011: implement a new DebugLib instance that
     grabs the PL011 location in a manner that is specific to Xen guests
     (my guess: simply open-code it?) and then delegates the transmit
     work to PL011UartLib. That's all.

   - For the inverse: add a new DebugLib instance that embeds
     XenConsoleSerialPortLib's functionality, and add a SerialPortLib
     instace -- a variant of FdtPL011SerialPortLib.inf -- that grabs the
     PL011 location in a Xen-specific way, and delegates the transmit
     work to PL011UartLib.

   Both of these involve the introduction of a DebugLib instance that
   does *not* depend on the SerialPortLib class.

* Off the top of my head, I can't say how (and *whether*) this division
   of log devices in UEFI should be mirrored to the Linux guest OS as
   well. Earlier I made an effort to understand how Linux handled DBG2
   versus SPCR versus... whatever, but I've forgotten all that by now.

* If you *absolutely* want to multiplex both debug messages and console
   IO to both PL011 and the XenPV console, then a new DXE driver will be
   necessary that produces another EfiSerialIoProtocol instance, without
   going through the SerialPortLib class.

   This driver could be a clone of SerialDxe, but instead of consuming
   SerialPortLib (which we resolve to XenConsoleSerialPortLib in
   ArmVirtXen), it could be modified to:

   - grab the PL011 location in a Xen-specific way,

   - talk to PL011UartLib directly.

   Again, I do not recommend this; it would just duplicate the number of
   devices on which you'd get a mixture of DEBUGs and console IO. If Xen
   is gaining another serial port, use that opportunity to separate
   DEBUGs from console IO, like OVMF does. Which device is going to be
   used for which role is a matter of taste, or maybe it can be deduced
   from the relevant specs (ARM VM spec or maybe the SBBR).

Thanks,
Laszlo
PS: pls feel free to fwd this to some public list so that others can
comment should they want to.

-- 
Julien Grall

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

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

* Re: [PATCH 00/17 v5] SBSA UART emulation support in Xen
  2017-07-05 19:43         ` Julien Grall
  2017-07-05 19:51           ` Julien Grall
@ 2017-07-05 20:05           ` Stefano Stabellini
  2017-07-05 20:18             ` Julien Grall
  1 sibling, 1 reply; 67+ messages in thread
From: Stefano Stabellini @ 2017-07-05 20:05 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Wei Liu, Ian Jackson, Bhupinder Thakur,
	xen-devel, nd

On Wed, 5 Jul 2017, Julien Grall wrote:
> On 05/07/2017 20:06, Stefano Stabellini wrote:
> > On Wed, 5 Jul 2017, Julien Grall wrote:
> > > On 07/04/2017 08:31 AM, Bhupinder Thakur wrote:
> > > > Hi Julien,
> > > 
> > > Hi Bhupinder,
> > > 
> > > Thank you for the summary!
> > > 
> > > [...]
> > > > 
> > > > Currently, UEFI firmware uses hvc as the console for input/output. Now
> > > > with the support
> > > > of SBSA UART in Xen, it is preferrable that UEFI firmware should be
> > > > able to the uart
> > > > as well.
> > > > 
> > > > One option which was discussed was to use pl011 purely as a debug
> > > > port. Currently the debug
> > > > prints are intermixed with the normal console output. Now with uart
> > > > port becoming available
> > > > the debug prints can be redirected to pl011 thus cleaning up the console
> > > > output.
> > > > 
> > > > Other option is to output everything on both HVC and pl011 both but it
> > > > takes away the advantage
> > > > of separating out the debug and normal console prints. However, pl011
> > > > can be used as debug
> > > > port based on a compile time flag. If this compile-time is off, then
> > > > the output can be sent to both
> > > > HVC and pl011.
> > > > 
> > > > Based on this discussion I feel that:
> > > > - the default behaviour should be writing the output to both HVC and
> > > > pl011.
> > > 
> > > Hmmm. If I remember correctly this was suggested but ruled out. It was
> > > considered that pl011 and PV console should not be treated equal. PL011
> > > would
> > > be used for boot diagnostics (i.e imagine an Image with no Xen support).
> > 
> > Actually I remember the opposite:
> > afd2e931-706b-6e25-1f0e-feee16e83c88@redhat.com (this was a private
> > reply though).
> 
> This was an answer to my question whether a user could select the serial by
> himself. To this reply, you asked whether it was feasible to output on all the
> serials console, but I don't see any yes/no answer.
> 
> On the rest of the thread, it has been mentioned it was difficult to multiplex
> to serial console (I forwarded you the thread). Christoffer, Laszlo and Ard
> agreed that PL011 should only be used as boot diagnostics and debug (if
> selected at compile time).

I see now that I missed an important part of the thread. Just follow
Lazlo's suggestion.

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

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

* Re: [PATCH 00/17 v5] SBSA UART emulation support in Xen
  2017-07-05 20:05           ` Stefano Stabellini
@ 2017-07-05 20:18             ` Julien Grall
  0 siblings, 0 replies; 67+ messages in thread
From: Julien Grall @ 2017-07-05 20:18 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Bhupinder Thakur, Ian Jackson, nd, Wei Liu, xen-devel



On 05/07/2017 21:05, Stefano Stabellini wrote:
> On Wed, 5 Jul 2017, Julien Grall wrote:
>> On 05/07/2017 20:06, Stefano Stabellini wrote:
>>> On Wed, 5 Jul 2017, Julien Grall wrote:
>>>> On 07/04/2017 08:31 AM, Bhupinder Thakur wrote:
>>>>> Hi Julien,
>>>>
>>>> Hi Bhupinder,
>>>>
>>>> Thank you for the summary!
>>>>
>>>> [...]
>>>>>
>>>>> Currently, UEFI firmware uses hvc as the console for input/output. Now
>>>>> with the support
>>>>> of SBSA UART in Xen, it is preferrable that UEFI firmware should be
>>>>> able to the uart
>>>>> as well.
>>>>>
>>>>> One option which was discussed was to use pl011 purely as a debug
>>>>> port. Currently the debug
>>>>> prints are intermixed with the normal console output. Now with uart
>>>>> port becoming available
>>>>> the debug prints can be redirected to pl011 thus cleaning up the console
>>>>> output.
>>>>>
>>>>> Other option is to output everything on both HVC and pl011 both but it
>>>>> takes away the advantage
>>>>> of separating out the debug and normal console prints. However, pl011
>>>>> can be used as debug
>>>>> port based on a compile time flag. If this compile-time is off, then
>>>>> the output can be sent to both
>>>>> HVC and pl011.
>>>>>
>>>>> Based on this discussion I feel that:
>>>>> - the default behaviour should be writing the output to both HVC and
>>>>> pl011.
>>>>
>>>> Hmmm. If I remember correctly this was suggested but ruled out. It was
>>>> considered that pl011 and PV console should not be treated equal. PL011
>>>> would
>>>> be used for boot diagnostics (i.e imagine an Image with no Xen support).
>>>
>>> Actually I remember the opposite:
>>> afd2e931-706b-6e25-1f0e-feee16e83c88@redhat.com (this was a private
>>> reply though).
>>
>> This was an answer to my question whether a user could select the serial by
>> himself. To this reply, you asked whether it was feasible to output on all the
>> serials console, but I don't see any yes/no answer.
>>
>> On the rest of the thread, it has been mentioned it was difficult to multiplex
>> to serial console (I forwarded you the thread). Christoffer, Laszlo and Ard
>> agreed that PL011 should only be used as boot diagnostics and debug (if
>> selected at compile time).
>
> I see now that I missed an important part of the thread. Just follow
> Lazlo's suggestion.

Sorry for that. I forgot to include you from beginning.

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH 13/17 v5] xen/arm: vpl011: Modify xenconsole to support multiple consoles
  2017-06-28 17:16   ` Wei Liu
@ 2017-07-07 13:52     ` Bhupinder Thakur
  2017-07-07 14:00       ` Wei Liu
  0 siblings, 1 reply; 67+ messages in thread
From: Bhupinder Thakur @ 2017-07-07 13:52 UTC (permalink / raw)
  To: Wei Liu; +Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson

Hi Wei,


>>
>>  struct console {
>> +     char *ttyname;
>>       int master_fd;
>>       int master_pollfd_idx;
>>       int slave_fd;
>>       int log_fd;
>>       struct buffer buffer;
>>       char *xspath;
>> +     char *log_suffix;
>
> I suppose both new fields can be const.
ok. I will make all the new fields as const char *const.

>
>>       int ring_ref;
>>       xenevtchn_handle *xce_handle;
>>       int xce_pollfd_idx;
>> @@ -107,16 +109,112 @@ struct console {
>>       struct domain *d;
>>  };
>>
>> +struct console_data {
>> +     char *xsname;
>> +     char *ttyname;
>> +     char *log_suffix;
>
> const for all three.
ok.
>

>> +static inline void console_iter_void_arg1(struct domain *d,
>> +                                                                               VOID_ITER_FUNC_ARG1 iter_func)
>
> Too many tabs here and below?
>
> You might want to configure your editor to display tab as 8 spaces.
I have set  my editor to use 8 spaces for a tab. I will fix these misalignments.

>
>> +{
>> +     int i = 0;
>> +     struct console *con = &(d->console[0]);
>> +
>
> No need to have the (), I think.
ok.
>
>> -static struct domain *create_domain(int domid)
>> +static int console_init(struct console *con, struct domain *dom, void **data)
>>  {
>> -     struct domain *dom;
>>       char *s;
>> +     int err = -1;
>>       struct timespec ts;
>> -     struct console *con;
>> +     struct console_data **con_data = (struct console_data **)data;
>> +     char *xsname;
>>
>>       if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
>>               dolog(LOG_ERR, "Cannot get time of day %s:%s:L%d",
>>                     __FILE__, __FUNCTION__, __LINE__);
>> -             return NULL;
>> +             return err;
>> +     }
>> +
>
> There is a danger that you return at this point, the cleanup path in
> caller will free garbage.
>
> I suggest you at least initialise all pointers to NULL at the beginning.
>
I am checking that the pointer is not null before freeing them.

>> +     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->xce_pollfd_idx = -1;
>> +     con->next_period = ((long long)ts.tv_sec * 1000) + (ts.tv_nsec / 1000000) + RATE_LIMIT_PERIOD;
>> +     con->d = dom;
>> +     con->ttyname = (*con_data)->ttyname;
>> +     con->log_suffix = (*con_data)->log_suffix;
>> +     xsname = (*con_data)->xsname;
>> +     con->xspath = xs_get_domain_path(xs, dom->domid);
>> +     s = realloc(con->xspath, strlen(con->xspath) +
>> +                             strlen(xsname) + 1);
>> +     if (s)
>> +     {
>> +             con->xspath = s;
>> +             strcat(con->xspath, xsname);
>> +             err = 0;
>>       }
>>
>> +     (*con_data)++;
>> +
>> +     return err;
>> +}
>> +
>> +
> [...]
>> +static void handle_console_ring(struct console *con)
>> +{
>> +     if (con->event_count < RATE_LIMIT_ALLOWANCE) {
>> +             if (con->xce_handle != NULL &&
>> +                     con->xce_pollfd_idx != -1 &&
>> +                     !(fds[con->xce_pollfd_idx].revents &
>> +                       ~(POLLIN|POLLOUT|POLLPRI)) &&
>> +                       (fds[con->xce_pollfd_idx].revents &
>> +                        POLLIN))
>> +                     handle_ring_read(con);
>> +     }
>
> Refactoring like this should go to its own patch(es).
>
> It is currently very hard to review this patch because refactoring is
> mixed with all the iterator changes.
>
> I can't really continue at this point. Sorry. Please split the
> refactoring of all the buffer_* and handle_console_* functions to
> separate patches.

I have split the changes such that each new function and the related
changes appear in one patch.

Regards,
Bhupinder

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

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

* Re: [PATCH 13/17 v5] xen/arm: vpl011: Modify xenconsole to support multiple consoles
  2017-07-07 13:52     ` Bhupinder Thakur
@ 2017-07-07 14:00       ` Wei Liu
  2017-07-07 14:19         ` Bhupinder Thakur
  0 siblings, 1 reply; 67+ messages in thread
From: Wei Liu @ 2017-07-07 14:00 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Wei Liu, Ian Jackson

On Fri, Jul 07, 2017 at 07:22:14PM +0530, Bhupinder Thakur wrote:
> >> -static struct domain *create_domain(int domid)
> >> +static int console_init(struct console *con, struct domain *dom, void **data)
> >>  {
> >> -     struct domain *dom;
> >>       char *s;
> >> +     int err = -1;
> >>       struct timespec ts;
> >> -     struct console *con;
> >> +     struct console_data **con_data = (struct console_data **)data;
> >> +     char *xsname;
> >>
> >>       if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
> >>               dolog(LOG_ERR, "Cannot get time of day %s:%s:L%d",
> >>                     __FILE__, __FUNCTION__, __LINE__);
> >> -             return NULL;
> >> +             return err;
> >> +     }
> >> +
> >
> > There is a danger that you return at this point, the cleanup path in
> > caller will free garbage.
> >
> > I suggest you at least initialise all pointers to NULL at the beginning.
> >
> I am checking that the pointer is not null before freeing them.
> 

I'm not sure what your reply means.

Without initialising the pointers to NULL you can have garbage in your
pointer (currently only xspath) -- you end up freeing the garbage
pointer. That's why I made the suggestion in the first place. Checking
NULL isn't going to help that.

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

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

* Re: [PATCH 13/17 v5] xen/arm: vpl011: Modify xenconsole to support multiple consoles
  2017-07-07 14:00       ` Wei Liu
@ 2017-07-07 14:19         ` Bhupinder Thakur
  2017-07-07 14:23           ` Wei Liu
  0 siblings, 1 reply; 67+ messages in thread
From: Bhupinder Thakur @ 2017-07-07 14:19 UTC (permalink / raw)
  To: Wei Liu; +Cc: xen-devel, Julien Grall, Stefano Stabellini, Ian Jackson

Hi Wei,

On 7 July 2017 at 19:30, Wei Liu <wei.liu2@citrix.com> wrote:
> On Fri, Jul 07, 2017 at 07:22:14PM +0530, Bhupinder Thakur wrote:
>> >> -static struct domain *create_domain(int domid)
>> >> +static int console_init(struct console *con, struct domain *dom, void **data)
>> >>  {
>> >> -     struct domain *dom;
>> >>       char *s;
>> >> +     int err = -1;
>> >>       struct timespec ts;
>> >> -     struct console *con;
>> >> +     struct console_data **con_data = (struct console_data **)data;
>> >> +     char *xsname;
>> >>
>> >>       if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
>> >>               dolog(LOG_ERR, "Cannot get time of day %s:%s:L%d",
>> >>                     __FILE__, __FUNCTION__, __LINE__);
>> >> -             return NULL;
>> >> +             return err;
>> >> +     }
>> >> +
>> >
>> > There is a danger that you return at this point, the cleanup path in
>> > caller will free garbage.
>> >
>> > I suggest you at least initialise all pointers to NULL at the beginning.
>> >
>> I am checking that the pointer is not null before freeing them.
>>
>
> I'm not sure what your reply means.
>
> Without initialising the pointers to NULL you can have garbage in your
> pointer (currently only xspath) -- you end up freeing the garbage
> pointer. That's why I made the suggestion in the first place. Checking
> NULL isn't going to help that.

I believe when domain structure is allocated it is initialized with 0
(as calloc is used for allocation) so all fields
in the domain and console structures should be NULL.

Regards,
Bhupinder

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

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

* Re: [PATCH 13/17 v5] xen/arm: vpl011: Modify xenconsole to support multiple consoles
  2017-07-07 14:19         ` Bhupinder Thakur
@ 2017-07-07 14:23           ` Wei Liu
  0 siblings, 0 replies; 67+ messages in thread
From: Wei Liu @ 2017-07-07 14:23 UTC (permalink / raw)
  To: Bhupinder Thakur
  Cc: xen-devel, Julien Grall, Stefano Stabellini, Wei Liu, Ian Jackson

On Fri, Jul 07, 2017 at 07:49:32PM +0530, Bhupinder Thakur wrote:
> Hi Wei,
> 
> On 7 July 2017 at 19:30, Wei Liu <wei.liu2@citrix.com> wrote:
> > On Fri, Jul 07, 2017 at 07:22:14PM +0530, Bhupinder Thakur wrote:
> >> >> -static struct domain *create_domain(int domid)
> >> >> +static int console_init(struct console *con, struct domain *dom, void **data)
> >> >>  {
> >> >> -     struct domain *dom;
> >> >>       char *s;
> >> >> +     int err = -1;
> >> >>       struct timespec ts;
> >> >> -     struct console *con;
> >> >> +     struct console_data **con_data = (struct console_data **)data;
> >> >> +     char *xsname;
> >> >>
> >> >>       if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
> >> >>               dolog(LOG_ERR, "Cannot get time of day %s:%s:L%d",
> >> >>                     __FILE__, __FUNCTION__, __LINE__);
> >> >> -             return NULL;
> >> >> +             return err;
> >> >> +     }
> >> >> +
> >> >
> >> > There is a danger that you return at this point, the cleanup path in
> >> > caller will free garbage.
> >> >
> >> > I suggest you at least initialise all pointers to NULL at the beginning.
> >> >
> >> I am checking that the pointer is not null before freeing them.
> >>
> >
> > I'm not sure what your reply means.
> >
> > Without initialising the pointers to NULL you can have garbage in your
> > pointer (currently only xspath) -- you end up freeing the garbage
> > pointer. That's why I made the suggestion in the first place. Checking
> > NULL isn't going to help that.
> 
> I believe when domain structure is allocated it is initialized with 0
> (as calloc is used for allocation) so all fields
> in the domain and console structures should be NULL.
> 

OK in that case it is fine. Misread part of your patch.

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

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

end of thread, other threads:[~2017-07-07 14:23 UTC | newest]

Thread overview: 67+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-22  7:38 [PATCH 00/17 v5] SBSA UART emulation support in Xen Bhupinder Thakur
2017-06-22  7:38 ` [PATCH 01/17 v5] xen/arm: vpl011: Move vgic register access functions to vreg.h Bhupinder Thakur
2017-06-22  7:38 ` [PATCH 02/17 v5] xen/arm: vpl011: Rename vgic_reg* functions definitions and calls to vreg_reg* Bhupinder Thakur
2017-06-23  9:42   ` Julien Grall
2017-06-22  7:38 ` [PATCH 03/17 v5] xen/arm: vpl011: Define common ring buffer helper functions in console.h Bhupinder Thakur
2017-06-22 22:36   ` Stefano Stabellini
2017-06-28 17:16   ` Wei Liu
2017-06-22  7:38 ` [PATCH 04/17 v5] xen/arm: vpl011: Add SBSA UART emulation in Xen Bhupinder Thakur
2017-06-22 22:53   ` Stefano Stabellini
2017-06-23 12:33     ` Julien Grall
2017-06-23 18:28       ` Stefano Stabellini
2017-06-23 19:58         ` Julien Grall
2017-06-23 13:10   ` Julien Grall
2017-06-22  7:38 ` [PATCH 05/17 v5] xen/arm: vpl011: Allocate a new GFN in the toolstack for vuart Bhupinder Thakur
2017-06-22  7:38 ` [PATCH 06/17 v5] xen/arm: vpl011: Add support for vuart in libxl Bhupinder Thakur
2017-06-22 22:57   ` Stefano Stabellini
2017-06-28 17:16   ` Wei Liu
2017-06-22  7:38 ` [PATCH 07/17 v5] xen/arm: vpl011: Rearrange xen header includes in alphabetical order in domctl.c Bhupinder Thakur
2017-06-22 22:58   ` Stefano Stabellini
2017-06-23 13:14     ` Julien Grall
2017-06-22  7:38 ` [PATCH 08/17 v5] xen/arm: vpl011: Add a new domctl API to initialize vpl011 Bhupinder Thakur
2017-06-22 23:04   ` Stefano Stabellini
2017-06-23 13:17     ` Julien Grall
2017-06-23 13:25       ` Julien Grall
2017-06-23 17:57         ` Stefano Stabellini
2017-06-27 13:43         ` Bhupinder Thakur
2017-06-27 13:57           ` Julien Grall
2017-06-23 13:26   ` Julien Grall
2017-06-28 17:16   ` Wei Liu
2017-06-22  7:38 ` [PATCH 09/17 v5] xen/arm: vpl011: Add a new vuart node in the xenstore Bhupinder Thakur
2017-06-22 23:06   ` Stefano Stabellini
2017-06-28 17:16   ` Wei Liu
2017-06-22  7:38 ` [PATCH 10/17 v5] xen/arm: vpl011: Modify xenconsole to define and use a new console structure Bhupinder Thakur
2017-06-22 23:20   ` Stefano Stabellini
2017-06-28 17:16   ` Wei Liu
2017-06-22  7:38 ` [PATCH 11/17 v5] xen/arm: vpl011: Rename the console structure field conspath to xspath Bhupinder Thakur
2017-06-22 23:21   ` Stefano Stabellini
2017-06-28 17:16   ` Wei Liu
2017-06-22  7:38 ` [PATCH 12/17 v5] xen/arm: vpl011: Modify xenconsole functions to take console structure as input Bhupinder Thakur
2017-06-28 17:16   ` Wei Liu
2017-06-22  7:38 ` [PATCH 13/17 v5] xen/arm: vpl011: Modify xenconsole to support multiple consoles Bhupinder Thakur
2017-06-22 23:51   ` Stefano Stabellini
2017-06-28 17:16   ` Wei Liu
2017-07-07 13:52     ` Bhupinder Thakur
2017-07-07 14:00       ` Wei Liu
2017-07-07 14:19         ` Bhupinder Thakur
2017-07-07 14:23           ` Wei Liu
2017-06-22  7:38 ` [PATCH 14/17 v5] xen/arm: vpl011: Add support for vuart console in xenconsole Bhupinder Thakur
2017-06-23  0:02   ` Stefano Stabellini
2017-06-28 17:17   ` Wei Liu
2017-06-22  7:38 ` [PATCH 15/17 v5] xen/arm: vpl011: Add a new vuart console type to xenconsole client Bhupinder Thakur
2017-06-22 23:09   ` Stefano Stabellini
2017-06-28 17:17   ` Wei Liu
2017-06-29  9:33     ` Bhupinder Thakur
2017-06-29 10:11       ` Wei Liu
2017-06-22  7:38 ` [PATCH 16/17 v5] xen/arm: vpl011: Add a pl011 uart DT node in the guest device tree Bhupinder Thakur
2017-06-28 17:17   ` Wei Liu
2017-06-22  7:38 ` [PATCH 17/17 v5] xen/arm: vpl011: Update documentation for vuart console support Bhupinder Thakur
2017-06-23 10:42 ` [PATCH 00/17 v5] SBSA UART emulation support in Xen Julien Grall
2017-06-23 17:58   ` Stefano Stabellini
2017-07-04  7:31   ` Bhupinder Thakur
2017-07-05  8:36     ` Julien Grall
2017-07-05 19:06       ` Stefano Stabellini
2017-07-05 19:43         ` Julien Grall
2017-07-05 19:51           ` Julien Grall
2017-07-05 20:05           ` Stefano Stabellini
2017-07-05 20:18             ` Julien Grall

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.