All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 01/25] xen: allow console_io hypercalls from certain DomUs
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-23  2:02 ` [PATCH v5 02/25] xen/arm: extend device tree based multiboot protocol Stefano Stabellini
                   ` (23 subsequent siblings)
  24 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, sstabellini, andrii_anisov, konrad.wilk,
	George.Dunlap, andrew.cooper3, Achin.Gupta, 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>
Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
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 0ba80cb..abcc74e 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 b0ac1f6..29d7b50 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] 61+ messages in thread

* [PATCH v5 02/25] xen/arm: extend device tree based multiboot protocol
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
  2018-10-23  2:02 ` [PATCH v5 01/25] xen: allow console_io hypercalls from certain DomUs Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-23  2:02 ` [PATCH v5 03/25] xen/arm: document dom0less Stefano Stabellini
                   ` (22 subsequent siblings)
  24 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, 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 v4:
- memory is 64bit

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..317a9e9 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
+
+	A 64-bit 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 = <0 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 = <0 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] 61+ messages in thread

* [PATCH v5 03/25] xen/arm: document dom0less
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
  2018-10-23  2:02 ` [PATCH v5 01/25] xen: allow console_io hypercalls from certain DomUs Stefano Stabellini
  2018-10-23  2:02 ` [PATCH v5 02/25] xen/arm: extend device tree based multiboot protocol Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-23  2:02 ` [PATCH v5 04/25] xen/arm: increase MAX_MODULES Stefano Stabellini
                   ` (21 subsequent siblings)
  24 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, 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 v5:
- convert to markdown
- move to docs/features
- add entry to docs/INDEX

Changes in v4:
- rename to .txt
- improve wording

Changes in v3:
- add patch
---
 docs/INDEX                      |  1 +
 docs/features/dom0less.markdown | 49 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)
 create mode 100644 docs/features/dom0less.markdown

diff --git a/docs/INDEX b/docs/INDEX
index 868ab1f..e673edd 100644
--- a/docs/INDEX
+++ b/docs/INDEX
@@ -25,3 +25,4 @@ misc/arm/early-printk		Enabling early printk on ARM
 misc/arm/passthrough		Passthrough a device described in the Device Tree to a guest
 misc/arm/device-tree/booting	Device tree bindings to boot Xen
 misc/arm/device-tree/passthrough	Device tree binding to passthrough a device
+features/dom0less.markdown	Boot multiple domains from Xen in parallel
diff --git a/docs/features/dom0less.markdown b/docs/features/dom0less.markdown
new file mode 100644
index 0000000..4e342b7
--- /dev/null
+++ b/docs/features/dom0less.markdown
@@ -0,0 +1,49 @@
+Dom0less
+========
+
+"Dom0less" is a set of Xen features that enable the deployment of a Xen
+system without an control domain (often referred to as "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 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.
+
+Currently, a control domain ("dom0") is still required, but in the
+future it will become unnecessary when all domains are created
+directly from Xen. Instead of waiting for the control domain to be fully
+booted and the Xen tools to become available, domains created by Xen
+this way are started right away in parallel. 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.
+
+- Pinning vCPUs of domains started by Xen at boot can be
+  done from the control domain, using `xl vcpu-pin` as usual. It is not
+  currently possible to configure vCPU pinning without a control domain.
+  However, the NULL scheduler can be selected by passing `sched=null` to
+  the Xen command line. The NULL scheduler automatically assigns 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] 61+ messages in thread

* [PATCH v5 04/25] xen/arm: increase MAX_MODULES
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (2 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 03/25] xen/arm: document dom0less Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-23  2:02 ` [PATCH v5 05/25] xen/arm: check for multiboot nodes only under /chosen Stefano Stabellini
                   ` (20 subsequent siblings)
  24 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, 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] 61+ messages in thread

* [PATCH v5 05/25] xen/arm: check for multiboot nodes only under /chosen
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (3 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 04/25] xen/arm: increase MAX_MODULES Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-26 19:25   ` Julien Grall
  2018-10-23  2:02 ` [PATCH v5 06/25] xen/arm: introduce bootcmdlines Stefano Stabellini
                   ` (19 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, sstabellini, andrii_anisov, xen-devel

Make sure to only look for multiboot compatible nodes only under
/chosen, not under any other paths (depth <= 3).

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

---

Changes in v5:
- add patch
- add check on return value of fdt_get_path
---
 xen/arch/arm/bootfdt.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
index 8eba42c..a314aca 100644
--- a/xen/arch/arm/bootfdt.c
+++ b/xen/arch/arm/bootfdt.c
@@ -173,7 +173,14 @@ static void __init process_multiboot_node(const void *fdt, int node,
     bootmodule_kind kind;
     paddr_t start, size;
     const char *cmdline;
-    int len;
+    int len = sizeof("/chosen");
+    char path[8]; /* sizeof "/chosen" */
+    int ret;
+
+    /* Check that the node is under "chosen" */
+    ret = fdt_get_path(fdt, node, path, len);
+    if ( ret == 0 && strncmp(path, "/chosen", len - 1) )
+        return;
 
     prop = fdt_get_property(fdt, node, "reg", &len);
     if ( !prop )
@@ -286,8 +293,8 @@ static int __init early_scan_node(const void *fdt,
 {
     if ( device_tree_node_matches(fdt, node, "memory") )
         process_memory_node(fdt, node, name, address_cells, size_cells);
-    else if ( device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) ||
-              device_tree_node_compatible(fdt, node, "multiboot,module" ))
+    else if ( depth <= 3 && (device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) ||
+              device_tree_node_compatible(fdt, node, "multiboot,module" )))
         process_multiboot_node(fdt, node, name, address_cells, size_cells);
     else if ( depth == 1 && device_tree_node_matches(fdt, node, "chosen") )
         process_chosen_node(fdt, node, name, address_cells, size_cells);
-- 
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] 61+ messages in thread

* [PATCH v5 06/25] xen/arm: introduce bootcmdlines
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (4 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 05/25] xen/arm: check for multiboot nodes only under /chosen Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-26 19:44   ` Julien Grall
  2018-10-23  2:02 ` [PATCH v5 07/25] xen/arm: don't add duplicate boot modules, introduce domU flag Stefano Stabellini
                   ` (18 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, 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 v5:
- remove leftover DEBUG message
- improve commit message
- use kinfo->cmdline when possible
- move add_bood_cmdline to setup.c

Changes in v4:
- check that the multiboot node is under /chosen
- use cmd and cmds as variable names for struct bootcmdline and struct
  bootcmdline*
- fix printk
- use ASSERT instea of panic
- do not add empty cmdline entries
- add more debug printks to early_print_info
- code style fixes
- add comment on DT_MAX_NAME
- increase DT_MAX_NAME to 41
- make nr_mods unsigned int

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

Changes in v2:
- new patch
---
 xen/arch/arm/bootfdt.c      | 43 ++++++++++++++++++++++-------------------
 xen/arch/arm/domain_build.c | 12 ++++++------
 xen/arch/arm/kernel.h       |  1 +
 xen/arch/arm/setup.c        | 47 ++++++++++++++++++++++++++++++++++++++-------
 xen/include/asm-arm/setup.h | 19 ++++++++++++++++--
 5 files changed, 87 insertions(+), 35 deletions(-)

diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
index a314aca..cb6f77d 100644
--- a/xen/arch/arm/bootfdt.c
+++ b/xen/arch/arm/bootfdt.c
@@ -172,10 +172,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 = sizeof("/chosen");
     char path[8]; /* sizeof "/chosen" */
-    int ret;
+    int parent_node, ret;
+
+    parent_node = fdt_parent_offset(fdt, node);
+    ASSERT(parent_node >= 0);
 
     /* Check that the node is under "chosen" */
     ret = fdt_get_path(fdt, node, path, len);
@@ -227,17 +229,12 @@ 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);
 
-    add_boot_module(kind, start, size, cmdline);
+    prop = fdt_get_property(fdt, node, "bootargs", &len);
+    if ( !prop )
+        return;
+    add_boot_cmdline(fdt_get_name(fdt, parent_node, &len), prop->data, kind);
 }
 
 static void __init process_chosen_node(const void *fdt, int node,
@@ -283,7 +280,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,
@@ -306,6 +303,7 @@ static void __init early_print_info(void)
 {
     struct meminfo *mi = &bootinfo.mem;
     struct bootmodules *mods = &bootinfo.modules;
+    struct bootcmdlines *cmds = &bootinfo.cmdlines;
     int i, nr_rsvd;
 
     for ( i = 0; i < mi->nr_banks; i++ )
@@ -314,12 +312,12 @@ 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++ )
     {
@@ -332,6 +330,11 @@ static void __init early_print_info(void)
                      i, s, e);
     }
     printk("\n");
+    for ( i = 0 ; i < cmds->nr_mods; i++ )
+        printk("CMDLINE[%d]:%s %s\n", i,
+               cmds->cmdline[i].dt_name,
+               &cmds->cmdline[i].cmdline[0]);
+    printk("\n");
 }
 
 /**
@@ -348,7 +351,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();
@@ -368,11 +371,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 f552154..8977397 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -375,10 +375,8 @@ 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;
-
-    if ( kernel && kernel->cmdline[0] )
-        bootargs = &kernel->cmdline[0];
+    if ( kinfo->cmdline && kinfo->cmdline[0] )
+        bootargs = &kinfo->cmdline[0];
 
     dt_for_each_property_node (node, prop)
     {
@@ -952,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;
@@ -2109,6 +2107,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;
@@ -2154,6 +2153,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 ea2495a..2098591 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -201,8 +201,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;
@@ -218,10 +217,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;
 }
@@ -240,6 +235,44 @@ struct bootmodule * __init boot_module_find_by_kind(bootmodule_kind kind)
     return NULL;
 }
 
+void __init add_boot_cmdline(const char *name, const char *cmdline,
+                             bootmodule_kind kind)
+{
+    struct bootcmdlines *cmds = &bootinfo.cmdlines;
+    struct bootcmdline *cmd;
+
+    if ( cmds->nr_mods == MAX_MODULES )
+    {
+        printk("Ignoring %s cmdline (too many)\n", name);
+        return;
+    }
+
+    cmd = &cmds->cmdline[cmds->nr_mods++];
+    cmd->kind = kind;
+
+    ASSERT(strlen(name) <= DT_MAX_NAME);
+    safe_strcpy(cmd->dt_name, name);
+
+    if ( strlen(cmdline) > BOOTMOD_MAX_CMDLINE )
+        panic("module %s command line too long\n", name);
+    safe_strcpy(cmd->cmdline, cmdline);
+}
+
+struct bootcmdline * __init boot_cmdline_find_by_kind(bootmodule_kind kind)
+{
+    struct bootcmdlines *cmds = &bootinfo.cmdlines;
+    struct bootcmdline *cmd;
+    int i;
+
+    for ( i = 0 ; i < cmds->nr_mods ; i++ )
+    {
+        cmd = &cmds->cmdline[i];
+        if ( cmd->kind == kind )
+            return cmd;
+    }
+    return NULL;
+}
+
 const char * __init boot_module_kind_as_string(bootmodule_kind kind)
 {
     switch ( kind )
@@ -728,7 +761,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..7580007 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -35,6 +35,13 @@ struct bootmodule {
     bootmodule_kind kind;
     paddr_t start;
     paddr_t size;
+};
+
+/* DT_MAX_NAME is the node name max length according the DT spec */
+#define DT_MAX_NAME 41
+struct bootcmdline {
+    bootmodule_kind kind;
+    char dt_name[DT_MAX_NAME];
     char cmdline[BOOTMOD_MAX_CMDLINE];
 };
 
@@ -43,9 +50,15 @@ struct bootmodules {
     struct bootmodule module[MAX_MODULES];
 };
 
+struct bootcmdlines {
+    unsigned 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 +91,11 @@ 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);
+void add_boot_cmdline(const char *name, const char *cmdline,
+                      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] 61+ messages in thread

* [PATCH v5 07/25] xen/arm: don't add duplicate boot modules, introduce domU flag
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (5 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 06/25] xen/arm: introduce bootcmdlines Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-30 11:50   ` Julien Grall
  2018-10-23  2:02 ` [PATCH v5 08/25] xen/arm: probe domU kernels and initrds Stefano Stabellini
                   ` (17 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, sstabellini, andrii_anisov, xen-devel

Don't add duplicate boot modules (same kind and same start address),
they are freed later, we don't want to introduce double-free errors.

Introduce a domU flag in struct bootmodule and struct bootcmdline. Set
it for kernels and ramdisks of "xen,domain" nodes to avoid getting
confused in kernel_probe, where we try to guess which is the dom0 kernel
and initrd to be compatible with all versions of the multiboot spec.

boot_module_find_by_kind and boot_cmdline_find_by_kind automatically
check for !domU entries (they are only used for non-domU modules).

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

---
Changes in v5:
- improve commit message
- add in-code comments

Changes in v4:
- use unsigned int
- better commit message
- introduce domU flag and usage

Changes in v2:
- new patch
---
 xen/arch/arm/bootfdt.c      | 11 +++++++----
 xen/arch/arm/setup.c        | 30 +++++++++++++++++++++++++-----
 xen/include/asm-arm/setup.h | 12 ++++++++++--
 3 files changed, 42 insertions(+), 11 deletions(-)

diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
index cb6f77d..c325b6e 100644
--- a/xen/arch/arm/bootfdt.c
+++ b/xen/arch/arm/bootfdt.c
@@ -175,6 +175,7 @@ static void __init process_multiboot_node(const void *fdt, int node,
     int len = sizeof("/chosen");
     char path[8]; /* sizeof "/chosen" */
     int parent_node, ret;
+    bool domU;
 
     parent_node = fdt_parent_offset(fdt, node);
     ASSERT(parent_node >= 0);
@@ -229,12 +230,14 @@ static void __init process_multiboot_node(const void *fdt, int node,
             kind = BOOTMOD_XSM;
     }
 
-    add_boot_module(kind, start, size);
+    domU = fdt_node_check_compatible(fdt, parent_node, "xen,domain") == 0;
+    add_boot_module(kind, start, size, domU);
 
     prop = fdt_get_property(fdt, node, "bootargs", &len);
     if ( !prop )
         return;
-    add_boot_cmdline(fdt_get_name(fdt, parent_node, &len), prop->data, kind);
+    add_boot_cmdline(fdt_get_name(fdt, parent_node, &len), prop->data,
+                     kind, domU);
 }
 
 static void __init process_chosen_node(const void *fdt, int node,
@@ -280,7 +283,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);
+    add_boot_module(BOOTMOD_RAMDISK, start, end-start, false);
 }
 
 static int __init early_scan_node(const void *fdt,
@@ -351,7 +354,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));
+    add_boot_module(BOOTMOD_FDT, paddr, fdt_totalsize(fdt), false);
 
     device_tree_for_each_node((void *)fdt, early_scan_node, NULL);
     early_print_info();
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 2098591..72b12f9 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -201,10 +201,12 @@ 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)
+                                          paddr_t start, paddr_t size,
+                                          bool domU)
 {
     struct bootmodules *mods = &bootinfo.modules;
     struct bootmodule *mod;
+    unsigned int i;
 
     if ( mods->nr_mods == MAX_MODULES )
     {
@@ -212,15 +214,29 @@ 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 )
+        {
+            if ( !domU )
+                mod->domU = false;
+            return mod;
+        }
+    }
 
     mod = &mods->module[mods->nr_mods++];
     mod->kind = kind;
     mod->start = start;
     mod->size = size;
+    mod->domU = domU;
 
     return mod;
 }
 
+/*
+ * This function is only used to find dom0 modules, so check for !mod->domU
+ */
 struct bootmodule * __init boot_module_find_by_kind(bootmodule_kind kind)
 {
     struct bootmodules *mods = &bootinfo.modules;
@@ -229,14 +245,14 @@ struct bootmodule * __init boot_module_find_by_kind(bootmodule_kind kind)
     for (i = 0 ; i < mods->nr_mods ; i++ )
     {
         mod = &mods->module[i];
-        if ( mod->kind == kind )
+        if ( mod->kind == kind && !mod->domU )
             return mod;
     }
     return NULL;
 }
 
 void __init add_boot_cmdline(const char *name, const char *cmdline,
-                             bootmodule_kind kind)
+                             bootmodule_kind kind, bool domU)
 {
     struct bootcmdlines *cmds = &bootinfo.cmdlines;
     struct bootcmdline *cmd;
@@ -249,6 +265,7 @@ void __init add_boot_cmdline(const char *name, const char *cmdline,
 
     cmd = &cmds->cmdline[cmds->nr_mods++];
     cmd->kind = kind;
+    cmd->domU = domU;
 
     ASSERT(strlen(name) <= DT_MAX_NAME);
     safe_strcpy(cmd->dt_name, name);
@@ -258,6 +275,9 @@ void __init add_boot_cmdline(const char *name, const char *cmdline,
     safe_strcpy(cmd->cmdline, cmdline);
 }
 
+/*
+ * This function is only used to find dom0 modules, so check for !mod->domU
+ */
 struct bootcmdline * __init boot_cmdline_find_by_kind(bootmodule_kind kind)
 {
     struct bootcmdlines *cmds = &bootinfo.cmdlines;
@@ -267,7 +287,7 @@ struct bootcmdline * __init boot_cmdline_find_by_kind(bootmodule_kind kind)
     for ( i = 0 ; i < cmds->nr_mods ; i++ )
     {
         cmd = &cmds->cmdline[i];
-        if ( cmd->kind == kind )
+        if ( cmd->kind == kind && !cmd->domU )
             return cmd;
     }
     return NULL;
@@ -761,7 +781,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));
+                             (paddr_t)(uintptr_t)(_end - _start + 1), false);
     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 7580007..3a30329 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -30,9 +30,16 @@ struct meminfo {
     struct membank bank[NR_MEM_BANKS];
 };
 
+/*
+ * The domU flag is set for kernels and ramdisks of "xen,domain" nodes.
+ * The purpose of the domU flag is to avoid getting confused in
+ * kernel_probe, where we try to guess which is the dom0 kernel and
+ * initrd to be compatible with all versions of the multiboot spec. 
+ */
 #define BOOTMOD_MAX_CMDLINE 1024
 struct bootmodule {
     bootmodule_kind kind;
+    bool domU;
     paddr_t start;
     paddr_t size;
 };
@@ -41,6 +48,7 @@ struct bootmodule {
 #define DT_MAX_NAME 41
 struct bootcmdline {
     bootmodule_kind kind;
+    bool domU;
     char dt_name[DT_MAX_NAME];
     char cmdline[BOOTMOD_MAX_CMDLINE];
 };
@@ -91,10 +99,10 @@ 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);
+                                   paddr_t start, paddr_t size, bool domU);
 struct bootmodule *boot_module_find_by_kind(bootmodule_kind kind);
 void add_boot_cmdline(const char *name, const char *cmdline,
-                      bootmodule_kind kind);
+                      bootmodule_kind kind, bool domU);
 struct bootcmdline *boot_cmdline_find_by_kind(bootmodule_kind kind);
 const char * __init boot_module_kind_as_string(bootmodule_kind 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] 61+ messages in thread

* [PATCH v5 08/25] xen/arm: probe domU kernels and initrds
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (6 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 07/25] xen/arm: don't add duplicate boot modules, introduce domU flag Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-30 12:03   ` Julien Grall
  2018-10-23  2:02 ` [PATCH v5 09/25] xen/arm: rename get_11_allocation_size to get_allocation_size Stefano Stabellini
                   ` (16 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, 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.

Set command line for dom0 too for consistency.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
Changes in v5:
- constify kernel_probe
- add ASSERT and comment in kernel_probe
- limit variable scope
- fix printk message
- int/unsigned int
- set cmdline for dom0 too
- improve code readability

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       | 64 ++++++++++++++++++++++++++++++++++++++++-----
 xen/arch/arm/kernel.h       |  2 +-
 xen/arch/arm/setup.c        | 31 ++++++++++++++++++++++
 xen/include/asm-arm/setup.h |  3 +++
 5 files changed, 93 insertions(+), 9 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 8977397..8faf252 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -2135,7 +2135,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 da8410e..d56f776 100644
--- a/xen/arch/arm/kernel.c
+++ b/xen/arch/arm/kernel.c
@@ -421,22 +421,72 @@ 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,
+                        const struct dt_device_node *domain)
 {
-    struct bootmodule *mod = boot_module_find_by_kind(BOOTMOD_KERNEL);
+    struct bootmodule *mod = NULL;
+    struct bootcmdline *cmd = NULL;
+    struct dt_device_node *node;
+    u64 kernel_addr, initrd_addr, size;
     int rc;
 
+    /* domain is NULL only for the hardware_domain */
+    if ( domain == NULL )
+    {
+        ASSERT(is_hardware_domain(info->d));
+
+        mod = boot_module_find_by_kind(BOOTMOD_KERNEL);
+
+        info->kernel_bootmodule = mod;
+        info->initrd_bootmodule = boot_module_find_by_kind(BOOTMOD_RAMDISK);
+
+        cmd = boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
+        if ( cmd )
+            info->cmdline = &cmd->cmdline[0];
+    }
+    else
+    {
+        const char *name = NULL;
+
+        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);
+                mod = boot_module_find_by_addr_and_kind(
+                        BOOTMOD_KERNEL, kernel_addr);
+                info->kernel_bootmodule = mod;
+            }
+            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);
+                info->initrd_bootmodule = boot_module_find_by_addr_and_kind(
+                        BOOTMOD_RAMDISK, initrd_addr);
+            }
+            else
+                continue;
+        }
+        name = dt_node_name(domain);
+        cmd = boot_cmdline_find_by_name(name);
+        if ( cmd )
+            info->cmdline = &cmd->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 Dom%d kernel from boot module @ %"PRIpaddr"\n",
+           info->d->domain_id, 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..4320f72 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, const 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 72b12f9..49f2fef 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -293,6 +293,37 @@ 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;
+    unsigned 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;
+    unsigned 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 3a30329..33fb04e 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -101,9 +101,12 @@ const char __init *boot_fdt_cmdline(const void *fdt);
 struct bootmodule *add_boot_module(bootmodule_kind kind,
                                    paddr_t start, paddr_t size, bool domU);
 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);
 void add_boot_cmdline(const char *name, const char *cmdline,
                       bootmodule_kind kind, bool domU);
 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] 61+ messages in thread

