All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 01/25] xen: allow console_io hypercalls from certain DomUs
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
@ 2018-07-31 23:27 ` Stefano Stabellini
  2018-08-17 19:33   ` Daniel De Graaf
  2018-07-31 23:27 ` [PATCH v3 02/25] xen/arm: move a few DT related defines to public/device_tree_defs.h Stefano Stabellini
                   ` (24 subsequent siblings)
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:27 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, sstabellini, andrii_anisov, George.Dunlap,
	andrew.cooper3, ian.jackson, xen-devel, tim, jbeulich, wei.liu2,
	dgdegra

Introduce an is_console option to allow certain classes of domUs to use
the Xen console. Specifically, it will be used to give console access to
all domUs started from Xen from information on device tree.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
CC: andrew.cooper3@citrix.com
CC: George.Dunlap@eu.citrix.com
CC: ian.jackson@eu.citrix.com
CC: jbeulich@suse.com
CC: konrad.wilk@oracle.com
CC: tim@xen.org
CC: wei.liu2@citrix.com
CC: dgdegra@tycho.nsa.gov
---
Changes in v3:
- remove changes to hooks.c

Changes in v2:
- introduce is_console
- remove #ifdefs
---
 xen/include/xen/sched.h | 2 ++
 xen/include/xsm/dummy.h | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 851f11e..f894dc8 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -379,6 +379,8 @@ struct domain
     bool             auto_node_affinity;
     /* Is this guest fully privileged (aka dom0)? */
     bool             is_privileged;
+    /* Can this guest access the Xen console? */
+    bool             is_console;
     /* Is this a xenstore domain (not dom0)? */
     bool             is_xenstore;
     /* Domain's VCPUs are pinned 1:1 to physical CPUs? */
diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index ff6b2db..3888817 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -230,6 +230,8 @@ static XSM_INLINE int xsm_memory_stat_reservation(XSM_DEFAULT_ARG struct domain
 static XSM_INLINE int xsm_console_io(XSM_DEFAULT_ARG struct domain *d, int cmd)
 {
     XSM_ASSERT_ACTION(XSM_OTHER);
+    if ( d->is_console )
+        return xsm_default_action(XSM_HOOK, d, NULL);
 #ifdef CONFIG_VERBOSE_DEBUG
     if ( cmd == CONSOLEIO_write )
         return xsm_default_action(XSM_HOOK, d, NULL);
-- 
1.9.1


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

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

* [PATCH v3 02/25] xen/arm: move a few DT related defines to public/device_tree_defs.h
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
  2018-07-31 23:27 ` [PATCH v3 01/25] xen: allow console_io hypercalls from certain DomUs Stefano Stabellini
@ 2018-07-31 23:27 ` Stefano Stabellini
  2018-08-01  9:31   ` Julien Grall
  2018-07-31 23:27 ` [PATCH v3 03/25] xen/arm: extend device tree based multiboot protocol Stefano Stabellini
                   ` (23 subsequent siblings)
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:27 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, sstabellini, andrii_anisov, ian.jackson,
	xen-devel, wei.liu2

Move a few constants defined by libxl_arm.c to
xen/include/public/device_tree_defs.h, so that they can be used from Xen
and libxl. Prepend GUEST_ to avoid conflicts.

Move the DT_IRQ_TYPE* definitions from libxl_arm.c to
public/device_tree_defs.h. Use them in Xen where appropriate.

Re-define the existing Xen internal IRQ_TYPEs as DT_IRQ_TYPEs: they
already happen to be the same, let make it clear.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
CC: wei.liu2@citrix.com
CC: ian.jackson@eu.citrix.com
---
Changes in v3:
- only expose device_tree_defs.h to XEN and XEN_TOOLS

Changes in v2:
- introduce DT_IRQ_TYPE_* definitions in device_tree_guest.h
- prepend GUEST_ to other definitions moved to device_tree_guest.h
- redefine IRQ_TYPE_* as  DT_IRQ_TYPE_*
- use DT_IRQ_TYPE_* in Xen when dealing with DT
---
 tools/libxl/libxl_arm.c               | 59 ++++++++++-------------------------
 xen/arch/arm/domain_build.c           |  8 ++---
 xen/include/asm-arm/irq.h             | 16 ++++++++++
 xen/include/public/device_tree_defs.h | 42 +++++++++++++++++++++++++
 xen/include/xen/device_tree.h         | 33 +++-----------------
 5 files changed, 83 insertions(+), 75 deletions(-)
 create mode 100644 xen/include/public/device_tree_defs.h

diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
index 8af9f6f..01ce2ea 100644
--- a/tools/libxl/libxl_arm.c
+++ b/tools/libxl/libxl_arm.c
@@ -7,23 +7,7 @@
 #include <stdbool.h>
 #include <libfdt.h>
 #include <assert.h>
-
-/**
- * IRQ line type.
- * DT_IRQ_TYPE_NONE            - default, unspecified type
- * DT_IRQ_TYPE_EDGE_RISING     - rising edge triggered
- * DT_IRQ_TYPE_EDGE_FALLING    - falling edge triggered
- * DT_IRQ_TYPE_EDGE_BOTH       - rising and falling edge triggered
- * DT_IRQ_TYPE_LEVEL_HIGH      - high level triggered
- * DT_IRQ_TYPE_LEVEL_LOW       - low level triggered
- */
-#define DT_IRQ_TYPE_NONE           0x00000000
-#define DT_IRQ_TYPE_EDGE_RISING    0x00000001
-#define DT_IRQ_TYPE_EDGE_FALLING   0x00000002
-#define DT_IRQ_TYPE_EDGE_BOTH                           \
-    (DT_IRQ_TYPE_EDGE_FALLING | DT_IRQ_TYPE_EDGE_RISING)
-#define DT_IRQ_TYPE_LEVEL_HIGH     0x00000004
-#define DT_IRQ_TYPE_LEVEL_LOW      0x00000008
+#include <xen/device_tree_defs.h>
 
 static const char *gicv_to_string(libxl_gic_version gic_version)
 {
@@ -165,18 +149,9 @@ static struct arch_info {
     {"xen-3.0-aarch64", "arm,armv8-timer", "arm,armv8" },
 };
 
-/*
- * The device tree compiler (DTC) is allocating the phandle from 1 to
- * onwards. Reserve a high value for the GIC phandle.
- */
-#define PHANDLE_GIC (65000)
-
 typedef uint32_t be32;
 typedef be32 gic_interrupt[3];
 
-#define ROOT_ADDRESS_CELLS 2
-#define ROOT_SIZE_CELLS 2
-
 #define PROP_INITRD_START "linux,initrd-start"
 #define PROP_INITRD_END "linux,initrd-end"
 
@@ -252,7 +227,7 @@ static int fdt_property_interrupts(libxl__gc *gc, void *fdt,
     res = fdt_property(fdt, "interrupts", intr, sizeof (intr[0]) * num_irq);
     if (res) return res;
 
-    res = fdt_property_cell(fdt, "interrupt-parent", PHANDLE_GIC);
+    res = fdt_property_cell(fdt, "interrupt-parent", GUEST_PHANDLE_GIC);
     if (res) return res;
 
     return 0;
@@ -298,13 +273,13 @@ static int make_root_properties(libxl__gc *gc,
                               "xen,xenvm");
     if (res) return res;
 
-    res = fdt_property_cell(fdt, "interrupt-parent", PHANDLE_GIC);
+    res = fdt_property_cell(fdt, "interrupt-parent", GUEST_PHANDLE_GIC);
     if (res) return res;
 
-    res = fdt_property_cell(fdt, "#address-cells", ROOT_ADDRESS_CELLS);
+    res = fdt_property_cell(fdt, "#address-cells", GUEST_ROOT_ADDRESS_CELLS);
     if (res) return res;
 
-    res = fdt_property_cell(fdt, "#size-cells", ROOT_SIZE_CELLS);
+    res = fdt_property_cell(fdt, "#size-cells", GUEST_ROOT_SIZE_CELLS);
     if (res) return res;
 
     return 0;
@@ -346,7 +321,7 @@ static int make_chosen_node(libxl__gc *gc, void *fdt, bool ramdisk,
                                   "multiboot,module");
         if (res) return res;
 
-        res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
+        res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
                                 1, 0, 0);
         if (res) return res;
 
@@ -450,7 +425,7 @@ static int make_memory_nodes(libxl__gc *gc, void *fdt,
         res = fdt_property_string(fdt, "device_type", "memory");
         if (res) return res;
 
-        res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
+        res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
                                 1, 0, 0);
         if (res) return res;
 
@@ -486,16 +461,16 @@ static int make_gicv2_node(libxl__gc *gc, void *fdt,
     res = fdt_property(fdt, "interrupt-controller", NULL, 0);
     if (res) return res;
 
-    res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
+    res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
                             2,
                             gicd_base, gicd_size,
                             gicc_base, gicc_size);
     if (res) return res;
 
-    res = fdt_property_cell(fdt, "linux,phandle", PHANDLE_GIC);
+    res = fdt_property_cell(fdt, "linux,phandle", GUEST_PHANDLE_GIC);
     if (res) return res;
 
-    res = fdt_property_cell(fdt, "phandle", PHANDLE_GIC);
+    res = fdt_property_cell(fdt, "phandle", GUEST_PHANDLE_GIC);
     if (res) return res;
 
     res = fdt_end_node(fdt);
@@ -528,16 +503,16 @@ static int make_gicv3_node(libxl__gc *gc, void *fdt)
     res = fdt_property(fdt, "interrupt-controller", NULL, 0);
     if (res) return res;
 
-    res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
+    res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
                             2,
                             gicd_base, gicd_size,
                             gicr0_base, gicr0_size);
     if (res) return res;
 
-    res = fdt_property_cell(fdt, "linux,phandle", PHANDLE_GIC);
+    res = fdt_property_cell(fdt, "linux,phandle", GUEST_PHANDLE_GIC);
     if (res) return res;
 
-    res = fdt_property_cell(fdt, "phandle", PHANDLE_GIC);
+    res = fdt_property_cell(fdt, "phandle", GUEST_PHANDLE_GIC);
     if (res) return res;
 
     res = fdt_end_node(fdt);
@@ -593,7 +568,7 @@ static int make_hypervisor_node(libxl__gc *gc, void *fdt,
     if (res) return res;
 
     /* reg 0 is grant table space */
-    res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
+    res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
                             1,GUEST_GNTTAB_BASE, GUEST_GNTTAB_SIZE);
     if (res) return res;
 
@@ -626,7 +601,7 @@ static int make_vpl011_uart_node(libxl__gc *gc, void *fdt,
     res = fdt_property_compat(gc, fdt, 1, "arm,sbsa-uart");
     if (res) return res;
 
-    res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
+    res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
                             1,
                             GUEST_PL011_BASE, GUEST_PL011_SIZE);
     if (res) return res;
@@ -1027,12 +1002,12 @@ static void finalise_one_node(libxl__gc *gc, void *fdt, const char *uname,
         LOG(DEBUG, "Nopping out placeholder node %s", name);
         fdt_nop_node(fdt, node);
     } else {
-        uint32_t regs[ROOT_ADDRESS_CELLS+ROOT_SIZE_CELLS];
+        uint32_t regs[GUEST_ROOT_ADDRESS_CELLS+GUEST_ROOT_SIZE_CELLS];
         be32 *cells = &regs[0];
 
         LOG(DEBUG, "Populating placeholder node %s", name);
 
-        set_range(&cells, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS, base, size);
+        set_range(&cells, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS, base, size);
 
         res = fdt_setprop_inplace(fdt, node, "reg", regs, sizeof(regs));
         assert(!res);
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 1351572..df9309d 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -633,7 +633,7 @@ static int __init make_hypervisor_node(struct domain *d,
      *  - All CPUs
      *  TODO: Handle properly the cpumask;
      */
-    set_interrupt_ppi(intr, d->arch.evtchn_irq, 0xf, IRQ_TYPE_LEVEL_LOW);
+    set_interrupt_ppi(intr, d->arch.evtchn_irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
     res = fdt_property_interrupts(fdt, &intr, 1);
     if ( res )
         return res;
@@ -910,15 +910,15 @@ static int __init make_timer_node(const struct domain *d, void *fdt,
 
     irq = timer_get_irq(TIMER_PHYS_SECURE_PPI);
     dt_dprintk("  Secure interrupt %u\n", irq);
-    set_interrupt_ppi(intrs[0], irq, 0xf, IRQ_TYPE_LEVEL_LOW);
+    set_interrupt_ppi(intrs[0], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
 
     irq = timer_get_irq(TIMER_PHYS_NONSECURE_PPI);
     dt_dprintk("  Non secure interrupt %u\n", irq);
-    set_interrupt_ppi(intrs[1], irq, 0xf, IRQ_TYPE_LEVEL_LOW);
+    set_interrupt_ppi(intrs[1], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
 
     irq = timer_get_irq(TIMER_VIRT_PPI);
     dt_dprintk("  Virt interrupt %u\n", irq);
-    set_interrupt_ppi(intrs[2], irq, 0xf, IRQ_TYPE_LEVEL_LOW);
+    set_interrupt_ppi(intrs[2], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
 
     res = fdt_property_interrupts(fdt, intrs, 3);
     if ( res )
diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
index 9d55e9b..e45d574 100644
--- a/xen/include/asm-arm/irq.h
+++ b/xen/include/asm-arm/irq.h
@@ -2,6 +2,22 @@
 #define _ASM_HW_IRQ_H
 
 #include <xen/device_tree.h>
+#include <public/device_tree_defs.h>
+
+/*
+ * These defines correspond to the Xen internal representation of the
+ * IRQ types. We choose to make them the same as the existing device
+ * tree definitions for convenience.
+ */
+#define IRQ_TYPE_NONE           DT_IRQ_TYPE_NONE
+#define IRQ_TYPE_EDGE_RISING    DT_IRQ_TYPE_EDGE_RISING
+#define IRQ_TYPE_EDGE_FALLING   DT_IRQ_TYPE_EDGE_FALLING
+#define IRQ_TYPE_EDGE_BOTH      DT_IRQ_TYPE_EDGE_BOTH 
+#define IRQ_TYPE_LEVEL_HIGH     DT_IRQ_TYPE_LEVEL_HIGH
+#define IRQ_TYPE_LEVEL_LOW      DT_IRQ_TYPE_LEVEL_LOW
+#define IRQ_TYPE_LEVEL_MASK     DT_IRQ_TYPE_LEVEL_MASK
+#define IRQ_TYPE_SENSE_MASK     DT_IRQ_TYPE_SENSE_MASK
+#define IRQ_TYPE_INVALID        DT_IRQ_TYPE_INVALID
 
 #define NR_VECTORS 256 /* XXX */
 
diff --git a/xen/include/public/device_tree_defs.h b/xen/include/public/device_tree_defs.h
new file mode 100644
index 0000000..209d43d
--- /dev/null
+++ b/xen/include/public/device_tree_defs.h
@@ -0,0 +1,42 @@
+#ifndef __XEN_DEVICE_TREE_DEFS_H__
+#define __XEN_DEVICE_TREE_DEFS_H__
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+/*
+ * The device tree compiler (DTC) is allocating the phandle from 1 to
+ * onwards. Reserve a high value for the GIC phandle.
+ */
+#define GUEST_PHANDLE_GIC (65000)
+
+#define GUEST_ROOT_ADDRESS_CELLS 2
+#define GUEST_ROOT_SIZE_CELLS 2
+
+/**
+ * IRQ line type.
+ *
+ * DT_IRQ_TYPE_NONE            - default, unspecified type
+ * DT_IRQ_TYPE_EDGE_RISING     - rising edge triggered
+ * DT_IRQ_TYPE_EDGE_FALLING    - falling edge triggered
+ * DT_IRQ_TYPE_EDGE_BOTH       - rising and falling edge triggered
+ * DT_IRQ_TYPE_LEVEL_HIGH      - high level triggered
+ * DT_IRQ_TYPE_LEVEL_LOW       - low level triggered
+ * DT_IRQ_TYPE_LEVEL_MASK      - Mask to filter out the level bits
+ * DT_IRQ_TYPE_SENSE_MASK      - Mask for all the above bits
+ * DT_IRQ_TYPE_INVALID         - Use to initialize the type
+ */
+#define DT_IRQ_TYPE_NONE           0x00000000
+#define DT_IRQ_TYPE_EDGE_RISING    0x00000001
+#define DT_IRQ_TYPE_EDGE_FALLING   0x00000002
+#define DT_IRQ_TYPE_EDGE_BOTH                           \
+    (DT_IRQ_TYPE_EDGE_FALLING | DT_IRQ_TYPE_EDGE_RISING)
+#define DT_IRQ_TYPE_LEVEL_HIGH     0x00000004
+#define DT_IRQ_TYPE_LEVEL_LOW      0x00000008
+#define DT_IRQ_TYPE_LEVEL_MASK                          \
+    (DT_IRQ_TYPE_LEVEL_LOW | DT_IRQ_TYPE_LEVEL_HIGH)
+#define DT_IRQ_TYPE_SENSE_MASK     0x0000000f
+
+#define DT_IRQ_TYPE_INVALID        0x00000010
+
+#endif
+
+#endif
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index 0aecbe0..638b926 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -13,6 +13,7 @@
 #include <asm/byteorder.h>
 #include <asm/device.h>
 #include <public/xen.h>
+#include <public/device_tree_defs.h>
 #include <xen/kernel.h>
 #include <xen/init.h>
 #include <xen/string.h>
@@ -114,35 +115,9 @@ struct dt_phandle_args {
 };
 
 /**
- * IRQ line type.
- *
- * IRQ_TYPE_NONE            - default, unspecified type
- * IRQ_TYPE_EDGE_RISING     - rising edge triggered
- * IRQ_TYPE_EDGE_FALLING    - falling edge triggered
- * IRQ_TYPE_EDGE_BOTH       - rising and falling edge triggered
- * IRQ_TYPE_LEVEL_HIGH      - high level triggered
- * IRQ_TYPE_LEVEL_LOW       - low level triggered
- * IRQ_TYPE_LEVEL_MASK      - Mask to filter out the level bits
- * IRQ_TYPE_SENSE_MASK      - Mask for all the above bits
- * IRQ_TYPE_INVALID         - Use to initialize the type
- */
-#define IRQ_TYPE_NONE           0x00000000
-#define IRQ_TYPE_EDGE_RISING    0x00000001
-#define IRQ_TYPE_EDGE_FALLING   0x00000002
-#define IRQ_TYPE_EDGE_BOTH                           \
-    (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
-#define IRQ_TYPE_LEVEL_HIGH     0x00000004
-#define IRQ_TYPE_LEVEL_LOW      0x00000008
-#define IRQ_TYPE_LEVEL_MASK                          \
-    (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)
-#define IRQ_TYPE_SENSE_MASK     0x0000000f
-
-#define IRQ_TYPE_INVALID        0x00000010
-
-/**
  * dt_irq - describe an IRQ in the device tree
  * @irq: IRQ number
- * @type: IRQ type (see IRQ_TYPE_*)
+ * @type: IRQ type (see DT_IRQ_TYPE_*)
  *
  * This structure is returned when an interrupt is mapped.
  */
@@ -151,12 +126,12 @@ struct dt_irq {
     unsigned int type;
 };
 
-/* If type == IRQ_TYPE_NONE, assume we use level triggered */
+/* If type == DT_IRQ_TYPE_NONE, assume we use level triggered */
 static inline bool_t dt_irq_is_level_triggered(const struct dt_irq *irq)
 {
     unsigned int type = irq->type;
 
-    return (type & IRQ_TYPE_LEVEL_MASK) || (type == IRQ_TYPE_NONE);
+    return (type & DT_IRQ_TYPE_LEVEL_MASK) || (type == DT_IRQ_TYPE_NONE);
 }
 
 /**
-- 
1.9.1


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

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

* [PATCH v3 03/25] xen/arm: extend device tree based multiboot protocol
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
  2018-07-31 23:27 ` [PATCH v3 01/25] xen: allow console_io hypercalls from certain DomUs Stefano Stabellini
  2018-07-31 23:27 ` [PATCH v3 02/25] xen/arm: move a few DT related defines to public/device_tree_defs.h Stefano Stabellini
@ 2018-07-31 23:27 ` Stefano Stabellini
  2018-07-31 23:27 ` [PATCH v3 04/25] xen/arm: document dom0less Stefano Stabellini
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:27 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Extend the existing device tree based multiboot protocol to include
information regarding multiple domains to boot.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

---
Changes in v3:
- remove "xen,initial-domain" for now
- make vpl011 an empty property
- memory in KBs

Changes in v2:
- lower case kernel
- rename mem to memory
- mandate cpus and memory
- replace domU-kernel with kernel and domU-ramdisk with ramdisk
- rename xen,domU with xen,domain
- add info about dom0
- switch memory and cpus to integers
- remove defaults
- add vpl011
---
 docs/misc/arm/device-tree/booting.txt | 107 ++++++++++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/docs/misc/arm/device-tree/booting.txt b/docs/misc/arm/device-tree/booting.txt
index ce2d0dc..6b8e20f 100644
--- a/docs/misc/arm/device-tree/booting.txt
+++ b/docs/misc/arm/device-tree/booting.txt
@@ -119,3 +119,110 @@ For those you would hardcode the Xen commandline in the DTB under
 line by writing bootargs (as for native Linux).
 A Xen-aware bootloader would set xen,xen-bootargs for Xen, xen,dom0-bootargs
 for Dom0 and bootargs for native Linux.
+
+
+Creating Multiple Domains directly from Xen
+===========================================
+
+It is possible to have Xen create other domains, in addition to dom0,
+out of the information provided via device tree. A kernel and initrd
+(optional) need to be specified for each guest.
+
+For each domain to be created there needs to be one node under /chosen
+with the following properties:
+
+- compatible
+
+    For domUs: "xen,domain"
+
+- memory
+
+    An integer specifying the amount of kilobytes of RAM to allocate to
+    the guest.
+
+- cpus
+
+    An integer specifying the number of vcpus to allocate to the guest.
+
+- vpl011
+
+    An empty property to enable/disable a virtual pl011 for the guest to use.
+
+- #address-cells and #size-cells
+
+    Both #address-cells and #size-cells need to be specified because
+    both sub-nodes (described shortly) have reg properties.
+
+Under the "xen,domain" compatible node, one or more sub-nodes are present
+for the DomU kernel and ramdisk.
+
+The kernel sub-node has the following properties:
+
+- compatible
+
+    "multiboot,kernel"
+
+- reg
+
+    Specifies the physical address of the kernel in RAM and its
+    length.
+
+- bootargs (optional)
+
+    Command line parameters for the guest kernel.
+
+The ramdisk sub-node has the following properties:
+
+- compatible
+
+    "multiboot,ramdisk"
+
+- reg
+
+    Specifies the physical address of the ramdisk in RAM and its
+    length.
+
+
+Example
+=======
+
+chosen {
+    domU1 {
+        compatible = "xen,domain";
+        #address-cells = <0x2>;
+        #size-cells = <0x1>;
+        memory = <131072>;
+        cpus = <2>;
+        vpl011;
+
+        module@0x4a000000 {
+            compatible = "multiboot,kernel";
+            reg = <0x0 0x4a000000 0xffffff>;
+            bootargs = "console=ttyAMA0 init=/bin/sh";
+        };
+
+        module@0x4b000000 {
+            compatible = "multiboot,ramdisk";
+            reg = <0x0 0x4b000000 0xffffff>;
+        };
+    };
+
+    domU2 {
+        compatible = "xen,domain";
+        #address-cells = <0x2>;
+        #size-cells = <0x1>;
+        memory = <65536>;
+        cpus = <1>;
+
+        module@0x4c000000 {
+            compatible = "multiboot,kernel";
+            reg = <0x0 0x4c000000 0xffffff>;
+            bootargs = "console=ttyAMA0 init=/bin/sh";
+        };
+
+        module@0x4d000000 {
+            compatible = "multiboot,ramdisk";
+            reg = <0x0 0x4d000000 0xffffff>;
+        };
+    };
+};
-- 
1.9.1


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

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

* [PATCH v3 04/25] xen/arm: document dom0less
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (2 preceding siblings ...)
  2018-07-31 23:27 ` [PATCH v3 03/25] xen/arm: extend device tree based multiboot protocol Stefano Stabellini
@ 2018-07-31 23:27 ` Stefano Stabellini
  2018-08-01  9:46   ` Julien Grall
  2018-07-31 23:27 ` [PATCH v3 05/25] xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node Stefano Stabellini
                   ` (21 subsequent siblings)
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:27 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Add a new document to provide information on how to use dom0less related
features and their current limitations.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

---
Changes in v3:
- add patch
---
 docs/misc/arm/dom0less | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 docs/misc/arm/dom0less

diff --git a/docs/misc/arm/dom0less b/docs/misc/arm/dom0less
new file mode 100644
index 0000000..ae5a8b1
--- /dev/null
+++ b/docs/misc/arm/dom0less
@@ -0,0 +1,47 @@
+Dom0less
+========
+
+"Dom0less" is a set of Xen features that enable the deployment of a Xen
+system without Dom0. Each feature can be used independently from the
+others, unless otherwise stated.
+
+Booting Multiple Domains from Device Tree
+=========================================
+
+This feature enables Xen to create a set of DomUs alongside Dom0 at boot
+time. Information about the DomUs to be created by Xen is passed to the
+hypervisor via Device Tree. Specifically, the existing Device Tree based
+Multiboot specification has been extended to allow for multiple domains
+to be passed to Xen. See docs/misc/arm/device-tree/booting.txt for more
+information about the Multiboot specification and how to use it.
+
+Instead of waiting for Dom0 to be fully booted and the Xen tools to
+become available, domains created by Xen this way are started in
+parallel to Dom0. Hence, their boot time is typically much shorter.
+
+Domains started by Xen at boot time currently have the following
+limitations:
+
+- they cannot be properly shutdown or rebooted using xl
+If one of them crashes, the whole platform should be rebooted.
+
+- some xl operations might not work as expected
+xl is meant to be used with domains that have been created by it. Using
+xl with domains started by Xen at boot might not work as expected.
+
+- the GIC version is the native version
+In absence of other information, the GIC version exposed to the domains
+started by Xen at boot is the same as the native GIC version.
+
+- no PV drivers
+There is no support for PV devices at the moment. All devices need to be
+statically assigned to guests.
+
+- vCPU pinning
+Pinning vCPUs of domains started by Xen at boot can be done from dom0,
+using `xl vcpu-pin' as usual. It is not currently possible to configure
+vCPU pinning for domains other than dom0 without dom0. However, the NULL
+scheduler (currently unsupported) can be selected by passing
+`sched=null' to the Xen command line. The NULL scheduler automatically
+assignes and pins vCPUs to pCPUs, but the vCPU-pCPU assignments cannot
+be configured.
-- 
1.9.1


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

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

* [PATCH v3 05/25] xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (3 preceding siblings ...)
  2018-07-31 23:27 ` [PATCH v3 04/25] xen/arm: document dom0less Stefano Stabellini
@ 2018-07-31 23:27 ` Stefano Stabellini
  2018-08-01  9:50   ` Julien Grall
  2018-07-31 23:27 ` [PATCH v3 06/25] xen/arm: move evtchn_allocate call out of make_hypervisor_node Stefano Stabellini
                   ` (20 subsequent siblings)
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:27 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

In order to make make_memory_node and make_hypervisor_node more
reusable, do not pass them dt_host. As they only use it to calculate
addrcells and sizecells, pass addrcells and sizecells directly.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

---
Changes in v3:
- split evtchn_allocate movement to separate patch

Changes in v2:
- add blank line
- move evtchn_allocate to handle_node
---
 xen/arch/arm/domain_build.c   | 21 +++++++++++----------
 xen/common/device_tree.c      |  6 +++---
 xen/include/xen/device_tree.h |  2 +-
 3 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index df9309d..0177492 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -533,11 +533,11 @@ static int __init fdt_property_interrupts(void *fdt, gic_interrupt_t *intr,
 
 static int __init make_memory_node(const struct domain *d,
                                    void *fdt,
-                                   const struct dt_device_node *parent,
+                                   int addrcells, int sizecells,
                                    const struct kernel_info *kinfo)
 {
     int res, i;
-    int reg_size = dt_child_n_addr_cells(parent) + dt_child_n_size_cells(parent);
+    int reg_size = addrcells + sizecells;
     int nr_cells = reg_size*kinfo->mem.nr_banks;
     __be32 reg[nr_cells];
     __be32 *cells;
@@ -563,7 +563,7 @@ static int __init make_memory_node(const struct domain *d,
         dt_dprintk("  Bank %d: %#"PRIx64"->%#"PRIx64"\n",
                    i, start, start + size);
 
-        dt_child_set_range(&cells, parent, start, size);
+        dt_child_set_range(&cells, addrcells, sizecells, start, size);
     }
 
     res = fdt_property(fdt, "reg", reg, sizeof(reg));
@@ -579,7 +579,7 @@ static void evtchn_allocate(struct domain *d);
 
 static int __init make_hypervisor_node(struct domain *d,
                                        const struct kernel_info *kinfo,
-                                       const struct dt_device_node *parent)
+                                       int addrcells, int sizecells)
 {
     const char compat[] =
         "xen,xen-"__stringify(XEN_VERSION)"."__stringify(XEN_SUBVERSION)"\0"
@@ -588,9 +588,6 @@ static int __init make_hypervisor_node(struct domain *d,
     gic_interrupt_t intr;
     __be32 *cells;
     int res;
-    /* Convenience alias */
-    int addrcells = dt_child_n_addr_cells(parent);
-    int sizecells = dt_child_n_size_cells(parent);
     void *fdt = kinfo->fdt;
 
     dt_dprintk("Create hypervisor node\n");
@@ -615,7 +612,8 @@ static int __init make_hypervisor_node(struct domain *d,
 
     /* reg 0 is grant table space */
     cells = &reg[0];
-    dt_child_set_range(&cells, parent, kinfo->gnttab_start, kinfo->gnttab_size);
+    dt_child_set_range(&cells, addrcells, sizecells,
+                       kinfo->gnttab_start, kinfo->gnttab_size);
     res = fdt_property(fdt, "reg", reg,
                        dt_cells_to_size(addrcells + sizecells));
     if ( res )
@@ -1292,11 +1290,14 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
 
     if ( node == dt_host )
     {
+        int addrcells = dt_child_n_addr_cells(node);
+        int sizecells = dt_child_n_size_cells(node);
+
         /*
          * The hypervisor node should always be created after all nodes
          * from the host DT have been parsed.
          */
-        res = make_hypervisor_node(d, kinfo, node);
+        res = make_hypervisor_node(d, kinfo, addrcells, sizecells);
         if ( res )
             return res;
 
@@ -1308,7 +1309,7 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
         if ( res )
             return res;
 
-        res = make_memory_node(d, kinfo->fdt, node, kinfo);
+        res = make_memory_node(d, kinfo->fdt, addrcells, sizecells, kinfo);
         if ( res )
             return res;
 
diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 7b009ea..8fc401d 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -112,11 +112,11 @@ void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
     dt_set_cell(cellp, dt_n_size_cells(np), size);
 }
 
-void dt_child_set_range(__be32 **cellp, const struct dt_device_node *parent,
+void dt_child_set_range(__be32 **cellp, int addrcells, int sizecells,
                         u64 address, u64 size)
 {
-    dt_set_cell(cellp, dt_child_n_addr_cells(parent), address);
-    dt_set_cell(cellp, dt_child_n_size_cells(parent), size);
+    dt_set_cell(cellp, addrcells, address);
+    dt_set_cell(cellp, sizecells, size);
 }
 
 static void __init *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index 638b926..91fa0b6 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -674,7 +674,7 @@ void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
  * Write a range into a series of cells and update cellp to point to the
  * cell just after.
  */
-void dt_child_set_range(__be32 **cellp, const struct dt_device_node *parent,
+void dt_child_set_range(__be32 **cellp, int addrcells, int sizecells,
                         u64 address, u64 size);
 
 /**
-- 
1.9.1


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

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

* [PATCH v3 06/25] xen/arm: move evtchn_allocate call out of make_hypervisor_node
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (4 preceding siblings ...)
  2018-07-31 23:27 ` [PATCH v3 05/25] xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node Stefano Stabellini
@ 2018-07-31 23:27 ` Stefano Stabellini
  2018-08-01  9:51   ` Julien Grall
  2018-07-31 23:27 ` [PATCH v3 07/25] xen/arm: rename acpi_make_chosen_node to make_chosen_node Stefano Stabellini
                   ` (19 subsequent siblings)
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:27 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

In the case of domUs, evtchn_irq is allocated by arch_domain_create and
set to GUEST_EVTCHN_PPI.

To make make_hypervisor_node more reusable, move the call to
evtchn_allocate out of make_hypervisor_node, to the dom0 specific caller
(handle_node).

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

---
Changes in v3:
- add patch
- add BUG_ON
---
 xen/arch/arm/domain_build.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 0177492..b51d014 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -619,11 +619,7 @@ static int __init make_hypervisor_node(struct domain *d,
     if ( res )
         return res;
 
-    /*
-     * It is safe to allocate the event channel here because all the
-     * PPIs used by the hardware domain have been registered.
-     */
-    evtchn_allocate(d);
+    BUG_ON(d->arch.evtchn_irq == 0);
 
     /*
      * Interrupt event channel upcall:
@@ -1293,6 +1289,13 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
         int addrcells = dt_child_n_addr_cells(node);
         int sizecells = dt_child_n_size_cells(node);
 
+
+        /*
+         * It is safe to allocate the event channel here because all the
+         * PPIs used by the hardware domain have been registered.
+         */
+        evtchn_allocate(d);
+
         /*
          * The hypervisor node should always be created after all nodes
          * from the host DT have been parsed.
-- 
1.9.1


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

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

* [PATCH v3 07/25] xen/arm: rename acpi_make_chosen_node to make_chosen_node
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (5 preceding siblings ...)
  2018-07-31 23:27 ` [PATCH v3 06/25] xen/arm: move evtchn_allocate call out of make_hypervisor_node Stefano Stabellini
@ 2018-07-31 23:27 ` Stefano Stabellini
  2018-08-01  9:53   ` Julien Grall
  2018-07-31 23:27 ` [PATCH v3 08/25] xen/arm: increase MAX_MODULES Stefano Stabellini
                   ` (18 subsequent siblings)
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:27 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

acpi_make_chosen_node is actually generic and can be reused. Rename it
to make_chosen_node and make it available to non-ACPI builds.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
Removed Julien's ack due to small change below

Changes in v3:
- retain CONFIG_ACPI not to break bisection for !ACPI build, it will be
  removed by a later patch
---
 xen/arch/arm/domain_build.c | 91 ++++++++++++++++++++++++---------------------
 1 file changed, 49 insertions(+), 42 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index b51d014..cd47a68 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -932,6 +932,54 @@ static int __init make_timer_node(const struct domain *d, void *fdt,
     return res;
 }
 
+#ifdef CONFIG_ACPI
+/*
+ * This function is used as part of the device tree generation for Dom0
+ * on ACPI systems, and DomUs started directly from Xen based on device
+ * tree information.
+ */
+static int __init make_chosen_node(const struct kernel_info *kinfo)
+{
+    int res;
+    const char *bootargs = NULL;
+    const struct bootmodule *mod = kinfo->kernel_bootmodule;
+    void *fdt = kinfo->fdt;
+
+    dt_dprintk("Create chosen node\n");
+    res = fdt_begin_node(fdt, "chosen");
+    if ( res )
+        return res;
+
+    if ( mod && mod->cmdline[0] )
+    {
+        bootargs = &mod->cmdline[0];
+        res = fdt_property(fdt, "bootargs", bootargs, strlen(bootargs) + 1);
+        if ( res )
+           return res;
+    }
+
+    /*
+     * If the bootloader provides an initrd, we must create a placeholder
+     * for the initrd properties. The values will be replaced later.
+     */
+    if ( mod && mod->size )
+    {
+        u64 a = 0;
+        res = fdt_property(kinfo->fdt, "linux,initrd-start", &a, sizeof(a));
+        if ( res )
+            return res;
+
+        res = fdt_property(kinfo->fdt, "linux,initrd-end", &a, sizeof(a));
+        if ( res )
+            return res;
+    }
+
+    res = fdt_end_node(fdt);
+
+    return res;
+}
+#endif
+
 static int __init map_irq_to_domain(struct domain *d, unsigned int irq,
                                     bool need_mapping, const char *devname)
 {
@@ -1424,47 +1472,6 @@ static int __init acpi_route_spis(struct domain *d)
     return 0;
 }
 
-static int __init acpi_make_chosen_node(const struct kernel_info *kinfo)
-{
-    int res;
-    const char *bootargs = NULL;
-    const struct bootmodule *mod = kinfo->kernel_bootmodule;
-    void *fdt = kinfo->fdt;
-
-    dt_dprintk("Create chosen node\n");
-    res = fdt_begin_node(fdt, "chosen");
-    if ( res )
-        return res;
-
-    if ( mod && mod->cmdline[0] )
-    {
-        bootargs = &mod->cmdline[0];
-        res = fdt_property(fdt, "bootargs", bootargs, strlen(bootargs) + 1);
-        if ( res )
-           return res;
-    }
-
-    /*
-     * If the bootloader provides an initrd, we must create a placeholder
-     * for the initrd properties. The values will be replaced later.
-     */
-    if ( mod && mod->size )
-    {
-        u64 a = 0;
-        res = fdt_property(kinfo->fdt, "linux,initrd-start", &a, sizeof(a));
-        if ( res )
-            return res;
-
-        res = fdt_property(kinfo->fdt, "linux,initrd-end", &a, sizeof(a));
-        if ( res )
-            return res;
-    }
-
-    res = fdt_end_node(fdt);
-
-    return res;
-}
-
 static int __init acpi_make_hypervisor_node(const struct kernel_info *kinfo,
                                             struct membank tbl_add[])
 {
@@ -1537,7 +1544,7 @@ static int __init create_acpi_dtb(struct kernel_info *kinfo,
         return ret;
 
     /* Create a chosen node for DOM0 */
-    ret = acpi_make_chosen_node(kinfo);
+    ret = make_chosen_node(kinfo);
     if ( ret )
         goto err;
 
-- 
1.9.1


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

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

* [PATCH v3 08/25] xen/arm: increase MAX_MODULES
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (6 preceding siblings ...)
  2018-07-31 23:27 ` [PATCH v3 07/25] xen/arm: rename acpi_make_chosen_node to make_chosen_node Stefano Stabellini
@ 2018-07-31 23:27 ` Stefano Stabellini
  2018-07-31 23:27 ` [PATCH v3 09/25] xen/arm: introduce bootcmdlines Stefano Stabellini
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:27 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Xen boot modules need to account not just for Dom0 but also for a few
potential DomUs, each of them coming with their own kernel and initrd.
Increase MAX_MODULES to 32 to allow for more DomUs.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
Reviewed-by: Doug Goldstein <cardoe@cardoe.com>
---
 xen/include/asm-arm/setup.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
index 0cc3330..f1e4a3f 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -8,7 +8,7 @@
 
 #define NR_MEM_BANKS 128
 
-#define MAX_MODULES 5 /* Current maximum useful modules */
+#define MAX_MODULES 32 /* Current maximum useful modules */
 
 typedef enum {
     BOOTMOD_XEN,
-- 
1.9.1


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

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

* [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree
@ 2018-07-31 23:27 Stefano Stabellini
  2018-07-31 23:27 ` [PATCH v3 01/25] xen: allow console_io hypercalls from certain DomUs Stefano Stabellini
                   ` (25 more replies)
  0 siblings, 26 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:27 UTC (permalink / raw)
  To: julien.grall; +Cc: sstabellini, andrii_anisov, xen-devel

Hi all,

This is first step toward "dom0less" as discussed in the various
certifications related threads and discussions.

The goal of this series is to enable Xen to boot multiple domains in
parallel, in addition to dom0, out of information found on device tree.

The device tree based boot protocol is extended to carry information
about DomUs. Based on that information, Xen creates and starts one or
more DomUs. DomUs created this way don't have access to xenstore for the
moment. This is actually OK, because this is meant for mission critical
applications that typically only access directly assigned devices. They
cannot tolerate interference or increased IRQ latency due to PV
protocols. Device assignment is not actually covered by this series, it
will be added later.

DomUs can print to the Xen serial using the CONSOLEIO hypercalls. A
virtual PL011 is also emulated for them so that they can use their
regular PL011 driver. This allows unmodified guests to run as Xen on ARM
guests -- no Xen support needed at all. Console input also comes from
the Xen serial: the Ctrl-AAA switching mechanism is extended to switch
among domUs, dom0, and Xen.

In this version of the series, I reordered the patches to make sure they
are all bisectable.


Cheers,

Stefano


The following changes since commit f1ad5ff73e7d07e6a18488430583168a857f2847:

  xen/arm: setup: Move in init code only used at boot in setup.c (2018-07-11 12:22:17 -0700)

are available in the git repository at:

  http://xenbits.xenproject.org/git-http/people/sstabellini/xen-unstable.git dom0less-v3

for you to fetch changes up to 15d869b83e3618ae637003711bd28dc847b9fe39:

  xen/arm: split domain_build.c (2018-07-27 19:39:42 -0700)

----------------------------------------------------------------
Stefano Stabellini (25):
      xen: allow console_io hypercalls from certain DomUs
      xen/arm: move a few DT related defines to public/device_tree_defs.h
      xen/arm: extend device tree based multiboot protocol
      xen/arm: document dom0less
      xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node
      xen/arm: move evtchn_allocate call out of make_hypervisor_node
      xen/arm: rename acpi_make_chosen_node to make_chosen_node
      xen/arm: increase MAX_MODULES
      xen/arm: introduce bootcmdlines
      xen/arm: don't add duplicate boot modules
      xen/arm: probe domU kernels and initrds
      xen/arm: refactor construct_dom0
      xen/arm: introduce create_domUs
      xen/arm: introduce construct_domU
      xen/arm: rename get_11_allocation_size to get_allocation_size
      xen/arm: rename allocate_memory to allocate_memory_11
      xen/arm: introduce allocate_memory
      xen/arm: generate a simple device tree for domUs
      xen/arm: generate vpl011 node on device tree for domU
      xen/arm: introduce a union in vpl011
      xen/arm: refactor vpl011_data_avail
      xen/arm: Allow vpl011 to be used by DomU
      xen: support console_switching between Dom0 and DomUs on ARM
      xen/vpl011: buffer out chars when the backend is xen
      xen/arm: split domain_build.c

 docs/misc/arm/device-tree/booting.txt |  107 +++
 docs/misc/arm/dom0less                |   47 ++
 tools/libxl/libxl_arm.c               |   59 +-
 xen/arch/arm/acpi/Makefile            |    1 +
 xen/arch/arm/acpi/acpi_dt_build.c     |  591 ++++++++++++++++
 xen/arch/arm/acpi/acpi_dt_build.h     |   32 +
 xen/arch/arm/bootfdt.c                |   69 +-
 xen/arch/arm/domain_build.c           | 1189 +++++++++++++++------------------
 xen/arch/arm/kernel.c                 |   49 +-
 xen/arch/arm/kernel.h                 |    6 +-
 xen/arch/arm/setup.c                  |   68 +-
 xen/arch/arm/vpl011.c                 |  281 ++++++--
 xen/common/device_tree.c              |    6 +-
 xen/drivers/char/console.c            |   71 +-
 xen/include/asm-arm/irq.h             |   16 +
 xen/include/asm-arm/setup.h           |   26 +-
 xen/include/asm-arm/vpl011.h          |   19 +-
 xen/include/asm-x86/setup.h           |    2 +
 xen/include/public/device_tree_defs.h |   42 ++
 xen/include/xen/console.h             |    2 +
 xen/include/xen/device_tree.h         |   35 +-
 xen/include/xen/sched.h               |    2 +
 xen/include/xsm/dummy.h               |    2 +
 23 files changed, 1910 insertions(+), 812 deletions(-)
 create mode 100644 docs/misc/arm/dom0less
 create mode 100644 xen/arch/arm/acpi/acpi_dt_build.c
 create mode 100644 xen/arch/arm/acpi/acpi_dt_build.h
 create mode 100644 xen/include/public/device_tree_defs.h

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

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

* [PATCH v3 09/25] xen/arm: introduce bootcmdlines
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (7 preceding siblings ...)
  2018-07-31 23:27 ` [PATCH v3 08/25] xen/arm: increase MAX_MODULES Stefano Stabellini
@ 2018-07-31 23:27 ` Stefano Stabellini
  2018-08-01 10:51   ` Julien Grall
  2018-07-31 23:27 ` [PATCH v3 10/25] xen/arm: don't add duplicate boot modules Stefano Stabellini
                   ` (16 subsequent siblings)
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:27 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Introduce a new array to store the cmdline of each boot module. It is
separate from struct bootmodules. Remove the cmdline field from struct
boot_module. This way, kernels and initrds with the same address in
memory can share struct bootmodule (important because we want them to be
free'd only once), but they can still have their separate bootcmdline
entries.

Add a dt_name field to struct bootcmdline to make it easier to find the
correct entry. Store the name of the "xen,domain" compatible node (for
example "Dom1"). This is a better choice compared to the name of the
"multiboot,kernel" compatible node, because their names are not unique.
For instance there can be more than one "module@0x4c000000" in the
system, but there can only be one "/chosen/Dom1".

Add a pointer to struct kernel_info to point to the cmdline for a given
kernel.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

---

Changes in v3:
- introduce bootcmdlines
- do not modify boot_fdt_cmdline
- add comments

Changes in v2:
- new patch
---
 xen/arch/arm/bootfdt.c      | 66 +++++++++++++++++++++++++++++++--------------
 xen/arch/arm/domain_build.c |  8 +++---
 xen/arch/arm/kernel.h       |  1 +
 xen/arch/arm/setup.c        | 23 +++++++++++-----
 xen/include/asm-arm/setup.h | 16 +++++++++--
 5 files changed, 82 insertions(+), 32 deletions(-)

diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
index 8eba42c..6f44022 100644
--- a/xen/arch/arm/bootfdt.c
+++ b/xen/arch/arm/bootfdt.c
@@ -163,6 +163,38 @@ static void __init process_memory_node(const void *fdt, int node,
     }
 }
 
+static void __init add_boot_cmdline(const void *fdt, int node,
+                                    const char *name, bootmodule_kind kind)
+{
+    struct bootcmdlines *mods = &bootinfo.cmdlines;
+    struct bootcmdline *mod;
+    const struct fdt_property *prop;
+    int len;
+    const char *cmdline;
+
+    if ( mods->nr_mods == MAX_MODULES )
+    {
+        printk("Ignoring %s boot module (too many)\n", name);
+        return;
+    }
+
+    mod = &mods->cmdline[mods->nr_mods++];
+    mod->kind = kind;
+
+    if ( strlen(name) > DT_MAX_NAME )
+        panic("module %s name too long\n", name);
+    safe_strcpy(mod->dt_name, name);
+
+    prop = fdt_get_property(fdt, node, "bootargs", &len);
+    if ( prop )
+    {
+        if ( len > BOOTMOD_MAX_CMDLINE )
+            panic("module %s command line too long\n", name);
+        cmdline = prop->data;
+        safe_strcpy(mod->cmdline, cmdline);
+    }
+}
+
 static void __init process_multiboot_node(const void *fdt, int node,
                                           const char *name,
                                           u32 address_cells, u32 size_cells)
@@ -172,8 +204,12 @@ static void __init process_multiboot_node(const void *fdt, int node,
     const __be32 *cell;
     bootmodule_kind kind;
     paddr_t start, size;
-    const char *cmdline;
     int len;
+    int parent_node;
+
+    parent_node = fdt_parent_offset(fdt, node);
+    if ( parent_node < 0 )
+        panic("node %s missing a parent\n", name);
 
     prop = fdt_get_property(fdt, node, "reg", &len);
     if ( !prop )
@@ -220,17 +256,8 @@ static void __init process_multiboot_node(const void *fdt, int node,
             kind = BOOTMOD_XSM;
     }
 
-    prop = fdt_get_property(fdt, node, "bootargs", &len);
-    if ( prop )
-    {
-        if ( len > BOOTMOD_MAX_CMDLINE )
-            panic("module %s command line too long\n", name);
-        cmdline = prop->data;
-    }
-    else
-        cmdline = NULL;
-
-    add_boot_module(kind, start, size, cmdline);
+    add_boot_module(kind, start, size);
+    add_boot_cmdline(fdt, node, fdt_get_name(fdt, parent_node, &len), kind);
 }
 
 static void __init process_chosen_node(const void *fdt, int node,
@@ -276,7 +303,7 @@ static void __init process_chosen_node(const void *fdt, int node,
 
     printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end);
 
-    add_boot_module(BOOTMOD_RAMDISK, start, end-start, NULL);
+    add_boot_module(BOOTMOD_RAMDISK, start, end-start);
 }
 
 static int __init early_scan_node(const void *fdt,
@@ -307,12 +334,11 @@ static void __init early_print_info(void)
                      mi->bank[i].start + mi->bank[i].size - 1);
     printk("\n");
     for ( i = 0 ; i < mods->nr_mods; i++ )
-        printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s %s\n",
+        printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s\n",
                      i,
                      mods->module[i].start,
                      mods->module[i].start + mods->module[i].size,
-                     boot_module_kind_as_string(mods->module[i].kind),
-                     mods->module[i].cmdline);
+                     boot_module_kind_as_string(mods->module[i].kind));
     nr_rsvd = fdt_num_mem_rsv(device_tree_flattened);
     for ( i = 0; i < nr_rsvd; i++ )
     {
@@ -341,7 +367,7 @@ size_t __init boot_fdt_info(const void *fdt, paddr_t paddr)
     if ( ret < 0 )
         panic("No valid device tree\n");
 
-    add_boot_module(BOOTMOD_FDT, paddr, fdt_totalsize(fdt), NULL);
+    add_boot_module(BOOTMOD_FDT, paddr, fdt_totalsize(fdt));
 
     device_tree_for_each_node((void *)fdt, early_scan_node, NULL);
     early_print_info();
@@ -361,11 +387,11 @@ const char *boot_fdt_cmdline(const void *fdt)
     prop = fdt_get_property(fdt, node, "xen,xen-bootargs", NULL);
     if ( prop == NULL )
     {
-        struct bootmodule *dom0_mod =
-            boot_module_find_by_kind(BOOTMOD_KERNEL);
+        struct bootcmdline *dom0_cmdline =
+            boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
 
         if (fdt_get_property(fdt, node, "xen,dom0-bootargs", NULL) ||
-            ( dom0_mod && dom0_mod->cmdline[0] ) )
+            ( dom0_cmdline && dom0_cmdline->cmdline[0] ) )
             prop = fdt_get_property(fdt, node, "bootargs", NULL);
     }
     if ( prop == NULL )
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index cd47a68..eba1b77 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -375,7 +375,7 @@ static int __init write_properties(struct domain *d, struct kernel_info *kinfo,
     int res = 0;
     int had_dom0_bootargs = 0;
 
-    const struct bootmodule *kernel = kinfo->kernel_bootmodule;
+    const struct bootcmdline *kernel = boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
 
     if ( kernel && kernel->cmdline[0] )
         bootargs = &kernel->cmdline[0];
@@ -950,9 +950,9 @@ static int __init make_chosen_node(const struct kernel_info *kinfo)
     if ( res )
         return res;
 
-    if ( mod && mod->cmdline[0] )
+    if ( kinfo->cmdline && kinfo->cmdline[0] )
     {
-        bootargs = &mod->cmdline[0];
+        bootargs = &kinfo->cmdline[0];
         res = fdt_property(fdt, "bootargs", bootargs, strlen(bootargs) + 1);
         if ( res )
            return res;
@@ -2108,6 +2108,7 @@ static void __init find_gnttab_region(struct domain *d,
 
 int __init construct_dom0(struct domain *d)
 {
+    const struct bootcmdline *kernel = boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
     struct kernel_info kinfo = {};
     struct vcpu *saved_current;
     int rc, i, cpu;
@@ -2153,6 +2154,7 @@ int __init construct_dom0(struct domain *d)
 
 #endif
 
+    kinfo.cmdline = kernel != NULL ? &kernel->cmdline[0] : NULL;
     allocate_memory(d, &kinfo);
     find_gnttab_region(d, &kinfo);
 
diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
index 47eacb5..39b7828 100644
--- a/xen/arch/arm/kernel.h
+++ b/xen/arch/arm/kernel.h
@@ -29,6 +29,7 @@ struct kernel_info {
 
     /* boot blob load addresses */
     const struct bootmodule *kernel_bootmodule, *initrd_bootmodule;
+    const char* cmdline;
     paddr_t dtb_paddr;
     paddr_t initrd_paddr;
 
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 7d40a84..67ab1fd 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -200,8 +200,7 @@ void __init dt_unreserved_regions(paddr_t s, paddr_t e,
 }
 
 struct bootmodule __init *add_boot_module(bootmodule_kind kind,
-                                          paddr_t start, paddr_t size,
-                                          const char *cmdline)
+                                          paddr_t start, paddr_t size)
 {
     struct bootmodules *mods = &bootinfo.modules;
     struct bootmodule *mod;
@@ -217,10 +216,6 @@ struct bootmodule __init *add_boot_module(bootmodule_kind kind,
     mod->kind = kind;
     mod->start = start;
     mod->size = size;
-    if ( cmdline )
-        safe_strcpy(mod->cmdline, cmdline);
-    else
-        mod->cmdline[0] = 0;
 
     return mod;
 }
@@ -239,6 +234,20 @@ struct bootmodule * __init boot_module_find_by_kind(bootmodule_kind kind)
     return NULL;
 }
 
+struct bootcmdline * __init boot_cmdline_find_by_kind(bootmodule_kind kind)
+{
+    struct bootcmdlines *mods = &bootinfo.cmdlines;
+    struct bootcmdline *mod;
+    int i;
+    for (i = 0 ; i < mods->nr_mods ; i++ )
+    {
+        mod = &mods->cmdline[i];
+        if ( mod->kind == kind )
+            return mod;
+    }
+    return NULL;
+}
+
 const char * __init boot_module_kind_as_string(bootmodule_kind kind)
 {
     switch ( kind )
@@ -723,7 +732,7 @@ void __init start_xen(unsigned long boot_phys_offset,
     /* Register Xen's load address as a boot module. */
     xen_bootmodule = add_boot_module(BOOTMOD_XEN,
                              (paddr_t)(uintptr_t)(_start + boot_phys_offset),
-                             (paddr_t)(uintptr_t)(_end - _start + 1), NULL);
+                             (paddr_t)(uintptr_t)(_end - _start + 1));
     BUG_ON(!xen_bootmodule);
 
     xen_paddr = get_xen_paddr();
diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
index f1e4a3f..cb7da51 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -35,6 +35,12 @@ struct bootmodule {
     bootmodule_kind kind;
     paddr_t start;
     paddr_t size;
+};
+
+#define DT_MAX_NAME 32
+struct bootcmdline {
+    bootmodule_kind kind;
+    char dt_name[DT_MAX_NAME];
     char cmdline[BOOTMOD_MAX_CMDLINE];
 };
 
@@ -43,9 +49,15 @@ struct bootmodules {
     struct bootmodule module[MAX_MODULES];
 };
 
+struct bootcmdlines {
+    int nr_mods;
+    struct bootcmdline cmdline[MAX_MODULES];
+};
+
 struct bootinfo {
     struct meminfo mem;
     struct bootmodules modules;
+    struct bootcmdlines cmdlines;
 #ifdef CONFIG_ACPI
     struct meminfo acpi;
 #endif
@@ -78,9 +90,9 @@ size_t __init boot_fdt_info(const void *fdt, paddr_t paddr);
 const char __init *boot_fdt_cmdline(const void *fdt);
 
 struct bootmodule *add_boot_module(bootmodule_kind kind,
-                                   paddr_t start, paddr_t size,
-                                   const char *cmdline);
+                                   paddr_t start, paddr_t size);
 struct bootmodule *boot_module_find_by_kind(bootmodule_kind kind);
+struct bootcmdline *boot_cmdline_find_by_kind(bootmodule_kind kind);
 const char * __init boot_module_kind_as_string(bootmodule_kind kind);
 
 #endif
-- 
1.9.1


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

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

* [PATCH v3 10/25] xen/arm: don't add duplicate boot modules
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (8 preceding siblings ...)
  2018-07-31 23:27 ` [PATCH v3 09/25] xen/arm: introduce bootcmdlines Stefano Stabellini
@ 2018-07-31 23:27 ` Stefano Stabellini
  2018-08-01 11:06   ` Julien Grall
  2018-07-31 23:27 ` [PATCH v3 11/25] xen/arm: probe domU kernels and initrds Stefano Stabellini
                   ` (15 subsequent siblings)
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:27 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Don't add duplicate boot modules (same kind and same start address).

Mark kernels and ramdisks of "xen,domain" nodes as BOOTMOD_KERNEL_DOMAIN
and BOOTMOD_RAMDISK_DOMAIN respectively, to avoid getting confused in
kernel_probe, where we try to guess which is the dom0 kernel and initrd
to be compatible with older versions of the multiboot spec.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

---
Changes in v2:
- new patch
---
 xen/arch/arm/bootfdt.c      | 7 +++++++
 xen/arch/arm/setup.c        | 9 +++++++++
 xen/include/asm-arm/setup.h | 2 ++
 3 files changed, 18 insertions(+)

diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
index 6f44022..dbaa8f4 100644
--- a/xen/arch/arm/bootfdt.c
+++ b/xen/arch/arm/bootfdt.c
@@ -256,6 +256,13 @@ static void __init process_multiboot_node(const void *fdt, int node,
             kind = BOOTMOD_XSM;
     }
 
+    if ( fdt_node_check_compatible(fdt, parent_node, "xen,domain") == 0 )
+    {
+        if ( kind == BOOTMOD_KERNEL )
+            kind = BOOTMOD_KERNEL_DOMAIN;
+        if ( kind == BOOTMOD_RAMDISK )
+            kind = BOOTMOD_RAMDISK_DOMAIN;
+    }
     add_boot_module(kind, start, size);
     add_boot_cmdline(fdt, node, fdt_get_name(fdt, parent_node, &len), kind);
 }
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 67ab1fd..b1a117f 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -204,6 +204,7 @@ struct bootmodule __init *add_boot_module(bootmodule_kind kind,
 {
     struct bootmodules *mods = &bootinfo.modules;
     struct bootmodule *mod;
+    int i;
 
     if ( mods->nr_mods == MAX_MODULES )
     {
@@ -211,6 +212,12 @@ struct bootmodule __init *add_boot_module(bootmodule_kind kind,
                boot_module_kind_as_string(kind), start, start + size);
         return NULL;
     }
+    for ( i = 0 ; i < mods->nr_mods ; i++ )
+    {
+        mod = &mods->module[i];
+        if ( mod->kind == kind && mod->start == start )
+            return mod;
+    }
 
     mod = &mods->module[mods->nr_mods++];
     mod->kind = kind;
@@ -257,6 +264,8 @@ const char * __init boot_module_kind_as_string(bootmodule_kind kind)
     case BOOTMOD_KERNEL:  return "Kernel";
     case BOOTMOD_RAMDISK: return "Ramdisk";
     case BOOTMOD_XSM:     return "XSM";
+    case BOOTMOD_KERNEL_DOMAIN:  return "DomU Kernel";
+    case BOOTMOD_RAMDISK_DOMAIN: return "DomU Ramdisk";
     case BOOTMOD_UNKNOWN: return "Unknown";
     default: BUG();
     }
diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
index cb7da51..353c32a 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -16,6 +16,8 @@ typedef enum {
     BOOTMOD_KERNEL,
     BOOTMOD_RAMDISK,
     BOOTMOD_XSM,
+    BOOTMOD_KERNEL_DOMAIN,
+    BOOTMOD_RAMDISK_DOMAIN,
     BOOTMOD_UNKNOWN
 }  bootmodule_kind;
 
-- 
1.9.1


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

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

* [PATCH v3 11/25] xen/arm: probe domU kernels and initrds
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (9 preceding siblings ...)
  2018-07-31 23:27 ` [PATCH v3 10/25] xen/arm: don't add duplicate boot modules Stefano Stabellini
@ 2018-07-31 23:27 ` Stefano Stabellini
  2018-07-31 23:27 ` [PATCH v3 12/25] xen/arm: refactor construct_dom0 Stefano Stabellini
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:27 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Find addresses, sizes on device tree from kernel_probe.
Find the cmdline from the bootcmdlines array.

Introduce a new boot_module_find_by_addr_and_kind function to match not
just on boot module kind, but also by address so that we can support
multiple domains.

Introduce a boot_cmdline_find_by_name function to find the right struct
cmdline based on the device tree node name of the "xen,domain"
compatible node.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
Changes in v3:
- retrieve cmdline from bootcmdlines array

Changes in v2:
- fix indentation
- unify kernel_probe with kernel_probe_domU
- find cmdline on device_tree from kernel_probe
---
 xen/arch/arm/domain_build.c |  2 +-
 xen/arch/arm/kernel.c       | 49 ++++++++++++++++++++++++++++++++++++++-------
 xen/arch/arm/kernel.h       |  2 +-
 xen/arch/arm/setup.c        | 29 +++++++++++++++++++++++++++
 xen/include/asm-arm/setup.h |  3 +++
 5 files changed, 76 insertions(+), 9 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index eba1b77..8d82849 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -2136,7 +2136,7 @@ int __init construct_dom0(struct domain *d)
     kinfo.unassigned_mem = dom0_mem;
     kinfo.d = d;
 
-    rc = kernel_probe(&kinfo);
+    rc = kernel_probe(&kinfo, NULL);
     if ( rc < 0 )
         return rc;
 
diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
index 000d939..12c6884 100644
--- a/xen/arch/arm/kernel.c
+++ b/xen/arch/arm/kernel.c
@@ -421,22 +421,57 @@ static int __init kernel_zimage32_probe(struct kernel_info *info,
     return 0;
 }
 
-int __init kernel_probe(struct kernel_info *info)
+int __init kernel_probe(struct kernel_info *info, struct dt_device_node *domain) 
 {
-    struct bootmodule *mod = boot_module_find_by_kind(BOOTMOD_KERNEL);
+    struct bootmodule *mod;
+    struct dt_device_node *node;
+    u64 kernel_addr, initrd_addr, size;
+    const char *name = NULL;
     int rc;
 
+    if ( domain == NULL )
+    {
+        mod = boot_module_find_by_kind(BOOTMOD_KERNEL);
+
+        info->kernel_bootmodule = mod;
+        info->initrd_bootmodule = boot_module_find_by_kind(BOOTMOD_RAMDISK);
+    } else {
+        dt_for_each_child_node(domain, node)
+        {
+            if ( dt_device_is_compatible(node, "multiboot,kernel") )
+            {
+                u32 len;
+                const __be32 *val;
+                val = dt_get_property(node, "reg", &len);
+                dt_get_range(&val, node, &kernel_addr, &size);
+            }
+            else if ( dt_device_is_compatible(node, "multiboot,ramdisk") )
+            {
+                u32 len;
+                const __be32 *val;
+                val = dt_get_property(node, "reg", &len);
+                dt_get_range(&val, node, &initrd_addr, &size);
+            }
+            else
+                continue;
+        }
+        if ( kernel_addr )
+            info->kernel_bootmodule = mod = boot_module_find_by_addr_and_kind(
+                                      BOOTMOD_KERNEL_DOMAIN, kernel_addr);
+        if ( initrd_addr )
+            info->initrd_bootmodule = boot_module_find_by_addr_and_kind(
+                                      BOOTMOD_RAMDISK_DOMAIN, initrd_addr);
+        name = dt_node_name(domain);
+        info->cmdline = &boot_cmdline_find_by_name(name)->cmdline[0];
+    }
     if ( !mod || !mod->size )
     {
         printk(XENLOG_ERR "Missing kernel boot module?\n");
         return -ENOENT;
     }
 
-    info->kernel_bootmodule = mod;
-
-    printk("Loading kernel from boot module @ %"PRIpaddr"\n", mod->start);
-
-    info->initrd_bootmodule = boot_module_find_by_kind(BOOTMOD_RAMDISK);
+    printk("Loading DomU kernel from boot module @ %"PRIpaddr"\n",
+           info->kernel_bootmodule->start);
     if ( info->initrd_bootmodule )
         printk("Loading ramdisk from boot module @ %"PRIpaddr"\n",
                info->initrd_bootmodule->start);
diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
index 39b7828..4a65289 100644
--- a/xen/arch/arm/kernel.h
+++ b/xen/arch/arm/kernel.h
@@ -55,7 +55,7 @@ struct kernel_info {
  *  ->type
  *  ->load hook, and sets loader specific variables ->zimage
  */
-int kernel_probe(struct kernel_info *info);
+int kernel_probe(struct kernel_info *info, struct dt_device_node *domain);
 
 /*
  * Loads the kernel into guest RAM.
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index b1a117f..c320df9 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -255,6 +255,35 @@ struct bootcmdline * __init boot_cmdline_find_by_kind(bootmodule_kind kind)
     return NULL;
 }
 
+struct bootcmdline * __init boot_cmdline_find_by_name(const char *name)
+{
+    struct bootcmdlines *mods = &bootinfo.cmdlines;
+    struct bootcmdline *mod;
+    int i;
+    for (i = 0 ; i < mods->nr_mods ; i++ )
+    {
+        mod = &mods->cmdline[i];
+        if ( strcmp(mod->dt_name, name) == 0 )
+            return mod;
+    }
+    return NULL;
+}
+
+struct bootmodule * __init boot_module_find_by_addr_and_kind(bootmodule_kind kind,
+                                                             paddr_t start)
+{
+    struct bootmodules *mods = &bootinfo.modules;
+    struct bootmodule *mod;
+    int i;
+    for (i = 0 ; i < mods->nr_mods ; i++ )
+    {
+        mod = &mods->module[i];
+        if ( mod->kind == kind && mod->start == start )
+            return mod;
+    }
+    return NULL;
+}
+
 const char * __init boot_module_kind_as_string(bootmodule_kind kind)
 {
     switch ( kind )
diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
index 353c32a..4551f72 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -94,7 +94,10 @@ const char __init *boot_fdt_cmdline(const void *fdt);
 struct bootmodule *add_boot_module(bootmodule_kind kind,
                                    paddr_t start, paddr_t size);
 struct bootmodule *boot_module_find_by_kind(bootmodule_kind kind);
+struct bootmodule * __init boot_module_find_by_addr_and_kind(bootmodule_kind kind,
+                                                             paddr_t start);
 struct bootcmdline *boot_cmdline_find_by_kind(bootmodule_kind kind);
+struct bootcmdline * __init boot_cmdline_find_by_name(const char *name);
 const char * __init boot_module_kind_as_string(bootmodule_kind kind);
 
 #endif
-- 
1.9.1


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

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

* [PATCH v3 12/25] xen/arm: refactor construct_dom0
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (10 preceding siblings ...)
  2018-07-31 23:27 ` [PATCH v3 11/25] xen/arm: probe domU kernels and initrds Stefano Stabellini
@ 2018-07-31 23:27 ` Stefano Stabellini
  2018-08-13 10:15   ` Julien Grall
  2018-07-31 23:27 ` [PATCH v3 13/25] xen/arm: introduce create_domUs Stefano Stabellini
                   ` (13 subsequent siblings)
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:27 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Move generic initializations out of construct_dom0 so that they can be
reused.

Rename prepare_dtb to prepare_dtb_hwdom to avoid confusion.

No functional changes in this patch.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

---
Changes in v3:
- move setting type before allocate_memory
- add ifdef around it and a comment
Changes in v2:
- move discard_initial_modules() after __construct_domain()
- remove useless blank line
- leave safety BUG_ONs in __construct_domain
- rename prepare_dtb to prepare_dtb_hwdom
---
 xen/arch/arm/domain_build.c | 128 ++++++++++++++++++++++++--------------------
 1 file changed, 70 insertions(+), 58 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 8d82849..0835340 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1371,7 +1371,7 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
     return res;
 }
 
-static int __init prepare_dtb(struct domain *d, struct kernel_info *kinfo)
+static int __init prepare_dtb_hwdom(struct domain *d, struct kernel_info *kinfo)
 {
     const p2m_type_t default_p2mt = p2m_mmio_direct_c;
     const void *fdt;
@@ -2106,75 +2106,31 @@ static void __init find_gnttab_region(struct domain *d,
            kinfo->gnttab_start, kinfo->gnttab_start + kinfo->gnttab_size);
 }
 
-int __init construct_dom0(struct domain *d)
+static int __init __construct_domain(struct domain *d, struct kernel_info *kinfo)
 {
-    const struct bootcmdline *kernel = boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
-    struct kernel_info kinfo = {};
     struct vcpu *saved_current;
-    int rc, i, cpu;
-
+    int i, cpu;
+    struct cpu_user_regs *regs;
     struct vcpu *v = d->vcpu[0];
-    struct cpu_user_regs *regs = &v->arch.cpu_info->guest_cpu_user_regs;
 
-    /* Sanity! */
-    BUG_ON(d->domain_id != 0);
     BUG_ON(d->vcpu[0] == NULL);
     BUG_ON(v->is_initialised);
 
-    printk("*** LOADING DOMAIN 0 ***\n");
-    if ( dom0_mem <= 0 )
-    {
-        warning_add("PLEASE SPECIFY dom0_mem PARAMETER - USING 512M FOR NOW\n");
-        dom0_mem = MB(512);
-    }
-
-
-    iommu_hwdom_init(d);
-
-    d->max_pages = ~0U;
-
-    kinfo.unassigned_mem = dom0_mem;
-    kinfo.d = d;
-
-    rc = kernel_probe(&kinfo, NULL);
-    if ( rc < 0 )
-        return rc;
+    regs = &v->arch.cpu_info->guest_cpu_user_regs;
 
 #ifdef CONFIG_ARM_64
     /* if aarch32 mode is not supported at EL1 do not allow 32-bit domain */
-    if ( !(cpu_has_el1_32) && kinfo.type == DOMAIN_32BIT )
+    if ( !(cpu_has_el1_32) && kinfo->type == DOMAIN_32BIT )
     {
         printk("Platform does not support 32-bit domain\n");
         return -EINVAL;
     }
-    d->arch.type = kinfo.type;
 
     if ( is_64bit_domain(d) )
         vcpu_switch_to_aarch64_mode(v);
 
 #endif
 
-    kinfo.cmdline = kernel != NULL ? &kernel->cmdline[0] : NULL;
-    allocate_memory(d, &kinfo);
-    find_gnttab_region(d, &kinfo);
-
-    /* Map extra GIC MMIO, irqs and other hw stuffs to dom0. */
-    rc = gic_map_hwdom_extra_mappings(d);
-    if ( rc < 0 )
-        return rc;
-
-    rc = platform_specific_mapping(d);
-    if ( rc < 0 )
-        return rc;
-
-    if ( acpi_disabled )
-        rc = prepare_dtb(d, &kinfo);
-    else
-        rc = prepare_acpi(d, &kinfo);
-
-    if ( rc < 0 )
-        return rc;
-
     /*
      * The following loads use the domain's p2m and require current to
      * be a vcpu of the domain, temporarily switch
@@ -2187,20 +2143,18 @@ int __init construct_dom0(struct domain *d)
      * kernel_load will determine the placement of the kernel as well
      * as the initrd & fdt in RAM, so call it first.
      */
-    kernel_load(&kinfo);
+    kernel_load(kinfo);
     /* initrd_load will fix up the fdt, so call it before dtb_load */
-    initrd_load(&kinfo);
-    dtb_load(&kinfo);
+    initrd_load(kinfo);
+    dtb_load(kinfo);
 
     /* Now that we are done restore the original p2m and current. */
     set_current(saved_current);
     p2m_restore_state(saved_current);
 
-    discard_initial_modules();
-
     memset(regs, 0, sizeof(*regs));
 
-    regs->pc = (register_t)kinfo.entry;
+    regs->pc = (register_t)kinfo->entry;
 
     if ( is_32bit_domain(d) )
     {
@@ -2218,14 +2172,14 @@ int __init construct_dom0(struct domain *d)
          */
         regs->r0 = 0; /* SBZ */
         regs->r1 = 0xffffffff; /* We use DTB therefore no machine id */
-        regs->r2 = kinfo.dtb_paddr;
+        regs->r2 = kinfo->dtb_paddr;
     }
 #ifdef CONFIG_ARM_64
     else
     {
         regs->cpsr = PSR_GUEST64_INIT;
         /* From linux/Documentation/arm64/booting.txt */
-        regs->x0 = kinfo.dtb_paddr;
+        regs->x0 = kinfo->dtb_paddr;
         regs->x1 = 0; /* Reserved for future use */
         regs->x2 = 0; /* Reserved for future use */
         regs->x3 = 0; /* Reserved for future use */
@@ -2251,6 +2205,64 @@ int __init construct_dom0(struct domain *d)
     return 0;
 }
 
+int __init construct_dom0(struct domain *d)
+{
+    const struct bootcmdline *kernel = boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
+    struct kernel_info kinfo = {};
+    int rc;
+
+    /* Sanity! */
+    BUG_ON(d->domain_id != 0);
+
+    printk("*** LOADING DOMAIN 0 ***\n");
+    if ( dom0_mem <= 0 )
+    {
+        warning_add("PLEASE SPECIFY dom0_mem PARAMETER - USING 512M FOR NOW\n");
+        dom0_mem = MB(512);
+    }
+
+    iommu_hwdom_init(d);
+
+    d->max_pages = ~0U;
+
+    kinfo.unassigned_mem = dom0_mem;
+    kinfo.d = d;
+
+    rc = kernel_probe(&kinfo, NULL);
+    if ( rc < 0 )
+        return rc;
+
+    kinfo.cmdline = kernel != NULL ? &kernel->cmdline[0] : NULL;
+#ifdef CONFIG_ARM_64
+    /* type must be set before allocate_memory */
+    d->arch.type = kinfo.type;
+#endif
+    allocate_memory(d, &kinfo);
+    find_gnttab_region(d, &kinfo);
+
+    /* Map extra GIC MMIO, irqs and other hw stuffs to dom0. */
+    rc = gic_map_hwdom_extra_mappings(d);
+    if ( rc < 0 )
+        return rc;
+
+    rc = platform_specific_mapping(d);
+    if ( rc < 0 )
+        return rc;
+
+    if ( acpi_disabled )
+        rc = prepare_dtb_hwdom(d, &kinfo);
+    else
+        rc = prepare_acpi(d, &kinfo);
+
+    if ( rc < 0 )
+        return rc;
+
+
+    rc = __construct_domain(d, &kinfo);
+    discard_initial_modules();
+    return rc;
+}
+
 /*
  * Local variables:
  * mode: C
-- 
1.9.1


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

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

* [PATCH v3 13/25] xen/arm: introduce create_domUs
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (11 preceding siblings ...)
  2018-07-31 23:27 ` [PATCH v3 12/25] xen/arm: refactor construct_dom0 Stefano Stabellini
@ 2018-07-31 23:27 ` Stefano Stabellini
  2018-08-01  8:48   ` Jan Beulich
                     ` (2 more replies)
  2018-07-31 23:27 ` [PATCH v3 14/25] xen/arm: introduce construct_domU Stefano Stabellini
                   ` (12 subsequent siblings)
  25 siblings, 3 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:27 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, sstabellini, andrii_anisov, andrew.cooper3,
	xen-devel, jbeulich

Call a new function, "create_domUs", from setup_xen to start DomU VMs.

Introduce support for the "xen,domU" compatible node on device tree.
Create new DomU VMs based on the information found on device tree under
"xen,domU". Calls construct_domU for each domain.

Introduce a simple global variable named max_init_domid to keep track of
the initial allocated domids. It holds the max domid among the initial
domains.

Move the discard_initial_modules after DomUs have been built.

First create domUs, then start dom0 -- no point in trying to start dom0
when the cpu is busy.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
CC: andrew.cooper3@citrix.com
CC: jbeulich@suse.com
---
Changes in v3:
- move patch earlier and introduce empty construct_domU to fix bisection
  builds
- fix max_init_domid to actually hold the max domid among initial
  domains (instead of max_domid + 1)
- move domain_unpause_by_systemcontroller(dom0) after creating domUs

Changes in v2:
- coding style
- set nr_spis to 32
- introduce create_domUs
---
 xen/arch/arm/domain_build.c | 42 +++++++++++++++++++++++++++++++++++++++---
 xen/arch/arm/setup.c        |  7 ++++++-
 xen/include/asm-arm/setup.h |  3 +++
 xen/include/asm-x86/setup.h |  2 ++
 4 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 0835340..8f7ac54 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -7,6 +7,7 @@
 #include <asm/irq.h>
 #include <asm/regs.h>
 #include <xen/errno.h>
+#include <xen/err.h>
 #include <xen/device_tree.h>
 #include <xen/libfdt/libfdt.h>
 #include <xen/guest_access.h>
@@ -2205,6 +2206,43 @@ static int __init __construct_domain(struct domain *d, struct kernel_info *kinfo
     return 0;
 }
 
+static int __init construct_domU(struct domain *d, struct dt_device_node *node)
+{
+    return 0;
+}
+
+void __init create_domUs(void)
+{
+    struct dt_device_node *node;
+    struct dt_device_node *chosen = dt_find_node_by_name(dt_host, "chosen");
+
+    if ( chosen != NULL )
+    {
+        dt_for_each_child_node(chosen, node)
+        {
+            struct domain *d;
+            struct xen_domctl_createdomain d_cfg = {
+                .arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE,
+                .arch.nr_spis = 32,
+            };
+
+            if ( !dt_device_is_compatible(node, "xen,domain") )
+                continue;
+
+            d = domain_create(++max_init_domid, &d_cfg, false);
+            if ( IS_ERR(d) )
+                panic("Error creating domain %s", dt_node_name(node));
+
+            d->is_console = 1;
+
+            if ( construct_domU(d, node) != 0 )
+                panic("Could not set up domain %s", dt_node_name(node));
+
+            domain_unpause_by_systemcontroller(d);
+        }
+    }
+}
+
 int __init construct_dom0(struct domain *d)
 {
     const struct bootcmdline *kernel = boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
@@ -2258,9 +2296,7 @@ int __init construct_dom0(struct domain *d)
         return rc;
 
 
-    rc = __construct_domain(d, &kinfo);
-    discard_initial_modules();
-    return rc;
+    return __construct_domain(d, &kinfo);
 }
 
 /*
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index c320df9..096484f 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -63,8 +63,11 @@ static unsigned long opt_xenheap_megabytes __initdata;
 integer_param("xenheap_megabytes", opt_xenheap_megabytes);
 #endif
 
+domid_t __read_mostly max_init_domid = 0;
+
 static __used void init_done(void)
 {
+    discard_initial_modules();
     free_init_memory();
     startup_cpu_idle_loop();
 }
@@ -894,7 +897,7 @@ void __init start_xen(unsigned long boot_phys_offset,
     dom0_cfg.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
     dom0_cfg.arch.nr_spis = gic_number_lines() - 32;
 
-    dom0 = domain_create(0, &dom0_cfg, true);
+    dom0 = domain_create(max_init_domid, &dom0_cfg, true);
     if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
             panic("Error creating domain 0");
 
@@ -915,6 +918,8 @@ void __init start_xen(unsigned long boot_phys_offset,
     /* Must be done past setting system_state. */
     unregister_init_virtual_region();
 
+    create_domUs();
+
     domain_unpause_by_systemcontroller(dom0);
 
     /* Switch on to the dynamically allocated stack for the idle vcpu
diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
index 4551f72..d9cd8e1 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -67,6 +67,8 @@ struct bootinfo {
 
 extern struct bootinfo bootinfo;
 
+extern domid_t max_init_domid;
+
 void arch_init_memory(void);
 
 void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len);
@@ -83,6 +85,7 @@ void acpi_create_efi_mmap_table(struct domain *d,
 int acpi_make_efi_nodes(void *fdt, struct membank tbl_add[]);
 
 int construct_dom0(struct domain *d);
+void __init create_domUs(void);
 
 void discard_initial_modules(void);
 void dt_unreserved_regions(paddr_t s, paddr_t e,
diff --git a/xen/include/asm-x86/setup.h b/xen/include/asm-x86/setup.h
index 8d4b9ee..c0bd86f 100644
--- a/xen/include/asm-x86/setup.h
+++ b/xen/include/asm-x86/setup.h
@@ -66,4 +66,6 @@ extern bool opt_dom0_shadow;
 #endif
 extern bool dom0_pvh;
 
+#define max_init_domid (0)
+
 #endif
-- 
1.9.1


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

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

* [PATCH v3 14/25] xen/arm: introduce construct_domU
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (12 preceding siblings ...)
  2018-07-31 23:27 ` [PATCH v3 13/25] xen/arm: introduce create_domUs Stefano Stabellini
@ 2018-07-31 23:27 ` Stefano Stabellini
  2018-08-13 10:55   ` Julien Grall
  2018-07-31 23:27 ` [PATCH v3 15/25] xen/arm: rename get_11_allocation_size to get_allocation_size Stefano Stabellini
                   ` (11 subsequent siblings)
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:27 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Similar to construct_dom0, construct_domU creates a barebone DomU guest.

The device tree node passed as argument is compatible "xen,domain", see
docs/misc/arm/device-tree/booting.txt.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

---
Changes in v3:
- move setting type before allocate_memory
- add ifdef around it and a comment

Changes in v2:
- rename mem to memory
- make cpus and memory mandatory
- remove wront comment from commit message
- cpus and memory are read as integers
- read the vpl011 option
---
 xen/arch/arm/domain_build.c | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 8f7ac54..101cca2 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -2208,7 +2208,41 @@ static int __init __construct_domain(struct domain *d, struct kernel_info *kinfo
 
 static int __init construct_domU(struct domain *d, struct dt_device_node *node)
 {
-    return 0;
+    struct kernel_info kinfo = {};
+    int rc;
+    u32 mem;
+
+    printk("*** LOADING DOMU ***\n");
+
+    rc = dt_property_read_u32(node, "cpus", &d->max_vcpus);
+    if ( !rc )
+        return -EINVAL;
+
+    rc = dt_property_read_u32(node, "memory", &mem);
+    if ( !rc )
+        return -EINVAL;
+    kinfo.unassigned_mem = (paddr_t)mem << 10;
+
+    d->vcpu = xzalloc_array(struct vcpu *, d->max_vcpus);
+    if ( !d->vcpu )
+        return -ENOMEM;;
+    if ( alloc_vcpu(d, 0, 0) == NULL )
+        return -ENOMEM;
+    d->max_pages = ~0U;
+
+    kinfo.d = d;
+
+    rc = kernel_probe(&kinfo, node);
+    if ( rc < 0 )
+        return rc;
+
+#ifdef CONFIG_ARM_64
+    /* type must be set before allocate memory */
+    d->arch.type = kinfo.type;
+#endif
+    allocate_memory(d, &kinfo);
+
+    return __construct_domain(d, &kinfo);
 }
 
 void __init create_domUs(void)
-- 
1.9.1


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

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

* [PATCH v3 15/25] xen/arm: rename get_11_allocation_size to get_allocation_size
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (13 preceding siblings ...)
  2018-07-31 23:27 ` [PATCH v3 14/25] xen/arm: introduce construct_domU Stefano Stabellini
@ 2018-07-31 23:27 ` Stefano Stabellini
  2018-07-31 23:27 ` [PATCH v3 16/25] xen/arm: rename allocate_memory to allocate_memory_11 Stefano Stabellini
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:27 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

No functional changes.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

---

Changes in v3:
- no change in print messages
- do not remove BUG_ON

Changes in v2:
- new patch
---
 xen/arch/arm/domain_build.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 101cca2..066dd75 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -78,7 +78,7 @@ struct vcpu *__init alloc_dom0_vcpu0(struct domain *dom0)
     return alloc_vcpu(dom0, 0, 0);
 }
 
-static unsigned int __init get_11_allocation_size(paddr_t size)
+static unsigned int __init get_allocation_size(paddr_t size)
 {
     /*
      * get_order_from_bytes returns the order greater than or equal to
@@ -250,7 +250,7 @@ static void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
         get_order_from_bytes(min_t(paddr_t, dom0_mem, MB(128)));
     const unsigned int min_order = get_order_from_bytes(MB(4));
     struct page_info *pg;
-    unsigned int order = get_11_allocation_size(kinfo->unassigned_mem);
+    unsigned int order = get_allocation_size(kinfo->unassigned_mem);
     int i;
 
     bool lowmem = true;
@@ -302,7 +302,7 @@ static void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
      * If we failed to allocate bank0 under 4GB, continue allocating
      * memory from above 4GB and fill in banks.
      */
-    order = get_11_allocation_size(kinfo->unassigned_mem);
+    order = get_allocation_size(kinfo->unassigned_mem);
     while ( kinfo->unassigned_mem && kinfo->mem.nr_banks < NR_MEM_BANKS )
     {
         pg = alloc_domheap_pages(d, order, lowmem ? MEMF_bits(32) : 0);
@@ -313,7 +313,7 @@ static void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
             if ( lowmem && order < min_low_order)
             {
                 D11PRINT("Failed at min_low_order, allow high allocations\n");
-                order = get_11_allocation_size(kinfo->unassigned_mem);
+                order = get_allocation_size(kinfo->unassigned_mem);
                 lowmem = false;
                 continue;
             }
@@ -333,7 +333,7 @@ static void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
             if ( lowmem )
             {
                 D11PRINT("Allocation below bank 0, allow high allocations\n");
-                order = get_11_allocation_size(kinfo->unassigned_mem);
+                order = get_allocation_size(kinfo->unassigned_mem);
                 lowmem = false;
                 continue;
             }
@@ -348,7 +348,7 @@ static void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
          * Success, next time around try again to get the largest order
          * allocation possible.
          */
-        order = get_11_allocation_size(kinfo->unassigned_mem);
+        order = get_allocation_size(kinfo->unassigned_mem);
     }
 
     if ( kinfo->unassigned_mem )
-- 
1.9.1


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

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

* [PATCH v3 16/25] xen/arm: rename allocate_memory to allocate_memory_11
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (14 preceding siblings ...)
  2018-07-31 23:27 ` [PATCH v3 15/25] xen/arm: rename get_11_allocation_size to get_allocation_size Stefano Stabellini
@ 2018-07-31 23:27 ` Stefano Stabellini
  2018-08-13 10:57   ` Julien Grall
  2018-07-31 23:28 ` [PATCH v3 17/25] xen/arm: introduce allocate_memory Stefano Stabellini
                   ` (9 subsequent siblings)
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:27 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

allocate_memory only deals with directly mapped memory. Rename it to
allocate_memory_11.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

---
Changes in v3:
- add patch
---
 xen/arch/arm/domain_build.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 066dd75..ab72c36 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -244,7 +244,8 @@ fail:
  * (as described above) we allow higher allocations and continue until
  * that runs out (or we have allocated sufficient dom0 memory).
  */
-static void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
+static void __init allocate_memory_11(struct domain *d,
+                                      struct kernel_info *kinfo)
 {
     const unsigned int min_low_order =
         get_order_from_bytes(min_t(paddr_t, dom0_mem, MB(128)));
@@ -2240,7 +2241,7 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
     /* type must be set before allocate memory */
     d->arch.type = kinfo.type;
 #endif
-    allocate_memory(d, &kinfo);
+    allocate_memory_11(d, &kinfo);
 
     return __construct_domain(d, &kinfo);
 }
@@ -2309,7 +2310,7 @@ int __init construct_dom0(struct domain *d)
     /* type must be set before allocate_memory */
     d->arch.type = kinfo.type;
 #endif
-    allocate_memory(d, &kinfo);
+    allocate_memory_11(d, &kinfo);
     find_gnttab_region(d, &kinfo);
 
     /* Map extra GIC MMIO, irqs and other hw stuffs to dom0. */
-- 
1.9.1


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

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

* [PATCH v3 17/25] xen/arm: introduce allocate_memory
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (15 preceding siblings ...)
  2018-07-31 23:27 ` [PATCH v3 16/25] xen/arm: rename allocate_memory to allocate_memory_11 Stefano Stabellini
@ 2018-07-31 23:28 ` Stefano Stabellini
  2018-08-01 11:28   ` Julien Grall
  2018-07-31 23:28 ` [PATCH v3 18/25] xen/arm: generate a simple device tree for domUs Stefano Stabellini
                   ` (8 subsequent siblings)
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:28 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Introduce an allocate_memory function able to allocate memory for DomUs
and map it at the right guest addresses, according to the guest memory
map: GUEST_RAM0_BASE and GUEST_RAM1_BASE.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
Changes in v3:
- new patch
---
 xen/arch/arm/domain_build.c | 125 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 124 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index ab72c36..dfa74e4 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -369,6 +369,129 @@ static void __init allocate_memory_11(struct domain *d,
     }
 }
 
+static bool __init insert_bank(struct domain *d,
+                               struct kernel_info *kinfo,
+                               struct page_info *pg,
+                               unsigned int order)
+{
+    int res, i;
+    mfn_t smfn;
+    paddr_t gaddr, size;
+    struct membank *bank;
+
+    smfn = page_to_mfn(pg);
+    size = pfn_to_paddr(1UL << order);
+
+    /*
+     * DomU memory is provided in two banks:
+     *   GUEST_RAM0_BASE - GUEST_RAM0_BASE + GUEST_RAM0_SIZE
+     *   GUEST_RAM1_BASE - GUEST_RAM1_BASE + GUEST_RAM1_SIZE
+     *
+     * Find the right gaddr address for DomUs accordingly.
+     */
+    gaddr = GUEST_RAM0_BASE;
+    if ( kinfo->mem.nr_banks > 0 )
+    {
+        for( i = 0; i < kinfo->mem.nr_banks; i++ )
+        {
+            bank = &kinfo->mem.bank[i];
+            gaddr = bank->start + bank->size;
+        }
+        if ( bank->start == GUEST_RAM0_BASE &&
+             gaddr + size > (GUEST_RAM0_BASE + GUEST_RAM0_SIZE) )
+            gaddr = GUEST_RAM1_BASE;
+        if ( bank->start == GUEST_RAM1_BASE &&
+             gaddr + size > (GUEST_RAM1_BASE + GUEST_RAM1_SIZE) )
+            goto fail;
+    }
+
+    dprintk(XENLOG_INFO,
+            "Allocated %#"PRIpaddr"-%#"PRIpaddr":%#"PRIpaddr"-%#"PRIpaddr" (%ldMB/%ldMB, order %d)\n",
+            mfn_to_maddr(smfn), mfn_to_maddr(smfn) + size,
+            gaddr, gaddr + size,
+            1UL << (order + PAGE_SHIFT - 20),
+            /* Don't want format this as PRIpaddr (16 digit hex) */
+            (unsigned long)(kinfo->unassigned_mem >> 20),
+            order);
+
+    res = guest_physmap_add_page(d, gaddr_to_gfn(gaddr), smfn, order);
+    if ( res )
+    {
+        dprintk(XENLOG_ERR, "Failed map pages to DOMU: %d", res);
+        goto fail;
+    }
+
+    kinfo->unassigned_mem -= size;
+    bank = &kinfo->mem.bank[kinfo->mem.nr_banks];
+
+    bank->start = gaddr;
+    bank->size = size;
+    kinfo->mem.nr_banks++;
+    return true;
+
+fail:
+    free_domheap_pages(pg, order);
+    return false;
+}
+
+static void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
+{
+    const unsigned int min_order = get_order_from_bytes(MB(4));
+    struct page_info *pg;
+    unsigned int order = get_allocation_size(kinfo->unassigned_mem);
+    int i;
+
+    dprintk(XENLOG_INFO, "Allocating mappings totalling %ldMB for dom%d:\n",
+            /* Don't want format this as PRIpaddr (16 digit hex) */
+            (unsigned long)(kinfo->unassigned_mem >> 20), d->domain_id);
+
+    kinfo->mem.nr_banks = 0;
+
+    order = get_allocation_size(kinfo->unassigned_mem);
+    if ( order > GUEST_RAM0_SIZE )
+        order = GUEST_RAM0_SIZE;
+    while ( kinfo->unassigned_mem )
+    {
+        pg = alloc_domheap_pages(d, order, 0);
+        if ( !pg )
+        {
+            order --;
+
+            if ( order >= min_order )
+                continue;
+
+            /* No more we can do */
+            break;
+        }
+
+        if ( !insert_bank(d, kinfo, pg, order) )
+            break;
+
+        /*
+         * Success, next time around try again to get the largest order
+         * allocation possible.
+         */
+        order = get_allocation_size(kinfo->unassigned_mem);
+    }
+
+    if ( kinfo->unassigned_mem )
+        dprintk(XENLOG_WARNING, "Failed to allocate requested domain memory."
+               /* Don't want format this as PRIpaddr (16 digit hex) */
+               " %ldMB unallocated\n",
+               (unsigned long)kinfo->unassigned_mem >> 20);
+
+    for( i = 0; i < kinfo->mem.nr_banks; i++ )
+    {
+        dprintk(XENLOG_INFO, "Dom%d BANK[%d] %#"PRIpaddr"-%#"PRIpaddr" (%ldMB)\n",
+                d->domain_id,
+                i,
+                kinfo->mem.bank[i].start,
+                kinfo->mem.bank[i].start + kinfo->mem.bank[i].size,
+                /* Don't want format this as PRIpaddr (16 digit hex) */
+                (unsigned long)(kinfo->mem.bank[i].size >> 20));
+    }
+}
+
 static int __init write_properties(struct domain *d, struct kernel_info *kinfo,
                                    const struct dt_device_node *node)
 {
@@ -2241,7 +2364,7 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
     /* type must be set before allocate memory */
     d->arch.type = kinfo.type;
 #endif
-    allocate_memory_11(d, &kinfo);
+    allocate_memory(d, &kinfo);
 
     return __construct_domain(d, &kinfo);
 }
-- 
1.9.1


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

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

* [PATCH v3 18/25] xen/arm: generate a simple device tree for domUs
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (16 preceding siblings ...)
  2018-07-31 23:28 ` [PATCH v3 17/25] xen/arm: introduce allocate_memory Stefano Stabellini
@ 2018-07-31 23:28 ` Stefano Stabellini
  2018-08-13 11:07   ` Julien Grall
  2018-07-31 23:28 ` [PATCH v3 19/25] xen/arm: generate vpl011 node on device tree for domU Stefano Stabellini
                   ` (7 subsequent siblings)
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:28 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Introduce functions to generate a basic domU device tree, similar to the
existing functions in tools/libxl/libxl_arm.c.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
Changes in v3:
- remove CONFIG_ACPI for make_chosen_node
- remove make_hypervisor_node until all Xen related functionalities
  (evtchns, grant table, etc.) work correctly

Changes in v2:
- move prepare_dtb rename to previous patch
- use switch for the gic version
- use arm,gic-400 instead of arm,cortex-a15-gic
- add @unit-address in the gic node name
- add comment on DOMU_DTB_SIZE
---
 xen/arch/arm/domain_build.c | 211 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 209 insertions(+), 2 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index dfa74e4..167a56e 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1057,7 +1057,6 @@ static int __init make_timer_node(const struct domain *d, void *fdt,
     return res;
 }
 
-#ifdef CONFIG_ACPI
 /*
  * This function is used as part of the device tree generation for Dom0
  * on ACPI systems, and DomUs started directly from Xen based on device
@@ -1103,7 +1102,6 @@ static int __init make_chosen_node(const struct kernel_info *kinfo)
 
     return res;
 }
-#endif
 
 static int __init map_irq_to_domain(struct domain *d, unsigned int irq,
                                     bool need_mapping, const char *devname)
@@ -1496,6 +1494,211 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
     return res;
 }
 
+static int __init make_gic_domU_node(const struct domain *d, void *fdt, int addrcells, int sizecells)
+{
+    int res = 0;
+    int reg_size = addrcells + sizecells;
+    int nr_cells = reg_size * 2;
+    __be32 reg[nr_cells];
+    __be32 *cells;
+
+    switch ( gic_hw_version() )
+    {
+    case GIC_V3:
+        res = fdt_begin_node(fdt, "interrupt-controller@"__stringify(GUEST_GICV3_GICD_BASE));
+        break;
+    case GIC_V2:
+        res = fdt_begin_node(fdt, "interrupt-controller@"__stringify(GUEST_GICD_BASE));
+        break;
+    default:
+        panic("Unsupported GIC version");
+    }
+
+    if ( res )
+        return res;
+
+    res = fdt_property_cell(fdt, "#address-cells", 0);
+    if ( res )
+        return res;
+
+    res = fdt_property_cell(fdt, "#interrupt-cells", 3);
+    if ( res )
+        return res;
+
+    res = fdt_property(fdt, "interrupt-controller", NULL, 0);
+    if ( res )
+        return res;
+
+    switch ( gic_hw_version() )
+    {
+    case GIC_V3:
+    {
+        const uint64_t gicd_base = GUEST_GICV3_GICD_BASE;
+        const uint64_t gicd_size = GUEST_GICV3_GICD_SIZE;
+        const uint64_t gicr0_base = GUEST_GICV3_GICR0_BASE;
+        const uint64_t gicr0_size = GUEST_GICV3_GICR0_SIZE;
+
+        res = fdt_property_string(fdt, "compatible", "arm,gic-v3");
+        if ( res )
+            return res;
+
+        cells = &reg[0];
+        dt_child_set_range(&cells, addrcells, sizecells, gicd_base, gicd_size);
+        dt_child_set_range(&cells, addrcells, sizecells, gicr0_base, gicr0_size);
+        res = fdt_property(fdt, "reg", reg, sizeof(reg));
+        break;
+    }
+    case GIC_V2:
+    {
+        const uint64_t gicd_base = GUEST_GICD_BASE;
+        const uint64_t gicd_size = GUEST_GICD_SIZE;
+        const uint64_t gicc_base = GUEST_GICC_BASE;
+        const uint64_t gicc_size = GUEST_GICC_SIZE;
+
+        res = fdt_property_string(fdt, "compatible", "arm,gic-400");
+        if ( res )
+            return res;
+
+        cells = &reg[0];
+        dt_child_set_range(&cells, addrcells, sizecells, gicd_base, gicd_size);
+        dt_child_set_range(&cells, addrcells, sizecells, gicc_base, gicc_size);
+        break;
+    }
+    default:
+        break;
+    }
+
+    res = fdt_property(fdt, "reg", reg, sizeof(reg));
+    if (res)
+        return res;
+
+    res = fdt_property_cell(fdt, "linux,phandle", GUEST_PHANDLE_GIC);
+    if (res)
+        return res;
+
+    res = fdt_property_cell(fdt, "phandle", GUEST_PHANDLE_GIC);
+    if (res)
+        return res;
+
+    res = fdt_end_node(fdt);
+
+    return res;
+}
+
+static int __init make_timer_domU_node(const struct domain *d, void *fdt)
+{
+    int res;
+    gic_interrupt_t intrs[3];
+
+    res = fdt_begin_node(fdt, "timer");
+    if ( res )
+        return res;
+
+    if (!is_64bit_domain(d))
+    {
+        res = fdt_property_string(fdt, "compatible", "arm,armv7-timer");
+        if ( res )
+            return res;
+    } else {
+        res = fdt_property_string(fdt, "compatible", "arm,armv8-timer");
+        if ( res )
+            return res;
+    }
+
+    set_interrupt_ppi(intrs[0], GUEST_TIMER_PHYS_S_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
+    set_interrupt_ppi(intrs[1], GUEST_TIMER_PHYS_NS_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
+    set_interrupt_ppi(intrs[2], GUEST_TIMER_VIRT_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
+
+    res = fdt_property(fdt, "interrupts", intrs, sizeof (intrs[0]) * 3);
+    if ( res )
+        return res;
+
+    res = fdt_property_cell(fdt, "interrupt-parent",
+                            GUEST_PHANDLE_GIC);
+    if (res)
+        return res;
+
+    res = fdt_end_node(fdt);
+    return res;
+}
+
+/*
+ * The max size for DT is 2MB. However, the generated DT is small, 4KB
+ * are enough for now, but we might have to increase it in the feature.
+ */
+#define DOMU_DTB_SIZE 4096
+static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
+{
+    int addrcells, sizecells;
+    int ret;
+
+    addrcells = dt_child_n_addr_cells(dt_host);
+    sizecells = dt_child_n_size_cells(dt_host);
+
+    kinfo->fdt = xmalloc_bytes(DOMU_DTB_SIZE);
+    if ( kinfo->fdt == NULL )
+        return -ENOMEM;
+
+    ret = fdt_create(kinfo->fdt, DOMU_DTB_SIZE);
+    if ( ret < 0 )
+        goto err;
+
+    ret = fdt_finish_reservemap(kinfo->fdt);
+    if ( ret < 0 )
+        goto err;
+
+    ret = fdt_begin_node(kinfo->fdt, "/");
+    if ( ret < 0 )
+        goto err;
+
+    ret = fdt_property_cell(kinfo->fdt, "#address-cells", addrcells);
+    if ( ret )
+        goto err;
+
+    ret = fdt_property_cell(kinfo->fdt, "#size-cells", sizecells);
+    if ( ret )
+        goto err;
+
+    ret = make_chosen_node(kinfo);
+    if ( ret )
+        goto err;
+
+    ret = make_psci_node(kinfo->fdt, NULL);
+    if ( ret )
+        goto err;
+
+    ret = make_cpus_node(d, kinfo->fdt, NULL);
+    if ( ret )
+        goto err;
+
+    ret = make_memory_node(d, kinfo->fdt, addrcells, sizecells, kinfo);
+    if ( ret )
+        goto err;
+
+    ret = make_gic_domU_node(d, kinfo->fdt, addrcells, sizecells);
+    if ( ret )
+        goto err;
+
+    ret = make_timer_domU_node(d, kinfo->fdt);
+    if ( ret )
+        goto err;
+
+    ret = fdt_end_node(kinfo->fdt);
+    if ( ret < 0 )
+        goto err;
+
+    ret = fdt_finish(kinfo->fdt);
+    if ( ret < 0 )
+        goto err;
+
+    return 0;
+
+  err:
+    printk("Device tree generation failed (%d).\n", ret);
+    xfree(kinfo->fdt);
+    return -EINVAL;
+}
+
 static int __init prepare_dtb_hwdom(struct domain *d, struct kernel_info *kinfo)
 {
     const p2m_type_t default_p2mt = p2m_mmio_direct_c;
@@ -2366,6 +2569,10 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
 #endif
     allocate_memory(d, &kinfo);
 
+    rc = prepare_dtb_domU(d, &kinfo);
+    if ( rc < 0 )
+        return rc;
+
     return __construct_domain(d, &kinfo);
 }
 
-- 
1.9.1


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

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

* [PATCH v3 19/25] xen/arm: generate vpl011 node on device tree for domU
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (17 preceding siblings ...)
  2018-07-31 23:28 ` [PATCH v3 18/25] xen/arm: generate a simple device tree for domUs Stefano Stabellini
@ 2018-07-31 23:28 ` Stefano Stabellini
  2018-08-13 11:20   ` Julien Grall
  2018-07-31 23:28 ` [PATCH v3 20/25] xen/arm: introduce a union in vpl011 Stefano Stabellini
                   ` (6 subsequent siblings)
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:28 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Introduce vpl011 support to guests started from Xen: it provides a
simple way to print output from a guest, as most guests come with a
pl011 driver. It is also able to provide a working console with
interrupt support.

The UART exposed to the guest is a SBSA compatible UART and not a PL011.
SBSA UART is a subset of PL011 r1p5. A full PL011 implementation in Xen
would just be too difficult, so guests may require some drivers changes.

Enable vpl011 conditionally if the user requested it.

Make set_interrupt_ppi able to handle non-PPI and rename it
set_interrupt.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
Changes in v3:
- use bool
- retain BUG_ON(irq < 16)
- add vpl011 bool to kinfo
- return error of vpl011 is required but CONFIG_SBSA_VUART_CONSOLE is
  missing

Changes in v2:
- code style fixes
- make set_interrupt_ppi generic
- rename set_interrupt_ppi to set_interrupt
- only make the vpl011 node if the option was enabled
---
 xen/arch/arm/domain_build.c | 95 ++++++++++++++++++++++++++++++++++++++-------
 xen/arch/arm/kernel.h       |  3 ++
 2 files changed, 83 insertions(+), 15 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 167a56e..f9fa484 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -619,19 +619,20 @@ static int __init write_properties(struct domain *d, struct kernel_info *kinfo,
 
 typedef __be32 gic_interrupt_t[3];
 
-static void __init set_interrupt_ppi(gic_interrupt_t interrupt,
-                                     unsigned int irq,
-                                     unsigned int cpumask,
-                                     unsigned int level)
+static void __init set_interrupt(gic_interrupt_t interrupt,
+                                 unsigned int irq,
+                                 unsigned int cpumask,
+                                 unsigned int level)
 {
     __be32 *cells = interrupt;
+    bool is_ppi = !!(irq < 32);
 
     BUG_ON(irq < 16);
-    BUG_ON(irq >= 32);
+    irq -= (is_ppi) ? 16: 32; /* PPIs start at 16, SPIs at 32 */
 
     /* See linux Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt */
-    dt_set_cell(&cells, 1, 1); /* is a PPI */
-    dt_set_cell(&cells, 1, irq - 16); /* PPIs start at 16 */
+    dt_set_cell(&cells, 1, is_ppi); /* is a PPI? */
+    dt_set_cell(&cells, 1, irq);
     dt_set_cell(&cells, 1, (cpumask << 8) | level);
 }
 
@@ -752,7 +753,7 @@ static int __init make_hypervisor_node(struct domain *d,
      *  - All CPUs
      *  TODO: Handle properly the cpumask;
      */
-    set_interrupt_ppi(intr, d->arch.evtchn_irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
+    set_interrupt(intr, d->arch.evtchn_irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
     res = fdt_property_interrupts(fdt, &intr, 1);
     if ( res )
         return res;
@@ -1029,15 +1030,15 @@ static int __init make_timer_node(const struct domain *d, void *fdt,
 
     irq = timer_get_irq(TIMER_PHYS_SECURE_PPI);
     dt_dprintk("  Secure interrupt %u\n", irq);
-    set_interrupt_ppi(intrs[0], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
+    set_interrupt(intrs[0], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
 
     irq = timer_get_irq(TIMER_PHYS_NONSECURE_PPI);
     dt_dprintk("  Non secure interrupt %u\n", irq);
-    set_interrupt_ppi(intrs[1], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
+    set_interrupt(intrs[1], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
 
     irq = timer_get_irq(TIMER_VIRT_PPI);
     dt_dprintk("  Virt interrupt %u\n", irq);
-    set_interrupt_ppi(intrs[2], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
+    set_interrupt(intrs[2], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
 
     res = fdt_property_interrupts(fdt, intrs, 3);
     if ( res )
@@ -1605,9 +1606,9 @@ static int __init make_timer_domU_node(const struct domain *d, void *fdt)
             return res;
     }
 
-    set_interrupt_ppi(intrs[0], GUEST_TIMER_PHYS_S_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
-    set_interrupt_ppi(intrs[1], GUEST_TIMER_PHYS_NS_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
-    set_interrupt_ppi(intrs[2], GUEST_TIMER_VIRT_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
+    set_interrupt(intrs[0], GUEST_TIMER_PHYS_S_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
+    set_interrupt(intrs[1], GUEST_TIMER_PHYS_NS_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
+    set_interrupt(intrs[2], GUEST_TIMER_VIRT_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
 
     res = fdt_property(fdt, "interrupts", intrs, sizeof (intrs[0]) * 3);
     if ( res )
@@ -1622,6 +1623,56 @@ static int __init make_timer_domU_node(const struct domain *d, void *fdt)
     return res;
 }
 
+#ifdef CONFIG_SBSA_VUART_CONSOLE
+static int __init make_vpl011_uart_node(const struct domain *d, void *fdt,
+                                 int addrcells, int sizecells)
+{
+    int res;
+    gic_interrupt_t intr;
+    int reg_size = addrcells + sizecells;
+    int nr_cells = reg_size;
+    __be32 reg[nr_cells];
+    __be32 *cells;
+
+    res = fdt_begin_node(fdt, "sbsa-pl011");
+    if ( res )
+        return res;
+
+    res = fdt_property_string(fdt, "compatible", "arm,sbsa-uart");
+    if ( res )
+        return res;
+
+    cells = &reg[0];
+    dt_child_set_range(&cells, addrcells, sizecells, GUEST_PL011_BASE,
+                       GUEST_PL011_SIZE);
+    if ( res )
+        return res;
+    res = fdt_property(fdt, "reg", reg, sizeof(reg));
+    if ( res )
+        return res;
+
+    set_interrupt(intr, GUEST_VPL011_SPI, 0xf, DT_IRQ_TYPE_LEVEL_HIGH);
+
+    res = fdt_property(fdt, "interrupts", intr, sizeof (intr));
+    if ( res )
+        return res;
+
+    res = fdt_property_cell(fdt, "interrupt-parent",
+                            GUEST_PHANDLE_GIC);
+    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;
+}
+#endif
+
 /*
  * The max size for DT is 2MB. However, the generated DT is small, 4KB
  * are enough for now, but we might have to increase it in the feature.
@@ -1683,6 +1734,18 @@ static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
     if ( ret )
         goto err;
 
+    if ( kinfo->vpl011 )
+    {
+#ifdef CONFIG_SBSA_VUART_CONSOLE
+        ret = make_vpl011_uart_node(d, kinfo->fdt, addrcells, sizecells);
+        if ( ret )
+            goto err;
+#else
+        ret = -EINVAL;
+        goto err;
+#endif
+    }
+
     ret = fdt_end_node(kinfo->fdt);
     if ( ret < 0 )
         goto err;
@@ -2537,7 +2600,7 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
 {
     struct kernel_info kinfo = {};
     int rc;
-    u32 mem;
+    u32 mem, len;
 
     printk("*** LOADING DOMU ***\n");
 
@@ -2550,6 +2613,8 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
         return -EINVAL;
     kinfo.unassigned_mem = (paddr_t)mem << 10;
 
+    kinfo.vpl011 = dt_get_property(node, "vpl011", &len) != NULL;
+
     d->vcpu = xzalloc_array(struct vcpu *, d->max_vcpus);
     if ( !d->vcpu )
         return -ENOMEM;;
diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
index 4a65289..9c9e568 100644
--- a/xen/arch/arm/kernel.h
+++ b/xen/arch/arm/kernel.h
@@ -33,6 +33,9 @@ struct kernel_info {
     paddr_t dtb_paddr;
     paddr_t initrd_paddr;
 
+    /* Enable pl011 emulation */
+    bool vpl011;
+
     /* loader to use for this kernel */
     void (*load)(struct kernel_info *info);
     /* loader specific state */
-- 
1.9.1


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

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

* [PATCH v3 20/25] xen/arm: introduce a union in vpl011
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (18 preceding siblings ...)
  2018-07-31 23:28 ` [PATCH v3 19/25] xen/arm: generate vpl011 node on device tree for domU Stefano Stabellini
@ 2018-07-31 23:28 ` Stefano Stabellini
  2018-08-13 11:24   ` Julien Grall
  2018-07-31 23:28 ` [PATCH v3 21/25] xen/arm: refactor vpl011_data_avail Stefano Stabellini
                   ` (5 subsequent siblings)
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:28 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Introduce a union in struct vpl011 to contain the console ring members.
A later patch will add another member of the union for the case where
the backend is in Xen.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
Changes in v3:
- rename ring field to dom

Changes in v2:
- new patch
---
 xen/arch/arm/vpl011.c        | 20 ++++++++++----------
 xen/include/asm-arm/vpl011.h |  8 ++++++--
 2 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index a281eab..e70c5ec 100644
--- a/xen/arch/arm/vpl011.c
+++ b/xen/arch/arm/vpl011.c
@@ -82,7 +82,7 @@ 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;
+    struct xencons_interface *intf = vpl011->dom.ring_buf;
     XENCONS_RING_IDX in_cons, in_prod;
 
     VPL011_LOCK(d, flags);
@@ -145,7 +145,7 @@ static uint8_t vpl011_read_data(struct domain *d)
 static void vpl011_update_tx_fifo_status(struct vpl011 *vpl011,
                                          unsigned int fifo_level)
 {
-    struct xencons_interface *intf = vpl011->ring_buf;
+    struct xencons_interface *intf = vpl011->dom.ring_buf;
     unsigned int fifo_threshold = sizeof(intf->out) - SBSA_UART_FIFO_LEVEL;
 
     BUILD_BUG_ON(sizeof(intf->out) < SBSA_UART_FIFO_SIZE);
@@ -164,7 +164,7 @@ 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;
+    struct xencons_interface *intf = vpl011->dom.ring_buf;
     XENCONS_RING_IDX out_cons, out_prod;
 
     VPL011_LOCK(d, flags);
@@ -382,7 +382,7 @@ static void vpl011_data_avail(struct domain *d)
 {
     unsigned long flags;
     struct vpl011 *vpl011 = &d->arch.vpl011;
-    struct xencons_interface *intf = vpl011->ring_buf;
+    struct xencons_interface *intf = vpl011->dom.ring_buf;
     XENCONS_RING_IDX in_cons, in_prod, out_cons, out_prod;
     XENCONS_RING_IDX in_fifo_level, out_fifo_level;
 
@@ -459,14 +459,14 @@ int domain_vpl011_init(struct domain *d, struct vpl011_init_info *info)
     int rc;
     struct vpl011 *vpl011 = &d->arch.vpl011;
 
-    if ( vpl011->ring_buf )
+    if ( vpl011->dom.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);
+                                  &vpl011->dom.ring_page,
+                                  &vpl011->dom.ring_buf);
     if ( rc < 0 )
         goto out;
 
@@ -495,7 +495,7 @@ out2:
     vgic_free_virq(d, GUEST_VPL011_SPI);
 
 out1:
-    destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
+    destroy_ring_for_helper(&vpl011->dom.ring_buf, vpl011->dom.ring_page);
 
 out:
     return rc;
@@ -505,11 +505,11 @@ void domain_vpl011_deinit(struct domain *d)
 {
     struct vpl011 *vpl011 = &d->arch.vpl011;
 
-    if ( !vpl011->ring_buf )
+    if ( !vpl011->dom.ring_buf )
         return;
 
     free_xen_event_channel(d, vpl011->evtchn);
-    destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
+    destroy_ring_for_helper(&vpl011->dom.ring_buf, vpl011->dom.ring_page);
 }
 
 /*
diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
index db95ff8..b873a29 100644
--- a/xen/include/asm-arm/vpl011.h
+++ b/xen/include/asm-arm/vpl011.h
@@ -31,8 +31,12 @@
 #define SBSA_UART_FIFO_SIZE 32
 
 struct vpl011 {
-    void *ring_buf;
-    struct page_info *ring_page;
+    union {
+        struct {
+            void *ring_buf;
+            struct page_info *ring_page;
+        } dom;
+    };
     uint32_t    uartfr;         /* Flag register */
     uint32_t    uartcr;         /* Control register */
     uint32_t    uartimsc;       /* Interrupt mask register*/
-- 
1.9.1


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

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

* [PATCH v3 21/25] xen/arm: refactor vpl011_data_avail
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (19 preceding siblings ...)
  2018-07-31 23:28 ` [PATCH v3 20/25] xen/arm: introduce a union in vpl011 Stefano Stabellini
@ 2018-07-31 23:28 ` Stefano Stabellini
  2018-08-13 13:23   ` Julien Grall
  2018-07-31 23:28 ` [PATCH v3 22/25] xen/arm: Allow vpl011 to be used by DomU Stefano Stabellini
                   ` (4 subsequent siblings)
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:28 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Move the code to calculate in_fifo_level and out_fifo_level out of
vpl011_data_avail, to the caller.
This change will make it possible to reuse vpl011_data_avail with
different ring structures in a later patch.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

---
Changes in v3:
- remove forward declaration of vpl011_data_avail

Changes in v2:
- new patch
---
 xen/arch/arm/vpl011.c | 64 +++++++++++++++++++++++++++++----------------------
 1 file changed, 36 insertions(+), 28 deletions(-)

diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index e70c5ec..725a203 100644
--- a/xen/arch/arm/vpl011.c
+++ b/xen/arch/arm/vpl011.c
@@ -378,30 +378,13 @@ static const struct mmio_handler_ops vpl011_mmio_handler = {
     .write = vpl011_mmio_write,
 };
 
-static void vpl011_data_avail(struct domain *d)
+static void vpl011_data_avail(struct domain *d,
+                              XENCONS_RING_IDX in_fifo_level,
+                              XENCONS_RING_IDX in_size,
+                              XENCONS_RING_IDX out_fifo_level,
+                              XENCONS_RING_IDX out_size)
 {
-    unsigned long flags;
     struct vpl011 *vpl011 = &d->arch.vpl011;
-    struct xencons_interface *intf = vpl011->dom.ring_buf;
-    XENCONS_RING_IDX in_cons, in_prod, out_cons, out_prod;
-    XENCONS_RING_IDX in_fifo_level, out_fifo_level;
-
-    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_fifo_level = xencons_queued(in_prod,
-                                   in_cons,
-                                   sizeof(intf->in));
-
-    out_fifo_level = xencons_queued(out_prod,
-                                    out_cons,
-                                    sizeof(intf->out));
 
     /**** Update the UART RX state ****/
 
@@ -410,11 +393,11 @@ static void vpl011_data_avail(struct domain *d)
         vpl011->uartfr &= ~RXFE;
 
     /* Set the FIFO_FULL bit if the Xen buffer is full. */
-    if ( in_fifo_level == sizeof(intf->in) )
+    if ( in_fifo_level == in_size )
         vpl011->uartfr |= RXFF;
 
     /* Assert the RX interrupt if the FIFO is more than half way filled. */
-    if ( in_fifo_level >= sizeof(intf->in) - SBSA_UART_FIFO_LEVEL )
+    if ( in_fifo_level >= in_size - SBSA_UART_FIFO_LEVEL )
         vpl011->uartris |= RXI;
 
     /*
@@ -427,7 +410,7 @@ static void vpl011_data_avail(struct domain *d)
 
     /**** Update the UART TX state ****/
 
-    if ( out_fifo_level != sizeof(intf->out) )
+    if ( out_fifo_level != out_size )
     {
         vpl011->uartfr &= ~TXFF;
 
@@ -445,13 +428,38 @@ static void vpl011_data_avail(struct domain *d)
 
     if ( out_fifo_level == 0 )
         vpl011->uartfr |= TXFE;
-
-    VPL011_UNLOCK(d, flags);
 }
 
 static void vpl011_notification(struct vcpu *v, unsigned int port)
 {
-    vpl011_data_avail(v->domain);
+    unsigned long flags;
+    struct domain *d = v->domain;
+    struct vpl011 *vpl011 = &d->arch.vpl011;
+    struct xencons_interface *intf = vpl011->dom.ring_buf;
+    XENCONS_RING_IDX in_cons, in_prod, out_cons, out_prod;
+    XENCONS_RING_IDX in_fifo_level, out_fifo_level;
+
+    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_fifo_level = xencons_queued(in_prod,
+                                   in_cons,
+                                   sizeof(intf->in));
+
+    out_fifo_level = xencons_queued(out_prod,
+                                    out_cons,
+                                    sizeof(intf->out));
+
+    vpl011_data_avail(v->domain, in_fifo_level, sizeof(intf->in),
+                      out_fifo_level, sizeof(intf->out));
+
+    VPL011_UNLOCK(d, flags);
 }
 
 int domain_vpl011_init(struct domain *d, struct vpl011_init_info *info)
-- 
1.9.1


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

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

* [PATCH v3 22/25] xen/arm: Allow vpl011 to be used by DomU
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (20 preceding siblings ...)
  2018-07-31 23:28 ` [PATCH v3 21/25] xen/arm: refactor vpl011_data_avail Stefano Stabellini
@ 2018-07-31 23:28 ` Stefano Stabellini
  2018-08-13 13:42   ` Julien Grall
  2018-08-13 14:10   ` Julien Grall
  2018-07-31 23:28 ` [PATCH v3 23/25] xen: support console_switching between Dom0 and DomUs on ARM Stefano Stabellini
                   ` (3 subsequent siblings)
  25 siblings, 2 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:28 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Make vpl011 being able to be used without a userspace component in Dom0.
In that case, output is printed to the Xen serial and input is received
from the Xen serial one character at a time.

Call domain_vpl011_init during construct_domU if vpl011 is enabled.

Introduce a new ring struct with only the ring array to avoid a waste of
memory. Introduce separate read_data and write_data functions for
initial domains: vpl011_write_data_xen is very simple and just writes
to the console, while vpl011_read_data_xen is a duplicate of
vpl011_read_data. Although textually almost identical, we are forced to
duplicate the functions because the struct layout is different.

Output characters are printed one by one, potentially leading to
intermixed output of different domains on the console. A follow-up patch
will solve the issue by introducing buffering.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
Changes in v3:
- add in-code comments
- improve existing comments
- remove ifdef around domain_vpl011_init in construct_domU
- add ASSERT
- use SBSA_UART_FIFO_SIZE for in buffer size
- rename ring_enable to backend_in_domain
- rename struct xencons_in to struct vpl011_xen_backend
- rename inring field to xen
- rename helper functions accordingly
- remove unnecessary stub implementation of vpl011_rx_char
- move vpl011_rx_char_xen within the file to avoid the need of a forward
  declaration of vpl011_data_avail
- fix small bug in vpl011_rx_char_xen: increment in_prod before using it
  to check xencons_queued.

Changes in v2:
- only init if vpl011
- rename vpl011_read_char to vpl011_rx_char
- remove spurious change
- fix coding style
- use different ring struct
- move the write_data changes to their own function
  (vpl011_write_data_noring)
- duplicate vpl011_read_data
---
 xen/arch/arm/domain_build.c  |   9 +-
 xen/arch/arm/vpl011.c        | 198 ++++++++++++++++++++++++++++++++++++++-----
 xen/include/asm-arm/vpl011.h |   8 ++
 3 files changed, 192 insertions(+), 23 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index f9fa484..0888a76 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -2638,7 +2638,14 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
     if ( rc < 0 )
         return rc;
 
-    return __construct_domain(d, &kinfo);
+    rc = __construct_domain(d, &kinfo);
+    if ( rc < 0 )
+        return rc;
+
+    if ( kinfo.vpl011 )
+        rc = domain_vpl011_init(d, NULL);
+
+    return rc;
 }
 
 void __init create_domUs(void)
diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index 725a203..f206c61 100644
--- a/xen/arch/arm/vpl011.c
+++ b/xen/arch/arm/vpl011.c
@@ -77,6 +77,91 @@ static void vpl011_update_interrupt_status(struct domain *d)
 #endif
 }
 
+/*
+ * vpl011_write_data_xen writes chars from the vpl011 out buffer to the
+ * console. Only to be used when the backend is Xen.
+ */
+static void vpl011_write_data_xen(struct domain *d, uint8_t data)
+{
+    unsigned long flags;
+    struct vpl011 *vpl011 = &d->arch.vpl011;
+
+    VPL011_LOCK(d, flags);
+
+    printk("%c", data);
+    if (data == '\n')
+        printk("DOM%u: ", d->domain_id);
+
+    vpl011->uartris |= TXI;
+    vpl011->uartfr &= ~TXFE;
+    vpl011_update_interrupt_status(d);
+
+    VPL011_UNLOCK(d, flags);
+}
+
+/*
+ * vpl011_read_data_xen reads data when the backend is xen. Characters
+ * are added to the vpl011 receive buffer by vpl011_rx_char_xen.
+ */
+static uint8_t vpl011_read_data_xen(struct domain *d)
+{
+    unsigned long flags;
+    uint8_t data = 0;
+    struct vpl011 *vpl011 = &d->arch.vpl011;
+    struct vpl011_xen_backend *intf = vpl011->xen;
+    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 )
+    {
+        unsigned int fifo_level;
+
+        data = intf->in[xencons_mask(in_cons, sizeof(intf->in))];
+        in_cons += 1;
+        smp_mb();
+        intf->in_cons = in_cons;
+
+        fifo_level = xencons_queued(in_prod, in_cons, sizeof(intf->in));
+
+        /* If the FIFO is now empty, we clear the receive timeout interrupt. */
+        if ( fifo_level == 0 )
+        {
+            vpl011->uartfr |= RXFE;
+            vpl011->uartris &= ~RTI;
+        }
+
+        /* If the FIFO is more than half empty, we clear the RX interrupt. */
+        if ( fifo_level < sizeof(intf->in) - SBSA_UART_FIFO_LEVEL )
+            vpl011->uartris &= ~RXI;
+
+        vpl011_update_interrupt_status(d);
+    }
+    else
+        gprintk(XENLOG_ERR, "vpl011: Unexpected IN ring buffer empty\n");
+
+    /*
+     * We have consumed a character or the FIFO was empty, so clear the
+     * "FIFO full" bit.
+     */
+    vpl011->uartfr &= ~RXFF;
+
+    VPL011_UNLOCK(d, flags);
+
+    return data;
+}
+
 static uint8_t vpl011_read_data(struct domain *d)
 {
     unsigned long flags;
@@ -240,7 +325,10 @@ static int vpl011_mmio_read(struct vcpu *v,
     case DR:
         if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
 
-        *r = vreg_reg32_extract(vpl011_read_data(d), info);
+        if ( vpl011->backend_in_domain )
+            *r = vreg_reg32_extract(vpl011_read_data(d), info);
+        else
+            *r = vreg_reg32_extract(vpl011_read_data_xen(d), info);
         return 1;
 
     case RSR:
@@ -325,7 +413,10 @@ static int vpl011_mmio_write(struct vcpu *v,
 
         vreg_reg32_update(&data, r, info);
         data &= 0xFF;
-        vpl011_write_data(v->domain, data);
+        if ( vpl011->backend_in_domain )
+            vpl011_write_data(v->domain, data);
+        else
+            vpl011_write_data_xen(v->domain, data);
         return 1;
     }
 
@@ -430,6 +521,39 @@ static void vpl011_data_avail(struct domain *d,
         vpl011->uartfr |= TXFE;
 }
 
+/*
+ * vpl011_rx_char_xen adds a char to a domain's vpl011 receive buffer.
+ * It is only used when the vpl011 backend is in Xen.
+ */
+void vpl011_rx_char_xen(struct domain *d, char c)
+{
+    unsigned long flags;
+    struct vpl011 *vpl011 = &d->arch.vpl011;
+    struct vpl011_xen_backend *intf = vpl011->xen;
+    XENCONS_RING_IDX in_cons, in_prod, in_fifo_level;
+
+    ASSERT(!vpl011->backend_in_domain);
+    VPL011_LOCK(d, flags);
+
+    in_cons = intf->in_cons;
+    in_prod = intf->in_prod;
+    if ( xencons_queued(in_prod, in_cons, sizeof(intf->in)) == sizeof(intf->in) )
+    {
+        VPL011_UNLOCK(d, flags);
+        return;
+    }
+
+    intf->in[xencons_mask(in_prod, sizeof(intf->in))] = c;
+    intf->in_prod = ++in_prod;
+
+    in_fifo_level = xencons_queued(in_prod,
+                                   in_cons,
+                                   sizeof(intf->in));
+
+    vpl011_data_avail(d, in_fifo_level, sizeof(intf->in), 0, SBSA_UART_FIFO_SIZE);
+    VPL011_UNLOCK(d, flags);
+}
+
 static void vpl011_notification(struct vcpu *v, unsigned int port)
 {
     unsigned long flags;
@@ -470,27 +594,47 @@ int domain_vpl011_init(struct domain *d, struct vpl011_init_info *info)
     if ( vpl011->dom.ring_buf )
         return -EINVAL;
 
-    /* Map the guest PFN to Xen address space. */
-    rc =  prepare_ring_for_helper(d,
-                                  gfn_x(info->gfn),
-                                  &vpl011->dom.ring_page,
-                                  &vpl011->dom.ring_buf);
-    if ( rc < 0 )
-        goto out;
+    /*
+     * info is NULL when the backend is in Xen.
+     * info is != NULL when the backend is in a domain.
+     */
+    if ( info != NULL )
+    {
+        vpl011->backend_in_domain = true;
+
+        /* Map the guest PFN to Xen address space. */
+        rc =  prepare_ring_for_helper(d,
+                gfn_x(info->gfn),
+                &vpl011->dom.ring_page,
+                &vpl011->dom.ring_buf);
+        if ( rc < 0 )
+            goto out;
+
+        rc = alloc_unbound_xen_event_channel(d, 0, info->console_domid,
+                vpl011_notification);
+        if ( rc < 0 )
+            goto out1;
+
+        vpl011->evtchn = info->evtchn = rc;
+    }
+    else
+    {
+        vpl011->backend_in_domain = false;
+
+        vpl011->xen = xzalloc(struct vpl011_xen_backend);
+        if ( vpl011->xen == NULL )
+        {
+            rc = -EINVAL;
+            goto out1;
+        }
+    }
 
     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);
 
@@ -503,7 +647,10 @@ out2:
     vgic_free_virq(d, GUEST_VPL011_SPI);
 
 out1:
-    destroy_ring_for_helper(&vpl011->dom.ring_buf, vpl011->dom.ring_page);
+    if ( vpl011->backend_in_domain )
+        destroy_ring_for_helper(&vpl011->dom.ring_buf, vpl011->dom.ring_page);
+    else
+        xfree(vpl011->xen);
 
 out:
     return rc;
@@ -513,11 +660,18 @@ void domain_vpl011_deinit(struct domain *d)
 {
     struct vpl011 *vpl011 = &d->arch.vpl011;
 
-    if ( !vpl011->dom.ring_buf )
-        return;
+    if ( vpl011->backend_in_domain )
+    {
+        if ( !vpl011->dom.ring_buf )
+            return;
 
-    free_xen_event_channel(d, vpl011->evtchn);
-    destroy_ring_for_helper(&vpl011->dom.ring_buf, vpl011->dom.ring_page);
+        free_xen_event_channel(d, vpl011->evtchn);
+        destroy_ring_for_helper(&vpl011->dom.ring_buf, vpl011->dom.ring_page);
+    }
+    else
+    {
+        xfree(vpl011->xen);
+    }
 }
 
 /*
diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
index b873a29..c9918c1 100644
--- a/xen/include/asm-arm/vpl011.h
+++ b/xen/include/asm-arm/vpl011.h
@@ -21,6 +21,7 @@
 
 #include <public/domctl.h>
 #include <public/io/ring.h>
+#include <public/io/console.h>
 #include <asm/vreg.h>
 #include <xen/mm.h>
 
@@ -29,13 +30,19 @@
 #define VPL011_UNLOCK(d,flags) spin_unlock_irqrestore(&(d)->arch.vpl011.lock, flags)
 
 #define SBSA_UART_FIFO_SIZE 32
+struct vpl011_xen_backend {
+    char in[SBSA_UART_FIFO_SIZE];
+    XENCONS_RING_IDX in_cons, in_prod;
+};
 
 struct vpl011 {
+    bool backend_in_domain;
     union {
         struct {
             void *ring_buf;
             struct page_info *ring_page;
         } dom;
+        struct vpl011_xen_backend *xen;
     };
     uint32_t    uartfr;         /* Flag register */
     uint32_t    uartcr;         /* Control register */
@@ -57,6 +64,7 @@ struct vpl011_init_info {
 int domain_vpl011_init(struct domain *d,
                        struct vpl011_init_info *info);
 void domain_vpl011_deinit(struct domain *d);
+void vpl011_rx_char_xen(struct domain *d, char c);
 #else
 static inline int domain_vpl011_init(struct domain *d,
                                      struct vpl011_init_info *info)
-- 
1.9.1


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

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

* [PATCH v3 23/25] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (21 preceding siblings ...)
  2018-07-31 23:28 ` [PATCH v3 22/25] xen/arm: Allow vpl011 to be used by DomU Stefano Stabellini
@ 2018-07-31 23:28 ` Stefano Stabellini
  2018-08-01  9:03   ` Jan Beulich
  2018-08-13 13:58   ` Julien Grall
  2018-07-31 23:28 ` [PATCH v3 24/25] xen/vpl011: buffer out chars when the backend is xen Stefano Stabellini
                   ` (2 subsequent siblings)
  25 siblings, 2 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:28 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, sstabellini, andrii_anisov, George.Dunlap,
	andrew.cooper3, ian.jackson, xen-devel, tim, jbeulich, wei.liu2

Today Ctrl-AAA is used to switch between Xen and Dom0. Extend the
mechanism to allow for switching between Xen, Dom0, and any of the
initial DomU created from Xen alongside Dom0 out of information provided
via device tree.

Rename xen_rx to console_rx to match the new behavior.

Clarify existing comment about "notify the guest", making it clear that
it is only about the hardware domain.

Export a function named console_input_domain() to allow others to know
which domains has input at a given time.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
CC: andrew.cooper3@citrix.com
CC: George.Dunlap@eu.citrix.com
CC: ian.jackson@eu.citrix.com
CC: jbeulich@suse.com
CC: konrad.wilk@oracle.com
CC: tim@xen.org
CC: wei.liu2@citrix.com
---
Changes in v3:
- only call vpl011 functions ifdef CONFIG_SBSA_VUART_CONSOLE
- add blank line and spaces
- remove xen_rx from print messages
- rename xen_rx to console_rx
- keep switch_serial_input() at boot
- add better comments
- fix existing comment
- add warning if no guests console/uart is available
- add console_input_domain function

Changes in v2:
- only call vpl011_rx_char if the vpl011 has been initialized
---
 xen/drivers/char/console.c | 71 +++++++++++++++++++++++++++++++++++++---------
 xen/include/xen/console.h  |  2 ++
 2 files changed, 60 insertions(+), 13 deletions(-)

diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 0f05369..cd4dfb1 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -31,10 +31,13 @@
 #include <xen/early_printk.h>
 #include <xen/warning.h>
 #include <xen/pv_console.h>
+#include <asm/setup.h>
 
 #ifdef CONFIG_X86
 #include <xen/consoled.h>
 #include <asm/guest.h>
+#else
+#include <asm/vpl011.h>
 #endif
 
 /* console: comma-separated list of console outputs. */
@@ -389,30 +392,72 @@ static void dump_console_ring_key(unsigned char key)
     free_xenheap_pages(buf, order);
 }
 
-/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
+/*
+ * CTRL-<switch_char> switches input direction between Xen, Dom0 and
+ * DomUs.
+ */
 #define switch_code (opt_conswitch[0]-'a'+1)
-static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain 0. */
+/*
+ * console_rx=0 => input to xen
+ * console_rx=1 => input to dom0
+ * console_rx=N => input dom(N-1)
+ */
+static int __read_mostly console_rx = 0;
+
+struct domain *console_input_domain(void)
+{
+    return get_domain_by_id(console_rx - 1);
+}
 
 static void switch_serial_input(void)
 {
-    static char *input_str[2] = { "DOM0", "Xen" };
-    xen_rx = !xen_rx;
-    printk("*** Serial input -> %s", input_str[xen_rx]);
+    console_rx++;
+    if ( console_rx == max_init_domid + 2 )
+        console_rx = 0;
+
+    if ( !console_rx )
+        printk("*** Serial input to Xen");
+    else
+        printk("*** Serial input to DOM%d", console_rx - 1);
+
     if ( switch_code )
-        printk(" (type 'CTRL-%c' three times to switch input to %s)",
-               opt_conswitch[0], input_str[!xen_rx]);
+        printk(" (type 'CTRL-%c' three times to switch input)",
+               opt_conswitch[0]);
     printk("\n");
 }
 
 static void __serial_rx(char c, struct cpu_user_regs *regs)
 {
-    if ( xen_rx )
+    if ( console_rx == 0 )
         return handle_keypress(c, regs);
 
-    /* Deliver input to guest buffer, unless it is already full. */
-    if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
-        serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
-    /* Always notify the guest: prevents receive path from getting stuck. */
+    if ( console_rx == 1 )
+    {
+        /* Deliver input to guest buffer, unless it is already full. */
+        if ( (serial_rx_prod - serial_rx_cons) != SERIAL_RX_SIZE )
+            serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
+    }
+#ifdef CONFIG_SBSA_VUART_CONSOLE
+    else
+    {
+        struct domain *d = get_domain_by_id(console_rx - 1);
+
+        /*
+         * If we have a properly initialized vpl011 console for the
+         * domain, without a full PV ring to Dom0 (in that case input
+         * comes from the PV ring), then send the character to it.
+         */
+        if ( !d->arch.vpl011.backend_in_domain && d->arch.vpl011.xen != NULL )
+            vpl011_rx_char_xen(d, c);
+        else
+            printk("Cannot send chars to Dom%d: no UART available\n",
+                   d->domain_id);
+    }
+#endif
+    /*
+     * Always notify the hardware domain: prevents receive path from
+     * getting stuck.
+     */
     send_global_virq(VIRQ_CONSOLE);
 
 #ifdef CONFIG_X86
@@ -923,7 +968,7 @@ void __init console_endboot(void)
      * a useful 'how to switch' message.
      */
     if ( opt_conswitch[1] == 'x' )
-        xen_rx = !xen_rx;
+        console_rx = 0;
 
     register_keyhandler('w', dump_console_ring_key,
                         "synchronously dump console ring buffer (dmesg)", 0);
diff --git a/xen/include/xen/console.h b/xen/include/xen/console.h
index ea06fd8..2fe3912 100644
--- a/xen/include/xen/console.h
+++ b/xen/include/xen/console.h
@@ -31,6 +31,8 @@ void console_end_sync(void);
 void console_start_log_everything(void);
 void console_end_log_everything(void);
 
+struct domain *console_input_domain(void);
+
 /*
  * Steal output from the console. Returns +ve identifier, else -ve error.
  * Takes the handle of the serial line to steal, and steal callback function.
-- 
1.9.1


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

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

* [PATCH v3 24/25] xen/vpl011: buffer out chars when the backend is xen
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (22 preceding siblings ...)
  2018-07-31 23:28 ` [PATCH v3 23/25] xen: support console_switching between Dom0 and DomUs on ARM Stefano Stabellini
@ 2018-07-31 23:28 ` Stefano Stabellini
  2018-08-13 14:21   ` Julien Grall
  2018-07-31 23:28 ` [PATCH v3 25/25] xen/arm: split domain_build.c Stefano Stabellini
  2018-08-22 15:44 ` [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Julien Grall
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:28 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

To avoid mixing the output of different domains on the console, buffer
the output chars and print line by line. Unless the domain has input
from the serial, in which case we want to print char by char for a
smooth user experience.

The size of SBSA_UART_OUT_BUF_SIZE is arbitrary. 90 should be large
enough to accommodate the length of most lines of output (typically they
are limited to 80 characters on Unix systems), plus one extra char for
the string terminator.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
 xen/arch/arm/vpl011.c        | 21 ++++++++++++++++++---
 xen/include/asm-arm/vpl011.h |  3 +++
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index f206c61..8137371 100644
--- a/xen/arch/arm/vpl011.c
+++ b/xen/arch/arm/vpl011.c
@@ -28,6 +28,7 @@
 #include <xen/lib.h>
 #include <xen/mm.h>
 #include <xen/sched.h>
+#include <xen/console.h>
 #include <public/domctl.h>
 #include <public/io/console.h>
 #include <asm/pl011-uart.h>
@@ -85,12 +86,26 @@ static void vpl011_write_data_xen(struct domain *d, uint8_t data)
 {
     unsigned long flags;
     struct vpl011 *vpl011 = &d->arch.vpl011;
+    struct vpl011_xen_backend *intf = vpl011->xen;
+    struct domain *input = console_input_domain();
 
     VPL011_LOCK(d, flags);
 
-    printk("%c", data);
-    if (data == '\n')
-        printk("DOM%u: ", d->domain_id);
+    intf->out[intf->out_prod++] = data;
+    if ( d == input && intf->out_prod == 1 )
+    {
+        printk("%c", data);
+        if ( data == '\n' )
+            printk("DOM%u: ", d->domain_id);
+        intf->out_prod = 0;
+    } else if ( d == input ||
+                intf->out_prod == SBSA_UART_OUT_BUF_SIZE - 1 ||
+                data == '\n' )
+    {
+        intf->out[intf->out_prod++] = '\0';
+        printk("DOM%u: %s", d->domain_id, intf->out);
+        intf->out_prod = 0;
+    }
 
     vpl011->uartris |= TXI;
     vpl011->uartfr &= ~TXFE;
diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
index c9918c1..30487e8 100644
--- a/xen/include/asm-arm/vpl011.h
+++ b/xen/include/asm-arm/vpl011.h
@@ -30,9 +30,12 @@
 #define VPL011_UNLOCK(d,flags) spin_unlock_irqrestore(&(d)->arch.vpl011.lock, flags)
 
 #define SBSA_UART_FIFO_SIZE 32
+#define SBSA_UART_OUT_BUF_SIZE 91
 struct vpl011_xen_backend {
     char in[SBSA_UART_FIFO_SIZE];
+    char out[SBSA_UART_OUT_BUF_SIZE];
     XENCONS_RING_IDX in_cons, in_prod;
+    XENCONS_RING_IDX out_prod;
 };
 
 struct vpl011 {
-- 
1.9.1


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

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

* [PATCH v3 25/25] xen/arm: split domain_build.c
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (23 preceding siblings ...)
  2018-07-31 23:28 ` [PATCH v3 24/25] xen/vpl011: buffer out chars when the backend is xen Stefano Stabellini
@ 2018-07-31 23:28 ` Stefano Stabellini
  2018-08-13 14:29   ` Julien Grall
  2018-08-22 15:44 ` [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Julien Grall
  25 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-07-31 23:28 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

domain_build.c is too large.

Move all the ACPI specific device tree generating functions from
domain_build.c to acpi/acpi_dt_build.c.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
 xen/arch/arm/acpi/Makefile        |   1 +
 xen/arch/arm/acpi/acpi_dt_build.c | 591 ++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/acpi/acpi_dt_build.h |  32 +++
 xen/arch/arm/domain_build.c       | 585 +------------------------------------
 4 files changed, 629 insertions(+), 580 deletions(-)
 create mode 100644 xen/arch/arm/acpi/acpi_dt_build.c
 create mode 100644 xen/arch/arm/acpi/acpi_dt_build.h

diff --git a/xen/arch/arm/acpi/Makefile b/xen/arch/arm/acpi/Makefile
index 23963f8..ac0804b 100644
--- a/xen/arch/arm/acpi/Makefile
+++ b/xen/arch/arm/acpi/Makefile
@@ -1,2 +1,3 @@
 obj-y += lib.o
+obj-y += acpi_dt_build.o
 obj-y += boot.init.o
diff --git a/xen/arch/arm/acpi/acpi_dt_build.c b/xen/arch/arm/acpi/acpi_dt_build.c
new file mode 100644
index 0000000..7e12d64
--- /dev/null
+++ b/xen/arch/arm/acpi/acpi_dt_build.c
@@ -0,0 +1,591 @@
+#include <xen/mm.h>
+#include <xen/sched.h>
+#include <xen/acpi.h>
+#include <xen/event.h>
+#include <xen/iocap.h>
+#include <xen/device_tree.h>
+#include <xen/libfdt/libfdt.h>
+#include <xen/irq.h>
+#include <asm/irq.h>
+#include <acpi/actables.h>
+#include "acpi_dt_build.h"
+#include "../kernel.h"
+
+/* Override macros from asm/page.h to make them work with mfn_t */
+#undef virt_to_mfn
+#define virt_to_mfn(va) _mfn(__virt_to_mfn(va))
+
+#define ACPI_DOM0_FDT_MIN_SIZE 4096
+
+static int __init acpi_iomem_deny_access(struct domain *d)
+{
+    acpi_status status;
+    struct acpi_table_spcr *spcr = NULL;
+    unsigned long mfn;
+    int rc;
+
+    /* Firstly permit full MMIO capabilities. */
+    rc = iomem_permit_access(d, 0UL, ~0UL);
+    if ( rc )
+        return rc;
+
+    /* TODO: Deny MMIO access for SMMU, GIC ITS */
+    status = acpi_get_table(ACPI_SIG_SPCR, 0,
+                            (struct acpi_table_header **)&spcr);
+
+    if ( ACPI_FAILURE(status) )
+    {
+        printk("Failed to get SPCR table\n");
+        return -EINVAL;
+    }
+
+    mfn = spcr->serial_port.address >> PAGE_SHIFT;
+    /* Deny MMIO access for UART */
+    rc = iomem_deny_access(d, mfn, mfn + 1);
+    if ( rc )
+        return rc;
+
+    /* Deny MMIO access for GIC regions */
+    return gic_iomem_deny_access(d);
+}
+
+static int __init acpi_route_spis(struct domain *d)
+{
+    int i, res;
+    struct irq_desc *desc;
+
+    /*
+     * Route the IRQ to hardware domain and permit the access.
+     * The interrupt type will be set by set by the hardware domain.
+     */
+    for( i = NR_LOCAL_IRQS; i < vgic_num_irqs(d); i++ )
+    {
+        /*
+         * TODO: Exclude the SPIs SMMU uses which should not be routed to
+         * the hardware domain.
+         */
+        desc = irq_to_desc(i);
+        if ( desc->action != NULL)
+            continue;
+
+        /* XXX: Shall we use a proper devname? */
+        res = map_irq_to_domain(d, i, true, "ACPI");
+        if ( res )
+            return res;
+    }
+
+    return 0;
+}
+
+static int __init acpi_make_hypervisor_node(const struct kernel_info *kinfo,
+                                            struct membank tbl_add[])
+{
+    const char compat[] =
+        "xen,xen-"__stringify(XEN_VERSION)"."__stringify(XEN_SUBVERSION)"\0"
+        "xen,xen";
+    int res;
+    /* Convenience alias */
+    void *fdt = kinfo->fdt;
+
+    dt_dprintk("Create hypervisor node\n");
+
+    /* See linux Documentation/devicetree/bindings/arm/xen.txt */
+    res = fdt_begin_node(fdt, "hypervisor");
+    if ( res )
+        return res;
+
+    /* Cannot use fdt_property_string due to embedded nulls */
+    res = fdt_property(fdt, "compatible", compat, sizeof(compat));
+    if ( res )
+        return res;
+
+    res = acpi_make_efi_nodes(fdt, tbl_add);
+    if ( res )
+        return res;
+
+    res = fdt_end_node(fdt);
+
+    return res;
+}
+
+/*
+ * Prepare a minimal DTB for Dom0 which contains bootargs, initrd, memory
+ * information, EFI table.
+ */
+static int __init create_acpi_dtb(struct kernel_info *kinfo,
+                                  struct membank tbl_add[])
+{
+    int new_size;
+    int ret;
+
+    dt_dprintk("Prepare a min DTB for DOM0\n");
+
+    /* Allocate min size for DT */
+    new_size = ACPI_DOM0_FDT_MIN_SIZE;
+    kinfo->fdt = xmalloc_bytes(new_size);
+
+    if ( kinfo->fdt == NULL )
+        return -ENOMEM;
+
+    /* Create a new empty DT for DOM0 */
+    ret = fdt_create(kinfo->fdt, new_size);
+    if ( ret < 0 )
+        goto err;
+
+    ret = fdt_finish_reservemap(kinfo->fdt);
+    if ( ret < 0 )
+        goto err;
+
+    ret = fdt_begin_node(kinfo->fdt, "/");
+    if ( ret < 0 )
+        goto err;
+
+    ret = fdt_property_cell(kinfo->fdt, "#address-cells", 2);
+    if ( ret )
+        return ret;
+
+    ret = fdt_property_cell(kinfo->fdt, "#size-cells", 1);
+    if ( ret )
+        return ret;
+
+    /* Create a chosen node for DOM0 */
+    ret = make_chosen_node(kinfo);
+    if ( ret )
+        goto err;
+
+    ret = acpi_make_hypervisor_node(kinfo, tbl_add);
+    if ( ret )
+        goto err;
+
+    ret = fdt_end_node(kinfo->fdt);
+    if ( ret < 0 )
+        goto err;
+
+    ret = fdt_finish(kinfo->fdt);
+    if ( ret < 0 )
+        goto err;
+
+    return 0;
+
+  err:
+    printk("Device tree generation failed (%d).\n", ret);
+    xfree(kinfo->fdt);
+    return -EINVAL;
+}
+
+static void __init acpi_map_other_tables(struct domain *d)
+{
+    int i;
+    unsigned long res;
+    u64 addr, size;
+
+    /* Map all ACPI tables to Dom0 using 1:1 mappings. */
+    for( i = 0; i < acpi_gbl_root_table_list.count; i++ )
+    {
+        addr = acpi_gbl_root_table_list.tables[i].address;
+        size = acpi_gbl_root_table_list.tables[i].length;
+        res = map_regions_p2mt(d,
+                               gaddr_to_gfn(addr),
+                               PFN_UP(size),
+                               maddr_to_mfn(addr),
+                               p2m_mmio_direct_c);
+        if ( res )
+        {
+             panic(XENLOG_ERR "Unable to map ACPI region 0x%"PRIx64
+                   " - 0x%"PRIx64" in domain \n",
+                   addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1);
+        }
+    }
+}
+
+static int __init acpi_create_rsdp(struct domain *d, struct membank tbl_add[])
+{
+
+    struct acpi_table_rsdp *rsdp = NULL;
+    u64 addr;
+    u64 table_size = sizeof(struct acpi_table_rsdp);
+    u8 *base_ptr;
+    u8 checksum;
+
+    addr = acpi_os_get_root_pointer();
+    if ( !addr  )
+    {
+        printk("Unable to get acpi root pointer\n");
+        return -EINVAL;
+    }
+    rsdp = acpi_os_map_memory(addr, table_size);
+    base_ptr = d->arch.efi_acpi_table
+               + acpi_get_table_offset(tbl_add, TBL_RSDP);
+    memcpy(base_ptr, rsdp, table_size);
+    acpi_os_unmap_memory(rsdp, table_size);
+
+    rsdp = (struct acpi_table_rsdp *)base_ptr;
+    /* Replace xsdt_physical_address */
+    rsdp->xsdt_physical_address = tbl_add[TBL_XSDT].start;
+    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, rsdp), table_size);
+    rsdp->checksum = rsdp->checksum - checksum;
+
+    tbl_add[TBL_RSDP].start = d->arch.efi_acpi_gpa
+                              + acpi_get_table_offset(tbl_add, TBL_RSDP);
+    tbl_add[TBL_RSDP].size = table_size;
+
+    return 0;
+}
+
+static void __init acpi_xsdt_modify_entry(u64 entry[],
+                                          unsigned long entry_count,
+                                          char *signature, u64 addr)
+{
+    int i;
+    struct acpi_table_header *table;
+    u64 size = sizeof(struct acpi_table_header);
+
+    for( i = 0; i < entry_count; i++ )
+    {
+        table = acpi_os_map_memory(entry[i], size);
+        if ( ACPI_COMPARE_NAME(table->signature, signature) )
+        {
+            entry[i] = addr;
+            acpi_os_unmap_memory(table, size);
+            break;
+        }
+        acpi_os_unmap_memory(table, size);
+    }
+}
+
+static int __init acpi_create_xsdt(struct domain *d, struct membank tbl_add[])
+{
+    struct acpi_table_header *table = NULL;
+    struct acpi_table_rsdp *rsdp_tbl;
+    struct acpi_table_xsdt *xsdt = NULL;
+    u64 table_size, addr;
+    unsigned long entry_count;
+    u8 *base_ptr;
+    u8 checksum;
+
+    addr = acpi_os_get_root_pointer();
+    if ( !addr )
+    {
+        printk("Unable to get acpi root pointer\n");
+        return -EINVAL;
+    }
+    rsdp_tbl = acpi_os_map_memory(addr, sizeof(struct acpi_table_rsdp));
+    table = acpi_os_map_memory(rsdp_tbl->xsdt_physical_address,
+                               sizeof(struct acpi_table_header));
+
+    /* Add place for STAO table in XSDT table */
+    table_size = table->length + sizeof(u64);
+    entry_count = (table->length - sizeof(struct acpi_table_header))
+                  / sizeof(u64);
+    base_ptr = d->arch.efi_acpi_table
+               + acpi_get_table_offset(tbl_add, TBL_XSDT);
+    memcpy(base_ptr, table, table->length);
+    acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
+    acpi_os_unmap_memory(rsdp_tbl, sizeof(struct acpi_table_rsdp));
+
+    xsdt = (struct acpi_table_xsdt *)base_ptr;
+    acpi_xsdt_modify_entry(xsdt->table_offset_entry, entry_count,
+                           ACPI_SIG_FADT, tbl_add[TBL_FADT].start);
+    acpi_xsdt_modify_entry(xsdt->table_offset_entry, entry_count,
+                           ACPI_SIG_MADT, tbl_add[TBL_MADT].start);
+    xsdt->table_offset_entry[entry_count] = tbl_add[TBL_STAO].start;
+
+    xsdt->header.length = table_size;
+    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, xsdt), table_size);
+    xsdt->header.checksum -= checksum;
+
+    tbl_add[TBL_XSDT].start = d->arch.efi_acpi_gpa
+                              + acpi_get_table_offset(tbl_add, TBL_XSDT);
+    tbl_add[TBL_XSDT].size = table_size;
+
+    return 0;
+}
+
+static int __init acpi_create_stao(struct domain *d, struct membank tbl_add[])
+{
+    struct acpi_table_header *table = NULL;
+    struct acpi_table_stao *stao = NULL;
+    u32 table_size = sizeof(struct acpi_table_stao);
+    u32 offset = acpi_get_table_offset(tbl_add, TBL_STAO);
+    acpi_status status;
+    u8 *base_ptr, checksum;
+
+    /* Copy OEM and ASL compiler fields from another table, use MADT */
+    status = acpi_get_table(ACPI_SIG_MADT, 0, &table);
+
+    if ( ACPI_FAILURE(status) )
+    {
+        const char *msg = acpi_format_exception(status);
+
+        printk("STAO: Failed to get MADT table, %s\n", msg);
+        return -EINVAL;
+    }
+
+    base_ptr = d->arch.efi_acpi_table + offset;
+    memcpy(base_ptr, table, sizeof(struct acpi_table_header));
+
+    stao = (struct acpi_table_stao *)base_ptr;
+    memcpy(stao->header.signature, ACPI_SIG_STAO, 4);
+    stao->header.revision = 1;
+    stao->header.length = table_size;
+    stao->ignore_uart = 1;
+    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, stao), table_size);
+    stao->header.checksum -= checksum;
+
+    tbl_add[TBL_STAO].start = d->arch.efi_acpi_gpa + offset;
+    tbl_add[TBL_STAO].size = table_size;
+
+    return 0;
+}
+
+static int __init acpi_create_madt(struct domain *d, struct membank tbl_add[])
+{
+    struct acpi_table_header *table = NULL;
+    struct acpi_table_madt *madt = NULL;
+    struct acpi_subtable_header *header;
+    struct acpi_madt_generic_distributor *gicd;
+    u32 table_size = sizeof(struct acpi_table_madt);
+    u32 offset = acpi_get_table_offset(tbl_add, TBL_MADT);
+    int ret;
+    acpi_status status;
+    u8 *base_ptr, checksum;
+
+    status = acpi_get_table(ACPI_SIG_MADT, 0, &table);
+
+    if ( ACPI_FAILURE(status) )
+    {
+        const char *msg = acpi_format_exception(status);
+
+        printk("Failed to get MADT table, %s\n", msg);
+        return -EINVAL;
+    }
+
+    base_ptr = d->arch.efi_acpi_table + offset;
+    memcpy(base_ptr, table, table_size);
+
+    /* Add Generic Distributor. */
+    header = acpi_table_get_entry_madt(ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0);
+    if ( !header )
+    {
+        printk("Can't get GICD entry\n");
+        return -EINVAL;
+    }
+    gicd = container_of(header, struct acpi_madt_generic_distributor, header);
+    memcpy(base_ptr + table_size, gicd,
+                sizeof(struct acpi_madt_generic_distributor));
+    table_size += sizeof(struct acpi_madt_generic_distributor);
+
+    /* Add other subtables. */
+    ret = gic_make_hwdom_madt(d, offset + table_size);
+    if ( ret < 0 )
+    {
+        printk("Failed to get other subtables\n");
+        return -EINVAL;
+    }
+    table_size += ret;
+
+    madt = (struct acpi_table_madt *)base_ptr;
+    madt->header.length = table_size;
+    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, madt), table_size);
+    madt->header.checksum -= checksum;
+
+    tbl_add[TBL_MADT].start = d->arch.efi_acpi_gpa + offset;
+    tbl_add[TBL_MADT].size = table_size;
+
+    return 0;
+}
+
+static int __init acpi_create_fadt(struct domain *d, struct membank tbl_add[])
+{
+    struct acpi_table_header *table = NULL;
+    struct acpi_table_fadt *fadt = NULL;
+    u64 table_size;
+    acpi_status status;
+    u8 *base_ptr;
+    u8 checksum;
+
+    status = acpi_get_table(ACPI_SIG_FADT, 0, &table);
+
+    if ( ACPI_FAILURE(status) )
+    {
+        const char *msg = acpi_format_exception(status);
+
+        printk("Failed to get FADT table, %s\n", msg);
+        return -EINVAL;
+    }
+
+    table_size = table->length;
+    base_ptr = d->arch.efi_acpi_table
+               + acpi_get_table_offset(tbl_add, TBL_FADT);
+    memcpy(base_ptr, table, table_size);
+    fadt = (struct acpi_table_fadt *)base_ptr;
+
+    /* Set PSCI_COMPLIANT and PSCI_USE_HVC */
+    fadt->arm_boot_flags |= (ACPI_FADT_PSCI_COMPLIANT | ACPI_FADT_PSCI_USE_HVC);
+    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, fadt), table_size);
+    fadt->header.checksum -= checksum;
+
+    tbl_add[TBL_FADT].start = d->arch.efi_acpi_gpa
+                              + acpi_get_table_offset(tbl_add, TBL_FADT);
+    tbl_add[TBL_FADT].size = table_size;
+
+    return 0;
+}
+
+static int __init estimate_acpi_efi_size(struct domain *d,
+                                         struct kernel_info *kinfo)
+{
+    size_t efi_size, acpi_size, madt_size;
+    u64 addr;
+    struct acpi_table_rsdp *rsdp_tbl;
+    struct acpi_table_header *table;
+
+    efi_size = estimate_efi_size(kinfo->mem.nr_banks);
+
+    acpi_size = ROUNDUP(sizeof(struct acpi_table_fadt), 8);
+    acpi_size += ROUNDUP(sizeof(struct acpi_table_stao), 8);
+
+    madt_size = gic_get_hwdom_madt_size(d);
+    acpi_size += ROUNDUP(madt_size, 8);
+
+    addr = acpi_os_get_root_pointer();
+    if ( !addr )
+    {
+        printk("Unable to get acpi root pointer\n");
+        return -EINVAL;
+    }
+
+    rsdp_tbl = acpi_os_map_memory(addr, sizeof(struct acpi_table_rsdp));
+    if ( !rsdp_tbl )
+    {
+        printk("Unable to map RSDP table\n");
+        return -EINVAL;
+    }
+
+    table = acpi_os_map_memory(rsdp_tbl->xsdt_physical_address,
+                               sizeof(struct acpi_table_header));
+    acpi_os_unmap_memory(rsdp_tbl, sizeof(struct acpi_table_rsdp));
+    if ( !table )
+    {
+        printk("Unable to map XSDT table\n");
+        return -EINVAL;
+    }
+
+    /* Add place for STAO table in XSDT table */
+    acpi_size += ROUNDUP(table->length + sizeof(u64), 8);
+    acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
+
+    acpi_size += ROUNDUP(sizeof(struct acpi_table_rsdp), 8);
+    d->arch.efi_acpi_len = PAGE_ALIGN(ROUNDUP(efi_size, 8)
+                                      + ROUNDUP(acpi_size, 8));
+
+    return 0;
+}
+
+int __init prepare_acpi(struct domain *d, struct kernel_info *kinfo)
+{
+    int rc = 0;
+    int order;
+    struct membank tbl_add[TBL_MMAX] = {};
+
+    rc = estimate_acpi_efi_size(d, kinfo);
+    if ( rc != 0 )
+        return rc;
+
+    order = get_order_from_bytes(d->arch.efi_acpi_len);
+    d->arch.efi_acpi_table = alloc_xenheap_pages(order, 0);
+    if ( d->arch.efi_acpi_table == NULL )
+    {
+        printk("unable to allocate memory!\n");
+        return -ENOMEM;
+    }
+    memset(d->arch.efi_acpi_table, 0, d->arch.efi_acpi_len);
+
+    /*
+     * For ACPI, Dom0 doesn't use kinfo->gnttab_start to get the grant table
+     * region. So we use it as the ACPI table mapped address. Also it needs to
+     * check if the size of grant table region is enough for those ACPI tables.
+     */
+    d->arch.efi_acpi_gpa = kinfo->gnttab_start;
+    if ( kinfo->gnttab_size < d->arch.efi_acpi_len )
+    {
+        printk("The grant table region is not enough to fit the ACPI tables!\n");
+        return -EINVAL;
+    }
+
+    rc = acpi_create_fadt(d, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_create_madt(d, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_create_stao(d, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_create_xsdt(d, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_create_rsdp(d, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    acpi_map_other_tables(d);
+    acpi_create_efi_system_table(d, tbl_add);
+    acpi_create_efi_mmap_table(d, &kinfo->mem, tbl_add);
+
+    /* Map the EFI and ACPI tables to Dom0 */
+    rc = map_regions_p2mt(d,
+                          gaddr_to_gfn(d->arch.efi_acpi_gpa),
+                          PFN_UP(d->arch.efi_acpi_len),
+                          virt_to_mfn(d->arch.efi_acpi_table),
+                          p2m_mmio_direct_c);
+    if ( rc != 0 )
+    {
+        printk(XENLOG_ERR "Unable to map EFI/ACPI table 0x%"PRIx64
+               " - 0x%"PRIx64" in domain %d\n",
+               d->arch.efi_acpi_gpa & PAGE_MASK,
+               PAGE_ALIGN(d->arch.efi_acpi_gpa + d->arch.efi_acpi_len) - 1,
+               d->domain_id);
+        return rc;
+    }
+
+    /*
+     * Flush the cache for this region, otherwise DOM0 may read wrong data when
+     * the cache is disabled.
+     */
+    clean_and_invalidate_dcache_va_range(d->arch.efi_acpi_table,
+                                         d->arch.efi_acpi_len);
+
+    rc = create_acpi_dtb(kinfo, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_route_spis(d);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_iomem_deny_access(d);
+    if ( rc != 0 )
+        return rc;
+
+    /*
+     * All PPIs have been registered, allocate the event channel
+     * interrupts.
+     */
+    evtchn_allocate(d);
+
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/acpi/acpi_dt_build.h b/xen/arch/arm/acpi/acpi_dt_build.h
new file mode 100644
index 0000000..08e7aab
--- /dev/null
+++ b/xen/arch/arm/acpi/acpi_dt_build.h
@@ -0,0 +1,32 @@
+#ifndef __ARCH_ARM_ACPI_ACPI_DT_BUILD_H__
+#define __ARCH_ARM_ACPI_ACPI_DT_BUILD_H__
+
+#include <xen/sched.h>
+#include "../kernel.h"
+
+int map_irq_to_domain(struct domain *d, unsigned int irq,
+                      bool need_mapping, const char *devname);
+int make_chosen_node(const struct kernel_info *kinfo);
+void evtchn_allocate(struct domain *d);
+
+#ifndef CONFIG_ACPI
+static inline int prepare_acpi(struct domain *d, struct kernel_info *kinfo)
+{
+    /* Only booting with ACPI will hit here */
+    BUG();
+    return -EINVAL;
+}
+#else
+int prepare_acpi(struct domain *d, struct kernel_info *kinfo);
+#endif
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 0888a76..a123111 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -24,6 +24,7 @@
 
 #include <xen/irq.h>
 #include <xen/grant_table.h>
+#include "acpi/acpi_dt_build.h"
 #include "kernel.h"
 
 static unsigned int __initdata opt_dom0_max_vcpus;
@@ -701,8 +702,6 @@ static int __init make_memory_node(const struct domain *d,
     return res;
 }
 
-static void evtchn_allocate(struct domain *d);
-
 static int __init make_hypervisor_node(struct domain *d,
                                        const struct kernel_info *kinfo,
                                        int addrcells, int sizecells)
@@ -1063,7 +1062,7 @@ static int __init make_timer_node(const struct domain *d, void *fdt,
  * on ACPI systems, and DomUs started directly from Xen based on device
  * tree information.
  */
-static int __init make_chosen_node(const struct kernel_info *kinfo)
+int __init make_chosen_node(const struct kernel_info *kinfo)
 {
     int res;
     const char *bootargs = NULL;
@@ -1104,8 +1103,8 @@ static int __init make_chosen_node(const struct kernel_info *kinfo)
     return res;
 }
 
-static int __init map_irq_to_domain(struct domain *d, unsigned int irq,
-                                    bool need_mapping, const char *devname)
+int __init map_irq_to_domain(struct domain *d, unsigned int irq,
+                             bool need_mapping, const char *devname)
 {
     int res;
 
@@ -1800,580 +1799,6 @@ static int __init prepare_dtb_hwdom(struct domain *d, struct kernel_info *kinfo)
     return -EINVAL;
 }
 
-#ifdef CONFIG_ACPI
-#define ACPI_DOM0_FDT_MIN_SIZE 4096
-
-static int __init acpi_iomem_deny_access(struct domain *d)
-{
-    acpi_status status;
-    struct acpi_table_spcr *spcr = NULL;
-    unsigned long mfn;
-    int rc;
-
-    /* Firstly permit full MMIO capabilities. */
-    rc = iomem_permit_access(d, 0UL, ~0UL);
-    if ( rc )
-        return rc;
-
-    /* TODO: Deny MMIO access for SMMU, GIC ITS */
-    status = acpi_get_table(ACPI_SIG_SPCR, 0,
-                            (struct acpi_table_header **)&spcr);
-
-    if ( ACPI_FAILURE(status) )
-    {
-        printk("Failed to get SPCR table\n");
-        return -EINVAL;
-    }
-
-    mfn = spcr->serial_port.address >> PAGE_SHIFT;
-    /* Deny MMIO access for UART */
-    rc = iomem_deny_access(d, mfn, mfn + 1);
-    if ( rc )
-        return rc;
-
-    /* Deny MMIO access for GIC regions */
-    return gic_iomem_deny_access(d);
-}
-
-static int __init acpi_route_spis(struct domain *d)
-{
-    int i, res;
-    struct irq_desc *desc;
-
-    /*
-     * Route the IRQ to hardware domain and permit the access.
-     * The interrupt type will be set by set by the hardware domain.
-     */
-    for( i = NR_LOCAL_IRQS; i < vgic_num_irqs(d); i++ )
-    {
-        /*
-         * TODO: Exclude the SPIs SMMU uses which should not be routed to
-         * the hardware domain.
-         */
-        desc = irq_to_desc(i);
-        if ( desc->action != NULL)
-            continue;
-
-        /* XXX: Shall we use a proper devname? */
-        res = map_irq_to_domain(d, i, true, "ACPI");
-        if ( res )
-            return res;
-    }
-
-    return 0;
-}
-
-static int __init acpi_make_hypervisor_node(const struct kernel_info *kinfo,
-                                            struct membank tbl_add[])
-{
-    const char compat[] =
-        "xen,xen-"__stringify(XEN_VERSION)"."__stringify(XEN_SUBVERSION)"\0"
-        "xen,xen";
-    int res;
-    /* Convenience alias */
-    void *fdt = kinfo->fdt;
-
-    dt_dprintk("Create hypervisor node\n");
-
-    /* See linux Documentation/devicetree/bindings/arm/xen.txt */
-    res = fdt_begin_node(fdt, "hypervisor");
-    if ( res )
-        return res;
-
-    /* Cannot use fdt_property_string due to embedded nulls */
-    res = fdt_property(fdt, "compatible", compat, sizeof(compat));
-    if ( res )
-        return res;
-
-    res = acpi_make_efi_nodes(fdt, tbl_add);
-    if ( res )
-        return res;
-
-    res = fdt_end_node(fdt);
-
-    return res;
-}
-
-/*
- * Prepare a minimal DTB for Dom0 which contains bootargs, initrd, memory
- * information, EFI table.
- */
-static int __init create_acpi_dtb(struct kernel_info *kinfo,
-                                  struct membank tbl_add[])
-{
-    int new_size;
-    int ret;
-
-    dt_dprintk("Prepare a min DTB for DOM0\n");
-
-    /* Allocate min size for DT */
-    new_size = ACPI_DOM0_FDT_MIN_SIZE;
-    kinfo->fdt = xmalloc_bytes(new_size);
-
-    if ( kinfo->fdt == NULL )
-        return -ENOMEM;
-
-    /* Create a new empty DT for DOM0 */
-    ret = fdt_create(kinfo->fdt, new_size);
-    if ( ret < 0 )
-        goto err;
-
-    ret = fdt_finish_reservemap(kinfo->fdt);
-    if ( ret < 0 )
-        goto err;
-
-    ret = fdt_begin_node(kinfo->fdt, "/");
-    if ( ret < 0 )
-        goto err;
-
-    ret = fdt_property_cell(kinfo->fdt, "#address-cells", 2);
-    if ( ret )
-        return ret;
-
-    ret = fdt_property_cell(kinfo->fdt, "#size-cells", 1);
-    if ( ret )
-        return ret;
-
-    /* Create a chosen node for DOM0 */
-    ret = make_chosen_node(kinfo);
-    if ( ret )
-        goto err;
-
-    ret = acpi_make_hypervisor_node(kinfo, tbl_add);
-    if ( ret )
-        goto err;
-
-    ret = fdt_end_node(kinfo->fdt);
-    if ( ret < 0 )
-        goto err;
-
-    ret = fdt_finish(kinfo->fdt);
-    if ( ret < 0 )
-        goto err;
-
-    return 0;
-
-  err:
-    printk("Device tree generation failed (%d).\n", ret);
-    xfree(kinfo->fdt);
-    return -EINVAL;
-}
-
-static void __init acpi_map_other_tables(struct domain *d)
-{
-    int i;
-    unsigned long res;
-    u64 addr, size;
-
-    /* Map all ACPI tables to Dom0 using 1:1 mappings. */
-    for( i = 0; i < acpi_gbl_root_table_list.count; i++ )
-    {
-        addr = acpi_gbl_root_table_list.tables[i].address;
-        size = acpi_gbl_root_table_list.tables[i].length;
-        res = map_regions_p2mt(d,
-                               gaddr_to_gfn(addr),
-                               PFN_UP(size),
-                               maddr_to_mfn(addr),
-                               p2m_mmio_direct_c);
-        if ( res )
-        {
-             panic(XENLOG_ERR "Unable to map ACPI region 0x%"PRIx64
-                   " - 0x%"PRIx64" in domain \n",
-                   addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1);
-        }
-    }
-}
-
-static int __init acpi_create_rsdp(struct domain *d, struct membank tbl_add[])
-{
-
-    struct acpi_table_rsdp *rsdp = NULL;
-    u64 addr;
-    u64 table_size = sizeof(struct acpi_table_rsdp);
-    u8 *base_ptr;
-    u8 checksum;
-
-    addr = acpi_os_get_root_pointer();
-    if ( !addr  )
-    {
-        printk("Unable to get acpi root pointer\n");
-        return -EINVAL;
-    }
-    rsdp = acpi_os_map_memory(addr, table_size);
-    base_ptr = d->arch.efi_acpi_table
-               + acpi_get_table_offset(tbl_add, TBL_RSDP);
-    memcpy(base_ptr, rsdp, table_size);
-    acpi_os_unmap_memory(rsdp, table_size);
-
-    rsdp = (struct acpi_table_rsdp *)base_ptr;
-    /* Replace xsdt_physical_address */
-    rsdp->xsdt_physical_address = tbl_add[TBL_XSDT].start;
-    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, rsdp), table_size);
-    rsdp->checksum = rsdp->checksum - checksum;
-
-    tbl_add[TBL_RSDP].start = d->arch.efi_acpi_gpa
-                              + acpi_get_table_offset(tbl_add, TBL_RSDP);
-    tbl_add[TBL_RSDP].size = table_size;
-
-    return 0;
-}
-
-static void __init acpi_xsdt_modify_entry(u64 entry[],
-                                          unsigned long entry_count,
-                                          char *signature, u64 addr)
-{
-    int i;
-    struct acpi_table_header *table;
-    u64 size = sizeof(struct acpi_table_header);
-
-    for( i = 0; i < entry_count; i++ )
-    {
-        table = acpi_os_map_memory(entry[i], size);
-        if ( ACPI_COMPARE_NAME(table->signature, signature) )
-        {
-            entry[i] = addr;
-            acpi_os_unmap_memory(table, size);
-            break;
-        }
-        acpi_os_unmap_memory(table, size);
-    }
-}
-
-static int __init acpi_create_xsdt(struct domain *d, struct membank tbl_add[])
-{
-    struct acpi_table_header *table = NULL;
-    struct acpi_table_rsdp *rsdp_tbl;
-    struct acpi_table_xsdt *xsdt = NULL;
-    u64 table_size, addr;
-    unsigned long entry_count;
-    u8 *base_ptr;
-    u8 checksum;
-
-    addr = acpi_os_get_root_pointer();
-    if ( !addr )
-    {
-        printk("Unable to get acpi root pointer\n");
-        return -EINVAL;
-    }
-    rsdp_tbl = acpi_os_map_memory(addr, sizeof(struct acpi_table_rsdp));
-    table = acpi_os_map_memory(rsdp_tbl->xsdt_physical_address,
-                               sizeof(struct acpi_table_header));
-
-    /* Add place for STAO table in XSDT table */
-    table_size = table->length + sizeof(u64);
-    entry_count = (table->length - sizeof(struct acpi_table_header))
-                  / sizeof(u64);
-    base_ptr = d->arch.efi_acpi_table
-               + acpi_get_table_offset(tbl_add, TBL_XSDT);
-    memcpy(base_ptr, table, table->length);
-    acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
-    acpi_os_unmap_memory(rsdp_tbl, sizeof(struct acpi_table_rsdp));
-
-    xsdt = (struct acpi_table_xsdt *)base_ptr;
-    acpi_xsdt_modify_entry(xsdt->table_offset_entry, entry_count,
-                           ACPI_SIG_FADT, tbl_add[TBL_FADT].start);
-    acpi_xsdt_modify_entry(xsdt->table_offset_entry, entry_count,
-                           ACPI_SIG_MADT, tbl_add[TBL_MADT].start);
-    xsdt->table_offset_entry[entry_count] = tbl_add[TBL_STAO].start;
-
-    xsdt->header.length = table_size;
-    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, xsdt), table_size);
-    xsdt->header.checksum -= checksum;
-
-    tbl_add[TBL_XSDT].start = d->arch.efi_acpi_gpa
-                              + acpi_get_table_offset(tbl_add, TBL_XSDT);
-    tbl_add[TBL_XSDT].size = table_size;
-
-    return 0;
-}
-
-static int __init acpi_create_stao(struct domain *d, struct membank tbl_add[])
-{
-    struct acpi_table_header *table = NULL;
-    struct acpi_table_stao *stao = NULL;
-    u32 table_size = sizeof(struct acpi_table_stao);
-    u32 offset = acpi_get_table_offset(tbl_add, TBL_STAO);
-    acpi_status status;
-    u8 *base_ptr, checksum;
-
-    /* Copy OEM and ASL compiler fields from another table, use MADT */
-    status = acpi_get_table(ACPI_SIG_MADT, 0, &table);
-
-    if ( ACPI_FAILURE(status) )
-    {
-        const char *msg = acpi_format_exception(status);
-
-        printk("STAO: Failed to get MADT table, %s\n", msg);
-        return -EINVAL;
-    }
-
-    base_ptr = d->arch.efi_acpi_table + offset;
-    memcpy(base_ptr, table, sizeof(struct acpi_table_header));
-
-    stao = (struct acpi_table_stao *)base_ptr;
-    memcpy(stao->header.signature, ACPI_SIG_STAO, 4);
-    stao->header.revision = 1;
-    stao->header.length = table_size;
-    stao->ignore_uart = 1;
-    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, stao), table_size);
-    stao->header.checksum -= checksum;
-
-    tbl_add[TBL_STAO].start = d->arch.efi_acpi_gpa + offset;
-    tbl_add[TBL_STAO].size = table_size;
-
-    return 0;
-}
-
-static int __init acpi_create_madt(struct domain *d, struct membank tbl_add[])
-{
-    struct acpi_table_header *table = NULL;
-    struct acpi_table_madt *madt = NULL;
-    struct acpi_subtable_header *header;
-    struct acpi_madt_generic_distributor *gicd;
-    u32 table_size = sizeof(struct acpi_table_madt);
-    u32 offset = acpi_get_table_offset(tbl_add, TBL_MADT);
-    int ret;
-    acpi_status status;
-    u8 *base_ptr, checksum;
-
-    status = acpi_get_table(ACPI_SIG_MADT, 0, &table);
-
-    if ( ACPI_FAILURE(status) )
-    {
-        const char *msg = acpi_format_exception(status);
-
-        printk("Failed to get MADT table, %s\n", msg);
-        return -EINVAL;
-    }
-
-    base_ptr = d->arch.efi_acpi_table + offset;
-    memcpy(base_ptr, table, table_size);
-
-    /* Add Generic Distributor. */
-    header = acpi_table_get_entry_madt(ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0);
-    if ( !header )
-    {
-        printk("Can't get GICD entry\n");
-        return -EINVAL;
-    }
-    gicd = container_of(header, struct acpi_madt_generic_distributor, header);
-    memcpy(base_ptr + table_size, gicd,
-                sizeof(struct acpi_madt_generic_distributor));
-    table_size += sizeof(struct acpi_madt_generic_distributor);
-
-    /* Add other subtables. */
-    ret = gic_make_hwdom_madt(d, offset + table_size);
-    if ( ret < 0 )
-    {
-        printk("Failed to get other subtables\n");
-        return -EINVAL;
-    }
-    table_size += ret;
-
-    madt = (struct acpi_table_madt *)base_ptr;
-    madt->header.length = table_size;
-    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, madt), table_size);
-    madt->header.checksum -= checksum;
-
-    tbl_add[TBL_MADT].start = d->arch.efi_acpi_gpa + offset;
-    tbl_add[TBL_MADT].size = table_size;
-
-    return 0;
-}
-
-static int __init acpi_create_fadt(struct domain *d, struct membank tbl_add[])
-{
-    struct acpi_table_header *table = NULL;
-    struct acpi_table_fadt *fadt = NULL;
-    u64 table_size;
-    acpi_status status;
-    u8 *base_ptr;
-    u8 checksum;
-
-    status = acpi_get_table(ACPI_SIG_FADT, 0, &table);
-
-    if ( ACPI_FAILURE(status) )
-    {
-        const char *msg = acpi_format_exception(status);
-
-        printk("Failed to get FADT table, %s\n", msg);
-        return -EINVAL;
-    }
-
-    table_size = table->length;
-    base_ptr = d->arch.efi_acpi_table
-               + acpi_get_table_offset(tbl_add, TBL_FADT);
-    memcpy(base_ptr, table, table_size);
-    fadt = (struct acpi_table_fadt *)base_ptr;
-
-    /* Set PSCI_COMPLIANT and PSCI_USE_HVC */
-    fadt->arm_boot_flags |= (ACPI_FADT_PSCI_COMPLIANT | ACPI_FADT_PSCI_USE_HVC);
-    checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, fadt), table_size);
-    fadt->header.checksum -= checksum;
-
-    tbl_add[TBL_FADT].start = d->arch.efi_acpi_gpa
-                              + acpi_get_table_offset(tbl_add, TBL_FADT);
-    tbl_add[TBL_FADT].size = table_size;
-
-    return 0;
-}
-
-static int __init estimate_acpi_efi_size(struct domain *d,
-                                         struct kernel_info *kinfo)
-{
-    size_t efi_size, acpi_size, madt_size;
-    u64 addr;
-    struct acpi_table_rsdp *rsdp_tbl;
-    struct acpi_table_header *table;
-
-    efi_size = estimate_efi_size(kinfo->mem.nr_banks);
-
-    acpi_size = ROUNDUP(sizeof(struct acpi_table_fadt), 8);
-    acpi_size += ROUNDUP(sizeof(struct acpi_table_stao), 8);
-
-    madt_size = gic_get_hwdom_madt_size(d);
-    acpi_size += ROUNDUP(madt_size, 8);
-
-    addr = acpi_os_get_root_pointer();
-    if ( !addr )
-    {
-        printk("Unable to get acpi root pointer\n");
-        return -EINVAL;
-    }
-
-    rsdp_tbl = acpi_os_map_memory(addr, sizeof(struct acpi_table_rsdp));
-    if ( !rsdp_tbl )
-    {
-        printk("Unable to map RSDP table\n");
-        return -EINVAL;
-    }
-
-    table = acpi_os_map_memory(rsdp_tbl->xsdt_physical_address,
-                               sizeof(struct acpi_table_header));
-    acpi_os_unmap_memory(rsdp_tbl, sizeof(struct acpi_table_rsdp));
-    if ( !table )
-    {
-        printk("Unable to map XSDT table\n");
-        return -EINVAL;
-    }
-
-    /* Add place for STAO table in XSDT table */
-    acpi_size += ROUNDUP(table->length + sizeof(u64), 8);
-    acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
-
-    acpi_size += ROUNDUP(sizeof(struct acpi_table_rsdp), 8);
-    d->arch.efi_acpi_len = PAGE_ALIGN(ROUNDUP(efi_size, 8)
-                                      + ROUNDUP(acpi_size, 8));
-
-    return 0;
-}
-
-static int __init prepare_acpi(struct domain *d, struct kernel_info *kinfo)
-{
-    int rc = 0;
-    int order;
-    struct membank tbl_add[TBL_MMAX] = {};
-
-    rc = estimate_acpi_efi_size(d, kinfo);
-    if ( rc != 0 )
-        return rc;
-
-    order = get_order_from_bytes(d->arch.efi_acpi_len);
-    d->arch.efi_acpi_table = alloc_xenheap_pages(order, 0);
-    if ( d->arch.efi_acpi_table == NULL )
-    {
-        printk("unable to allocate memory!\n");
-        return -ENOMEM;
-    }
-    memset(d->arch.efi_acpi_table, 0, d->arch.efi_acpi_len);
-
-    /*
-     * For ACPI, Dom0 doesn't use kinfo->gnttab_start to get the grant table
-     * region. So we use it as the ACPI table mapped address. Also it needs to
-     * check if the size of grant table region is enough for those ACPI tables.
-     */
-    d->arch.efi_acpi_gpa = kinfo->gnttab_start;
-    if ( kinfo->gnttab_size < d->arch.efi_acpi_len )
-    {
-        printk("The grant table region is not enough to fit the ACPI tables!\n");
-        return -EINVAL;
-    }
-
-    rc = acpi_create_fadt(d, tbl_add);
-    if ( rc != 0 )
-        return rc;
-
-    rc = acpi_create_madt(d, tbl_add);
-    if ( rc != 0 )
-        return rc;
-
-    rc = acpi_create_stao(d, tbl_add);
-    if ( rc != 0 )
-        return rc;
-
-    rc = acpi_create_xsdt(d, tbl_add);
-    if ( rc != 0 )
-        return rc;
-
-    rc = acpi_create_rsdp(d, tbl_add);
-    if ( rc != 0 )
-        return rc;
-
-    acpi_map_other_tables(d);
-    acpi_create_efi_system_table(d, tbl_add);
-    acpi_create_efi_mmap_table(d, &kinfo->mem, tbl_add);
-
-    /* Map the EFI and ACPI tables to Dom0 */
-    rc = map_regions_p2mt(d,
-                          gaddr_to_gfn(d->arch.efi_acpi_gpa),
-                          PFN_UP(d->arch.efi_acpi_len),
-                          virt_to_mfn(d->arch.efi_acpi_table),
-                          p2m_mmio_direct_c);
-    if ( rc != 0 )
-    {
-        printk(XENLOG_ERR "Unable to map EFI/ACPI table 0x%"PRIx64
-               " - 0x%"PRIx64" in domain %d\n",
-               d->arch.efi_acpi_gpa & PAGE_MASK,
-               PAGE_ALIGN(d->arch.efi_acpi_gpa + d->arch.efi_acpi_len) - 1,
-               d->domain_id);
-        return rc;
-    }
-
-    /*
-     * Flush the cache for this region, otherwise DOM0 may read wrong data when
-     * the cache is disabled.
-     */
-    clean_and_invalidate_dcache_va_range(d->arch.efi_acpi_table,
-                                         d->arch.efi_acpi_len);
-
-    rc = create_acpi_dtb(kinfo, tbl_add);
-    if ( rc != 0 )
-        return rc;
-
-    rc = acpi_route_spis(d);
-    if ( rc != 0 )
-        return rc;
-
-    rc = acpi_iomem_deny_access(d);
-    if ( rc != 0 )
-        return rc;
-
-    /*
-     * All PPIs have been registered, allocate the event channel
-     * interrupts.
-     */
-    evtchn_allocate(d);
-
-    return 0;
-}
-#else
-static int __init prepare_acpi(struct domain *d, struct kernel_info *kinfo)
-{
-    /* Only booting with ACPI will hit here */
-    BUG();
-    return -EINVAL;
-}
-#endif
 static void __init dtb_load(struct kernel_info *kinfo)
 {
     unsigned long left;
@@ -2446,7 +1871,7 @@ static void __init initrd_load(struct kernel_info *kinfo)
  * Note that this should only be called once all PPIs used by the
  * hardware domain have been registered.
  */
-static void __init evtchn_allocate(struct domain *d)
+void __init evtchn_allocate(struct domain *d)
 {
     int res;
     u64 val;
-- 
1.9.1


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

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

* Re: [PATCH v3 13/25] xen/arm: introduce create_domUs
  2018-07-31 23:27 ` [PATCH v3 13/25] xen/arm: introduce create_domUs Stefano Stabellini
@ 2018-08-01  8:48   ` Jan Beulich
  2018-08-13 10:23   ` Julien Grall
  2018-08-13 10:55   ` Julien Grall
  2 siblings, 0 replies; 88+ messages in thread
From: Jan Beulich @ 2018-08-01  8:48 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Andrew Cooper, Julien Grall, andrii_anisov, Stefano Stabellini,
	xen-devel

>>> On 01.08.18 at 01:27, <sstabellini@kernel.org> wrote:
> ---
>  xen/arch/arm/domain_build.c | 42 +++++++++++++++++++++++++++++++++++++++---
>  xen/arch/arm/setup.c        |  7 ++++++-
>  xen/include/asm-arm/setup.h |  3 +++
>  xen/include/asm-x86/setup.h |  2 ++

The (trivial) x86 addition
Acked-by: Jan Beulich <jbeulich@suse.com>
albeit I don't think it really belongs here, since you don't use it
outside of ARM code just yet. If I was an ARM maintainer, I'd
have three more comments/questions:

> @@ -2205,6 +2206,43 @@ static int __init __construct_domain(struct domain *d, struct kernel_info *kinfo
>      return 0;
>  }
>  
> +static int __init construct_domU(struct domain *d, struct dt_device_node *node)
> +{
> +    return 0;

As long as unimplemented I think this should return an error.

> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -63,8 +63,11 @@ static unsigned long opt_xenheap_megabytes __initdata;
>  integer_param("xenheap_megabytes", opt_xenheap_megabytes);
>  #endif
>  
> +domid_t __read_mostly max_init_domid = 0;

Pointless initializer.

> @@ -894,7 +897,7 @@ void __init start_xen(unsigned long boot_phys_offset,
>      dom0_cfg.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
>      dom0_cfg.arch.nr_spis = gic_number_lines() - 32;
>  
> -    dom0 = domain_create(0, &dom0_cfg, true);
> +    dom0 = domain_create(max_init_domid, &dom0_cfg, true);

Why?

Jan



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

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

* Re: [PATCH v3 23/25] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-31 23:28 ` [PATCH v3 23/25] xen: support console_switching between Dom0 and DomUs on ARM Stefano Stabellini
@ 2018-08-01  9:03   ` Jan Beulich
  2018-10-04 21:52     ` Stefano Stabellini
  2018-08-13 13:58   ` Julien Grall
  1 sibling, 1 reply; 88+ messages in thread
From: Jan Beulich @ 2018-08-01  9:03 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Tim Deegan, Wei Liu, George Dunlap, Andrew Cooper,
	Stefano Stabellini, Ian Jackson, xen-devel, Julien Grall,
	andrii_anisov

>>> On 01.08.18 at 01:28, <sstabellini@kernel.org> wrote:
> Today Ctrl-AAA is used to switch between Xen and Dom0. Extend the
> mechanism to allow for switching between Xen, Dom0, and any of the
> initial DomU created from Xen alongside Dom0 out of information provided
> via device tree.
> 
> Rename xen_rx to console_rx to match the new behavior.
> 
> Clarify existing comment about "notify the guest", making it clear that
> it is only about the hardware domain.
> 
> Export a function named console_input_domain() to allow others to know
> which domains has input at a given time.

As always in such cases I don't think such functions should be added
without any caller.

> @@ -389,30 +392,72 @@ static void dump_console_ring_key(unsigned char key)
>      free_xenheap_pages(buf, order);
>  }
>  
> -/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
> +/*
> + * CTRL-<switch_char> switches input direction between Xen, Dom0 and
> + * DomUs.
> + */
>  #define switch_code (opt_conswitch[0]-'a'+1)
> -static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain 0. */
> +/*
> + * console_rx=0 => input to xen
> + * console_rx=1 => input to dom0
> + * console_rx=N => input dom(N-1)
> + */
> +static int __read_mostly console_rx = 0;

Originally this was supposed to be bool, but didn't get switched yet.
With your current scheme it can't go negative and hence should be
unsigned int. However, I still wonder whether it wouldn't be better
(especially for readers of the code) is this was an actual domid_t.
But as clarified before, I'm not meaning to make this a requirement.

> +struct domain *console_input_domain(void)
> +{
> +    return get_domain_by_id(console_rx - 1);
> +}

And this is exactly the reason for the above remark: This is (or at
least looks) broken for console_rx == 0.

>  static void switch_serial_input(void)
>  {
> -    static char *input_str[2] = { "DOM0", "Xen" };
> -    xen_rx = !xen_rx;
> -    printk("*** Serial input -> %s", input_str[xen_rx]);
> +    console_rx++;
> +    if ( console_rx == max_init_domid + 2 )
> +        console_rx = 0;

Same here - the literal 2 at least raises questions. I think it would
at least be a little less confusing if you had

    if ( console_rx++ == max_init_domid + 1 )
        console_rx = 0;

>  static void __serial_rx(char c, struct cpu_user_regs *regs)
>  {
> -    if ( xen_rx )
> +    if ( console_rx == 0 )
>          return handle_keypress(c, regs);
>  
> -    /* Deliver input to guest buffer, unless it is already full. */
> -    if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
> -        serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> -    /* Always notify the guest: prevents receive path from getting stuck. */

Just like you adjust "guest" in this comment, I think you'd better ...

> +    if ( console_rx == 1 )
> +    {
> +        /* Deliver input to guest buffer, unless it is already full. */

... adjust it here too.

> +        if ( (serial_rx_prod - serial_rx_cons) != SERIAL_RX_SIZE )
> +            serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> +    }
> +#ifdef CONFIG_SBSA_VUART_CONSOLE
> +    else
> +    {
> +        struct domain *d = get_domain_by_id(console_rx - 1);
> +
> +        /*
> +         * If we have a properly initialized vpl011 console for the
> +         * domain, without a full PV ring to Dom0 (in that case input
> +         * comes from the PV ring), then send the character to it.
> +         */
> +        if ( !d->arch.vpl011.backend_in_domain && d->arch.vpl011.xen != NULL )
> +            vpl011_rx_char_xen(d, c);
> +        else
> +            printk("Cannot send chars to Dom%d: no UART available\n",
> +                   d->domain_id);
> +    }
> +#endif
> +    /*
> +     * Always notify the hardware domain: prevents receive path from
> +     * getting stuck.
> +     */
>      send_global_virq(VIRQ_CONSOLE);

Why does this not move into the if() body above?

> @@ -923,7 +968,7 @@ void __init console_endboot(void)
>       * a useful 'how to switch' message.
>       */
>      if ( opt_conswitch[1] == 'x' )
> -        xen_rx = !xen_rx;
> +        console_rx = 0;

According to the comment I think you need to store
max_init_domid + 1 here, so that the switch_serial_input() a few
lines down would actually switch to Xen.

Jan


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

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

* Re: [PATCH v3 02/25] xen/arm: move a few DT related defines to public/device_tree_defs.h
  2018-07-31 23:27 ` [PATCH v3 02/25] xen/arm: move a few DT related defines to public/device_tree_defs.h Stefano Stabellini
@ 2018-08-01  9:31   ` Julien Grall
  2018-08-22 15:25     ` Wei Liu
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-01  9:31 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: ian.jackson, Stefano Stabellini, andrii_anisov, wei.liu2, xen-devel



On 01/08/18 00:27, Stefano Stabellini wrote:
> Move a few constants defined by libxl_arm.c to
> xen/include/public/device_tree_defs.h, so that they can be used from Xen
> and libxl. Prepend GUEST_ to avoid conflicts.
> 
> Move the DT_IRQ_TYPE* definitions from libxl_arm.c to
> public/device_tree_defs.h. Use them in Xen where appropriate.
> 
> Re-define the existing Xen internal IRQ_TYPEs as DT_IRQ_TYPEs: they
> already happen to be the same, let make it clear.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

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

> CC: wei.liu2@citrix.com
> CC: ian.jackson@eu.citrix.com
> ---
> Changes in v3:
> - only expose device_tree_defs.h to XEN and XEN_TOOLS
> 
> Changes in v2:
> - introduce DT_IRQ_TYPE_* definitions in device_tree_guest.h
> - prepend GUEST_ to other definitions moved to device_tree_guest.h
> - redefine IRQ_TYPE_* as  DT_IRQ_TYPE_*
> - use DT_IRQ_TYPE_* in Xen when dealing with DT
> ---
>   tools/libxl/libxl_arm.c               | 59 ++++++++++-------------------------
>   xen/arch/arm/domain_build.c           |  8 ++---
>   xen/include/asm-arm/irq.h             | 16 ++++++++++
>   xen/include/public/device_tree_defs.h | 42 +++++++++++++++++++++++++
>   xen/include/xen/device_tree.h         | 33 +++-----------------
>   5 files changed, 83 insertions(+), 75 deletions(-)
>   create mode 100644 xen/include/public/device_tree_defs.h
> 
> diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
> index 8af9f6f..01ce2ea 100644
> --- a/tools/libxl/libxl_arm.c
> +++ b/tools/libxl/libxl_arm.c
> @@ -7,23 +7,7 @@
>   #include <stdbool.h>
>   #include <libfdt.h>
>   #include <assert.h>
> -
> -/**
> - * IRQ line type.
> - * DT_IRQ_TYPE_NONE            - default, unspecified type
> - * DT_IRQ_TYPE_EDGE_RISING     - rising edge triggered
> - * DT_IRQ_TYPE_EDGE_FALLING    - falling edge triggered
> - * DT_IRQ_TYPE_EDGE_BOTH       - rising and falling edge triggered
> - * DT_IRQ_TYPE_LEVEL_HIGH      - high level triggered
> - * DT_IRQ_TYPE_LEVEL_LOW       - low level triggered
> - */
> -#define DT_IRQ_TYPE_NONE           0x00000000
> -#define DT_IRQ_TYPE_EDGE_RISING    0x00000001
> -#define DT_IRQ_TYPE_EDGE_FALLING   0x00000002
> -#define DT_IRQ_TYPE_EDGE_BOTH                           \
> -    (DT_IRQ_TYPE_EDGE_FALLING | DT_IRQ_TYPE_EDGE_RISING)
> -#define DT_IRQ_TYPE_LEVEL_HIGH     0x00000004
> -#define DT_IRQ_TYPE_LEVEL_LOW      0x00000008
> +#include <xen/device_tree_defs.h>
>   
>   static const char *gicv_to_string(libxl_gic_version gic_version)
>   {
> @@ -165,18 +149,9 @@ static struct arch_info {
>       {"xen-3.0-aarch64", "arm,armv8-timer", "arm,armv8" },
>   };
>   
> -/*
> - * The device tree compiler (DTC) is allocating the phandle from 1 to
> - * onwards. Reserve a high value for the GIC phandle.
> - */
> -#define PHANDLE_GIC (65000)
> -
>   typedef uint32_t be32;
>   typedef be32 gic_interrupt[3];
>   
> -#define ROOT_ADDRESS_CELLS 2
> -#define ROOT_SIZE_CELLS 2
> -
>   #define PROP_INITRD_START "linux,initrd-start"
>   #define PROP_INITRD_END "linux,initrd-end"
>   
> @@ -252,7 +227,7 @@ static int fdt_property_interrupts(libxl__gc *gc, void *fdt,
>       res = fdt_property(fdt, "interrupts", intr, sizeof (intr[0]) * num_irq);
>       if (res) return res;
>   
> -    res = fdt_property_cell(fdt, "interrupt-parent", PHANDLE_GIC);
> +    res = fdt_property_cell(fdt, "interrupt-parent", GUEST_PHANDLE_GIC);
>       if (res) return res;
>   
>       return 0;
> @@ -298,13 +273,13 @@ static int make_root_properties(libxl__gc *gc,
>                                 "xen,xenvm");
>       if (res) return res;
>   
> -    res = fdt_property_cell(fdt, "interrupt-parent", PHANDLE_GIC);
> +    res = fdt_property_cell(fdt, "interrupt-parent", GUEST_PHANDLE_GIC);
>       if (res) return res;
>   
> -    res = fdt_property_cell(fdt, "#address-cells", ROOT_ADDRESS_CELLS);
> +    res = fdt_property_cell(fdt, "#address-cells", GUEST_ROOT_ADDRESS_CELLS);
>       if (res) return res;
>   
> -    res = fdt_property_cell(fdt, "#size-cells", ROOT_SIZE_CELLS);
> +    res = fdt_property_cell(fdt, "#size-cells", GUEST_ROOT_SIZE_CELLS);
>       if (res) return res;
>   
>       return 0;
> @@ -346,7 +321,7 @@ static int make_chosen_node(libxl__gc *gc, void *fdt, bool ramdisk,
>                                     "multiboot,module");
>           if (res) return res;
>   
> -        res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
> +        res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
>                                   1, 0, 0);
>           if (res) return res;
>   
> @@ -450,7 +425,7 @@ static int make_memory_nodes(libxl__gc *gc, void *fdt,
>           res = fdt_property_string(fdt, "device_type", "memory");
>           if (res) return res;
>   
> -        res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
> +        res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
>                                   1, 0, 0);
>           if (res) return res;
>   
> @@ -486,16 +461,16 @@ static int make_gicv2_node(libxl__gc *gc, void *fdt,
>       res = fdt_property(fdt, "interrupt-controller", NULL, 0);
>       if (res) return res;
>   
> -    res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
> +    res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
>                               2,
>                               gicd_base, gicd_size,
>                               gicc_base, gicc_size);
>       if (res) return res;
>   
> -    res = fdt_property_cell(fdt, "linux,phandle", PHANDLE_GIC);
> +    res = fdt_property_cell(fdt, "linux,phandle", GUEST_PHANDLE_GIC);
>       if (res) return res;
>   
> -    res = fdt_property_cell(fdt, "phandle", PHANDLE_GIC);
> +    res = fdt_property_cell(fdt, "phandle", GUEST_PHANDLE_GIC);
>       if (res) return res;
>   
>       res = fdt_end_node(fdt);
> @@ -528,16 +503,16 @@ static int make_gicv3_node(libxl__gc *gc, void *fdt)
>       res = fdt_property(fdt, "interrupt-controller", NULL, 0);
>       if (res) return res;
>   
> -    res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
> +    res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
>                               2,
>                               gicd_base, gicd_size,
>                               gicr0_base, gicr0_size);
>       if (res) return res;
>   
> -    res = fdt_property_cell(fdt, "linux,phandle", PHANDLE_GIC);
> +    res = fdt_property_cell(fdt, "linux,phandle", GUEST_PHANDLE_GIC);
>       if (res) return res;
>   
> -    res = fdt_property_cell(fdt, "phandle", PHANDLE_GIC);
> +    res = fdt_property_cell(fdt, "phandle", GUEST_PHANDLE_GIC);
>       if (res) return res;
>   
>       res = fdt_end_node(fdt);
> @@ -593,7 +568,7 @@ static int make_hypervisor_node(libxl__gc *gc, void *fdt,
>       if (res) return res;
>   
>       /* reg 0 is grant table space */
> -    res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
> +    res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
>                               1,GUEST_GNTTAB_BASE, GUEST_GNTTAB_SIZE);
>       if (res) return res;
>   
> @@ -626,7 +601,7 @@ static int make_vpl011_uart_node(libxl__gc *gc, void *fdt,
>       res = fdt_property_compat(gc, fdt, 1, "arm,sbsa-uart");
>       if (res) return res;
>   
> -    res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
> +    res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
>                               1,
>                               GUEST_PL011_BASE, GUEST_PL011_SIZE);
>       if (res) return res;
> @@ -1027,12 +1002,12 @@ static void finalise_one_node(libxl__gc *gc, void *fdt, const char *uname,
>           LOG(DEBUG, "Nopping out placeholder node %s", name);
>           fdt_nop_node(fdt, node);
>       } else {
> -        uint32_t regs[ROOT_ADDRESS_CELLS+ROOT_SIZE_CELLS];
> +        uint32_t regs[GUEST_ROOT_ADDRESS_CELLS+GUEST_ROOT_SIZE_CELLS];
>           be32 *cells = &regs[0];
>   
>           LOG(DEBUG, "Populating placeholder node %s", name);
>   
> -        set_range(&cells, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS, base, size);
> +        set_range(&cells, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS, base, size);
>   
>           res = fdt_setprop_inplace(fdt, node, "reg", regs, sizeof(regs));
>           assert(!res);
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 1351572..df9309d 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -633,7 +633,7 @@ static int __init make_hypervisor_node(struct domain *d,
>        *  - All CPUs
>        *  TODO: Handle properly the cpumask;
>        */
> -    set_interrupt_ppi(intr, d->arch.evtchn_irq, 0xf, IRQ_TYPE_LEVEL_LOW);
> +    set_interrupt_ppi(intr, d->arch.evtchn_irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
>       res = fdt_property_interrupts(fdt, &intr, 1);
>       if ( res )
>           return res;
> @@ -910,15 +910,15 @@ static int __init make_timer_node(const struct domain *d, void *fdt,
>   
>       irq = timer_get_irq(TIMER_PHYS_SECURE_PPI);
>       dt_dprintk("  Secure interrupt %u\n", irq);
> -    set_interrupt_ppi(intrs[0], irq, 0xf, IRQ_TYPE_LEVEL_LOW);
> +    set_interrupt_ppi(intrs[0], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
>   
>       irq = timer_get_irq(TIMER_PHYS_NONSECURE_PPI);
>       dt_dprintk("  Non secure interrupt %u\n", irq);
> -    set_interrupt_ppi(intrs[1], irq, 0xf, IRQ_TYPE_LEVEL_LOW);
> +    set_interrupt_ppi(intrs[1], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
>   
>       irq = timer_get_irq(TIMER_VIRT_PPI);
>       dt_dprintk("  Virt interrupt %u\n", irq);
> -    set_interrupt_ppi(intrs[2], irq, 0xf, IRQ_TYPE_LEVEL_LOW);
> +    set_interrupt_ppi(intrs[2], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
>   
>       res = fdt_property_interrupts(fdt, intrs, 3);
>       if ( res )
> diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
> index 9d55e9b..e45d574 100644
> --- a/xen/include/asm-arm/irq.h
> +++ b/xen/include/asm-arm/irq.h
> @@ -2,6 +2,22 @@
>   #define _ASM_HW_IRQ_H
>   
>   #include <xen/device_tree.h>
> +#include <public/device_tree_defs.h>
> +
> +/*
> + * These defines correspond to the Xen internal representation of the
> + * IRQ types. We choose to make them the same as the existing device
> + * tree definitions for convenience.
> + */
> +#define IRQ_TYPE_NONE           DT_IRQ_TYPE_NONE
> +#define IRQ_TYPE_EDGE_RISING    DT_IRQ_TYPE_EDGE_RISING
> +#define IRQ_TYPE_EDGE_FALLING   DT_IRQ_TYPE_EDGE_FALLING
> +#define IRQ_TYPE_EDGE_BOTH      DT_IRQ_TYPE_EDGE_BOTH
> +#define IRQ_TYPE_LEVEL_HIGH     DT_IRQ_TYPE_LEVEL_HIGH
> +#define IRQ_TYPE_LEVEL_LOW      DT_IRQ_TYPE_LEVEL_LOW
> +#define IRQ_TYPE_LEVEL_MASK     DT_IRQ_TYPE_LEVEL_MASK
> +#define IRQ_TYPE_SENSE_MASK     DT_IRQ_TYPE_SENSE_MASK
> +#define IRQ_TYPE_INVALID        DT_IRQ_TYPE_INVALID
>   
>   #define NR_VECTORS 256 /* XXX */
>   
> diff --git a/xen/include/public/device_tree_defs.h b/xen/include/public/device_tree_defs.h
> new file mode 100644
> index 0000000..209d43d
> --- /dev/null
> +++ b/xen/include/public/device_tree_defs.h
> @@ -0,0 +1,42 @@
> +#ifndef __XEN_DEVICE_TREE_DEFS_H__
> +#define __XEN_DEVICE_TREE_DEFS_H__
> +
> +#if defined(__XEN__) || defined(__XEN_TOOLS__)
> +/*
> + * The device tree compiler (DTC) is allocating the phandle from 1 to
> + * onwards. Reserve a high value for the GIC phandle.
> + */
> +#define GUEST_PHANDLE_GIC (65000)
> +
> +#define GUEST_ROOT_ADDRESS_CELLS 2
> +#define GUEST_ROOT_SIZE_CELLS 2
> +
> +/**
> + * IRQ line type.
> + *
> + * DT_IRQ_TYPE_NONE            - default, unspecified type
> + * DT_IRQ_TYPE_EDGE_RISING     - rising edge triggered
> + * DT_IRQ_TYPE_EDGE_FALLING    - falling edge triggered
> + * DT_IRQ_TYPE_EDGE_BOTH       - rising and falling edge triggered
> + * DT_IRQ_TYPE_LEVEL_HIGH      - high level triggered
> + * DT_IRQ_TYPE_LEVEL_LOW       - low level triggered
> + * DT_IRQ_TYPE_LEVEL_MASK      - Mask to filter out the level bits
> + * DT_IRQ_TYPE_SENSE_MASK      - Mask for all the above bits
> + * DT_IRQ_TYPE_INVALID         - Use to initialize the type
> + */
> +#define DT_IRQ_TYPE_NONE           0x00000000
> +#define DT_IRQ_TYPE_EDGE_RISING    0x00000001
> +#define DT_IRQ_TYPE_EDGE_FALLING   0x00000002
> +#define DT_IRQ_TYPE_EDGE_BOTH                           \
> +    (DT_IRQ_TYPE_EDGE_FALLING | DT_IRQ_TYPE_EDGE_RISING)
> +#define DT_IRQ_TYPE_LEVEL_HIGH     0x00000004
> +#define DT_IRQ_TYPE_LEVEL_LOW      0x00000008
> +#define DT_IRQ_TYPE_LEVEL_MASK                          \
> +    (DT_IRQ_TYPE_LEVEL_LOW | DT_IRQ_TYPE_LEVEL_HIGH)
> +#define DT_IRQ_TYPE_SENSE_MASK     0x0000000f
> +
> +#define DT_IRQ_TYPE_INVALID        0x00000010
> +
> +#endif
> +
> +#endif
> diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
> index 0aecbe0..638b926 100644
> --- a/xen/include/xen/device_tree.h
> +++ b/xen/include/xen/device_tree.h
> @@ -13,6 +13,7 @@
>   #include <asm/byteorder.h>
>   #include <asm/device.h>
>   #include <public/xen.h>
> +#include <public/device_tree_defs.h>
>   #include <xen/kernel.h>
>   #include <xen/init.h>
>   #include <xen/string.h>
> @@ -114,35 +115,9 @@ struct dt_phandle_args {
>   };
>   
>   /**
> - * IRQ line type.
> - *
> - * IRQ_TYPE_NONE            - default, unspecified type
> - * IRQ_TYPE_EDGE_RISING     - rising edge triggered
> - * IRQ_TYPE_EDGE_FALLING    - falling edge triggered
> - * IRQ_TYPE_EDGE_BOTH       - rising and falling edge triggered
> - * IRQ_TYPE_LEVEL_HIGH      - high level triggered
> - * IRQ_TYPE_LEVEL_LOW       - low level triggered
> - * IRQ_TYPE_LEVEL_MASK      - Mask to filter out the level bits
> - * IRQ_TYPE_SENSE_MASK      - Mask for all the above bits
> - * IRQ_TYPE_INVALID         - Use to initialize the type
> - */
> -#define IRQ_TYPE_NONE           0x00000000
> -#define IRQ_TYPE_EDGE_RISING    0x00000001
> -#define IRQ_TYPE_EDGE_FALLING   0x00000002
> -#define IRQ_TYPE_EDGE_BOTH                           \
> -    (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
> -#define IRQ_TYPE_LEVEL_HIGH     0x00000004
> -#define IRQ_TYPE_LEVEL_LOW      0x00000008
> -#define IRQ_TYPE_LEVEL_MASK                          \
> -    (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)
> -#define IRQ_TYPE_SENSE_MASK     0x0000000f
> -
> -#define IRQ_TYPE_INVALID        0x00000010
> -
> -/**
>    * dt_irq - describe an IRQ in the device tree
>    * @irq: IRQ number
> - * @type: IRQ type (see IRQ_TYPE_*)
> + * @type: IRQ type (see DT_IRQ_TYPE_*)
>    *
>    * This structure is returned when an interrupt is mapped.
>    */
> @@ -151,12 +126,12 @@ struct dt_irq {
>       unsigned int type;
>   };
>   
> -/* If type == IRQ_TYPE_NONE, assume we use level triggered */
> +/* If type == DT_IRQ_TYPE_NONE, assume we use level triggered */
>   static inline bool_t dt_irq_is_level_triggered(const struct dt_irq *irq)
>   {
>       unsigned int type = irq->type;
>   
> -    return (type & IRQ_TYPE_LEVEL_MASK) || (type == IRQ_TYPE_NONE);
> +    return (type & DT_IRQ_TYPE_LEVEL_MASK) || (type == DT_IRQ_TYPE_NONE);
>   }
>   
>   /**
> 

-- 
Julien Grall

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

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

* Re: [PATCH v3 04/25] xen/arm: document dom0less
  2018-07-31 23:27 ` [PATCH v3 04/25] xen/arm: document dom0less Stefano Stabellini
@ 2018-08-01  9:46   ` Julien Grall
  2018-10-03 16:47     ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-01  9:46 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 01/08/18 00:27, Stefano Stabellini wrote:
> Add a new document to provide information on how to use dom0less related
> features and their current limitations.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> 
> ---
> Changes in v3:
> - add patch
> ---
>   docs/misc/arm/dom0less | 47 +++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 47 insertions(+)
>   create mode 100644 docs/misc/arm/dom0less
> 
> diff --git a/docs/misc/arm/dom0less b/docs/misc/arm/dom0less

This should be suffixed with .txt. You also want to add a line in 
docs/INDEX describing the file.

> new file mode 100644
> index 0000000..ae5a8b1
> --- /dev/null
> +++ b/docs/misc/arm/dom0less
> @@ -0,0 +1,47 @@
> +Dom0less
> +========
> +
> +"Dom0less" is a set of Xen features that enable the deployment of a Xen
> +system without Dom0.

I think this sentence is misleading. You still deploy Xen with Dom0.

Also, we have been trying to removing the wording Dom0 anywhere in the 
code. Instead, we are now using "Hardware Domain". I would rather avoid 
to use Dom0 in the documentation as it could be misleading, you will 
always have a domain with ID (it may not be what you call Dom0 here).

> Each feature can be used independently from the
> +others, unless otherwise stated.
> +
> +Booting Multiple Domains from Device Tree
> +=========================================
> +
> +This feature enables Xen to create a set of DomUs alongside Dom0 at boot
> +time. Information about the DomUs to be created by Xen is passed to the
> +hypervisor via Device Tree. Specifically, the existing Device Tree based
> +Multiboot specification has been extended to allow for multiple domains
> +to be passed to Xen. See docs/misc/arm/device-tree/booting.txt for more
> +information about the Multiboot specification and how to use it.
> +
> +Instead of waiting for Dom0 to be fully booted and the Xen tools to
> +become available, domains created by Xen this way are started in
> +parallel to Dom0. Hence, their boot time is typically much shorter.
> +
> +Domains started by Xen at boot time currently have the following
> +limitations:
> +
> +- they cannot be properly shutdown or rebooted using xl
> +If one of them crashes, the whole platform should be rebooted.
> +
> +- some xl operations might not work as expected
> +xl is meant to be used with domains that have been created by it. Using
> +xl with domains started by Xen at boot might not work as expected.
> +
> +- the GIC version is the native version
> +In absence of other information, the GIC version exposed to the domains
> +started by Xen at boot is the same as the native GIC version.
> +
> +- no PV drivers
> +There is no support for PV devices at the moment. All devices need to be
> +statically assigned to guests.
> +
> +- vCPU pinning
> +Pinning vCPUs of domains started by Xen at boot can be done from dom0,
> +using `xl vcpu-pin' as usual. It is not currently possible to configure
> +vCPU pinning for domains other than dom0 without dom0. However, the NULL
> +scheduler (currently unsupported) can be selected by passing

I would rather not mention NULL scheduler is unsupported here. That's 
another place to update the doc when it gets supported and maybe be missed.

> +`sched=null' to the Xen command line. The NULL scheduler automatically
> +assignes and pins vCPUs to pCPUs, but the vCPU-pCPU assignments cannot

s/assignes/assigns/

> +be configured.

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 05/25] xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node
  2018-07-31 23:27 ` [PATCH v3 05/25] xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node Stefano Stabellini
@ 2018-08-01  9:50   ` Julien Grall
  0 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2018-08-01  9:50 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 01/08/18 00:27, Stefano Stabellini wrote:
> In order to make make_memory_node and make_hypervisor_node more
> reusable, do not pass them dt_host. As they only use it to calculate
> addrcells and sizecells, pass addrcells and sizecells directly.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

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

Cheers,

> 
> ---
> Changes in v3:
> - split evtchn_allocate movement to separate patch
> 
> Changes in v2:
> - add blank line
> - move evtchn_allocate to handle_node
> ---
>   xen/arch/arm/domain_build.c   | 21 +++++++++++----------
>   xen/common/device_tree.c      |  6 +++---
>   xen/include/xen/device_tree.h |  2 +-
>   3 files changed, 15 insertions(+), 14 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index df9309d..0177492 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -533,11 +533,11 @@ static int __init fdt_property_interrupts(void *fdt, gic_interrupt_t *intr,
>   
>   static int __init make_memory_node(const struct domain *d,
>                                      void *fdt,
> -                                   const struct dt_device_node *parent,
> +                                   int addrcells, int sizecells,
>                                      const struct kernel_info *kinfo)
>   {
>       int res, i;
> -    int reg_size = dt_child_n_addr_cells(parent) + dt_child_n_size_cells(parent);
> +    int reg_size = addrcells + sizecells;
>       int nr_cells = reg_size*kinfo->mem.nr_banks;
>       __be32 reg[nr_cells];
>       __be32 *cells;
> @@ -563,7 +563,7 @@ static int __init make_memory_node(const struct domain *d,
>           dt_dprintk("  Bank %d: %#"PRIx64"->%#"PRIx64"\n",
>                      i, start, start + size);
>   
> -        dt_child_set_range(&cells, parent, start, size);
> +        dt_child_set_range(&cells, addrcells, sizecells, start, size);
>       }
>   
>       res = fdt_property(fdt, "reg", reg, sizeof(reg));
> @@ -579,7 +579,7 @@ static void evtchn_allocate(struct domain *d);
>   
>   static int __init make_hypervisor_node(struct domain *d,
>                                          const struct kernel_info *kinfo,
> -                                       const struct dt_device_node *parent)
> +                                       int addrcells, int sizecells)
>   {
>       const char compat[] =
>           "xen,xen-"__stringify(XEN_VERSION)"."__stringify(XEN_SUBVERSION)"\0"
> @@ -588,9 +588,6 @@ static int __init make_hypervisor_node(struct domain *d,
>       gic_interrupt_t intr;
>       __be32 *cells;
>       int res;
> -    /* Convenience alias */
> -    int addrcells = dt_child_n_addr_cells(parent);
> -    int sizecells = dt_child_n_size_cells(parent);
>       void *fdt = kinfo->fdt;
>   
>       dt_dprintk("Create hypervisor node\n");
> @@ -615,7 +612,8 @@ static int __init make_hypervisor_node(struct domain *d,
>   
>       /* reg 0 is grant table space */
>       cells = &reg[0];
> -    dt_child_set_range(&cells, parent, kinfo->gnttab_start, kinfo->gnttab_size);
> +    dt_child_set_range(&cells, addrcells, sizecells,
> +                       kinfo->gnttab_start, kinfo->gnttab_size);
>       res = fdt_property(fdt, "reg", reg,
>                          dt_cells_to_size(addrcells + sizecells));
>       if ( res )
> @@ -1292,11 +1290,14 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
>   
>       if ( node == dt_host )
>       {
> +        int addrcells = dt_child_n_addr_cells(node);
> +        int sizecells = dt_child_n_size_cells(node);
> +
>           /*
>            * The hypervisor node should always be created after all nodes
>            * from the host DT have been parsed.
>            */
> -        res = make_hypervisor_node(d, kinfo, node);
> +        res = make_hypervisor_node(d, kinfo, addrcells, sizecells);
>           if ( res )
>               return res;
>   
> @@ -1308,7 +1309,7 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
>           if ( res )
>               return res;
>   
> -        res = make_memory_node(d, kinfo->fdt, node, kinfo);
> +        res = make_memory_node(d, kinfo->fdt, addrcells, sizecells, kinfo);
>           if ( res )
>               return res;
>   
> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
> index 7b009ea..8fc401d 100644
> --- a/xen/common/device_tree.c
> +++ b/xen/common/device_tree.c
> @@ -112,11 +112,11 @@ void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
>       dt_set_cell(cellp, dt_n_size_cells(np), size);
>   }
>   
> -void dt_child_set_range(__be32 **cellp, const struct dt_device_node *parent,
> +void dt_child_set_range(__be32 **cellp, int addrcells, int sizecells,
>                           u64 address, u64 size)
>   {
> -    dt_set_cell(cellp, dt_child_n_addr_cells(parent), address);
> -    dt_set_cell(cellp, dt_child_n_size_cells(parent), size);
> +    dt_set_cell(cellp, addrcells, address);
> +    dt_set_cell(cellp, sizecells, size);
>   }
>   
>   static void __init *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
> diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
> index 638b926..91fa0b6 100644
> --- a/xen/include/xen/device_tree.h
> +++ b/xen/include/xen/device_tree.h
> @@ -674,7 +674,7 @@ void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
>    * Write a range into a series of cells and update cellp to point to the
>    * cell just after.
>    */
> -void dt_child_set_range(__be32 **cellp, const struct dt_device_node *parent,
> +void dt_child_set_range(__be32 **cellp, int addrcells, int sizecells,
>                           u64 address, u64 size);
>   
>   /**
> 

-- 
Julien Grall

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

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

* Re: [PATCH v3 06/25] xen/arm: move evtchn_allocate call out of make_hypervisor_node
  2018-07-31 23:27 ` [PATCH v3 06/25] xen/arm: move evtchn_allocate call out of make_hypervisor_node Stefano Stabellini
@ 2018-08-01  9:51   ` Julien Grall
  0 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2018-08-01  9:51 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 01/08/18 00:27, Stefano Stabellini wrote:
> In the case of domUs, evtchn_irq is allocated by arch_domain_create and
> set to GUEST_EVTCHN_PPI.
> 
> To make make_hypervisor_node more reusable, move the call to
> evtchn_allocate out of make_hypervisor_node, to the dom0 specific caller
> (handle_node).
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> 
> ---
> Changes in v3:
> - add patch
> - add BUG_ON
> ---
>   xen/arch/arm/domain_build.c | 13 ++++++++-----
>   1 file changed, 8 insertions(+), 5 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 0177492..b51d014 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -619,11 +619,7 @@ static int __init make_hypervisor_node(struct domain *d,
>       if ( res )
>           return res;
>   
> -    /*
> -     * It is safe to allocate the event channel here because all the
> -     * PPIs used by the hardware domain have been registered.
> -     */
> -    evtchn_allocate(d);
> +    BUG_ON(d->arch.evtchn_irq == 0);
>   
>       /*
>        * Interrupt event channel upcall:
> @@ -1293,6 +1289,13 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
>           int addrcells = dt_child_n_addr_cells(node);
>           int sizecells = dt_child_n_size_cells(node);
>   
> +
Spurious line.

With that fixed:

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

Cheers,

> +        /*
> +         * It is safe to allocate the event channel here because all the
> +         * PPIs used by the hardware domain have been registered.
> +         */
> +        evtchn_allocate(d);
> +
>           /*
>            * The hypervisor node should always be created after all nodes
>            * from the host DT have been parsed.
> 

-- 
Julien Grall

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

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

* Re: [PATCH v3 07/25] xen/arm: rename acpi_make_chosen_node to make_chosen_node
  2018-07-31 23:27 ` [PATCH v3 07/25] xen/arm: rename acpi_make_chosen_node to make_chosen_node Stefano Stabellini
@ 2018-08-01  9:53   ` Julien Grall
  0 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2018-08-01  9:53 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel



On 01/08/18 00:27, Stefano Stabellini wrote:
> acpi_make_chosen_node is actually generic and can be reused. Rename it
> to make_chosen_node and make it available to non-ACPI builds.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

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

> ---
> Removed Julien's ack due to small change below
> 
> Changes in v3:
> - retain CONFIG_ACPI not to break bisection for !ACPI build, it will be
>    removed by a later patch
> ---
>   xen/arch/arm/domain_build.c | 91 ++++++++++++++++++++++++---------------------
>   1 file changed, 49 insertions(+), 42 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index b51d014..cd47a68 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -932,6 +932,54 @@ static int __init make_timer_node(const struct domain *d, void *fdt,
>       return res;
>   }
>   
> +#ifdef CONFIG_ACPI
> +/*
> + * This function is used as part of the device tree generation for Dom0
> + * on ACPI systems, and DomUs started directly from Xen based on device
> + * tree information.
> + */
> +static int __init make_chosen_node(const struct kernel_info *kinfo)
> +{
> +    int res;
> +    const char *bootargs = NULL;
> +    const struct bootmodule *mod = kinfo->kernel_bootmodule;
> +    void *fdt = kinfo->fdt;
> +
> +    dt_dprintk("Create chosen node\n");
> +    res = fdt_begin_node(fdt, "chosen");
> +    if ( res )
> +        return res;
> +
> +    if ( mod && mod->cmdline[0] )
> +    {
> +        bootargs = &mod->cmdline[0];
> +        res = fdt_property(fdt, "bootargs", bootargs, strlen(bootargs) + 1);
> +        if ( res )
> +           return res;
> +    }
> +
> +    /*
> +     * If the bootloader provides an initrd, we must create a placeholder
> +     * for the initrd properties. The values will be replaced later.
> +     */
> +    if ( mod && mod->size )
> +    {
> +        u64 a = 0;
> +        res = fdt_property(kinfo->fdt, "linux,initrd-start", &a, sizeof(a));
> +        if ( res )
> +            return res;
> +
> +        res = fdt_property(kinfo->fdt, "linux,initrd-end", &a, sizeof(a));
> +        if ( res )
> +            return res;
> +    }
> +
> +    res = fdt_end_node(fdt);
> +
> +    return res;
> +}
> +#endif
> +
>   static int __init map_irq_to_domain(struct domain *d, unsigned int irq,
>                                       bool need_mapping, const char *devname)
>   {
> @@ -1424,47 +1472,6 @@ static int __init acpi_route_spis(struct domain *d)
>       return 0;
>   }
>   
> -static int __init acpi_make_chosen_node(const struct kernel_info *kinfo)
> -{
> -    int res;
> -    const char *bootargs = NULL;
> -    const struct bootmodule *mod = kinfo->kernel_bootmodule;
> -    void *fdt = kinfo->fdt;
> -
> -    dt_dprintk("Create chosen node\n");
> -    res = fdt_begin_node(fdt, "chosen");
> -    if ( res )
> -        return res;
> -
> -    if ( mod && mod->cmdline[0] )
> -    {
> -        bootargs = &mod->cmdline[0];
> -        res = fdt_property(fdt, "bootargs", bootargs, strlen(bootargs) + 1);
> -        if ( res )
> -           return res;
> -    }
> -
> -    /*
> -     * If the bootloader provides an initrd, we must create a placeholder
> -     * for the initrd properties. The values will be replaced later.
> -     */
> -    if ( mod && mod->size )
> -    {
> -        u64 a = 0;
> -        res = fdt_property(kinfo->fdt, "linux,initrd-start", &a, sizeof(a));
> -        if ( res )
> -            return res;
> -
> -        res = fdt_property(kinfo->fdt, "linux,initrd-end", &a, sizeof(a));
> -        if ( res )
> -            return res;
> -    }
> -
> -    res = fdt_end_node(fdt);
> -
> -    return res;
> -}
> -
>   static int __init acpi_make_hypervisor_node(const struct kernel_info *kinfo,
>                                               struct membank tbl_add[])
>   {
> @@ -1537,7 +1544,7 @@ static int __init create_acpi_dtb(struct kernel_info *kinfo,
>           return ret;
>   
>       /* Create a chosen node for DOM0 */
> -    ret = acpi_make_chosen_node(kinfo);
> +    ret = make_chosen_node(kinfo);
>       if ( ret )
>           goto err;
>   
> 

-- 
Julien Grall

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

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

* Re: [PATCH v3 09/25] xen/arm: introduce bootcmdlines
  2018-07-31 23:27 ` [PATCH v3 09/25] xen/arm: introduce bootcmdlines Stefano Stabellini
@ 2018-08-01 10:51   ` Julien Grall
  2018-10-03 23:11     ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-01 10:51 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 01/08/18 00:27, Stefano Stabellini wrote:
> Introduce a new array to store the cmdline of each boot module. It is
> separate from struct bootmodules. Remove the cmdline field from struct
> boot_module. This way, kernels and initrds with the same address in
> memory can share struct bootmodule (important because we want them to be
> free'd only once), but they can still have their separate bootcmdline
> entries.
> 
> Add a dt_name field to struct bootcmdline to make it easier to find the
> correct entry. Store the name of the "xen,domain" compatible node (for
> example "Dom1"). This is a better choice compared to the name of the
> "multiboot,kernel" compatible node, because their names are not unique.
> For instance there can be more than one "module@0x4c000000" in the
> system, but there can only be one "/chosen/Dom1".

As I mentioned in the previous version, the code is currently looking 
for multiboot,module everywhere in the DT rather than only in /chosen. 
So your name could not be uniq.

However, this is not compliant with the protocol. Therefore you need to 
fix the code first to ensure the name will be uniq.

> 
> Add a pointer to struct kernel_info to point to the cmdline for a given
> kernel.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> 
> ---
> 
> Changes in v3:
> - introduce bootcmdlines
> - do not modify boot_fdt_cmdline
> - add comments

I see no comments in the code. Did I miss anything?

> 
> Changes in v2:
> - new patch
> ---
>   xen/arch/arm/bootfdt.c      | 66 +++++++++++++++++++++++++++++++--------------
>   xen/arch/arm/domain_build.c |  8 +++---
>   xen/arch/arm/kernel.h       |  1 +
>   xen/arch/arm/setup.c        | 23 +++++++++++-----
>   xen/include/asm-arm/setup.h | 16 +++++++++--
>   5 files changed, 82 insertions(+), 32 deletions(-)
> 
> diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
> index 8eba42c..6f44022 100644
> --- a/xen/arch/arm/bootfdt.c
> +++ b/xen/arch/arm/bootfdt.c
> @@ -163,6 +163,38 @@ static void __init process_memory_node(const void *fdt, int node,
>       }
>   }
>   
> +static void __init add_boot_cmdline(const void *fdt, int node,
> +                                    const char *name, bootmodule_kind kind)
> +{
> +    struct bootcmdlines *mods = &bootinfo.cmdlines;
> +    struct bootcmdline *mod;

This feels sligthtly strange to use "mod" here. We are not dealing with 
boot modules but boot command line.

> +    const struct fdt_property *prop;
> +    int len;
> +    const char *cmdline;
> +
> +    if ( mods->nr_mods == MAX_MODULES )
> +    {
> +        printk("Ignoring %s boot module (too many)\n", name);

Same here. This needs to be updated.

> +        return;
> +    }
> +
> +    mod = &mods->cmdline[mods->nr_mods++];
> +    mod->kind = kind;
> +
> +    if ( strlen(name) > DT_MAX_NAME )
> +        panic("module %s name too long\n", name);

This would really never happen. It feels an ASSERT(strlen(name) > 
DT_MAX_NAME)) would be more suitable.

> +    safe_strcpy(mod->dt_name, name);
> +
> +    prop = fdt_get_property(fdt, node, "bootargs", &len);
> +    if ( prop )
> +    {
> +        if ( len > BOOTMOD_MAX_CMDLINE )
> +            panic("module %s command line too long\n", name);
> +        cmdline = prop->data;
> +        safe_strcpy(mod->cmdline, cmdline);
> +    }
> +}
> +
>   static void __init process_multiboot_node(const void *fdt, int node,
>                                             const char *name,
>                                             u32 address_cells, u32 size_cells)
> @@ -172,8 +204,12 @@ static void __init process_multiboot_node(const void *fdt, int node,
>       const __be32 *cell;
>       bootmodule_kind kind;
>       paddr_t start, size;
> -    const char *cmdline;
>       int len;
> +    int parent_node;
> +
> +    parent_node = fdt_parent_offset(fdt, node);
> +    if ( parent_node < 0 )
> +        panic("node %s missing a parent\n", name);

It feels an ASSERT(parent_node < 0) would be more suitable as this 
should never really happen.

>   
>       prop = fdt_get_property(fdt, node, "reg", &len);
>       if ( !prop )
> @@ -220,17 +256,8 @@ static void __init process_multiboot_node(const void *fdt, int node,
>               kind = BOOTMOD_XSM;
>       }
>   
> -    prop = fdt_get_property(fdt, node, "bootargs", &len);
> -    if ( prop )
> -    {
> -        if ( len > BOOTMOD_MAX_CMDLINE )
> -            panic("module %s command line too long\n", name);
> -        cmdline = prop->data;
> -    }
> -    else
> -        cmdline = NULL;
> -

I am not entirely sure to understand why this code has been moved. With 
your new code, if you have a module without commandline then you will 
still add a cmdline with nothing. This looks quite pointless.

Instead, you could keep this code here and only call add_bootcmdline 
when it is not NULL (or ignore it directly in the function).

> -    add_boot_module(kind, start, size, cmdline);
> +    add_boot_module(kind, start, size);
> +    add_boot_cmdline(fdt, node, fdt_get_name(fdt, parent_node, &len), kind);
>   }
>   
>   static void __init process_chosen_node(const void *fdt, int node,
> @@ -276,7 +303,7 @@ static void __init process_chosen_node(const void *fdt, int node,
>   
>       printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end);
>   
> -    add_boot_module(BOOTMOD_RAMDISK, start, end-start, NULL);
> +    add_boot_module(BOOTMOD_RAMDISK, start, end-start);
>   }
>   
>   static int __init early_scan_node(const void *fdt,
> @@ -307,12 +334,11 @@ static void __init early_print_info(void)
>                        mi->bank[i].start + mi->bank[i].size - 1);
>       printk("\n");
>       for ( i = 0 ; i < mods->nr_mods; i++ )
> -        printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s %s\n",
> +        printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s\n",
>                        i,
>                        mods->module[i].start,
>                        mods->module[i].start + mods->module[i].size,
> -                     boot_module_kind_as_string(mods->module[i].kind),
> -                     mods->module[i].cmdline);
> +                     boot_module_kind_as_string(mods->module[i].kind));

With that change the command line is not printed anymore and also not 
associated to a module. This was quite useful for debugging bootloader 
issue.

>       nr_rsvd = fdt_num_mem_rsv(device_tree_flattened);
>       for ( i = 0; i < nr_rsvd; i++ )
>       {

[...]

> +struct bootcmdline * __init boot_cmdline_find_by_kind(bootmodule_kind kind)
> +{
> +    struct bootcmdlines *mods = &bootinfo.cmdlines;
> +    struct bootcmdline *mod;

Again, the name "mod" is misleading here.

> +    int i;

Newline here.

> +    for (i = 0 ; i < mods->nr_mods ; i++ )

for ( ... )

> +    {
> +        mod = &mods->cmdline[i];
> +        if ( mod->kind == kind )
> +            return mod;
> +    }
> +    return NULL;
> +}
> +
>   const char * __init boot_module_kind_as_string(bootmodule_kind kind)
>   {
>       switch ( kind )
> @@ -723,7 +732,7 @@ void __init start_xen(unsigned long boot_phys_offset,
>       /* Register Xen's load address as a boot module. */
>       xen_bootmodule = add_boot_module(BOOTMOD_XEN,
>                                (paddr_t)(uintptr_t)(_start + boot_phys_offset),
> -                             (paddr_t)(uintptr_t)(_end - _start + 1), NULL);
> +                             (paddr_t)(uintptr_t)(_end - _start + 1));
>       BUG_ON(!xen_bootmodule);
>   
>       xen_paddr = get_xen_paddr();
> diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
> index f1e4a3f..cb7da51 100644
> --- a/xen/include/asm-arm/setup.h
> +++ b/xen/include/asm-arm/setup.h
> @@ -35,6 +35,12 @@ struct bootmodule {
>       bootmodule_kind kind;
>       paddr_t start;
>       paddr_t size;
> +};
> +
> +#define DT_MAX_NAME 32

It might be useful to explain where 32 comes from.

> +struct bootcmdline {
> +    bootmodule_kind kind;
> +    char dt_name[DT_MAX_NAME];
>       char cmdline[BOOTMOD_MAX_CMDLINE];
>   };
>   
> @@ -43,9 +49,15 @@ struct bootmodules {
>       struct bootmodule module[MAX_MODULES];
>   };
>   
> +struct bootcmdlines {
> +    int nr_mods;

unsigned int here please.

> +    struct bootcmdline cmdline[MAX_MODULES];
> +};
> +
>   struct bootinfo {
>       struct meminfo mem;
>       struct bootmodules modules;
> +    struct bootcmdlines cmdlines;
>   #ifdef CONFIG_ACPI
>       struct meminfo acpi;
>   #endif
> @@ -78,9 +90,9 @@ size_t __init boot_fdt_info(const void *fdt, paddr_t paddr);
>   const char __init *boot_fdt_cmdline(const void *fdt);
>   
>   struct bootmodule *add_boot_module(bootmodule_kind kind,
> -                                   paddr_t start, paddr_t size,
> -                                   const char *cmdline);
> +                                   paddr_t start, paddr_t size);
>   struct bootmodule *boot_module_find_by_kind(bootmodule_kind kind);
> +struct bootcmdline *boot_cmdline_find_by_kind(bootmodule_kind kind);
>   const char * __init boot_module_kind_as_string(bootmodule_kind kind);
>   
>   #endif
> 

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 10/25] xen/arm: don't add duplicate boot modules
  2018-07-31 23:27 ` [PATCH v3 10/25] xen/arm: don't add duplicate boot modules Stefano Stabellini
@ 2018-08-01 11:06   ` Julien Grall
  2018-10-04 21:05     ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-01 11:06 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 01/08/18 00:27, Stefano Stabellini wrote:
> Don't add duplicate boot modules (same kind and same start address).

Please explain why you don't want to duplicate it.

> 
> Mark kernels and ramdisks of "xen,domain" nodes as BOOTMOD_KERNEL_DOMAIN
> and BOOTMOD_RAMDISK_DOMAIN respectively, to avoid getting confused in
> kernel_probe, where we try to guess which is the dom0 kernel and initrd
> to be compatible with older versions of the multiboot spec.

In patch #9, you wrote we don't want duplication because of the free 
function. But it would be possible to have all the domains (including 
Dom0) to use the same kernel.

It would be better to find a different way to find Dom0 information. One 
way would be to add a flag in the boot module.

> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> 
> ---
> Changes in v2:
> - new patch
> ---
>   xen/arch/arm/bootfdt.c      | 7 +++++++
>   xen/arch/arm/setup.c        | 9 +++++++++
>   xen/include/asm-arm/setup.h | 2 ++
>   3 files changed, 18 insertions(+)
> 
> diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
> index 6f44022..dbaa8f4 100644
> --- a/xen/arch/arm/bootfdt.c
> +++ b/xen/arch/arm/bootfdt.c
> @@ -256,6 +256,13 @@ static void __init process_multiboot_node(const void *fdt, int node,
>               kind = BOOTMOD_XSM;
>       }
>   
> +    if ( fdt_node_check_compatible(fdt, parent_node, "xen,domain") == 0 )
> +    {
> +        if ( kind == BOOTMOD_KERNEL )
> +            kind = BOOTMOD_KERNEL_DOMAIN;
> +        if ( kind == BOOTMOD_RAMDISK )
> +            kind = BOOTMOD_RAMDISK_DOMAIN;
> +    }
>       add_boot_module(kind, start, size);
>       add_boot_cmdline(fdt, node, fdt_get_name(fdt, parent_node, &len), kind);
>   }
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index 67ab1fd..b1a117f 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -204,6 +204,7 @@ struct bootmodule __init *add_boot_module(bootmodule_kind kind,
>   {
>       struct bootmodules *mods = &bootinfo.modules;
>       struct bootmodule *mod;
> +    int i;

unsigned please.

>   
>       if ( mods->nr_mods == MAX_MODULES )
>       {
> @@ -211,6 +212,12 @@ struct bootmodule __init *add_boot_module(bootmodule_kind kind,
>                  boot_module_kind_as_string(kind), start, start + size);
>           return NULL;
>       }
> +    for ( i = 0 ; i < mods->nr_mods ; i++ )
> +    {
> +        mod = &mods->module[i];
> +        if ( mod->kind == kind && mod->start == start )
> +            return mod;
> +    }
>   
>       mod = &mods->module[mods->nr_mods++];
>       mod->kind = kind;
> @@ -257,6 +264,8 @@ const char * __init boot_module_kind_as_string(bootmodule_kind kind)
>       case BOOTMOD_KERNEL:  return "Kernel";
>       case BOOTMOD_RAMDISK: return "Ramdisk";
>       case BOOTMOD_XSM:     return "XSM";
> +    case BOOTMOD_KERNEL_DOMAIN:  return "DomU Kernel";
> +    case BOOTMOD_RAMDISK_DOMAIN: return "DomU Ramdisk";
>       case BOOTMOD_UNKNOWN: return "Unknown";
>       default: BUG();
>       }
> diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
> index cb7da51..353c32a 100644
> --- a/xen/include/asm-arm/setup.h
> +++ b/xen/include/asm-arm/setup.h
> @@ -16,6 +16,8 @@ typedef enum {
>       BOOTMOD_KERNEL,
>       BOOTMOD_RAMDISK,
>       BOOTMOD_XSM,
> +    BOOTMOD_KERNEL_DOMAIN,
> +    BOOTMOD_RAMDISK_DOMAIN,
>       BOOTMOD_UNKNOWN
>   }  bootmodule_kind;
>   
> 

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 17/25] xen/arm: introduce allocate_memory
  2018-07-31 23:28 ` [PATCH v3 17/25] xen/arm: introduce allocate_memory Stefano Stabellini
@ 2018-08-01 11:28   ` Julien Grall
  2018-10-03 17:46     ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-01 11:28 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi,

On 01/08/18 00:28, Stefano Stabellini wrote:
> Introduce an allocate_memory function able to allocate memory for DomUs
> and map it at the right guest addresses, according to the guest memory
> map: GUEST_RAM0_BASE and GUEST_RAM1_BASE.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> ---
> Changes in v3:
> - new patch
> ---
>   xen/arch/arm/domain_build.c | 125 +++++++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 124 insertions(+), 1 deletion(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index ab72c36..dfa74e4 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -369,6 +369,129 @@ static void __init allocate_memory_11(struct domain *d,
>       }
>   }
>   
> +static bool __init insert_bank(struct domain *d,
> +                               struct kernel_info *kinfo,
> +                               struct page_info *pg,
> +                               unsigned int order)
> +{
> +    int res, i;
> +    mfn_t smfn;
> +    paddr_t gaddr, size;
> +    struct membank *bank;
> +
> +    smfn = page_to_mfn(pg);

This could combine with the declaration above.

> +    size = pfn_to_paddr(1UL << order);

Ditto.

> +
> +    /*
> +     * DomU memory is provided in two banks:
> +     *   GUEST_RAM0_BASE - GUEST_RAM0_BASE + GUEST_RAM0_SIZE
> +     *   GUEST_RAM1_BASE - GUEST_RAM1_BASE + GUEST_RAM1_SIZE
> +     *
> +     * Find the right gaddr address for DomUs accordingly.
> +     */
> +    gaddr = GUEST_RAM0_BASE;
> +    if ( kinfo->mem.nr_banks > 0 )
> +    {
> +        for( i = 0; i < kinfo->mem.nr_banks; i++ )
> +        {
> +            bank = &kinfo->mem.bank[i];
> +            gaddr = bank->start + bank->size;
> +        }
> +        if ( bank->start == GUEST_RAM0_BASE &&
> +             gaddr + size > (GUEST_RAM0_BASE + GUEST_RAM0_SIZE) )
> +            gaddr = GUEST_RAM1_BASE;
> +        if ( bank->start == GUEST_RAM1_BASE &&
> +             gaddr + size > (GUEST_RAM1_BASE + GUEST_RAM1_SIZE) )
> +            goto fail;
> +    }

I still really dislike this code. This is difficult to understand and 
not scalable. As I said in the previous version, it would be possible to 
have more than 2 banks in the future. This will either come with PCI PT 
or dynamic memory layout.

What should really be done is a function allocate_memory that take in 
parameter the range to allocate. E.g

allocate_bank_memory(struct domain *d, gfn_t sgfn, unsigned long order);

Then the function allocate_memory will compute the size of each bank 
based on mem_ and call allocate_bank_memory for each bank.

> +
> +    dprintk(XENLOG_INFO,
> +            "Allocated %#"PRIpaddr"-%#"PRIpaddr":%#"PRIpaddr"-%#"PRIpaddr" (%ldMB/%ldMB, order %d)\n",

It would be possible to request a guest with 16KB of memory. This would 
be printed as 0.

> +            mfn_to_maddr(smfn), mfn_to_maddr(smfn) + size,
> +            gaddr, gaddr + size,
> +            1UL << (order + PAGE_SHIFT - 20),
> +            /* Don't want format this as PRIpaddr (16 digit hex) */
> +            (unsigned long)(kinfo->unassigned_mem >> 20),
> +            order);
> +
> +    res = guest_physmap_add_page(d, gaddr_to_gfn(gaddr), smfn, order);
> +    if ( res )
> +    {
> +        dprintk(XENLOG_ERR, "Failed map pages to DOMU: %d", res);
> +        goto fail;
> +    }
> +
> +    kinfo->unassigned_mem -= size;
> +    bank = &kinfo->mem.bank[kinfo->mem.nr_banks];
> +
> +    bank->start = gaddr;
> +    bank->size = size;
> +    kinfo->mem.nr_banks++;
> +    return true;
> +
> +fail:
> +    free_domheap_pages(pg, order);
> +    return false;
> +}
> +
> +static void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
> +{
> +    const unsigned int min_order = get_order_from_bytes(MB(4));

Why do you have this limitation for non-direct mapped domain? There are 
nothing wrong to allocate 2MB/4K pages for them.

> +    struct page_info *pg;
> +    unsigned int order = get_allocation_size(kinfo->unassigned_mem);
> +    int i;
> +
> +    dprintk(XENLOG_INFO, "Allocating mappings totalling %ldMB for dom%d:\n",

Ditto.

> +            /* Don't want format this as PRIpaddr (16 digit hex) */
> +            (unsigned long)(kinfo->unassigned_mem >> 20), d->domain_id);
> +
> +    kinfo->mem.nr_banks = 0;
> +
> +    order = get_allocation_size(kinfo->unassigned_mem);
> +    if ( order > GUEST_RAM0_SIZE )
> +        order = GUEST_RAM0_SIZE;

I don't understand this check. You are comparing a power of 2 with KB.

> +    while ( kinfo->unassigned_mem )
> +    {
> +        pg = alloc_domheap_pages(d, order, 0);
> +        if ( !pg )
> +        {
> +            order --;
> +
> +            if ( order >= min_order )
> +                continue;
> +
> +            /* No more we can do */
> +            break;
> +        }
> +
> +        if ( !insert_bank(d, kinfo, pg, order) )
> +            break;
> +
> +        /*
> +         * Success, next time around try again to get the largest order
> +         * allocation possible.
> +         */
> +        order = get_allocation_size(kinfo->unassigned_mem);
> +    }
> +
> +    if ( kinfo->unassigned_mem )
> +        dprintk(XENLOG_WARNING, "Failed to allocate requested domain memory."
> +               /* Don't want format this as PRIpaddr (16 digit hex) */
> +               " %ldMB unallocated\n",
> +               (unsigned long)kinfo->unassigned_mem >> 20);

I understand this is the current behavior for direct mapped domain. It 
makes sense for them because we don't want to create very small bank (we 
request 4MB min). But for non direct mapped domain, there are no need 
for such limitation. So if you don't allocate the memory, then it means 
Xen has no more RAM and it makes little sense to boot them.

> +
> +    for( i = 0; i < kinfo->mem.nr_banks; i++ )
> +    {
> +        dprintk(XENLOG_INFO, "Dom%d BANK[%d] %#"PRIpaddr"-%#"PRIpaddr" (%ldMB)\n",
> +                d->domain_id,
> +                i,
> +                kinfo->mem.bank[i].start,
> +                kinfo->mem.bank[i].start + kinfo->mem.bank[i].size,
> +                /* Don't want format this as PRIpaddr (16 digit hex) */
> +                (unsigned long)(kinfo->mem.bank[i].size >> 20));
> +    }
> +}
> +
>   static int __init write_properties(struct domain *d, struct kernel_info *kinfo,
>                                      const struct dt_device_node *node)
>   {
> @@ -2241,7 +2364,7 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
>       /* type must be set before allocate memory */
>       d->arch.type = kinfo.type;
>   #endif
> -    allocate_memory_11(d, &kinfo);
> +    allocate_memory(d, &kinfo);

The call to allocate_memory_11() should have never been added. Please 
refactor/re-order the patch to avoid introducing wrong code.

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 12/25] xen/arm: refactor construct_dom0
  2018-07-31 23:27 ` [PATCH v3 12/25] xen/arm: refactor construct_dom0 Stefano Stabellini
@ 2018-08-13 10:15   ` Julien Grall
  2018-08-15 19:27     ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-13 10:15 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 01/08/18 00:27, Stefano Stabellini wrote:
> Move generic initializations out of construct_dom0 so that they can be
> reused.
> 
> Rename prepare_dtb to prepare_dtb_hwdom to avoid confusion.
> 
> No functional changes in this patch.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> 
> ---
> Changes in v3:
> - move setting type before allocate_memory
> - add ifdef around it and a comment
> Changes in v2:
> - move discard_initial_modules() after __construct_domain()
> - remove useless blank line
> - leave safety BUG_ONs in __construct_domain
> - rename prepare_dtb to prepare_dtb_hwdom
> ---
>   xen/arch/arm/domain_build.c | 128 ++++++++++++++++++++++++--------------------
>   1 file changed, 70 insertions(+), 58 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 8d82849..0835340 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -1371,7 +1371,7 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
>       return res;
>   }
>   
> -static int __init prepare_dtb(struct domain *d, struct kernel_info *kinfo)
> +static int __init prepare_dtb_hwdom(struct domain *d, struct kernel_info *kinfo)
>   {
>       const p2m_type_t default_p2mt = p2m_mmio_direct_c;
>       const void *fdt;
> @@ -2106,75 +2106,31 @@ static void __init find_gnttab_region(struct domain *d,
>              kinfo->gnttab_start, kinfo->gnttab_start + kinfo->gnttab_size);
>   }
>   
> -int __init construct_dom0(struct domain *d)
> +static int __init __construct_domain(struct domain *d, struct kernel_info *kinfo)
>   {
> -    const struct bootcmdline *kernel = boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
> -    struct kernel_info kinfo = {};
>       struct vcpu *saved_current;
> -    int rc, i, cpu;
> -
> +    int i, cpu;
> +    struct cpu_user_regs *regs;
>       struct vcpu *v = d->vcpu[0];
> -    struct cpu_user_regs *regs = &v->arch.cpu_info->guest_cpu_user_regs;

There is no need to rewrite that line in

struct cpu_user_regs *regs;

regs = ...;

>   
> -    /* Sanity! */
> -    BUG_ON(d->domain_id != 0);
>       BUG_ON(d->vcpu[0] == NULL);
>       BUG_ON(v->is_initialised);
>   
> -    printk("*** LOADING DOMAIN 0 ***\n");
> -    if ( dom0_mem <= 0 )
> -    {
> -        warning_add("PLEASE SPECIFY dom0_mem PARAMETER - USING 512M FOR NOW\n");
> -        dom0_mem = MB(512);
> -    }
> -
> -
> -    iommu_hwdom_init(d);
> -
> -    d->max_pages = ~0U;
> -
> -    kinfo.unassigned_mem = dom0_mem;
> -    kinfo.d = d;
> -
> -    rc = kernel_probe(&kinfo, NULL);
> -    if ( rc < 0 )
> -        return rc;
> +    regs = &v->arch.cpu_info->guest_cpu_user_regs;
>   
>   #ifdef CONFIG_ARM_64
>       /* if aarch32 mode is not supported at EL1 do not allow 32-bit domain */
> -    if ( !(cpu_has_el1_32) && kinfo.type == DOMAIN_32BIT )
> +    if ( !(cpu_has_el1_32) && kinfo->type == DOMAIN_32BIT )
>       {
>           printk("Platform does not support 32-bit domain\n");
>           return -EINVAL;
>       }
> -    d->arch.type = kinfo.type;
>   
>       if ( is_64bit_domain(d) )
>           vcpu_switch_to_aarch64_mode(v);
>   
>   #endif
>   
> -    kinfo.cmdline = kernel != NULL ? &kernel->cmdline[0] : NULL;
> -    allocate_memory(d, &kinfo);
> -    find_gnttab_region(d, &kinfo);
> -
> -    /* Map extra GIC MMIO, irqs and other hw stuffs to dom0. */
> -    rc = gic_map_hwdom_extra_mappings(d);
> -    if ( rc < 0 )
> -        return rc;
> -
> -    rc = platform_specific_mapping(d);
> -    if ( rc < 0 )
> -        return rc;
> -
> -    if ( acpi_disabled )
> -        rc = prepare_dtb(d, &kinfo);
> -    else
> -        rc = prepare_acpi(d, &kinfo);
> -
> -    if ( rc < 0 )
> -        return rc;
> -
>       /*
>        * The following loads use the domain's p2m and require current to
>        * be a vcpu of the domain, temporarily switch
> @@ -2187,20 +2143,18 @@ int __init construct_dom0(struct domain *d)
>        * kernel_load will determine the placement of the kernel as well
>        * as the initrd & fdt in RAM, so call it first.
>        */
> -    kernel_load(&kinfo);
> +    kernel_load(kinfo);
>       /* initrd_load will fix up the fdt, so call it before dtb_load */
> -    initrd_load(&kinfo);
> -    dtb_load(&kinfo);
> +    initrd_load(kinfo);
> +    dtb_load(kinfo);
>   
>       /* Now that we are done restore the original p2m and current. */
>       set_current(saved_current);
>       p2m_restore_state(saved_current);
>   
> -    discard_initial_modules();
> -
>       memset(regs, 0, sizeof(*regs));
>   
> -    regs->pc = (register_t)kinfo.entry;
> +    regs->pc = (register_t)kinfo->entry;
>   
>       if ( is_32bit_domain(d) )
>       {
> @@ -2218,14 +2172,14 @@ int __init construct_dom0(struct domain *d)
>            */
>           regs->r0 = 0; /* SBZ */
>           regs->r1 = 0xffffffff; /* We use DTB therefore no machine id */
> -        regs->r2 = kinfo.dtb_paddr;
> +        regs->r2 = kinfo->dtb_paddr;
>       }
>   #ifdef CONFIG_ARM_64
>       else
>       {
>           regs->cpsr = PSR_GUEST64_INIT;
>           /* From linux/Documentation/arm64/booting.txt */
> -        regs->x0 = kinfo.dtb_paddr;
> +        regs->x0 = kinfo->dtb_paddr;
>           regs->x1 = 0; /* Reserved for future use */
>           regs->x2 = 0; /* Reserved for future use */
>           regs->x3 = 0; /* Reserved for future use */
> @@ -2251,6 +2205,64 @@ int __init construct_dom0(struct domain *d)
>       return 0;
>   }
>   
> +int __init construct_dom0(struct domain *d)
> +{
> +    const struct bootcmdline *kernel = boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
> +    struct kernel_info kinfo = {};
> +    int rc;
> +
> +    /* Sanity! */
> +    BUG_ON(d->domain_id != 0);
> +
> +    printk("*** LOADING DOMAIN 0 ***\n");
> +    if ( dom0_mem <= 0 )
> +    {
> +        warning_add("PLEASE SPECIFY dom0_mem PARAMETER - USING 512M FOR NOW\n");
> +        dom0_mem = MB(512);
> +    }
> +
> +    iommu_hwdom_init(d);
> +
> +    d->max_pages = ~0U;
> +
> +    kinfo.unassigned_mem = dom0_mem;
> +    kinfo.d = d;
> +
> +    rc = kernel_probe(&kinfo, NULL);
> +    if ( rc < 0 )
> +        return rc;
> +
> +    kinfo.cmdline = kernel != NULL ? &kernel->cmdline[0] : NULL;
> +#ifdef CONFIG_ARM_64
> +    /* type must be set before allocate_memory */
> +    d->arch.type = kinfo.type;
> +#endif
> +    allocate_memory(d, &kinfo);
> +    find_gnttab_region(d, &kinfo);
> +
> +    /* Map extra GIC MMIO, irqs and other hw stuffs to dom0. */
> +    rc = gic_map_hwdom_extra_mappings(d);
> +    if ( rc < 0 )
> +        return rc;
> +
> +    rc = platform_specific_mapping(d);
> +    if ( rc < 0 )
> +        return rc;
> +
> +    if ( acpi_disabled )
> +        rc = prepare_dtb_hwdom(d, &kinfo);
> +    else
> +        rc = prepare_acpi(d, &kinfo);
> +
> +    if ( rc < 0 )
> +        return rc;
> +
> +

Spurious newline.

> +    rc = __construct_domain(d, &kinfo);
> +    discard_initial_modules();

Newline here please.

> +    return rc;
> +}
> +
>   /*
>    * Local variables:
>    * mode: C
> 

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 13/25] xen/arm: introduce create_domUs
  2018-07-31 23:27 ` [PATCH v3 13/25] xen/arm: introduce create_domUs Stefano Stabellini
  2018-08-01  8:48   ` Jan Beulich
@ 2018-08-13 10:23   ` Julien Grall
  2018-08-15 19:37     ` Stefano Stabellini
  2018-08-13 10:55   ` Julien Grall
  2 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-13 10:23 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, andrew.cooper3, andrii_anisov, jbeulich, xen-devel

Hi Stefano,

On 01/08/18 00:27, Stefano Stabellini wrote:
> Call a new function, "create_domUs", from setup_xen to start DomU VMs.
> 
> Introduce support for the "xen,domU" compatible node on device tree.
> Create new DomU VMs based on the information found on device tree under
> "xen,domU". Calls construct_domU for each domain.
> 
> Introduce a simple global variable named max_init_domid to keep track of
> the initial allocated domids. It holds the max domid among the initial
> domains.
> 
> Move the discard_initial_modules after DomUs have been built.
> 
> First create domUs, then start dom0 -- no point in trying to start dom0
> when the cpu is busy.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> CC: andrew.cooper3@citrix.com
> CC: jbeulich@suse.com
> ---
> Changes in v3:
> - move patch earlier and introduce empty construct_domU to fix bisection
>    builds
> - fix max_init_domid to actually hold the max domid among initial
>    domains (instead of max_domid + 1)
> - move domain_unpause_by_systemcontroller(dom0) after creating domUs
> 
> Changes in v2:
> - coding style
> - set nr_spis to 32
> - introduce create_domUs
> ---
>   xen/arch/arm/domain_build.c | 42 +++++++++++++++++++++++++++++++++++++++---
>   xen/arch/arm/setup.c        |  7 ++++++-
>   xen/include/asm-arm/setup.h |  3 +++
>   xen/include/asm-x86/setup.h |  2 ++
>   4 files changed, 50 insertions(+), 4 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 0835340..8f7ac54 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -7,6 +7,7 @@
>   #include <asm/irq.h>
>   #include <asm/regs.h>
>   #include <xen/errno.h>
> +#include <xen/err.h>
>   #include <xen/device_tree.h>
>   #include <xen/libfdt/libfdt.h>
>   #include <xen/guest_access.h>
> @@ -2205,6 +2206,43 @@ static int __init __construct_domain(struct domain *d, struct kernel_info *kinfo
>       return 0;
>   }
>   
> +static int __init construct_domU(struct domain *d, struct dt_device_node *node)

AFAICT, the node is not going to be modified. So it should be const here.

> +{
> +    return 0;

As Jan said, this should return an error until it is been implemented.

> +}
> +
> +void __init create_domUs(void)
> +{
> +    struct dt_device_node *node;
> +    struct dt_device_node *chosen = dt_find_node_by_name(dt_host, "chosen");

Same here, you want them to be const.

> +
> +    if ( chosen != NULL )

I would prefer if we don't introduce another indentation level by 
inverting the condition.

Also, it is very unlikely to not have the chosen node. So it might be 
better to turn this into a panic/BUG_ON.

> +    {
> +        dt_for_each_child_node(chosen, node)
> +        {
> +            struct domain *d;
> +            struct xen_domctl_createdomain d_cfg = {
> +                .arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE,
> +                .arch.nr_spis = 32,
> +            };
> +
> +            if ( !dt_device_is_compatible(node, "xen,domain") )
> +                continue;
> +
> +            d = domain_create(++max_init_domid, &d_cfg, false);
> +            if ( IS_ERR(d) )
> +                panic("Error creating domain %s", dt_node_name(node));
> +
> +            d->is_console = 1;
> +
> +            if ( construct_domU(d, node) != 0 )
> +                panic("Could not set up domain %s", dt_node_name(node));
> +
> +            domain_unpause_by_systemcontroller(d);
> +        }
> +    }
> +}
> +
>   int __init construct_dom0(struct domain *d)
>   {
>       const struct bootcmdline *kernel = boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
> @@ -2258,9 +2296,7 @@ int __init construct_dom0(struct domain *d)
>           return rc;
>   
>   
> -    rc = __construct_domain(d, &kinfo);
> -    discard_initial_modules();
> -    return rc;
> +    return __construct_domain(d, &kinfo);
>   }
>   
>   /*
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index c320df9..096484f 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -63,8 +63,11 @@ static unsigned long opt_xenheap_megabytes __initdata;
>   integer_param("xenheap_megabytes", opt_xenheap_megabytes);
>   #endif
>   
> +domid_t __read_mostly max_init_domid = 0;
> +
>   static __used void init_done(void)
>   {
> +    discard_initial_modules();
>       free_init_memory();
>       startup_cpu_idle_loop();
>   }
> @@ -894,7 +897,7 @@ void __init start_xen(unsigned long boot_phys_offset,
>       dom0_cfg.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
>       dom0_cfg.arch.nr_spis = gic_number_lines() - 32;
>   
> -    dom0 = domain_create(0, &dom0_cfg, true);
> +    dom0 = domain_create(max_init_domid, &dom0_cfg, true);
>       if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
>               panic("Error creating domain 0");
>   
> @@ -915,6 +918,8 @@ void __init start_xen(unsigned long boot_phys_offset,
>       /* Must be done past setting system_state. */
>       unregister_init_virtual_region();
>   
> +    create_domUs();
> +
>       domain_unpause_by_systemcontroller(dom0);
>   
>       /* Switch on to the dynamically allocated stack for the idle vcpu
> diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
> index 4551f72..d9cd8e1 100644
> --- a/xen/include/asm-arm/setup.h
> +++ b/xen/include/asm-arm/setup.h
> @@ -67,6 +67,8 @@ struct bootinfo {
>   
>   extern struct bootinfo bootinfo;
>   
> +extern domid_t max_init_domid;
> +
>   void arch_init_memory(void);
>   
>   void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len);
> @@ -83,6 +85,7 @@ void acpi_create_efi_mmap_table(struct domain *d,
>   int acpi_make_efi_nodes(void *fdt, struct membank tbl_add[]);
>   
>   int construct_dom0(struct domain *d);
> +void __init create_domUs(void);
>   
>   void discard_initial_modules(void);
>   void dt_unreserved_regions(paddr_t s, paddr_t e,
> diff --git a/xen/include/asm-x86/setup.h b/xen/include/asm-x86/setup.h
> index 8d4b9ee..c0bd86f 100644
> --- a/xen/include/asm-x86/setup.h
> +++ b/xen/include/asm-x86/setup.h
> @@ -66,4 +66,6 @@ extern bool opt_dom0_shadow;
>   #endif
>   extern bool dom0_pvh;
>   
> +#define max_init_domid (0)
> +
>   #endif
> 

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 13/25] xen/arm: introduce create_domUs
  2018-07-31 23:27 ` [PATCH v3 13/25] xen/arm: introduce create_domUs Stefano Stabellini
  2018-08-01  8:48   ` Jan Beulich
  2018-08-13 10:23   ` Julien Grall
@ 2018-08-13 10:55   ` Julien Grall
  2018-08-15 20:04     ` Stefano Stabellini
  2 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-13 10:55 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, andrew.cooper3, andrii_anisov, jbeulich, xen-devel



On 01/08/18 00:27, Stefano Stabellini wrote:
> Call a new function, "create_domUs", from setup_xen to start DomU VMs.
> 
> Introduce support for the "xen,domU" compatible node on device tree.
> Create new DomU VMs based on the information found on device tree under
> "xen,domU". Calls construct_domU for each domain.
> 
> Introduce a simple global variable named max_init_domid to keep track of
> the initial allocated domids. It holds the max domid among the initial
> domains.
> 
> Move the discard_initial_modules after DomUs have been built.
> 
> First create domUs, then start dom0 -- no point in trying to start dom0
> when the cpu is busy.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> CC: andrew.cooper3@citrix.com
> CC: jbeulich@suse.com
> ---
> Changes in v3:
> - move patch earlier and introduce empty construct_domU to fix bisection
>    builds
> - fix max_init_domid to actually hold the max domid among initial
>    domains (instead of max_domid + 1)
> - move domain_unpause_by_systemcontroller(dom0) after creating domUs
> 
> Changes in v2:
> - coding style
> - set nr_spis to 32
> - introduce create_domUs
> ---
>   xen/arch/arm/domain_build.c | 42 +++++++++++++++++++++++++++++++++++++++---
>   xen/arch/arm/setup.c        |  7 ++++++-
>   xen/include/asm-arm/setup.h |  3 +++
>   xen/include/asm-x86/setup.h |  2 ++
>   4 files changed, 50 insertions(+), 4 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 0835340..8f7ac54 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -7,6 +7,7 @@
>   #include <asm/irq.h>
>   #include <asm/regs.h>
>   #include <xen/errno.h>
> +#include <xen/err.h>
>   #include <xen/device_tree.h>
>   #include <xen/libfdt/libfdt.h>
>   #include <xen/guest_access.h>
> @@ -2205,6 +2206,43 @@ static int __init __construct_domain(struct domain *d, struct kernel_info *kinfo
>       return 0;
>   }
>   
> +static int __init construct_domU(struct domain *d, struct dt_device_node *node)
> +{
> +    return 0;
> +}
> +
> +void __init create_domUs(void)
> +{
> +    struct dt_device_node *node;
> +    struct dt_device_node *chosen = dt_find_node_by_name(dt_host, "chosen");
> +
> +    if ( chosen != NULL )
> +    {
> +        dt_for_each_child_node(chosen, node)
> +        {
> +            struct domain *d;
> +            struct xen_domctl_createdomain d_cfg = {
> +                .arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE,
> +                .arch.nr_spis = 32,

AFAICT, when creating DomU from the toolstack nr_spis will be 0. So why 
32 here?

> +            };
> +
> +            if ( !dt_device_is_compatible(node, "xen,domain") )
> +                continue;
> +
> +            d = domain_create(++max_init_domid, &d_cfg, false);
> +            if ( IS_ERR(d) )
> +                panic("Error creating domain %s", dt_node_name(node));
> +
> +            d->is_console = 1;
> +
> +            if ( construct_domU(d, node) != 0 )
> +                panic("Could not set up domain %s", dt_node_name(node));
> +
> +            domain_unpause_by_systemcontroller(d);
> +        }
> +    }
> +}
> +
>   int __init construct_dom0(struct domain *d)
>   {
>       const struct bootcmdline *kernel = boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
> @@ -2258,9 +2296,7 @@ int __init construct_dom0(struct domain *d)
>           return rc;
>   
>   
> -    rc = __construct_domain(d, &kinfo);
> -    discard_initial_modules();
> -    return rc;
> +    return __construct_domain(d, &kinfo);
>   }
>   
>   /*
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index c320df9..096484f 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -63,8 +63,11 @@ static unsigned long opt_xenheap_megabytes __initdata;
>   integer_param("xenheap_megabytes", opt_xenheap_megabytes);
>   #endif
>   
> +domid_t __read_mostly max_init_domid = 0;
> +
>   static __used void init_done(void)
>   {
> +    discard_initial_modules();
>       free_init_memory();
>       startup_cpu_idle_loop();
>   }
> @@ -894,7 +897,7 @@ void __init start_xen(unsigned long boot_phys_offset,
>       dom0_cfg.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
>       dom0_cfg.arch.nr_spis = gic_number_lines() - 32;
>   
> -    dom0 = domain_create(0, &dom0_cfg, true);
> +    dom0 = domain_create(max_init_domid, &dom0_cfg, true);
>       if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
>               panic("Error creating domain 0");
>   
> @@ -915,6 +918,8 @@ void __init start_xen(unsigned long boot_phys_offset,
>       /* Must be done past setting system_state. */
>       unregister_init_virtual_region();
>   
> +    create_domUs();
> +
>       domain_unpause_by_systemcontroller(dom0);
>   
>       /* Switch on to the dynamically allocated stack for the idle vcpu
> diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
> index 4551f72..d9cd8e1 100644
> --- a/xen/include/asm-arm/setup.h
> +++ b/xen/include/asm-arm/setup.h
> @@ -67,6 +67,8 @@ struct bootinfo {
>   
>   extern struct bootinfo bootinfo;
>   
> +extern domid_t max_init_domid;
> +
>   void arch_init_memory(void);
>   
>   void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len);
> @@ -83,6 +85,7 @@ void acpi_create_efi_mmap_table(struct domain *d,
>   int acpi_make_efi_nodes(void *fdt, struct membank tbl_add[]);
>   
>   int construct_dom0(struct domain *d);
> +void __init create_domUs(void);
>   
>   void discard_initial_modules(void);
>   void dt_unreserved_regions(paddr_t s, paddr_t e,
> diff --git a/xen/include/asm-x86/setup.h b/xen/include/asm-x86/setup.h
> index 8d4b9ee..c0bd86f 100644
> --- a/xen/include/asm-x86/setup.h
> +++ b/xen/include/asm-x86/setup.h
> @@ -66,4 +66,6 @@ extern bool opt_dom0_shadow;
>   #endif
>   extern bool dom0_pvh;
>   
> +#define max_init_domid (0)
> +
>   #endif
> 

-- 
Julien Grall

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

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

* Re: [PATCH v3 14/25] xen/arm: introduce construct_domU
  2018-07-31 23:27 ` [PATCH v3 14/25] xen/arm: introduce construct_domU Stefano Stabellini
@ 2018-08-13 10:55   ` Julien Grall
  2018-08-15 20:21     ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-13 10:55 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi,

Title: You don't really introduce "construct_domU". You implement it. So 
a better title would be "Implement construct_domU".

On 01/08/18 00:27, Stefano Stabellini wrote:
> Similar to construct_dom0, construct_domU creates a barebone DomU guest.
> 
> The device tree node passed as argument is compatible "xen,domain", see
> docs/misc/arm/device-tree/booting.txt.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> 
> ---
> Changes in v3:
> - move setting type before allocate_memory
> - add ifdef around it and a comment
> 
> Changes in v2:
> - rename mem to memory
> - make cpus and memory mandatory
> - remove wront comment from commit message
> - cpus and memory are read as integers
> - read the vpl011 option
> ---
>   xen/arch/arm/domain_build.c | 36 +++++++++++++++++++++++++++++++++++-
>   1 file changed, 35 insertions(+), 1 deletion(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 8f7ac54..101cca2 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -2208,7 +2208,41 @@ static int __init __construct_domain(struct domain *d, struct kernel_info *kinfo
>   
>   static int __init construct_domU(struct domain *d, struct dt_device_node *node)
>   {
> -    return 0;
> +    struct kernel_info kinfo = {};
> +    int rc;
> +    u32 mem;
> +
> +    printk("*** LOADING DOMU ***\n");
> +
> +    rc = dt_property_read_u32(node, "cpus", &d->max_vcpus);
> +    if ( !rc )
> +        return -EINVAL;

For a user PoV this will be difficult to differentiate between the 
-EINVAL here and the only below.

It is probably useful to log some error message. Similarly you might 
want to add some print telling the information about the domain created.

> +
> +    rc = dt_property_read_u32(node, "memory", &mem);

I don't think 32-bit integer is going to be enough to cover all the 
case. Nowadays Arm supports up to 52-bits Address-Space.

So it would be best to cover all the case and use 64-bit here. That 
would also mean updating the documentation.

> +    if ( !rc ) > +        return -EINVAL;
> +    kinfo.unassigned_mem = (paddr_t)mem << 10;

kinfo.unassigned_mem = KB(mem);


> +
> +    d->vcpu = xzalloc_array(struct vcpu *, d->max_vcpus);
> +    if ( !d->vcpu )
> +        return -ENOMEM;;
> +    if ( alloc_vcpu(d, 0, 0) == NULL )
> +        return -ENOMEM;
> +    d->max_pages = ~0U;
> +
> +    kinfo.d = d;
> +
> +    rc = kernel_probe(&kinfo, node);
> +    if ( rc < 0 )
> +        return rc;
> +
> +#ifdef CONFIG_ARM_64
> +    /* type must be set before allocate memory */
> +    d->arch.type = kinfo.type;
> +#endif
> +    allocate_memory(d, &kinfo);
> +
> +    return __construct_domain(d, &kinfo);
>   }
>   
>   void __init create_domUs(void)
> 

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 16/25] xen/arm: rename allocate_memory to allocate_memory_11
  2018-07-31 23:27 ` [PATCH v3 16/25] xen/arm: rename allocate_memory to allocate_memory_11 Stefano Stabellini
@ 2018-08-13 10:57   ` Julien Grall
  2018-08-15 20:26     ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-13 10:57 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi,

On 01/08/18 00:27, Stefano Stabellini wrote:
> allocate_memory only deals with directly mapped memory. Rename it to
> allocate_memory_11.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> 
> ---
> Changes in v3:
> - add patch
> ---
>   xen/arch/arm/domain_build.c | 7 ++++---
>   1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 066dd75..ab72c36 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -244,7 +244,8 @@ fail:
>    * (as described above) we allow higher allocations and continue until
>    * that runs out (or we have allocated sufficient dom0 memory).
>    */
> -static void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
> +static void __init allocate_memory_11(struct domain *d,
> +                                      struct kernel_info *kinfo)
>   {
>       const unsigned int min_low_order =
>           get_order_from_bytes(min_t(paddr_t, dom0_mem, MB(128)));
> @@ -2240,7 +2241,7 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
>       /* type must be set before allocate memory */
>       d->arch.type = kinfo.type;
>   #endif
> -    allocate_memory(d, &kinfo);
> +    allocate_memory_11(d, &kinfo);

I don't think your patches are correctly ordered. This is adding a lot 
of confusion in the review because the DomU memory layout is fixed, yet 
here you rename the function to 1:1 mapping.

Most likely you want to do add the new memory function before 
introducing DomU.

Cheers,

>   
>       return __construct_domain(d, &kinfo);
>   }
> @@ -2309,7 +2310,7 @@ int __init construct_dom0(struct domain *d)
>       /* type must be set before allocate_memory */
>       d->arch.type = kinfo.type;
>   #endif
> -    allocate_memory(d, &kinfo);
> +    allocate_memory_11(d, &kinfo);
>       find_gnttab_region(d, &kinfo);
>   
>       /* Map extra GIC MMIO, irqs and other hw stuffs to dom0. */
> 

-- 
Julien Grall

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

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

* Re: [PATCH v3 18/25] xen/arm: generate a simple device tree for domUs
  2018-07-31 23:28 ` [PATCH v3 18/25] xen/arm: generate a simple device tree for domUs Stefano Stabellini
@ 2018-08-13 11:07   ` Julien Grall
  2018-08-15 20:47     ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-13 11:07 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 01/08/18 00:28, Stefano Stabellini wrote:
> Introduce functions to generate a basic domU device tree, similar to the
> existing functions in tools/libxl/libxl_arm.c.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> ---
> Changes in v3:
> - remove CONFIG_ACPI for make_chosen_node
> - remove make_hypervisor_node until all Xen related functionalities
>    (evtchns, grant table, etc.) work correctly
> 
> Changes in v2:
> - move prepare_dtb rename to previous patch
> - use switch for the gic version
> - use arm,gic-400 instead of arm,cortex-a15-gic
> - add @unit-address in the gic node name
> - add comment on DOMU_DTB_SIZE
> ---
>   xen/arch/arm/domain_build.c | 211 +++++++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 209 insertions(+), 2 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index dfa74e4..167a56e 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -1057,7 +1057,6 @@ static int __init make_timer_node(const struct domain *d, void *fdt,
>       return res;
>   }
>   
> -#ifdef CONFIG_ACPI
>   /*
>    * This function is used as part of the device tree generation for Dom0
>    * on ACPI systems, and DomUs started directly from Xen based on device
> @@ -1103,7 +1102,6 @@ static int __init make_chosen_node(const struct kernel_info *kinfo)
>   
>       return res;
>   }
> -#endif
>   
>   static int __init map_irq_to_domain(struct domain *d, unsigned int irq,
>                                       bool need_mapping, const char *devname)
> @@ -1496,6 +1494,211 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
>       return res;
>   }
>   
> +static int __init make_gic_domU_node(const struct domain *d, void *fdt, int addrcells, int sizecells)
> +{
> +    int res = 0;
> +    int reg_size = addrcells + sizecells;
> +    int nr_cells = reg_size * 2;
> +    __be32 reg[nr_cells];
> +    __be32 *cells;

You are trying to be save a few lines by handling both GICv2 and GICv3 
node in a single function. But this only thing it adds is confusion when 
reading the code.

Please have two functions (one for each GIC version) to generate the DT. 
This would also help to add ITS/GICv2m support in the future.

> +
> +    switch ( gic_hw_version() )
> +    {
> +    case GIC_V3:
> +        res = fdt_begin_node(fdt, "interrupt-controller@"__stringify(GUEST_GICV3_GICD_BASE));
> +        break;
> +    case GIC_V2:
> +        res = fdt_begin_node(fdt, "interrupt-controller@"__stringify(GUEST_GICD_BASE));
> +        break;
> +    default:
> +        panic("Unsupported GIC version");
> +    }
> +
> +    if ( res )
> +        return res;
> +
> +    res = fdt_property_cell(fdt, "#address-cells", 0);
> +    if ( res )
> +        return res;
> +
> +    res = fdt_property_cell(fdt, "#interrupt-cells", 3);
> +    if ( res )
> +        return res;
> +
> +    res = fdt_property(fdt, "interrupt-controller", NULL, 0);
> +    if ( res )
> +        return res;
> +
> +    switch ( gic_hw_version() )
> +    {
> +    case GIC_V3:
> +    {
> +        const uint64_t gicd_base = GUEST_GICV3_GICD_BASE;
> +        const uint64_t gicd_size = GUEST_GICV3_GICD_SIZE;
> +        const uint64_t gicr0_base = GUEST_GICV3_GICR0_BASE;
> +        const uint64_t gicr0_size = GUEST_GICV3_GICR0_SIZE;

I am not entirely convinced of the usefulness of those variables.

> +
> +        res = fdt_property_string(fdt, "compatible", "arm,gic-v3");
> +        if ( res )
> +            return res;
> +
> +        cells = &reg[0];
> +        dt_child_set_range(&cells, addrcells, sizecells, gicd_base, gicd_size);
> +        dt_child_set_range(&cells, addrcells, sizecells, gicr0_base, gicr0_size);
> +        res = fdt_property(fdt, "reg", reg, sizeof(reg));
> +        break;
> +    }
> +    case GIC_V2:
> +    {
> +        const uint64_t gicd_base = GUEST_GICD_BASE;
> +        const uint64_t gicd_size = GUEST_GICD_SIZE;
> +        const uint64_t gicc_base = GUEST_GICC_BASE;
> +        const uint64_t gicc_size = GUEST_GICC_SIZE;

Same here.

> +
> +        res = fdt_property_string(fdt, "compatible", "arm,gic-400");
> +        if ( res )
> +            return res;
> +
> +        cells = &reg[0];
> +        dt_child_set_range(&cells, addrcells, sizecells, gicd_base, gicd_size);
> +        dt_child_set_range(&cells, addrcells, sizecells, gicc_base, gicc_size);
> +        break;
> +    }
> +    default:
> +        break;
> +    }
> +
> +    res = fdt_property(fdt, "reg", reg, sizeof(reg));
> +    if (res)
> +        return res;
> +
> +    res = fdt_property_cell(fdt, "linux,phandle", GUEST_PHANDLE_GIC);
> +    if (res)
> +        return res;
> +
> +    res = fdt_property_cell(fdt, "phandle", GUEST_PHANDLE_GIC);
> +    if (res)
> +        return res;
> +
> +    res = fdt_end_node(fdt);
> +
> +    return res;
> +}
> +
> +static int __init make_timer_domU_node(const struct domain *d, void *fdt)
> +{
> +    int res;
> +    gic_interrupt_t intrs[3];
> +
> +    res = fdt_begin_node(fdt, "timer");
> +    if ( res )
> +        return res;
> +
> +    if (!is_64bit_domain(d))

Coding style:

if ( ... )

> +    {
> +        res = fdt_property_string(fdt, "compatible", "arm,armv7-timer");
> +        if ( res )
> +            return res;
> +    } else {

Coding style:

}
else
{

> +        res = fdt_property_string(fdt, "compatible", "arm,armv8-timer");
> +        if ( res )
> +            return res;
> +    }
> +
> +    set_interrupt_ppi(intrs[0], GUEST_TIMER_PHYS_S_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> +    set_interrupt_ppi(intrs[1], GUEST_TIMER_PHYS_NS_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> +    set_interrupt_ppi(intrs[2], GUEST_TIMER_VIRT_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> +
> +    res = fdt_property(fdt, "interrupts", intrs, sizeof (intrs[0]) * 3);
> +    if ( res )
> +        return res;
> +
> +    res = fdt_property_cell(fdt, "interrupt-parent",
> +                            GUEST_PHANDLE_GIC);
> +    if (res)
> +        return res;
> +
> +    res = fdt_end_node(fdt);

Newline here please.

> +    return res;
> +}
> +
> +/*
> + * The max size for DT is 2MB. However, the generated DT is small, 4KB
> + * are enough for now, but we might have to increase it in the feature.

s/feature/future/

> + */
> +#define DOMU_DTB_SIZE 4096
> +static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
> +{
> +    int addrcells, sizecells;
> +    int ret;
> +
> +    addrcells = dt_child_n_addr_cells(dt_host); > +    sizecells = dt_child_n_size_cells(dt_host);

Why do you use the host DT to find out the the #address-cells and 
#size-cells? Should not this be independent?

> +
> +    kinfo->fdt = xmalloc_bytes(DOMU_DTB_SIZE);
> +    if ( kinfo->fdt == NULL )
> +        return -ENOMEM;
> +
> +    ret = fdt_create(kinfo->fdt, DOMU_DTB_SIZE);
> +    if ( ret < 0 )
> +        goto err;
> +
> +    ret = fdt_finish_reservemap(kinfo->fdt);
> +    if ( ret < 0 )
> +        goto err;
> +
> +    ret = fdt_begin_node(kinfo->fdt, "/");
> +    if ( ret < 0 )
> +        goto err;
> +
> +    ret = fdt_property_cell(kinfo->fdt, "#address-cells", addrcells);
> +    if ( ret )
> +        goto err;
> +
> +    ret = fdt_property_cell(kinfo->fdt, "#size-cells", sizecells);
> +    if ( ret )
> +        goto err;
> +
> +    ret = make_chosen_node(kinfo);
> +    if ( ret )
> +        goto err;
> +
> +    ret = make_psci_node(kinfo->fdt, NULL);
> +    if ( ret )
> +        goto err;
> +
> +    ret = make_cpus_node(d, kinfo->fdt, NULL);
> +    if ( ret )
> +        goto err;
> +
> +    ret = make_memory_node(d, kinfo->fdt, addrcells, sizecells, kinfo);
> +    if ( ret )
> +        goto err;
> +
> +    ret = make_gic_domU_node(d, kinfo->fdt, addrcells, sizecells);
> +    if ( ret )
> +        goto err;
> +
> +    ret = make_timer_domU_node(d, kinfo->fdt);
> +    if ( ret )
> +        goto err;
> +
> +    ret = fdt_end_node(kinfo->fdt);
> +    if ( ret < 0 )
> +        goto err;
> +
> +    ret = fdt_finish(kinfo->fdt);
> +    if ( ret < 0 )
> +        goto err;
> +
> +    return 0;
> +
> +  err:
> +    printk("Device tree generation failed (%d).\n", ret);
> +    xfree(kinfo->fdt);

Newline here please.

> +    return -EINVAL;
> +}
> +
>   static int __init prepare_dtb_hwdom(struct domain *d, struct kernel_info *kinfo)
>   {
>       const p2m_type_t default_p2mt = p2m_mmio_direct_c;
> @@ -2366,6 +2569,10 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
>   #endif
>       allocate_memory(d, &kinfo);
>   
> +    rc = prepare_dtb_domU(d, &kinfo);
> +    if ( rc < 0 )
> +        return rc;
> +
>       return __construct_domain(d, &kinfo);
>   }
>   
> 

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 19/25] xen/arm: generate vpl011 node on device tree for domU
  2018-07-31 23:28 ` [PATCH v3 19/25] xen/arm: generate vpl011 node on device tree for domU Stefano Stabellini
@ 2018-08-13 11:20   ` Julien Grall
  2018-08-15 23:23     ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-13 11:20 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 01/08/18 00:28, Stefano Stabellini wrote:
> Introduce vpl011 support to guests started from Xen: it provides a
> simple way to print output from a guest, as most guests come with a
> pl011 driver. It is also able to provide a working console with
> interrupt support.
> 
> The UART exposed to the guest is a SBSA compatible UART and not a PL011.
> SBSA UART is a subset of PL011 r1p5. A full PL011 implementation in Xen
> would just be too difficult, so guests may require some drivers changes.
> 
> Enable vpl011 conditionally if the user requested it.
> 
> Make set_interrupt_ppi able to handle non-PPI and rename it
> set_interrupt.

It would have been better to have this change in a separate patch.

> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> ---
> Changes in v3:
> - use bool
> - retain BUG_ON(irq < 16)
> - add vpl011 bool to kinfo
> - return error of vpl011 is required but CONFIG_SBSA_VUART_CONSOLE is
>    missing
> 
> Changes in v2:
> - code style fixes
> - make set_interrupt_ppi generic
> - rename set_interrupt_ppi to set_interrupt
> - only make the vpl011 node if the option was enabled
> ---
>   xen/arch/arm/domain_build.c | 95 ++++++++++++++++++++++++++++++++++++++-------
>   xen/arch/arm/kernel.h       |  3 ++
>   2 files changed, 83 insertions(+), 15 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 167a56e..f9fa484 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -619,19 +619,20 @@ static int __init write_properties(struct domain *d, struct kernel_info *kinfo,
>   
>   typedef __be32 gic_interrupt_t[3];
>   
> -static void __init set_interrupt_ppi(gic_interrupt_t interrupt,
> -                                     unsigned int irq,
> -                                     unsigned int cpumask,
> -                                     unsigned int level)
> +static void __init set_interrupt(gic_interrupt_t interrupt,
> +                                 unsigned int irq,
> +                                 unsigned int cpumask,
> +                                 unsigned int level)
>   {
>       __be32 *cells = interrupt;
> +    bool is_ppi = !!(irq < 32);
>   
>       BUG_ON(irq < 16);
> -    BUG_ON(irq >= 32);
> +    irq -= (is_ppi) ? 16: 32; /* PPIs start at 16, SPIs at 32 */
>   
>       /* See linux Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt */
> -    dt_set_cell(&cells, 1, 1); /* is a PPI */
> -    dt_set_cell(&cells, 1, irq - 16); /* PPIs start at 16 */
> +    dt_set_cell(&cells, 1, is_ppi); /* is a PPI? */
> +    dt_set_cell(&cells, 1, irq);
>       dt_set_cell(&cells, 1, (cpumask << 8) | level);
>   }
>   
> @@ -752,7 +753,7 @@ static int __init make_hypervisor_node(struct domain *d,
>        *  - All CPUs
>        *  TODO: Handle properly the cpumask;
>        */
> -    set_interrupt_ppi(intr, d->arch.evtchn_irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> +    set_interrupt(intr, d->arch.evtchn_irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
>       res = fdt_property_interrupts(fdt, &intr, 1);
>       if ( res )
>           return res;
> @@ -1029,15 +1030,15 @@ static int __init make_timer_node(const struct domain *d, void *fdt,
>   
>       irq = timer_get_irq(TIMER_PHYS_SECURE_PPI);
>       dt_dprintk("  Secure interrupt %u\n", irq);
> -    set_interrupt_ppi(intrs[0], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> +    set_interrupt(intrs[0], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
>   
>       irq = timer_get_irq(TIMER_PHYS_NONSECURE_PPI);
>       dt_dprintk("  Non secure interrupt %u\n", irq);
> -    set_interrupt_ppi(intrs[1], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> +    set_interrupt(intrs[1], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
>   
>       irq = timer_get_irq(TIMER_VIRT_PPI);
>       dt_dprintk("  Virt interrupt %u\n", irq);
> -    set_interrupt_ppi(intrs[2], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> +    set_interrupt(intrs[2], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
>   
>       res = fdt_property_interrupts(fdt, intrs, 3);
>       if ( res )
> @@ -1605,9 +1606,9 @@ static int __init make_timer_domU_node(const struct domain *d, void *fdt)
>               return res;
>       }
>   
> -    set_interrupt_ppi(intrs[0], GUEST_TIMER_PHYS_S_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> -    set_interrupt_ppi(intrs[1], GUEST_TIMER_PHYS_NS_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> -    set_interrupt_ppi(intrs[2], GUEST_TIMER_VIRT_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> +    set_interrupt(intrs[0], GUEST_TIMER_PHYS_S_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> +    set_interrupt(intrs[1], GUEST_TIMER_PHYS_NS_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> +    set_interrupt(intrs[2], GUEST_TIMER_VIRT_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
>   
>       res = fdt_property(fdt, "interrupts", intrs, sizeof (intrs[0]) * 3);
>       if ( res )
> @@ -1622,6 +1623,56 @@ static int __init make_timer_domU_node(const struct domain *d, void *fdt)
>       return res;
>   }
>   
> +#ifdef CONFIG_SBSA_VUART_CONSOLE
> +static int __init make_vpl011_uart_node(const struct domain *d, void *fdt,
> +                                 int addrcells, int sizecells)
> +{
> +    int res;
> +    gic_interrupt_t intr;
> +    int reg_size = addrcells + sizecells;
> +    int nr_cells = reg_size;
> +    __be32 reg[nr_cells];
> +    __be32 *cells;
> +
> +    res = fdt_begin_node(fdt, "sbsa-pl011");

Node should contain the address in the name. Also, the name should be 
SBSA UART (which happens to be based on PL011 :)).

> +    if ( res )
> +        return res;
> +
> +    res = fdt_property_string(fdt, "compatible", "arm,sbsa-uart");
> +    if ( res )
> +        return res;
> +
> +    cells = &reg[0];
> +    dt_child_set_range(&cells, addrcells, sizecells, GUEST_PL011_BASE,
> +                       GUEST_PL011_SIZE);
> +    if ( res )
> +        return res;
> +    res = fdt_property(fdt, "reg", reg, sizeof(reg));
> +    if ( res )
> +        return res;
> +
> +    set_interrupt(intr, GUEST_VPL011_SPI, 0xf, DT_IRQ_TYPE_LEVEL_HIGH);
> +
> +    res = fdt_property(fdt, "interrupts", intr, sizeof (intr));
> +    if ( res )
> +        return res;
> +
> +    res = fdt_property_cell(fdt, "interrupt-parent",
> +                            GUEST_PHANDLE_GIC);
> +    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;
> +}
> +#endif
> +
>   /*
>    * The max size for DT is 2MB. However, the generated DT is small, 4KB
>    * are enough for now, but we might have to increase it in the feature.
> @@ -1683,6 +1734,18 @@ static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
>       if ( ret )
>           goto err;
>   
> +    if ( kinfo->vpl011 )
> +    {
> +#ifdef CONFIG_SBSA_VUART_CONSOLE
> +        ret = make_vpl011_uart_node(d, kinfo->fdt, addrcells, sizecells);
> +        if ( ret )
> +            goto err;
> +#else
> +        ret = -EINVAL;
> +        goto err;
> +#endif

I would prefer:


ret = -EINVAL
#ifdef CONFIG_SBSA...
	ret = make...
#endif
	if ( ret )
	  goto err;

> +    }
> +
>       ret = fdt_end_node(kinfo->fdt);
>       if ( ret < 0 )
>           goto err;
> @@ -2537,7 +2600,7 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
>   {
>       struct kernel_info kinfo = {};
>       int rc;
> -    u32 mem;
> +    u32 mem, len;
>   
>       printk("*** LOADING DOMU ***\n");
>   
> @@ -2550,6 +2613,8 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
>           return -EINVAL;
>       kinfo.unassigned_mem = (paddr_t)mem << 10;
>   
> +    kinfo.vpl011 = dt_get_property(node, "vpl011", &len) != NULL;
> +
>       d->vcpu = xzalloc_array(struct vcpu *, d->max_vcpus);
>       if ( !d->vcpu )
>           return -ENOMEM;;
> diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
> index 4a65289..9c9e568 100644
> --- a/xen/arch/arm/kernel.h
> +++ b/xen/arch/arm/kernel.h
> @@ -33,6 +33,9 @@ struct kernel_info {
>       paddr_t dtb_paddr;
>       paddr_t initrd_paddr;
>   
> +    /* Enable pl011 emulation */
> +    bool vpl011;
> +
>       /* loader to use for this kernel */
>       void (*load)(struct kernel_info *info);
>       /* loader specific state */
> 

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 20/25] xen/arm: introduce a union in vpl011
  2018-07-31 23:28 ` [PATCH v3 20/25] xen/arm: introduce a union in vpl011 Stefano Stabellini
@ 2018-08-13 11:24   ` Julien Grall
  2018-08-15 23:36     ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-13 11:24 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 01/08/18 00:28, Stefano Stabellini wrote:
> Introduce a union in struct vpl011 to contain the console ring members.
> A later patch will add another member of the union for the case where
> the backend is in Xen.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> ---
> Changes in v3:
> - rename ring field to dom
> 
> Changes in v2:
> - new patch
> ---
>   xen/arch/arm/vpl011.c        | 20 ++++++++++----------
>   xen/include/asm-arm/vpl011.h |  8 ++++++--
>   2 files changed, 16 insertions(+), 12 deletions(-)
> 
> diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> index a281eab..e70c5ec 100644
> --- a/xen/arch/arm/vpl011.c
> +++ b/xen/arch/arm/vpl011.c
> @@ -82,7 +82,7 @@ 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;
> +    struct xencons_interface *intf = vpl011->dom.ring_buf;
>       XENCONS_RING_IDX in_cons, in_prod;
>   
>       VPL011_LOCK(d, flags);
> @@ -145,7 +145,7 @@ static uint8_t vpl011_read_data(struct domain *d)
>   static void vpl011_update_tx_fifo_status(struct vpl011 *vpl011,
>                                            unsigned int fifo_level)
>   {
> -    struct xencons_interface *intf = vpl011->ring_buf;
> +    struct xencons_interface *intf = vpl011->dom.ring_buf;
>       unsigned int fifo_threshold = sizeof(intf->out) - SBSA_UART_FIFO_LEVEL;
>   
>       BUILD_BUG_ON(sizeof(intf->out) < SBSA_UART_FIFO_SIZE);
> @@ -164,7 +164,7 @@ 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;
> +    struct xencons_interface *intf = vpl011->dom.ring_buf;
>       XENCONS_RING_IDX out_cons, out_prod;
>   
>       VPL011_LOCK(d, flags);
> @@ -382,7 +382,7 @@ static void vpl011_data_avail(struct domain *d)
>   {
>       unsigned long flags;
>       struct vpl011 *vpl011 = &d->arch.vpl011;
> -    struct xencons_interface *intf = vpl011->ring_buf;
> +    struct xencons_interface *intf = vpl011->dom.ring_buf;
>       XENCONS_RING_IDX in_cons, in_prod, out_cons, out_prod;
>       XENCONS_RING_IDX in_fifo_level, out_fifo_level;
>   
> @@ -459,14 +459,14 @@ int domain_vpl011_init(struct domain *d, struct vpl011_init_info *info)
>       int rc;
>       struct vpl011 *vpl011 = &d->arch.vpl011;
>   
> -    if ( vpl011->ring_buf )
> +    if ( vpl011->dom.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);
> +                                  &vpl011->dom.ring_page,
> +                                  &vpl011->dom.ring_buf);
>       if ( rc < 0 )
>           goto out;
>   
> @@ -495,7 +495,7 @@ out2:
>       vgic_free_virq(d, GUEST_VPL011_SPI);
>   
>   out1:
> -    destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
> +    destroy_ring_for_helper(&vpl011->dom.ring_buf, vpl011->dom.ring_page);
>   
>   out:
>       return rc;
> @@ -505,11 +505,11 @@ void domain_vpl011_deinit(struct domain *d)
>   {
>       struct vpl011 *vpl011 = &d->arch.vpl011;
>   
> -    if ( !vpl011->ring_buf )
> +    if ( !vpl011->dom.ring_buf )
>           return;
>   
>       free_xen_event_channel(d, vpl011->evtchn);
> -    destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
> +    destroy_ring_for_helper(&vpl011->dom.ring_buf, vpl011->dom.ring_page);
>   }
>   
>   /*
> diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
> index db95ff8..b873a29 100644
> --- a/xen/include/asm-arm/vpl011.h
> +++ b/xen/include/asm-arm/vpl011.h
> @@ -31,8 +31,12 @@
>   #define SBSA_UART_FIFO_SIZE 32
>   
>   struct vpl011 {
> -    void *ring_buf;
> -    struct page_info *ring_page;
> +    union {

If you name the union vpl011_backend it would be clearer that this deal 
with backend information. Or even just avoiding the anonymous union by 
naming it "backend".

> +        struct {
> +            void *ring_buf;
> +            struct page_info *ring_page;
> +        } dom;
> +    };
>       uint32_t    uartfr;         /* Flag register */
>       uint32_t    uartcr;         /* Control register */
>       uint32_t    uartimsc;       /* Interrupt mask register*/
> 

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 21/25] xen/arm: refactor vpl011_data_avail
  2018-07-31 23:28 ` [PATCH v3 21/25] xen/arm: refactor vpl011_data_avail Stefano Stabellini
@ 2018-08-13 13:23   ` Julien Grall
  0 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2018-08-13 13:23 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 01/08/18 00:28, Stefano Stabellini wrote:
> Move the code to calculate in_fifo_level and out_fifo_level out of
> vpl011_data_avail, to the caller.
> This change will make it possible to reuse vpl011_data_avail with
> different ring structures in a later patch.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

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

Cheers,

> 
> ---
> Changes in v3:
> - remove forward declaration of vpl011_data_avail
> 
> Changes in v2:
> - new patch
> ---
>   xen/arch/arm/vpl011.c | 64 +++++++++++++++++++++++++++++----------------------
>   1 file changed, 36 insertions(+), 28 deletions(-)
> 
> diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> index e70c5ec..725a203 100644
> --- a/xen/arch/arm/vpl011.c
> +++ b/xen/arch/arm/vpl011.c
> @@ -378,30 +378,13 @@ static const struct mmio_handler_ops vpl011_mmio_handler = {
>       .write = vpl011_mmio_write,
>   };
>   
> -static void vpl011_data_avail(struct domain *d)
> +static void vpl011_data_avail(struct domain *d,
> +                              XENCONS_RING_IDX in_fifo_level,
> +                              XENCONS_RING_IDX in_size,
> +                              XENCONS_RING_IDX out_fifo_level,
> +                              XENCONS_RING_IDX out_size)
>   {
> -    unsigned long flags;
>       struct vpl011 *vpl011 = &d->arch.vpl011;
> -    struct xencons_interface *intf = vpl011->dom.ring_buf;
> -    XENCONS_RING_IDX in_cons, in_prod, out_cons, out_prod;
> -    XENCONS_RING_IDX in_fifo_level, out_fifo_level;
> -
> -    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_fifo_level = xencons_queued(in_prod,
> -                                   in_cons,
> -                                   sizeof(intf->in));
> -
> -    out_fifo_level = xencons_queued(out_prod,
> -                                    out_cons,
> -                                    sizeof(intf->out));
>   
>       /**** Update the UART RX state ****/
>   
> @@ -410,11 +393,11 @@ static void vpl011_data_avail(struct domain *d)
>           vpl011->uartfr &= ~RXFE;
>   
>       /* Set the FIFO_FULL bit if the Xen buffer is full. */
> -    if ( in_fifo_level == sizeof(intf->in) )
> +    if ( in_fifo_level == in_size )
>           vpl011->uartfr |= RXFF;
>   
>       /* Assert the RX interrupt if the FIFO is more than half way filled. */
> -    if ( in_fifo_level >= sizeof(intf->in) - SBSA_UART_FIFO_LEVEL )
> +    if ( in_fifo_level >= in_size - SBSA_UART_FIFO_LEVEL )
>           vpl011->uartris |= RXI;
>   
>       /*
> @@ -427,7 +410,7 @@ static void vpl011_data_avail(struct domain *d)
>   
>       /**** Update the UART TX state ****/
>   
> -    if ( out_fifo_level != sizeof(intf->out) )
> +    if ( out_fifo_level != out_size )
>       {
>           vpl011->uartfr &= ~TXFF;
>   
> @@ -445,13 +428,38 @@ static void vpl011_data_avail(struct domain *d)
>   
>       if ( out_fifo_level == 0 )
>           vpl011->uartfr |= TXFE;
> -
> -    VPL011_UNLOCK(d, flags);
>   }
>   
>   static void vpl011_notification(struct vcpu *v, unsigned int port)
>   {
> -    vpl011_data_avail(v->domain);
> +    unsigned long flags;
> +    struct domain *d = v->domain;
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +    struct xencons_interface *intf = vpl011->dom.ring_buf;
> +    XENCONS_RING_IDX in_cons, in_prod, out_cons, out_prod;
> +    XENCONS_RING_IDX in_fifo_level, out_fifo_level;
> +
> +    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_fifo_level = xencons_queued(in_prod,
> +                                   in_cons,
> +                                   sizeof(intf->in));
> +
> +    out_fifo_level = xencons_queued(out_prod,
> +                                    out_cons,
> +                                    sizeof(intf->out));
> +
> +    vpl011_data_avail(v->domain, in_fifo_level, sizeof(intf->in),
> +                      out_fifo_level, sizeof(intf->out));
> +
> +    VPL011_UNLOCK(d, flags);
>   }
>   
>   int domain_vpl011_init(struct domain *d, struct vpl011_init_info *info)
> 

-- 
Julien Grall

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

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

* Re: [PATCH v3 22/25] xen/arm: Allow vpl011 to be used by DomU
  2018-07-31 23:28 ` [PATCH v3 22/25] xen/arm: Allow vpl011 to be used by DomU Stefano Stabellini
@ 2018-08-13 13:42   ` Julien Grall
  2018-08-15 23:41     ` Stefano Stabellini
  2018-08-13 14:10   ` Julien Grall
  1 sibling, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-13 13:42 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel



On 01/08/18 00:28, Stefano Stabellini wrote:
> Make vpl011 being able to be used without a userspace component in Dom0.
> In that case, output is printed to the Xen serial and input is received
> from the Xen serial one character at a time.
> 
> Call domain_vpl011_init during construct_domU if vpl011 is enabled.
> 
> Introduce a new ring struct with only the ring array to avoid a waste of
> memory. Introduce separate read_data and write_data functions for
> initial domains: vpl011_write_data_xen is very simple and just writes
> to the console, while vpl011_read_data_xen is a duplicate of
> vpl011_read_data. Although textually almost identical, we are forced to
> duplicate the functions because the struct layout is different.
> 
> Output characters are printed one by one, potentially leading to
> intermixed output of different domains on the console. A follow-up patch
> will solve the issue by introducing buffering.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> ---
> Changes in v3:
> - add in-code comments
> - improve existing comments
> - remove ifdef around domain_vpl011_init in construct_domU
> - add ASSERT
> - use SBSA_UART_FIFO_SIZE for in buffer size
> - rename ring_enable to backend_in_domain
> - rename struct xencons_in to struct vpl011_xen_backend
> - rename inring field to xen
> - rename helper functions accordingly
> - remove unnecessary stub implementation of vpl011_rx_char
> - move vpl011_rx_char_xen within the file to avoid the need of a forward
>    declaration of vpl011_data_avail
> - fix small bug in vpl011_rx_char_xen: increment in_prod before using it
>    to check xencons_queued.
> 
> Changes in v2:
> - only init if vpl011
> - rename vpl011_read_char to vpl011_rx_char
> - remove spurious change
> - fix coding style
> - use different ring struct
> - move the write_data changes to their own function
>    (vpl011_write_data_noring)
> - duplicate vpl011_read_data
> ---
>   xen/arch/arm/domain_build.c  |   9 +-
>   xen/arch/arm/vpl011.c        | 198 ++++++++++++++++++++++++++++++++++++++-----
>   xen/include/asm-arm/vpl011.h |   8 ++
>   3 files changed, 192 insertions(+), 23 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index f9fa484..0888a76 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -2638,7 +2638,14 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
>       if ( rc < 0 )
>           return rc;
>   
> -    return __construct_domain(d, &kinfo);
> +    rc = __construct_domain(d, &kinfo);
> +    if ( rc < 0 )
> +        return rc;
> +
> +    if ( kinfo.vpl011 )
> +        rc = domain_vpl011_init(d, NULL);
> +
> +    return rc;
>   }
>   
>   void __init create_domUs(void)
> diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> index 725a203..f206c61 100644
> --- a/xen/arch/arm/vpl011.c
> +++ b/xen/arch/arm/vpl011.c
> @@ -77,6 +77,91 @@ static void vpl011_update_interrupt_status(struct domain *d)
>   #endif
>   }
>   
> +/*
> + * vpl011_write_data_xen writes chars from the vpl011 out buffer to the
> + * console. Only to be used when the backend is Xen.
> + */
> +static void vpl011_write_data_xen(struct domain *d, uint8_t data)
> +{
> +    unsigned long flags;
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +
> +    VPL011_LOCK(d, flags);
> +
> +    printk("%c", data);
> +    if (data == '\n')
> +        printk("DOM%u: ", d->domain_id);
> +
> +    vpl011->uartris |= TXI;
> +    vpl011->uartfr &= ~TXFE;
> +    vpl011_update_interrupt_status(d);
> +
> +    VPL011_UNLOCK(d, flags);
> +}
> +
> +/*
> + * vpl011_read_data_xen reads data when the backend is xen. Characters
> + * are added to the vpl011 receive buffer by vpl011_rx_char_xen.
> + */
> +static uint8_t vpl011_read_data_xen(struct domain *d)
> +{
> +    unsigned long flags;
> +    uint8_t data = 0;
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +    struct vpl011_xen_backend *intf = vpl011->xen;
> +    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 )
> +    {
> +        unsigned int fifo_level;
> +
> +        data = intf->in[xencons_mask(in_cons, sizeof(intf->in))];
> +        in_cons += 1;
> +        smp_mb();
> +        intf->in_cons = in_cons;
> +
> +        fifo_level = xencons_queued(in_prod, in_cons, sizeof(intf->in));
> +
> +        /* If the FIFO is now empty, we clear the receive timeout interrupt. */
> +        if ( fifo_level == 0 )
> +        {
> +            vpl011->uartfr |= RXFE;
> +            vpl011->uartris &= ~RTI;
> +        }
> +
> +        /* If the FIFO is more than half empty, we clear the RX interrupt. */
> +        if ( fifo_level < sizeof(intf->in) - SBSA_UART_FIFO_LEVEL )
> +            vpl011->uartris &= ~RXI;
> +
> +        vpl011_update_interrupt_status(d);
> +    }
> +    else
> +        gprintk(XENLOG_ERR, "vpl011: Unexpected IN ring buffer empty\n");
> +
> +    /*
> +     * We have consumed a character or the FIFO was empty, so clear the
> +     * "FIFO full" bit.
> +     */
> +    vpl011->uartfr &= ~RXFF;
> +
> +    VPL011_UNLOCK(d, flags);
> +
> +    return data;
> +}
> +
>   static uint8_t vpl011_read_data(struct domain *d)
>   {
>       unsigned long flags;
> @@ -240,7 +325,10 @@ static int vpl011_mmio_read(struct vcpu *v,
>       case DR:
>           if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
>   
> -        *r = vreg_reg32_extract(vpl011_read_data(d), info);
> +        if ( vpl011->backend_in_domain )
> +            *r = vreg_reg32_extract(vpl011_read_data(d), info);
> +        else
> +            *r = vreg_reg32_extract(vpl011_read_data_xen(d), info);
>           return 1;
>   
>       case RSR:
> @@ -325,7 +413,10 @@ static int vpl011_mmio_write(struct vcpu *v,
>   
>           vreg_reg32_update(&data, r, info);
>           data &= 0xFF;
> -        vpl011_write_data(v->domain, data);
> +        if ( vpl011->backend_in_domain )
> +            vpl011_write_data(v->domain, data);
> +        else
> +            vpl011_write_data_xen(v->domain, data);
>           return 1;
>       }
>   
> @@ -430,6 +521,39 @@ static void vpl011_data_avail(struct domain *d,
>           vpl011->uartfr |= TXFE;
>   }
>   
> +/*
> + * vpl011_rx_char_xen adds a char to a domain's vpl011 receive buffer.
> + * It is only used when the vpl011 backend is in Xen.
> + */
> +void vpl011_rx_char_xen(struct domain *d, char c)
> +{
> +    unsigned long flags;
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +    struct vpl011_xen_backend *intf = vpl011->xen;
> +    XENCONS_RING_IDX in_cons, in_prod, in_fifo_level;
> +
> +    ASSERT(!vpl011->backend_in_domain);
> +    VPL011_LOCK(d, flags);
> +
> +    in_cons = intf->in_cons;
> +    in_prod = intf->in_prod;
> +    if ( xencons_queued(in_prod, in_cons, sizeof(intf->in)) == sizeof(intf->in) )
> +    {
> +        VPL011_UNLOCK(d, flags);
> +        return;
> +    }
> +
> +    intf->in[xencons_mask(in_prod, sizeof(intf->in))] = c;
> +    intf->in_prod = ++in_prod;
> +
> +    in_fifo_level = xencons_queued(in_prod,
> +                                   in_cons,
> +                                   sizeof(intf->in));
> +
> +    vpl011_data_avail(d, in_fifo_level, sizeof(intf->in), 0, SBSA_UART_FIFO_SIZE);
> +    VPL011_UNLOCK(d, flags);
> +}
> +
>   static void vpl011_notification(struct vcpu *v, unsigned int port)
>   {
>       unsigned long flags;
> @@ -470,27 +594,47 @@ int domain_vpl011_init(struct domain *d, struct vpl011_init_info *info)
>       if ( vpl011->dom.ring_buf )
>           return -EINVAL;
>   
> -    /* Map the guest PFN to Xen address space. */
> -    rc =  prepare_ring_for_helper(d,
> -                                  gfn_x(info->gfn),
> -                                  &vpl011->dom.ring_page,
> -                                  &vpl011->dom.ring_buf);
> -    if ( rc < 0 )
> -        goto out;
> +    /*
> +     * info is NULL when the backend is in Xen.
> +     * info is != NULL when the backend is in a domain.
> +     */
> +    if ( info != NULL )
> +    {
> +        vpl011->backend_in_domain = true;
> +
> +        /* Map the guest PFN to Xen address space. */
> +        rc =  prepare_ring_for_helper(d,
> +                gfn_x(info->gfn),
> +                &vpl011->dom.ring_page,
> +                &vpl011->dom.ring_buf);

The indentation looks wrong here.

> +        if ( rc < 0 )
> +            goto out;
> +
> +        rc = alloc_unbound_xen_event_channel(d, 0, info->console_domid,
> +                vpl011_notification);

The indentation looks wrong here.

> +        if ( rc < 0 )
> +            goto out1;
> +
> +        vpl011->evtchn = info->evtchn = rc;
> +    }
> +    else
> +    {
> +        vpl011->backend_in_domain = false;
> +
> +        vpl011->xen = xzalloc(struct vpl011_xen_backend);
> +        if ( vpl011->xen == NULL )
> +        {
> +            rc = -EINVAL;
> +            goto out1;
> +        }
> +    }
>   
>       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);
>   
> @@ -503,7 +647,10 @@ out2:
>       vgic_free_virq(d, GUEST_VPL011_SPI);
>   
>   out1:
> -    destroy_ring_for_helper(&vpl011->dom.ring_buf, vpl011->dom.ring_page);
> +    if ( vpl011->backend_in_domain )
> +        destroy_ring_for_helper(&vpl011->dom.ring_buf, vpl011->dom.ring_page);
> +    else
> +        xfree(vpl011->xen);
>   
>   out:
>       return rc;
> @@ -513,11 +660,18 @@ void domain_vpl011_deinit(struct domain *d)
>   {
>       struct vpl011 *vpl011 = &d->arch.vpl011;
>   
> -    if ( !vpl011->dom.ring_buf )
> -        return;
> +    if ( vpl011->backend_in_domain )
> +    {
> +        if ( !vpl011->dom.ring_buf )
> +            return;
>   
> -    free_xen_event_channel(d, vpl011->evtchn);
> -    destroy_ring_for_helper(&vpl011->dom.ring_buf, vpl011->dom.ring_page);
> +        free_xen_event_channel(d, vpl011->evtchn);
> +        destroy_ring_for_helper(&vpl011->dom.ring_buf, vpl011->dom.ring_page);
> +    }
> +    else
> +    {
> +        xfree(vpl011->xen);
> +    }

NIT: The { } is not necessary for one line.

>   }
>   
>   /*
> diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
> index b873a29..c9918c1 100644
> --- a/xen/include/asm-arm/vpl011.h
> +++ b/xen/include/asm-arm/vpl011.h
> @@ -21,6 +21,7 @@
>   
>   #include <public/domctl.h>
>   #include <public/io/ring.h>
> +#include <public/io/console.h>
>   #include <asm/vreg.h>
>   #include <xen/mm.h>
>   
> @@ -29,13 +30,19 @@
>   #define VPL011_UNLOCK(d,flags) spin_unlock_irqrestore(&(d)->arch.vpl011.lock, flags)
>   
>   #define SBSA_UART_FIFO_SIZE 32
> +struct vpl011_xen_backend {
> +    char in[SBSA_UART_FIFO_SIZE];
> +    XENCONS_RING_IDX in_cons, in_prod;
> +};
>   
>   struct vpl011 {
> +    bool backend_in_domain;
>       union {
>           struct {
>               void *ring_buf;
>               struct page_info *ring_page;
>           } dom;
> +        struct vpl011_xen_backend *xen;
>       };
>       uint32_t    uartfr;         /* Flag register */
>       uint32_t    uartcr;         /* Control register */
> @@ -57,6 +64,7 @@ struct vpl011_init_info {
>   int domain_vpl011_init(struct domain *d,
>                          struct vpl011_init_info *info);
>   void domain_vpl011_deinit(struct domain *d);
> +void vpl011_rx_char_xen(struct domain *d, char c);
>   #else
>   static inline int domain_vpl011_init(struct domain *d,
>                                        struct vpl011_init_info *info)
> 

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 23/25] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-31 23:28 ` [PATCH v3 23/25] xen: support console_switching between Dom0 and DomUs on ARM Stefano Stabellini
  2018-08-01  9:03   ` Jan Beulich
@ 2018-08-13 13:58   ` Julien Grall
  2018-08-16 21:48     ` Stefano Stabellini
  1 sibling, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-13 13:58 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, andrii_anisov, George.Dunlap, andrew.cooper3,
	ian.jackson, xen-devel, tim, jbeulich, wei.liu2

Hi Stefano,

OOI, on the previous version you said you will explore the CTRL-x N 
solution (where N is the domID console to switch too). What was the 
result here?

On 01/08/18 00:28, Stefano Stabellini wrote:
> Today Ctrl-AAA is used to switch between Xen and Dom0. Extend the
> mechanism to allow for switching between Xen, Dom0, and any of the
> initial DomU created from Xen alongside Dom0 out of information provided
> via device tree.
> 
> Rename xen_rx to console_rx to match the new behavior.
> 
> Clarify existing comment about "notify the guest", making it clear that
> it is only about the hardware domain.
> 
> Export a function named console_input_domain() to allow others to know
> which domains has input at a given time.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> CC: andrew.cooper3@citrix.com
> CC: George.Dunlap@eu.citrix.com
> CC: ian.jackson@eu.citrix.com
> CC: jbeulich@suse.com
> CC: konrad.wilk@oracle.com
> CC: tim@xen.org
> CC: wei.liu2@citrix.com
> ---
> Changes in v3:
> - only call vpl011 functions ifdef CONFIG_SBSA_VUART_CONSOLE
> - add blank line and spaces
> - remove xen_rx from print messages
> - rename xen_rx to console_rx
> - keep switch_serial_input() at boot
> - add better comments
> - fix existing comment
> - add warning if no guests console/uart is available
> - add console_input_domain function
> 
> Changes in v2:
> - only call vpl011_rx_char if the vpl011 has been initialized
> ---
>   xen/drivers/char/console.c | 71 +++++++++++++++++++++++++++++++++++++---------
>   xen/include/xen/console.h  |  2 ++
>   2 files changed, 60 insertions(+), 13 deletions(-)
> 
> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> index 0f05369..cd4dfb1 100644
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -31,10 +31,13 @@
>   #include <xen/early_printk.h>
>   #include <xen/warning.h>
>   #include <xen/pv_console.h>
> +#include <asm/setup.h>
>   
>   #ifdef CONFIG_X86
>   #include <xen/consoled.h>
>   #include <asm/guest.h>
> +#else
> +#include <asm/vpl011.h>
>   #endif
>   
>   /* console: comma-separated list of console outputs. */
> @@ -389,30 +392,72 @@ static void dump_console_ring_key(unsigned char key)
>       free_xenheap_pages(buf, order);
>   }
>   
> -/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
> +/*
> + * CTRL-<switch_char> switches input direction between Xen, Dom0 and
> + * DomUs.
> + */
>   #define switch_code (opt_conswitch[0]-'a'+1)
> -static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain 0. */
> +/*
> + * console_rx=0 => input to xen
> + * console_rx=1 => input to dom0
> + * console_rx=N => input dom(N-1)
> + */
> +static int __read_mostly console_rx = 0;
> +
> +struct domain *console_input_domain(void)
> +{
> +    return get_domain_by_id(console_rx - 1);

Please take care of the case where console_rx == 0.

> +}
>   
>   static void switch_serial_input(void)
>   {
> -    static char *input_str[2] = { "DOM0", "Xen" };
> -    xen_rx = !xen_rx;
> -    printk("*** Serial input -> %s", input_str[xen_rx]);
> +    console_rx++;
> +    if ( console_rx == max_init_domid + 2 )
> +        console_rx = 0;
> +
> +    if ( !console_rx )
> +        printk("*** Serial input to Xen");
> +    else
> +        printk("*** Serial input to DOM%d", console_rx - 1);
> +
>       if ( switch_code )
> -        printk(" (type 'CTRL-%c' three times to switch input to %s)",
> -               opt_conswitch[0], input_str[!xen_rx]);
> +        printk(" (type 'CTRL-%c' three times to switch input)",
> +               opt_conswitch[0]);
>       printk("\n");
>   }
>   
>   static void __serial_rx(char c, struct cpu_user_regs *regs)
>   {
> -    if ( xen_rx )
> +    if ( console_rx == 0 )
>           return handle_keypress(c, regs);
>   
> -    /* Deliver input to guest buffer, unless it is already full. */
> -    if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
> -        serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> -    /* Always notify the guest: prevents receive path from getting stuck. */
> +    if ( console_rx == 1 )
> +    {
> +        /* Deliver input to guest buffer, unless it is already full. */
> +        if ( (serial_rx_prod - serial_rx_cons) != SERIAL_RX_SIZE )
> +            serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> +    }
> +#ifdef CONFIG_SBSA_VUART_CONSOLE
> +    else
> +    {
> +        struct domain *d = get_domain_by_id(console_rx - 1);

I don't think this is correct to assume the domain will always be 
present. With this series, it would be possible to retire a domain and 
therefore get_domain_by_id() would return NULL here. This would result 
to a data abort below.

Also, I think you want to use rcu_lock_by_domain here (I am not 100% 
sure though).

> +
> +        /*
> +         * If we have a properly initialized vpl011 console for the
> +         * domain, without a full PV ring to Dom0 (in that case input
> +         * comes from the PV ring), then send the character to it.
> +         */
> +        if ( !d->arch.vpl011.backend_in_domain && d->arch.vpl011.xen != NULL )
> +            vpl011_rx_char_xen(d, c);
> +        else
> +            printk("Cannot send chars to Dom%d: no UART available\n",
> +                   d->domain_id);
> +    }
> +#endif
> +    /*
> +     * Always notify the hardware domain: prevents receive path from

That's not true. If you look at send_global_virq, it will send to the 
domain that register the VIRQ. That may be the hardware domain but could 
be someone else.

However, I still don't understand how this work in presence of multiple 
backend here. Why would you notify Domain B everytime a character is 
redirected to domain A/C/D the console?

> +     * getting stuck.
> +     */
>       send_global_virq(VIRQ_CONSOLE);
>   
>   #ifdef CONFIG_X86
> @@ -923,7 +968,7 @@ void __init console_endboot(void)
>        * a useful 'how to switch' message.
>        */
>       if ( opt_conswitch[1] == 'x' )
> -        xen_rx = !xen_rx;
> +        console_rx = 0;
>   
>       register_keyhandler('w', dump_console_ring_key,
>                           "synchronously dump console ring buffer (dmesg)", 0);
> diff --git a/xen/include/xen/console.h b/xen/include/xen/console.h
> index ea06fd8..2fe3912 100644
> --- a/xen/include/xen/console.h
> +++ b/xen/include/xen/console.h
> @@ -31,6 +31,8 @@ void console_end_sync(void);
>   void console_start_log_everything(void);
>   void console_end_log_everything(void);
>   
> +struct domain *console_input_domain(void);
> +
>   /*
>    * Steal output from the console. Returns +ve identifier, else -ve error.
>    * Takes the handle of the serial line to steal, and steal callback function.
> 

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 22/25] xen/arm: Allow vpl011 to be used by DomU
  2018-07-31 23:28 ` [PATCH v3 22/25] xen/arm: Allow vpl011 to be used by DomU Stefano Stabellini
  2018-08-13 13:42   ` Julien Grall
@ 2018-08-13 14:10   ` Julien Grall
  2018-08-16 19:21     ` Stefano Stabellini
  1 sibling, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-13 14:10 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 01/08/18 00:28, Stefano Stabellini wrote:
> Make vpl011 being able to be used without a userspace component in Dom0.
> In that case, output is printed to the Xen serial and input is received
> from the Xen serial one character at a time.
> 
> Call domain_vpl011_init during construct_domU if vpl011 is enabled.
> 
> Introduce a new ring struct with only the ring array to avoid a waste of
> memory. Introduce separate read_data and write_data functions for
> initial domains: vpl011_write_data_xen is very simple and just writes
> to the console, while vpl011_read_data_xen is a duplicate of
> vpl011_read_data. Although textually almost identical, we are forced to
> duplicate the functions because the struct layout is different.
> 
> Output characters are printed one by one, potentially leading to
> intermixed output of different domains on the console. A follow-up patch
> will solve the issue by introducing buffering.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> ---
> Changes in v3:
> - add in-code comments
> - improve existing comments
> - remove ifdef around domain_vpl011_init in construct_domU
> - add ASSERT
> - use SBSA_UART_FIFO_SIZE for in buffer size
> - rename ring_enable to backend_in_domain
> - rename struct xencons_in to struct vpl011_xen_backend
> - rename inring field to xen
> - rename helper functions accordingly
> - remove unnecessary stub implementation of vpl011_rx_char
> - move vpl011_rx_char_xen within the file to avoid the need of a forward
>    declaration of vpl011_data_avail
> - fix small bug in vpl011_rx_char_xen: increment in_prod before using it
>    to check xencons_queued.
> 
> Changes in v2:
> - only init if vpl011
> - rename vpl011_read_char to vpl011_rx_char
> - remove spurious change
> - fix coding style
> - use different ring struct
> - move the write_data changes to their own function
>    (vpl011_write_data_noring)
> - duplicate vpl011_read_data
> ---
>   xen/arch/arm/domain_build.c  |   9 +-
>   xen/arch/arm/vpl011.c        | 198 ++++++++++++++++++++++++++++++++++++++-----
>   xen/include/asm-arm/vpl011.h |   8 ++
>   3 files changed, 192 insertions(+), 23 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index f9fa484..0888a76 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -2638,7 +2638,14 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
>       if ( rc < 0 )
>           return rc;
>   
> -    return __construct_domain(d, &kinfo);
> +    rc = __construct_domain(d, &kinfo);
> +    if ( rc < 0 )
> +        return rc;
> +
> +    if ( kinfo.vpl011 )
> +        rc = domain_vpl011_init(d, NULL);
> +
> +    return rc;
>   }
>   
>   void __init create_domUs(void)
> diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> index 725a203..f206c61 100644
> --- a/xen/arch/arm/vpl011.c
> +++ b/xen/arch/arm/vpl011.c
> @@ -77,6 +77,91 @@ static void vpl011_update_interrupt_status(struct domain *d)
>   #endif
>   }
>   
> +/*
> + * vpl011_write_data_xen writes chars from the vpl011 out buffer to the
> + * console. Only to be used when the backend is Xen.
> + */
> +static void vpl011_write_data_xen(struct domain *d, uint8_t data)
> +{
> +    unsigned long flags;
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +
> +    VPL011_LOCK(d, flags);
> +
> +    printk("%c", data);
> +    if (data == '\n')
> +        printk("DOM%u: ", d->domain_id);

There are a problem in this code. The first line of a domain will always 
printed without "DOM%u: " in front. This means you don't really know 
where it is coming from until you get the second line.

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 24/25] xen/vpl011: buffer out chars when the backend is xen
  2018-07-31 23:28 ` [PATCH v3 24/25] xen/vpl011: buffer out chars when the backend is xen Stefano Stabellini
@ 2018-08-13 14:21   ` Julien Grall
  2018-08-16 19:41     ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-13 14:21 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi,

On 01/08/18 00:28, Stefano Stabellini wrote:
> To avoid mixing the output of different domains on the console, buffer
> the output chars and print line by line. Unless the domain has input
> from the serial, in which case we want to print char by char for a
> smooth user experience.
> 
> The size of SBSA_UART_OUT_BUF_SIZE is arbitrary. 90 should be large
> enough to accommodate the length of most lines of output (typically they
> are limited to 80 characters on Unix systems), plus one extra char for
> the string terminator.

How about using the same value as vuart (e.g VUART_BUT_SIZE) instead? So 
we buffer the same way for the vpl011?

> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> ---
>   xen/arch/arm/vpl011.c        | 21 ++++++++++++++++++---
>   xen/include/asm-arm/vpl011.h |  3 +++
>   2 files changed, 21 insertions(+), 3 deletions(-)
> 
> diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> index f206c61..8137371 100644
> --- a/xen/arch/arm/vpl011.c
> +++ b/xen/arch/arm/vpl011.c
> @@ -28,6 +28,7 @@
>   #include <xen/lib.h>
>   #include <xen/mm.h>
>   #include <xen/sched.h>
> +#include <xen/console.h>
>   #include <public/domctl.h>
>   #include <public/io/console.h>
>   #include <asm/pl011-uart.h>
> @@ -85,12 +86,26 @@ static void vpl011_write_data_xen(struct domain *d, uint8_t data)
>   {
>       unsigned long flags;
>       struct vpl011 *vpl011 = &d->arch.vpl011;
> +    struct vpl011_xen_backend *intf = vpl011->xen;
> +    struct domain *input = console_input_domain();
>   
>       VPL011_LOCK(d, flags);
>   
> -    printk("%c", data);
> -    if (data == '\n')
> -        printk("DOM%u: ", d->domain_id);
> +    intf->out[intf->out_prod++] = data;
> +    if ( d == input && intf->out_prod == 1 )
> +    {
> +        printk("%c", data);
> +        if ( data == '\n' )
> +            printk("DOM%u: ", d->domain_id);
> +        intf->out_prod = 0;

See my remark on the patch implementing vpl011_write_data_xen.

> +    } else if ( d == input ||

Coding style:

}
else if
{

> +                intf->out_prod == SBSA_UART_OUT_BUF_SIZE - 1 ||
> +                data == '\n' )
> +    {
> +        intf->out[intf->out_prod++] = '\0';
> +        printk("DOM%u: %s", d->domain_id, intf->out);
> +        intf->out_prod = 0;
> +    }

The code is quite difficult to read. It would be easier to differentiate 
(domain == input vs domain != input) even if it means a bit of duplication.

You also don't handle all the cases.

For the input domain, I don't think you want to print the domain in 
front. Instead I would rely on the "Switch to ...". This would avoid the 
problem where DomB needs to have his line printed while it is not the 
console input. If this happens in the middle of DomA, then you are 
loosing track what's going on.

Also if you have the buffer full, you will write the line without a 
newline. So, the next line is going to be wrong. In that case, you need 
to add a newline before printed. I think you want to look at what we did 
in vuart_print_char.

>   
>       vpl011->uartris |= TXI;
>       vpl011->uartfr &= ~TXFE;
> diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
> index c9918c1..30487e8 100644
> --- a/xen/include/asm-arm/vpl011.h
> +++ b/xen/include/asm-arm/vpl011.h
> @@ -30,9 +30,12 @@
>   #define VPL011_UNLOCK(d,flags) spin_unlock_irqrestore(&(d)->arch.vpl011.lock, flags)
>   
>   #define SBSA_UART_FIFO_SIZE 32
> +#define SBSA_UART_OUT_BUF_SIZE 91
>   struct vpl011_xen_backend {
>       char in[SBSA_UART_FIFO_SIZE];
> +    char out[SBSA_UART_OUT_BUF_SIZE];
>       XENCONS_RING_IDX in_cons, in_prod;
> +    XENCONS_RING_IDX out_prod;
>   };
>   
>   struct vpl011 {
> 

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 25/25] xen/arm: split domain_build.c
  2018-07-31 23:28 ` [PATCH v3 25/25] xen/arm: split domain_build.c Stefano Stabellini
@ 2018-08-13 14:29   ` Julien Grall
  2018-08-16  0:25     ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-13 14:29 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi,

On 01/08/18 00:28, Stefano Stabellini wrote:
> domain_build.c is too large.
> 
> Move all the ACPI specific device tree generating functions from
> domain_build.c to acpi/acpi_dt_build.c.

The directory is called "acpi" so there is no point to duplicate in the 
filename.

Also, looking at the code moved, the name does not seem to be correct. 
Indeed you also generate ACPI tables. A better name for this file would 
be domain_build.c

> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> ---
>   xen/arch/arm/acpi/Makefile        |   1 +
>   xen/arch/arm/acpi/acpi_dt_build.c | 591 ++++++++++++++++++++++++++++++++++++++
>   xen/arch/arm/acpi/acpi_dt_build.h |  32 +++
>   xen/arch/arm/domain_build.c       | 585 +------------------------------------
>   4 files changed, 629 insertions(+), 580 deletions(-)
>   create mode 100644 xen/arch/arm/acpi/acpi_dt_build.c
>   create mode 100644 xen/arch/arm/acpi/acpi_dt_build.h
> 
> diff --git a/xen/arch/arm/acpi/Makefile b/xen/arch/arm/acpi/Makefile
> index 23963f8..ac0804b 100644
> --- a/xen/arch/arm/acpi/Makefile
> +++ b/xen/arch/arm/acpi/Makefile
> @@ -1,2 +1,3 @@
>   obj-y += lib.o
> +obj-y += acpi_dt_build.o
>   obj-y += boot.init.o
> diff --git a/xen/arch/arm/acpi/acpi_dt_build.c b/xen/arch/arm/acpi/acpi_dt_build.c
> new file mode 100644
> index 0000000..7e12d64
> --- /dev/null
> +++ b/xen/arch/arm/acpi/acpi_dt_build.c
> @@ -0,0 +1,591 @@

Missing copyright headers here.

> +#include <xen/mm.h>
> +#include <xen/sched.h>
> +#include <xen/acpi.h>
> +#include <xen/event.h>
> +#include <xen/iocap.h>
> +#include <xen/device_tree.h>
> +#include <xen/libfdt/libfdt.h>
> +#include <xen/irq.h>
> +#include <asm/irq.h>

Do we really need xen/irq.h and asm/irq.h?

> +#include <acpi/actables.h>
> +#include "acpi_dt_build.h"
> +#include "../kernel.h"

Urgh, that's a call to move kernel.h in asm-arm/.

> diff --git a/xen/arch/arm/acpi/acpi_dt_build.h b/xen/arch/arm/acpi/acpi_dt_build.h
> new file mode 100644
> index 0000000..08e7aab
> --- /dev/null
> +++ b/xen/arch/arm/acpi/acpi_dt_build.h
> @@ -0,0 +1,32 @@
> +#ifndef __ARCH_ARM_ACPI_ACPI_DT_BUILD_H__
> +#define __ARCH_ARM_ACPI_ACPI_DT_BUILD_H__
> +
> +#include <xen/sched.h>
> +#include "../kernel.h"

See above.

> +
> +int map_irq_to_domain(struct domain *d, unsigned int irq,
> +                      bool need_mapping, const char *devname);
> +int make_chosen_node(const struct kernel_info *kinfo);
> +void evtchn_allocate(struct domain *d);

Those one should be moved in an header domain_build.h in asm-arm.

> +
> +#ifndef CONFIG_ACPI
> +static inline int prepare_acpi(struct domain *d, struct kernel_info *kinfo)
> +{
> +    /* Only booting with ACPI will hit here */
> +    BUG();
> +    return -EINVAL;
> +}
> +#else
> +int prepare_acpi(struct domain *d, struct kernel_info *kinfo);
> +#endif

This one should go in asm-arm/acpi.h.

So this header is not necessary anymore.

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 12/25] xen/arm: refactor construct_dom0
  2018-08-13 10:15   ` Julien Grall
@ 2018-08-15 19:27     ` Stefano Stabellini
  0 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-08-15 19:27 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Mon, 13 Aug 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 01/08/18 00:27, Stefano Stabellini wrote:
> > Move generic initializations out of construct_dom0 so that they can be
> > reused.
> > 
> > Rename prepare_dtb to prepare_dtb_hwdom to avoid confusion.
> > 
> > No functional changes in this patch.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > 
> > ---
> > Changes in v3:
> > - move setting type before allocate_memory
> > - add ifdef around it and a comment
> > Changes in v2:
> > - move discard_initial_modules() after __construct_domain()
> > - remove useless blank line
> > - leave safety BUG_ONs in __construct_domain
> > - rename prepare_dtb to prepare_dtb_hwdom
> > ---
> >   xen/arch/arm/domain_build.c | 128
> > ++++++++++++++++++++++++--------------------
> >   1 file changed, 70 insertions(+), 58 deletions(-)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 8d82849..0835340 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -1371,7 +1371,7 @@ static int __init handle_node(struct domain *d, struct
> > kernel_info *kinfo,
> >       return res;
> >   }
> >   -static int __init prepare_dtb(struct domain *d, struct kernel_info
> > *kinfo)
> > +static int __init prepare_dtb_hwdom(struct domain *d, struct kernel_info
> > *kinfo)
> >   {
> >       const p2m_type_t default_p2mt = p2m_mmio_direct_c;
> >       const void *fdt;
> > @@ -2106,75 +2106,31 @@ static void __init find_gnttab_region(struct domain
> > *d,
> >              kinfo->gnttab_start, kinfo->gnttab_start + kinfo->gnttab_size);
> >   }
> >   -int __init construct_dom0(struct domain *d)
> > +static int __init __construct_domain(struct domain *d, struct kernel_info
> > *kinfo)
> >   {
> > -    const struct bootcmdline *kernel =
> > boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
> > -    struct kernel_info kinfo = {};
> >       struct vcpu *saved_current;
> > -    int rc, i, cpu;
> > -
> > +    int i, cpu;
> > +    struct cpu_user_regs *regs;
> >       struct vcpu *v = d->vcpu[0];
> > -    struct cpu_user_regs *regs = &v->arch.cpu_info->guest_cpu_user_regs;
> 
> There is no need to rewrite that line in
> 
> struct cpu_user_regs *regs;
> 
> regs = ...;

OK


> >   -    /* Sanity! */
> > -    BUG_ON(d->domain_id != 0);
> >       BUG_ON(d->vcpu[0] == NULL);
> >       BUG_ON(v->is_initialised);
> >   -    printk("*** LOADING DOMAIN 0 ***\n");
> > -    if ( dom0_mem <= 0 )
> > -    {
> > -        warning_add("PLEASE SPECIFY dom0_mem PARAMETER - USING 512M FOR
> > NOW\n");
> > -        dom0_mem = MB(512);
> > -    }
> > -
> > -
> > -    iommu_hwdom_init(d);
> > -
> > -    d->max_pages = ~0U;
> > -
> > -    kinfo.unassigned_mem = dom0_mem;
> > -    kinfo.d = d;
> > -
> > -    rc = kernel_probe(&kinfo, NULL);
> > -    if ( rc < 0 )
> > -        return rc;
> > +    regs = &v->arch.cpu_info->guest_cpu_user_regs;
> >     #ifdef CONFIG_ARM_64
> >       /* if aarch32 mode is not supported at EL1 do not allow 32-bit domain
> > */
> > -    if ( !(cpu_has_el1_32) && kinfo.type == DOMAIN_32BIT )
> > +    if ( !(cpu_has_el1_32) && kinfo->type == DOMAIN_32BIT )
> >       {
> >           printk("Platform does not support 32-bit domain\n");
> >           return -EINVAL;
> >       }
> > -    d->arch.type = kinfo.type;
> >         if ( is_64bit_domain(d) )
> >           vcpu_switch_to_aarch64_mode(v);
> >     #endif
> >   -    kinfo.cmdline = kernel != NULL ? &kernel->cmdline[0] : NULL;
> > -    allocate_memory(d, &kinfo);
> > -    find_gnttab_region(d, &kinfo);
> > -
> > -    /* Map extra GIC MMIO, irqs and other hw stuffs to dom0. */
> > -    rc = gic_map_hwdom_extra_mappings(d);
> > -    if ( rc < 0 )
> > -        return rc;
> > -
> > -    rc = platform_specific_mapping(d);
> > -    if ( rc < 0 )
> > -        return rc;
> > -
> > -    if ( acpi_disabled )
> > -        rc = prepare_dtb(d, &kinfo);
> > -    else
> > -        rc = prepare_acpi(d, &kinfo);
> > -
> > -    if ( rc < 0 )
> > -        return rc;
> > -
> >       /*
> >        * The following loads use the domain's p2m and require current to
> >        * be a vcpu of the domain, temporarily switch
> > @@ -2187,20 +2143,18 @@ int __init construct_dom0(struct domain *d)
> >        * kernel_load will determine the placement of the kernel as well
> >        * as the initrd & fdt in RAM, so call it first.
> >        */
> > -    kernel_load(&kinfo);
> > +    kernel_load(kinfo);
> >       /* initrd_load will fix up the fdt, so call it before dtb_load */
> > -    initrd_load(&kinfo);
> > -    dtb_load(&kinfo);
> > +    initrd_load(kinfo);
> > +    dtb_load(kinfo);
> >         /* Now that we are done restore the original p2m and current. */
> >       set_current(saved_current);
> >       p2m_restore_state(saved_current);
> >   -    discard_initial_modules();
> > -
> >       memset(regs, 0, sizeof(*regs));
> >   -    regs->pc = (register_t)kinfo.entry;
> > +    regs->pc = (register_t)kinfo->entry;
> >         if ( is_32bit_domain(d) )
> >       {
> > @@ -2218,14 +2172,14 @@ int __init construct_dom0(struct domain *d)
> >            */
> >           regs->r0 = 0; /* SBZ */
> >           regs->r1 = 0xffffffff; /* We use DTB therefore no machine id */
> > -        regs->r2 = kinfo.dtb_paddr;
> > +        regs->r2 = kinfo->dtb_paddr;
> >       }
> >   #ifdef CONFIG_ARM_64
> >       else
> >       {
> >           regs->cpsr = PSR_GUEST64_INIT;
> >           /* From linux/Documentation/arm64/booting.txt */
> > -        regs->x0 = kinfo.dtb_paddr;
> > +        regs->x0 = kinfo->dtb_paddr;
> >           regs->x1 = 0; /* Reserved for future use */
> >           regs->x2 = 0; /* Reserved for future use */
> >           regs->x3 = 0; /* Reserved for future use */
> > @@ -2251,6 +2205,64 @@ int __init construct_dom0(struct domain *d)
> >       return 0;
> >   }
> >   +int __init construct_dom0(struct domain *d)
> > +{
> > +    const struct bootcmdline *kernel =
> > boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
> > +    struct kernel_info kinfo = {};
> > +    int rc;
> > +
> > +    /* Sanity! */
> > +    BUG_ON(d->domain_id != 0);
> > +
> > +    printk("*** LOADING DOMAIN 0 ***\n");
> > +    if ( dom0_mem <= 0 )
> > +    {
> > +        warning_add("PLEASE SPECIFY dom0_mem PARAMETER - USING 512M FOR
> > NOW\n");
> > +        dom0_mem = MB(512);
> > +    }
> > +
> > +    iommu_hwdom_init(d);
> > +
> > +    d->max_pages = ~0U;
> > +
> > +    kinfo.unassigned_mem = dom0_mem;
> > +    kinfo.d = d;
> > +
> > +    rc = kernel_probe(&kinfo, NULL);
> > +    if ( rc < 0 )
> > +        return rc;
> > +
> > +    kinfo.cmdline = kernel != NULL ? &kernel->cmdline[0] : NULL;
> > +#ifdef CONFIG_ARM_64
> > +    /* type must be set before allocate_memory */
> > +    d->arch.type = kinfo.type;
> > +#endif
> > +    allocate_memory(d, &kinfo);
> > +    find_gnttab_region(d, &kinfo);
> > +
> > +    /* Map extra GIC MMIO, irqs and other hw stuffs to dom0. */
> > +    rc = gic_map_hwdom_extra_mappings(d);
> > +    if ( rc < 0 )
> > +        return rc;
> > +
> > +    rc = platform_specific_mapping(d);
> > +    if ( rc < 0 )
> > +        return rc;
> > +
> > +    if ( acpi_disabled )
> > +        rc = prepare_dtb_hwdom(d, &kinfo);
> > +    else
> > +        rc = prepare_acpi(d, &kinfo);
> > +
> > +    if ( rc < 0 )
> > +        return rc;
> > +
> > +
> 
> Spurious newline.
> 
> > +    rc = __construct_domain(d, &kinfo);
> > +    discard_initial_modules();
> 
> Newline here please.

OK


> > +    return rc;
> > +}
> > +
> >   /*
> >    * Local variables:
> >    * mode: C
> > 
> 
> Cheers,
> 
> -- 
> Julien Grall
> 

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

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

* Re: [PATCH v3 13/25] xen/arm: introduce create_domUs
  2018-08-13 10:23   ` Julien Grall
@ 2018-08-15 19:37     ` Stefano Stabellini
  0 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-08-15 19:37 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov,
	andrew.cooper3, xen-devel, jbeulich

On Mon, 13 Aug 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 01/08/18 00:27, Stefano Stabellini wrote:
> > Call a new function, "create_domUs", from setup_xen to start DomU VMs.
> > 
> > Introduce support for the "xen,domU" compatible node on device tree.
> > Create new DomU VMs based on the information found on device tree under
> > "xen,domU". Calls construct_domU for each domain.
> > 
> > Introduce a simple global variable named max_init_domid to keep track of
> > the initial allocated domids. It holds the max domid among the initial
> > domains.
> > 
> > Move the discard_initial_modules after DomUs have been built.
> > 
> > First create domUs, then start dom0 -- no point in trying to start dom0
> > when the cpu is busy.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > CC: andrew.cooper3@citrix.com
> > CC: jbeulich@suse.com
> > ---
> > Changes in v3:
> > - move patch earlier and introduce empty construct_domU to fix bisection
> >    builds
> > - fix max_init_domid to actually hold the max domid among initial
> >    domains (instead of max_domid + 1)
> > - move domain_unpause_by_systemcontroller(dom0) after creating domUs
> > 
> > Changes in v2:
> > - coding style
> > - set nr_spis to 32
> > - introduce create_domUs
> > ---
> >   xen/arch/arm/domain_build.c | 42
> > +++++++++++++++++++++++++++++++++++++++---
> >   xen/arch/arm/setup.c        |  7 ++++++-
> >   xen/include/asm-arm/setup.h |  3 +++
> >   xen/include/asm-x86/setup.h |  2 ++
> >   4 files changed, 50 insertions(+), 4 deletions(-)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 0835340..8f7ac54 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -7,6 +7,7 @@
> >   #include <asm/irq.h>
> >   #include <asm/regs.h>
> >   #include <xen/errno.h>
> > +#include <xen/err.h>
> >   #include <xen/device_tree.h>
> >   #include <xen/libfdt/libfdt.h>
> >   #include <xen/guest_access.h>
> > @@ -2205,6 +2206,43 @@ static int __init __construct_domain(struct domain
> > *d, struct kernel_info *kinfo
> >       return 0;
> >   }
> >   +static int __init construct_domU(struct domain *d, struct dt_device_node
> > *node)
> 
> AFAICT, the node is not going to be modified. So it should be const here.

OK


> > +{
> > +    return 0;
> 
> As Jan said, this should return an error until it is been implemented.

OK


> > +}
> > +
> > +void __init create_domUs(void)
> > +{
> > +    struct dt_device_node *node;
> > +    struct dt_device_node *chosen = dt_find_node_by_name(dt_host,
> > "chosen");
> 
> Same here, you want them to be const.

OK


> > +
> > +    if ( chosen != NULL )
> 
> I would prefer if we don't introduce another indentation level by inverting
> the condition.
> 
> Also, it is very unlikely to not have the chosen node. So it might be better
> to turn this into a panic/BUG_ON.

OK


> > +    {
> > +        dt_for_each_child_node(chosen, node)
> > +        {
> > +            struct domain *d;
> > +            struct xen_domctl_createdomain d_cfg = {
> > +                .arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE,
> > +                .arch.nr_spis = 32,
> > +            };
> > +
> > +            if ( !dt_device_is_compatible(node, "xen,domain") )
> > +                continue;
> > +
> > +            d = domain_create(++max_init_domid, &d_cfg, false);
> > +            if ( IS_ERR(d) )
> > +                panic("Error creating domain %s", dt_node_name(node));
> > +
> > +            d->is_console = 1;
> > +
> > +            if ( construct_domU(d, node) != 0 )
> > +                panic("Could not set up domain %s", dt_node_name(node));
> > +
> > +            domain_unpause_by_systemcontroller(d);
> > +        }
> > +    }
> > +}
> > +
> >   int __init construct_dom0(struct domain *d)
> >   {
> >       const struct bootcmdline *kernel =
> > boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
> > @@ -2258,9 +2296,7 @@ int __init construct_dom0(struct domain *d)
> >           return rc;
> >     -    rc = __construct_domain(d, &kinfo);
> > -    discard_initial_modules();
> > -    return rc;
> > +    return __construct_domain(d, &kinfo);
> >   }
> >     /*
> > diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> > index c320df9..096484f 100644
> > --- a/xen/arch/arm/setup.c
> > +++ b/xen/arch/arm/setup.c
> > @@ -63,8 +63,11 @@ static unsigned long opt_xenheap_megabytes __initdata;
> >   integer_param("xenheap_megabytes", opt_xenheap_megabytes);
> >   #endif
> >   +domid_t __read_mostly max_init_domid = 0;
> > +
> >   static __used void init_done(void)
> >   {
> > +    discard_initial_modules();
> >       free_init_memory();
> >       startup_cpu_idle_loop();
> >   }
> > @@ -894,7 +897,7 @@ void __init start_xen(unsigned long boot_phys_offset,
> >       dom0_cfg.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
> >       dom0_cfg.arch.nr_spis = gic_number_lines() - 32;
> >   -    dom0 = domain_create(0, &dom0_cfg, true);
> > +    dom0 = domain_create(max_init_domid, &dom0_cfg, true);
> >       if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
> >               panic("Error creating domain 0");
> >   @@ -915,6 +918,8 @@ void __init start_xen(unsigned long boot_phys_offset,
> >       /* Must be done past setting system_state. */
> >       unregister_init_virtual_region();
> >   +    create_domUs();
> > +
> >       domain_unpause_by_systemcontroller(dom0);
> >         /* Switch on to the dynamically allocated stack for the idle vcpu
> > diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
> > index 4551f72..d9cd8e1 100644
> > --- a/xen/include/asm-arm/setup.h
> > +++ b/xen/include/asm-arm/setup.h
> > @@ -67,6 +67,8 @@ struct bootinfo {
> >     extern struct bootinfo bootinfo;
> >   +extern domid_t max_init_domid;
> > +
> >   void arch_init_memory(void);
> >     void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len);
> > @@ -83,6 +85,7 @@ void acpi_create_efi_mmap_table(struct domain *d,
> >   int acpi_make_efi_nodes(void *fdt, struct membank tbl_add[]);
> >     int construct_dom0(struct domain *d);
> > +void __init create_domUs(void);
> >     void discard_initial_modules(void);
> >   void dt_unreserved_regions(paddr_t s, paddr_t e,
> > diff --git a/xen/include/asm-x86/setup.h b/xen/include/asm-x86/setup.h
> > index 8d4b9ee..c0bd86f 100644
> > --- a/xen/include/asm-x86/setup.h
> > +++ b/xen/include/asm-x86/setup.h
> > @@ -66,4 +66,6 @@ extern bool opt_dom0_shadow;
> >   #endif
> >   extern bool dom0_pvh;
> >   +#define max_init_domid (0)
> > +
> >   #endif
> > 
> 
> Cheers,
> 
> -- 
> Julien Grall
> 

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

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

* Re: [PATCH v3 13/25] xen/arm: introduce create_domUs
  2018-08-13 10:55   ` Julien Grall
@ 2018-08-15 20:04     ` Stefano Stabellini
  2018-08-16  9:03       ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-08-15 20:04 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov,
	andrew.cooper3, xen-devel, jbeulich

On Mon, 13 Aug 2018, Julien Grall wrote:
> On 01/08/18 00:27, Stefano Stabellini wrote:
> > Call a new function, "create_domUs", from setup_xen to start DomU VMs.
> > 
> > Introduce support for the "xen,domU" compatible node on device tree.
> > Create new DomU VMs based on the information found on device tree under
> > "xen,domU". Calls construct_domU for each domain.
> > 
> > Introduce a simple global variable named max_init_domid to keep track of
> > the initial allocated domids. It holds the max domid among the initial
> > domains.
> > 
> > Move the discard_initial_modules after DomUs have been built.
> > 
> > First create domUs, then start dom0 -- no point in trying to start dom0
> > when the cpu is busy.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > CC: andrew.cooper3@citrix.com
> > CC: jbeulich@suse.com
> > ---
> > Changes in v3:
> > - move patch earlier and introduce empty construct_domU to fix bisection
> >    builds
> > - fix max_init_domid to actually hold the max domid among initial
> >    domains (instead of max_domid + 1)
> > - move domain_unpause_by_systemcontroller(dom0) after creating domUs
> > 
> > Changes in v2:
> > - coding style
> > - set nr_spis to 32
> > - introduce create_domUs
> > ---
> >   xen/arch/arm/domain_build.c | 42
> > +++++++++++++++++++++++++++++++++++++++---
> >   xen/arch/arm/setup.c        |  7 ++++++-
> >   xen/include/asm-arm/setup.h |  3 +++
> >   xen/include/asm-x86/setup.h |  2 ++
> >   4 files changed, 50 insertions(+), 4 deletions(-)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 0835340..8f7ac54 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -7,6 +7,7 @@
> >   #include <asm/irq.h>
> >   #include <asm/regs.h>
> >   #include <xen/errno.h>
> > +#include <xen/err.h>
> >   #include <xen/device_tree.h>
> >   #include <xen/libfdt/libfdt.h>
> >   #include <xen/guest_access.h>
> > @@ -2205,6 +2206,43 @@ static int __init __construct_domain(struct domain
> > *d, struct kernel_info *kinfo
> >       return 0;
> >   }
> >   +static int __init construct_domU(struct domain *d, struct dt_device_node
> > *node)
> > +{
> > +    return 0;
> > +}
> > +
> > +void __init create_domUs(void)
> > +{
> > +    struct dt_device_node *node;
> > +    struct dt_device_node *chosen = dt_find_node_by_name(dt_host,
> > "chosen");
> > +
> > +    if ( chosen != NULL )
> > +    {
> > +        dt_for_each_child_node(chosen, node)
> > +        {
> > +            struct domain *d;
> > +            struct xen_domctl_createdomain d_cfg = {
> > +                .arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE,
> > +                .arch.nr_spis = 32,
> 
> AFAICT, when creating DomU from the toolstack nr_spis will be 0. So why 32
> here?

Legacy from debug code. It should be 0, unless vpl011 is enabled, in
which case it should be 1.


> > +            };
> > +
> > +            if ( !dt_device_is_compatible(node, "xen,domain") )
> > +                continue;
> > +
> > +            d = domain_create(++max_init_domid, &d_cfg, false);
> > +            if ( IS_ERR(d) )
> > +                panic("Error creating domain %s", dt_node_name(node));
> > +
> > +            d->is_console = 1;
> > +
> > +            if ( construct_domU(d, node) != 0 )
> > +                panic("Could not set up domain %s", dt_node_name(node));
> > +
> > +            domain_unpause_by_systemcontroller(d);
> > +        }
> > +    }
> > +}
> > +
> >   int __init construct_dom0(struct domain *d)
> >   {
> >       const struct bootcmdline *kernel =
> > boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
> > @@ -2258,9 +2296,7 @@ int __init construct_dom0(struct domain *d)
> >           return rc;
> >     -    rc = __construct_domain(d, &kinfo);
> > -    discard_initial_modules();
> > -    return rc;
> > +    return __construct_domain(d, &kinfo);
> >   }
> >     /*
> > diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> > index c320df9..096484f 100644
> > --- a/xen/arch/arm/setup.c
> > +++ b/xen/arch/arm/setup.c
> > @@ -63,8 +63,11 @@ static unsigned long opt_xenheap_megabytes __initdata;
> >   integer_param("xenheap_megabytes", opt_xenheap_megabytes);
> >   #endif
> >   +domid_t __read_mostly max_init_domid = 0;
> > +
> >   static __used void init_done(void)
> >   {
> > +    discard_initial_modules();
> >       free_init_memory();
> >       startup_cpu_idle_loop();
> >   }
> > @@ -894,7 +897,7 @@ void __init start_xen(unsigned long boot_phys_offset,
> >       dom0_cfg.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
> >       dom0_cfg.arch.nr_spis = gic_number_lines() - 32;
> >   -    dom0 = domain_create(0, &dom0_cfg, true);
> > +    dom0 = domain_create(max_init_domid, &dom0_cfg, true);
> >       if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
> >               panic("Error creating domain 0");
> >   @@ -915,6 +918,8 @@ void __init start_xen(unsigned long boot_phys_offset,
> >       /* Must be done past setting system_state. */
> >       unregister_init_virtual_region();
> >   +    create_domUs();
> > +
> >       domain_unpause_by_systemcontroller(dom0);
> >         /* Switch on to the dynamically allocated stack for the idle vcpu
> > diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
> > index 4551f72..d9cd8e1 100644
> > --- a/xen/include/asm-arm/setup.h
> > +++ b/xen/include/asm-arm/setup.h
> > @@ -67,6 +67,8 @@ struct bootinfo {
> >     extern struct bootinfo bootinfo;
> >   +extern domid_t max_init_domid;
> > +
> >   void arch_init_memory(void);
> >     void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len);
> > @@ -83,6 +85,7 @@ void acpi_create_efi_mmap_table(struct domain *d,
> >   int acpi_make_efi_nodes(void *fdt, struct membank tbl_add[]);
> >     int construct_dom0(struct domain *d);
> > +void __init create_domUs(void);
> >     void discard_initial_modules(void);
> >   void dt_unreserved_regions(paddr_t s, paddr_t e,
> > diff --git a/xen/include/asm-x86/setup.h b/xen/include/asm-x86/setup.h
> > index 8d4b9ee..c0bd86f 100644
> > --- a/xen/include/asm-x86/setup.h
> > +++ b/xen/include/asm-x86/setup.h
> > @@ -66,4 +66,6 @@ extern bool opt_dom0_shadow;
> >   #endif
> >   extern bool dom0_pvh;
> >   +#define max_init_domid (0)
> > +
> >   #endif
> > 
> 
> -- 
> Julien Grall
> 

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

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

* Re: [PATCH v3 14/25] xen/arm: introduce construct_domU
  2018-08-13 10:55   ` Julien Grall
@ 2018-08-15 20:21     ` Stefano Stabellini
  0 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-08-15 20:21 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Mon, 13 Aug 2018, Julien Grall wrote:
> Hi,
> 
> Title: You don't really introduce "construct_domU". You implement it. So a
> better title would be "Implement construct_domU".

OK


> On 01/08/18 00:27, Stefano Stabellini wrote:
> > Similar to construct_dom0, construct_domU creates a barebone DomU guest.
> > 
> > The device tree node passed as argument is compatible "xen,domain", see
> > docs/misc/arm/device-tree/booting.txt.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > 
> > ---
> > Changes in v3:
> > - move setting type before allocate_memory
> > - add ifdef around it and a comment
> > 
> > Changes in v2:
> > - rename mem to memory
> > - make cpus and memory mandatory
> > - remove wront comment from commit message
> > - cpus and memory are read as integers
> > - read the vpl011 option
> > ---
> >   xen/arch/arm/domain_build.c | 36 +++++++++++++++++++++++++++++++++++-
> >   1 file changed, 35 insertions(+), 1 deletion(-)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 8f7ac54..101cca2 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -2208,7 +2208,41 @@ static int __init __construct_domain(struct domain
> > *d, struct kernel_info *kinfo
> >     static int __init construct_domU(struct domain *d, struct dt_device_node
> > *node)
> >   {
> > -    return 0;
> > +    struct kernel_info kinfo = {};
> > +    int rc;
> > +    u32 mem;
> > +
> > +    printk("*** LOADING DOMU ***\n");
> > +
> > +    rc = dt_property_read_u32(node, "cpus", &d->max_vcpus);
> > +    if ( !rc )
> > +        return -EINVAL;
> 
> For a user PoV this will be difficult to differentiate between the -EINVAL
> here and the only below.
> 
> It is probably useful to log some error message. Similarly you might want to
> add some print telling the information about the domain created.

OK


> > +
> > +    rc = dt_property_read_u32(node, "memory", &mem);
> 
> I don't think 32-bit integer is going to be enough to cover all the case.
> Nowadays Arm supports up to 52-bits Address-Space.
> 
> So it would be best to cover all the case and use 64-bit here. That would also
> mean updating the documentation.

We need to support the whole address space, but unfortunately it means
have to add one more cell to the memory attribute, becoming less
intuitive to write. Even if we switched from KB to MB for the unit, we
would still need two cells from my calculations.

Are you sure I cannot convince you to switch to a string format for the
memory attribute where users can specify the unit (KB, MB, GB, etc.),
like they do today with the mem= command line?


> > +    if ( !rc ) > +        return -EINVAL;
> > +    kinfo.unassigned_mem = (paddr_t)mem << 10;
> 
> kinfo.unassigned_mem = KB(mem);

KB() only works for numbers, it is defined as: (_AC(_kb, ULL) << 10)


> > +
> > +    d->vcpu = xzalloc_array(struct vcpu *, d->max_vcpus);
> > +    if ( !d->vcpu )
> > +        return -ENOMEM;;
> > +    if ( alloc_vcpu(d, 0, 0) == NULL )
> > +        return -ENOMEM;
> > +    d->max_pages = ~0U;
> > +
> > +    kinfo.d = d;
> > +
> > +    rc = kernel_probe(&kinfo, node);
> > +    if ( rc < 0 )
> > +        return rc;
> > +
> > +#ifdef CONFIG_ARM_64
> > +    /* type must be set before allocate memory */
> > +    d->arch.type = kinfo.type;
> > +#endif
> > +    allocate_memory(d, &kinfo);
> > +
> > +    return __construct_domain(d, &kinfo);
> >   }
> >     void __init create_domUs(void)

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

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

* Re: [PATCH v3 16/25] xen/arm: rename allocate_memory to allocate_memory_11
  2018-08-13 10:57   ` Julien Grall
@ 2018-08-15 20:26     ` Stefano Stabellini
  2018-08-16  9:08       ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-08-15 20:26 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Mon, 13 Aug 2018, Julien Grall wrote:
> Hi,
> 
> On 01/08/18 00:27, Stefano Stabellini wrote:
> > allocate_memory only deals with directly mapped memory. Rename it to
> > allocate_memory_11.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > 
> > ---
> > Changes in v3:
> > - add patch
> > ---
> >   xen/arch/arm/domain_build.c | 7 ++++---
> >   1 file changed, 4 insertions(+), 3 deletions(-)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 066dd75..ab72c36 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -244,7 +244,8 @@ fail:
> >    * (as described above) we allow higher allocations and continue until
> >    * that runs out (or we have allocated sufficient dom0 memory).
> >    */
> > -static void __init allocate_memory(struct domain *d, struct kernel_info
> > *kinfo)
> > +static void __init allocate_memory_11(struct domain *d,
> > +                                      struct kernel_info *kinfo)
> >   {
> >       const unsigned int min_low_order =
> >           get_order_from_bytes(min_t(paddr_t, dom0_mem, MB(128)));
> > @@ -2240,7 +2241,7 @@ static int __init construct_domU(struct domain *d,
> > struct dt_device_node *node)
> >       /* type must be set before allocate memory */
> >       d->arch.type = kinfo.type;
> >   #endif
> > -    allocate_memory(d, &kinfo);
> > +    allocate_memory_11(d, &kinfo);
> 
> I don't think your patches are correctly ordered. This is adding a lot of
> confusion in the review because the DomU memory layout is fixed, yet here you
> rename the function to 1:1 mapping.
> 
> Most likely you want to do add the new memory function before introducing
> DomU.

If I do that there will be no callers for the new function and
compilation fails. Bisectibility is the reason why I had to reorder the
patches.

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

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

* Re: [PATCH v3 18/25] xen/arm: generate a simple device tree for domUs
  2018-08-13 11:07   ` Julien Grall
@ 2018-08-15 20:47     ` Stefano Stabellini
  0 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-08-15 20:47 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Mon, 13 Aug 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 01/08/18 00:28, Stefano Stabellini wrote:
> > Introduce functions to generate a basic domU device tree, similar to the
> > existing functions in tools/libxl/libxl_arm.c.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > ---
> > Changes in v3:
> > - remove CONFIG_ACPI for make_chosen_node
> > - remove make_hypervisor_node until all Xen related functionalities
> >    (evtchns, grant table, etc.) work correctly
> > 
> > Changes in v2:
> > - move prepare_dtb rename to previous patch
> > - use switch for the gic version
> > - use arm,gic-400 instead of arm,cortex-a15-gic
> > - add @unit-address in the gic node name
> > - add comment on DOMU_DTB_SIZE
> > ---
> >   xen/arch/arm/domain_build.c | 211
> > +++++++++++++++++++++++++++++++++++++++++++-
> >   1 file changed, 209 insertions(+), 2 deletions(-)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index dfa74e4..167a56e 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -1057,7 +1057,6 @@ static int __init make_timer_node(const struct domain
> > *d, void *fdt,
> >       return res;
> >   }
> >   -#ifdef CONFIG_ACPI
> >   /*
> >    * This function is used as part of the device tree generation for Dom0
> >    * on ACPI systems, and DomUs started directly from Xen based on device
> > @@ -1103,7 +1102,6 @@ static int __init make_chosen_node(const struct
> > kernel_info *kinfo)
> >         return res;
> >   }
> > -#endif
> >     static int __init map_irq_to_domain(struct domain *d, unsigned int irq,
> >                                       bool need_mapping, const char
> > *devname)
> > @@ -1496,6 +1494,211 @@ static int __init handle_node(struct domain *d,
> > struct kernel_info *kinfo,
> >       return res;
> >   }
> >   +static int __init make_gic_domU_node(const struct domain *d, void *fdt,
> > int addrcells, int sizecells)
> > +{
> > +    int res = 0;
> > +    int reg_size = addrcells + sizecells;
> > +    int nr_cells = reg_size * 2;
> > +    __be32 reg[nr_cells];
> > +    __be32 *cells;
> 
> You are trying to be save a few lines by handling both GICv2 and GICv3 node in
> a single function. But this only thing it adds is confusion when reading the
> code.
> 
> Please have two functions (one for each GIC version) to generate the DT. This
> would also help to add ITS/GICv2m support in the future.

OK


> > +
> > +    switch ( gic_hw_version() )
> > +    {
> > +    case GIC_V3:
> > +        res = fdt_begin_node(fdt,
> > "interrupt-controller@"__stringify(GUEST_GICV3_GICD_BASE));
> > +        break;
> > +    case GIC_V2:
> > +        res = fdt_begin_node(fdt,
> > "interrupt-controller@"__stringify(GUEST_GICD_BASE));
> > +        break;
> > +    default:
> > +        panic("Unsupported GIC version");
> > +    }
> > +
> > +    if ( res )
> > +        return res;
> > +
> > +    res = fdt_property_cell(fdt, "#address-cells", 0);
> > +    if ( res )
> > +        return res;
> > +
> > +    res = fdt_property_cell(fdt, "#interrupt-cells", 3);
> > +    if ( res )
> > +        return res;
> > +
> > +    res = fdt_property(fdt, "interrupt-controller", NULL, 0);
> > +    if ( res )
> > +        return res;
> > +
> > +    switch ( gic_hw_version() )
> > +    {
> > +    case GIC_V3:
> > +    {
> > +        const uint64_t gicd_base = GUEST_GICV3_GICD_BASE;
> > +        const uint64_t gicd_size = GUEST_GICV3_GICD_SIZE;
> > +        const uint64_t gicr0_base = GUEST_GICV3_GICR0_BASE;
> > +        const uint64_t gicr0_size = GUEST_GICV3_GICR0_SIZE;
> 
> I am not entirely convinced of the usefulness of those variables.

I can remove

> > +
> > +        res = fdt_property_string(fdt, "compatible", "arm,gic-v3");
> > +        if ( res )
> > +            return res;
> > +
> > +        cells = &reg[0];
> > +        dt_child_set_range(&cells, addrcells, sizecells, gicd_base,
> > gicd_size);
> > +        dt_child_set_range(&cells, addrcells, sizecells, gicr0_base,
> > gicr0_size);
> > +        res = fdt_property(fdt, "reg", reg, sizeof(reg));
> > +        break;
> > +    }
> > +    case GIC_V2:
> > +    {
> > +        const uint64_t gicd_base = GUEST_GICD_BASE;
> > +        const uint64_t gicd_size = GUEST_GICD_SIZE;
> > +        const uint64_t gicc_base = GUEST_GICC_BASE;
> > +        const uint64_t gicc_size = GUEST_GICC_SIZE;
> 
> Same here.
>
> > +
> > +        res = fdt_property_string(fdt, "compatible", "arm,gic-400");
> > +        if ( res )
> > +            return res;
> > +
> > +        cells = &reg[0];
> > +        dt_child_set_range(&cells, addrcells, sizecells, gicd_base,
> > gicd_size);
> > +        dt_child_set_range(&cells, addrcells, sizecells, gicc_base,
> > gicc_size);
> > +        break;
> > +    }
> > +    default:
> > +        break;
> > +    }
> > +
> > +    res = fdt_property(fdt, "reg", reg, sizeof(reg));
> > +    if (res)
> > +        return res;
> > +
> > +    res = fdt_property_cell(fdt, "linux,phandle", GUEST_PHANDLE_GIC);
> > +    if (res)
> > +        return res;
> > +
> > +    res = fdt_property_cell(fdt, "phandle", GUEST_PHANDLE_GIC);
> > +    if (res)
> > +        return res;
> > +
> > +    res = fdt_end_node(fdt);
> > +
> > +    return res;
> > +}
> > +
> > +static int __init make_timer_domU_node(const struct domain *d, void *fdt)
> > +{
> > +    int res;
> > +    gic_interrupt_t intrs[3];
> > +
> > +    res = fdt_begin_node(fdt, "timer");
> > +    if ( res )
> > +        return res;
> > +
> > +    if (!is_64bit_domain(d))
> 
> Coding style:
> 
> if ( ... )

OK


> > +    {
> > +        res = fdt_property_string(fdt, "compatible", "arm,armv7-timer");
> > +        if ( res )
> > +            return res;
> > +    } else {
> 
> Coding style:
> 
> }
> else
> {

OK


> > +        res = fdt_property_string(fdt, "compatible", "arm,armv8-timer");
> > +        if ( res )
> > +            return res;
> > +    }
> > +
> > +    set_interrupt_ppi(intrs[0], GUEST_TIMER_PHYS_S_PPI, 0xf,
> > DT_IRQ_TYPE_LEVEL_LOW);
> > +    set_interrupt_ppi(intrs[1], GUEST_TIMER_PHYS_NS_PPI, 0xf,
> > DT_IRQ_TYPE_LEVEL_LOW);
> > +    set_interrupt_ppi(intrs[2], GUEST_TIMER_VIRT_PPI, 0xf,
> > DT_IRQ_TYPE_LEVEL_LOW);
> > +
> > +    res = fdt_property(fdt, "interrupts", intrs, sizeof (intrs[0]) * 3);
> > +    if ( res )
> > +        return res;
> > +
> > +    res = fdt_property_cell(fdt, "interrupt-parent",
> > +                            GUEST_PHANDLE_GIC);
> > +    if (res)
> > +        return res;
> > +
> > +    res = fdt_end_node(fdt);
> 
> Newline here please.

OK


> > +    return res;
> > +}
> > +
> > +/*
> > + * The max size for DT is 2MB. However, the generated DT is small, 4KB
> > + * are enough for now, but we might have to increase it in the feature.
> 
> s/feature/future/

*blush*


> > + */
> > +#define DOMU_DTB_SIZE 4096
> > +static int __init prepare_dtb_domU(struct domain *d, struct kernel_info
> > *kinfo)
> > +{
> > +    int addrcells, sizecells;
> > +    int ret;
> > +
> > +    addrcells = dt_child_n_addr_cells(dt_host); > +    sizecells =
> > dt_child_n_size_cells(dt_host);
> 
> Why do you use the host DT to find out the the #address-cells and #size-cells?
> Should not this be independent?

Yes, that is a mistake. I'll fix.


> > +
> > +    kinfo->fdt = xmalloc_bytes(DOMU_DTB_SIZE);
> > +    if ( kinfo->fdt == NULL )
> > +        return -ENOMEM;
> > +
> > +    ret = fdt_create(kinfo->fdt, DOMU_DTB_SIZE);
> > +    if ( ret < 0 )
> > +        goto err;
> > +
> > +    ret = fdt_finish_reservemap(kinfo->fdt);
> > +    if ( ret < 0 )
> > +        goto err;
> > +
> > +    ret = fdt_begin_node(kinfo->fdt, "/");
> > +    if ( ret < 0 )
> > +        goto err;
> > +
> > +    ret = fdt_property_cell(kinfo->fdt, "#address-cells", addrcells);
> > +    if ( ret )
> > +        goto err;
> > +
> > +    ret = fdt_property_cell(kinfo->fdt, "#size-cells", sizecells);
> > +    if ( ret )
> > +        goto err;
> > +
> > +    ret = make_chosen_node(kinfo);
> > +    if ( ret )
> > +        goto err;
> > +
> > +    ret = make_psci_node(kinfo->fdt, NULL);
> > +    if ( ret )
> > +        goto err;
> > +
> > +    ret = make_cpus_node(d, kinfo->fdt, NULL);
> > +    if ( ret )
> > +        goto err;
> > +
> > +    ret = make_memory_node(d, kinfo->fdt, addrcells, sizecells, kinfo);
> > +    if ( ret )
> > +        goto err;
> > +
> > +    ret = make_gic_domU_node(d, kinfo->fdt, addrcells, sizecells);
> > +    if ( ret )
> > +        goto err;
> > +
> > +    ret = make_timer_domU_node(d, kinfo->fdt);
> > +    if ( ret )
> > +        goto err;
> > +
> > +    ret = fdt_end_node(kinfo->fdt);
> > +    if ( ret < 0 )
> > +        goto err;
> > +
> > +    ret = fdt_finish(kinfo->fdt);
> > +    if ( ret < 0 )
> > +        goto err;
> > +
> > +    return 0;
> > +
> > +  err:
> > +    printk("Device tree generation failed (%d).\n", ret);
> > +    xfree(kinfo->fdt);
> 
> Newline here please.

OK


> > +    return -EINVAL;
> > +}
> > +
> >   static int __init prepare_dtb_hwdom(struct domain *d, struct kernel_info
> > *kinfo)
> >   {
> >       const p2m_type_t default_p2mt = p2m_mmio_direct_c;
> > @@ -2366,6 +2569,10 @@ static int __init construct_domU(struct domain *d,
> > struct dt_device_node *node)
> >   #endif
> >       allocate_memory(d, &kinfo);
> >   +    rc = prepare_dtb_domU(d, &kinfo);
> > +    if ( rc < 0 )
> > +        return rc;
> > +
> >       return __construct_domain(d, &kinfo);
> >   }
> >   
> 
> Cheers,
> 
> -- 
> Julien Grall
> 

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

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

* Re: [PATCH v3 19/25] xen/arm: generate vpl011 node on device tree for domU
  2018-08-13 11:20   ` Julien Grall
@ 2018-08-15 23:23     ` Stefano Stabellini
  0 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-08-15 23:23 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Mon, 13 Aug 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 01/08/18 00:28, Stefano Stabellini wrote:
> > Introduce vpl011 support to guests started from Xen: it provides a
> > simple way to print output from a guest, as most guests come with a
> > pl011 driver. It is also able to provide a working console with
> > interrupt support.
> > 
> > The UART exposed to the guest is a SBSA compatible UART and not a PL011.
> > SBSA UART is a subset of PL011 r1p5. A full PL011 implementation in Xen
> > would just be too difficult, so guests may require some drivers changes.
> > 
> > Enable vpl011 conditionally if the user requested it.
> > 
> > Make set_interrupt_ppi able to handle non-PPI and rename it
> > set_interrupt.
> 
> It would have been better to have this change in a separate patch.

I'll separate it


> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > ---
> > Changes in v3:
> > - use bool
> > - retain BUG_ON(irq < 16)
> > - add vpl011 bool to kinfo
> > - return error of vpl011 is required but CONFIG_SBSA_VUART_CONSOLE is
> >    missing
> > 
> > Changes in v2:
> > - code style fixes
> > - make set_interrupt_ppi generic
> > - rename set_interrupt_ppi to set_interrupt
> > - only make the vpl011 node if the option was enabled
> > ---
> >   xen/arch/arm/domain_build.c | 95
> > ++++++++++++++++++++++++++++++++++++++-------
> >   xen/arch/arm/kernel.h       |  3 ++
> >   2 files changed, 83 insertions(+), 15 deletions(-)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 167a56e..f9fa484 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -619,19 +619,20 @@ static int __init write_properties(struct domain *d,
> > struct kernel_info *kinfo,
> >     typedef __be32 gic_interrupt_t[3];
> >   -static void __init set_interrupt_ppi(gic_interrupt_t interrupt,
> > -                                     unsigned int irq,
> > -                                     unsigned int cpumask,
> > -                                     unsigned int level)
> > +static void __init set_interrupt(gic_interrupt_t interrupt,
> > +                                 unsigned int irq,
> > +                                 unsigned int cpumask,
> > +                                 unsigned int level)
> >   {
> >       __be32 *cells = interrupt;
> > +    bool is_ppi = !!(irq < 32);
> >         BUG_ON(irq < 16);
> > -    BUG_ON(irq >= 32);
> > +    irq -= (is_ppi) ? 16: 32; /* PPIs start at 16, SPIs at 32 */
> >         /* See linux
> > Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt */
> > -    dt_set_cell(&cells, 1, 1); /* is a PPI */
> > -    dt_set_cell(&cells, 1, irq - 16); /* PPIs start at 16 */
> > +    dt_set_cell(&cells, 1, is_ppi); /* is a PPI? */
> > +    dt_set_cell(&cells, 1, irq);
> >       dt_set_cell(&cells, 1, (cpumask << 8) | level);
> >   }
> >   @@ -752,7 +753,7 @@ static int __init make_hypervisor_node(struct domain
> > *d,
> >        *  - All CPUs
> >        *  TODO: Handle properly the cpumask;
> >        */
> > -    set_interrupt_ppi(intr, d->arch.evtchn_irq, 0xf,
> > DT_IRQ_TYPE_LEVEL_LOW);
> > +    set_interrupt(intr, d->arch.evtchn_irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> >       res = fdt_property_interrupts(fdt, &intr, 1);
> >       if ( res )
> >           return res;
> > @@ -1029,15 +1030,15 @@ static int __init make_timer_node(const struct
> > domain *d, void *fdt,
> >         irq = timer_get_irq(TIMER_PHYS_SECURE_PPI);
> >       dt_dprintk("  Secure interrupt %u\n", irq);
> > -    set_interrupt_ppi(intrs[0], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> > +    set_interrupt(intrs[0], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> >         irq = timer_get_irq(TIMER_PHYS_NONSECURE_PPI);
> >       dt_dprintk("  Non secure interrupt %u\n", irq);
> > -    set_interrupt_ppi(intrs[1], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> > +    set_interrupt(intrs[1], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> >         irq = timer_get_irq(TIMER_VIRT_PPI);
> >       dt_dprintk("  Virt interrupt %u\n", irq);
> > -    set_interrupt_ppi(intrs[2], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> > +    set_interrupt(intrs[2], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
> >         res = fdt_property_interrupts(fdt, intrs, 3);
> >       if ( res )
> > @@ -1605,9 +1606,9 @@ static int __init make_timer_domU_node(const struct
> > domain *d, void *fdt)
> >               return res;
> >       }
> >   -    set_interrupt_ppi(intrs[0], GUEST_TIMER_PHYS_S_PPI, 0xf,
> > DT_IRQ_TYPE_LEVEL_LOW);
> > -    set_interrupt_ppi(intrs[1], GUEST_TIMER_PHYS_NS_PPI, 0xf,
> > DT_IRQ_TYPE_LEVEL_LOW);
> > -    set_interrupt_ppi(intrs[2], GUEST_TIMER_VIRT_PPI, 0xf,
> > DT_IRQ_TYPE_LEVEL_LOW);
> > +    set_interrupt(intrs[0], GUEST_TIMER_PHYS_S_PPI, 0xf,
> > DT_IRQ_TYPE_LEVEL_LOW);
> > +    set_interrupt(intrs[1], GUEST_TIMER_PHYS_NS_PPI, 0xf,
> > DT_IRQ_TYPE_LEVEL_LOW);
> > +    set_interrupt(intrs[2], GUEST_TIMER_VIRT_PPI, 0xf,
> > DT_IRQ_TYPE_LEVEL_LOW);
> >         res = fdt_property(fdt, "interrupts", intrs, sizeof (intrs[0]) * 3);
> >       if ( res )
> > @@ -1622,6 +1623,56 @@ static int __init make_timer_domU_node(const struct
> > domain *d, void *fdt)
> >       return res;
> >   }
> >   +#ifdef CONFIG_SBSA_VUART_CONSOLE
> > +static int __init make_vpl011_uart_node(const struct domain *d, void *fdt,
> > +                                 int addrcells, int sizecells)
> > +{
> > +    int res;
> > +    gic_interrupt_t intr;
> > +    int reg_size = addrcells + sizecells;
> > +    int nr_cells = reg_size;
> > +    __be32 reg[nr_cells];
> > +    __be32 *cells;
> > +
> > +    res = fdt_begin_node(fdt, "sbsa-pl011");
> 
> Node should contain the address in the name. Also, the name should be SBSA
> UART (which happens to be based on PL011 :)).

OK


> > +    if ( res )
> > +        return res;
> > +
> > +    res = fdt_property_string(fdt, "compatible", "arm,sbsa-uart");
> > +    if ( res )
> > +        return res;
> > +
> > +    cells = &reg[0];
> > +    dt_child_set_range(&cells, addrcells, sizecells, GUEST_PL011_BASE,
> > +                       GUEST_PL011_SIZE);
> > +    if ( res )
> > +        return res;
> > +    res = fdt_property(fdt, "reg", reg, sizeof(reg));
> > +    if ( res )
> > +        return res;
> > +
> > +    set_interrupt(intr, GUEST_VPL011_SPI, 0xf, DT_IRQ_TYPE_LEVEL_HIGH);
> > +
> > +    res = fdt_property(fdt, "interrupts", intr, sizeof (intr));
> > +    if ( res )
> > +        return res;
> > +
> > +    res = fdt_property_cell(fdt, "interrupt-parent",
> > +                            GUEST_PHANDLE_GIC);
> > +    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;
> > +}
> > +#endif
> > +
> >   /*
> >    * The max size for DT is 2MB. However, the generated DT is small, 4KB
> >    * are enough for now, but we might have to increase it in the feature.
> > @@ -1683,6 +1734,18 @@ static int __init prepare_dtb_domU(struct domain *d,
> > struct kernel_info *kinfo)
> >       if ( ret )
> >           goto err;
> >   +    if ( kinfo->vpl011 )
> > +    {
> > +#ifdef CONFIG_SBSA_VUART_CONSOLE
> > +        ret = make_vpl011_uart_node(d, kinfo->fdt, addrcells, sizecells);
> > +        if ( ret )
> > +            goto err;
> > +#else
> > +        ret = -EINVAL;
> > +        goto err;
> > +#endif
> 
> I would prefer:
> 
> 
> ret = -EINVAL
> #ifdef CONFIG_SBSA...
> 	ret = make...
> #endif
> 	if ( ret )
> 	  goto err;

Yes, that's better


> 
> > +    }
> > +
> >       ret = fdt_end_node(kinfo->fdt);
> >       if ( ret < 0 )
> >           goto err;
> > @@ -2537,7 +2600,7 @@ static int __init construct_domU(struct domain *d,
> > struct dt_device_node *node)
> >   {
> >       struct kernel_info kinfo = {};
> >       int rc;
> > -    u32 mem;
> > +    u32 mem, len;
> >         printk("*** LOADING DOMU ***\n");
> >   @@ -2550,6 +2613,8 @@ static int __init construct_domU(struct domain *d,
> > struct dt_device_node *node)
> >           return -EINVAL;
> >       kinfo.unassigned_mem = (paddr_t)mem << 10;
> >   +    kinfo.vpl011 = dt_get_property(node, "vpl011", &len) != NULL;
> > +
> >       d->vcpu = xzalloc_array(struct vcpu *, d->max_vcpus);
> >       if ( !d->vcpu )
> >           return -ENOMEM;;
> > diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
> > index 4a65289..9c9e568 100644
> > --- a/xen/arch/arm/kernel.h
> > +++ b/xen/arch/arm/kernel.h
> > @@ -33,6 +33,9 @@ struct kernel_info {
> >       paddr_t dtb_paddr;
> >       paddr_t initrd_paddr;
> >   +    /* Enable pl011 emulation */
> > +    bool vpl011;
> > +
> >       /* loader to use for this kernel */
> >       void (*load)(struct kernel_info *info);
> >       /* loader specific state */
> > 
> 
> Cheers,
> 
> -- 
> Julien Grall
> 

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

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

* Re: [PATCH v3 20/25] xen/arm: introduce a union in vpl011
  2018-08-13 11:24   ` Julien Grall
@ 2018-08-15 23:36     ` Stefano Stabellini
  0 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-08-15 23:36 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Mon, 13 Aug 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 01/08/18 00:28, Stefano Stabellini wrote:
> > Introduce a union in struct vpl011 to contain the console ring members.
> > A later patch will add another member of the union for the case where
> > the backend is in Xen.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > ---
> > Changes in v3:
> > - rename ring field to dom
> > 
> > Changes in v2:
> > - new patch
> > ---
> >   xen/arch/arm/vpl011.c        | 20 ++++++++++----------
> >   xen/include/asm-arm/vpl011.h |  8 ++++++--
> >   2 files changed, 16 insertions(+), 12 deletions(-)
> > 
> > diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> > index a281eab..e70c5ec 100644
> > --- a/xen/arch/arm/vpl011.c
> > +++ b/xen/arch/arm/vpl011.c
> > @@ -82,7 +82,7 @@ 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;
> > +    struct xencons_interface *intf = vpl011->dom.ring_buf;
> >       XENCONS_RING_IDX in_cons, in_prod;
> >         VPL011_LOCK(d, flags);
> > @@ -145,7 +145,7 @@ static uint8_t vpl011_read_data(struct domain *d)
> >   static void vpl011_update_tx_fifo_status(struct vpl011 *vpl011,
> >                                            unsigned int fifo_level)
> >   {
> > -    struct xencons_interface *intf = vpl011->ring_buf;
> > +    struct xencons_interface *intf = vpl011->dom.ring_buf;
> >       unsigned int fifo_threshold = sizeof(intf->out) -
> > SBSA_UART_FIFO_LEVEL;
> >         BUILD_BUG_ON(sizeof(intf->out) < SBSA_UART_FIFO_SIZE);
> > @@ -164,7 +164,7 @@ 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;
> > +    struct xencons_interface *intf = vpl011->dom.ring_buf;
> >       XENCONS_RING_IDX out_cons, out_prod;
> >         VPL011_LOCK(d, flags);
> > @@ -382,7 +382,7 @@ static void vpl011_data_avail(struct domain *d)
> >   {
> >       unsigned long flags;
> >       struct vpl011 *vpl011 = &d->arch.vpl011;
> > -    struct xencons_interface *intf = vpl011->ring_buf;
> > +    struct xencons_interface *intf = vpl011->dom.ring_buf;
> >       XENCONS_RING_IDX in_cons, in_prod, out_cons, out_prod;
> >       XENCONS_RING_IDX in_fifo_level, out_fifo_level;
> >   @@ -459,14 +459,14 @@ int domain_vpl011_init(struct domain *d, struct
> > vpl011_init_info *info)
> >       int rc;
> >       struct vpl011 *vpl011 = &d->arch.vpl011;
> >   -    if ( vpl011->ring_buf )
> > +    if ( vpl011->dom.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);
> > +                                  &vpl011->dom.ring_page,
> > +                                  &vpl011->dom.ring_buf);
> >       if ( rc < 0 )
> >           goto out;
> >   @@ -495,7 +495,7 @@ out2:
> >       vgic_free_virq(d, GUEST_VPL011_SPI);
> >     out1:
> > -    destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
> > +    destroy_ring_for_helper(&vpl011->dom.ring_buf, vpl011->dom.ring_page);
> >     out:
> >       return rc;
> > @@ -505,11 +505,11 @@ void domain_vpl011_deinit(struct domain *d)
> >   {
> >       struct vpl011 *vpl011 = &d->arch.vpl011;
> >   -    if ( !vpl011->ring_buf )
> > +    if ( !vpl011->dom.ring_buf )
> >           return;
> >         free_xen_event_channel(d, vpl011->evtchn);
> > -    destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
> > +    destroy_ring_for_helper(&vpl011->dom.ring_buf, vpl011->dom.ring_page);
> >   }
> >     /*
> > diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
> > index db95ff8..b873a29 100644
> > --- a/xen/include/asm-arm/vpl011.h
> > +++ b/xen/include/asm-arm/vpl011.h
> > @@ -31,8 +31,12 @@
> >   #define SBSA_UART_FIFO_SIZE 32
> >     struct vpl011 {
> > -    void *ring_buf;
> > -    struct page_info *ring_page;
> > +    union {
> 
> If you name the union vpl011_backend it would be clearer that this deal with
> backend information. Or even just avoiding the anonymous union by naming it
> "backend".

OK

> > +        struct {
> > +            void *ring_buf;
> > +            struct page_info *ring_page;
> > +        } dom;
> > +    };
> >       uint32_t    uartfr;         /* Flag register */
> >       uint32_t    uartcr;         /* Control register */
> >       uint32_t    uartimsc;       /* Interrupt mask register*/
> > 
> 
> Cheers,
> 
> -- 
> Julien Grall
> 

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

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

* Re: [PATCH v3 22/25] xen/arm: Allow vpl011 to be used by DomU
  2018-08-13 13:42   ` Julien Grall
@ 2018-08-15 23:41     ` Stefano Stabellini
  0 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-08-15 23:41 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Mon, 13 Aug 2018, Julien Grall wrote:
> On 01/08/18 00:28, Stefano Stabellini wrote:
> > Make vpl011 being able to be used without a userspace component in Dom0.
> > In that case, output is printed to the Xen serial and input is received
> > from the Xen serial one character at a time.
> > 
> > Call domain_vpl011_init during construct_domU if vpl011 is enabled.
> > 
> > Introduce a new ring struct with only the ring array to avoid a waste of
> > memory. Introduce separate read_data and write_data functions for
> > initial domains: vpl011_write_data_xen is very simple and just writes
> > to the console, while vpl011_read_data_xen is a duplicate of
> > vpl011_read_data. Although textually almost identical, we are forced to
> > duplicate the functions because the struct layout is different.
> > 
> > Output characters are printed one by one, potentially leading to
> > intermixed output of different domains on the console. A follow-up patch
> > will solve the issue by introducing buffering.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > ---
> > Changes in v3:
> > - add in-code comments
> > - improve existing comments
> > - remove ifdef around domain_vpl011_init in construct_domU
> > - add ASSERT
> > - use SBSA_UART_FIFO_SIZE for in buffer size
> > - rename ring_enable to backend_in_domain
> > - rename struct xencons_in to struct vpl011_xen_backend
> > - rename inring field to xen
> > - rename helper functions accordingly
> > - remove unnecessary stub implementation of vpl011_rx_char
> > - move vpl011_rx_char_xen within the file to avoid the need of a forward
> >    declaration of vpl011_data_avail
> > - fix small bug in vpl011_rx_char_xen: increment in_prod before using it
> >    to check xencons_queued.
> > 
> > Changes in v2:
> > - only init if vpl011
> > - rename vpl011_read_char to vpl011_rx_char
> > - remove spurious change
> > - fix coding style
> > - use different ring struct
> > - move the write_data changes to their own function
> >    (vpl011_write_data_noring)
> > - duplicate vpl011_read_data
> > ---
> >   xen/arch/arm/domain_build.c  |   9 +-
> >   xen/arch/arm/vpl011.c        | 198
> > ++++++++++++++++++++++++++++++++++++++-----
> >   xen/include/asm-arm/vpl011.h |   8 ++
> >   3 files changed, 192 insertions(+), 23 deletions(-)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index f9fa484..0888a76 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -2638,7 +2638,14 @@ static int __init construct_domU(struct domain *d,
> > struct dt_device_node *node)
> >       if ( rc < 0 )
> >           return rc;
> >   -    return __construct_domain(d, &kinfo);
> > +    rc = __construct_domain(d, &kinfo);
> > +    if ( rc < 0 )
> > +        return rc;
> > +
> > +    if ( kinfo.vpl011 )
> > +        rc = domain_vpl011_init(d, NULL);
> > +
> > +    return rc;
> >   }
> >     void __init create_domUs(void)
> > diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> > index 725a203..f206c61 100644
> > --- a/xen/arch/arm/vpl011.c
> > +++ b/xen/arch/arm/vpl011.c
> > @@ -77,6 +77,91 @@ static void vpl011_update_interrupt_status(struct domain
> > *d)
> >   #endif
> >   }
> >   +/*
> > + * vpl011_write_data_xen writes chars from the vpl011 out buffer to the
> > + * console. Only to be used when the backend is Xen.
> > + */
> > +static void vpl011_write_data_xen(struct domain *d, uint8_t data)
> > +{
> > +    unsigned long flags;
> > +    struct vpl011 *vpl011 = &d->arch.vpl011;
> > +
> > +    VPL011_LOCK(d, flags);
> > +
> > +    printk("%c", data);
> > +    if (data == '\n')
> > +        printk("DOM%u: ", d->domain_id);
> > +
> > +    vpl011->uartris |= TXI;
> > +    vpl011->uartfr &= ~TXFE;
> > +    vpl011_update_interrupt_status(d);
> > +
> > +    VPL011_UNLOCK(d, flags);
> > +}
> > +
> > +/*
> > + * vpl011_read_data_xen reads data when the backend is xen. Characters
> > + * are added to the vpl011 receive buffer by vpl011_rx_char_xen.
> > + */
> > +static uint8_t vpl011_read_data_xen(struct domain *d)
> > +{
> > +    unsigned long flags;
> > +    uint8_t data = 0;
> > +    struct vpl011 *vpl011 = &d->arch.vpl011;
> > +    struct vpl011_xen_backend *intf = vpl011->xen;
> > +    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 )
> > +    {
> > +        unsigned int fifo_level;
> > +
> > +        data = intf->in[xencons_mask(in_cons, sizeof(intf->in))];
> > +        in_cons += 1;
> > +        smp_mb();
> > +        intf->in_cons = in_cons;
> > +
> > +        fifo_level = xencons_queued(in_prod, in_cons, sizeof(intf->in));
> > +
> > +        /* If the FIFO is now empty, we clear the receive timeout
> > interrupt. */
> > +        if ( fifo_level == 0 )
> > +        {
> > +            vpl011->uartfr |= RXFE;
> > +            vpl011->uartris &= ~RTI;
> > +        }
> > +
> > +        /* If the FIFO is more than half empty, we clear the RX interrupt.
> > */
> > +        if ( fifo_level < sizeof(intf->in) - SBSA_UART_FIFO_LEVEL )
> > +            vpl011->uartris &= ~RXI;
> > +
> > +        vpl011_update_interrupt_status(d);
> > +    }
> > +    else
> > +        gprintk(XENLOG_ERR, "vpl011: Unexpected IN ring buffer empty\n");
> > +
> > +    /*
> > +     * We have consumed a character or the FIFO was empty, so clear the
> > +     * "FIFO full" bit.
> > +     */
> > +    vpl011->uartfr &= ~RXFF;
> > +
> > +    VPL011_UNLOCK(d, flags);
> > +
> > +    return data;
> > +}
> > +
> >   static uint8_t vpl011_read_data(struct domain *d)
> >   {
> >       unsigned long flags;
> > @@ -240,7 +325,10 @@ static int vpl011_mmio_read(struct vcpu *v,
> >       case DR:
> >           if ( !vpl011_reg32_check_access(dabt) ) goto bad_width;
> >   -        *r = vreg_reg32_extract(vpl011_read_data(d), info);
> > +        if ( vpl011->backend_in_domain )
> > +            *r = vreg_reg32_extract(vpl011_read_data(d), info);
> > +        else
> > +            *r = vreg_reg32_extract(vpl011_read_data_xen(d), info);
> >           return 1;
> >         case RSR:
> > @@ -325,7 +413,10 @@ static int vpl011_mmio_write(struct vcpu *v,
> >             vreg_reg32_update(&data, r, info);
> >           data &= 0xFF;
> > -        vpl011_write_data(v->domain, data);
> > +        if ( vpl011->backend_in_domain )
> > +            vpl011_write_data(v->domain, data);
> > +        else
> > +            vpl011_write_data_xen(v->domain, data);
> >           return 1;
> >       }
> >   @@ -430,6 +521,39 @@ static void vpl011_data_avail(struct domain *d,
> >           vpl011->uartfr |= TXFE;
> >   }
> >   +/*
> > + * vpl011_rx_char_xen adds a char to a domain's vpl011 receive buffer.
> > + * It is only used when the vpl011 backend is in Xen.
> > + */
> > +void vpl011_rx_char_xen(struct domain *d, char c)
> > +{
> > +    unsigned long flags;
> > +    struct vpl011 *vpl011 = &d->arch.vpl011;
> > +    struct vpl011_xen_backend *intf = vpl011->xen;
> > +    XENCONS_RING_IDX in_cons, in_prod, in_fifo_level;
> > +
> > +    ASSERT(!vpl011->backend_in_domain);
> > +    VPL011_LOCK(d, flags);
> > +
> > +    in_cons = intf->in_cons;
> > +    in_prod = intf->in_prod;
> > +    if ( xencons_queued(in_prod, in_cons, sizeof(intf->in)) ==
> > sizeof(intf->in) )
> > +    {
> > +        VPL011_UNLOCK(d, flags);
> > +        return;
> > +    }
> > +
> > +    intf->in[xencons_mask(in_prod, sizeof(intf->in))] = c;
> > +    intf->in_prod = ++in_prod;
> > +
> > +    in_fifo_level = xencons_queued(in_prod,
> > +                                   in_cons,
> > +                                   sizeof(intf->in));
> > +
> > +    vpl011_data_avail(d, in_fifo_level, sizeof(intf->in), 0,
> > SBSA_UART_FIFO_SIZE);
> > +    VPL011_UNLOCK(d, flags);
> > +}
> > +
> >   static void vpl011_notification(struct vcpu *v, unsigned int port)
> >   {
> >       unsigned long flags;
> > @@ -470,27 +594,47 @@ int domain_vpl011_init(struct domain *d, struct
> > vpl011_init_info *info)
> >       if ( vpl011->dom.ring_buf )
> >           return -EINVAL;
> >   -    /* Map the guest PFN to Xen address space. */
> > -    rc =  prepare_ring_for_helper(d,
> > -                                  gfn_x(info->gfn),
> > -                                  &vpl011->dom.ring_page,
> > -                                  &vpl011->dom.ring_buf);
> > -    if ( rc < 0 )
> > -        goto out;
> > +    /*
> > +     * info is NULL when the backend is in Xen.
> > +     * info is != NULL when the backend is in a domain.
> > +     */
> > +    if ( info != NULL )
> > +    {
> > +        vpl011->backend_in_domain = true;
> > +
> > +        /* Map the guest PFN to Xen address space. */
> > +        rc =  prepare_ring_for_helper(d,
> > +                gfn_x(info->gfn),
> > +                &vpl011->dom.ring_page,
> > +                &vpl011->dom.ring_buf);
> 
> The indentation looks wrong here.

I'll fix

> > +        if ( rc < 0 )
> > +            goto out;
> > +
> > +        rc = alloc_unbound_xen_event_channel(d, 0, info->console_domid,
> > +                vpl011_notification);
> 
> The indentation looks wrong here.

Here too

> > +        if ( rc < 0 )
> > +            goto out1;
> > +
> > +        vpl011->evtchn = info->evtchn = rc;
> > +    }
> > +    else
> > +    {
> > +        vpl011->backend_in_domain = false;
> > +
> > +        vpl011->xen = xzalloc(struct vpl011_xen_backend);
> > +        if ( vpl011->xen == NULL )
> > +        {
> > +            rc = -EINVAL;
> > +            goto out1;
> > +        }
> > +    }
> >         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);
> >   @@ -503,7 +647,10 @@ out2:
> >       vgic_free_virq(d, GUEST_VPL011_SPI);
> >     out1:
> > -    destroy_ring_for_helper(&vpl011->dom.ring_buf, vpl011->dom.ring_page);
> > +    if ( vpl011->backend_in_domain )
> > +        destroy_ring_for_helper(&vpl011->dom.ring_buf,
> > vpl011->dom.ring_page);
> > +    else
> > +        xfree(vpl011->xen);
> >     out:
> >       return rc;
> > @@ -513,11 +660,18 @@ void domain_vpl011_deinit(struct domain *d)
> >   {
> >       struct vpl011 *vpl011 = &d->arch.vpl011;
> >   -    if ( !vpl011->dom.ring_buf )
> > -        return;
> > +    if ( vpl011->backend_in_domain )
> > +    {
> > +        if ( !vpl011->dom.ring_buf )
> > +            return;
> >   -    free_xen_event_channel(d, vpl011->evtchn);
> > -    destroy_ring_for_helper(&vpl011->dom.ring_buf, vpl011->dom.ring_page);
> > +        free_xen_event_channel(d, vpl011->evtchn);
> > +        destroy_ring_for_helper(&vpl011->dom.ring_buf,
> > vpl011->dom.ring_page);
> > +    }
> > +    else
> > +    {
> > +        xfree(vpl011->xen);
> > +    }
> 
> NIT: The { } is not necessary for one line.

OK

> >   }
> >     /*
> > diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
> > index b873a29..c9918c1 100644
> > --- a/xen/include/asm-arm/vpl011.h
> > +++ b/xen/include/asm-arm/vpl011.h
> > @@ -21,6 +21,7 @@
> >     #include <public/domctl.h>
> >   #include <public/io/ring.h>
> > +#include <public/io/console.h>
> >   #include <asm/vreg.h>
> >   #include <xen/mm.h>
> >   @@ -29,13 +30,19 @@
> >   #define VPL011_UNLOCK(d,flags)
> > spin_unlock_irqrestore(&(d)->arch.vpl011.lock, flags)
> >     #define SBSA_UART_FIFO_SIZE 32
> > +struct vpl011_xen_backend {
> > +    char in[SBSA_UART_FIFO_SIZE];
> > +    XENCONS_RING_IDX in_cons, in_prod;
> > +};
> >     struct vpl011 {
> > +    bool backend_in_domain;
> >       union {
> >           struct {
> >               void *ring_buf;
> >               struct page_info *ring_page;
> >           } dom;
> > +        struct vpl011_xen_backend *xen;
> >       };
> >       uint32_t    uartfr;         /* Flag register */
> >       uint32_t    uartcr;         /* Control register */
> > @@ -57,6 +64,7 @@ struct vpl011_init_info {
> >   int domain_vpl011_init(struct domain *d,
> >                          struct vpl011_init_info *info);
> >   void domain_vpl011_deinit(struct domain *d);
> > +void vpl011_rx_char_xen(struct domain *d, char c);
> >   #else
> >   static inline int domain_vpl011_init(struct domain *d,
> >                                        struct vpl011_init_info *info)
> > 
> 
> Cheers,
> 
> -- 
> Julien Grall
> 

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

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

* Re: [PATCH v3 25/25] xen/arm: split domain_build.c
  2018-08-13 14:29   ` Julien Grall
@ 2018-08-16  0:25     ` Stefano Stabellini
  2018-08-16  9:20       ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-08-16  0:25 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 4282 bytes --]

On Mon, 13 Aug 2018, Julien Grall wrote:
> Hi,
> 
> On 01/08/18 00:28, Stefano Stabellini wrote:
> > domain_build.c is too large.
> > 
> > Move all the ACPI specific device tree generating functions from
> > domain_build.c to acpi/acpi_dt_build.c.
> 
> The directory is called "acpi" so there is no point to duplicate in the
> filename.
> 
> Also, looking at the code moved, the name does not seem to be correct. Indeed
> you also generate ACPI tables. A better name for this file would be
> domain_build.c

OK


> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > ---
> >   xen/arch/arm/acpi/Makefile        |   1 +
> >   xen/arch/arm/acpi/acpi_dt_build.c | 591
> > ++++++++++++++++++++++++++++++++++++++
> >   xen/arch/arm/acpi/acpi_dt_build.h |  32 +++
> >   xen/arch/arm/domain_build.c       | 585
> > +------------------------------------
> >   4 files changed, 629 insertions(+), 580 deletions(-)
> >   create mode 100644 xen/arch/arm/acpi/acpi_dt_build.c
> >   create mode 100644 xen/arch/arm/acpi/acpi_dt_build.h
> > 
> > diff --git a/xen/arch/arm/acpi/Makefile b/xen/arch/arm/acpi/Makefile
> > index 23963f8..ac0804b 100644
> > --- a/xen/arch/arm/acpi/Makefile
> > +++ b/xen/arch/arm/acpi/Makefile
> > @@ -1,2 +1,3 @@
> >   obj-y += lib.o
> > +obj-y += acpi_dt_build.o
> >   obj-y += boot.init.o
> > diff --git a/xen/arch/arm/acpi/acpi_dt_build.c
> > b/xen/arch/arm/acpi/acpi_dt_build.c
> > new file mode 100644
> > index 0000000..7e12d64
> > --- /dev/null
> > +++ b/xen/arch/arm/acpi/acpi_dt_build.c
> > @@ -0,0 +1,591 @@
> 
> Missing copyright headers here.

OK


> > +#include <xen/mm.h>
> > +#include <xen/sched.h>
> > +#include <xen/acpi.h>
> > +#include <xen/event.h>
> > +#include <xen/iocap.h>
> > +#include <xen/device_tree.h>
> > +#include <xen/libfdt/libfdt.h>
> > +#include <xen/irq.h>
> > +#include <asm/irq.h>
> 
> Do we really need xen/irq.h and asm/irq.h?

No, I'll remove


> > +#include <acpi/actables.h>
> > +#include "acpi_dt_build.h"
> > +#include "../kernel.h"
> 
> Urgh, that's a call to move kernel.h in asm-arm/.

OK


> > diff --git a/xen/arch/arm/acpi/acpi_dt_build.h
> > b/xen/arch/arm/acpi/acpi_dt_build.h
> > new file mode 100644
> > index 0000000..08e7aab
> > --- /dev/null
> > +++ b/xen/arch/arm/acpi/acpi_dt_build.h
> > @@ -0,0 +1,32 @@
> > +#ifndef __ARCH_ARM_ACPI_ACPI_DT_BUILD_H__
> > +#define __ARCH_ARM_ACPI_ACPI_DT_BUILD_H__
> > +
> > +#include <xen/sched.h>
> > +#include "../kernel.h"
> 
> See above.

OK


> > +
> > +int map_irq_to_domain(struct domain *d, unsigned int irq,
> > +                      bool need_mapping, const char *devname);
> > +int make_chosen_node(const struct kernel_info *kinfo);
> > +void evtchn_allocate(struct domain *d);
> 
> Those one should be moved in an header domain_build.h in asm-arm.

OK


> > +
> > +#ifndef CONFIG_ACPI
> > +static inline int prepare_acpi(struct domain *d, struct kernel_info *kinfo)
> > +{
> > +    /* Only booting with ACPI will hit here */
> > +    BUG();
> > +    return -EINVAL;
> > +}
> > +#else
> > +int prepare_acpi(struct domain *d, struct kernel_info *kinfo);
> > +#endif
> 
> This one should go in asm-arm/acpi.h.
> 
> So this header is not necessary anymore.

I was unable to add prepare_acpi to asm-arm/acpi.h because it causes a
#include dependency hell, I am thinking of adding it to asm-arm/domain_build.h.

In file included from /local/repos/xen-upstream/xen/include/xen/sched.h:11:0,
                 from /local/repos/xen-upstream/xen/include/asm/domain.h:5,
                 from /local/repos/xen-upstream/xen/include/asm/kernel.h:10,
                 from /local/repos/xen-upstream/xen/include/asm/acpi.h:27,
                 from /local/repos/xen-upstream/xen/include/acpi/platform/aclinux.h:58,
                 from /local/repos/xen-upstream/xen/include/acpi/platform/acenv.h:142,
                 from /local/repos/xen-upstream/xen/include/acpi/acpi.h:56,
                 from /local/repos/xen-upstream/xen/include/xen/acpi.h:33,
                 from pl011.c:307:
/local/repos/xen-upstream/xen/include/xen/domain.h:59:31: error: ‘struct xen_domctl_createdomain’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
                        struct xen_domctl_createdomain *config);

[-- Attachment #2: Type: text/plain, Size: 157 bytes --]

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

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

* Re: [PATCH v3 13/25] xen/arm: introduce create_domUs
  2018-08-15 20:04     ` Stefano Stabellini
@ 2018-08-16  9:03       ` Julien Grall
  2018-08-16 18:20         ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-16  9:03 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, andrew.cooper3, andrii_anisov, jbeulich, xen-devel

Hi Stefano,

On 08/15/2018 09:04 PM, Stefano Stabellini wrote:
> On Mon, 13 Aug 2018, Julien Grall wrote:
>>> +void __init create_domUs(void)
>>> +{
>>> +    struct dt_device_node *node;
>>> +    struct dt_device_node *chosen = dt_find_node_by_name(dt_host,
>>> "chosen");
>>> +
>>> +    if ( chosen != NULL )
>>> +    {
>>> +        dt_for_each_child_node(chosen, node)
>>> +        {
>>> +            struct domain *d;
>>> +            struct xen_domctl_createdomain d_cfg = {
>>> +                .arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE,
>>> +                .arch.nr_spis = 32,
>>
>> AFAICT, when creating DomU from the toolstack nr_spis will be 0. So why 32
>> here?
> 
> Legacy from debug code. It should be 0, unless vpl011 is enabled, in
> which case it should be 1.

I would prefer if we use GUEST_VPL011_SPI - 32. This would make the code 
bullet-proof for any potential reshuffle of the IRQs.

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 16/25] xen/arm: rename allocate_memory to allocate_memory_11
  2018-08-15 20:26     ` Stefano Stabellini
@ 2018-08-16  9:08       ` Julien Grall
  2018-08-16 18:27         ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-16  9:08 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 08/15/2018 09:26 PM, Stefano Stabellini wrote:
> On Mon, 13 Aug 2018, Julien Grall wrote:
>> Hi,
>>
>> On 01/08/18 00:27, Stefano Stabellini wrote:
>>> allocate_memory only deals with directly mapped memory. Rename it to
>>> allocate_memory_11.
>>>
>>> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
>>>
>>> ---
>>> Changes in v3:
>>> - add patch
>>> ---
>>>    xen/arch/arm/domain_build.c | 7 ++++---
>>>    1 file changed, 4 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>>> index 066dd75..ab72c36 100644
>>> --- a/xen/arch/arm/domain_build.c
>>> +++ b/xen/arch/arm/domain_build.c
>>> @@ -244,7 +244,8 @@ fail:
>>>     * (as described above) we allow higher allocations and continue until
>>>     * that runs out (or we have allocated sufficient dom0 memory).
>>>     */
>>> -static void __init allocate_memory(struct domain *d, struct kernel_info
>>> *kinfo)
>>> +static void __init allocate_memory_11(struct domain *d,
>>> +                                      struct kernel_info *kinfo)
>>>    {
>>>        const unsigned int min_low_order =
>>>            get_order_from_bytes(min_t(paddr_t, dom0_mem, MB(128)));
>>> @@ -2240,7 +2241,7 @@ static int __init construct_domU(struct domain *d,
>>> struct dt_device_node *node)
>>>        /* type must be set before allocate memory */
>>>        d->arch.type = kinfo.type;
>>>    #endif
>>> -    allocate_memory(d, &kinfo);
>>> +    allocate_memory_11(d, &kinfo);
>>
>> I don't think your patches are correctly ordered. This is adding a lot of
>> confusion in the review because the DomU memory layout is fixed, yet here you
>> rename the function to 1:1 mapping.
>>
>> Most likely you want to do add the new memory function before introducing
>> DomU.
> 
> If I do that there will be no callers for the new function and
> compilation fails. Bisectibility is the reason why I had to reorder the
> patches.
> 

I understand but I don't want to give the impression that 1:1 mapping is 
used for guests. I can see a couple of solutions:
	- Implement allocate_memory in a static inline/#if 0 #endif.
	- Provide a dummy call for the memory that will be implemented later 
(similar to you do for construct_domU).

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 25/25] xen/arm: split domain_build.c
  2018-08-16  0:25     ` Stefano Stabellini
@ 2018-08-16  9:20       ` Julien Grall
  2018-08-16 18:12         ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-16  9:20 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 08/16/2018 01:25 AM, Stefano Stabellini wrote:
> On Mon, 13 Aug 2018, Julien Grall wrote:
>>> +
>>> +#ifndef CONFIG_ACPI
>>> +static inline int prepare_acpi(struct domain *d, struct kernel_info *kinfo)
>>> +{
>>> +    /* Only booting with ACPI will hit here */
>>> +    BUG();
>>> +    return -EINVAL;
>>> +}
>>> +#else
>>> +int prepare_acpi(struct domain *d, struct kernel_info *kinfo);
>>> +#endif
>>
>> This one should go in asm-arm/acpi.h.
>>
>> So this header is not necessary anymore.
> 
> I was unable to add prepare_acpi to asm-arm/acpi.h because it causes a
> #include dependency hell, I am thinking of adding it to asm-arm/domain_build.h.
> 
> In file included from /local/repos/xen-upstream/xen/include/xen/sched.h:11:0,
>                   from /local/repos/xen-upstream/xen/include/asm/domain.h:5,
>                   from /local/repos/xen-upstream/xen/include/asm/kernel.h:10,
>                   from /local/repos/xen-upstream/xen/include/asm/acpi.h:27,
>                   from /local/repos/xen-upstream/xen/include/acpi/platform/aclinux.h:58,
>                   from /local/repos/xen-upstream/xen/include/acpi/platform/acenv.h:142,
>                   from /local/repos/xen-upstream/xen/include/acpi/acpi.h:56,
>                   from /local/repos/xen-upstream/xen/include/xen/acpi.h:33,
>                   from pl011.c:307:
> /local/repos/xen-upstream/xen/include/xen/domain.h:59:31: error: ‘struct xen_domctl_createdomain’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
>                          struct xen_domctl_createdomain *config);

Xen Arm headers are a bit a mess. :/

It looks like create_dom0 lives in setup.h, would it be possible to move 
the prototypes there?

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 25/25] xen/arm: split domain_build.c
  2018-08-16  9:20       ` Julien Grall
@ 2018-08-16 18:12         ` Stefano Stabellini
  0 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-08-16 18:12 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 2170 bytes --]

On Thu, 16 Aug 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 08/16/2018 01:25 AM, Stefano Stabellini wrote:
> > On Mon, 13 Aug 2018, Julien Grall wrote:
> > > > +
> > > > +#ifndef CONFIG_ACPI
> > > > +static inline int prepare_acpi(struct domain *d, struct kernel_info
> > > > *kinfo)
> > > > +{
> > > > +    /* Only booting with ACPI will hit here */
> > > > +    BUG();
> > > > +    return -EINVAL;
> > > > +}
> > > > +#else
> > > > +int prepare_acpi(struct domain *d, struct kernel_info *kinfo);
> > > > +#endif
> > > 
> > > This one should go in asm-arm/acpi.h.
> > > 
> > > So this header is not necessary anymore.
> > 
> > I was unable to add prepare_acpi to asm-arm/acpi.h because it causes a
> > #include dependency hell, I am thinking of adding it to
> > asm-arm/domain_build.h.
> > 
> > In file included from
> > /local/repos/xen-upstream/xen/include/xen/sched.h:11:0,
> >                   from /local/repos/xen-upstream/xen/include/asm/domain.h:5,
> >                   from
> > /local/repos/xen-upstream/xen/include/asm/kernel.h:10,
> >                   from /local/repos/xen-upstream/xen/include/asm/acpi.h:27,
> >                   from
> > /local/repos/xen-upstream/xen/include/acpi/platform/aclinux.h:58,
> >                   from
> > /local/repos/xen-upstream/xen/include/acpi/platform/acenv.h:142,
> >                   from /local/repos/xen-upstream/xen/include/acpi/acpi.h:56,
> >                   from /local/repos/xen-upstream/xen/include/xen/acpi.h:33,
> >                   from pl011.c:307:
> > /local/repos/xen-upstream/xen/include/xen/domain.h:59:31: error: ‘struct
> > xen_domctl_createdomain’ declared inside parameter list will not be visible
> > outside of this definition or declaration [-Werror]
> >                          struct xen_domctl_createdomain *config);
> 
> Xen Arm headers are a bit a mess. :/
> 
> It looks like create_dom0 lives in setup.h, would it be possible to move the
> prototypes there?

It doesn't work either :-/

The problem is that the prototype of prepare_acpi needs the definition
of struct kernel_info, which triggers the include mess. Leaving the
prototypes in asm-arm/domain_build.h work though.

[-- Attachment #2: Type: text/plain, Size: 157 bytes --]

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

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

* Re: [PATCH v3 13/25] xen/arm: introduce create_domUs
  2018-08-16  9:03       ` Julien Grall
@ 2018-08-16 18:20         ` Stefano Stabellini
  0 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-08-16 18:20 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov,
	andrew.cooper3, xen-devel, jbeulich

On Thu, 16 Aug 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 08/15/2018 09:04 PM, Stefano Stabellini wrote:
> > On Mon, 13 Aug 2018, Julien Grall wrote:
> > > > +void __init create_domUs(void)
> > > > +{
> > > > +    struct dt_device_node *node;
> > > > +    struct dt_device_node *chosen = dt_find_node_by_name(dt_host,
> > > > "chosen");
> > > > +
> > > > +    if ( chosen != NULL )
> > > > +    {
> > > > +        dt_for_each_child_node(chosen, node)
> > > > +        {
> > > > +            struct domain *d;
> > > > +            struct xen_domctl_createdomain d_cfg = {
> > > > +                .arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE,
> > > > +                .arch.nr_spis = 32,
> > > 
> > > AFAICT, when creating DomU from the toolstack nr_spis will be 0. So why 32
> > > here?
> > 
> > Legacy from debug code. It should be 0, unless vpl011 is enabled, in
> > which case it should be 1.
> 
> I would prefer if we use GUEST_VPL011_SPI - 32. This would make the code
> bullet-proof for any potential reshuffle of the IRQs.

OK, I'll do that. It is actually GUEST_VPL011_SPI - 32 + 1.
(GUEST_VPL011_SPI - 32 is 0.)

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

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

* Re: [PATCH v3 16/25] xen/arm: rename allocate_memory to allocate_memory_11
  2018-08-16  9:08       ` Julien Grall
@ 2018-08-16 18:27         ` Stefano Stabellini
  0 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-08-16 18:27 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Thu, 16 Aug 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 08/15/2018 09:26 PM, Stefano Stabellini wrote:
> > On Mon, 13 Aug 2018, Julien Grall wrote:
> > > Hi,
> > > 
> > > On 01/08/18 00:27, Stefano Stabellini wrote:
> > > > allocate_memory only deals with directly mapped memory. Rename it to
> > > > allocate_memory_11.
> > > > 
> > > > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > > > 
> > > > ---
> > > > Changes in v3:
> > > > - add patch
> > > > ---
> > > >    xen/arch/arm/domain_build.c | 7 ++++---
> > > >    1 file changed, 4 insertions(+), 3 deletions(-)
> > > > 
> > > > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > > > index 066dd75..ab72c36 100644
> > > > --- a/xen/arch/arm/domain_build.c
> > > > +++ b/xen/arch/arm/domain_build.c
> > > > @@ -244,7 +244,8 @@ fail:
> > > >     * (as described above) we allow higher allocations and continue
> > > > until
> > > >     * that runs out (or we have allocated sufficient dom0 memory).
> > > >     */
> > > > -static void __init allocate_memory(struct domain *d, struct kernel_info
> > > > *kinfo)
> > > > +static void __init allocate_memory_11(struct domain *d,
> > > > +                                      struct kernel_info *kinfo)
> > > >    {
> > > >        const unsigned int min_low_order =
> > > >            get_order_from_bytes(min_t(paddr_t, dom0_mem, MB(128)));
> > > > @@ -2240,7 +2241,7 @@ static int __init construct_domU(struct domain *d,
> > > > struct dt_device_node *node)
> > > >        /* type must be set before allocate memory */
> > > >        d->arch.type = kinfo.type;
> > > >    #endif
> > > > -    allocate_memory(d, &kinfo);
> > > > +    allocate_memory_11(d, &kinfo);
> > > 
> > > I don't think your patches are correctly ordered. This is adding a lot of
> > > confusion in the review because the DomU memory layout is fixed, yet here
> > > you
> > > rename the function to 1:1 mapping.
> > > 
> > > Most likely you want to do add the new memory function before introducing
> > > DomU.
> > 
> > If I do that there will be no callers for the new function and
> > compilation fails. Bisectibility is the reason why I had to reorder the
> > patches.
> > 
> 
> I understand but I don't want to give the impression that 1:1 mapping is used
> for guests. I can see a couple of solutions:
> 	- Implement allocate_memory in a static inline/#if 0 #endif.
> 	- Provide a dummy call for the memory that will be implemented later
> (similar to you do for construct_domU).

OK, #if 0 it is

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

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

* Re: [PATCH v3 22/25] xen/arm: Allow vpl011 to be used by DomU
  2018-08-13 14:10   ` Julien Grall
@ 2018-08-16 19:21     ` Stefano Stabellini
  2018-08-22 10:19       ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-08-16 19:21 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Mon, 13 Aug 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 01/08/18 00:28, Stefano Stabellini wrote:
> > Make vpl011 being able to be used without a userspace component in Dom0.
> > In that case, output is printed to the Xen serial and input is received
> > from the Xen serial one character at a time.
> > 
> > Call domain_vpl011_init during construct_domU if vpl011 is enabled.
> > 
> > Introduce a new ring struct with only the ring array to avoid a waste of
> > memory. Introduce separate read_data and write_data functions for
> > initial domains: vpl011_write_data_xen is very simple and just writes
> > to the console, while vpl011_read_data_xen is a duplicate of
> > vpl011_read_data. Although textually almost identical, we are forced to
> > duplicate the functions because the struct layout is different.
> > 
> > Output characters are printed one by one, potentially leading to
> > intermixed output of different domains on the console. A follow-up patch
> > will solve the issue by introducing buffering.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > ---
> > Changes in v3:
> > - add in-code comments
> > - improve existing comments
> > - remove ifdef around domain_vpl011_init in construct_domU
> > - add ASSERT
> > - use SBSA_UART_FIFO_SIZE for in buffer size
> > - rename ring_enable to backend_in_domain
> > - rename struct xencons_in to struct vpl011_xen_backend
> > - rename inring field to xen
> > - rename helper functions accordingly
> > - remove unnecessary stub implementation of vpl011_rx_char
> > - move vpl011_rx_char_xen within the file to avoid the need of a forward
> >    declaration of vpl011_data_avail
> > - fix small bug in vpl011_rx_char_xen: increment in_prod before using it
> >    to check xencons_queued.
> > 
> > Changes in v2:
> > - only init if vpl011
> > - rename vpl011_read_char to vpl011_rx_char
> > - remove spurious change
> > - fix coding style
> > - use different ring struct
> > - move the write_data changes to their own function
> >    (vpl011_write_data_noring)
> > - duplicate vpl011_read_data
> > ---
> >   xen/arch/arm/domain_build.c  |   9 +-
> >   xen/arch/arm/vpl011.c        | 198
> > ++++++++++++++++++++++++++++++++++++++-----
> >   xen/include/asm-arm/vpl011.h |   8 ++
> >   3 files changed, 192 insertions(+), 23 deletions(-)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index f9fa484..0888a76 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -2638,7 +2638,14 @@ static int __init construct_domU(struct domain *d,
> > struct dt_device_node *node)
> >       if ( rc < 0 )
> >           return rc;
> >   -    return __construct_domain(d, &kinfo);
> > +    rc = __construct_domain(d, &kinfo);
> > +    if ( rc < 0 )
> > +        return rc;
> > +
> > +    if ( kinfo.vpl011 )
> > +        rc = domain_vpl011_init(d, NULL);
> > +
> > +    return rc;
> >   }
> >     void __init create_domUs(void)
> > diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> > index 725a203..f206c61 100644
> > --- a/xen/arch/arm/vpl011.c
> > +++ b/xen/arch/arm/vpl011.c
> > @@ -77,6 +77,91 @@ static void vpl011_update_interrupt_status(struct domain
> > *d)
> >   #endif
> >   }
> >   +/*
> > + * vpl011_write_data_xen writes chars from the vpl011 out buffer to the
> > + * console. Only to be used when the backend is Xen.
> > + */
> > +static void vpl011_write_data_xen(struct domain *d, uint8_t data)
> > +{
> > +    unsigned long flags;
> > +    struct vpl011 *vpl011 = &d->arch.vpl011;
> > +
> > +    VPL011_LOCK(d, flags);
> > +
> > +    printk("%c", data);
> > +    if (data == '\n')
> > +        printk("DOM%u: ", d->domain_id);
> 
> There are a problem in this code. The first line of a domain will always
> printed without "DOM%u: " in front. This means you don't really know where it
> is coming from until you get the second line.

This problem is solved by the follow-up patch that introduces characters
buffering. I'll mention it in the commit message.

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

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

* Re: [PATCH v3 24/25] xen/vpl011: buffer out chars when the backend is xen
  2018-08-13 14:21   ` Julien Grall
@ 2018-08-16 19:41     ` Stefano Stabellini
  2018-08-22 10:35       ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-08-16 19:41 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Mon, 13 Aug 2018, Julien Grall wrote:
> Hi,
> 
> On 01/08/18 00:28, Stefano Stabellini wrote:
> > To avoid mixing the output of different domains on the console, buffer
> > the output chars and print line by line. Unless the domain has input
> > from the serial, in which case we want to print char by char for a
> > smooth user experience.
> > 
> > The size of SBSA_UART_OUT_BUF_SIZE is arbitrary. 90 should be large
> > enough to accommodate the length of most lines of output (typically they
> > are limited to 80 characters on Unix systems), plus one extra char for
> > the string terminator.
> 
> How about using the same value as vuart (e.g VUART_BUT_SIZE) instead? So we
> buffer the same way for the vpl011?

Yes, I can do that.


> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > ---
> >   xen/arch/arm/vpl011.c        | 21 ++++++++++++++++++---
> >   xen/include/asm-arm/vpl011.h |  3 +++
> >   2 files changed, 21 insertions(+), 3 deletions(-)
> > 
> > diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> > index f206c61..8137371 100644
> > --- a/xen/arch/arm/vpl011.c
> > +++ b/xen/arch/arm/vpl011.c
> > @@ -28,6 +28,7 @@
> >   #include <xen/lib.h>
> >   #include <xen/mm.h>
> >   #include <xen/sched.h>
> > +#include <xen/console.h>
> >   #include <public/domctl.h>
> >   #include <public/io/console.h>
> >   #include <asm/pl011-uart.h>
> > @@ -85,12 +86,26 @@ static void vpl011_write_data_xen(struct domain *d,
> > uint8_t data)
> >   {
> >       unsigned long flags;
> >       struct vpl011 *vpl011 = &d->arch.vpl011;
> > +    struct vpl011_xen_backend *intf = vpl011->xen;
> > +    struct domain *input = console_input_domain();
> >         VPL011_LOCK(d, flags);
> >   -    printk("%c", data);
> > -    if (data == '\n')
> > -        printk("DOM%u: ", d->domain_id);
> > +    intf->out[intf->out_prod++] = data;
> > +    if ( d == input && intf->out_prod == 1 )
> > +    {
> > +        printk("%c", data);
> > +        if ( data == '\n' )
> > +            printk("DOM%u: ", d->domain_id);
> > +        intf->out_prod = 0;
> 
> See my remark on the patch implementing vpl011_write_data_xen.

With this patch, the missing "DOM" at the beginning cannot happen
anymore due to the out buffering. Theoretically it can still happen by
switching to DOM1 before DOM1 prints anything, but it is impossible to
do in practice. Even in this theoretical scenario, the user would still
get the useful "Switching to DOM1" message, that would help clarify what
is going on. Thus, my preference is to avoid making the code more
complex to fix this issue.


> > +    } else if ( d == input ||
> 
> Coding style:
> 
> }
> else if
> {

I'll fix


> > +                intf->out_prod == SBSA_UART_OUT_BUF_SIZE - 1 ||
> > +                data == '\n' )
> > +    {
> > +        intf->out[intf->out_prod++] = '\0';
> > +        printk("DOM%u: %s", d->domain_id, intf->out);
> > +        intf->out_prod = 0;
> > +    }
> 
> The code is quite difficult to read. It would be easier to differentiate
> (domain == input vs domain != input) even if it means a bit of duplication.

OK, I can rearrange the code that way. For example:

    if ( d == input ){
        if ( intf->out_prod == 1 )
        {
            printk("%c", data);
            if ( data == '\n' )
                printk("DOM%u: ", d->domain_id);
            intf->out_prod = 0;
        }
        else
        {
            if ( data != '\n' )
                intf->out[intf->out_prod++] = '\n';
            intf->out[intf->out_prod++] = '\0';
            printk("DOM%u: %s", d->domain_id, intf->out);
            intf->out_prod = 0;
        }
    }
    else
    {
        if ( intf->out_prod == SBSA_UART_OUT_BUF_SIZE - 2 ||
             data == '\n' )
        {
            if ( data != '\n' )
                intf->out[intf->out_prod++] = '\n';
            intf->out[intf->out_prod++] = '\0';
            printk("DOM%u: %s", d->domain_id, intf->out);
            intf->out_prod = 0;
        }
    }

Is it better?


> You also don't handle all the cases.
> 
> For the input domain, I don't think you want to print the domain in front.
> Instead I would rely on the "Switch to ...". 

Actually it is very convenient to know at any given time which domain
you are talking to. I couldn't find any problems with the prefix, even
using VIM, etc. I would rather keep the "DOM" string around.


> This would avoid the problem
> where DomB needs to have his line printed while it is not the console input.
> If this happens in the middle of DomA, then you are loosing track what's going
> on.

I don't understand the example: if DOM1 has input, and DOM2 prints
something, the DOM2 output will be prepended by "DOM2", avoiding any
confusion. What am I missing?


> Also if you have the buffer full, you will write the line without a newline.
> So, the next line is going to be wrong. In that case, you need to add a
> newline before printed. I think you want to look at what we did in
> vuart_print_char.

Yes, this is a problem. I'll do the same as vuart_print_char.

 
> >         vpl011->uartris |= TXI;
> >       vpl011->uartfr &= ~TXFE;
> > diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
> > index c9918c1..30487e8 100644
> > --- a/xen/include/asm-arm/vpl011.h
> > +++ b/xen/include/asm-arm/vpl011.h
> > @@ -30,9 +30,12 @@
> >   #define VPL011_UNLOCK(d,flags)
> > spin_unlock_irqrestore(&(d)->arch.vpl011.lock, flags)
> >     #define SBSA_UART_FIFO_SIZE 32
> > +#define SBSA_UART_OUT_BUF_SIZE 91
> >   struct vpl011_xen_backend {
> >       char in[SBSA_UART_FIFO_SIZE];
> > +    char out[SBSA_UART_OUT_BUF_SIZE];
> >       XENCONS_RING_IDX in_cons, in_prod;
> > +    XENCONS_RING_IDX out_prod;
> >   };
> >     struct vpl011 {
> > 
> 
> Cheers,
> 
> -- 
> Julien Grall
>

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

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

* Re: [PATCH v3 23/25] xen: support console_switching between Dom0 and DomUs on ARM
  2018-08-13 13:58   ` Julien Grall
@ 2018-08-16 21:48     ` Stefano Stabellini
  0 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-08-16 21:48 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov,
	George.Dunlap, andrew.cooper3, ian.jackson, xen-devel, tim,
	jbeulich, wei.liu2

On Mon, 13 Aug 2018, Julien Grall wrote:
> Hi Stefano,
> 
> OOI, on the previous version you said you will explore the CTRL-x N solution
> (where N is the domID console to switch too). What was the result here?

I meant I'll explore it as a follow-up to this series. I haven't looked
into it yet, but it is in my todo.


> On 01/08/18 00:28, Stefano Stabellini wrote:
> > Today Ctrl-AAA is used to switch between Xen and Dom0. Extend the
> > mechanism to allow for switching between Xen, Dom0, and any of the
> > initial DomU created from Xen alongside Dom0 out of information provided
> > via device tree.
> > 
> > Rename xen_rx to console_rx to match the new behavior.
> > 
> > Clarify existing comment about "notify the guest", making it clear that
> > it is only about the hardware domain.
> > 
> > Export a function named console_input_domain() to allow others to know
> > which domains has input at a given time.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > CC: andrew.cooper3@citrix.com
> > CC: George.Dunlap@eu.citrix.com
> > CC: ian.jackson@eu.citrix.com
> > CC: jbeulich@suse.com
> > CC: konrad.wilk@oracle.com
> > CC: tim@xen.org
> > CC: wei.liu2@citrix.com
> > ---
> > Changes in v3:
> > - only call vpl011 functions ifdef CONFIG_SBSA_VUART_CONSOLE
> > - add blank line and spaces
> > - remove xen_rx from print messages
> > - rename xen_rx to console_rx
> > - keep switch_serial_input() at boot
> > - add better comments
> > - fix existing comment
> > - add warning if no guests console/uart is available
> > - add console_input_domain function
> > 
> > Changes in v2:
> > - only call vpl011_rx_char if the vpl011 has been initialized
> > ---
> >   xen/drivers/char/console.c | 71
> > +++++++++++++++++++++++++++++++++++++---------
> >   xen/include/xen/console.h  |  2 ++
> >   2 files changed, 60 insertions(+), 13 deletions(-)
> > 
> > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> > index 0f05369..cd4dfb1 100644
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -31,10 +31,13 @@
> >   #include <xen/early_printk.h>
> >   #include <xen/warning.h>
> >   #include <xen/pv_console.h>
> > +#include <asm/setup.h>
> >     #ifdef CONFIG_X86
> >   #include <xen/consoled.h>
> >   #include <asm/guest.h>
> > +#else
> > +#include <asm/vpl011.h>
> >   #endif
> >     /* console: comma-separated list of console outputs. */
> > @@ -389,30 +392,72 @@ static void dump_console_ring_key(unsigned char key)
> >       free_xenheap_pages(buf, order);
> >   }
> >   -/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
> > +/*
> > + * CTRL-<switch_char> switches input direction between Xen, Dom0 and
> > + * DomUs.
> > + */
> >   #define switch_code (opt_conswitch[0]-'a'+1)
> > -static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain 0.
> > */
> > +/*
> > + * console_rx=0 => input to xen
> > + * console_rx=1 => input to dom0
> > + * console_rx=N => input dom(N-1)
> > + */
> > +static int __read_mostly console_rx = 0;
> > +
> > +struct domain *console_input_domain(void)
> > +{
> > +    return get_domain_by_id(console_rx - 1);
> 
> Please take care of the case where console_rx == 0.

I'll do


> > +}
> >     static void switch_serial_input(void)
> >   {
> > -    static char *input_str[2] = { "DOM0", "Xen" };
> > -    xen_rx = !xen_rx;
> > -    printk("*** Serial input -> %s", input_str[xen_rx]);
> > +    console_rx++;
> > +    if ( console_rx == max_init_domid + 2 )
> > +        console_rx = 0;
> > +
> > +    if ( !console_rx )
> > +        printk("*** Serial input to Xen");
> > +    else
> > +        printk("*** Serial input to DOM%d", console_rx - 1);
> > +
> >       if ( switch_code )
> > -        printk(" (type 'CTRL-%c' three times to switch input to %s)",
> > -               opt_conswitch[0], input_str[!xen_rx]);
> > +        printk(" (type 'CTRL-%c' three times to switch input)",
> > +               opt_conswitch[0]);
> >       printk("\n");
> >   }
> >     static void __serial_rx(char c, struct cpu_user_regs *regs)
> >   {
> > -    if ( xen_rx )
> > +    if ( console_rx == 0 )
> >           return handle_keypress(c, regs);
> >   -    /* Deliver input to guest buffer, unless it is already full. */
> > -    if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
> > -        serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> > -    /* Always notify the guest: prevents receive path from getting stuck.
> > */
> > +    if ( console_rx == 1 )
> > +    {
> > +        /* Deliver input to guest buffer, unless it is already full. */
> > +        if ( (serial_rx_prod - serial_rx_cons) != SERIAL_RX_SIZE )
> > +            serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> > +    }
> > +#ifdef CONFIG_SBSA_VUART_CONSOLE
> > +    else
> > +    {
> > +        struct domain *d = get_domain_by_id(console_rx - 1);
> 
> I don't think this is correct to assume the domain will always be present.
> With this series, it would be possible to retire a domain and therefore
> get_domain_by_id() would return NULL here. This would result to a data abort
> below.

Well, spotted! I'll fix.


> Also, I think you want to use rcu_lock_by_domain here (I am not 100% sure
> though).

Uhm... I think you are right


> > +
> > +        /*
> > +         * If we have a properly initialized vpl011 console for the
> > +         * domain, without a full PV ring to Dom0 (in that case input
> > +         * comes from the PV ring), then send the character to it.
> > +         */
> > +        if ( !d->arch.vpl011.backend_in_domain && d->arch.vpl011.xen !=
> > NULL )
> > +            vpl011_rx_char_xen(d, c);
> > +        else
> > +            printk("Cannot send chars to Dom%d: no UART available\n",
> > +                   d->domain_id);
> > +    }
> > +#endif
> > +    /*
> > +     * Always notify the hardware domain: prevents receive path from
> 
> That's not true. If you look at send_global_virq, it will send to the domain
> that register the VIRQ. That may be the hardware domain but could be someone
> else.

The comment and the code are from the existing code, they have only been
moved by this patch. I changed it from "Always notify the guest" to
"Always notify the hardware domain" for clarity. Would you like me to
improve the comment since I am at it? I am happy to include a specific
line, if you prefer.


> However, I still don't understand how this work in presence of multiple
> backend here. Why would you notify Domain B everytime a character is
> redirected to domain A/C/D the console?

You are right, I'll fix that



> > +     * getting stuck.
> > +     */
> >       send_global_virq(VIRQ_CONSOLE);
> >     #ifdef CONFIG_X86
> > @@ -923,7 +968,7 @@ void __init console_endboot(void)
> >        * a useful 'how to switch' message.
> >        */
> >       if ( opt_conswitch[1] == 'x' )
> > -        xen_rx = !xen_rx;
> > +        console_rx = 0;
> >         register_keyhandler('w', dump_console_ring_key,
> >                           "synchronously dump console ring buffer (dmesg)",
> > 0);
> > diff --git a/xen/include/xen/console.h b/xen/include/xen/console.h
> > index ea06fd8..2fe3912 100644
> > --- a/xen/include/xen/console.h
> > +++ b/xen/include/xen/console.h
> > @@ -31,6 +31,8 @@ void console_end_sync(void);
> >   void console_start_log_everything(void);
> >   void console_end_log_everything(void);
> >   +struct domain *console_input_domain(void);
> > +
> >   /*
> >    * Steal output from the console. Returns +ve identifier, else -ve error.
> >    * Takes the handle of the serial line to steal, and steal callback
> > function.

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

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

* Re: [PATCH v3 01/25] xen: allow console_io hypercalls from certain DomUs
  2018-07-31 23:27 ` [PATCH v3 01/25] xen: allow console_io hypercalls from certain DomUs Stefano Stabellini
@ 2018-08-17 19:33   ` Daniel De Graaf
  0 siblings, 0 replies; 88+ messages in thread
From: Daniel De Graaf @ 2018-08-17 19:33 UTC (permalink / raw)
  To: Stefano Stabellini, julien.grall
  Cc: Stefano Stabellini, andrii_anisov, George.Dunlap, andrew.cooper3,
	ian.jackson, xen-devel, tim, jbeulich, wei.liu2

On 07/31/2018 07:27 PM, Stefano Stabellini wrote:
> Introduce an is_console option to allow certain classes of domUs to use
> the Xen console. Specifically, it will be used to give console access to
> all domUs started from Xen from information on device tree.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>

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

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

* Re: [PATCH v3 22/25] xen/arm: Allow vpl011 to be used by DomU
  2018-08-16 19:21     ` Stefano Stabellini
@ 2018-08-22 10:19       ` Julien Grall
  2018-10-03 21:21         ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-22 10:19 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel



On 16/08/18 20:21, Stefano Stabellini wrote:
> On Mon, 13 Aug 2018, Julien Grall wrote:
>> Hi Stefano,
>>
>> On 01/08/18 00:28, Stefano Stabellini wrote:
>>> Make vpl011 being able to be used without a userspace component in Dom0.
>>> In that case, output is printed to the Xen serial and input is received
>>> from the Xen serial one character at a time.
>>>
>>> Call domain_vpl011_init during construct_domU if vpl011 is enabled.
>>>
>>> Introduce a new ring struct with only the ring array to avoid a waste of
>>> memory. Introduce separate read_data and write_data functions for
>>> initial domains: vpl011_write_data_xen is very simple and just writes
>>> to the console, while vpl011_read_data_xen is a duplicate of
>>> vpl011_read_data. Although textually almost identical, we are forced to
>>> duplicate the functions because the struct layout is different.
>>>
>>> Output characters are printed one by one, potentially leading to
>>> intermixed output of different domains on the console. A follow-up patch
>>> will solve the issue by introducing buffering.
>>>
>>> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
>>> ---
>>> Changes in v3:
>>> - add in-code comments
>>> - improve existing comments
>>> - remove ifdef around domain_vpl011_init in construct_domU
>>> - add ASSERT
>>> - use SBSA_UART_FIFO_SIZE for in buffer size
>>> - rename ring_enable to backend_in_domain
>>> - rename struct xencons_in to struct vpl011_xen_backend
>>> - rename inring field to xen
>>> - rename helper functions accordingly
>>> - remove unnecessary stub implementation of vpl011_rx_char
>>> - move vpl011_rx_char_xen within the file to avoid the need of a forward
>>>     declaration of vpl011_data_avail
>>> - fix small bug in vpl011_rx_char_xen: increment in_prod before using it
>>>     to check xencons_queued.
>>>
>>> Changes in v2:
>>> - only init if vpl011
>>> - rename vpl011_read_char to vpl011_rx_char
>>> - remove spurious change
>>> - fix coding style
>>> - use different ring struct
>>> - move the write_data changes to their own function
>>>     (vpl011_write_data_noring)
>>> - duplicate vpl011_read_data
>>> ---
>>>    xen/arch/arm/domain_build.c  |   9 +-
>>>    xen/arch/arm/vpl011.c        | 198
>>> ++++++++++++++++++++++++++++++++++++++-----
>>>    xen/include/asm-arm/vpl011.h |   8 ++
>>>    3 files changed, 192 insertions(+), 23 deletions(-)
>>>
>>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>>> index f9fa484..0888a76 100644
>>> --- a/xen/arch/arm/domain_build.c
>>> +++ b/xen/arch/arm/domain_build.c
>>> @@ -2638,7 +2638,14 @@ static int __init construct_domU(struct domain *d,
>>> struct dt_device_node *node)
>>>        if ( rc < 0 )
>>>            return rc;
>>>    -    return __construct_domain(d, &kinfo);
>>> +    rc = __construct_domain(d, &kinfo);
>>> +    if ( rc < 0 )
>>> +        return rc;
>>> +
>>> +    if ( kinfo.vpl011 )
>>> +        rc = domain_vpl011_init(d, NULL);
>>> +
>>> +    return rc;
>>>    }
>>>      void __init create_domUs(void)
>>> diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
>>> index 725a203..f206c61 100644
>>> --- a/xen/arch/arm/vpl011.c
>>> +++ b/xen/arch/arm/vpl011.c
>>> @@ -77,6 +77,91 @@ static void vpl011_update_interrupt_status(struct domain
>>> *d)
>>>    #endif
>>>    }
>>>    +/*
>>> + * vpl011_write_data_xen writes chars from the vpl011 out buffer to the
>>> + * console. Only to be used when the backend is Xen.
>>> + */
>>> +static void vpl011_write_data_xen(struct domain *d, uint8_t data)
>>> +{
>>> +    unsigned long flags;
>>> +    struct vpl011 *vpl011 = &d->arch.vpl011;
>>> +
>>> +    VPL011_LOCK(d, flags);
>>> +
>>> +    printk("%c", data);
>>> +    if (data == '\n')
>>> +        printk("DOM%u: ", d->domain_id);
>>
>> There are a problem in this code. The first line of a domain will always
>> printed without "DOM%u: " in front. This means you don't really know where it
>> is coming from until you get the second line.
> 
> This problem is solved by the follow-up patch that introduces characters
> buffering. I'll mention it in the commit message.

To be honest, this should be solved in this patch and not the follow-up one.

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 24/25] xen/vpl011: buffer out chars when the backend is xen
  2018-08-16 19:41     ` Stefano Stabellini
@ 2018-08-22 10:35       ` Julien Grall
  2018-10-04 21:29         ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-08-22 10:35 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi,

On 16/08/18 20:41, Stefano Stabellini wrote:
> On Mon, 13 Aug 2018, Julien Grall wrote:
>> Hi,
>>
>> On 01/08/18 00:28, Stefano Stabellini wrote:
>>> To avoid mixing the output of different domains on the console, buffer
>>> the output chars and print line by line. Unless the domain has input
>>> from the serial, in which case we want to print char by char for a
>>> smooth user experience.
>>>
>>> The size of SBSA_UART_OUT_BUF_SIZE is arbitrary. 90 should be large
>>> enough to accommodate the length of most lines of output (typically they
>>> are limited to 80 characters on Unix systems), plus one extra char for
>>> the string terminator.
>>
>> How about using the same value as vuart (e.g VUART_BUT_SIZE) instead? So we
>> buffer the same way for the vpl011?
> 
> Yes, I can do that.
> 
> 
>>> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
>>> ---
>>>    xen/arch/arm/vpl011.c        | 21 ++++++++++++++++++---
>>>    xen/include/asm-arm/vpl011.h |  3 +++
>>>    2 files changed, 21 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
>>> index f206c61..8137371 100644
>>> --- a/xen/arch/arm/vpl011.c
>>> +++ b/xen/arch/arm/vpl011.c
>>> @@ -28,6 +28,7 @@
>>>    #include <xen/lib.h>
>>>    #include <xen/mm.h>
>>>    #include <xen/sched.h>
>>> +#include <xen/console.h>
>>>    #include <public/domctl.h>
>>>    #include <public/io/console.h>
>>>    #include <asm/pl011-uart.h>
>>> @@ -85,12 +86,26 @@ static void vpl011_write_data_xen(struct domain *d,
>>> uint8_t data)
>>>    {
>>>        unsigned long flags;
>>>        struct vpl011 *vpl011 = &d->arch.vpl011;
>>> +    struct vpl011_xen_backend *intf = vpl011->xen;
>>> +    struct domain *input = console_input_domain();
>>>          VPL011_LOCK(d, flags);
>>>    -    printk("%c", data);
>>> -    if (data == '\n')
>>> -        printk("DOM%u: ", d->domain_id);
>>> +    intf->out[intf->out_prod++] = data;
>>> +    if ( d == input && intf->out_prod == 1 )
>>> +    {
>>> +        printk("%c", data);
>>> +        if ( data == '\n' )
>>> +            printk("DOM%u: ", d->domain_id);
>>> +        intf->out_prod = 0;
>>
>> See my remark on the patch implementing vpl011_write_data_xen.
> 
> With this patch, the missing "DOM" at the beginning cannot happen
> anymore due to the out buffering. Theoretically it can still happen by
> switching to DOM1 before DOM1 prints anything, but it is impossible to
> do in practice.

How come this is impossible? DOM1 may have print very late and therefore 
you have time to switch to DOM1 before any print.

> Even in this theoretical scenario, the user would still
> get the useful "Switching to DOM1" message, that would help clarify what
> is going on. Thus, my preference is to avoid making the code more
> complex to fix this issue.

I don't like the idea that in some case DOM%u: is not printed in front 
of the line. This is making more difficult to read the logs.

> 
> 
>>> +    } else if ( d == input ||
>>
>> Coding style:
>>
>> }
>> else if
>> {
> 
> I'll fix
> 
> 
>>> +                intf->out_prod == SBSA_UART_OUT_BUF_SIZE - 1 ||
>>> +                data == '\n' )
>>> +    {
>>> +        intf->out[intf->out_prod++] = '\0';
>>> +        printk("DOM%u: %s", d->domain_id, intf->out);
>>> +        intf->out_prod = 0;
>>> +    }
>>
>> The code is quite difficult to read. It would be easier to differentiate
>> (domain == input vs domain != input) even if it means a bit of duplication.
> 
> OK, I can rearrange the code that way. For example:
> 
>      if ( d == input ){
>          if ( intf->out_prod == 1 )
>          {
>              printk("%c", data);
>              if ( data == '\n' )
>                  printk("DOM%u: ", d->domain_id);
>              intf->out_prod = 0;
>          }
>          else
>          {
>              if ( data != '\n' )
>                  intf->out[intf->out_prod++] = '\n';
>              intf->out[intf->out_prod++] = '\0';
>              printk("DOM%u: %s", d->domain_id, intf->out);
>              intf->out_prod = 0;
>          }
>      }
>      else
>      {
>          if ( intf->out_prod == SBSA_UART_OUT_BUF_SIZE - 2 ||
>               data == '\n' )
>          {
>              if ( data != '\n' )
>                  intf->out[intf->out_prod++] = '\n';
>              intf->out[intf->out_prod++] = '\0';
>              printk("DOM%u: %s", d->domain_id, intf->out);
>              intf->out_prod = 0;
>          }
>      }
> 
> Is it better?

Looks easier to read.

> 
> 
>> You also don't handle all the cases.
>>
>> For the input domain, I don't think you want to print the domain in front.
>> Instead I would rely on the "Switch to ...".
> 
> Actually it is very convenient to know at any given time which domain
> you are talking to. I couldn't find any problems with the prefix, even
> using VIM, etc. I would rather keep the "DOM" string around.

Well it is convenient if you manage to put "DOM" string in front. From a 
look at your implementation and your own comment this is not always the 
case.

I am also quite surprised that this does not make VIM (or any other 
editor) more difficult to use as "DOM:" is printed in front of each line.

> 
> 
>> This would avoid the problem
>> where DomB needs to have his line printed while it is not the console input.
>> If this happens in the middle of DomA, then you are loosing track what's going
>> on.
> 
> I don't understand the example: if DOM1 has input, and DOM2 prints
> something, the DOM2 output will be prepended by "DOM2", avoiding any
> confusion. What am I missing?

Let's take an example:
	1) DOM1 writes "\nab"
	2) DOM2 writes "Foobar\n"
	3) DOM1 write "cde"

The output would be:

DOM1: ab DOM2: Foobar
cde

DOM1 and DOM2 has the line combined (not a big deal). However, the next 
few characters for DOM1 "cde" will not be prefixed with "DOM1:".

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 02/25] xen/arm: move a few DT related defines to public/device_tree_defs.h
  2018-08-01  9:31   ` Julien Grall
@ 2018-08-22 15:25     ` Wei Liu
  0 siblings, 0 replies; 88+ messages in thread
From: Wei Liu @ 2018-08-22 15:25 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov,
	ian.jackson, xen-devel, wei.liu2

On Wed, Aug 01, 2018 at 10:31:50AM +0100, Julien Grall wrote:
> 
> 
> On 01/08/18 00:27, Stefano Stabellini wrote:
> > Move a few constants defined by libxl_arm.c to
> > xen/include/public/device_tree_defs.h, so that they can be used from Xen
> > and libxl. Prepend GUEST_ to avoid conflicts.
> > 
> > Move the DT_IRQ_TYPE* definitions from libxl_arm.c to
> > public/device_tree_defs.h. Use them in Xen where appropriate.
> > 
> > Re-define the existing Xen internal IRQ_TYPEs as DT_IRQ_TYPEs: they
> > already happen to be the same, let make it clear.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> 
> Acked-by: Julien Grall <julien.grall@arm.com>

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

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

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

* Re: [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree
  2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (24 preceding siblings ...)
  2018-07-31 23:28 ` [PATCH v3 25/25] xen/arm: split domain_build.c Stefano Stabellini
@ 2018-08-22 15:44 ` Julien Grall
  25 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2018-08-22 15:44 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: andrii_anisov, xen-devel

Hi Stefano,

On 01/08/18 00:27, Stefano Stabellini wrote:
>        xen/arm: move a few DT related defines to public/device_tree_defs.h
>        xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node
>        xen/arm: move evtchn_allocate call out of make_hypervisor_node
>        xen/arm: rename acpi_make_chosen_node to make_chosen_node

I have committed those 4 patches. 21 to go ;)

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 04/25] xen/arm: document dom0less
  2018-08-01  9:46   ` Julien Grall
@ 2018-10-03 16:47     ` Stefano Stabellini
  0 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-10-03 16:47 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Wed, 1 Aug 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 01/08/18 00:27, Stefano Stabellini wrote:
> > Add a new document to provide information on how to use dom0less related
> > features and their current limitations.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > 
> > ---
> > Changes in v3:
> > - add patch
> > ---
> >   docs/misc/arm/dom0less | 47
> > +++++++++++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 47 insertions(+)
> >   create mode 100644 docs/misc/arm/dom0less
> > 
> > diff --git a/docs/misc/arm/dom0less b/docs/misc/arm/dom0less
> 
> This should be suffixed with .txt. You also want to add a line in docs/INDEX
> describing the file.

I'll make this changes and all the others suggested in this email


> > new file mode 100644
> > index 0000000..ae5a8b1
> > --- /dev/null
> > +++ b/docs/misc/arm/dom0less
> > @@ -0,0 +1,47 @@
> > +Dom0less
> > +========
> > +
> > +"Dom0less" is a set of Xen features that enable the deployment of a Xen
> > +system without Dom0.
> 
> I think this sentence is misleading. You still deploy Xen with Dom0.
> 
> Also, we have been trying to removing the wording Dom0 anywhere in the code.
> Instead, we are now using "Hardware Domain". I would rather avoid to use Dom0
> in the documentation as it could be misleading, you will always have a domain
> with ID (it may not be what you call Dom0 here).
> 
> > Each feature can be used independently from the
> > +others, unless otherwise stated.
> > +
> > +Booting Multiple Domains from Device Tree
> > +=========================================
> > +
> > +This feature enables Xen to create a set of DomUs alongside Dom0 at boot
> > +time. Information about the DomUs to be created by Xen is passed to the
> > +hypervisor via Device Tree. Specifically, the existing Device Tree based
> > +Multiboot specification has been extended to allow for multiple domains
> > +to be passed to Xen. See docs/misc/arm/device-tree/booting.txt for more
> > +information about the Multiboot specification and how to use it.
> > +
> > +Instead of waiting for Dom0 to be fully booted and the Xen tools to
> > +become available, domains created by Xen this way are started in
> > +parallel to Dom0. Hence, their boot time is typically much shorter.
> > +
> > +Domains started by Xen at boot time currently have the following
> > +limitations:
> > +
> > +- they cannot be properly shutdown or rebooted using xl
> > +If one of them crashes, the whole platform should be rebooted.
> > +
> > +- some xl operations might not work as expected
> > +xl is meant to be used with domains that have been created by it. Using
> > +xl with domains started by Xen at boot might not work as expected.
> > +
> > +- the GIC version is the native version
> > +In absence of other information, the GIC version exposed to the domains
> > +started by Xen at boot is the same as the native GIC version.
> > +
> > +- no PV drivers
> > +There is no support for PV devices at the moment. All devices need to be
> > +statically assigned to guests.
> > +
> > +- vCPU pinning
> > +Pinning vCPUs of domains started by Xen at boot can be done from dom0,
> > +using `xl vcpu-pin' as usual. It is not currently possible to configure
> > +vCPU pinning for domains other than dom0 without dom0. However, the NULL
> > +scheduler (currently unsupported) can be selected by passing
> 
> I would rather not mention NULL scheduler is unsupported here. That's another
> place to update the doc when it gets supported and maybe be missed.
> 
> > +`sched=null' to the Xen command line. The NULL scheduler automatically
> > +assignes and pins vCPUs to pCPUs, but the vCPU-pCPU assignments cannot
> 
> s/assignes/assigns/
> 
> > +be configured.
> 
> Cheers,
> 
> -- 
> Julien Grall
> 

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

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

* Re: [PATCH v3 17/25] xen/arm: introduce allocate_memory
  2018-08-01 11:28   ` Julien Grall
@ 2018-10-03 17:46     ` Stefano Stabellini
  0 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-10-03 17:46 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Wed, 1 Aug 2018, Julien Grall wrote:
> Hi,
> 
> On 01/08/18 00:28, Stefano Stabellini wrote:
> > Introduce an allocate_memory function able to allocate memory for DomUs
> > and map it at the right guest addresses, according to the guest memory
> > map: GUEST_RAM0_BASE and GUEST_RAM1_BASE.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > ---
> > Changes in v3:
> > - new patch
> > ---
> >   xen/arch/arm/domain_build.c | 125
> > +++++++++++++++++++++++++++++++++++++++++++-
> >   1 file changed, 124 insertions(+), 1 deletion(-)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index ab72c36..dfa74e4 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -369,6 +369,129 @@ static void __init allocate_memory_11(struct domain
> > *d,
> >       }
> >   }
> >   +static bool __init insert_bank(struct domain *d,
> > +                               struct kernel_info *kinfo,
> > +                               struct page_info *pg,
> > +                               unsigned int order)
> > +{
> > +    int res, i;
> > +    mfn_t smfn;
> > +    paddr_t gaddr, size;
> > +    struct membank *bank;
> > +
> > +    smfn = page_to_mfn(pg);
> 
> This could combine with the declaration above.

OK


> > +    size = pfn_to_paddr(1UL << order);
> 
> Ditto.

OK


> > +
> > +    /*
> > +     * DomU memory is provided in two banks:
> > +     *   GUEST_RAM0_BASE - GUEST_RAM0_BASE + GUEST_RAM0_SIZE
> > +     *   GUEST_RAM1_BASE - GUEST_RAM1_BASE + GUEST_RAM1_SIZE
> > +     *
> > +     * Find the right gaddr address for DomUs accordingly.
> > +     */
> > +    gaddr = GUEST_RAM0_BASE;
> > +    if ( kinfo->mem.nr_banks > 0 )
> > +    {
> > +        for( i = 0; i < kinfo->mem.nr_banks; i++ )
> > +        {
> > +            bank = &kinfo->mem.bank[i];
> > +            gaddr = bank->start + bank->size;
> > +        }
> > +        if ( bank->start == GUEST_RAM0_BASE &&
> > +             gaddr + size > (GUEST_RAM0_BASE + GUEST_RAM0_SIZE) )
> > +            gaddr = GUEST_RAM1_BASE;
> > +        if ( bank->start == GUEST_RAM1_BASE &&
> > +             gaddr + size > (GUEST_RAM1_BASE + GUEST_RAM1_SIZE) )
> > +            goto fail;
> > +    }
> 
> I still really dislike this code. This is difficult to understand and not
> scalable. As I said in the previous version, it would be possible to have more
> than 2 banks in the future. This will either come with PCI PT or dynamic
> memory layout.
> 
> What should really be done is a function allocate_memory that take in
> parameter the range to allocate. E.g
> 
> allocate_bank_memory(struct domain *d, gfn_t sgfn, unsigned long order);
> 
> Then the function allocate_memory will compute the size of each bank based on
> mem_ and call allocate_bank_memory for each bank.

I'll make the change.


> > +
> > +    dprintk(XENLOG_INFO,
> > +            "Allocated %#"PRIpaddr"-%#"PRIpaddr":%#"PRIpaddr"-%#"PRIpaddr"
> > (%ldMB/%ldMB, order %d)\n",
> 
> It would be possible to request a guest with 16KB of memory. This would be
> printed as 0.

I'll printk KBs instead of MBs.


> > +            mfn_to_maddr(smfn), mfn_to_maddr(smfn) + size,
> > +            gaddr, gaddr + size,
> > +            1UL << (order + PAGE_SHIFT - 20),
> > +            /* Don't want format this as PRIpaddr (16 digit hex) */
> > +            (unsigned long)(kinfo->unassigned_mem >> 20),
> > +            order);
> > +
> > +    res = guest_physmap_add_page(d, gaddr_to_gfn(gaddr), smfn, order);
> > +    if ( res )
> > +    {
> > +        dprintk(XENLOG_ERR, "Failed map pages to DOMU: %d", res);
> > +        goto fail;
> > +    }
> > +
> > +    kinfo->unassigned_mem -= size;
> > +    bank = &kinfo->mem.bank[kinfo->mem.nr_banks];
> > +
> > +    bank->start = gaddr;
> > +    bank->size = size;
> > +    kinfo->mem.nr_banks++;
> > +    return true;
> > +
> > +fail:
> > +    free_domheap_pages(pg, order);
> > +    return false;
> > +}
> > +
> > +static void __init allocate_memory(struct domain *d, struct kernel_info
> > *kinfo)
> > +{
> > +    const unsigned int min_order = get_order_from_bytes(MB(4));
> 
> Why do you have this limitation for non-direct mapped domain? There are
> nothing wrong to allocate 2MB/4K pages for them.

I'll remove


> > +    struct page_info *pg;
> > +    unsigned int order = get_allocation_size(kinfo->unassigned_mem);
> > +    int i;
> > +
> > +    dprintk(XENLOG_INFO, "Allocating mappings totalling %ldMB for
> > dom%d:\n",
> 
> Ditto.

I'll print KBs


> > +            /* Don't want format this as PRIpaddr (16 digit hex) */
> > +            (unsigned long)(kinfo->unassigned_mem >> 20), d->domain_id);
> > +
> > +    kinfo->mem.nr_banks = 0;
> > +
> > +    order = get_allocation_size(kinfo->unassigned_mem);
> > +    if ( order > GUEST_RAM0_SIZE )
> > +        order = GUEST_RAM0_SIZE;
> 
> I don't understand this check. You are comparing a power of 2 with KB.

I'll fix


> > +    while ( kinfo->unassigned_mem )
> > +    {
> > +        pg = alloc_domheap_pages(d, order, 0);
> > +        if ( !pg )
> > +        {
> > +            order --;
> > +
> > +            if ( order >= min_order )
> > +                continue;
> > +
> > +            /* No more we can do */
> > +            break;
> > +        }
> > +
> > +        if ( !insert_bank(d, kinfo, pg, order) )
> > +            break;
> > +
> > +        /*
> > +         * Success, next time around try again to get the largest order
> > +         * allocation possible.
> > +         */
> > +        order = get_allocation_size(kinfo->unassigned_mem);
> > +    }
> > +
> > +    if ( kinfo->unassigned_mem )
> > +        dprintk(XENLOG_WARNING, "Failed to allocate requested domain
> > memory."
> > +               /* Don't want format this as PRIpaddr (16 digit hex) */
> > +               " %ldMB unallocated\n",
> > +               (unsigned long)kinfo->unassigned_mem >> 20);
> 
> I understand this is the current behavior for direct mapped domain. It makes
> sense for them because we don't want to create very small bank (we request 4MB
> min). But for non direct mapped domain, there are no need for such limitation.
> So if you don't allocate the memory, then it means Xen has no more RAM and it
> makes little sense to boot them.

Yes, it makes sense to print an error instead of a warning and stop the
boot, so that the user can go back and fix the configuration.


> > +
> > +    for( i = 0; i < kinfo->mem.nr_banks; i++ )
> > +    {
> > +        dprintk(XENLOG_INFO, "Dom%d BANK[%d] %#"PRIpaddr"-%#"PRIpaddr"
> > (%ldMB)\n",
> > +                d->domain_id,
> > +                i,
> > +                kinfo->mem.bank[i].start,
> > +                kinfo->mem.bank[i].start + kinfo->mem.bank[i].size,
> > +                /* Don't want format this as PRIpaddr (16 digit hex) */
> > +                (unsigned long)(kinfo->mem.bank[i].size >> 20));
> > +    }
> > +}
> > +
> >   static int __init write_properties(struct domain *d, struct kernel_info
> > *kinfo,
> >                                      const struct dt_device_node *node)
> >   {
> > @@ -2241,7 +2364,7 @@ static int __init construct_domU(struct domain *d,
> > struct dt_device_node *node)
> >       /* type must be set before allocate memory */
> >       d->arch.type = kinfo.type;
> >   #endif
> > -    allocate_memory_11(d, &kinfo);
> > +    allocate_memory(d, &kinfo);
> 
> The call to allocate_memory_11() should have never been added. Please
> refactor/re-order the patch to avoid introducing wrong code.

done

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

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

* Re: [PATCH v3 22/25] xen/arm: Allow vpl011 to be used by DomU
  2018-08-22 10:19       ` Julien Grall
@ 2018-10-03 21:21         ` Stefano Stabellini
  2018-10-04 17:17           ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-10-03 21:21 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Wed, 22 Aug 2018, Julien Grall wrote:
> On 16/08/18 20:21, Stefano Stabellini wrote:
> > On Mon, 13 Aug 2018, Julien Grall wrote:
> > > Hi Stefano,
> > > 
> > > On 01/08/18 00:28, Stefano Stabellini wrote:
> > > > Make vpl011 being able to be used without a userspace component in Dom0.
> > > > In that case, output is printed to the Xen serial and input is received
> > > > from the Xen serial one character at a time.
> > > > 
> > > > Call domain_vpl011_init during construct_domU if vpl011 is enabled.
> > > > 
> > > > Introduce a new ring struct with only the ring array to avoid a waste of
> > > > memory. Introduce separate read_data and write_data functions for
> > > > initial domains: vpl011_write_data_xen is very simple and just writes
> > > > to the console, while vpl011_read_data_xen is a duplicate of
> > > > vpl011_read_data. Although textually almost identical, we are forced to
> > > > duplicate the functions because the struct layout is different.
> > > > 
> > > > Output characters are printed one by one, potentially leading to
> > > > intermixed output of different domains on the console. A follow-up patch
> > > > will solve the issue by introducing buffering.
> > > > 
> > > > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > > > ---
> > > > Changes in v3:
> > > > - add in-code comments
> > > > - improve existing comments
> > > > - remove ifdef around domain_vpl011_init in construct_domU
> > > > - add ASSERT
> > > > - use SBSA_UART_FIFO_SIZE for in buffer size
> > > > - rename ring_enable to backend_in_domain
> > > > - rename struct xencons_in to struct vpl011_xen_backend
> > > > - rename inring field to xen
> > > > - rename helper functions accordingly
> > > > - remove unnecessary stub implementation of vpl011_rx_char
> > > > - move vpl011_rx_char_xen within the file to avoid the need of a forward
> > > >     declaration of vpl011_data_avail
> > > > - fix small bug in vpl011_rx_char_xen: increment in_prod before using it
> > > >     to check xencons_queued.
> > > > 
> > > > Changes in v2:
> > > > - only init if vpl011
> > > > - rename vpl011_read_char to vpl011_rx_char
> > > > - remove spurious change
> > > > - fix coding style
> > > > - use different ring struct
> > > > - move the write_data changes to their own function
> > > >     (vpl011_write_data_noring)
> > > > - duplicate vpl011_read_data
> > > > ---
> > > >    xen/arch/arm/domain_build.c  |   9 +-
> > > >    xen/arch/arm/vpl011.c        | 198
> > > > ++++++++++++++++++++++++++++++++++++++-----
> > > >    xen/include/asm-arm/vpl011.h |   8 ++
> > > >    3 files changed, 192 insertions(+), 23 deletions(-)
> > > > 
> > > > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > > > index f9fa484..0888a76 100644
> > > > --- a/xen/arch/arm/domain_build.c
> > > > +++ b/xen/arch/arm/domain_build.c
> > > > @@ -2638,7 +2638,14 @@ static int __init construct_domU(struct domain
> > > > *d,
> > > > struct dt_device_node *node)
> > > >        if ( rc < 0 )
> > > >            return rc;
> > > >    -    return __construct_domain(d, &kinfo);
> > > > +    rc = __construct_domain(d, &kinfo);
> > > > +    if ( rc < 0 )
> > > > +        return rc;
> > > > +
> > > > +    if ( kinfo.vpl011 )
> > > > +        rc = domain_vpl011_init(d, NULL);
> > > > +
> > > > +    return rc;
> > > >    }
> > > >      void __init create_domUs(void)
> > > > diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> > > > index 725a203..f206c61 100644
> > > > --- a/xen/arch/arm/vpl011.c
> > > > +++ b/xen/arch/arm/vpl011.c
> > > > @@ -77,6 +77,91 @@ static void vpl011_update_interrupt_status(struct
> > > > domain
> > > > *d)
> > > >    #endif
> > > >    }
> > > >    +/*
> > > > + * vpl011_write_data_xen writes chars from the vpl011 out buffer to the
> > > > + * console. Only to be used when the backend is Xen.
> > > > + */
> > > > +static void vpl011_write_data_xen(struct domain *d, uint8_t data)
> > > > +{
> > > > +    unsigned long flags;
> > > > +    struct vpl011 *vpl011 = &d->arch.vpl011;
> > > > +
> > > > +    VPL011_LOCK(d, flags);
> > > > +
> > > > +    printk("%c", data);
> > > > +    if (data == '\n')
> > > > +        printk("DOM%u: ", d->domain_id);
> > > 
> > > There are a problem in this code. The first line of a domain will always
> > > printed without "DOM%u: " in front. This means you don't really know where
> > > it
> > > is coming from until you get the second line.
> > 
> > This problem is solved by the follow-up patch that introduces characters
> > buffering. I'll mention it in the commit message.
> 
> To be honest, this should be solved in this patch and not the follow-up one.

I agree. I kept them separate to make them easier to review. Would you
be OK with me merging the two patches into one once they have both been
acked? Otherwise, if you prefer that I merge them now, let me know.

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

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

* Re: [PATCH v3 09/25] xen/arm: introduce bootcmdlines
  2018-08-01 10:51   ` Julien Grall
@ 2018-10-03 23:11     ` Stefano Stabellini
  2018-10-04 17:23       ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-10-03 23:11 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Wed, 1 Aug 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 01/08/18 00:27, Stefano Stabellini wrote:
> > Introduce a new array to store the cmdline of each boot module. It is
> > separate from struct bootmodules. Remove the cmdline field from struct
> > boot_module. This way, kernels and initrds with the same address in
> > memory can share struct bootmodule (important because we want them to be
> > free'd only once), but they can still have their separate bootcmdline
> > entries.
> > 
> > Add a dt_name field to struct bootcmdline to make it easier to find the
> > correct entry. Store the name of the "xen,domain" compatible node (for
> > example "Dom1"). This is a better choice compared to the name of the
> > "multiboot,kernel" compatible node, because their names are not unique.
> > For instance there can be more than one "module@0x4c000000" in the
> > system, but there can only be one "/chosen/Dom1".
> 
> As I mentioned in the previous version, the code is currently looking for
> multiboot,module everywhere in the DT rather than only in /chosen. So your
> name could not be uniq.
> 
> However, this is not compliant with the protocol. Therefore you need to fix
> the code first to ensure the name will be uniq.

I'll fix this and everything else you pointed out


> > 
> > Add a pointer to struct kernel_info to point to the cmdline for a given
> > kernel.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > 
> > ---
> > 
> > Changes in v3:
> > - introduce bootcmdlines
> > - do not modify boot_fdt_cmdline
> > - add comments
> 
> I see no comments in the code. Did I miss anything?
> 
> > 
> > Changes in v2:
> > - new patch
> > ---
> >   xen/arch/arm/bootfdt.c      | 66
> > +++++++++++++++++++++++++++++++--------------
> >   xen/arch/arm/domain_build.c |  8 +++---
> >   xen/arch/arm/kernel.h       |  1 +
> >   xen/arch/arm/setup.c        | 23 +++++++++++-----
> >   xen/include/asm-arm/setup.h | 16 +++++++++--
> >   5 files changed, 82 insertions(+), 32 deletions(-)
> > 
> > diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
> > index 8eba42c..6f44022 100644
> > --- a/xen/arch/arm/bootfdt.c
> > +++ b/xen/arch/arm/bootfdt.c
> > @@ -163,6 +163,38 @@ static void __init process_memory_node(const void *fdt,
> > int node,
> >       }
> >   }
> >   +static void __init add_boot_cmdline(const void *fdt, int node,
> > +                                    const char *name, bootmodule_kind kind)
> > +{
> > +    struct bootcmdlines *mods = &bootinfo.cmdlines;
> > +    struct bootcmdline *mod;
> 
> This feels sligthtly strange to use "mod" here. We are not dealing with boot
> modules but boot command line.

I'l rename it


> > +    const struct fdt_property *prop;
> > +    int len;
> > +    const char *cmdline;
> > +
> > +    if ( mods->nr_mods == MAX_MODULES )
> > +    {
> > +        printk("Ignoring %s boot module (too many)\n", name);
> 
> Same here. This needs to be updated.

I'll reword it


> > +        return;
> > +    }
> > +
> > +    mod = &mods->cmdline[mods->nr_mods++];
> > +    mod->kind = kind;
> > +
> > +    if ( strlen(name) > DT_MAX_NAME )
> > +        panic("module %s name too long\n", name);
> 
> This would really never happen. It feels an ASSERT(strlen(name) >
> DT_MAX_NAME)) would be more suitable.

OK, easy to change


> > +    safe_strcpy(mod->dt_name, name);
> > +
> > +    prop = fdt_get_property(fdt, node, "bootargs", &len);
> > +    if ( prop )
> > +    {
> > +        if ( len > BOOTMOD_MAX_CMDLINE )
> > +            panic("module %s command line too long\n", name);
> > +        cmdline = prop->data;
> > +        safe_strcpy(mod->cmdline, cmdline);
> > +    }
> > +}
> > +
> >   static void __init process_multiboot_node(const void *fdt, int node,
> >                                             const char *name,
> >                                             u32 address_cells, u32
> > size_cells)
> > @@ -172,8 +204,12 @@ static void __init process_multiboot_node(const void
> > *fdt, int node,
> >       const __be32 *cell;
> >       bootmodule_kind kind;
> >       paddr_t start, size;
> > -    const char *cmdline;
> >       int len;
> > +    int parent_node;
> > +
> > +    parent_node = fdt_parent_offset(fdt, node);
> > +    if ( parent_node < 0 )
> > +        panic("node %s missing a parent\n", name);
> 
> It feels an ASSERT(parent_node < 0) would be more suitable as this should
> never really happen.

OK


> >         prop = fdt_get_property(fdt, node, "reg", &len);
> >       if ( !prop )
> > @@ -220,17 +256,8 @@ static void __init process_multiboot_node(const void
> > *fdt, int node,
> >               kind = BOOTMOD_XSM;
> >       }
> > -    prop = fdt_get_property(fdt, node, "bootargs", &len);
> > -    if ( prop )
> > -    {
> > -        if ( len > BOOTMOD_MAX_CMDLINE )
> > -            panic("module %s command line too long\n", name);
> > -        cmdline = prop->data;
> > -    }
> > -    else
> > -        cmdline = NULL;
> > -
> 
> I am not entirely sure to understand why this code has been moved. With your
> new code, if you have a module without commandline then you will still add a
> cmdline with nothing. This looks quite pointless.
> 
> Instead, you could keep this code here and only call add_bootcmdline when it
> is not NULL (or ignore it directly in the function).

I'll do that


> > -    add_boot_module(kind, start, size, cmdline);
> > +    add_boot_module(kind, start, size);
> > +    add_boot_cmdline(fdt, node, fdt_get_name(fdt, parent_node, &len),
> > kind);
> >   }
> >     static void __init process_chosen_node(const void *fdt, int node,
> > @@ -276,7 +303,7 @@ static void __init process_chosen_node(const void *fdt,
> > int node,
> >         printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end);
> >   -    add_boot_module(BOOTMOD_RAMDISK, start, end-start, NULL);
> > +    add_boot_module(BOOTMOD_RAMDISK, start, end-start);
> >   }
> >     static int __init early_scan_node(const void *fdt,
> > @@ -307,12 +334,11 @@ static void __init early_print_info(void)
> >                        mi->bank[i].start + mi->bank[i].size - 1);
> >       printk("\n");
> >       for ( i = 0 ; i < mods->nr_mods; i++ )
> > -        printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s %s\n",
> > +        printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s\n",
> >                        i,
> >                        mods->module[i].start,
> >                        mods->module[i].start + mods->module[i].size,
> > -                     boot_module_kind_as_string(mods->module[i].kind),
> > -                     mods->module[i].cmdline);
> > +                     boot_module_kind_as_string(mods->module[i].kind));
> 
> With that change the command line is not printed anymore and also not
> associated to a module. This was quite useful for debugging bootloader issue.

I'll add more debug info, but in a separate loop for simplicity


> >       nr_rsvd = fdt_num_mem_rsv(device_tree_flattened);
> >       for ( i = 0; i < nr_rsvd; i++ )
> >       {
> 
> [...]
> 
> > +struct bootcmdline * __init boot_cmdline_find_by_kind(bootmodule_kind kind)
> > +{
> > +    struct bootcmdlines *mods = &bootinfo.cmdlines;
> > +    struct bootcmdline *mod;
> 
> Again, the name "mod" is misleading here.

I'll rename


> > +    int i;
> 
> Newline here.

I'll add


> > +    for (i = 0 ; i < mods->nr_mods ; i++ )
> 
> for ( ... )

I'll fix


> > +    {
> > +        mod = &mods->cmdline[i];
> > +        if ( mod->kind == kind )
> > +            return mod;
> > +    }
> > +    return NULL;
> > +}
> > +
> >   const char * __init boot_module_kind_as_string(bootmodule_kind kind)
> >   {
> >       switch ( kind )
> > @@ -723,7 +732,7 @@ void __init start_xen(unsigned long boot_phys_offset,
> >       /* Register Xen's load address as a boot module. */
> >       xen_bootmodule = add_boot_module(BOOTMOD_XEN,
> >                                (paddr_t)(uintptr_t)(_start +
> > boot_phys_offset),
> > -                             (paddr_t)(uintptr_t)(_end - _start + 1),
> > NULL);
> > +                             (paddr_t)(uintptr_t)(_end - _start + 1));
> >       BUG_ON(!xen_bootmodule);
> >         xen_paddr = get_xen_paddr();
> > diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
> > index f1e4a3f..cb7da51 100644
> > --- a/xen/include/asm-arm/setup.h
> > +++ b/xen/include/asm-arm/setup.h
> > @@ -35,6 +35,12 @@ struct bootmodule {
> >       bootmodule_kind kind;
> >       paddr_t start;
> >       paddr_t size;
> > +};
> > +
> > +#define DT_MAX_NAME 32
> 
> It might be useful to explain where 32 comes from.

The limit is somewhat arbitrary. I'll explain in a comment.


> > +struct bootcmdline {
> > +    bootmodule_kind kind;
> > +    char dt_name[DT_MAX_NAME];
> >       char cmdline[BOOTMOD_MAX_CMDLINE];
> >   };
> >   @@ -43,9 +49,15 @@ struct bootmodules {
> >       struct bootmodule module[MAX_MODULES];
> >   };
> >   +struct bootcmdlines {
> > +    int nr_mods;
> 
> unsigned int here please.

OK


> > +    struct bootcmdline cmdline[MAX_MODULES];
> > +};
> > +
> >   struct bootinfo {
> >       struct meminfo mem;
> >       struct bootmodules modules;
> > +    struct bootcmdlines cmdlines;
> >   #ifdef CONFIG_ACPI
> >       struct meminfo acpi;
> >   #endif
> > @@ -78,9 +90,9 @@ size_t __init boot_fdt_info(const void *fdt, paddr_t
> > paddr);
> >   const char __init *boot_fdt_cmdline(const void *fdt);
> >     struct bootmodule *add_boot_module(bootmodule_kind kind,
> > -                                   paddr_t start, paddr_t size,
> > -                                   const char *cmdline);
> > +                                   paddr_t start, paddr_t size);
> >   struct bootmodule *boot_module_find_by_kind(bootmodule_kind kind);
> > +struct bootcmdline *boot_cmdline_find_by_kind(bootmodule_kind kind);
> >   const char * __init boot_module_kind_as_string(bootmodule_kind kind);
> >     #endif

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

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

* Re: [PATCH v3 22/25] xen/arm: Allow vpl011 to be used by DomU
  2018-10-03 21:21         ` Stefano Stabellini
@ 2018-10-04 17:17           ` Julien Grall
  0 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2018-10-04 17:17 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel



On 03/10/2018 22:21, Stefano Stabellini wrote:
> On Wed, 22 Aug 2018, Julien Grall wrote:
>> On 16/08/18 20:21, Stefano Stabellini wrote:
>>> On Mon, 13 Aug 2018, Julien Grall wrote:
>>>> Hi Stefano,
>>>>
>>>> On 01/08/18 00:28, Stefano Stabellini wrote:
>>>>> Make vpl011 being able to be used without a userspace component in Dom0.
>>>>> In that case, output is printed to the Xen serial and input is received
>>>>> from the Xen serial one character at a time.
>>>>>
>>>>> Call domain_vpl011_init during construct_domU if vpl011 is enabled.
>>>>>
>>>>> Introduce a new ring struct with only the ring array to avoid a waste of
>>>>> memory. Introduce separate read_data and write_data functions for
>>>>> initial domains: vpl011_write_data_xen is very simple and just writes
>>>>> to the console, while vpl011_read_data_xen is a duplicate of
>>>>> vpl011_read_data. Although textually almost identical, we are forced to
>>>>> duplicate the functions because the struct layout is different.
>>>>>
>>>>> Output characters are printed one by one, potentially leading to
>>>>> intermixed output of different domains on the console. A follow-up patch
>>>>> will solve the issue by introducing buffering.
>>>>>
>>>>> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
>>>>> ---
>>>>> Changes in v3:
>>>>> - add in-code comments
>>>>> - improve existing comments
>>>>> - remove ifdef around domain_vpl011_init in construct_domU
>>>>> - add ASSERT
>>>>> - use SBSA_UART_FIFO_SIZE for in buffer size
>>>>> - rename ring_enable to backend_in_domain
>>>>> - rename struct xencons_in to struct vpl011_xen_backend
>>>>> - rename inring field to xen
>>>>> - rename helper functions accordingly
>>>>> - remove unnecessary stub implementation of vpl011_rx_char
>>>>> - move vpl011_rx_char_xen within the file to avoid the need of a forward
>>>>>      declaration of vpl011_data_avail
>>>>> - fix small bug in vpl011_rx_char_xen: increment in_prod before using it
>>>>>      to check xencons_queued.
>>>>>
>>>>> Changes in v2:
>>>>> - only init if vpl011
>>>>> - rename vpl011_read_char to vpl011_rx_char
>>>>> - remove spurious change
>>>>> - fix coding style
>>>>> - use different ring struct
>>>>> - move the write_data changes to their own function
>>>>>      (vpl011_write_data_noring)
>>>>> - duplicate vpl011_read_data
>>>>> ---
>>>>>     xen/arch/arm/domain_build.c  |   9 +-
>>>>>     xen/arch/arm/vpl011.c        | 198
>>>>> ++++++++++++++++++++++++++++++++++++++-----
>>>>>     xen/include/asm-arm/vpl011.h |   8 ++
>>>>>     3 files changed, 192 insertions(+), 23 deletions(-)
>>>>>
>>>>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>>>>> index f9fa484..0888a76 100644
>>>>> --- a/xen/arch/arm/domain_build.c
>>>>> +++ b/xen/arch/arm/domain_build.c
>>>>> @@ -2638,7 +2638,14 @@ static int __init construct_domU(struct domain
>>>>> *d,
>>>>> struct dt_device_node *node)
>>>>>         if ( rc < 0 )
>>>>>             return rc;
>>>>>     -    return __construct_domain(d, &kinfo);
>>>>> +    rc = __construct_domain(d, &kinfo);
>>>>> +    if ( rc < 0 )
>>>>> +        return rc;
>>>>> +
>>>>> +    if ( kinfo.vpl011 )
>>>>> +        rc = domain_vpl011_init(d, NULL);
>>>>> +
>>>>> +    return rc;
>>>>>     }
>>>>>       void __init create_domUs(void)
>>>>> diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
>>>>> index 725a203..f206c61 100644
>>>>> --- a/xen/arch/arm/vpl011.c
>>>>> +++ b/xen/arch/arm/vpl011.c
>>>>> @@ -77,6 +77,91 @@ static void vpl011_update_interrupt_status(struct
>>>>> domain
>>>>> *d)
>>>>>     #endif
>>>>>     }
>>>>>     +/*
>>>>> + * vpl011_write_data_xen writes chars from the vpl011 out buffer to the
>>>>> + * console. Only to be used when the backend is Xen.
>>>>> + */
>>>>> +static void vpl011_write_data_xen(struct domain *d, uint8_t data)
>>>>> +{
>>>>> +    unsigned long flags;
>>>>> +    struct vpl011 *vpl011 = &d->arch.vpl011;
>>>>> +
>>>>> +    VPL011_LOCK(d, flags);
>>>>> +
>>>>> +    printk("%c", data);
>>>>> +    if (data == '\n')
>>>>> +        printk("DOM%u: ", d->domain_id);
>>>>
>>>> There are a problem in this code. The first line of a domain will always
>>>> printed without "DOM%u: " in front. This means you don't really know where
>>>> it
>>>> is coming from until you get the second line.
>>>
>>> This problem is solved by the follow-up patch that introduces characters
>>> buffering. I'll mention it in the commit message.
>>
>> To be honest, this should be solved in this patch and not the follow-up one.
> 
> I agree. I kept them separate to make them easier to review. Would you
> be OK with me merging the two patches into one once they have both been
> acked? Otherwise, if you prefer that I merge them now, let me know.

I am ok to have them merged when committing.

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v3 09/25] xen/arm: introduce bootcmdlines
  2018-10-03 23:11     ` Stefano Stabellini
@ 2018-10-04 17:23       ` Julien Grall
  2018-10-04 21:08         ` Stefano Stabellini
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-10-04 17:23 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 04/10/2018 00:11, Stefano Stabellini wrote:
> On Wed, 1 Aug 2018, Julien Grall wrote:
>>> +    {
>>> +        mod = &mods->cmdline[i];
>>> +        if ( mod->kind == kind )
>>> +            return mod;
>>> +    }
>>> +    return NULL;
>>> +}
>>> +
>>>    const char * __init boot_module_kind_as_string(bootmodule_kind kind)
>>>    {
>>>        switch ( kind )
>>> @@ -723,7 +732,7 @@ void __init start_xen(unsigned long boot_phys_offset,
>>>        /* Register Xen's load address as a boot module. */
>>>        xen_bootmodule = add_boot_module(BOOTMOD_XEN,
>>>                                 (paddr_t)(uintptr_t)(_start +
>>> boot_phys_offset),
>>> -                             (paddr_t)(uintptr_t)(_end - _start + 1),
>>> NULL);
>>> +                             (paddr_t)(uintptr_t)(_end - _start + 1));
>>>        BUG_ON(!xen_bootmodule);
>>>          xen_paddr = get_xen_paddr();
>>> diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
>>> index f1e4a3f..cb7da51 100644
>>> --- a/xen/include/asm-arm/setup.h
>>> +++ b/xen/include/asm-arm/setup.h
>>> @@ -35,6 +35,12 @@ struct bootmodule {
>>>        bootmodule_kind kind;
>>>        paddr_t start;
>>>        paddr_t size;
>>> +};
>>> +
>>> +#define DT_MAX_NAME 32
>>
>> It might be useful to explain where 32 comes from.
> 
> The limit is somewhat arbitrary. I'll explain in a comment.

Is it? I thought you got it from the specification (2.2.1 in [1]):

"Each node in the devicetree is named according to the following convention:

node-name@unit-address

The node-name component specifies the name of the node. It shall be 1 to 
31 characters in length and consist solely of characters from the set of 
characters in Table 2.1.
"

As the number does not take into account the unit-address, I would bump 
to 41 characters (8 digit for unit-address should be sufficient and 1 
for @).

Cheers,

[1] 
https://github.com/devicetree-org/devicetree-specification/releases/tag/v0.2

-- 
Julien Grall

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

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

* Re: [PATCH v3 10/25] xen/arm: don't add duplicate boot modules
  2018-08-01 11:06   ` Julien Grall
@ 2018-10-04 21:05     ` Stefano Stabellini
  0 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-10-04 21:05 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Wed, 1 Aug 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 01/08/18 00:27, Stefano Stabellini wrote:
> > Don't add duplicate boot modules (same kind and same start address).
> 
> Please explain why you don't want to duplicate it.

OK


> > 
> > Mark kernels and ramdisks of "xen,domain" nodes as BOOTMOD_KERNEL_DOMAIN
> > and BOOTMOD_RAMDISK_DOMAIN respectively, to avoid getting confused in
> > kernel_probe, where we try to guess which is the dom0 kernel and initrd
> > to be compatible with older versions of the multiboot spec.
> 
> In patch #9, you wrote we don't want duplication because of the free function.
> But it would be possible to have all the domains (including Dom0) to use the
> same kernel.
> 
> It would be better to find a different way to find Dom0 information. One way
> would be to add a flag in the boot module.

I'll add a flag.


> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > 
> > ---
> > Changes in v2:
> > - new patch
> > ---
> >   xen/arch/arm/bootfdt.c      | 7 +++++++
> >   xen/arch/arm/setup.c        | 9 +++++++++
> >   xen/include/asm-arm/setup.h | 2 ++
> >   3 files changed, 18 insertions(+)
> > 
> > diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
> > index 6f44022..dbaa8f4 100644
> > --- a/xen/arch/arm/bootfdt.c
> > +++ b/xen/arch/arm/bootfdt.c
> > @@ -256,6 +256,13 @@ static void __init process_multiboot_node(const void
> > *fdt, int node,
> >               kind = BOOTMOD_XSM;
> >       }
> >   +    if ( fdt_node_check_compatible(fdt, parent_node, "xen,domain") == 0 )
> > +    {
> > +        if ( kind == BOOTMOD_KERNEL )
> > +            kind = BOOTMOD_KERNEL_DOMAIN;
> > +        if ( kind == BOOTMOD_RAMDISK )
> > +            kind = BOOTMOD_RAMDISK_DOMAIN;
> > +    }
> >       add_boot_module(kind, start, size);
> >       add_boot_cmdline(fdt, node, fdt_get_name(fdt, parent_node, &len),
> > kind);
> >   }
> > diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> > index 67ab1fd..b1a117f 100644
> > --- a/xen/arch/arm/setup.c
> > +++ b/xen/arch/arm/setup.c
> > @@ -204,6 +204,7 @@ struct bootmodule __init
> > *add_boot_module(bootmodule_kind kind,
> >   {
> >       struct bootmodules *mods = &bootinfo.modules;
> >       struct bootmodule *mod;
> > +    int i;
> 
> unsigned please.

OK


> >         if ( mods->nr_mods == MAX_MODULES )
> >       {
> > @@ -211,6 +212,12 @@ struct bootmodule __init
> > *add_boot_module(bootmodule_kind kind,
> >                  boot_module_kind_as_string(kind), start, start + size);
> >           return NULL;
> >       }
> > +    for ( i = 0 ; i < mods->nr_mods ; i++ )
> > +    {
> > +        mod = &mods->module[i];
> > +        if ( mod->kind == kind && mod->start == start )
> > +            return mod;
> > +    }
> >         mod = &mods->module[mods->nr_mods++];
> >       mod->kind = kind;
> > @@ -257,6 +264,8 @@ const char * __init
> > boot_module_kind_as_string(bootmodule_kind kind)
> >       case BOOTMOD_KERNEL:  return "Kernel";
> >       case BOOTMOD_RAMDISK: return "Ramdisk";
> >       case BOOTMOD_XSM:     return "XSM";
> > +    case BOOTMOD_KERNEL_DOMAIN:  return "DomU Kernel";
> > +    case BOOTMOD_RAMDISK_DOMAIN: return "DomU Ramdisk";
> >       case BOOTMOD_UNKNOWN: return "Unknown";
> >       default: BUG();
> >       }
> > diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
> > index cb7da51..353c32a 100644
> > --- a/xen/include/asm-arm/setup.h
> > +++ b/xen/include/asm-arm/setup.h
> > @@ -16,6 +16,8 @@ typedef enum {
> >       BOOTMOD_KERNEL,
> >       BOOTMOD_RAMDISK,
> >       BOOTMOD_XSM,
> > +    BOOTMOD_KERNEL_DOMAIN,
> > +    BOOTMOD_RAMDISK_DOMAIN,
> >       BOOTMOD_UNKNOWN
> >   }  bootmodule_kind;

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

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

* Re: [PATCH v3 09/25] xen/arm: introduce bootcmdlines
  2018-10-04 17:23       ` Julien Grall
@ 2018-10-04 21:08         ` Stefano Stabellini
  0 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-10-04 21:08 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Thu, 4 Oct 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 04/10/2018 00:11, Stefano Stabellini wrote:
> > On Wed, 1 Aug 2018, Julien Grall wrote:
> > > > +    {
> > > > +        mod = &mods->cmdline[i];
> > > > +        if ( mod->kind == kind )
> > > > +            return mod;
> > > > +    }
> > > > +    return NULL;
> > > > +}
> > > > +
> > > >    const char * __init boot_module_kind_as_string(bootmodule_kind kind)
> > > >    {
> > > >        switch ( kind )
> > > > @@ -723,7 +732,7 @@ void __init start_xen(unsigned long
> > > > boot_phys_offset,
> > > >        /* Register Xen's load address as a boot module. */
> > > >        xen_bootmodule = add_boot_module(BOOTMOD_XEN,
> > > >                                 (paddr_t)(uintptr_t)(_start +
> > > > boot_phys_offset),
> > > > -                             (paddr_t)(uintptr_t)(_end - _start + 1),
> > > > NULL);
> > > > +                             (paddr_t)(uintptr_t)(_end - _start + 1));
> > > >        BUG_ON(!xen_bootmodule);
> > > >          xen_paddr = get_xen_paddr();
> > > > diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
> > > > index f1e4a3f..cb7da51 100644
> > > > --- a/xen/include/asm-arm/setup.h
> > > > +++ b/xen/include/asm-arm/setup.h
> > > > @@ -35,6 +35,12 @@ struct bootmodule {
> > > >        bootmodule_kind kind;
> > > >        paddr_t start;
> > > >        paddr_t size;
> > > > +};
> > > > +
> > > > +#define DT_MAX_NAME 32
> > > 
> > > It might be useful to explain where 32 comes from.
> > 
> > The limit is somewhat arbitrary. I'll explain in a comment.
> 
> Is it? I thought you got it from the specification (2.2.1 in [1]):
> 
> "Each node in the devicetree is named according to the following convention:
> 
> node-name@unit-address
> 
> The node-name component specifies the name of the node. It shall be 1 to 31
> characters in length and consist solely of characters from the set of
> characters in Table 2.1.
> "
> 
> As the number does not take into account the unit-address, I would bump to 41
> characters (8 digit for unit-address should be sufficient and 1 for @).

Will do, thanks for looking up the spec, I forgot about it


> Cheers,
> 
> [1]
> https://github.com/devicetree-org/devicetree-specification/releases/tag/v0.2

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

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

* Re: [PATCH v3 24/25] xen/vpl011: buffer out chars when the backend is xen
  2018-08-22 10:35       ` Julien Grall
@ 2018-10-04 21:29         ` Stefano Stabellini
  0 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-10-04 21:29 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

Hi Julien,

I'll remove the DOM prefix for the input domain, relying to the
"Switching..." message as you suggested.

Cheers,

Stefano

On Wed, 22 Aug 2018, Julien Grall wrote:
> Hi,
> 
> On 16/08/18 20:41, Stefano Stabellini wrote:
> > On Mon, 13 Aug 2018, Julien Grall wrote:
> > > Hi,
> > > 
> > > On 01/08/18 00:28, Stefano Stabellini wrote:
> > > > To avoid mixing the output of different domains on the console, buffer
> > > > the output chars and print line by line. Unless the domain has input
> > > > from the serial, in which case we want to print char by char for a
> > > > smooth user experience.
> > > > 
> > > > The size of SBSA_UART_OUT_BUF_SIZE is arbitrary. 90 should be large
> > > > enough to accommodate the length of most lines of output (typically they
> > > > are limited to 80 characters on Unix systems), plus one extra char for
> > > > the string terminator.
> > > 
> > > How about using the same value as vuart (e.g VUART_BUT_SIZE) instead? So
> > > we
> > > buffer the same way for the vpl011?
> > 
> > Yes, I can do that.
> > 
> > 
> > > > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > > > ---
> > > >    xen/arch/arm/vpl011.c        | 21 ++++++++++++++++++---
> > > >    xen/include/asm-arm/vpl011.h |  3 +++
> > > >    2 files changed, 21 insertions(+), 3 deletions(-)
> > > > 
> > > > diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> > > > index f206c61..8137371 100644
> > > > --- a/xen/arch/arm/vpl011.c
> > > > +++ b/xen/arch/arm/vpl011.c
> > > > @@ -28,6 +28,7 @@
> > > >    #include <xen/lib.h>
> > > >    #include <xen/mm.h>
> > > >    #include <xen/sched.h>
> > > > +#include <xen/console.h>
> > > >    #include <public/domctl.h>
> > > >    #include <public/io/console.h>
> > > >    #include <asm/pl011-uart.h>
> > > > @@ -85,12 +86,26 @@ static void vpl011_write_data_xen(struct domain *d,
> > > > uint8_t data)
> > > >    {
> > > >        unsigned long flags;
> > > >        struct vpl011 *vpl011 = &d->arch.vpl011;
> > > > +    struct vpl011_xen_backend *intf = vpl011->xen;
> > > > +    struct domain *input = console_input_domain();
> > > >          VPL011_LOCK(d, flags);
> > > >    -    printk("%c", data);
> > > > -    if (data == '\n')
> > > > -        printk("DOM%u: ", d->domain_id);
> > > > +    intf->out[intf->out_prod++] = data;
> > > > +    if ( d == input && intf->out_prod == 1 )
> > > > +    {
> > > > +        printk("%c", data);
> > > > +        if ( data == '\n' )
> > > > +            printk("DOM%u: ", d->domain_id);
> > > > +        intf->out_prod = 0;
> > > 
> > > See my remark on the patch implementing vpl011_write_data_xen.
> > 
> > With this patch, the missing "DOM" at the beginning cannot happen
> > anymore due to the out buffering. Theoretically it can still happen by
> > switching to DOM1 before DOM1 prints anything, but it is impossible to
> > do in practice.
> 
> How come this is impossible? DOM1 may have print very late and therefore you
> have time to switch to DOM1 before any print.
> 
> > Even in this theoretical scenario, the user would still
> > get the useful "Switching to DOM1" message, that would help clarify what
> > is going on. Thus, my preference is to avoid making the code more
> > complex to fix this issue.
> 
> I don't like the idea that in some case DOM%u: is not printed in front of the
> line. This is making more difficult to read the logs.
> 
> > 
> > 
> > > > +    } else if ( d == input ||
> > > 
> > > Coding style:
> > > 
> > > }
> > > else if
> > > {
> > 
> > I'll fix
> > 
> > 
> > > > +                intf->out_prod == SBSA_UART_OUT_BUF_SIZE - 1 ||
> > > > +                data == '\n' )
> > > > +    {
> > > > +        intf->out[intf->out_prod++] = '\0';
> > > > +        printk("DOM%u: %s", d->domain_id, intf->out);
> > > > +        intf->out_prod = 0;
> > > > +    }
> > > 
> > > The code is quite difficult to read. It would be easier to differentiate
> > > (domain == input vs domain != input) even if it means a bit of
> > > duplication.
> > 
> > OK, I can rearrange the code that way. For example:
> > 
> >      if ( d == input ){
> >          if ( intf->out_prod == 1 )
> >          {
> >              printk("%c", data);
> >              if ( data == '\n' )
> >                  printk("DOM%u: ", d->domain_id);
> >              intf->out_prod = 0;
> >          }
> >          else
> >          {
> >              if ( data != '\n' )
> >                  intf->out[intf->out_prod++] = '\n';
> >              intf->out[intf->out_prod++] = '\0';
> >              printk("DOM%u: %s", d->domain_id, intf->out);
> >              intf->out_prod = 0;
> >          }
> >      }
> >      else
> >      {
> >          if ( intf->out_prod == SBSA_UART_OUT_BUF_SIZE - 2 ||
> >               data == '\n' )
> >          {
> >              if ( data != '\n' )
> >                  intf->out[intf->out_prod++] = '\n';
> >              intf->out[intf->out_prod++] = '\0';
> >              printk("DOM%u: %s", d->domain_id, intf->out);
> >              intf->out_prod = 0;
> >          }
> >      }
> > 
> > Is it better?
> 
> Looks easier to read.
> 
> > 
> > 
> > > You also don't handle all the cases.
> > > 
> > > For the input domain, I don't think you want to print the domain in front.
> > > Instead I would rely on the "Switch to ...".
> > 
> > Actually it is very convenient to know at any given time which domain
> > you are talking to. I couldn't find any problems with the prefix, even
> > using VIM, etc. I would rather keep the "DOM" string around.
> 
> Well it is convenient if you manage to put "DOM" string in front. From a look
> at your implementation and your own comment this is not always the case.
> 
> I am also quite surprised that this does not make VIM (or any other editor)
> more difficult to use as "DOM:" is printed in front of each line.
> 
> > 
> > 
> > > This would avoid the problem
> > > where DomB needs to have his line printed while it is not the console
> > > input.
> > > If this happens in the middle of DomA, then you are loosing track what's
> > > going
> > > on.
> > 
> > I don't understand the example: if DOM1 has input, and DOM2 prints
> > something, the DOM2 output will be prepended by "DOM2", avoiding any
> > confusion. What am I missing?
> 
> Let's take an example:
> 	1) DOM1 writes "\nab"
> 	2) DOM2 writes "Foobar\n"
> 	3) DOM1 write "cde"
> 
> The output would be:
> 
> DOM1: ab DOM2: Foobar
> cde
> 
> DOM1 and DOM2 has the line combined (not a big deal). However, the next few
> characters for DOM1 "cde" will not be prefixed with "DOM1:".
> 
> Cheers,
> 
> -- 
> Julien Grall
> 

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

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

* Re: [PATCH v3 23/25] xen: support console_switching between Dom0 and DomUs on ARM
  2018-08-01  9:03   ` Jan Beulich
@ 2018-10-04 21:52     ` Stefano Stabellini
  2018-10-05  9:25       ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Stefano Stabellini @ 2018-10-04 21:52 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Stefano Stabellini, Ian Jackson,
	xen-devel, Julien Grall, andrii_anisov

On Wed, 1 Aug 2018, Jan Beulich wrote:
> >>> On 01.08.18 at 01:28, <sstabellini@kernel.org> wrote:
> > Today Ctrl-AAA is used to switch between Xen and Dom0. Extend the
> > mechanism to allow for switching between Xen, Dom0, and any of the
> > initial DomU created from Xen alongside Dom0 out of information provided
> > via device tree.
> > 
> > Rename xen_rx to console_rx to match the new behavior.
> > 
> > Clarify existing comment about "notify the guest", making it clear that
> > it is only about the hardware domain.
> > 
> > Export a function named console_input_domain() to allow others to know
> > which domains has input at a given time.
> 
> As always in such cases I don't think such functions should be added
> without any caller.

I'll add console_input_domain within an #if 0 and remove the #if 0 in
the following patch. If you are OK with it, the two patches can be
merged on commit (Julien already agreed to it.) They are separate only
to make them easier to review.


> > @@ -389,30 +392,72 @@ static void dump_console_ring_key(unsigned char key)
> >      free_xenheap_pages(buf, order);
> >  }
> >  
> > -/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
> > +/*
> > + * CTRL-<switch_char> switches input direction between Xen, Dom0 and
> > + * DomUs.
> > + */
> >  #define switch_code (opt_conswitch[0]-'a'+1)
> > -static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain 0. */
> > +/*
> > + * console_rx=0 => input to xen
> > + * console_rx=1 => input to dom0
> > + * console_rx=N => input dom(N-1)
> > + */
> > +static int __read_mostly console_rx = 0;
> 
> Originally this was supposed to be bool, but didn't get switched yet.
> With your current scheme it can't go negative and hence should be
> unsigned int. However, I still wonder whether it wouldn't be better
> (especially for readers of the code) is this was an actual domid_t.
> But as clarified before, I'm not meaning to make this a requirement.

I'll use unsigned int


> > +struct domain *console_input_domain(void)
> > +{
> > +    return get_domain_by_id(console_rx - 1);
> > +}
> 
> And this is exactly the reason for the above remark: This is (or at
> least looks) broken for console_rx == 0.

I'll fix


> >  static void switch_serial_input(void)
> >  {
> > -    static char *input_str[2] = { "DOM0", "Xen" };
> > -    xen_rx = !xen_rx;
> > -    printk("*** Serial input -> %s", input_str[xen_rx]);
> > +    console_rx++;
> > +    if ( console_rx == max_init_domid + 2 )
> > +        console_rx = 0;
> 
> Same here - the literal 2 at least raises questions. I think it would
> at least be a little less confusing if you had
> 
>     if ( console_rx++ == max_init_domid + 1 )
>         console_rx = 0;

I'll do


> >  static void __serial_rx(char c, struct cpu_user_regs *regs)
> >  {
> > -    if ( xen_rx )
> > +    if ( console_rx == 0 )
> >          return handle_keypress(c, regs);
> >  
> > -    /* Deliver input to guest buffer, unless it is already full. */
> > -    if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
> > -        serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> > -    /* Always notify the guest: prevents receive path from getting stuck. */
> 
> Just like you adjust "guest" in this comment, I think you'd better ...
> 
> > +    if ( console_rx == 1 )
> > +    {
> > +        /* Deliver input to guest buffer, unless it is already full. */
> 
> ... adjust it here too.

I'll fix


> > +        if ( (serial_rx_prod - serial_rx_cons) != SERIAL_RX_SIZE )
> > +            serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> > +    }
> > +#ifdef CONFIG_SBSA_VUART_CONSOLE
> > +    else
> > +    {
> > +        struct domain *d = get_domain_by_id(console_rx - 1);
> > +
> > +        /*
> > +         * If we have a properly initialized vpl011 console for the
> > +         * domain, without a full PV ring to Dom0 (in that case input
> > +         * comes from the PV ring), then send the character to it.
> > +         */
> > +        if ( !d->arch.vpl011.backend_in_domain && d->arch.vpl011.xen != NULL )
> > +            vpl011_rx_char_xen(d, c);
> > +        else
> > +            printk("Cannot send chars to Dom%d: no UART available\n",
> > +                   d->domain_id);
> > +    }
> > +#endif
> > +    /*
> > +     * Always notify the hardware domain: prevents receive path from
> > +     * getting stuck.
> > +     */
> >      send_global_virq(VIRQ_CONSOLE);
> 
> Why does this not move into the if() body above?

That was a mistake, I fixed it


> > @@ -923,7 +968,7 @@ void __init console_endboot(void)
> >       * a useful 'how to switch' message.
> >       */
> >      if ( opt_conswitch[1] == 'x' )
> > -        xen_rx = !xen_rx;
> > +        console_rx = 0;
> 
> According to the comment I think you need to store
> max_init_domid + 1 here, so that the switch_serial_input() a few
> lines down would actually switch to Xen.

I'll fix

Thanks for the comments!

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

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

* Re: [PATCH v3 23/25] xen: support console_switching between Dom0 and DomUs on ARM
  2018-10-04 21:52     ` Stefano Stabellini
@ 2018-10-05  9:25       ` Julien Grall
  2018-10-05  9:48         ` Julien Grall
  2018-10-05 18:39         ` Stefano Stabellini
  0 siblings, 2 replies; 88+ messages in thread
From: Julien Grall @ 2018-10-05  9:25 UTC (permalink / raw)
  To: Stefano Stabellini, Jan Beulich
  Cc: Tim Deegan, Wei Liu, Konrad Rzeszutek Wilk, George Dunlap,
	Andrew Cooper, Stefano Stabellini, Ian Jackson, xen-devel,
	andrii_anisov

Hi Stefano,

On 10/04/2018 10:52 PM, Stefano Stabellini wrote:
> On Wed, 1 Aug 2018, Jan Beulich wrote:
>>>>> On 01.08.18 at 01:28, <sstabellini@kernel.org> wrote:
>>> Today Ctrl-AAA is used to switch between Xen and Dom0. Extend the
>>> mechanism to allow for switching between Xen, Dom0, and any of the
>>> initial DomU created from Xen alongside Dom0 out of information provided
>>> via device tree.
>>>
>>> Rename xen_rx to console_rx to match the new behavior.
>>>
>>> Clarify existing comment about "notify the guest", making it clear that
>>> it is only about the hardware domain.
>>>
>>> Export a function named console_input_domain() to allow others to know
>>> which domains has input at a given time.
>>
>> As always in such cases I don't think such functions should be added
>> without any caller.
> 
> I'll add console_input_domain within an #if 0 and remove the #if 0 in
> the following patch. If you are OK with it, the two patches can be
> merged on commit (Julien already agreed to it.) They are separate only
> to make them easier to review.

Which two patches? I agreed to merge #24 and #22. Not #23. Merging the 3 
of them is going to make a massive patch which is not going to help 
understand patches after they get merged.

Cheers,

> 
> 
>>> @@ -389,30 +392,72 @@ static void dump_console_ring_key(unsigned char key)
>>>       free_xenheap_pages(buf, order);
>>>   }
>>>   
>>> -/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
>>> +/*
>>> + * CTRL-<switch_char> switches input direction between Xen, Dom0 and
>>> + * DomUs.
>>> + */
>>>   #define switch_code (opt_conswitch[0]-'a'+1)
>>> -static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain 0. */
>>> +/*
>>> + * console_rx=0 => input to xen
>>> + * console_rx=1 => input to dom0
>>> + * console_rx=N => input dom(N-1)
>>> + */
>>> +static int __read_mostly console_rx = 0;
>>
>> Originally this was supposed to be bool, but didn't get switched yet.
>> With your current scheme it can't go negative and hence should be
>> unsigned int. However, I still wonder whether it wouldn't be better
>> (especially for readers of the code) is this was an actual domid_t.
>> But as clarified before, I'm not meaning to make this a requirement.
> 
> I'll use unsigned int
> 
> 
>>> +struct domain *console_input_domain(void)
>>> +{
>>> +    return get_domain_by_id(console_rx - 1);
>>> +}
>>
>> And this is exactly the reason for the above remark: This is (or at
>> least looks) broken for console_rx == 0.
> 
> I'll fix
> 
> 
>>>   static void switch_serial_input(void)
>>>   {
>>> -    static char *input_str[2] = { "DOM0", "Xen" };
>>> -    xen_rx = !xen_rx;
>>> -    printk("*** Serial input -> %s", input_str[xen_rx]);
>>> +    console_rx++;
>>> +    if ( console_rx == max_init_domid + 2 )
>>> +        console_rx = 0;
>>
>> Same here - the literal 2 at least raises questions. I think it would
>> at least be a little less confusing if you had
>>
>>      if ( console_rx++ == max_init_domid + 1 )
>>          console_rx = 0;
> 
> I'll do
> 
> 
>>>   static void __serial_rx(char c, struct cpu_user_regs *regs)
>>>   {
>>> -    if ( xen_rx )
>>> +    if ( console_rx == 0 )
>>>           return handle_keypress(c, regs);
>>>   
>>> -    /* Deliver input to guest buffer, unless it is already full. */
>>> -    if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
>>> -        serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
>>> -    /* Always notify the guest: prevents receive path from getting stuck. */
>>
>> Just like you adjust "guest" in this comment, I think you'd better ...
>>
>>> +    if ( console_rx == 1 )
>>> +    {
>>> +        /* Deliver input to guest buffer, unless it is already full. */
>>
>> ... adjust it here too.
> 
> I'll fix
> 
> 
>>> +        if ( (serial_rx_prod - serial_rx_cons) != SERIAL_RX_SIZE )
>>> +            serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
>>> +    }
>>> +#ifdef CONFIG_SBSA_VUART_CONSOLE
>>> +    else
>>> +    {
>>> +        struct domain *d = get_domain_by_id(console_rx - 1);
>>> +
>>> +        /*
>>> +         * If we have a properly initialized vpl011 console for the
>>> +         * domain, without a full PV ring to Dom0 (in that case input
>>> +         * comes from the PV ring), then send the character to it.
>>> +         */
>>> +        if ( !d->arch.vpl011.backend_in_domain && d->arch.vpl011.xen != NULL )
>>> +            vpl011_rx_char_xen(d, c);
>>> +        else
>>> +            printk("Cannot send chars to Dom%d: no UART available\n",
>>> +                   d->domain_id);
>>> +    }
>>> +#endif
>>> +    /*
>>> +     * Always notify the hardware domain: prevents receive path from
>>> +     * getting stuck.
>>> +     */
>>>       send_global_virq(VIRQ_CONSOLE);
>>
>> Why does this not move into the if() body above?
> 
> That was a mistake, I fixed it
> 
> 
>>> @@ -923,7 +968,7 @@ void __init console_endboot(void)
>>>        * a useful 'how to switch' message.
>>>        */
>>>       if ( opt_conswitch[1] == 'x' )
>>> -        xen_rx = !xen_rx;
>>> +        console_rx = 0;
>>
>> According to the comment I think you need to store
>> max_init_domid + 1 here, so that the switch_serial_input() a few
>> lines down would actually switch to Xen.
> 
> I'll fix
> 
> Thanks for the comments!
> 

-- 
Julien Grall

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

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

* Re: [PATCH v3 23/25] xen: support console_switching between Dom0 and DomUs on ARM
  2018-10-05  9:25       ` Julien Grall
@ 2018-10-05  9:48         ` Julien Grall
  2018-10-05 18:39           ` Stefano Stabellini
  2018-10-05 18:39         ` Stefano Stabellini
  1 sibling, 1 reply; 88+ messages in thread
From: Julien Grall @ 2018-10-05  9:48 UTC (permalink / raw)
  To: Stefano Stabellini, Jan Beulich
  Cc: Tim Deegan, Wei Liu, Konrad Rzeszutek Wilk, George Dunlap,
	Andrew Cooper, Stefano Stabellini, Ian Jackson, xen-devel,
	andrii_anisov

On 10/05/2018 10:25 AM, Julien Grall wrote:
> On 10/04/2018 10:52 PM, Stefano Stabellini wrote:
>> On Wed, 1 Aug 2018, Jan Beulich wrote:
>>>>>> On 01.08.18 at 01:28, <sstabellini@kernel.org> wrote:
>>>> Today Ctrl-AAA is used to switch between Xen and Dom0. Extend the
>>>> mechanism to allow for switching between Xen, Dom0, and any of the
>>>> initial DomU created from Xen alongside Dom0 out of information 
>>>> provided
>>>> via device tree.
>>>>
>>>> Rename xen_rx to console_rx to match the new behavior.
>>>>
>>>> Clarify existing comment about "notify the guest", making it clear that
>>>> it is only about the hardware domain.
>>>>
>>>> Export a function named console_input_domain() to allow others to know
>>>> which domains has input at a given time.
>>>
>>> As always in such cases I don't think such functions should be added
>>> without any caller.
>>
>> I'll add console_input_domain within an #if 0 and remove the #if 0 in
>> the following patch. If you are OK with it, the two patches can be
>> merged on commit (Julien already agreed to it.) They are separate only
>> to make them easier to review.
> 
> Which two patches? I agreed to merge #24 and #22. Not #23. Merging the 3 
> of them is going to make a massive patch which is not going to help 
> understand patches after they get merged.

Thinking a bit more. Why does it need to be under #if 0 and then merging 
the 2 patches? There are nothing prevent a 2 line function to be moved 
from one patch to another.

Cheers.

-- 
Julien Grall

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

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

* Re: [PATCH v3 23/25] xen: support console_switching between Dom0 and DomUs on ARM
  2018-10-05  9:48         ` Julien Grall
@ 2018-10-05 18:39           ` Stefano Stabellini
  0 siblings, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-10-05 18:39 UTC (permalink / raw)
  To: Julien Grall
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Stefano Stabellini, Ian Jackson,
	xen-devel, Jan Beulich, andrii_anisov

On Fri, 5 Oct 2018, Julien Grall wrote:
> On 10/05/2018 10:25 AM, Julien Grall wrote:
> > On 10/04/2018 10:52 PM, Stefano Stabellini wrote:
> > > On Wed, 1 Aug 2018, Jan Beulich wrote:
> > > > > > > On 01.08.18 at 01:28, <sstabellini@kernel.org> wrote:
> > > > > Today Ctrl-AAA is used to switch between Xen and Dom0. Extend the
> > > > > mechanism to allow for switching between Xen, Dom0, and any of the
> > > > > initial DomU created from Xen alongside Dom0 out of information
> > > > > provided
> > > > > via device tree.
> > > > > 
> > > > > Rename xen_rx to console_rx to match the new behavior.
> > > > > 
> > > > > Clarify existing comment about "notify the guest", making it clear
> > > > > that
> > > > > it is only about the hardware domain.
> > > > > 
> > > > > Export a function named console_input_domain() to allow others to know
> > > > > which domains has input at a given time.
> > > > 
> > > > As always in such cases I don't think such functions should be added
> > > > without any caller.
> > > 
> > > I'll add console_input_domain within an #if 0 and remove the #if 0 in
> > > the following patch. If you are OK with it, the two patches can be
> > > merged on commit (Julien already agreed to it.) They are separate only
> > > to make them easier to review.
> > 
> > Which two patches? I agreed to merge #24 and #22. Not #23. Merging the 3 of
> > them is going to make a massive patch which is not going to help understand
> > patches after they get merged.
> 
> Thinking a bit more. Why does it need to be under #if 0 and then merging the 2
> patches? There are nothing prevent a 2 line function to be moved from one
> patch to another.

I'll move console_input_domain to the following patch (#24).

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

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

* Re: [PATCH v3 23/25] xen: support console_switching between Dom0 and DomUs on ARM
  2018-10-05  9:25       ` Julien Grall
  2018-10-05  9:48         ` Julien Grall
@ 2018-10-05 18:39         ` Stefano Stabellini
  1 sibling, 0 replies; 88+ messages in thread
From: Stefano Stabellini @ 2018-10-05 18:39 UTC (permalink / raw)
  To: Julien Grall
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Stefano Stabellini, Ian Jackson,
	xen-devel, Jan Beulich, andrii_anisov

On Fri, 5 Oct 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 10/04/2018 10:52 PM, Stefano Stabellini wrote:
> > On Wed, 1 Aug 2018, Jan Beulich wrote:
> > > > > > On 01.08.18 at 01:28, <sstabellini@kernel.org> wrote:
> > > > Today Ctrl-AAA is used to switch between Xen and Dom0. Extend the
> > > > mechanism to allow for switching between Xen, Dom0, and any of the
> > > > initial DomU created from Xen alongside Dom0 out of information provided
> > > > via device tree.
> > > > 
> > > > Rename xen_rx to console_rx to match the new behavior.
> > > > 
> > > > Clarify existing comment about "notify the guest", making it clear that
> > > > it is only about the hardware domain.
> > > > 
> > > > Export a function named console_input_domain() to allow others to know
> > > > which domains has input at a given time.
> > > 
> > > As always in such cases I don't think such functions should be added
> > > without any caller.
> > 
> > I'll add console_input_domain within an #if 0 and remove the #if 0 in
> > the following patch. If you are OK with it, the two patches can be
> > merged on commit (Julien already agreed to it.) They are separate only
> > to make them easier to review.
> 
> Which two patches? I agreed to merge #24 and #22. Not #23. Merging the 3 of
> them is going to make a massive patch which is not going to help understand
> patches after they get merged.

No, you are right, I got confused. That's correct #22 and #24 are the
ones to be merged, I'll add a note about this to the patches. Sorry
about that.


> > 
> > > > @@ -389,30 +392,72 @@ static void dump_console_ring_key(unsigned char
> > > > key)
> > > >       free_xenheap_pages(buf, order);
> > > >   }
> > > >   -/* CTRL-<switch_char> switches input direction between Xen and DOM0.
> > > > */
> > > > +/*
> > > > + * CTRL-<switch_char> switches input direction between Xen, Dom0 and
> > > > + * DomUs.
> > > > + */
> > > >   #define switch_code (opt_conswitch[0]-'a'+1)
> > > > -static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain
> > > > 0. */
> > > > +/*
> > > > + * console_rx=0 => input to xen
> > > > + * console_rx=1 => input to dom0
> > > > + * console_rx=N => input dom(N-1)
> > > > + */
> > > > +static int __read_mostly console_rx = 0;
> > > 
> > > Originally this was supposed to be bool, but didn't get switched yet.
> > > With your current scheme it can't go negative and hence should be
> > > unsigned int. However, I still wonder whether it wouldn't be better
> > > (especially for readers of the code) is this was an actual domid_t.
> > > But as clarified before, I'm not meaning to make this a requirement.
> > 
> > I'll use unsigned int
> > 
> > 
> > > > +struct domain *console_input_domain(void)
> > > > +{
> > > > +    return get_domain_by_id(console_rx - 1);
> > > > +}
> > > 
> > > And this is exactly the reason for the above remark: This is (or at
> > > least looks) broken for console_rx == 0.
> > 
> > I'll fix
> > 
> > 
> > > >   static void switch_serial_input(void)
> > > >   {
> > > > -    static char *input_str[2] = { "DOM0", "Xen" };
> > > > -    xen_rx = !xen_rx;
> > > > -    printk("*** Serial input -> %s", input_str[xen_rx]);
> > > > +    console_rx++;
> > > > +    if ( console_rx == max_init_domid + 2 )
> > > > +        console_rx = 0;
> > > 
> > > Same here - the literal 2 at least raises questions. I think it would
> > > at least be a little less confusing if you had
> > > 
> > >      if ( console_rx++ == max_init_domid + 1 )
> > >          console_rx = 0;
> > 
> > I'll do
> > 
> > 
> > > >   static void __serial_rx(char c, struct cpu_user_regs *regs)
> > > >   {
> > > > -    if ( xen_rx )
> > > > +    if ( console_rx == 0 )
> > > >           return handle_keypress(c, regs);
> > > >   -    /* Deliver input to guest buffer, unless it is already full. */
> > > > -    if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
> > > > -        serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> > > > -    /* Always notify the guest: prevents receive path from getting
> > > > stuck. */
> > > 
> > > Just like you adjust "guest" in this comment, I think you'd better ...
> > > 
> > > > +    if ( console_rx == 1 )
> > > > +    {
> > > > +        /* Deliver input to guest buffer, unless it is already full. */
> > > 
> > > ... adjust it here too.
> > 
> > I'll fix
> > 
> > 
> > > > +        if ( (serial_rx_prod - serial_rx_cons) != SERIAL_RX_SIZE )
> > > > +            serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> > > > +    }
> > > > +#ifdef CONFIG_SBSA_VUART_CONSOLE
> > > > +    else
> > > > +    {
> > > > +        struct domain *d = get_domain_by_id(console_rx - 1);
> > > > +
> > > > +        /*
> > > > +         * If we have a properly initialized vpl011 console for the
> > > > +         * domain, without a full PV ring to Dom0 (in that case input
> > > > +         * comes from the PV ring), then send the character to it.
> > > > +         */
> > > > +        if ( !d->arch.vpl011.backend_in_domain && d->arch.vpl011.xen !=
> > > > NULL )
> > > > +            vpl011_rx_char_xen(d, c);
> > > > +        else
> > > > +            printk("Cannot send chars to Dom%d: no UART available\n",
> > > > +                   d->domain_id);
> > > > +    }
> > > > +#endif
> > > > +    /*
> > > > +     * Always notify the hardware domain: prevents receive path from
> > > > +     * getting stuck.
> > > > +     */
> > > >       send_global_virq(VIRQ_CONSOLE);
> > > 
> > > Why does this not move into the if() body above?
> > 
> > That was a mistake, I fixed it
> > 
> > 
> > > > @@ -923,7 +968,7 @@ void __init console_endboot(void)
> > > >        * a useful 'how to switch' message.
> > > >        */
> > > >       if ( opt_conswitch[1] == 'x' )
> > > > -        xen_rx = !xen_rx;
> > > > +        console_rx = 0;
> > > 
> > > According to the comment I think you need to store
> > > max_init_domid + 1 here, so that the switch_serial_input() a few
> > > lines down would actually switch to Xen.
> > 
> > I'll fix
> > 
> > Thanks for the comments!
> > 


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

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

end of thread, other threads:[~2018-10-05 18:39 UTC | newest]

Thread overview: 88+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-31 23:27 [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
2018-07-31 23:27 ` [PATCH v3 01/25] xen: allow console_io hypercalls from certain DomUs Stefano Stabellini
2018-08-17 19:33   ` Daniel De Graaf
2018-07-31 23:27 ` [PATCH v3 02/25] xen/arm: move a few DT related defines to public/device_tree_defs.h Stefano Stabellini
2018-08-01  9:31   ` Julien Grall
2018-08-22 15:25     ` Wei Liu
2018-07-31 23:27 ` [PATCH v3 03/25] xen/arm: extend device tree based multiboot protocol Stefano Stabellini
2018-07-31 23:27 ` [PATCH v3 04/25] xen/arm: document dom0less Stefano Stabellini
2018-08-01  9:46   ` Julien Grall
2018-10-03 16:47     ` Stefano Stabellini
2018-07-31 23:27 ` [PATCH v3 05/25] xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node Stefano Stabellini
2018-08-01  9:50   ` Julien Grall
2018-07-31 23:27 ` [PATCH v3 06/25] xen/arm: move evtchn_allocate call out of make_hypervisor_node Stefano Stabellini
2018-08-01  9:51   ` Julien Grall
2018-07-31 23:27 ` [PATCH v3 07/25] xen/arm: rename acpi_make_chosen_node to make_chosen_node Stefano Stabellini
2018-08-01  9:53   ` Julien Grall
2018-07-31 23:27 ` [PATCH v3 08/25] xen/arm: increase MAX_MODULES Stefano Stabellini
2018-07-31 23:27 ` [PATCH v3 09/25] xen/arm: introduce bootcmdlines Stefano Stabellini
2018-08-01 10:51   ` Julien Grall
2018-10-03 23:11     ` Stefano Stabellini
2018-10-04 17:23       ` Julien Grall
2018-10-04 21:08         ` Stefano Stabellini
2018-07-31 23:27 ` [PATCH v3 10/25] xen/arm: don't add duplicate boot modules Stefano Stabellini
2018-08-01 11:06   ` Julien Grall
2018-10-04 21:05     ` Stefano Stabellini
2018-07-31 23:27 ` [PATCH v3 11/25] xen/arm: probe domU kernels and initrds Stefano Stabellini
2018-07-31 23:27 ` [PATCH v3 12/25] xen/arm: refactor construct_dom0 Stefano Stabellini
2018-08-13 10:15   ` Julien Grall
2018-08-15 19:27     ` Stefano Stabellini
2018-07-31 23:27 ` [PATCH v3 13/25] xen/arm: introduce create_domUs Stefano Stabellini
2018-08-01  8:48   ` Jan Beulich
2018-08-13 10:23   ` Julien Grall
2018-08-15 19:37     ` Stefano Stabellini
2018-08-13 10:55   ` Julien Grall
2018-08-15 20:04     ` Stefano Stabellini
2018-08-16  9:03       ` Julien Grall
2018-08-16 18:20         ` Stefano Stabellini
2018-07-31 23:27 ` [PATCH v3 14/25] xen/arm: introduce construct_domU Stefano Stabellini
2018-08-13 10:55   ` Julien Grall
2018-08-15 20:21     ` Stefano Stabellini
2018-07-31 23:27 ` [PATCH v3 15/25] xen/arm: rename get_11_allocation_size to get_allocation_size Stefano Stabellini
2018-07-31 23:27 ` [PATCH v3 16/25] xen/arm: rename allocate_memory to allocate_memory_11 Stefano Stabellini
2018-08-13 10:57   ` Julien Grall
2018-08-15 20:26     ` Stefano Stabellini
2018-08-16  9:08       ` Julien Grall
2018-08-16 18:27         ` Stefano Stabellini
2018-07-31 23:28 ` [PATCH v3 17/25] xen/arm: introduce allocate_memory Stefano Stabellini
2018-08-01 11:28   ` Julien Grall
2018-10-03 17:46     ` Stefano Stabellini
2018-07-31 23:28 ` [PATCH v3 18/25] xen/arm: generate a simple device tree for domUs Stefano Stabellini
2018-08-13 11:07   ` Julien Grall
2018-08-15 20:47     ` Stefano Stabellini
2018-07-31 23:28 ` [PATCH v3 19/25] xen/arm: generate vpl011 node on device tree for domU Stefano Stabellini
2018-08-13 11:20   ` Julien Grall
2018-08-15 23:23     ` Stefano Stabellini
2018-07-31 23:28 ` [PATCH v3 20/25] xen/arm: introduce a union in vpl011 Stefano Stabellini
2018-08-13 11:24   ` Julien Grall
2018-08-15 23:36     ` Stefano Stabellini
2018-07-31 23:28 ` [PATCH v3 21/25] xen/arm: refactor vpl011_data_avail Stefano Stabellini
2018-08-13 13:23   ` Julien Grall
2018-07-31 23:28 ` [PATCH v3 22/25] xen/arm: Allow vpl011 to be used by DomU Stefano Stabellini
2018-08-13 13:42   ` Julien Grall
2018-08-15 23:41     ` Stefano Stabellini
2018-08-13 14:10   ` Julien Grall
2018-08-16 19:21     ` Stefano Stabellini
2018-08-22 10:19       ` Julien Grall
2018-10-03 21:21         ` Stefano Stabellini
2018-10-04 17:17           ` Julien Grall
2018-07-31 23:28 ` [PATCH v3 23/25] xen: support console_switching between Dom0 and DomUs on ARM Stefano Stabellini
2018-08-01  9:03   ` Jan Beulich
2018-10-04 21:52     ` Stefano Stabellini
2018-10-05  9:25       ` Julien Grall
2018-10-05  9:48         ` Julien Grall
2018-10-05 18:39           ` Stefano Stabellini
2018-10-05 18:39         ` Stefano Stabellini
2018-08-13 13:58   ` Julien Grall
2018-08-16 21:48     ` Stefano Stabellini
2018-07-31 23:28 ` [PATCH v3 24/25] xen/vpl011: buffer out chars when the backend is xen Stefano Stabellini
2018-08-13 14:21   ` Julien Grall
2018-08-16 19:41     ` Stefano Stabellini
2018-08-22 10:35       ` Julien Grall
2018-10-04 21:29         ` Stefano Stabellini
2018-07-31 23:28 ` [PATCH v3 25/25] xen/arm: split domain_build.c Stefano Stabellini
2018-08-13 14:29   ` Julien Grall
2018-08-16  0:25     ` Stefano Stabellini
2018-08-16  9:20       ` Julien Grall
2018-08-16 18:12         ` Stefano Stabellini
2018-08-22 15:44 ` [PATCH v3 00/25] dom0less step1: boot multiple domains from device tree 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.