* [PATCH v5 09/25] xen/arm: rename get_11_allocation_size to get_allocation_size
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (7 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 08/25] xen/arm: probe domU kernels and initrds Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-23  2:02 ` [PATCH v5 10/25] xen/arm: rename allocate_memory to allocate_memory_11 Stefano Stabellini
                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, sstabellini, andrii_anisov, xen-devel

No functional changes.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
Acked-by: Julien Grall <julien.grall@arm.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 8faf252..c4ae39b 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -77,7 +77,7 @@ struct vcpu *__init alloc_dom0_vcpu0(struct domain *dom0)
     return vcpu_create(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
@@ -249,7 +249,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;
@@ -301,7 +301,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);
@@ -312,7 +312,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;
             }
@@ -332,7 +332,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;
             }
@@ -347,7 +347,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] 61+ messages in thread

* [PATCH v5 10/25] xen/arm: rename allocate_memory to allocate_memory_11
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (8 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 09/25] xen/arm: rename get_11_allocation_size to get_allocation_size Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-23  2:02 ` [PATCH v5 11/25] xen/arm: introduce allocate_memory Stefano Stabellini
                   ` (14 subsequent siblings)
  24 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, 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>
Acked-by: Julien Grall <julien.grall@arm.com>

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

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index c4ae39b..c61a27f 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -243,7 +243,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)));
@@ -2154,7 +2155,7 @@ int __init construct_dom0(struct domain *d)
 #endif
 
     kinfo.cmdline = kernel != NULL ? &kernel->cmdline[0] : NULL;
-    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] 61+ messages in thread

* [PATCH v5 11/25] xen/arm: introduce allocate_memory
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (9 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 10/25] xen/arm: rename allocate_memory to allocate_memory_11 Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-30 12:24   ` Julien Grall
  2018-10-30 20:56   ` Julien Grall
  2018-10-23  2:02 ` [PATCH v5 12/25] xen/arm: refactor construct_dom0 Stefano Stabellini
                   ` (13 subsequent siblings)
  24 siblings, 2 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, 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.

This is under #if 0 as not used for now.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
Changes in v5:
- improve commit message
- code style
- remove unneeded local var
- while loop in allocate_bank_memory to allocate memory so that it
  doesn't have to be contiguos
- combile while loops in allocate_memory

Changes in v4:
- move earlier, add #if 0
- introduce allocate_bank_memory, remove insert_bank
- allocate_bank_memory allocate memory and inserts the bank, while
  allocate_memory specifies where to do that

Changes in v3:
- new patch
---
 xen/arch/arm/domain_build.c | 99 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 99 insertions(+)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index c61a27f..146d81e 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -368,6 +368,105 @@ static void __init allocate_memory_11(struct domain *d,
     }
 }
 
+#if 0
+static bool __init allocate_bank_memory(struct domain *d,
+                                        struct kernel_info *kinfo,
+                                        gfn_t sgfn,
+                                        unsigned int order)
+{
+    int res;
+    struct page_info *pg;
+    struct membank *bank;
+    paddr_t size = pfn_to_paddr(1UL << order);
+    gfn_t _sgfn = sgfn;
+    gfn_t _egfn = gfn_add(sgfn, 1UL << order);
+
+    while ( gfn_x(_sgfn) < gfn_x(_egfn) )
+    {
+        pg = alloc_domheap_pages(d, order, 0);
+        if ( pg != NULL )
+        {
+            res = guest_physmap_add_page(d, _sgfn, page_to_mfn(pg), order);
+            if ( res )
+            {
+                dprintk(XENLOG_ERR, "Failed map pages to DOMU: %d", res);
+                goto fail;
+            }
+            _sgfn = gfn_add(_sgfn, 1UL << order);
+        }
+        else
+        {
+            order--;
+            if ( order == 0 )
+            {
+                dprintk(XENLOG_ERR, "Failed to allocated DOMU memory");
+                goto fail;
+            }
+        }
+    }
+
+    bank = &kinfo->mem.bank[kinfo->mem.nr_banks];
+    bank->start = gfn_to_gaddr(sgfn);
+    bank->size = size;
+    kinfo->mem.nr_banks++;
+    kinfo->unassigned_mem -= size;
+
+    return true;
+
+fail:
+    /*
+     * Fatal failure, don't attempt to free memory.
+     */
+    return false;
+}
+
+static void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
+{
+    unsigned int order = get_allocation_size(kinfo->unassigned_mem);
+    unsigned int order_req;
+    unsigned 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 > get_order_from_bytes(GUEST_RAM0_SIZE) )
+        order_req = get_order_from_bytes(GUEST_RAM0_SIZE);
+    else
+        order_req = order;
+    if ( !allocate_bank_memory(d, kinfo, gaddr_to_gfn(GUEST_RAM0_BASE), order_req) )
+        goto fail;
+
+    order -= order_req;
+    if ( order > 0 &&
+         !allocate_bank_memory(d, kinfo, gaddr_to_gfn(GUEST_RAM1_BASE), order) )
+        goto fail;
+
+    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));
+    }
+
+    return;
+
+fail:
+    dprintk(XENLOG_ERR, "Failed to allocate requested domain memory."
+            /* Don't want format this as PRIpaddr (16 digit hex) */
+            " %ldKB unallocated. Fix the VMs configurations.\n",
+            (unsigned long)kinfo->unassigned_mem >> 10);
+    BUG();
+}
+#endif
+
 static int __init write_properties(struct domain *d, struct kernel_info *kinfo,
                                    const struct dt_device_node *node)
 {
-- 
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] 61+ messages in thread

* [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree
@ 2018-10-23  2:02 Stefano Stabellini
  2018-10-23  2:02 ` [PATCH v5 01/25] xen: allow console_io hypercalls from certain DomUs Stefano Stabellini
                   ` (24 more replies)
  0 siblings, 25 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall; +Cc: Achin.Gupta, 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 359970fd8b781fac2ddcbc84dd5b890075fa08ef:

  tools/libxl: Switch Arm guest type to PVH (2018-10-03 15:58:02 +0100)

are available in the git repository at:

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

for you to fetch changes up to b97df820bf3687dccf6401fb8174f5e4d8d2d8c3:

  xen/arm: split domain_build.c (2018-10-22 18:59:12 -0700)

----------------------------------------------------------------
Stefano Stabellini (25):
      xen: allow console_io hypercalls from certain DomUs
      xen/arm: extend device tree based multiboot protocol
      xen/arm: document dom0less
      xen/arm: increase MAX_MODULES
      xen/arm: check for multiboot nodes only under /chosen
      xen/arm: introduce bootcmdlines
      xen/arm: don't add duplicate boot modules, introduce domU flag
      xen/arm: probe domU kernels and initrds
      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: refactor construct_dom0
      xen/arm: move unregister_init_virtual_region to init_done
      xen/arm: introduce create_domUs
      xen/arm: implement construct_domU
      xen/arm: generate a simple device tree for domUs
      xen/arm: make set_interrupt_ppi able to handle non-PPI
      xen/arm: generate vpl011 node on device tree for domU
      xen/arm: introduce a union in vpl011
      xen/arm: refactor vpl011_data_avail
      xen: support console_switching between Dom0 and DomUs on ARM
      xen/arm: Allow vpl011 to be used by DomU
      xen/vpl011: buffer out chars when the backend is xen
      xen/arm: move kernel.h to asm-arm/
      xen/arm: split domain_build.c

 docs/INDEX                                 |    1 +
 docs/features/dom0less.markdown            |   49 ++
 docs/misc/arm/device-tree/booting.txt      |  107 +++
 xen/arch/arm/acpi/Makefile                 |    1 +
 xen/arch/arm/acpi/domain_build.c           |  592 +++++++++++++++
 xen/arch/arm/bootfdt.c                     |   57 +-
 xen/arch/arm/domain_build.c                | 1101 +++++++++++++---------------
 xen/arch/arm/kernel.c                      |   67 +-
 xen/arch/arm/setup.c                       |  107 ++-
 xen/arch/arm/vpl011.c                      |  296 ++++++--
 xen/drivers/char/console.c                 |   87 ++-
 xen/include/asm-arm/domain_build.h         |   31 +
 xen/{arch/arm => include/asm-arm}/kernel.h |    6 +-
 xen/include/asm-arm/setup.h                |   35 +-
 xen/include/asm-arm/vpl011.h               |   20 +-
 xen/include/asm-x86/setup.h                |    2 +
 xen/include/xen/console.h                  |    2 +
 xen/include/xen/sched.h                    |    2 +
 xen/include/xsm/dummy.h                    |    2 +
 19 files changed, 1855 insertions(+), 710 deletions(-)
 create mode 100644 docs/features/dom0less.markdown
 create mode 100644 xen/arch/arm/acpi/domain_build.c
 create mode 100644 xen/include/asm-arm/domain_build.h
 rename xen/{arch/arm => include/asm-arm}/kernel.h (91%)

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

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

* [PATCH v5 12/25] xen/arm: refactor construct_dom0
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (10 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 11/25] xen/arm: introduce allocate_memory Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-30 16:32   ` Julien Grall
  2018-10-23  2:02 ` [PATCH v5 13/25] xen/arm: move unregister_init_virtual_region to init_done Stefano Stabellini
                   ` (12 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, 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 v5:
- rename __construct_domain to construct_domain

Changes in v4:
- newline and style changes

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 | 126 ++++++++++++++++++++++++--------------------
 1 file changed, 68 insertions(+), 58 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 146d81e..d1dab5a 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1470,7 +1470,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;
@@ -2205,75 +2205,29 @@ 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 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;
-
 #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_11(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
@@ -2286,20 +2240,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) )
     {
@@ -2317,14 +2269,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 */
@@ -2352,6 +2304,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_11(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] 61+ messages in thread

* [PATCH v5 13/25] xen/arm: move unregister_init_virtual_region to init_done
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (11 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 12/25] xen/arm: refactor construct_dom0 Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-30 16:33   ` Julien Grall
  2018-10-23  2:02 ` [PATCH v5 14/25] xen/arm: introduce create_domUs Stefano Stabellini
                   ` (11 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, sstabellini, andrii_anisov, xen-devel

Move unregister_init_virtual_region to init_done. Follow the same path
as x86. It is also useful to move it later so that create_domUs can be
called before that in following patches.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
 xen/arch/arm/setup.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 49f2fef..f3dc96c 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -66,6 +66,9 @@ integer_param("xenheap_megabytes", opt_xenheap_megabytes);
 
 static __used void init_done(void)
 {
+    /* Must be done past setting system_state. */
+    unregister_init_virtual_region();
+
     free_init_memory();
     startup_cpu_idle_loop();
 }
@@ -955,9 +958,6 @@ void __init start_xen(unsigned long boot_phys_offset,
 
     system_state = SYS_STATE_active;
 
-    /* Must be done past setting system_state. */
-    unregister_init_virtual_region();
-
     domain_unpause_by_systemcontroller(dom0);
 
     /* Switch on to the dynamically allocated stack for the idle vcpu
-- 
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] 61+ messages in thread

* [PATCH v5 14/25] xen/arm: introduce create_domUs
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (12 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 13/25] xen/arm: move unregister_init_virtual_region to init_done Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-30 16:38   ` Julien Grall
  2018-10-23  2:02 ` [PATCH v5 15/25] xen/arm: implement construct_domU Stefano Stabellini
                   ` (10 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, sstabellini, andrii_anisov, andrew.cooper3,
	Achin.Gupta, xen-devel, jbeulich

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

Introduce support for the "xen,domain" compatible node on device tree.
Create new DomU VMs based on the information found on device tree under
"xen,domain". Call 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>
Acked-by: Jan Beulich <jbeulich@suse.com>
CC: andrew.cooper3@citrix.com
CC: jbeulich@suse.com
---
Changes in v5:
- use dt_property_read_bool
- improve commit message
- code style
- use dt_find_node_by_path instead of dt_find_node_by_name
- use true with is_console

Changes in v4:
- constify parameters
- nr_spis to 0 or  GUEST_VPL011_SPI - 32 + 1 depending on vpl011
- remove pointless initializer
- remove change to domain_create for dom0 (useless)
- make construct_domU return error

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 | 50 +++++++++++++++++++++++++++++++++++++++++----
 xen/arch/arm/setup.c        |  5 +++++
 xen/include/asm-arm/setup.h |  3 +++
 xen/include/asm-x86/setup.h |  2 ++
 4 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index d1dab5a..93e9510 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>
@@ -2304,6 +2305,50 @@ static int __init construct_domain(struct domain *d, struct kernel_info *kinfo)
     return 0;
 }
 
+static int __init construct_domU(struct domain *d,
+                                 const struct dt_device_node *node)
+{
+    return -ENOSYS;
+}
+
+void __init create_domUs(void)
+{
+    struct dt_device_node *node;
+    const struct dt_device_node *chosen = dt_find_node_by_path("/chosen");
+
+    BUG_ON(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 = 0,
+            .max_vcpus = 1,
+            .max_evtchn_port = -1,
+            .max_grant_frames = 64,
+            .max_maptrack_frames = 1024,
+        };
+
+        if ( !dt_device_is_compatible(node, "xen,domain") )
+            continue;
+
+        if ( dt_property_read_bool(node, "vpl011") )
+            d_cfg.arch.nr_spis = GUEST_VPL011_SPI - 32 + 1;
+        dt_property_read_u32(node, "cpus", &d_cfg.max_vcpus);
+
+        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 = true;
+
+        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);
@@ -2356,10 +2401,7 @@ int __init construct_dom0(struct domain *d)
     if ( rc < 0 )
         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 f3dc96c..43eb208 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -64,11 +64,14 @@ static unsigned long opt_xenheap_megabytes __initdata;
 integer_param("xenheap_megabytes", opt_xenheap_megabytes);
 #endif
 
+domid_t __read_mostly max_init_domid;
+
 static __used void init_done(void)
 {
     /* Must be done past setting system_state. */
     unregister_init_virtual_region();
 
+    discard_initial_modules();
     free_init_memory();
     startup_cpu_idle_loop();
 }
@@ -958,6 +961,8 @@ void __init start_xen(unsigned long boot_phys_offset,
 
     system_state = SYS_STATE_active;
 
+    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 33fb04e..3071ba8 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -74,6 +74,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);
@@ -90,6 +92,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 42fddeb..1c80783 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] 61+ messages in thread

* [PATCH v5 15/25] xen/arm: implement construct_domU
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (13 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 14/25] xen/arm: introduce create_domUs Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-30 20:56   ` Julien Grall
  2018-10-23  2:02 ` [PATCH v5 16/25] xen/arm: generate a simple device tree for domUs Stefano Stabellini
                   ` (9 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, 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.

Remove #if 0 from allocate_memory as this patch will start using it.

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

---
Changes in v5:
- move changes to kernel_probe prototype to previous patch
- improve commit message
- remove superflous allocation of d->vcpu
- use mem * SZ_1K

Changes in v4:
- constify kernel_probe
- change title
- better error messages and printed info
- 64bit memory

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 | 35 ++++++++++++++++++++++++++++++++---
 1 file changed, 32 insertions(+), 3 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 93e9510..4bb0db8 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -4,6 +4,7 @@
 #include <xen/mm.h>
 #include <xen/domain_page.h>
 #include <xen/sched.h>
+#include <xen/sizes.h>
 #include <asm/irq.h>
 #include <asm/regs.h>
 #include <xen/errno.h>
@@ -369,7 +370,6 @@ static void __init allocate_memory_11(struct domain *d,
     }
 }
 
-#if 0
 static bool __init allocate_bank_memory(struct domain *d,
                                         struct kernel_info *kinfo,
                                         gfn_t sgfn,
@@ -466,7 +466,6 @@ fail:
             (unsigned long)kinfo->unassigned_mem >> 10);
     BUG();
 }
-#endif
 
 static int __init write_properties(struct domain *d, struct kernel_info *kinfo,
                                    const struct dt_device_node *node)
@@ -2308,7 +2307,37 @@ static int __init construct_domain(struct domain *d, struct kernel_info *kinfo)
 static int __init construct_domU(struct domain *d,
                                  const struct dt_device_node *node)
 {
-    return -ENOSYS;
+    struct kernel_info kinfo = {};
+    int rc;
+    u64 mem;
+
+    rc = dt_property_read_u64(node, "memory", &mem);
+    if ( !rc )
+    {
+        printk("Error building DomU: cannot read \"memory\" property\n");
+        return -EINVAL;
+    }
+    kinfo.unassigned_mem = (paddr_t)mem * SZ_1K;
+
+    printk("*** LOADING DOMU cpus=%u memory=%luKB ***\n", d->max_vcpus, mem);
+
+    if ( vcpu_create(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] 61+ messages in thread

* [PATCH v5 16/25] xen/arm: generate a simple device tree for domUs
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (14 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 15/25] xen/arm: implement construct_domU Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-23  2:02 ` [PATCH v5 17/25] xen/arm: make set_interrupt_ppi able to handle non-PPI Stefano Stabellini
                   ` (8 subsequent siblings)
  24 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, 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>
Acked-by: Julien Grall <julien.grall@arm.com>
---
Changes in v5:
- use d->arch.vgic.version

Changes in v4:
- code style
- two separate functions for gicv2 and gicv3
- remove useless local variables
- fix typos
- do not use host address and size cells for the guest DT
- use #define for addrcells and sizecells

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 | 235 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 233 insertions(+), 2 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 4bb0db8..4a6ed23 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1032,7 +1032,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
@@ -1078,7 +1077,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)
@@ -1470,6 +1468,235 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
     return res;
 }
 
+static int __init make_gicv2_domU_node(const struct domain *d, void *fdt)
+{
+    int res = 0;
+    __be32 reg[(GUEST_ROOT_ADDRESS_CELLS + GUEST_ROOT_SIZE_CELLS) * 2];
+    __be32 *cells;
+
+    res = fdt_begin_node(fdt, "interrupt-controller@"__stringify(GUEST_GICD_BASE));
+    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;
+
+    res = fdt_property_string(fdt, "compatible", "arm,gic-400");
+    if ( res )
+        return res;
+
+    cells = &reg[0];
+    dt_child_set_range(&cells, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
+                       GUEST_GICD_BASE, GUEST_GICD_SIZE);
+    dt_child_set_range(&cells, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
+                       GUEST_GICC_BASE, GUEST_GICC_SIZE);
+
+    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_gicv3_domU_node(const struct domain *d, void *fdt)
+{
+    int res = 0;
+    __be32 reg[(GUEST_ROOT_ADDRESS_CELLS + GUEST_ROOT_SIZE_CELLS) * 2];
+    __be32 *cells;
+
+    res = fdt_begin_node(fdt, "interrupt-controller@"__stringify(GUEST_GICV3_GICD_BASE));
+    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;
+
+    res = fdt_property_string(fdt, "compatible", "arm,gic-v3");
+    if ( res )
+        return res;
+
+    cells = &reg[0];
+    dt_child_set_range(&cells, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
+                       GUEST_GICV3_GICD_BASE, GUEST_GICV3_GICD_SIZE);
+    dt_child_set_range(&cells, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
+                       GUEST_GICV3_GICR0_BASE, GUEST_GICV3_GICR0_SIZE);
+
+    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_gic_domU_node(const struct domain *d, void *fdt)
+{
+    switch ( d->arch.vgic.version )
+    {
+    case GIC_V3:
+        return make_gicv3_domU_node(d, fdt);
+    case GIC_V2:
+        return make_gicv2_domU_node(d, fdt);
+    default:
+        panic("Unsupported GIC version");
+    }
+}
+
+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 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 = GUEST_ROOT_ADDRESS_CELLS;
+    sizecells = GUEST_ROOT_SIZE_CELLS;
+
+    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);
+    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;
@@ -2337,6 +2564,10 @@ static int __init construct_domU(struct domain *d,
 #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] 61+ messages in thread

* [PATCH v5 17/25] xen/arm: make set_interrupt_ppi able to handle non-PPI
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (15 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 16/25] xen/arm: generate a simple device tree for domUs Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-23  2:02 ` [PATCH v5 18/25] xen/arm: generate vpl011 node on device tree for domU Stefano Stabellini
                   ` (7 subsequent siblings)
  24 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, sstabellini, andrii_anisov, xen-devel

also rename it to set_interrupt.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
Reviewed-by: Julien Grall <julien.grall@arm.com>
---
 xen/arch/arm/domain_build.c | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 4a6ed23..a7fd4f1 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -592,19 +592,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);
 }
 
@@ -727,7 +728,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;
@@ -1004,15 +1005,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 )
@@ -1601,9 +1602,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 )
-- 
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] 61+ messages in thread

* [PATCH v5 18/25] xen/arm: generate vpl011 node on device tree for domU
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (16 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 17/25] xen/arm: make set_interrupt_ppi able to handle non-PPI Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-30 20:58   ` Julien Grall
  2018-10-23  2:02 ` [PATCH v5 19/25] xen/arm: introduce a union in vpl011 Stefano Stabellini
                   ` (6 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, 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.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
Changes in v5:
- use dt_property_read_bool

Changes in v4:
- move rename set_interrupt_ppi and making set_interrupt_ppi generic to
  a separate patch
- properly name the vpl011 device node name
- code style
- use #define for addrcells and sizecells

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 | 60 +++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/kernel.h       |  3 +++
 2 files changed, 63 insertions(+)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index a7fd4f1..6026b77 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1620,6 +1620,54 @@ 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 res;
+    gic_interrupt_t intr;
+    __be32 reg[GUEST_ROOT_ADDRESS_CELLS + GUEST_ROOT_SIZE_CELLS];
+    __be32 *cells;
+
+    res = fdt_begin_node(fdt, "sbsa-uart@"__stringify(GUEST_PL011_BASE));
+    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, GUEST_ROOT_ADDRESS_CELLS,
+                       GUEST_ROOT_SIZE_CELLS, 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 future.
@@ -1681,6 +1729,16 @@ static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
     if ( ret )
         goto err;
 
+    if ( kinfo->vpl011 )
+    {
+        ret = -EINVAL;
+#ifdef CONFIG_SBSA_VUART_CONSOLE
+        ret = make_vpl011_uart_node(d, kinfo->fdt);
+#endif
+        if ( ret )
+            goto err;
+    }
+
     ret = fdt_end_node(kinfo->fdt);
     if ( ret < 0 )
         goto err;
@@ -2549,6 +2607,8 @@ static int __init construct_domU(struct domain *d,
 
     printk("*** LOADING DOMU cpus=%u memory=%luKB ***\n", d->max_vcpus, mem);
 
+    kinfo.vpl011 = dt_property_read_bool(node, "vpl011");
+
     if ( vcpu_create(d, 0, 0) == NULL )
         return -ENOMEM;
     d->max_pages = ~0U;
diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
index 4320f72..33f3e72 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] 61+ messages in thread

* [PATCH v5 19/25] xen/arm: introduce a union in vpl011
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (17 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 18/25] xen/arm: generate vpl011 node on device tree for domU Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-23  2:02 ` [PATCH v5 20/25] xen/arm: refactor vpl011_data_avail Stefano Stabellini
                   ` (5 subsequent siblings)
  24 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, 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>
Acked-by: Julien Grall <julien.grall@arm.com>
---
Changes in v4:
- name union "backend"

Changes in v3:
- rename ring field to dom

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

diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index a281eab..ebc045e 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->backend.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->backend.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->backend.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->backend.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->backend.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->backend.dom.ring_page,
+                                  &vpl011->backend.dom.ring_buf);
     if ( rc < 0 )
         goto out;
 
@@ -495,7 +495,8 @@ out2:
     vgic_free_virq(d, GUEST_VPL011_SPI);
 
 out1:
-    destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
+    destroy_ring_for_helper(&vpl011->backend.dom.ring_buf,
+			                vpl011->backend.dom.ring_page);
 
 out:
     return rc;
@@ -505,11 +506,12 @@ void domain_vpl011_deinit(struct domain *d)
 {
     struct vpl011 *vpl011 = &d->arch.vpl011;
 
-    if ( !vpl011->ring_buf )
+    if ( !vpl011->backend.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->backend.dom.ring_buf,
+			                vpl011->backend.dom.ring_page);
 }
 
 /*
diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
index db95ff8..42d7a24 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;
+    } backend;
     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] 61+ messages in thread

* [PATCH v5 20/25] xen/arm: refactor vpl011_data_avail
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (18 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 19/25] xen/arm: introduce a union in vpl011 Stefano Stabellini
@ 2018-10-23  2:02 ` Stefano Stabellini
  2018-10-23  2:03 ` [PATCH v5 21/25] xen: support console_switching between Dom0 and DomUs on ARM Stefano Stabellini
                   ` (4 subsequent siblings)
  24 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:02 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, 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>
Acked-by: Julien Grall <julien.grall@arm.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 ebc045e..68452a8 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->backend.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->backend.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] 61+ messages in thread

* [PATCH v5 21/25] xen: support console_switching between Dom0 and DomUs on ARM
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (19 preceding siblings ...)
  2018-10-23  2:02 ` [PATCH v5 20/25] xen/arm: refactor vpl011_data_avail Stefano Stabellini
@ 2018-10-23  2:03 ` Stefano Stabellini
  2018-10-24 14:55   ` Oleksandr Andrushchenko
  2018-10-26 14:29   ` Jan Beulich
  2018-10-23  2:03 ` [PATCH v5 22/25] xen/arm: Allow vpl011 to be used by DomU Stefano Stabellini
                   ` (3 subsequent siblings)
  24 siblings, 2 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:03 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, sstabellini, andrii_anisov, konrad.wilk,
	George.Dunlap, andrew.cooper3, Achin.Gupta, 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.

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 v5:
- move patch earlier and disable code that calls vpl011_rx_char_xen (not
  defined yet)
- improve comments
- replace ifs with a switch
- code style

Changes in v4:
- handle console_rx == 0 in console_input_domain
- use rcu_lock_by_domain instead of get_domain_by_id
- handle the case where the returned domain is NULL
- send_global_virq(VIRQ_CONSOLE) only when chars are for Dom0
- make console_rx unsigned int
- fix comment
- code readability improvement
- fix opt_conswitch[1] == 'x' case
- move console_input_domain to next patch

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 | 79 ++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 65 insertions(+), 14 deletions(-)

diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 3b75f7a..75172e7 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. */
@@ -391,31 +394,79 @@ 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> changes input direction, rotating among 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 to dom(N-1)
+ */
+static unsigned int __read_mostly 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]);
+    if ( console_rx++ == max_init_domid + 1 )
+        console_rx = 0;
+
+    if ( console_rx == 0 )
+        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 )
+    switch ( console_rx )
+    {
+    case 0:
         return handle_keypress(c, regs);
+    case 1:
+    {
+        /*
+         * Deliver input to the hardware domain 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 hardware domain: prevents receive path from
+         * getting stuck.
+         */
+        send_global_virq(VIRQ_CONSOLE);
+        break;
+    }
+#if 0
+    default:
+    {
+        struct domain *d = rcu_lock_domain_by_any_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 != NULL &&
+             !d->arch.vpl011.backend_in_domain &&
+             d->arch.vpl011.backend.xen != NULL )
+            vpl011_rx_char_xen(d, c);
+        else
+            printk("Cannot send chars to Dom%d: no UART available\n",
+                   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;
-    /* Always notify the guest: prevents receive path from getting stuck. */
-    send_global_virq(VIRQ_CONSOLE);
+        if ( d != NULL )
+            rcu_unlock_domain(d);
+    }
+#endif
+    }
 
 #ifdef CONFIG_X86
     if ( pv_shim && pv_console )
@@ -943,7 +994,7 @@ void __init console_endboot(void)
      * a useful 'how to switch' message.
      */
     if ( opt_conswitch[1] == 'x' )
-        xen_rx = !xen_rx;
+        console_rx = max_init_domid + 1;
 
     register_keyhandler('w', dump_console_ring_key,
                         "synchronously dump console ring buffer (dmesg)", 0);
-- 
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] 61+ messages in thread

* [PATCH v5 22/25] xen/arm: Allow vpl011 to be used by DomU
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (20 preceding siblings ...)
  2018-10-23  2:03 ` [PATCH v5 21/25] xen: support console_switching between Dom0 and DomUs on ARM Stefano Stabellini
@ 2018-10-23  2:03 ` Stefano Stabellini
  2018-10-24 17:14   ` Oleksandr Tyshchenko
  2018-10-23  2:03 ` [PATCH v5 23/25] xen/vpl011: buffer out chars when the backend is xen Stefano Stabellini
                   ` (2 subsequent siblings)
  24 siblings, 1 reply; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:03 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, 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>
Acked-by: Julien Grall <julien.grall@arm.com>
---
Changes in v5:
- renable call to vpl011_rx_char_xen from console.c

Changes in v4:
- code style

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        | 200 +++++++++++++++++++++++++++++++++++++------
 xen/drivers/char/console.c   |   2 +-
 xen/include/asm-arm/vpl011.h |   8 ++
 4 files changed, 193 insertions(+), 26 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 6026b77..9ffd919 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -2629,7 +2629,14 @@ static int __init construct_domU(struct domain *d,
     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 68452a8..131507e 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->backend.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->backend.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->backend.dom.ring_buf )
         return -EINVAL;
 
-    /* Map the guest PFN to Xen address space. */
-    rc =  prepare_ring_for_helper(d,
-                                  gfn_x(info->gfn),
-                                  &vpl011->backend.dom.ring_page,
-                                  &vpl011->backend.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->backend.dom.ring_page,
+                                      &vpl011->backend.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->backend.xen = xzalloc(struct vpl011_xen_backend);
+        if ( vpl011->backend.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,8 +647,11 @@ out2:
     vgic_free_virq(d, GUEST_VPL011_SPI);
 
 out1:
-    destroy_ring_for_helper(&vpl011->backend.dom.ring_buf,
-			                vpl011->backend.dom.ring_page);
+    if ( vpl011->backend_in_domain )
+        destroy_ring_for_helper(&vpl011->backend.dom.ring_buf,
+                                vpl011->backend.dom.ring_page);
+    else
+        xfree(vpl011->backend.xen);
 
 out:
     return rc;
@@ -514,12 +661,17 @@ void domain_vpl011_deinit(struct domain *d)
 {
     struct vpl011 *vpl011 = &d->arch.vpl011;
 
-    if ( !vpl011->backend.dom.ring_buf )
-        return;
+    if ( vpl011->backend_in_domain )
+    {
+        if ( !vpl011->backend.dom.ring_buf )
+            return;
 
-    free_xen_event_channel(d, vpl011->evtchn);
-    destroy_ring_for_helper(&vpl011->backend.dom.ring_buf,
-			                vpl011->backend.dom.ring_page);
+        free_xen_event_channel(d, vpl011->evtchn);
+        destroy_ring_for_helper(&vpl011->backend.dom.ring_buf,
+                                vpl011->backend.dom.ring_page);
+    }
+    else
+        xfree(vpl011->backend.xen);
 }
 
 /*
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 75172e7..990c51c 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -444,7 +444,7 @@ static void __serial_rx(char c, struct cpu_user_regs *regs)
         send_global_virq(VIRQ_CONSOLE);
         break;
     }
-#if 0
+#ifdef CONFIG_SBSA_VUART_CONSOLE
     default:
     {
         struct domain *d = rcu_lock_domain_by_any_id(console_rx - 1);
diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
index 42d7a24..5eb6d25 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;
     } backend;
     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] 61+ messages in thread

* [PATCH v5 23/25] xen/vpl011: buffer out chars when the backend is xen
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (21 preceding siblings ...)
  2018-10-23  2:03 ` [PATCH v5 22/25] xen/arm: Allow vpl011 to be used by DomU Stefano Stabellini
@ 2018-10-23  2:03 ` Stefano Stabellini
  2018-10-24 14:46   ` Oleksandr Andrushchenko
  2018-10-31 13:27   ` Julien Grall
  2018-10-23  2:03 ` [PATCH v5 24/25] xen/arm: move kernel.h to asm-arm/ Stefano Stabellini
  2018-10-23  2:03 ` [PATCH v5 25/25] xen/arm: split domain_build.c Stefano Stabellini
  24 siblings, 2 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:03 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, sstabellini, andrii_anisov, konrad.wilk,
	George.Dunlap, andrew.cooper3, Achin.Gupta, ian.jackson,
	xen-devel, tim, jbeulich, wei.liu2

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, choose the same size
as VUART_BUT_SIZE used in vuart.c.

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
---
XXX: merge this patch with "xen/arm: Allow vpl011 to be used by DomU" on
     commit

Changes in v5:
- use rcu_lock in console_input_domain
- rcu_unlock at the end of vpl011_write_data_xen
- add a comment on top of console_input_domain as a reminder that the
  caller needs to rcu_unlock

Changes in v4:
- make SBSA_UART_OUT_BUF_SIZE the same size of VUART_BUT_SIZE
- rearrange the code to be clearer input and != input cases
- code style
- add \n when printing the out buffer because is full
- don't print prefix for input domain
---
 xen/arch/arm/vpl011.c        | 36 +++++++++++++++++++++++++++++++++---
 xen/drivers/char/console.c   |  8 ++++++++
 xen/include/asm-arm/vpl011.h |  4 ++++
 xen/include/xen/console.h    |  2 ++
 4 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index 131507e..f7db18b 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,18 +86,47 @@ 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->backend.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 )
+    {
+        if ( intf->out_prod == 1 )
+        {
+            printk("%c", data);
+            intf->out_prod = 0;
+        }
+        else
+        {
+            if ( data != '\n' )
+                intf->out[intf->out_prod++] = '\n';
+            intf->out[intf->out_prod++] = '\0';
+            printk("%s", 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;
+        }
+    }
 
     vpl011->uartris |= TXI;
     vpl011->uartfr &= ~TXFE;
     vpl011_update_interrupt_status(d);
 
     VPL011_UNLOCK(d, flags);
+    rcu_unlock_domain(input);
 }
 
 /*
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 990c51c..eb1cc1b 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -406,6 +406,14 @@ static void dump_console_ring_key(unsigned char key)
  */
 static unsigned int __read_mostly console_rx = 0;
 
+/* Make sure to rcu_unlock_domain after use */
+struct domain *console_input_domain(void)
+{
+    if ( console_rx == 0 )
+            return NULL;
+    return rcu_lock_domain_by_id(console_rx - 1);
+}
+
 static void switch_serial_input(void)
 {
     if ( console_rx++ == max_init_domid + 1 )
diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
index 5eb6d25..ab6fd79 100644
--- a/xen/include/asm-arm/vpl011.h
+++ b/xen/include/asm-arm/vpl011.h
@@ -30,9 +30,13 @@
 #define VPL011_UNLOCK(d,flags) spin_unlock_irqrestore(&(d)->arch.vpl011.lock, flags)
 
 #define SBSA_UART_FIFO_SIZE 32
+/* Same size as VUART_BUT_SIZE, used in vuart.c */
+#define SBSA_UART_OUT_BUF_SIZE 128
 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 {
diff --git a/xen/include/xen/console.h b/xen/include/xen/console.h
index 70c9911..c5a85c8 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] 61+ messages in thread

* [PATCH v5 24/25] xen/arm: move kernel.h to asm-arm/
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (22 preceding siblings ...)
  2018-10-23  2:03 ` [PATCH v5 23/25] xen/vpl011: buffer out chars when the backend is xen Stefano Stabellini
@ 2018-10-23  2:03 ` Stefano Stabellini
  2018-10-31 13:28   ` Julien Grall
  2018-10-23  2:03 ` [PATCH v5 25/25] xen/arm: split domain_build.c Stefano Stabellini
  24 siblings, 1 reply; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:03 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, sstabellini, andrii_anisov, xen-devel

It will be #included by a file in a xen/arch/arm subdirectory.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
 xen/arch/arm/domain_build.c  |  2 +-
 xen/arch/arm/kernel.c        |  3 +-
 xen/arch/arm/kernel.h        | 86 --------------------------------------------
 xen/include/asm-arm/kernel.h | 86 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 88 insertions(+), 89 deletions(-)
 delete mode 100644 xen/arch/arm/kernel.h
 create mode 100644 xen/include/asm-arm/kernel.h

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 9ffd919..6f47832 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -17,6 +17,7 @@
 #include <xen/warning.h>
 #include <acpi/actables.h>
 #include <asm/device.h>
+#include <asm/kernel.h>
 #include <asm/setup.h>
 #include <asm/platform.h>
 #include <asm/psci.h>
@@ -25,7 +26,6 @@
 
 #include <xen/irq.h>
 #include <xen/grant_table.h>
-#include "kernel.h"
 
 static unsigned int __initdata opt_dom0_max_vcpus;
 integer_param("dom0_max_vcpus", opt_dom0_max_vcpus);
diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
index d56f776..d10c03a 100644
--- a/xen/arch/arm/kernel.c
+++ b/xen/arch/arm/kernel.c
@@ -16,8 +16,7 @@
 #include <xen/vmap.h>
 
 #include <asm/guest_access.h>
-
-#include "kernel.h"
+#include <asm/kernel.h>
 
 #define UIMAGE_MAGIC          0x27051956
 #define UIMAGE_NMLEN          32
diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
deleted file mode 100644
index 33f3e72..0000000
--- a/xen/arch/arm/kernel.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Kernel image loading.
- *
- * Copyright (C) 2011 Citrix Systems, Inc.
- */
-#ifndef __ARCH_ARM_KERNEL_H__
-#define __ARCH_ARM_KERNEL_H__
-
-#include <xen/device_tree.h>
-#include <asm/setup.h>
-
-struct kernel_info {
-#ifdef CONFIG_ARM_64
-    enum domain_type type;
-#endif
-
-    struct domain *d;
-
-    void *fdt; /* flat device tree */
-    paddr_t unassigned_mem; /* RAM not (yet) assigned to a bank */
-    struct meminfo mem;
-
-    /* kernel entry point */
-    paddr_t entry;
-
-    /* grant table region */
-    paddr_t gnttab_start;
-    paddr_t gnttab_size;
-
-    /* boot blob load addresses */
-    const struct bootmodule *kernel_bootmodule, *initrd_bootmodule;
-    const char* cmdline;
-    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 */
-    union {
-        struct {
-            paddr_t kernel_addr;
-            paddr_t len;
-#ifdef CONFIG_ARM_64
-            paddr_t text_offset; /* 64-bit Image only */
-#endif
-            paddr_t start; /* 32-bit zImage only */
-        } zimage;
-    };
-};
-
-/*
- * Probe the kernel to detemine its type and select a loader.
- *
- * Sets in info:
- *  ->type
- *  ->load hook, and sets loader specific variables ->zimage
- */
-int kernel_probe(struct kernel_info *info, const struct dt_device_node *domain);
-
-/*
- * Loads the kernel into guest RAM.
- *
- * Expects to be set in info when called:
- *  ->mem
- *  ->fdt
- *
- * Sets in info:
- *  ->entry
- *  ->dtb_paddr
- *  ->initrd_paddr
- */
-void kernel_load(struct kernel_info *info);
-
-#endif /* #ifdef __ARCH_ARM_KERNEL_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/include/asm-arm/kernel.h b/xen/include/asm-arm/kernel.h
new file mode 100644
index 0000000..33f3e72
--- /dev/null
+++ b/xen/include/asm-arm/kernel.h
@@ -0,0 +1,86 @@
+/*
+ * Kernel image loading.
+ *
+ * Copyright (C) 2011 Citrix Systems, Inc.
+ */
+#ifndef __ARCH_ARM_KERNEL_H__
+#define __ARCH_ARM_KERNEL_H__
+
+#include <xen/device_tree.h>
+#include <asm/setup.h>
+
+struct kernel_info {
+#ifdef CONFIG_ARM_64
+    enum domain_type type;
+#endif
+
+    struct domain *d;
+
+    void *fdt; /* flat device tree */
+    paddr_t unassigned_mem; /* RAM not (yet) assigned to a bank */
+    struct meminfo mem;
+
+    /* kernel entry point */
+    paddr_t entry;
+
+    /* grant table region */
+    paddr_t gnttab_start;
+    paddr_t gnttab_size;
+
+    /* boot blob load addresses */
+    const struct bootmodule *kernel_bootmodule, *initrd_bootmodule;
+    const char* cmdline;
+    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 */
+    union {
+        struct {
+            paddr_t kernel_addr;
+            paddr_t len;
+#ifdef CONFIG_ARM_64
+            paddr_t text_offset; /* 64-bit Image only */
+#endif
+            paddr_t start; /* 32-bit zImage only */
+        } zimage;
+    };
+};
+
+/*
+ * Probe the kernel to detemine its type and select a loader.
+ *
+ * Sets in info:
+ *  ->type
+ *  ->load hook, and sets loader specific variables ->zimage
+ */
+int kernel_probe(struct kernel_info *info, const struct dt_device_node *domain);
+
+/*
+ * Loads the kernel into guest RAM.
+ *
+ * Expects to be set in info when called:
+ *  ->mem
+ *  ->fdt
+ *
+ * Sets in info:
+ *  ->entry
+ *  ->dtb_paddr
+ *  ->initrd_paddr
+ */
+void kernel_load(struct kernel_info *info);
+
+#endif /* #ifdef __ARCH_ARM_KERNEL_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
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] 61+ messages in thread

* [PATCH v5 25/25] xen/arm: split domain_build.c
  2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (23 preceding siblings ...)
  2018-10-23  2:03 ` [PATCH v5 24/25] xen/arm: move kernel.h to asm-arm/ Stefano Stabellini
@ 2018-10-23  2:03 ` Stefano Stabellini
  2018-10-31 13:44   ` Julien Grall
  24 siblings, 1 reply; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-23  2:03 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, Achin.Gupta, 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/domain_build.c.

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

---

Changes in v4:
- rename acpi_dt_build to domain_build.c
- add copyright header
- remove useless #include
- remove acpi_dt_build.h, add domain_build.h
---
 xen/arch/arm/acpi/Makefile         |   1 +
 xen/arch/arm/acpi/domain_build.c   | 592 +++++++++++++++++++++++++++++++++++++
 xen/arch/arm/domain_build.c        | 585 +-----------------------------------
 xen/include/asm-arm/domain_build.h |  31 ++
 4 files changed, 629 insertions(+), 580 deletions(-)
 create mode 100644 xen/arch/arm/acpi/domain_build.c
 create mode 100644 xen/include/asm-arm/domain_build.h

diff --git a/xen/arch/arm/acpi/Makefile b/xen/arch/arm/acpi/Makefile
index 23963f8..94ae249 100644
--- a/xen/arch/arm/acpi/Makefile
+++ b/xen/arch/arm/acpi/Makefile
@@ -1,2 +1,3 @@
 obj-y += lib.o
+obj-y += domain_build.o
 obj-y += boot.init.o
diff --git a/xen/arch/arm/acpi/domain_build.c b/xen/arch/arm/acpi/domain_build.c
new file mode 100644
index 0000000..44d3ad1
--- /dev/null
+++ b/xen/arch/arm/acpi/domain_build.c
@@ -0,0 +1,592 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#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 <acpi/actables.h>
+#include <asm/kernel.h>
+#include <asm/domain_build.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;
+}
+
+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;
+}
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 6f47832..9f8e37c 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -23,6 +23,7 @@
 #include <asm/psci.h>
 #include <asm/setup.h>
 #include <asm/cpufeature.h>
+#include <asm/domain_build.h>
 
 #include <xen/irq.h>
 #include <xen/grant_table.h>
@@ -676,8 +677,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)
@@ -1038,7 +1037,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;
@@ -1079,8 +1078,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;
 
@@ -1794,580 +1793,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;
@@ -2440,7 +1865,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;
diff --git a/xen/include/asm-arm/domain_build.h b/xen/include/asm-arm/domain_build.h
new file mode 100644
index 0000000..34ceddc
--- /dev/null
+++ b/xen/include/asm-arm/domain_build.h
@@ -0,0 +1,31 @@
+#ifndef __ASM_DOMAIN_BUILD_H__
+#define __ASM_DOMAIN_BUILD_H__
+
+#include <xen/sched.h>
+#include <asm/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:
+ */
-- 
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] 61+ messages in thread

* Re: [PATCH v5 23/25] xen/vpl011: buffer out chars when the backend is xen
  2018-10-23  2:03 ` [PATCH v5 23/25] xen/vpl011: buffer out chars when the backend is xen Stefano Stabellini
@ 2018-10-24 14:46   ` Oleksandr Andrushchenko
  2018-10-29 20:09     ` Stefano Stabellini
  2018-10-31 13:27   ` Julien Grall
  1 sibling, 1 reply; 61+ messages in thread
From: Oleksandr Andrushchenko @ 2018-10-24 14:46 UTC (permalink / raw)
  To: Stefano Stabellini, julien.grall
  Cc: Stefano Stabellini, andrii_anisov, konrad.wilk, George.Dunlap,
	andrew.cooper3, Achin.Gupta, ian.jackson, xen-devel, tim,
	jbeulich, wei.liu2

On 10/23/2018 05:03 AM, 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, choose the same size
> as VUART_BUT_SIZE used in vuart.c.
s/VUART_BUT_SIZE/VUART_BUF_SIZE
>
> 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
> ---
> XXX: merge this patch with "xen/arm: Allow vpl011 to be used by DomU" on
>       commit
>
> Changes in v5:
> - use rcu_lock in console_input_domain
> - rcu_unlock at the end of vpl011_write_data_xen
> - add a comment on top of console_input_domain as a reminder that the
>    caller needs to rcu_unlock
>
> Changes in v4:
> - make SBSA_UART_OUT_BUF_SIZE the same size of VUART_BUT_SIZE
> - rearrange the code to be clearer input and != input cases
> - code style
> - add \n when printing the out buffer because is full
> - don't print prefix for input domain
> ---
>   xen/arch/arm/vpl011.c        | 36 +++++++++++++++++++++++++++++++++---
>   xen/drivers/char/console.c   |  8 ++++++++
>   xen/include/asm-arm/vpl011.h |  4 ++++
>   xen/include/xen/console.h    |  2 ++
>   4 files changed, 47 insertions(+), 3 deletions(-)
>
> diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> index 131507e..f7db18b 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,18 +86,47 @@ 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->backend.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 )
> +    {
> +        if ( intf->out_prod == 1 )
> +        {
> +            printk("%c", data);
> +            intf->out_prod = 0;
> +        }
> +        else
> +        {
> +            if ( data != '\n' )
> +                intf->out[intf->out_prod++] = '\n';
> +            intf->out[intf->out_prod++] = '\0';
> +            printk("%s", 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;
> +        }
> +    }
>   
>       vpl011->uartris |= TXI;
>       vpl011->uartfr &= ~TXFE;
>       vpl011_update_interrupt_status(d);
>   
>       VPL011_UNLOCK(d, flags);
> +    rcu_unlock_domain(input);
input can be NULL. Although it won't hurt with the existing
code base things could change any time soon...
>   }
>   
>   /*
> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> index 990c51c..eb1cc1b 100644
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -406,6 +406,14 @@ static void dump_console_ring_key(unsigned char key)
>    */
>   static unsigned int __read_mostly console_rx = 0;
>   
> +/* Make sure to rcu_unlock_domain after use */
> +struct domain *console_input_domain(void)
> +{
> +    if ( console_rx == 0 )
> +            return NULL;
> +    return rcu_lock_domain_by_id(console_rx - 1);
> +}
> +
>   static void switch_serial_input(void)
>   {
>       if ( console_rx++ == max_init_domid + 1 )
> diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
> index 5eb6d25..ab6fd79 100644
> --- a/xen/include/asm-arm/vpl011.h
> +++ b/xen/include/asm-arm/vpl011.h
> @@ -30,9 +30,13 @@
>   #define VPL011_UNLOCK(d,flags) spin_unlock_irqrestore(&(d)->arch.vpl011.lock, flags)
>   
>   #define SBSA_UART_FIFO_SIZE 32
> +/* Same size as VUART_BUT_SIZE, used in vuart.c */
> +#define SBSA_UART_OUT_BUF_SIZE 128
>   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 {
> diff --git a/xen/include/xen/console.h b/xen/include/xen/console.h
> index 70c9911..c5a85c8 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] 61+ messages in thread

* Re: [PATCH v5 21/25] xen: support console_switching between Dom0 and DomUs on ARM
  2018-10-23  2:03 ` [PATCH v5 21/25] xen: support console_switching between Dom0 and DomUs on ARM Stefano Stabellini
@ 2018-10-24 14:55   ` Oleksandr Andrushchenko
  2018-10-29 20:00     ` Stefano Stabellini
  2018-10-26 14:29   ` Jan Beulich
  1 sibling, 1 reply; 61+ messages in thread
From: Oleksandr Andrushchenko @ 2018-10-24 14:55 UTC (permalink / raw)
  To: Stefano Stabellini, julien.grall
  Cc: Stefano Stabellini, andrii_anisov, konrad.wilk, George.Dunlap,
	andrew.cooper3, Achin.Gupta, ian.jackson, xen-devel, tim,
	jbeulich, wei.liu2

On 10/23/2018 05:03 AM, 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.
>
> 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 v5:
> - move patch earlier and disable code that calls vpl011_rx_char_xen (not
>    defined yet)
> - improve comments
> - replace ifs with a switch
> - code style
>
> Changes in v4:
> - handle console_rx == 0 in console_input_domain
> - use rcu_lock_by_domain instead of get_domain_by_id
> - handle the case where the returned domain is NULL
> - send_global_virq(VIRQ_CONSOLE) only when chars are for Dom0
> - make console_rx unsigned int
> - fix comment
> - code readability improvement
> - fix opt_conswitch[1] == 'x' case
> - move console_input_domain to next patch
>
> 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 | 79 ++++++++++++++++++++++++++++++++++++++--------
>   1 file changed, 65 insertions(+), 14 deletions(-)
>
> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> index 3b75f7a..75172e7 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. */
> @@ -391,31 +394,79 @@ 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> changes input direction, rotating among 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 to dom(N-1)
> + */
> +static unsigned int __read_mostly 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]);
> +    if ( console_rx++ == max_init_domid + 1 )
> +        console_rx = 0;
> +
> +    if ( console_rx == 0 )
> +        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 )
> +    switch ( console_rx )
> +    {
> +    case 0:
>           return handle_keypress(c, regs);
> +    case 1:
> +    {
> +        /*
> +         * Deliver input to the hardware domain 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 hardware domain: prevents receive path from
> +         * getting stuck.
> +         */
> +        send_global_virq(VIRQ_CONSOLE);
> +        break;
> +    }
+ * console_rx=0 => input to xen
+ * console_rx=1 => input to dom0
+ * console_rx=N => input to dom(N-1)
So, why do you only handle case 0/1?
> +#if 0
Do you need this #if 0?
> +    default:
> +    {
> +        struct domain *d = rcu_lock_domain_by_any_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 != NULL &&
> +             !d->arch.vpl011.backend_in_domain &&
> +             d->arch.vpl011.backend.xen != NULL )
> +            vpl011_rx_char_xen(d, c);
> +        else
> +            printk("Cannot send chars to Dom%d: no UART available\n",
> +                   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;
> -    /* Always notify the guest: prevents receive path from getting stuck. */
> -    send_global_virq(VIRQ_CONSOLE);
> +        if ( d != NULL )
> +            rcu_unlock_domain(d);
> +    }
> +#endif
> +    }
>   
>   #ifdef CONFIG_X86
>       if ( pv_shim && pv_console )
> @@ -943,7 +994,7 @@ void __init console_endboot(void)
>        * a useful 'how to switch' message.
>        */
>       if ( opt_conswitch[1] == 'x' )
> -        xen_rx = !xen_rx;
> +        console_rx = max_init_domid + 1;
>   
>       register_keyhandler('w', dump_console_ring_key,
>                           "synchronously dump console ring buffer (dmesg)", 0);


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

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

* Re: [PATCH v5 22/25] xen/arm: Allow vpl011 to be used by DomU
  2018-10-23  2:03 ` [PATCH v5 22/25] xen/arm: Allow vpl011 to be used by DomU Stefano Stabellini
@ 2018-10-24 17:14   ` Oleksandr Tyshchenko
  2018-10-29 20:03     ` Stefano Stabellini
  0 siblings, 1 reply; 61+ messages in thread
From: Oleksandr Tyshchenko @ 2018-10-24 17:14 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: stefanos, Julien Grall, Andrii Anisov, Achin.Gupta, Xen Devel

Hi, Stefano

On Tue, Oct 23, 2018 at 5:04 AM Stefano Stabellini
<sstabellini@kernel.org> 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>
> Acked-by: Julien Grall <julien.grall@arm.com>
> ---
> Changes in v5:
> - renable call to vpl011_rx_char_xen from console.c
>
> Changes in v4:
> - code style
>
> 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        | 200 +++++++++++++++++++++++++++++++++++++------
>  xen/drivers/char/console.c   |   2 +-
>  xen/include/asm-arm/vpl011.h |   8 ++
>  4 files changed, 193 insertions(+), 26 deletions(-)
>
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 6026b77..9ffd919 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -2629,7 +2629,14 @@ static int __init construct_domU(struct domain *d,
>      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 68452a8..131507e 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->backend.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->backend.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;
Do we need barriers here and after writing the ring?

> +    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->backend.dom.ring_buf )
>          return -EINVAL;
>
> -    /* Map the guest PFN to Xen address space. */
> -    rc =  prepare_ring_for_helper(d,
> -                                  gfn_x(info->gfn),
> -                                  &vpl011->backend.dom.ring_page,
> -                                  &vpl011->backend.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->backend.dom.ring_page,
> +                                      &vpl011->backend.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->backend.xen = xzalloc(struct vpl011_xen_backend);
> +        if ( vpl011->backend.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,8 +647,11 @@ out2:
>      vgic_free_virq(d, GUEST_VPL011_SPI);
>
>  out1:
> -    destroy_ring_for_helper(&vpl011->backend.dom.ring_buf,
> -                                       vpl011->backend.dom.ring_page);
> +    if ( vpl011->backend_in_domain )
> +        destroy_ring_for_helper(&vpl011->backend.dom.ring_buf,
> +                                vpl011->backend.dom.ring_page);
> +    else
> +        xfree(vpl011->backend.xen);
>
>  out:
>      return rc;
> @@ -514,12 +661,17 @@ void domain_vpl011_deinit(struct domain *d)
>  {
>      struct vpl011 *vpl011 = &d->arch.vpl011;
>
> -    if ( !vpl011->backend.dom.ring_buf )
> -        return;
> +    if ( vpl011->backend_in_domain )
> +    {
> +        if ( !vpl011->backend.dom.ring_buf )
> +            return;
>
> -    free_xen_event_channel(d, vpl011->evtchn);
> -    destroy_ring_for_helper(&vpl011->backend.dom.ring_buf,
> -                                       vpl011->backend.dom.ring_page);
> +        free_xen_event_channel(d, vpl011->evtchn);
> +        destroy_ring_for_helper(&vpl011->backend.dom.ring_buf,
> +                                vpl011->backend.dom.ring_page);
> +    }
> +    else
> +        xfree(vpl011->backend.xen);
>  }
>
>  /*
> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> index 75172e7..990c51c 100644
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -444,7 +444,7 @@ static void __serial_rx(char c, struct cpu_user_regs *regs)
>          send_global_virq(VIRQ_CONSOLE);
>          break;
>      }
> -#if 0
> +#ifdef CONFIG_SBSA_VUART_CONSOLE
>      default:
>      {
>          struct domain *d = rcu_lock_domain_by_any_id(console_rx - 1);
> diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
> index 42d7a24..5eb6d25 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;
>      } backend;
>      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



-- 
Regards,

Oleksandr Tyshchenko

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

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

* Re: [PATCH v5 21/25] xen: support console_switching between Dom0 and DomUs on ARM
  2018-10-23  2:03 ` [PATCH v5 21/25] xen: support console_switching between Dom0 and DomUs on ARM Stefano Stabellini
  2018-10-24 14:55   ` Oleksandr Andrushchenko
@ 2018-10-26 14:29   ` Jan Beulich
  2018-10-29 19:56     ` Stefano Stabellini
  1 sibling, 1 reply; 61+ messages in thread
From: Jan Beulich @ 2018-10-26 14:29 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Tim Deegan, andrii_anisov, Konrad Rzeszutek Wilk, George Dunlap,
	Andrew Cooper, Achin.Gupta, Ian Jackson, xen-devel, Julien Grall,
	Stefano Stabellini, Wei Liu

>>> On 23.10.18 at 04:03, <sstabellini@kernel.org> wrote:
> @@ -391,31 +394,79 @@ 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> changes input direction, rotating among Xen, Dom0,
> + * and DomUs.

Proper attribute to be inserted here, as per my (late) v4 comment.

> + */
>  #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 to dom(N-1)
> + */
> +static unsigned int __read_mostly 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]);
> +    if ( console_rx++ == max_init_domid + 1 )
> +        console_rx = 0;
> +
> +    if ( console_rx == 0 )
> +        printk("*** Serial input to Xen");

I think these two if()-s can and should be combined. Furthermore
I think it would be worthwhile to defer the increment until ...

> +    else
> +        printk("*** Serial input to DOM%d", console_rx - 1);

... after this printk(), but (obviously) then inside the else block.

>      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 )
> +    switch ( console_rx )
> +    {
> +    case 0:
>          return handle_keypress(c, regs);
> +    case 1:
> +    {

Stray figure braces. Blank lines between case blocks please.

> +        /*
> +         * Deliver input to the hardware domain 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 hardware domain: prevents receive path from
> +         * getting stuck.
> +         */
> +        send_global_virq(VIRQ_CONSOLE);
> +        break;
> +    }
> +#if 0

I suppose a later patch is meant to remove this again. But
perhaps still a good idea to attach a brief comment, in case
the series doesn't go in all in one go? This is assuming you
did already consider (and discard for whatever reason) the
option of adding this default case when the code can
actually be used.

Jan



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

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

* Re: [PATCH v5 05/25] xen/arm: check for multiboot nodes only under /chosen
  2018-10-23  2:02 ` [PATCH v5 05/25] xen/arm: check for multiboot nodes only under /chosen Stefano Stabellini
@ 2018-10-26 19:25   ` Julien Grall
  2018-10-26 21:12     ` Stefano Stabellini
  0 siblings, 1 reply; 61+ messages in thread
From: Julien Grall @ 2018-10-26 19:25 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, Achin.Gupta, andrii_anisov, xen-devel

Hi Stefano,

On 10/23/18 3:02 AM, Stefano Stabellini wrote:
> Make sure to only look for multiboot compatible nodes only under
> /chosen, not under any other paths (depth <= 3).
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> 
> ---
> 
> Changes in v5:
> - add patch
> - add check on return value of fdt_get_path
> ---
>   xen/arch/arm/bootfdt.c | 13 ++++++++++---
>   1 file changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
> index 8eba42c..a314aca 100644
> --- a/xen/arch/arm/bootfdt.c
> +++ b/xen/arch/arm/bootfdt.c
> @@ -173,7 +173,14 @@ static void __init process_multiboot_node(const void *fdt, int node,
>       bootmodule_kind kind;
>       paddr_t start, size;
>       const char *cmdline;
> -    int len;
> +    int len = sizeof("/chosen");

NIT, I am not convince you win anything with that trick. strlen could be 
optimized by the compiler (we use __builtin_strlen on Arm64).

> +    char path[8]; /* sizeof "/chosen" */
> +    int ret;
> +
> +    /* Check that the node is under "chosen" */
> +    ret = fdt_get_path(fdt, node, path, len);
> +    if ( ret == 0 && strncmp(path, "/chosen", len - 1) )
> +        return;

This is quite odd. You continue if fdt_get_path() returns an error. 
Shouldn't it be:

ret || strncmp(path, "/chosen", strlen("/chosen")

>   
>       prop = fdt_get_property(fdt, node, "reg", &len);
>       if ( !prop )
> @@ -286,8 +293,8 @@ static int __init early_scan_node(const void *fdt,
>   {
>       if ( device_tree_node_matches(fdt, node, "memory") )
>           process_memory_node(fdt, node, name, address_cells, size_cells);
> -    else if ( device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) ||
> -              device_tree_node_compatible(fdt, node, "multiboot,module" ))
> +    else if ( depth <= 3 && (device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) ||
> +              device_tree_node_compatible(fdt, node, "multiboot,module" )))
>           process_multiboot_node(fdt, node, name, address_cells, size_cells);
>       else if ( depth == 1 && device_tree_node_matches(fdt, node, "chosen") )
>           process_chosen_node(fdt, node, name, address_cells, size_cells);
> 

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] 61+ messages in thread

* Re: [PATCH v5 06/25] xen/arm: introduce bootcmdlines
  2018-10-23  2:02 ` [PATCH v5 06/25] xen/arm: introduce bootcmdlines Stefano Stabellini
@ 2018-10-26 19:44   ` Julien Grall
  2018-10-27  0:34     ` Stefano Stabellini
  0 siblings, 1 reply; 61+ messages in thread
From: Julien Grall @ 2018-10-26 19:44 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, Achin.Gupta, andrii_anisov, xen-devel

Hi Stefano,

On 10/23/18 3:02 AM, Stefano Stabellini wrote:
> @@ -314,12 +312,12 @@ 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++ )
>       {
> @@ -332,6 +330,11 @@ static void __init early_print_info(void)
>                        i, s, e);
>       }
>       printk("\n");
> +    for ( i = 0 ; i < cmds->nr_mods; i++ )
> +        printk("CMDLINE[%d]:%s %s\n", i,
> +               cmds->cmdline[i].dt_name,
> +               &cmds->cmdline[i].cmdline[0]);
> +    printk("\n");

I am ok to see to accept this patch with this new prints. However,
I would like to see a fix for it as soon as possible because this will 
be a massive pain to debug if a user has a issue. Indeed we can't figure 
out whether from the log the associatation cmdline <-> modules.

[...]

> @@ -2109,6 +2107,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;
> @@ -2154,6 +2153,7 @@ int __init construct_dom0(struct domain *d)
>   
>   #endif
>   
> +    kinfo.cmdline = kernel != NULL ? &kernel->cmdline[0] : NULL;

That's not the most obvious line to read. I would either put the 
condition between parentheses or use drop != NULL.

The rest of the code looks good to me. With that change and the other 
comment addressed in a separate patch:

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

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] 61+ messages in thread

* Re: [PATCH v5 05/25] xen/arm: check for multiboot nodes only under /chosen
  2018-10-26 19:25   ` Julien Grall
@ 2018-10-26 21:12     ` Stefano Stabellini
  2018-10-26 21:27       ` Julien Grall
  0 siblings, 1 reply; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-26 21:12 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Achin.Gupta, Stefano Stabellini,
	andrii_anisov, xen-devel

On Fri, 26 Oct 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 10/23/18 3:02 AM, Stefano Stabellini wrote:
> > Make sure to only look for multiboot compatible nodes only under
> > /chosen, not under any other paths (depth <= 3).
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > 
> > ---
> > 
> > Changes in v5:
> > - add patch
> > - add check on return value of fdt_get_path
> > ---
> >   xen/arch/arm/bootfdt.c | 13 ++++++++++---
> >   1 file changed, 10 insertions(+), 3 deletions(-)
> > 
> > diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
> > index 8eba42c..a314aca 100644
> > --- a/xen/arch/arm/bootfdt.c
> > +++ b/xen/arch/arm/bootfdt.c
> > @@ -173,7 +173,14 @@ static void __init process_multiboot_node(const void
> > *fdt, int node,
> >       bootmodule_kind kind;
> >       paddr_t start, size;
> >       const char *cmdline;
> > -    int len;
> > +    int len = sizeof("/chosen");
> 
> NIT, I am not convince you win anything with that trick. strlen could be
> optimized by the compiler (we use __builtin_strlen on Arm64).

I could use strlen if you prefer, but given that the string is known at
compile time, it should hopefully be resolved to "8" at compile time
using sizeof. What's wrong with it?


> > +    char path[8]; /* sizeof "/chosen" */
> > +    int ret;
> > +
> > +    /* Check that the node is under "chosen" */
> > +    ret = fdt_get_path(fdt, node, path, len);
> > +    if ( ret == 0 && strncmp(path, "/chosen", len - 1) )
> > +        return;
> 
> This is quite odd. You continue if fdt_get_path() returns an error. Shouldn't
> it be:
> 
> ret || strncmp(path, "/chosen", strlen("/chosen")

You are right, I'll change it


> >         prop = fdt_get_property(fdt, node, "reg", &len);
> >       if ( !prop )
> > @@ -286,8 +293,8 @@ static int __init early_scan_node(const void *fdt,
> >   {
> >       if ( device_tree_node_matches(fdt, node, "memory") )
> >           process_memory_node(fdt, node, name, address_cells, size_cells);
> > -    else if ( device_tree_node_compatible(fdt, node, "xen,multiboot-module"
> > ) ||
> > -              device_tree_node_compatible(fdt, node, "multiboot,module" ))
> > +    else if ( depth <= 3 && (device_tree_node_compatible(fdt, node,
> > "xen,multiboot-module" ) ||
> > +              device_tree_node_compatible(fdt, node, "multiboot,module" )))
> >           process_multiboot_node(fdt, node, name, address_cells,
> > size_cells);
> >       else if ( depth == 1 && device_tree_node_matches(fdt, node, "chosen")
> > )
> >           process_chosen_node(fdt, node, name, address_cells, size_cells);

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

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

* Re: [PATCH v5 05/25] xen/arm: check for multiboot nodes only under /chosen
  2018-10-26 21:12     ` Stefano Stabellini
@ 2018-10-26 21:27       ` Julien Grall
  2018-10-26 21:32         ` Julien Grall
  0 siblings, 1 reply; 61+ messages in thread
From: Julien Grall @ 2018-10-26 21:27 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, Achin.Gupta, andrii_anisov, xen-devel

Hi,

On 10/26/18 10:12 PM, Stefano Stabellini wrote:
> On Fri, 26 Oct 2018, Julien Grall wrote:
>> Hi Stefano,
>>
>> On 10/23/18 3:02 AM, Stefano Stabellini wrote:
>>> Make sure to only look for multiboot compatible nodes only under
>>> /chosen, not under any other paths (depth <= 3).
>>>
>>> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
>>>
>>> ---
>>>
>>> Changes in v5:
>>> - add patch
>>> - add check on return value of fdt_get_path
>>> ---
>>>    xen/arch/arm/bootfdt.c | 13 ++++++++++---
>>>    1 file changed, 10 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
>>> index 8eba42c..a314aca 100644
>>> --- a/xen/arch/arm/bootfdt.c
>>> +++ b/xen/arch/arm/bootfdt.c
>>> @@ -173,7 +173,14 @@ static void __init process_multiboot_node(const void
>>> *fdt, int node,
>>>        bootmodule_kind kind;
>>>        paddr_t start, size;
>>>        const char *cmdline;
>>> -    int len;
>>> +    int len = sizeof("/chosen");
>>
>> NIT, I am not convince you win anything with that trick. strlen could be
>> optimized by the compiler (we use __builtin_strlen on Arm64).
> 
> I could use strlen if you prefer, but given that the string is known at
> compile time, it should hopefully be resolved to "8" at compile time
> using sizeof. What's wrong with it?

__builtin_strlen should get optimized at compile-time. Although, I don't 
seem to be the case when I tried. Not sure why.

Never mind then.

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] 61+ messages in thread

* Re: [PATCH v5 05/25] xen/arm: check for multiboot nodes only under /chosen
  2018-10-26 21:27       ` Julien Grall
@ 2018-10-26 21:32         ` Julien Grall
  2018-10-27  0:42           ` Stefano Stabellini
  0 siblings, 1 reply; 61+ messages in thread
From: Julien Grall @ 2018-10-26 21:32 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, Achin.Gupta, andrii_anisov, xen-devel



On 10/26/18 10:27 PM, Julien Grall wrote:
> Hi,
> 
> On 10/26/18 10:12 PM, Stefano Stabellini wrote:
>> On Fri, 26 Oct 2018, Julien Grall wrote:
>>> Hi Stefano,
>>>
>>> On 10/23/18 3:02 AM, Stefano Stabellini wrote:
>>>> Make sure to only look for multiboot compatible nodes only under
>>>> /chosen, not under any other paths (depth <= 3).
>>>>
>>>> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
>>>>
>>>> ---
>>>>
>>>> Changes in v5:
>>>> - add patch
>>>> - add check on return value of fdt_get_path
>>>> ---
>>>>    xen/arch/arm/bootfdt.c | 13 ++++++++++---
>>>>    1 file changed, 10 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
>>>> index 8eba42c..a314aca 100644
>>>> --- a/xen/arch/arm/bootfdt.c
>>>> +++ b/xen/arch/arm/bootfdt.c
>>>> @@ -173,7 +173,14 @@ static void __init process_multiboot_node(const 
>>>> void
>>>> *fdt, int node,
>>>>        bootmodule_kind kind;
>>>>        paddr_t start, size;
>>>>        const char *cmdline;
>>>> -    int len;
>>>> +    int len = sizeof("/chosen");
>>>
>>> NIT, I am not convince you win anything with that trick. strlen could be
>>> optimized by the compiler (we use __builtin_strlen on Arm64).
>>
>> I could use strlen if you prefer, but given that the string is known at
>> compile time, it should hopefully be resolved to "8" at compile time
>> using sizeof. What's wrong with it?
> 
> __builtin_strlen should get optimized at compile-time. Although, I don't 
> seem to be the case when I tried. Not sure why.
> 
> Never mind then.

Actually I just tried to use __builtin_stlren rather than strlen. And
GCC is computing the size at compiler time.

Somehow, I thought arm64 was using __builtin_strlen but it seems to 
implement there own. Most likely we would want to use __builtin_strlen 
wor constant string. But that's another story.

In that case, I would prefer if you use __builtin_strlen. This is easier 
to understand over sizeof.

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] 61+ messages in thread

* Re: [PATCH v5 06/25] xen/arm: introduce bootcmdlines
  2018-10-26 19:44   ` Julien Grall
@ 2018-10-27  0:34     ` Stefano Stabellini
  0 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-27  0:34 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Achin.Gupta, Stefano Stabellini,
	andrii_anisov, xen-devel

On Fri, 26 Oct 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 10/23/18 3:02 AM, Stefano Stabellini wrote:
> > @@ -314,12 +312,12 @@ 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++ )
> >       {
> > @@ -332,6 +330,11 @@ static void __init early_print_info(void)
> >                        i, s, e);
> >       }
> >       printk("\n");
> > +    for ( i = 0 ; i < cmds->nr_mods; i++ )
> > +        printk("CMDLINE[%d]:%s %s\n", i,
> > +               cmds->cmdline[i].dt_name,
> > +               &cmds->cmdline[i].cmdline[0]);
> > +    printk("\n");
> 
> I am ok to see to accept this patch with this new prints. However,
> I would like to see a fix for it as soon as possible because this will be a
> massive pain to debug if a user has a issue. Indeed we can't figure out
> whether from the log the associatation cmdline <-> modules.

> 
> > @@ -2109,6 +2107,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;
> > @@ -2154,6 +2153,7 @@ int __init construct_dom0(struct domain *d)
> >     #endif
> >   +    kinfo.cmdline = kernel != NULL ? &kernel->cmdline[0] : NULL;
> 
> That's not the most obvious line to read. I would either put the condition
> between parentheses or use drop != NULL.

OK, I'll add the parentheses


> The rest of the code looks good to me. With that change and the other comment
> addressed in a separate patch:
> 

Turns out that to do that with the current stored information we need
access to the unflattened device tree, which we don't have yet in
early_print_info. So, I added a new start address field to struct
bootcmdline to store the start address in memory of the corresponding
bootmodule. That way, we can easily match a bootmodule with the
corresponding cmdline.

I did that in a new patch.


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

Thanks!

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

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

* Re: [PATCH v5 05/25] xen/arm: check for multiboot nodes only under /chosen
  2018-10-26 21:32         ` Julien Grall
@ 2018-10-27  0:42           ` Stefano Stabellini
  2018-10-28 17:28             ` Julien Grall
  0 siblings, 1 reply; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-27  0:42 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Achin.Gupta, Stefano Stabellini,
	andrii_anisov, xen-devel

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

On Fri, 26 Oct 2018, Julien Grall wrote:
> On 10/26/18 10:27 PM, Julien Grall wrote:
> > Hi,
> > 
> > On 10/26/18 10:12 PM, Stefano Stabellini wrote:
> > > On Fri, 26 Oct 2018, Julien Grall wrote:
> > > > Hi Stefano,
> > > > 
> > > > On 10/23/18 3:02 AM, Stefano Stabellini wrote:
> > > > > Make sure to only look for multiboot compatible nodes only under
> > > > > /chosen, not under any other paths (depth <= 3).
> > > > > 
> > > > > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > > > > 
> > > > > ---
> > > > > 
> > > > > Changes in v5:
> > > > > - add patch
> > > > > - add check on return value of fdt_get_path
> > > > > ---
> > > > >    xen/arch/arm/bootfdt.c | 13 ++++++++++---
> > > > >    1 file changed, 10 insertions(+), 3 deletions(-)
> > > > > 
> > > > > diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
> > > > > index 8eba42c..a314aca 100644
> > > > > --- a/xen/arch/arm/bootfdt.c
> > > > > +++ b/xen/arch/arm/bootfdt.c
> > > > > @@ -173,7 +173,14 @@ static void __init process_multiboot_node(const
> > > > > void
> > > > > *fdt, int node,
> > > > >        bootmodule_kind kind;
> > > > >        paddr_t start, size;
> > > > >        const char *cmdline;
> > > > > -    int len;
> > > > > +    int len = sizeof("/chosen");
> > > > 
> > > > NIT, I am not convince you win anything with that trick. strlen could be
> > > > optimized by the compiler (we use __builtin_strlen on Arm64).
> > > 
> > > I could use strlen if you prefer, but given that the string is known at
> > > compile time, it should hopefully be resolved to "8" at compile time
> > > using sizeof. What's wrong with it?
> > 
> > __builtin_strlen should get optimized at compile-time. Although, I don't
> > seem to be the case when I tried. Not sure why.
> > 
> > Never mind then.
> 
> Actually I just tried to use __builtin_stlren rather than strlen. And
> GCC is computing the size at compiler time.
> 
> Somehow, I thought arm64 was using __builtin_strlen but it seems to implement
> there own. Most likely we would want to use __builtin_strlen wor constant
> string. But that's another story.
> 
> In that case, I would prefer if you use __builtin_strlen. This is easier to
> understand over sizeof.

sizeof should be easier than __builtin_strlen for most: sizeof is part
of the C language, and it is taught in C classes. I expect everybody
should know what it is. While __builtin_strlen is a compiler construct,
which is certainly not for beginners. I think it is strange you find it
easier, probably a side of effect of years of Xen/kernel programming :-)

I would rather keep it as is.

[-- 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] 61+ messages in thread

* Re: [PATCH v5 05/25] xen/arm: check for multiboot nodes only under /chosen
  2018-10-27  0:42           ` Stefano Stabellini
@ 2018-10-28 17:28             ` Julien Grall
  0 siblings, 0 replies; 61+ messages in thread
From: Julien Grall @ 2018-10-28 17:28 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, Achin.Gupta, andrii_anisov, xen-devel

Hi Stefano,

On 10/27/18 1:42 AM, Stefano Stabellini wrote:
> On Fri, 26 Oct 2018, Julien Grall wrote:
>> On 10/26/18 10:27 PM, Julien Grall wrote:
>>> Hi,
>>>
>>> On 10/26/18 10:12 PM, Stefano Stabellini wrote:
>>>> On Fri, 26 Oct 2018, Julien Grall wrote:
>>>>> Hi Stefano,
>>>>>
>>>>> On 10/23/18 3:02 AM, Stefano Stabellini wrote:
>>>>>> Make sure to only look for multiboot compatible nodes only under
>>>>>> /chosen, not under any other paths (depth <= 3).
>>>>>>
>>>>>> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
>>>>>>
>>>>>> ---
>>>>>>
>>>>>> Changes in v5:
>>>>>> - add patch
>>>>>> - add check on return value of fdt_get_path
>>>>>> ---
>>>>>>     xen/arch/arm/bootfdt.c | 13 ++++++++++---
>>>>>>     1 file changed, 10 insertions(+), 3 deletions(-)
>>>>>>
>>>>>> diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
>>>>>> index 8eba42c..a314aca 100644
>>>>>> --- a/xen/arch/arm/bootfdt.c
>>>>>> +++ b/xen/arch/arm/bootfdt.c
>>>>>> @@ -173,7 +173,14 @@ static void __init process_multiboot_node(const
>>>>>> void
>>>>>> *fdt, int node,
>>>>>>         bootmodule_kind kind;
>>>>>>         paddr_t start, size;
>>>>>>         const char *cmdline;
>>>>>> -    int len;
>>>>>> +    int len = sizeof("/chosen");
>>>>>
>>>>> NIT, I am not convince you win anything with that trick. strlen could be
>>>>> optimized by the compiler (we use __builtin_strlen on Arm64).
>>>>
>>>> I could use strlen if you prefer, but given that the string is known at
>>>> compile time, it should hopefully be resolved to "8" at compile time
>>>> using sizeof. What's wrong with it?
>>>
>>> __builtin_strlen should get optimized at compile-time. Although, I don't
>>> seem to be the case when I tried. Not sure why.
>>>
>>> Never mind then.
>>
>> Actually I just tried to use __builtin_stlren rather than strlen. And
>> GCC is computing the size at compiler time.
>>
>> Somehow, I thought arm64 was using __builtin_strlen but it seems to implement
>> there own. Most likely we would want to use __builtin_strlen wor constant
>> string. But that's another story.
>>
>> In that case, I would prefer if you use __builtin_strlen. This is easier to
>> understand over sizeof.
> 
> sizeof should be easier than __builtin_strlen for most: sizeof is part
> of the C language, and it is taught in C classes. I expect everybody
> should know what it is. While __builtin_strlen is a compiler construct,
> which is certainly not for beginners. I think it is strange you find it
> easier, probably a side of effect of years of Xen/kernel programming :-)

I think it is pretty much the invert :). When I see "strlen" in the name 
I can imagine what you are trying to achieve. I.e computing the length 
of the string. If it has __builtin, my,... in front it just tells you 
that it is a different implementation.

Sizeof takes a bit more time because you have to wonder why strlen is 
not "suitable" here.

To be honest, this is a micro-optimization. It is very likely not going 
to make Xen booting much faster as that function might just get called 
~30 times at most.

> 
> I would rather keep it as is.

Then please stay consistent. You hardcode the value in one place, and 
the other you use sizeof("/chosen"). Either way works for me.

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] 61+ messages in thread

* Re: [PATCH v5 21/25] xen: support console_switching between Dom0 and DomUs on ARM
  2018-10-26 14:29   ` Jan Beulich
@ 2018-10-29 19:56     ` Stefano Stabellini
  0 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-29 19:56 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Achin.Gupta, Ian Jackson,
	xen-devel, Julien Grall, Stefano Stabellini, andrii_anisov

On Fri, 26 Oct 2018, Jan Beulich wrote:
> >>> On 23.10.18 at 04:03, <sstabellini@kernel.org> wrote:
> > @@ -391,31 +394,79 @@ 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> changes input direction, rotating among Xen, Dom0,
> > + * and DomUs.
> 
> Proper attribute to be inserted here, as per my (late) v4 comment.

OK, I wrote:

 * CTRL-<switch_char> changes input direction, rotating among Xen, Dom0,
 * and the DomUs started from Xen at boot.

but I would be happy take suggestion for a simple single word attribute
to describe this kind of domains. Maybe "dom0less 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 to dom(N-1)
> > + */
> > +static unsigned int __read_mostly 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]);
> > +    if ( console_rx++ == max_init_domid + 1 )
> > +        console_rx = 0;
> > +
> > +    if ( console_rx == 0 )
> > +        printk("*** Serial input to Xen");
> 
> I think these two if()-s can and should be combined. Furthermore
> I think it would be worthwhile to defer the increment until ...

OK

 
> > +    else
> > +        printk("*** Serial input to DOM%d", console_rx - 1);
> 
> ... after this printk(), but (obviously) then inside the else block.

Yes, I can do that


> >      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 )
> > +    switch ( console_rx )
> > +    {
> > +    case 0:
> >          return handle_keypress(c, regs);
> > +    case 1:
> > +    {
> 
> Stray figure braces. Blank lines between case blocks please.

OK


> > +        /*
> > +         * Deliver input to the hardware domain 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 hardware domain: prevents receive path from
> > +         * getting stuck.
> > +         */
> > +        send_global_virq(VIRQ_CONSOLE);
> > +        break;
> > +    }
> > +#if 0
> 
> I suppose a later patch is meant to remove this again. But
> perhaps still a good idea to attach a brief comment, in case
> the series doesn't go in all in one go? This is assuming you
> did already consider (and discard for whatever reason) the
> option of adding this default case when the code can
> actually be used.

I'll add a comment

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

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

* Re: [PATCH v5 21/25] xen: support console_switching between Dom0 and DomUs on ARM
  2018-10-24 14:55   ` Oleksandr Andrushchenko
@ 2018-10-29 20:00     ` Stefano Stabellini
  2018-10-29 20:01       ` Julien Grall
  0 siblings, 1 reply; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-29 20:00 UTC (permalink / raw)
  To: Oleksandr Andrushchenko
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov,
	konrad.wilk, George.Dunlap, andrew.cooper3, Achin.Gupta,
	ian.jackson, xen-devel, julien.grall, tim, jbeulich, wei.liu2

On Wed, 24 Oct 2018, Oleksandr Andrushchenko wrote:
> On 10/23/2018 05:03 AM, 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.
> > 
> > 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 v5:
> > - move patch earlier and disable code that calls vpl011_rx_char_xen (not
> >    defined yet)
> > - improve comments
> > - replace ifs with a switch
> > - code style
> > 
> > Changes in v4:
> > - handle console_rx == 0 in console_input_domain
> > - use rcu_lock_by_domain instead of get_domain_by_id
> > - handle the case where the returned domain is NULL
> > - send_global_virq(VIRQ_CONSOLE) only when chars are for Dom0
> > - make console_rx unsigned int
> > - fix comment
> > - code readability improvement
> > - fix opt_conswitch[1] == 'x' case
> > - move console_input_domain to next patch
> > 
> > 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 | 79
> > ++++++++++++++++++++++++++++++++++++++--------
> >   1 file changed, 65 insertions(+), 14 deletions(-)
> > 
> > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> > index 3b75f7a..75172e7 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. */
> > @@ -391,31 +394,79 @@ 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> changes input direction, rotating among 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 to dom(N-1)
> > + */
> > +static unsigned int __read_mostly 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]);
> > +    if ( console_rx++ == max_init_domid + 1 )
> > +        console_rx = 0;
> > +
> > +    if ( console_rx == 0 )
> > +        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 )
> > +    switch ( console_rx )
> > +    {
> > +    case 0:
> >           return handle_keypress(c, regs);
> > +    case 1:
> > +    {
> > +        /*
> > +         * Deliver input to the hardware domain 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 hardware domain: prevents receive path from
> > +         * getting stuck.
> > +         */
> > +        send_global_virq(VIRQ_CONSOLE);
> > +        break;
> > +    }
> + * console_rx=0 => input to xen
> + * console_rx=1 => input to dom0
> + * console_rx=N => input to dom(N-1)
> So, why do you only handle case 0/1?
> > +#if 0
> Do you need this #if 0?

To make the series fully bisectable: the code below requires
functionalities introduced by later patches.


> > +    default:
> > +    {
> > +        struct domain *d = rcu_lock_domain_by_any_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 != NULL &&
> > +             !d->arch.vpl011.backend_in_domain &&
> > +             d->arch.vpl011.backend.xen != NULL )
> > +            vpl011_rx_char_xen(d, c);
> > +        else
> > +            printk("Cannot send chars to Dom%d: no UART available\n",
> > +                   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;
> > -    /* Always notify the guest: prevents receive path from getting stuck.
> > */
> > -    send_global_virq(VIRQ_CONSOLE);
> > +        if ( d != NULL )
> > +            rcu_unlock_domain(d);
> > +    }
> > +#endif
> > +    }
> >     #ifdef CONFIG_X86
> >       if ( pv_shim && pv_console )
> > @@ -943,7 +994,7 @@ void __init console_endboot(void)
> >        * a useful 'how to switch' message.
> >        */
> >       if ( opt_conswitch[1] == 'x' )
> > -        xen_rx = !xen_rx;
> > +        console_rx = max_init_domid + 1;
> >         register_keyhandler('w', dump_console_ring_key,
> >                           "synchronously dump console ring buffer (dmesg)",
> > 0);
> 

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

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

* Re: [PATCH v5 21/25] xen: support console_switching between Dom0 and DomUs on ARM
  2018-10-29 20:00     ` Stefano Stabellini
@ 2018-10-29 20:01       ` Julien Grall
  0 siblings, 0 replies; 61+ messages in thread
From: Julien Grall @ 2018-10-29 20:01 UTC (permalink / raw)
  To: Stefano Stabellini, Oleksandr Andrushchenko
  Cc: Stefano Stabellini, andrii_anisov, konrad.wilk, George.Dunlap,
	andrew.cooper3, Achin.Gupta, ian.jackson, xen-devel, tim,
	jbeulich, wei.liu2



On 10/29/18 8:00 PM, Stefano Stabellini wrote:
> On Wed, 24 Oct 2018, Oleksandr Andrushchenko wrote:
>> On 10/23/2018 05:03 AM, Stefano Stabellini wrote:
>> + * console_rx=0 => input to xen
>> + * console_rx=1 => input to dom0
>> + * console_rx=N => input to dom(N-1)
>> So, why do you only handle case 0/1?
>>> +#if 0
>> Do you need this #if 0?
> 
> To make the series fully bisectable: the code below requires
> functionalities introduced by later patches.

That's a hint to update the commit message ;).

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] 61+ messages in thread

* Re: [PATCH v5 22/25] xen/arm: Allow vpl011 to be used by DomU
  2018-10-24 17:14   ` Oleksandr Tyshchenko
@ 2018-10-29 20:03     ` Stefano Stabellini
  2018-10-30 11:04       ` Oleksandr Tyshchenko
  0 siblings, 1 reply; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-29 20:03 UTC (permalink / raw)
  To: Oleksandr Tyshchenko
  Cc: stefanos, Stefano Stabellini, Andrii Anisov, Achin.Gupta,
	Xen Devel, Julien Grall

On Wed, 24 Oct 2018, Oleksandr Tyshchenko wrote:
> Hi, Stefano
> 
> On Tue, Oct 23, 2018 at 5:04 AM Stefano Stabellini
> <sstabellini@kernel.org> 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>
> > Acked-by: Julien Grall <julien.grall@arm.com>
> > ---
> > Changes in v5:
> > - renable call to vpl011_rx_char_xen from console.c
> >
> > Changes in v4:
> > - code style
> >
> > 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        | 200 +++++++++++++++++++++++++++++++++++++------
> >  xen/drivers/char/console.c   |   2 +-
> >  xen/include/asm-arm/vpl011.h |   8 ++
> >  4 files changed, 193 insertions(+), 26 deletions(-)
> >
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 6026b77..9ffd919 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -2629,7 +2629,14 @@ static int __init construct_domU(struct domain *d,
> >      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 68452a8..131507e 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->backend.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->backend.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;
> Do we need barriers here and after writing the ring?

We do not need barriers because both frontend and backend are in Xen for
this use-case: both in_cons and in_prod are modified by Xen with the
VPL011_LOCK held. There are no simultaneous reads/writes and the lock
includes a barrier.

 
> > +    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->backend.dom.ring_buf )
> >          return -EINVAL;
> >
> > -    /* Map the guest PFN to Xen address space. */
> > -    rc =  prepare_ring_for_helper(d,
> > -                                  gfn_x(info->gfn),
> > -                                  &vpl011->backend.dom.ring_page,
> > -                                  &vpl011->backend.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->backend.dom.ring_page,
> > +                                      &vpl011->backend.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->backend.xen = xzalloc(struct vpl011_xen_backend);
> > +        if ( vpl011->backend.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,8 +647,11 @@ out2:
> >      vgic_free_virq(d, GUEST_VPL011_SPI);
> >
> >  out1:
> > -    destroy_ring_for_helper(&vpl011->backend.dom.ring_buf,
> > -                                       vpl011->backend.dom.ring_page);
> > +    if ( vpl011->backend_in_domain )
> > +        destroy_ring_for_helper(&vpl011->backend.dom.ring_buf,
> > +                                vpl011->backend.dom.ring_page);
> > +    else
> > +        xfree(vpl011->backend.xen);
> >
> >  out:
> >      return rc;
> > @@ -514,12 +661,17 @@ void domain_vpl011_deinit(struct domain *d)
> >  {
> >      struct vpl011 *vpl011 = &d->arch.vpl011;
> >
> > -    if ( !vpl011->backend.dom.ring_buf )
> > -        return;
> > +    if ( vpl011->backend_in_domain )
> > +    {
> > +        if ( !vpl011->backend.dom.ring_buf )
> > +            return;
> >
> > -    free_xen_event_channel(d, vpl011->evtchn);
> > -    destroy_ring_for_helper(&vpl011->backend.dom.ring_buf,
> > -                                       vpl011->backend.dom.ring_page);
> > +        free_xen_event_channel(d, vpl011->evtchn);
> > +        destroy_ring_for_helper(&vpl011->backend.dom.ring_buf,
> > +                                vpl011->backend.dom.ring_page);
> > +    }
> > +    else
> > +        xfree(vpl011->backend.xen);
> >  }
> >
> >  /*
> > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> > index 75172e7..990c51c 100644
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -444,7 +444,7 @@ static void __serial_rx(char c, struct cpu_user_regs *regs)
> >          send_global_virq(VIRQ_CONSOLE);
> >          break;
> >      }
> > -#if 0
> > +#ifdef CONFIG_SBSA_VUART_CONSOLE
> >      default:
> >      {
> >          struct domain *d = rcu_lock_domain_by_any_id(console_rx - 1);
> > diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
> > index 42d7a24..5eb6d25 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;
> >      } backend;
> >      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)

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

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

* Re: [PATCH v5 23/25] xen/vpl011: buffer out chars when the backend is xen
  2018-10-24 14:46   ` Oleksandr Andrushchenko
@ 2018-10-29 20:09     ` Stefano Stabellini
  0 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-10-29 20:09 UTC (permalink / raw)
  To: Oleksandr Andrushchenko
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov,
	konrad.wilk, George.Dunlap, andrew.cooper3, Achin.Gupta,
	ian.jackson, xen-devel, julien.grall, tim, jbeulich, wei.liu2

On Wed, 24 Oct 2018, Oleksandr Andrushchenko wrote:
> On 10/23/2018 05:03 AM, 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, choose the same size
> > as VUART_BUT_SIZE used in vuart.c.
> s/VUART_BUT_SIZE/VUART_BUF_SIZE

Ops, I'll fix


> > 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
> > ---
> > XXX: merge this patch with "xen/arm: Allow vpl011 to be used by DomU" on
> >       commit
> > 
> > Changes in v5:
> > - use rcu_lock in console_input_domain
> > - rcu_unlock at the end of vpl011_write_data_xen
> > - add a comment on top of console_input_domain as a reminder that the
> >    caller needs to rcu_unlock
> > 
> > Changes in v4:
> > - make SBSA_UART_OUT_BUF_SIZE the same size of VUART_BUT_SIZE
> > - rearrange the code to be clearer input and != input cases
> > - code style
> > - add \n when printing the out buffer because is full
> > - don't print prefix for input domain
> > ---
> >   xen/arch/arm/vpl011.c        | 36 +++++++++++++++++++++++++++++++++---
> >   xen/drivers/char/console.c   |  8 ++++++++
> >   xen/include/asm-arm/vpl011.h |  4 ++++
> >   xen/include/xen/console.h    |  2 ++
> >   4 files changed, 47 insertions(+), 3 deletions(-)
> > 
> > diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> > index 131507e..f7db18b 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,18 +86,47 @@ 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->backend.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 )
> > +    {
> > +        if ( intf->out_prod == 1 )
> > +        {
> > +            printk("%c", data);
> > +            intf->out_prod = 0;
> > +        }
> > +        else
> > +        {
> > +            if ( data != '\n' )
> > +                intf->out[intf->out_prod++] = '\n';
> > +            intf->out[intf->out_prod++] = '\0';
> > +            printk("%s", 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;
> > +        }
> > +    }
> >         vpl011->uartris |= TXI;
> >       vpl011->uartfr &= ~TXFE;
> >       vpl011_update_interrupt_status(d);
> >         VPL011_UNLOCK(d, flags);
> > +    rcu_unlock_domain(input);
> input can be NULL. Although it won't hurt with the existing
> code base things could change any time soon...

No, you are right, I'll add an explicit check for it at the beginning of
the function.


> >   }
> >     /*
> > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> > index 990c51c..eb1cc1b 100644
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -406,6 +406,14 @@ static void dump_console_ring_key(unsigned char key)
> >    */
> >   static unsigned int __read_mostly console_rx = 0;
> >   +/* Make sure to rcu_unlock_domain after use */
> > +struct domain *console_input_domain(void)
> > +{
> > +    if ( console_rx == 0 )
> > +            return NULL;
> > +    return rcu_lock_domain_by_id(console_rx - 1);
> > +}
> > +
> >   static void switch_serial_input(void)
> >   {
> >       if ( console_rx++ == max_init_domid + 1 )
> > diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
> > index 5eb6d25..ab6fd79 100644
> > --- a/xen/include/asm-arm/vpl011.h
> > +++ b/xen/include/asm-arm/vpl011.h
> > @@ -30,9 +30,13 @@
> >   #define VPL011_UNLOCK(d,flags)
> > spin_unlock_irqrestore(&(d)->arch.vpl011.lock, flags)
> >     #define SBSA_UART_FIFO_SIZE 32
> > +/* Same size as VUART_BUT_SIZE, used in vuart.c */
> > +#define SBSA_UART_OUT_BUF_SIZE 128
> >   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 {
> > diff --git a/xen/include/xen/console.h b/xen/include/xen/console.h
> > index 70c9911..c5a85c8 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] 61+ messages in thread

* Re: [PATCH v5 22/25] xen/arm: Allow vpl011 to be used by DomU
  2018-10-29 20:03     ` Stefano Stabellini
@ 2018-10-30 11:04       ` Oleksandr Tyshchenko
  0 siblings, 0 replies; 61+ messages in thread
From: Oleksandr Tyshchenko @ 2018-10-30 11:04 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: stefanos, Julien Grall, Andrii Anisov, Achin.Gupta, Xen Devel

On Mon, Oct 29, 2018 at 10:03 PM Stefano Stabellini
<sstabellini@kernel.org> wrote:
>
> On Wed, 24 Oct 2018, Oleksandr Tyshchenko wrote:
> > Hi, Stefano
> >
> > On Tue, Oct 23, 2018 at 5:04 AM Stefano Stabellini
> > <sstabellini@kernel.org> 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>
> > > Acked-by: Julien Grall <julien.grall@arm.com>
> > > ---
> > > Changes in v5:
> > > - renable call to vpl011_rx_char_xen from console.c
> > >
> > > Changes in v4:
> > > - code style
> > >
> > > 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        | 200 +++++++++++++++++++++++++++++++++++++------
> > >  xen/drivers/char/console.c   |   2 +-
> > >  xen/include/asm-arm/vpl011.h |   8 ++
> > >  4 files changed, 193 insertions(+), 26 deletions(-)
> > >
> > > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > > index 6026b77..9ffd919 100644
> > > --- a/xen/arch/arm/domain_build.c
> > > +++ b/xen/arch/arm/domain_build.c
> > > @@ -2629,7 +2629,14 @@ static int __init construct_domU(struct domain *d,
> > >      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 68452a8..131507e 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->backend.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->backend.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;
> > Do we need barriers here and after writing the ring?
>
> We do not need barriers because both frontend and backend are in Xen for
> this use-case: both in_cons and in_prod are modified by Xen with the
> VPL011_LOCK held. There are no simultaneous reads/writes and the lock
> includes a barrier.
I got it. Thank you for the explanation.

>
>
> > > +    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->backend.dom.ring_buf )
> > >          return -EINVAL;
> > >
> > > -    /* Map the guest PFN to Xen address space. */
> > > -    rc =  prepare_ring_for_helper(d,
> > > -                                  gfn_x(info->gfn),
> > > -                                  &vpl011->backend.dom.ring_page,
> > > -                                  &vpl011->backend.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->backend.dom.ring_page,
> > > +                                      &vpl011->backend.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->backend.xen = xzalloc(struct vpl011_xen_backend);
> > > +        if ( vpl011->backend.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,8 +647,11 @@ out2:
> > >      vgic_free_virq(d, GUEST_VPL011_SPI);
> > >
> > >  out1:
> > > -    destroy_ring_for_helper(&vpl011->backend.dom.ring_buf,
> > > -                                       vpl011->backend.dom.ring_page);
> > > +    if ( vpl011->backend_in_domain )
> > > +        destroy_ring_for_helper(&vpl011->backend.dom.ring_buf,
> > > +                                vpl011->backend.dom.ring_page);
> > > +    else
> > > +        xfree(vpl011->backend.xen);
> > >
> > >  out:
> > >      return rc;
> > > @@ -514,12 +661,17 @@ void domain_vpl011_deinit(struct domain *d)
> > >  {
> > >      struct vpl011 *vpl011 = &d->arch.vpl011;
> > >
> > > -    if ( !vpl011->backend.dom.ring_buf )
> > > -        return;
> > > +    if ( vpl011->backend_in_domain )
> > > +    {
> > > +        if ( !vpl011->backend.dom.ring_buf )
> > > +            return;
> > >
> > > -    free_xen_event_channel(d, vpl011->evtchn);
> > > -    destroy_ring_for_helper(&vpl011->backend.dom.ring_buf,
> > > -                                       vpl011->backend.dom.ring_page);
> > > +        free_xen_event_channel(d, vpl011->evtchn);
> > > +        destroy_ring_for_helper(&vpl011->backend.dom.ring_buf,
> > > +                                vpl011->backend.dom.ring_page);
> > > +    }
> > > +    else
> > > +        xfree(vpl011->backend.xen);
> > >  }
> > >
> > >  /*
> > > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> > > index 75172e7..990c51c 100644
> > > --- a/xen/drivers/char/console.c
> > > +++ b/xen/drivers/char/console.c
> > > @@ -444,7 +444,7 @@ static void __serial_rx(char c, struct cpu_user_regs *regs)
> > >          send_global_virq(VIRQ_CONSOLE);
> > >          break;
> > >      }
> > > -#if 0
> > > +#ifdef CONFIG_SBSA_VUART_CONSOLE
> > >      default:
> > >      {
> > >          struct domain *d = rcu_lock_domain_by_any_id(console_rx - 1);
> > > diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
> > > index 42d7a24..5eb6d25 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;
> > >      } backend;
> > >      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)



-- 
Regards,

Oleksandr Tyshchenko

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

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

* Re: [PATCH v5 07/25] xen/arm: don't add duplicate boot modules, introduce domU flag
  2018-10-23  2:02 ` [PATCH v5 07/25] xen/arm: don't add duplicate boot modules, introduce domU flag Stefano Stabellini
@ 2018-10-30 11:50   ` Julien Grall
  2018-11-02 20:15     ` Stefano Stabellini
  0 siblings, 1 reply; 61+ messages in thread
From: Julien Grall @ 2018-10-30 11:50 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, Achin.Gupta, andrii_anisov, xen-devel

Hi Stefano,

On 23/10/2018 03:02, Stefano Stabellini wrote:
> Don't add duplicate boot modules (same kind and same start address),
> they are freed later, we don't want to introduce double-free errors.
> 
> Introduce a domU flag in struct bootmodule and struct bootcmdline. Set
> it for kernels and ramdisks of "xen,domain" nodes to avoid getting
> confused in kernel_probe, where we try to guess which is the dom0 kernel
> and initrd to be compatible with all versions of the multiboot spec.
> 
> boot_module_find_by_kind and boot_cmdline_find_by_kind automatically
> check for !domU entries (they are only used for non-domU modules).
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> 
> ---
> Changes in v5:
> - improve commit message
> - add in-code comments
> 
> Changes in v4:
> - use unsigned int
> - better commit message
> - introduce domU flag and usage
> 
> Changes in v2:
> - new patch
> ---
>   xen/arch/arm/bootfdt.c      | 11 +++++++----
>   xen/arch/arm/setup.c        | 30 +++++++++++++++++++++++++-----
>   xen/include/asm-arm/setup.h | 12 ++++++++++--
>   3 files changed, 42 insertions(+), 11 deletions(-)
> 
> diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
> index cb6f77d..c325b6e 100644
> --- a/xen/arch/arm/bootfdt.c
> +++ b/xen/arch/arm/bootfdt.c
> @@ -175,6 +175,7 @@ static void __init process_multiboot_node(const void *fdt, int node,
>       int len = sizeof("/chosen");
>       char path[8]; /* sizeof "/chosen" */
>       int parent_node, ret;
> +    bool domU;
>   
>       parent_node = fdt_parent_offset(fdt, node);
>       ASSERT(parent_node >= 0);
> @@ -229,12 +230,14 @@ static void __init process_multiboot_node(const void *fdt, int node,
>               kind = BOOTMOD_XSM;
>       }
>   
> -    add_boot_module(kind, start, size);
> +    domU = fdt_node_check_compatible(fdt, parent_node, "xen,domain") == 0;
> +    add_boot_module(kind, start, size, domU);
>   
>       prop = fdt_get_property(fdt, node, "bootargs", &len);
>       if ( !prop )
>           return;
> -    add_boot_cmdline(fdt_get_name(fdt, parent_node, &len), prop->data, kind);
> +    add_boot_cmdline(fdt_get_name(fdt, parent_node, &len), prop->data,
> +                     kind, domU);
>   }
>   
>   static void __init process_chosen_node(const void *fdt, int node,
> @@ -280,7 +283,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);
> +    add_boot_module(BOOTMOD_RAMDISK, start, end-start, false);
>   }
>   
>   static int __init early_scan_node(const void *fdt,
> @@ -351,7 +354,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));
> +    add_boot_module(BOOTMOD_FDT, paddr, fdt_totalsize(fdt), false);
>   
>       device_tree_for_each_node((void *)fdt, early_scan_node, NULL);
>       early_print_info();
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index 2098591..72b12f9 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -201,10 +201,12 @@ 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)
> +                                          paddr_t start, paddr_t size,
> +                                          bool domU)
>   {
>       struct bootmodules *mods = &bootinfo.modules;
>       struct bootmodule *mod;
> +    unsigned int i;
>   
>       if ( mods->nr_mods == MAX_MODULES )
>       {
> @@ -212,15 +214,29 @@ 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 )
> +        {
> +            if ( !domU )
> +                mod->domU = false;
> +            return mod;
> +        }
> +    }
>   
>       mod = &mods->module[mods->nr_mods++];
>       mod->kind = kind;
>       mod->start = start;
>       mod->size = size;
> +    mod->domU = domU;
>   
>       return mod;
>   }
>   
> +/*
> + * This function is only used to find dom0 modules, so check for !mod->domU

This comment is misleading. The function is used not only to find Dom0 Modules 
but also XSM & co.

How about:

"boot_module_find_by_kind can only be used to return Xen modules (e.g XSM, DTB) 
or Dom0 modules. This is not suitable for looking up for guest modules."

> + */
>   struct bootmodule * __init boot_module_find_by_kind(bootmodule_kind kind)
>   {
>       struct bootmodules *mods = &bootinfo.modules;
> @@ -229,14 +245,14 @@ struct bootmodule * __init boot_module_find_by_kind(bootmodule_kind kind)
>       for (i = 0 ; i < mods->nr_mods ; i++ )
>       {
>           mod = &mods->module[i];
> -        if ( mod->kind == kind )
> +        if ( mod->kind == kind && !mod->domU )
>               return mod;
>       }
>       return NULL;
>   }
>   
>   void __init add_boot_cmdline(const char *name, const char *cmdline,
> -                             bootmodule_kind kind)
> +                             bootmodule_kind kind, bool domU)
>   {
>       struct bootcmdlines *cmds = &bootinfo.cmdlines;
>       struct bootcmdline *cmd;
> @@ -249,6 +265,7 @@ void __init add_boot_cmdline(const char *name, const char *cmdline,
>   
>       cmd = &cmds->cmdline[cmds->nr_mods++];
>       cmd->kind = kind;
> +    cmd->domU = domU;
>   
>       ASSERT(strlen(name) <= DT_MAX_NAME);
>       safe_strcpy(cmd->dt_name, name);
> @@ -258,6 +275,9 @@ void __init add_boot_cmdline(const char *name, const char *cmdline,
>       safe_strcpy(cmd->cmdline, cmdline);
>   }
>   
> +/*
> + * This function is only used to find dom0 modules, so check for !mod->domU
> + */

Same here.

>   struct bootcmdline * __init boot_cmdline_find_by_kind(bootmodule_kind kind)
>   {
>       struct bootcmdlines *cmds = &bootinfo.cmdlines;
> @@ -267,7 +287,7 @@ struct bootcmdline * __init boot_cmdline_find_by_kind(bootmodule_kind kind)
>       for ( i = 0 ; i < cmds->nr_mods ; i++ )
>       {
>           cmd = &cmds->cmdline[i];
> -        if ( cmd->kind == kind )
> +        if ( cmd->kind == kind && !cmd->domU )
>               return cmd;
>       }
>       return NULL;
> @@ -761,7 +781,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));
> +                             (paddr_t)(uintptr_t)(_end - _start + 1), false);
>       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 7580007..3a30329 100644
> --- a/xen/include/asm-arm/setup.h
> +++ b/xen/include/asm-arm/setup.h
> @@ -30,9 +30,16 @@ struct meminfo {
>       struct membank bank[NR_MEM_BANKS];
>   };
>   
> +/*
> + * The domU flag is set for kernels and ramdisks of "xen,domain" nodes.
> + * The purpose of the domU flag is to avoid getting confused in
> + * kernel_probe, where we try to guess which is the dom0 kernel and
> + * initrd to be compatible with all versions of the multiboot spec.
> + */
>   #define BOOTMOD_MAX_CMDLINE 1024
>   struct bootmodule {
>       bootmodule_kind kind;
> +    bool domU;
>       paddr_t start;
>       paddr_t size;
>   };
> @@ -41,6 +48,7 @@ struct bootmodule {
>   #define DT_MAX_NAME 41
>   struct bootcmdline {
>       bootmodule_kind kind;
> +    bool domU;
>       char dt_name[DT_MAX_NAME];
>       char cmdline[BOOTMOD_MAX_CMDLINE];
>   };
> @@ -91,10 +99,10 @@ 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);
> +                                   paddr_t start, paddr_t size, bool domU);
>   struct bootmodule *boot_module_find_by_kind(bootmodule_kind kind);
>   void add_boot_cmdline(const char *name, const char *cmdline,
> -                      bootmodule_kind kind);
> +                      bootmodule_kind kind, bool domU);
>   struct bootcmdline *boot_cmdline_find_by_kind(bootmodule_kind kind);
>   const char * __init boot_module_kind_as_string(bootmodule_kind 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] 61+ messages in thread

* Re: [PATCH v5 08/25] xen/arm: probe domU kernels and initrds
  2018-10-23  2:02 ` [PATCH v5 08/25] xen/arm: probe domU kernels and initrds Stefano Stabellini
@ 2018-10-30 12:03   ` Julien Grall
  2018-11-02 20:41     ` Stefano Stabellini
  0 siblings, 1 reply; 61+ messages in thread
From: Julien Grall @ 2018-10-30 12:03 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, Achin.Gupta, andrii_anisov, xen-devel

Hi Stefano,

On 23/10/2018 03:02, Stefano Stabellini wrote:
> 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.
> 
> Set command line for dom0 too for consistency.

I was expecting you to remove the assignment in construct_dom0 to avoid the 
duplication.

[...]

> diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
> index da8410e..d56f776 100644
> --- a/xen/arch/arm/kernel.c
> +++ b/xen/arch/arm/kernel.c
> @@ -421,22 +421,72 @@ 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,
> +                        const struct dt_device_node *domain)
>   {
> -    struct bootmodule *mod = boot_module_find_by_kind(BOOTMOD_KERNEL);
> +    struct bootmodule *mod = NULL;
> +    struct bootcmdline *cmd = NULL;
> +    struct dt_device_node *node;
> +    u64 kernel_addr, initrd_addr, size;
>       int rc;
>   
> +    /* domain is NULL only for the hardware_domain */

NIT: No need to the _.

The rest of the code looks good to me.

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] 61+ messages in thread

* Re: [PATCH v5 11/25] xen/arm: introduce allocate_memory
  2018-10-23  2:02 ` [PATCH v5 11/25] xen/arm: introduce allocate_memory Stefano Stabellini
@ 2018-10-30 12:24   ` Julien Grall
  2018-11-02 22:20     ` Stefano Stabellini
  2018-10-30 20:56   ` Julien Grall
  1 sibling, 1 reply; 61+ messages in thread
From: Julien Grall @ 2018-10-30 12:24 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, Achin.Gupta, andrii_anisov, xen-devel

Hi,

On 23/10/2018 03:02, 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.
> 
> This is under #if 0 as not used for now.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> ---
> Changes in v5:
> - improve commit message
> - code style
> - remove unneeded local var
> - while loop in allocate_bank_memory to allocate memory so that it
>    doesn't have to be contiguos
> - combile while loops in allocate_memory
> 
> Changes in v4:
> - move earlier, add #if 0
> - introduce allocate_bank_memory, remove insert_bank
> - allocate_bank_memory allocate memory and inserts the bank, while
>    allocate_memory specifies where to do that
> 
> Changes in v3:
> - new patch
> ---
>   xen/arch/arm/domain_build.c | 99 +++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 99 insertions(+)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index c61a27f..146d81e 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -368,6 +368,105 @@ static void __init allocate_memory_11(struct domain *d,
>       }
>   }
>   
> +#if 0
> +static bool __init allocate_bank_memory(struct domain *d,
> +                                        struct kernel_info *kinfo,
> +                                        gfn_t sgfn,
> +                                        unsigned int order)

I don't think your implementation below is equivalent to the one I suggested 
earlier on ([1]). While you handled the contiguous problem, you didn't address 
the 2 others points:
        1) The memory specify by the user may not be in power of 2 pages. For
instance, a user can specify 40KB. With your algo, we will end to
allocate 32KB in the first bank and 8KB in the second bank. However what
we want is allocate 40KB in a single bank.
        2) You don't check whether the leftover memory is bigger than the size
of the second bank.

Because of 1), you can't reason in term of order here. You have to reason in 
bytes or number of pages.

> +{
> +    int res;
> +    struct page_info *pg;
> +    struct membank *bank;
> +    paddr_t size = pfn_to_paddr(1UL << order);
> +    gfn_t _sgfn = sgfn;
> +    gfn_t _egfn = gfn_add(sgfn, 1UL << order);
> +
> +    while ( gfn_x(_sgfn) < gfn_x(_egfn) )
> +    {
> +        pg = alloc_domheap_pages(d, order, 0);
> +        if ( pg != NULL )
> +        {
> +            res = guest_physmap_add_page(d, _sgfn, page_to_mfn(pg), order);
> +            if ( res )
> +            {
> +                dprintk(XENLOG_ERR, "Failed map pages to DOMU: %d", res);
> +                goto fail;
> +            }
> +            _sgfn = gfn_add(_sgfn, 1UL << order);
> +        }
> +        else
> +        {
> +            order--;

order may be equal to 0. So here you will underflow.

Overall, it would be best if you re-use the code I sent. While not tested, it 
addresses all the problems. Fixing the potential bug in that patch so be quite 
easily.

> +            if ( order == 0 )
> +            {
> +                dprintk(XENLOG_ERR, "Failed to allocated DOMU memory");
> +                goto fail;
> +            }
> +        }
> +    }
> +
> +    bank = &kinfo->mem.bank[kinfo->mem.nr_banks];
> +    bank->start = gfn_to_gaddr(sgfn);
> +    bank->size = size;
> +    kinfo->mem.nr_banks++;
> +    kinfo->unassigned_mem -= size;
> +
> +    return true;
> +
> +fail:
> +    /*
> +     * Fatal failure, don't attempt to free memory.
> +     */
> +    return false;
> +}
> +
> +static void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
> +{
> +    unsigned int order = get_allocation_size(kinfo->unassigned_mem);
> +    unsigned int order_req;
> +    unsigned 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 > get_order_from_bytes(GUEST_RAM0_SIZE) )
> +        order_req = get_order_from_bytes(GUEST_RAM0_SIZE);
> +    else
> +        order_req = order;
> +    if ( !allocate_bank_memory(d, kinfo, gaddr_to_gfn(GUEST_RAM0_BASE), order_req) )
> +        goto fail;
> +
> +    order -= order_req;
> +    if ( order > 0 &&
> +         !allocate_bank_memory(d, kinfo, gaddr_to_gfn(GUEST_RAM1_BASE), order) )
> +        goto fail;
> +
> +    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));
> +    }
> +
> +    return;
> +
> +fail:
> +    dprintk(XENLOG_ERR, "Failed to allocate requested domain memory."
> +            /* Don't want format this as PRIpaddr (16 digit hex) */
> +            " %ldKB unallocated. Fix the VMs configurations.\n",
> +            (unsigned long)kinfo->unassigned_mem >> 10);
> +    BUG();
> +}
> +#endif
> +
>   static int __init write_properties(struct domain *d, struct kernel_info *kinfo,
>                                      const struct dt_device_node *node)
>   {
> 

[1] https://pastebin.com/FQ9k9CbL

-- 
Julien Grall

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

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

* Re: [PATCH v5 12/25] xen/arm: refactor construct_dom0
  2018-10-23  2:02 ` [PATCH v5 12/25] xen/arm: refactor construct_dom0 Stefano Stabellini
@ 2018-10-30 16:32   ` Julien Grall
  0 siblings, 0 replies; 61+ messages in thread
From: Julien Grall @ 2018-10-30 16:32 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, Achin.Gupta, andrii_anisov, xen-devel

Hi Stefano,

On 23/10/2018 03:02, 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>

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

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] 61+ messages in thread

* Re: [PATCH v5 13/25] xen/arm: move unregister_init_virtual_region to init_done
  2018-10-23  2:02 ` [PATCH v5 13/25] xen/arm: move unregister_init_virtual_region to init_done Stefano Stabellini
@ 2018-10-30 16:33   ` Julien Grall
  0 siblings, 0 replies; 61+ messages in thread
From: Julien Grall @ 2018-10-30 16:33 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, Achin.Gupta, andrii_anisov, xen-devel

Hi Stefano,

On 23/10/2018 03:02, Stefano Stabellini wrote:
> Move unregister_init_virtual_region to init_done. Follow the same path
> as x86. It is also useful to move it later so that create_domUs can be
> called before that in following patches.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

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

Cheers,

> ---
>   xen/arch/arm/setup.c | 6 +++---
>   1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index 49f2fef..f3dc96c 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -66,6 +66,9 @@ integer_param("xenheap_megabytes", opt_xenheap_megabytes);
>   
>   static __used void init_done(void)
>   {
> +    /* Must be done past setting system_state. */
> +    unregister_init_virtual_region();
> +
>       free_init_memory();
>       startup_cpu_idle_loop();
>   }
> @@ -955,9 +958,6 @@ void __init start_xen(unsigned long boot_phys_offset,
>   
>       system_state = SYS_STATE_active;
>   
> -    /* Must be done past setting system_state. */
> -    unregister_init_virtual_region();
> -
>       domain_unpause_by_systemcontroller(dom0);
>   
>       /* Switch on to the dynamically allocated stack for the idle vcpu
> 

-- 
Julien Grall

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

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

* Re: [PATCH v5 14/25] xen/arm: introduce create_domUs
  2018-10-23  2:02 ` [PATCH v5 14/25] xen/arm: introduce create_domUs Stefano Stabellini
@ 2018-10-30 16:38   ` Julien Grall
  0 siblings, 0 replies; 61+ messages in thread
From: Julien Grall @ 2018-10-30 16:38 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, andrii_anisov, andrew.cooper3, Achin.Gupta,
	xen-devel, jbeulich

Hi Stefano,

On 23/10/2018 03:02, Stefano Stabellini wrote:
> Call a new function, "create_domUs", from setup_xen to start DomU VMs.
> 
> Introduce support for the "xen,domain" compatible node on device tree.
> Create new DomU VMs based on the information found on device tree under
> "xen,domain". Call 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>
> Acked-by: Jan Beulich <jbeulich@suse.com>

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

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] 61+ messages in thread

* Re: [PATCH v5 11/25] xen/arm: introduce allocate_memory
  2018-10-23  2:02 ` [PATCH v5 11/25] xen/arm: introduce allocate_memory Stefano Stabellini
  2018-10-30 12:24   ` Julien Grall
@ 2018-10-30 20:56   ` Julien Grall
  2018-11-02 21:15     ` Stefano Stabellini
  1 sibling, 1 reply; 61+ messages in thread
From: Julien Grall @ 2018-10-30 20:56 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, Achin.Gupta, andrii_anisov, xen-devel

Hi Stefano,

More comments on it :).

On 10/23/18 3:02 AM, 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.
> 
> This is under #if 0 as not used for now.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> ---
> Changes in v5:
> - improve commit message
> - code style
> - remove unneeded local var
> - while loop in allocate_bank_memory to allocate memory so that it
>    doesn't have to be contiguos
> - combile while loops in allocate_memory
> 
> Changes in v4:
> - move earlier, add #if 0
> - introduce allocate_bank_memory, remove insert_bank
> - allocate_bank_memory allocate memory and inserts the bank, while
>    allocate_memory specifies where to do that
> 
> Changes in v3:
> - new patch
> ---
>   xen/arch/arm/domain_build.c | 99 +++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 99 insertions(+)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index c61a27f..146d81e 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -368,6 +368,105 @@ static void __init allocate_memory_11(struct domain *d,
>       }
>   }
>   
> +#if 0
> +static bool __init allocate_bank_memory(struct domain *d,
> +                                        struct kernel_info *kinfo,
> +                                        gfn_t sgfn,
> +                                        unsigned int order)
> +{
> +    int res;
> +    struct page_info *pg;
> +    struct membank *bank;
> +    paddr_t size = pfn_to_paddr(1UL << order);
> +    gfn_t _sgfn = sgfn;
> +    gfn_t _egfn = gfn_add(sgfn, 1UL << order);
> +
> +    while ( gfn_x(_sgfn) < gfn_x(_egfn) )
> +    {
> +        pg = alloc_domheap_pages(d, order, 0);
> +        if ( pg != NULL )
> +        {
> +            res = guest_physmap_add_page(d, _sgfn, page_to_mfn(pg), order);
> +            if ( res )
> +            {
> +                dprintk(XENLOG_ERR, "Failed map pages to DOMU: %d", res);
> +                goto fail;
> +            }
> +            _sgfn = gfn_add(_sgfn, 1UL << order);
> +        }
> +        else
> +        {
> +            order--;
> +            if ( order == 0 )
> +            {
> +                dprintk(XENLOG_ERR, "Failed to allocated DOMU memory");
> +                goto fail;
> +            }
> +        }
> +    }
> +
> +    bank = &kinfo->mem.bank[kinfo->mem.nr_banks];
> +    bank->start = gfn_to_gaddr(sgfn);
> +    bank->size = size;
> +    kinfo->mem.nr_banks++;
> +    kinfo->unassigned_mem -= size;
> +
> +    return true;
> +
> +fail:
> +    /*
> +     * Fatal failure, don't attempt to free memory.
> +     */
> +    return false;
> +}
> +
> +static void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
> +{
> +    unsigned int order = get_allocation_size(kinfo->unassigned_mem);
> +    unsigned int order_req;
> +    unsigned 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);

While you are re-spinning this series. I would turn all the dprintk to 
printk as those messages are useful in non-debug build.

> +
> +    kinfo->mem.nr_banks = 0;
> +
> +    order = get_allocation_size(kinfo->unassigned_mem);
> +    if ( order > get_order_from_bytes(GUEST_RAM0_SIZE) )
> +        order_req = get_order_from_bytes(GUEST_RAM0_SIZE);
> +    else
> +        order_req = order;
> +    if ( !allocate_bank_memory(d, kinfo, gaddr_to_gfn(GUEST_RAM0_BASE), order_req) )
> +        goto fail;
> +
> +    order -= order_req;
> +    if ( order > 0 &&
> +         !allocate_bank_memory(d, kinfo, gaddr_to_gfn(GUEST_RAM1_BASE), order) )
> +        goto fail;
> +
> +    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));
> +    }
> +
> +    return;
> +
> +fail:
> +    dprintk(XENLOG_ERR, "Failed to allocate requested domain memory."
> +            /* Don't want format this as PRIpaddr (16 digit hex) */
> +            " %ldKB unallocated. Fix the VMs configurations.\n",
> +            (unsigned long)kinfo->unassigned_mem >> 10);

For this one, I would turned to a panic, avoid the BUG() below.

> +    BUG();
> +}
> +#endif
> +
>   static int __init write_properties(struct domain *d, struct kernel_info *kinfo,
>                                      const struct dt_device_node *node)
>   {
> 

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] 61+ messages in thread

* Re: [PATCH v5 15/25] xen/arm: implement construct_domU
  2018-10-23  2:02 ` [PATCH v5 15/25] xen/arm: implement construct_domU Stefano Stabellini
@ 2018-10-30 20:56   ` Julien Grall
  0 siblings, 0 replies; 61+ messages in thread
From: Julien Grall @ 2018-10-30 20:56 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, Achin.Gupta, andrii_anisov, xen-devel



On 10/23/18 3:02 AM, 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.
> 
> Remove #if 0 from allocate_memory as this patch will start using it.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

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

> 
> ---
> Changes in v5:
> - move changes to kernel_probe prototype to previous patch
> - improve commit message
> - remove superflous allocation of d->vcpu
> - use mem * SZ_1K
> 
> Changes in v4:
> - constify kernel_probe
> - change title
> - better error messages and printed info
> - 64bit memory
> 
> 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 | 35 ++++++++++++++++++++++++++++++++---
>   1 file changed, 32 insertions(+), 3 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 93e9510..4bb0db8 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -4,6 +4,7 @@
>   #include <xen/mm.h>
>   #include <xen/domain_page.h>
>   #include <xen/sched.h>
> +#include <xen/sizes.h>
>   #include <asm/irq.h>
>   #include <asm/regs.h>
>   #include <xen/errno.h>
> @@ -369,7 +370,6 @@ static void __init allocate_memory_11(struct domain *d,
>       }
>   }
>   
> -#if 0
>   static bool __init allocate_bank_memory(struct domain *d,
>                                           struct kernel_info *kinfo,
>                                           gfn_t sgfn,
> @@ -466,7 +466,6 @@ fail:
>               (unsigned long)kinfo->unassigned_mem >> 10);
>       BUG();
>   }
> -#endif
>   
>   static int __init write_properties(struct domain *d, struct kernel_info *kinfo,
>                                      const struct dt_device_node *node)
> @@ -2308,7 +2307,37 @@ static int __init construct_domain(struct domain *d, struct kernel_info *kinfo)
>   static int __init construct_domU(struct domain *d,
>                                    const struct dt_device_node *node)
>   {
> -    return -ENOSYS;
> +    struct kernel_info kinfo = {};
> +    int rc;
> +    u64 mem;
> +
> +    rc = dt_property_read_u64(node, "memory", &mem);
> +    if ( !rc )
> +    {
> +        printk("Error building DomU: cannot read \"memory\" property\n");
> +        return -EINVAL;
> +    }
> +    kinfo.unassigned_mem = (paddr_t)mem * SZ_1K;
> +
> +    printk("*** LOADING DOMU cpus=%u memory=%luKB ***\n", d->max_vcpus, mem);
> +
> +    if ( vcpu_create(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)
> 

-- 
Julien Grall

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

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

* Re: [PATCH v5 18/25] xen/arm: generate vpl011 node on device tree for domU
  2018-10-23  2:02 ` [PATCH v5 18/25] xen/arm: generate vpl011 node on device tree for domU Stefano Stabellini
@ 2018-10-30 20:58   ` Julien Grall
  0 siblings, 0 replies; 61+ messages in thread
From: Julien Grall @ 2018-10-30 20:58 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, Achin.Gupta, andrii_anisov, xen-devel

Hi Stefano,

On 10/23/18 3:02 AM, 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.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

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

Cheers,

> ---
> Changes in v5:
> - use dt_property_read_bool
> 
> Changes in v4:
> - move rename set_interrupt_ppi and making set_interrupt_ppi generic to
>    a separate patch
> - properly name the vpl011 device node name
> - code style
> - use #define for addrcells and sizecells
> 
> 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 | 60 +++++++++++++++++++++++++++++++++++++++++++++
>   xen/arch/arm/kernel.h       |  3 +++
>   2 files changed, 63 insertions(+)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index a7fd4f1..6026b77 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -1620,6 +1620,54 @@ 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 res;
> +    gic_interrupt_t intr;
> +    __be32 reg[GUEST_ROOT_ADDRESS_CELLS + GUEST_ROOT_SIZE_CELLS];
> +    __be32 *cells;
> +
> +    res = fdt_begin_node(fdt, "sbsa-uart@"__stringify(GUEST_PL011_BASE));
> +    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, GUEST_ROOT_ADDRESS_CELLS,
> +                       GUEST_ROOT_SIZE_CELLS, 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 future.
> @@ -1681,6 +1729,16 @@ static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
>       if ( ret )
>           goto err;
>   
> +    if ( kinfo->vpl011 )
> +    {
> +        ret = -EINVAL;
> +#ifdef CONFIG_SBSA_VUART_CONSOLE
> +        ret = make_vpl011_uart_node(d, kinfo->fdt);
> +#endif
> +        if ( ret )
> +            goto err;
> +    }
> +
>       ret = fdt_end_node(kinfo->fdt);
>       if ( ret < 0 )
>           goto err;
> @@ -2549,6 +2607,8 @@ static int __init construct_domU(struct domain *d,
>   
>       printk("*** LOADING DOMU cpus=%u memory=%luKB ***\n", d->max_vcpus, mem);
>   
> +    kinfo.vpl011 = dt_property_read_bool(node, "vpl011");
> +
>       if ( vcpu_create(d, 0, 0) == NULL )
>           return -ENOMEM;
>       d->max_pages = ~0U;
> diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
> index 4320f72..33f3e72 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 */
> 

-- 
Julien Grall

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

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

* Re: [PATCH v5 23/25] xen/vpl011: buffer out chars when the backend is xen
  2018-10-23  2:03 ` [PATCH v5 23/25] xen/vpl011: buffer out chars when the backend is xen Stefano Stabellini
  2018-10-24 14:46   ` Oleksandr Andrushchenko
@ 2018-10-31 13:27   ` Julien Grall
  1 sibling, 0 replies; 61+ messages in thread
From: Julien Grall @ 2018-10-31 13:27 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, andrii_anisov, konrad.wilk, George.Dunlap,
	andrew.cooper3, Achin.Gupta, ian.jackson, xen-devel, tim,
	jbeulich, wei.liu2

Hi Stefano,

On 10/23/18 3:03 AM, Stefano Stabellini wrote:
> diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
> index 5eb6d25..ab6fd79 100644
> --- a/xen/include/asm-arm/vpl011.h
> +++ b/xen/include/asm-arm/vpl011.h
> @@ -30,9 +30,13 @@
>   #define VPL011_UNLOCK(d,flags) spin_unlock_irqrestore(&(d)->arch.vpl011.lock, flags)
>   
>   #define SBSA_UART_FIFO_SIZE 32
> +/* Same size as VUART_BUT_SIZE, used in vuart.c */

s/BUT/BUF/

I will wait the next version to ack it (AFAICT Oleksandr requested some 
changes).

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] 61+ messages in thread

* Re: [PATCH v5 24/25] xen/arm: move kernel.h to asm-arm/
  2018-10-23  2:03 ` [PATCH v5 24/25] xen/arm: move kernel.h to asm-arm/ Stefano Stabellini
@ 2018-10-31 13:28   ` Julien Grall
  0 siblings, 0 replies; 61+ messages in thread
From: Julien Grall @ 2018-10-31 13:28 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, Achin.Gupta, andrii_anisov, xen-devel

Hi Stefano,

On 10/23/18 3:03 AM, Stefano Stabellini wrote:
> It will be #included by a file in a xen/arch/arm subdirectory.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>

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

Cheers,

> ---
>   xen/arch/arm/domain_build.c  |  2 +-
>   xen/arch/arm/kernel.c        |  3 +-
>   xen/arch/arm/kernel.h        | 86 --------------------------------------------
>   xen/include/asm-arm/kernel.h | 86 ++++++++++++++++++++++++++++++++++++++++++++
>   4 files changed, 88 insertions(+), 89 deletions(-)
>   delete mode 100644 xen/arch/arm/kernel.h
>   create mode 100644 xen/include/asm-arm/kernel.h
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 9ffd919..6f47832 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -17,6 +17,7 @@
>   #include <xen/warning.h>
>   #include <acpi/actables.h>
>   #include <asm/device.h>
> +#include <asm/kernel.h>
>   #include <asm/setup.h>
>   #include <asm/platform.h>
>   #include <asm/psci.h>
> @@ -25,7 +26,6 @@
>   
>   #include <xen/irq.h>
>   #include <xen/grant_table.h>
> -#include "kernel.h"
>   
>   static unsigned int __initdata opt_dom0_max_vcpus;
>   integer_param("dom0_max_vcpus", opt_dom0_max_vcpus);
> diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
> index d56f776..d10c03a 100644
> --- a/xen/arch/arm/kernel.c
> +++ b/xen/arch/arm/kernel.c
> @@ -16,8 +16,7 @@
>   #include <xen/vmap.h>
>   
>   #include <asm/guest_access.h>
> -
> -#include "kernel.h"
> +#include <asm/kernel.h>
>   
>   #define UIMAGE_MAGIC          0x27051956
>   #define UIMAGE_NMLEN          32
> diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
> deleted file mode 100644
> index 33f3e72..0000000
> --- a/xen/arch/arm/kernel.h
> +++ /dev/null
> @@ -1,86 +0,0 @@
> -/*
> - * Kernel image loading.
> - *
> - * Copyright (C) 2011 Citrix Systems, Inc.
> - */
> -#ifndef __ARCH_ARM_KERNEL_H__
> -#define __ARCH_ARM_KERNEL_H__
> -
> -#include <xen/device_tree.h>
> -#include <asm/setup.h>
> -
> -struct kernel_info {
> -#ifdef CONFIG_ARM_64
> -    enum domain_type type;
> -#endif
> -
> -    struct domain *d;
> -
> -    void *fdt; /* flat device tree */
> -    paddr_t unassigned_mem; /* RAM not (yet) assigned to a bank */
> -    struct meminfo mem;
> -
> -    /* kernel entry point */
> -    paddr_t entry;
> -
> -    /* grant table region */
> -    paddr_t gnttab_start;
> -    paddr_t gnttab_size;
> -
> -    /* boot blob load addresses */
> -    const struct bootmodule *kernel_bootmodule, *initrd_bootmodule;
> -    const char* cmdline;
> -    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 */
> -    union {
> -        struct {
> -            paddr_t kernel_addr;
> -            paddr_t len;
> -#ifdef CONFIG_ARM_64
> -            paddr_t text_offset; /* 64-bit Image only */
> -#endif
> -            paddr_t start; /* 32-bit zImage only */
> -        } zimage;
> -    };
> -};
> -
> -/*
> - * Probe the kernel to detemine its type and select a loader.
> - *
> - * Sets in info:
> - *  ->type
> - *  ->load hook, and sets loader specific variables ->zimage
> - */
> -int kernel_probe(struct kernel_info *info, const struct dt_device_node *domain);
> -
> -/*
> - * Loads the kernel into guest RAM.
> - *
> - * Expects to be set in info when called:
> - *  ->mem
> - *  ->fdt
> - *
> - * Sets in info:
> - *  ->entry
> - *  ->dtb_paddr
> - *  ->initrd_paddr
> - */
> -void kernel_load(struct kernel_info *info);
> -
> -#endif /* #ifdef __ARCH_ARM_KERNEL_H__ */
> -
> -/*
> - * Local variables:
> - * mode: C
> - * c-file-style: "BSD"
> - * c-basic-offset: 4
> - * indent-tabs-mode: nil
> - * End:
> - */
> diff --git a/xen/include/asm-arm/kernel.h b/xen/include/asm-arm/kernel.h
> new file mode 100644
> index 0000000..33f3e72
> --- /dev/null
> +++ b/xen/include/asm-arm/kernel.h
> @@ -0,0 +1,86 @@
> +/*
> + * Kernel image loading.
> + *
> + * Copyright (C) 2011 Citrix Systems, Inc.
> + */
> +#ifndef __ARCH_ARM_KERNEL_H__
> +#define __ARCH_ARM_KERNEL_H__
> +
> +#include <xen/device_tree.h>
> +#include <asm/setup.h>
> +
> +struct kernel_info {
> +#ifdef CONFIG_ARM_64
> +    enum domain_type type;
> +#endif
> +
> +    struct domain *d;
> +
> +    void *fdt; /* flat device tree */
> +    paddr_t unassigned_mem; /* RAM not (yet) assigned to a bank */
> +    struct meminfo mem;
> +
> +    /* kernel entry point */
> +    paddr_t entry;
> +
> +    /* grant table region */
> +    paddr_t gnttab_start;
> +    paddr_t gnttab_size;
> +
> +    /* boot blob load addresses */
> +    const struct bootmodule *kernel_bootmodule, *initrd_bootmodule;
> +    const char* cmdline;
> +    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 */
> +    union {
> +        struct {
> +            paddr_t kernel_addr;
> +            paddr_t len;
> +#ifdef CONFIG_ARM_64
> +            paddr_t text_offset; /* 64-bit Image only */
> +#endif
> +            paddr_t start; /* 32-bit zImage only */
> +        } zimage;
> +    };
> +};
> +
> +/*
> + * Probe the kernel to detemine its type and select a loader.
> + *
> + * Sets in info:
> + *  ->type
> + *  ->load hook, and sets loader specific variables ->zimage
> + */
> +int kernel_probe(struct kernel_info *info, const struct dt_device_node *domain);
> +
> +/*
> + * Loads the kernel into guest RAM.
> + *
> + * Expects to be set in info when called:
> + *  ->mem
> + *  ->fdt
> + *
> + * Sets in info:
> + *  ->entry
> + *  ->dtb_paddr
> + *  ->initrd_paddr
> + */
> +void kernel_load(struct kernel_info *info);
> +
> +#endif /* #ifdef __ARCH_ARM_KERNEL_H__ */
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> 

-- 
Julien Grall

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

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

* Re: [PATCH v5 25/25] xen/arm: split domain_build.c
  2018-10-23  2:03 ` [PATCH v5 25/25] xen/arm: split domain_build.c Stefano Stabellini
@ 2018-10-31 13:44   ` Julien Grall
  2018-11-01 20:37     ` Stefano Stabellini
  0 siblings, 1 reply; 61+ messages in thread
From: Julien Grall @ 2018-10-31 13:44 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, Achin.Gupta, andrii_anisov, xen-devel

On 10/23/18 3:03 AM, Stefano Stabellini wrote:
> domain_build.c is too large.
> 
> Move all the ACPI specific device tree generating functions from
> domain_build.c to acpi/domain_build.c.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> 
> ---
> 
> Changes in v4:
> - rename acpi_dt_build to domain_build.c
> - add copyright header
> - remove useless #include
> - remove acpi_dt_build.h, add domain_build.h
> ---
>   xen/arch/arm/acpi/Makefile         |   1 +
>   xen/arch/arm/acpi/domain_build.c   | 592 +++++++++++++++++++++++++++++++++++++
>   xen/arch/arm/domain_build.c        | 585 +-----------------------------------
>   xen/include/asm-arm/domain_build.h |  31 ++
>   4 files changed, 629 insertions(+), 580 deletions(-)
>   create mode 100644 xen/arch/arm/acpi/domain_build.c
>   create mode 100644 xen/include/asm-arm/domain_build.h
> 
> diff --git a/xen/arch/arm/acpi/Makefile b/xen/arch/arm/acpi/Makefile
> index 23963f8..94ae249 100644
> --- a/xen/arch/arm/acpi/Makefile
> +++ b/xen/arch/arm/acpi/Makefile
> @@ -1,2 +1,3 @@
>   obj-y += lib.o
> +obj-y += domain_build.o
>   obj-y += boot.init.o
> diff --git a/xen/arch/arm/acpi/domain_build.c b/xen/arch/arm/acpi/domain_build.c
> new file mode 100644
> index 0000000..44d3ad1
> --- /dev/null
> +++ b/xen/arch/arm/acpi/domain_build.c
> @@ -0,0 +1,592 @@
> +/*
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.

I was about to ack the patch when I noticed the license is not correct 
here. This is GPLv2+ license while Xen is GPLv2 only. I know that some 
of Xen code contain such license, but this is not the case for 
domain_build.c. As there as no copyright license, we should then assume 
GPLv2.

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] 61+ messages in thread

* Re: [PATCH v5 25/25] xen/arm: split domain_build.c
  2018-10-31 13:44   ` Julien Grall
@ 2018-11-01 20:37     ` Stefano Stabellini
  0 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-11-01 20:37 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Achin.Gupta, Stefano Stabellini,
	andrii_anisov, xen-devel

On Wed, 31 Oct 2018, Julien Grall wrote:
> On 10/23/18 3:03 AM, Stefano Stabellini wrote:
> > domain_build.c is too large.
> > 
> > Move all the ACPI specific device tree generating functions from
> > domain_build.c to acpi/domain_build.c.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > 
> > ---
> > 
> > Changes in v4:
> > - rename acpi_dt_build to domain_build.c
> > - add copyright header
> > - remove useless #include
> > - remove acpi_dt_build.h, add domain_build.h
> > ---
> >   xen/arch/arm/acpi/Makefile         |   1 +
> >   xen/arch/arm/acpi/domain_build.c   | 592
> > +++++++++++++++++++++++++++++++++++++
> >   xen/arch/arm/domain_build.c        | 585
> > +-----------------------------------
> >   xen/include/asm-arm/domain_build.h |  31 ++
> >   4 files changed, 629 insertions(+), 580 deletions(-)
> >   create mode 100644 xen/arch/arm/acpi/domain_build.c
> >   create mode 100644 xen/include/asm-arm/domain_build.h
> > 
> > diff --git a/xen/arch/arm/acpi/Makefile b/xen/arch/arm/acpi/Makefile
> > index 23963f8..94ae249 100644
> > --- a/xen/arch/arm/acpi/Makefile
> > +++ b/xen/arch/arm/acpi/Makefile
> > @@ -1,2 +1,3 @@
> >   obj-y += lib.o
> > +obj-y += domain_build.o
> >   obj-y += boot.init.o
> > diff --git a/xen/arch/arm/acpi/domain_build.c
> > b/xen/arch/arm/acpi/domain_build.c
> > new file mode 100644
> > index 0000000..44d3ad1
> > --- /dev/null
> > +++ b/xen/arch/arm/acpi/domain_build.c
> > @@ -0,0 +1,592 @@
> > +/*
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License as published by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> 
> I was about to ack the patch when I noticed the license is not correct here.
> This is GPLv2+ license while Xen is GPLv2 only. I know that some of Xen code
> contain such license, but this is not the case for domain_build.c. As there as
> no copyright license, we should then assume GPLv2.

Yes, I took the wrong template. I'll change it.

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

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

* Re: [PATCH v5 07/25] xen/arm: don't add duplicate boot modules, introduce domU flag
  2018-10-30 11:50   ` Julien Grall
@ 2018-11-02 20:15     ` Stefano Stabellini
  0 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-11-02 20:15 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Achin.Gupta, Stefano Stabellini,
	andrii_anisov, xen-devel

On Tue, 30 Oct 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 23/10/2018 03:02, Stefano Stabellini wrote:
> > Don't add duplicate boot modules (same kind and same start address),
> > they are freed later, we don't want to introduce double-free errors.
> > 
> > Introduce a domU flag in struct bootmodule and struct bootcmdline. Set
> > it for kernels and ramdisks of "xen,domain" nodes to avoid getting
> > confused in kernel_probe, where we try to guess which is the dom0 kernel
> > and initrd to be compatible with all versions of the multiboot spec.
> > 
> > boot_module_find_by_kind and boot_cmdline_find_by_kind automatically
> > check for !domU entries (they are only used for non-domU modules).
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > 
> > ---
> > Changes in v5:
> > - improve commit message
> > - add in-code comments
> > 
> > Changes in v4:
> > - use unsigned int
> > - better commit message
> > - introduce domU flag and usage
> > 
> > Changes in v2:
> > - new patch
> > ---
> >   xen/arch/arm/bootfdt.c      | 11 +++++++----
> >   xen/arch/arm/setup.c        | 30 +++++++++++++++++++++++++-----
> >   xen/include/asm-arm/setup.h | 12 ++++++++++--
> >   3 files changed, 42 insertions(+), 11 deletions(-)
> > 
> > diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
> > index cb6f77d..c325b6e 100644
> > --- a/xen/arch/arm/bootfdt.c
> > +++ b/xen/arch/arm/bootfdt.c
> > @@ -175,6 +175,7 @@ static void __init process_multiboot_node(const void
> > *fdt, int node,
> >       int len = sizeof("/chosen");
> >       char path[8]; /* sizeof "/chosen" */
> >       int parent_node, ret;
> > +    bool domU;
> >         parent_node = fdt_parent_offset(fdt, node);
> >       ASSERT(parent_node >= 0);
> > @@ -229,12 +230,14 @@ static void __init process_multiboot_node(const void
> > *fdt, int node,
> >               kind = BOOTMOD_XSM;
> >       }
> >   -    add_boot_module(kind, start, size);
> > +    domU = fdt_node_check_compatible(fdt, parent_node, "xen,domain") == 0;
> > +    add_boot_module(kind, start, size, domU);
> >         prop = fdt_get_property(fdt, node, "bootargs", &len);
> >       if ( !prop )
> >           return;
> > -    add_boot_cmdline(fdt_get_name(fdt, parent_node, &len), prop->data,
> > kind);
> > +    add_boot_cmdline(fdt_get_name(fdt, parent_node, &len), prop->data,
> > +                     kind, domU);
> >   }
> >     static void __init process_chosen_node(const void *fdt, int node,
> > @@ -280,7 +283,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);
> > +    add_boot_module(BOOTMOD_RAMDISK, start, end-start, false);
> >   }
> >     static int __init early_scan_node(const void *fdt,
> > @@ -351,7 +354,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));
> > +    add_boot_module(BOOTMOD_FDT, paddr, fdt_totalsize(fdt), false);
> >         device_tree_for_each_node((void *)fdt, early_scan_node, NULL);
> >       early_print_info();
> > diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> > index 2098591..72b12f9 100644
> > --- a/xen/arch/arm/setup.c
> > +++ b/xen/arch/arm/setup.c
> > @@ -201,10 +201,12 @@ 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)
> > +                                          paddr_t start, paddr_t size,
> > +                                          bool domU)
> >   {
> >       struct bootmodules *mods = &bootinfo.modules;
> >       struct bootmodule *mod;
> > +    unsigned int i;
> >         if ( mods->nr_mods == MAX_MODULES )
> >       {
> > @@ -212,15 +214,29 @@ 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 )
> > +        {
> > +            if ( !domU )
> > +                mod->domU = false;
> > +            return mod;
> > +        }
> > +    }
> >         mod = &mods->module[mods->nr_mods++];
> >       mod->kind = kind;
> >       mod->start = start;
> >       mod->size = size;
> > +    mod->domU = domU;
> >         return mod;
> >   }
> >   +/*
> > + * This function is only used to find dom0 modules, so check for !mod->domU
> 
> This comment is misleading. The function is used not only to find Dom0 Modules
> but also XSM & co.
> 
> How about:
> 
> "boot_module_find_by_kind can only be used to return Xen modules (e.g XSM,
> DTB) or Dom0 modules. This is not suitable for looking up for guest modules."

Sure, that's clearer


> > + */
> >   struct bootmodule * __init boot_module_find_by_kind(bootmodule_kind kind)
> >   {
> >       struct bootmodules *mods = &bootinfo.modules;
> > @@ -229,14 +245,14 @@ struct bootmodule * __init
> > boot_module_find_by_kind(bootmodule_kind kind)
> >       for (i = 0 ; i < mods->nr_mods ; i++ )
> >       {
> >           mod = &mods->module[i];
> > -        if ( mod->kind == kind )
> > +        if ( mod->kind == kind && !mod->domU )
> >               return mod;
> >       }
> >       return NULL;
> >   }
> >     void __init add_boot_cmdline(const char *name, const char *cmdline,
> > -                             bootmodule_kind kind)
> > +                             bootmodule_kind kind, bool domU)
> >   {
> >       struct bootcmdlines *cmds = &bootinfo.cmdlines;
> >       struct bootcmdline *cmd;
> > @@ -249,6 +265,7 @@ void __init add_boot_cmdline(const char *name, const
> > char *cmdline,
> >         cmd = &cmds->cmdline[cmds->nr_mods++];
> >       cmd->kind = kind;
> > +    cmd->domU = domU;
> >         ASSERT(strlen(name) <= DT_MAX_NAME);
> >       safe_strcpy(cmd->dt_name, name);
> > @@ -258,6 +275,9 @@ void __init add_boot_cmdline(const char *name, const
> > char *cmdline,
> >       safe_strcpy(cmd->cmdline, cmdline);
> >   }
> >   +/*
> > + * This function is only used to find dom0 modules, so check for !mod->domU
> > + */
> 
> Same here.

OK


> >   struct bootcmdline * __init boot_cmdline_find_by_kind(bootmodule_kind
> > kind)
> >   {
> >       struct bootcmdlines *cmds = &bootinfo.cmdlines;
> > @@ -267,7 +287,7 @@ struct bootcmdline * __init
> > boot_cmdline_find_by_kind(bootmodule_kind kind)
> >       for ( i = 0 ; i < cmds->nr_mods ; i++ )
> >       {
> >           cmd = &cmds->cmdline[i];
> > -        if ( cmd->kind == kind )
> > +        if ( cmd->kind == kind && !cmd->domU )
> >               return cmd;
> >       }
> >       return NULL;
> > @@ -761,7 +781,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));
> > +                             (paddr_t)(uintptr_t)(_end - _start + 1),
> > false);
> >       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 7580007..3a30329 100644
> > --- a/xen/include/asm-arm/setup.h
> > +++ b/xen/include/asm-arm/setup.h
> > @@ -30,9 +30,16 @@ struct meminfo {
> >       struct membank bank[NR_MEM_BANKS];
> >   };
> >   +/*
> > + * The domU flag is set for kernels and ramdisks of "xen,domain" nodes.
> > + * The purpose of the domU flag is to avoid getting confused in
> > + * kernel_probe, where we try to guess which is the dom0 kernel and
> > + * initrd to be compatible with all versions of the multiboot spec.
> > + */
> >   #define BOOTMOD_MAX_CMDLINE 1024
> >   struct bootmodule {
> >       bootmodule_kind kind;
> > +    bool domU;
> >       paddr_t start;
> >       paddr_t size;
> >   };
> > @@ -41,6 +48,7 @@ struct bootmodule {
> >   #define DT_MAX_NAME 41
> >   struct bootcmdline {
> >       bootmodule_kind kind;
> > +    bool domU;
> >       char dt_name[DT_MAX_NAME];
> >       char cmdline[BOOTMOD_MAX_CMDLINE];
> >   };
> > @@ -91,10 +99,10 @@ 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);
> > +                                   paddr_t start, paddr_t size, bool domU);
> >   struct bootmodule *boot_module_find_by_kind(bootmodule_kind kind);
> >   void add_boot_cmdline(const char *name, const char *cmdline,
> > -                      bootmodule_kind kind);
> > +                      bootmodule_kind kind, bool domU);
> >   struct bootcmdline *boot_cmdline_find_by_kind(bootmodule_kind kind);
> >   const char * __init boot_module_kind_as_string(bootmodule_kind kind);
> >   
 

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

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

* Re: [PATCH v5 08/25] xen/arm: probe domU kernels and initrds
  2018-10-30 12:03   ` Julien Grall
@ 2018-11-02 20:41     ` Stefano Stabellini
  0 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-11-02 20:41 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Achin.Gupta, Stefano Stabellini,
	andrii_anisov, xen-devel

On Tue, 30 Oct 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 23/10/2018 03:02, Stefano Stabellini wrote:
> > 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.
> > 
> > Set command line for dom0 too for consistency.
> 
> I was expecting you to remove the assignment in construct_dom0 to avoid the
> duplication.

Yes, that would be nicer. I'll do that in this patch.


> > diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
> > index da8410e..d56f776 100644
> > --- a/xen/arch/arm/kernel.c
> > +++ b/xen/arch/arm/kernel.c
> > @@ -421,22 +421,72 @@ 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,
> > +                        const struct dt_device_node *domain)
> >   {
> > -    struct bootmodule *mod = boot_module_find_by_kind(BOOTMOD_KERNEL);
> > +    struct bootmodule *mod = NULL;
> > +    struct bootcmdline *cmd = NULL;
> > +    struct dt_device_node *node;
> > +    u64 kernel_addr, initrd_addr, size;
> >       int rc;
> >   +    /* domain is NULL only for the hardware_domain */
> 
> NIT: No need to the _.
> 
> The rest of the code looks good to me.

OK

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

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

* Re: [PATCH v5 11/25] xen/arm: introduce allocate_memory
  2018-10-30 20:56   ` Julien Grall
@ 2018-11-02 21:15     ` Stefano Stabellini
  0 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-11-02 21:15 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Achin.Gupta, Stefano Stabellini,
	andrii_anisov, xen-devel

On Tue, 30 Oct 2018, Julien Grall wrote:
> Hi Stefano,
> 
> More comments on it :).
> 
> On 10/23/18 3:02 AM, 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.
> > 
> > This is under #if 0 as not used for now.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > ---
> > Changes in v5:
> > - improve commit message
> > - code style
> > - remove unneeded local var
> > - while loop in allocate_bank_memory to allocate memory so that it
> >    doesn't have to be contiguos
> > - combile while loops in allocate_memory
> > 
> > Changes in v4:
> > - move earlier, add #if 0
> > - introduce allocate_bank_memory, remove insert_bank
> > - allocate_bank_memory allocate memory and inserts the bank, while
> >    allocate_memory specifies where to do that
> > 
> > Changes in v3:
> > - new patch
> > ---
> >   xen/arch/arm/domain_build.c | 99
> > +++++++++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 99 insertions(+)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index c61a27f..146d81e 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -368,6 +368,105 @@ static void __init allocate_memory_11(struct domain
> > *d,
> >       }
> >   }
> >   +#if 0
> > +static bool __init allocate_bank_memory(struct domain *d,
> > +                                        struct kernel_info *kinfo,
> > +                                        gfn_t sgfn,
> > +                                        unsigned int order)
> > +{
> > +    int res;
> > +    struct page_info *pg;
> > +    struct membank *bank;
> > +    paddr_t size = pfn_to_paddr(1UL << order);
> > +    gfn_t _sgfn = sgfn;
> > +    gfn_t _egfn = gfn_add(sgfn, 1UL << order);
> > +
> > +    while ( gfn_x(_sgfn) < gfn_x(_egfn) )
> > +    {
> > +        pg = alloc_domheap_pages(d, order, 0);
> > +        if ( pg != NULL )
> > +        {
> > +            res = guest_physmap_add_page(d, _sgfn, page_to_mfn(pg), order);
> > +            if ( res )
> > +            {
> > +                dprintk(XENLOG_ERR, "Failed map pages to DOMU: %d", res);
> > +                goto fail;
> > +            }
> > +            _sgfn = gfn_add(_sgfn, 1UL << order);
> > +        }
> > +        else
> > +        {
> > +            order--;
> > +            if ( order == 0 )
> > +            {
> > +                dprintk(XENLOG_ERR, "Failed to allocated DOMU memory");
> > +                goto fail;
> > +            }
> > +        }
> > +    }
> > +
> > +    bank = &kinfo->mem.bank[kinfo->mem.nr_banks];
> > +    bank->start = gfn_to_gaddr(sgfn);
> > +    bank->size = size;
> > +    kinfo->mem.nr_banks++;
> > +    kinfo->unassigned_mem -= size;
> > +
> > +    return true;
> > +
> > +fail:
> > +    /*
> > +     * Fatal failure, don't attempt to free memory.
> > +     */
> > +    return false;
> > +}
> > +
> > +static void __init allocate_memory(struct domain *d, struct kernel_info
> > *kinfo)
> > +{
> > +    unsigned int order = get_allocation_size(kinfo->unassigned_mem);
> > +    unsigned int order_req;
> > +    unsigned 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);
> 
> While you are re-spinning this series. I would turn all the dprintk to printk
> as those messages are useful in non-debug build.

OK


> > +
> > +    kinfo->mem.nr_banks = 0;
> > +
> > +    order = get_allocation_size(kinfo->unassigned_mem);
> > +    if ( order > get_order_from_bytes(GUEST_RAM0_SIZE) )
> > +        order_req = get_order_from_bytes(GUEST_RAM0_SIZE);
> > +    else
> > +        order_req = order;
> > +    if ( !allocate_bank_memory(d, kinfo, gaddr_to_gfn(GUEST_RAM0_BASE),
> > order_req) )
> > +        goto fail;
> > +
> > +    order -= order_req;
> > +    if ( order > 0 &&
> > +         !allocate_bank_memory(d, kinfo, gaddr_to_gfn(GUEST_RAM1_BASE),
> > order) )
> > +        goto fail;
> > +
> > +    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));
> > +    }
> > +
> > +    return;
> > +
> > +fail:
> > +    dprintk(XENLOG_ERR, "Failed to allocate requested domain memory."
> > +            /* Don't want format this as PRIpaddr (16 digit hex) */
> > +            " %ldKB unallocated. Fix the VMs configurations.\n",
> > +            (unsigned long)kinfo->unassigned_mem >> 10);
> 
> For this one, I would turned to a panic, avoid the BUG() below.

OK


> > +    BUG();
> > +}
> > +#endif
> > +
> >   static int __init write_properties(struct domain *d, struct kernel_info
> > *kinfo,
> >                                      const struct dt_device_node *node)
> >   {

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

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

* Re: [PATCH v5 11/25] xen/arm: introduce allocate_memory
  2018-10-30 12:24   ` Julien Grall
@ 2018-11-02 22:20     ` Stefano Stabellini
  0 siblings, 0 replies; 61+ messages in thread
From: Stefano Stabellini @ 2018-11-02 22:20 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Achin.Gupta, Stefano Stabellini,
	andrii_anisov, xen-devel

On Tue, 30 Oct 2018, Julien Grall wrote:
> Hi,
> 
> On 23/10/2018 03:02, 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.
> > 
> > This is under #if 0 as not used for now.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > ---
> > Changes in v5:
> > - improve commit message
> > - code style
> > - remove unneeded local var
> > - while loop in allocate_bank_memory to allocate memory so that it
> >    doesn't have to be contiguos
> > - combile while loops in allocate_memory
> > 
> > Changes in v4:
> > - move earlier, add #if 0
> > - introduce allocate_bank_memory, remove insert_bank
> > - allocate_bank_memory allocate memory and inserts the bank, while
> >    allocate_memory specifies where to do that
> > 
> > Changes in v3:
> > - new patch
> > ---
> >   xen/arch/arm/domain_build.c | 99
> > +++++++++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 99 insertions(+)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index c61a27f..146d81e 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -368,6 +368,105 @@ static void __init allocate_memory_11(struct domain
> > *d,
> >       }
> >   }
> >   +#if 0
> > +static bool __init allocate_bank_memory(struct domain *d,
> > +                                        struct kernel_info *kinfo,
> > +                                        gfn_t sgfn,
> > +                                        unsigned int order)
> 
> I don't think your implementation below is equivalent to the one I suggested
> earlier on ([1]). While you handled the contiguous problem, you didn't address
> the 2 others points:
>        1) The memory specify by the user may not be in power of 2 pages. For
> instance, a user can specify 40KB. With your algo, we will end to
> allocate 32KB in the first bank and 8KB in the second bank. However what
> we want is allocate 40KB in a single bank.
>        2) You don't check whether the leftover memory is bigger than the size
> of the second bank.
> 
> Because of 1), you can't reason in term of order here. You have to reason in
> bytes or number of pages.
> 
> > +{
> > +    int res;
> > +    struct page_info *pg;
> > +    struct membank *bank;
> > +    paddr_t size = pfn_to_paddr(1UL << order);
> > +    gfn_t _sgfn = sgfn;
> > +    gfn_t _egfn = gfn_add(sgfn, 1UL << order);
> > +
> > +    while ( gfn_x(_sgfn) < gfn_x(_egfn) )
> > +    {
> > +        pg = alloc_domheap_pages(d, order, 0);
> > +        if ( pg != NULL )
> > +        {
> > +            res = guest_physmap_add_page(d, _sgfn, page_to_mfn(pg), order);
> > +            if ( res )
> > +            {
> > +                dprintk(XENLOG_ERR, "Failed map pages to DOMU: %d", res);
> > +                goto fail;
> > +            }
> > +            _sgfn = gfn_add(_sgfn, 1UL << order);
> > +        }
> > +        else
> > +        {
> > +            order--;
> 
> order may be equal to 0. So here you will underflow.
> 
> Overall, it would be best if you re-use the code I sent. While not tested, it
> addresses all the problems. Fixing the potential bug in that patch so be quite
> easily.

OK, I'll add your Signed-off-by to the patch.

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

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

end of thread, other threads:[~2018-11-02 22:20 UTC | newest]

Thread overview: 61+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-23  2:02 [PATCH v5 00/25] dom0less step1: boot multiple domains from device tree Stefano Stabellini
2018-10-23  2:02 ` [PATCH v5 01/25] xen: allow console_io hypercalls from certain DomUs Stefano Stabellini
2018-10-23  2:02 ` [PATCH v5 02/25] xen/arm: extend device tree based multiboot protocol Stefano Stabellini
2018-10-23  2:02 ` [PATCH v5 03/25] xen/arm: document dom0less Stefano Stabellini
2018-10-23  2:02 ` [PATCH v5 04/25] xen/arm: increase MAX_MODULES Stefano Stabellini
2018-10-23  2:02 ` [PATCH v5 05/25] xen/arm: check for multiboot nodes only under /chosen Stefano Stabellini
2018-10-26 19:25   ` Julien Grall
2018-10-26 21:12     ` Stefano Stabellini
2018-10-26 21:27       ` Julien Grall
2018-10-26 21:32         ` Julien Grall
2018-10-27  0:42           ` Stefano Stabellini
2018-10-28 17:28             ` Julien Grall
2018-10-23  2:02 ` [PATCH v5 06/25] xen/arm: introduce bootcmdlines Stefano Stabellini
2018-10-26 19:44   ` Julien Grall
2018-10-27  0:34     ` Stefano Stabellini
2018-10-23  2:02 ` [PATCH v5 07/25] xen/arm: don't add duplicate boot modules, introduce domU flag Stefano Stabellini
2018-10-30 11:50   ` Julien Grall
2018-11-02 20:15     ` Stefano Stabellini
2018-10-23  2:02 ` [PATCH v5 08/25] xen/arm: probe domU kernels and initrds Stefano Stabellini
2018-10-30 12:03   ` Julien Grall
2018-11-02 20:41     ` Stefano Stabellini
2018-10-23  2:02 ` [PATCH v5 09/25] xen/arm: rename get_11_allocation_size to get_allocation_size Stefano Stabellini
2018-10-23  2:02 ` [PATCH v5 10/25] xen/arm: rename allocate_memory to allocate_memory_11 Stefano Stabellini
2018-10-23  2:02 ` [PATCH v5 11/25] xen/arm: introduce allocate_memory Stefano Stabellini
2018-10-30 12:24   ` Julien Grall
2018-11-02 22:20     ` Stefano Stabellini
2018-10-30 20:56   ` Julien Grall
2018-11-02 21:15     ` Stefano Stabellini
2018-10-23  2:02 ` [PATCH v5 12/25] xen/arm: refactor construct_dom0 Stefano Stabellini
2018-10-30 16:32   ` Julien Grall
2018-10-23  2:02 ` [PATCH v5 13/25] xen/arm: move unregister_init_virtual_region to init_done Stefano Stabellini
2018-10-30 16:33   ` Julien Grall
2018-10-23  2:02 ` [PATCH v5 14/25] xen/arm: introduce create_domUs Stefano Stabellini
2018-10-30 16:38   ` Julien Grall
2018-10-23  2:02 ` [PATCH v5 15/25] xen/arm: implement construct_domU Stefano Stabellini
2018-10-30 20:56   ` Julien Grall
2018-10-23  2:02 ` [PATCH v5 16/25] xen/arm: generate a simple device tree for domUs Stefano Stabellini
2018-10-23  2:02 ` [PATCH v5 17/25] xen/arm: make set_interrupt_ppi able to handle non-PPI Stefano Stabellini
2018-10-23  2:02 ` [PATCH v5 18/25] xen/arm: generate vpl011 node on device tree for domU Stefano Stabellini
2018-10-30 20:58   ` Julien Grall
2018-10-23  2:02 ` [PATCH v5 19/25] xen/arm: introduce a union in vpl011 Stefano Stabellini
2018-10-23  2:02 ` [PATCH v5 20/25] xen/arm: refactor vpl011_data_avail Stefano Stabellini
2018-10-23  2:03 ` [PATCH v5 21/25] xen: support console_switching between Dom0 and DomUs on ARM Stefano Stabellini
2018-10-24 14:55   ` Oleksandr Andrushchenko
2018-10-29 20:00     ` Stefano Stabellini
2018-10-29 20:01       ` Julien Grall
2018-10-26 14:29   ` Jan Beulich
2018-10-29 19:56     ` Stefano Stabellini
2018-10-23  2:03 ` [PATCH v5 22/25] xen/arm: Allow vpl011 to be used by DomU Stefano Stabellini
2018-10-24 17:14   ` Oleksandr Tyshchenko
2018-10-29 20:03     ` Stefano Stabellini
2018-10-30 11:04       ` Oleksandr Tyshchenko
2018-10-23  2:03 ` [PATCH v5 23/25] xen/vpl011: buffer out chars when the backend is xen Stefano Stabellini
2018-10-24 14:46   ` Oleksandr Andrushchenko
2018-10-29 20:09     ` Stefano Stabellini
2018-10-31 13:27   ` Julien Grall
2018-10-23  2:03 ` [PATCH v5 24/25] xen/arm: move kernel.h to asm-arm/ Stefano Stabellini
2018-10-31 13:28   ` Julien Grall
2018-10-23  2:03 ` [PATCH v5 25/25] xen/arm: split domain_build.c Stefano Stabellini
2018-10-31 13:44   ` Julien Grall
2018-11-01 20:37     ` Stefano Stabellini

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.