All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 01/21] xen/arm: rename get_11_allocation_size to get_allocation_size
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
@ 2018-07-06 23:11 ` Stefano Stabellini
  2018-07-09 12:55   ` Julien Grall
  2018-07-06 23:11 ` [PATCH v2 02/21] xen/arm: make allocate_memory work for non 1:1 mapped guests Stefano Stabellini
                   ` (21 subsequent siblings)
  22 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:11 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

... and remove the BUG_ON(!dom0_11_mapping) in allocate_memory.
A follow-up patch will make the function work with non 1:1 mapped
guests.

No functional changes.

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

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

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 11cdf05..182e3d5 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -79,7 +79,7 @@ struct vcpu *__init alloc_dom0_vcpu0(struct domain *dom0)
     return alloc_vcpu(dom0, 0, 0);
 }
 
-static unsigned int get_11_allocation_size(paddr_t size)
+static unsigned int get_allocation_size(paddr_t size)
 {
     /*
      * get_order_from_bytes returns the order greater than or equal to
@@ -251,21 +251,15 @@ static void 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;
     unsigned int bits;
 
-    /*
-     * TODO: Implement memory bank allocation when DOM0 is not direct
-     * mapped
-     */
-    BUG_ON(!dom0_11_mapping);
-
-    printk("Allocating 1:1 mappings totalling %ldMB for dom0:\n",
+    printk("Allocating 1:1 mappings totalling %ldMB for dom%d:\n",
            /* Don't want format this as PRIpaddr (16 digit hex) */
-           (unsigned long)(kinfo->unassigned_mem >> 20));
+           (unsigned long)(kinfo->unassigned_mem >> 20), d->domain_id);
 
     kinfo->mem.nr_banks = 0;
 
@@ -303,7 +297,7 @@ static void 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);
@@ -314,7 +308,7 @@ static void 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;
             }
@@ -334,7 +328,7 @@ static void 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;
             }
@@ -349,7 +343,7 @@ static void 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	[flat|nested] 92+ messages in thread

* [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree
@ 2018-07-06 23:11 Stefano Stabellini
  2018-07-06 23:11 ` [PATCH v2 01/21] xen/arm: rename get_11_allocation_size to get_allocation_size Stefano Stabellini
                   ` (22 more replies)
  0 siblings, 23 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:11 UTC (permalink / raw)
  To: julien.grall
  Cc: andrew.cooper3, sstabellini, andrii_anisov, jbeulich, 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.

Cheers,

Stefano


Stefano Stabellini (21):
      xen/arm: rename get_11_allocation_size to get_allocation_size
      xen/arm: make allocate_memory work for non 1:1 mapped guests
      xen: allow console_io hypercalls from certain DomUs
      xen/arm: move a few DT related defines to public/device_tree_defs.h
      xen/arm: extend device tree based multiboot protocol
      xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node
      xen/arm: rename acpi_make_chosen_node to make_chosen_node
      xen/arm: increase MAX_MODULES
      xen/arm: move cmdline out of boot_modules
      xen/arm: don't add duplicate boot modules
      xen/arm: probe domU kernels and initrds
      xen/arm: refactor construct_dom0
      xen/arm: introduce construct_domU
      xen/arm: generate a simple device tree for domUs
      xen/arm: generate vpl011 node on device tree for domU
      xen/arm: introduce a union in vpl011
      xen/arm: refactor vpl011_data_avail
      xen/arm: Allow vpl011 to be used by DomU
      xen/arm: introduce create_domUs
      xen: support console_switching between Dom0 and DomUs on ARM
      xen/arm: split domain_build.c

 docs/misc/arm/device-tree/booting.txt |  108 ++++
 tools/libxl/libxl_arm.c               |   59 +-
 xen/arch/arm/acpi/Makefile            |    1 +
 xen/arch/arm/acpi/acpi_dt_build.c     |  588 +++++++++++++++++
 xen/arch/arm/acpi/acpi_dt_build.h     |   32 +
 xen/arch/arm/bootfdt.c                |   48 +-
 xen/arch/arm/domain_build.c           | 1130 ++++++++++++++-------------------
 xen/arch/arm/kernel.c                 |   47 +-
 xen/arch/arm/kernel.h                 |    3 +-
 xen/arch/arm/setup.c                  |   42 +-
 xen/arch/arm/vpl011.c                 |  263 ++++++--
 xen/common/device_tree.c              |    6 +-
 xen/drivers/char/console.c            |   50 +-
 xen/include/asm-arm/irq.h             |   16 +
 xen/include/asm-arm/setup.h           |   15 +-
 xen/include/asm-arm/vpl011.h          |   18 +-
 xen/include/asm-x86/setup.h           |    2 +
 xen/include/public/device_tree_defs.h |   39 ++
 xen/include/xen/device_tree.h         |   35 +-
 xen/include/xen/sched.h               |    2 +
 xen/include/xsm/dummy.h               |    2 +
 xen/xsm/flask/hooks.c                 |    5 +-
 22 files changed, 1668 insertions(+), 843 deletions(-)
 create mode 100644 xen/arch/arm/acpi/acpi_dt_build.c
 create mode 100644 xen/arch/arm/acpi/acpi_dt_build.h
 create mode 100644 xen/include/public/device_tree_defs.h

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

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

* [PATCH v2 02/21] xen/arm: make allocate_memory work for non 1:1 mapped guests
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
  2018-07-06 23:11 ` [PATCH v2 01/21] xen/arm: rename get_11_allocation_size to get_allocation_size Stefano Stabellini
@ 2018-07-06 23:11 ` Stefano Stabellini
  2018-07-09 13:43   ` Julien Grall
                     ` (2 more replies)
  2018-07-06 23:11 ` [PATCH v2 03/21] xen: allow console_io hypercalls from certain DomUs Stefano Stabellini
                   ` (20 subsequent siblings)
  22 siblings, 3 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:11 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Extend allocate_memory to work for non 1:1 mapped domUs. Specifically,
memory allocated for domU will be mapped into the domU pseudo-physical
address space at the appropriate addresses according to the guest memory
map: GUEST_RAM0_BASE and GUEST_RAM1_BASE.

To do that, insert_11_bank has been extended to deal with non-dom0
mappings starting from GUEST_RAM0_BASE. insert_11_bank has been renamed
to insert_bank.

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

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

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 182e3d5..2a6619a 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -97,27 +97,51 @@ static unsigned int get_allocation_size(paddr_t size)
  * Returns false if the memory would be below bank 0 or we have run
  * out of banks. In this case it will free the pages.
  */
-static bool insert_11_bank(struct domain *d,
-                           struct kernel_info *kinfo,
-                           struct page_info *pg,
-                           unsigned int order)
+static bool insert_bank(struct domain *d,
+                        struct kernel_info *kinfo,
+                        struct page_info *pg,
+                        unsigned int order,
+                        bool map_11)
 {
-    int res, i;
+    int res, i, nr_mem_banks = map_11 ? NR_MEM_BANKS : 2;
     mfn_t smfn;
     paddr_t start, size;
+    struct membank *bank;
 
     smfn = page_to_mfn(pg);
     start = mfn_to_maddr(smfn);
     size = pfn_to_paddr(1UL << order);
+    if ( !map_11 )
+    {
+        start = GUEST_RAM0_BASE;
+        if ( kinfo->mem.nr_banks > 0 )
+        {
+            for( i = 0; i < kinfo->mem.nr_banks; i++ )
+            {
+                bank = &kinfo->mem.bank[i];
+                start = bank->start + bank->size;
+            }
+            if ( bank->start == GUEST_RAM0_BASE &&
+                    start + size > (GUEST_RAM0_BASE + GUEST_RAM0_SIZE) )
+                start = GUEST_RAM1_BASE;
+            if ( bank->start == GUEST_RAM1_BASE &&
+                    start + size > (GUEST_RAM1_BASE + GUEST_RAM1_SIZE) )
+            {
+                D11PRINT("Allocation of domain memory exceeds max amount\n");
+                goto fail;
+            }
+        }
+    }
 
-    D11PRINT("Allocated %#"PRIpaddr"-%#"PRIpaddr" (%ldMB/%ldMB, order %d)\n",
+    D11PRINT("Allocated %#"PRIpaddr"-%#"PRIpaddr":%#"PRIpaddr"-%#"PRIpaddr" (%ldMB/%ldMB, order %d)\n",
+             mfn_to_maddr(smfn), mfn_to_maddr(smfn) + size,
              start, start + size,
              1UL << (order + PAGE_SHIFT - 20),
              /* Don't want format this as PRIpaddr (16 digit hex) */
              (unsigned long)(kinfo->unassigned_mem >> 20),
              order);
 
-    if ( kinfo->mem.nr_banks > 0 &&
+    if ( map_11 && kinfo->mem.nr_banks > 0 &&
          size < MB(128) &&
          start + size < kinfo->mem.bank[0].start )
     {
@@ -125,7 +149,7 @@ static bool insert_11_bank(struct domain *d,
         goto fail;
     }
 
-    res = guest_physmap_add_page(d, _gfn(mfn_x(smfn)), smfn, order);
+    res = guest_physmap_add_page(d, gaddr_to_gfn(start), smfn, order);
     if ( res )
         panic("Failed map pages to DOM0: %d", res);
 
@@ -141,7 +165,7 @@ static bool insert_11_bank(struct domain *d,
 
     for( i = 0; i < kinfo->mem.nr_banks; i++ )
     {
-        struct membank *bank = &kinfo->mem.bank[i];
+        bank = &kinfo->mem.bank[i];
 
         /* If possible merge new memory into the start of the bank */
         if ( bank->start == start+size )
@@ -164,7 +188,7 @@ static bool insert_11_bank(struct domain *d,
          * could have inserted the memory into/before we would already
          * have done so, so this must be the right place.
          */
-        if ( start + size < bank->start && kinfo->mem.nr_banks < NR_MEM_BANKS )
+        if ( start + size < bank->start && kinfo->mem.nr_banks < nr_mem_banks )
         {
             memmove(bank + 1, bank,
                     sizeof(*bank) * (kinfo->mem.nr_banks - i));
@@ -175,7 +199,7 @@ static bool insert_11_bank(struct domain *d,
         }
     }
 
-    if ( i == kinfo->mem.nr_banks && kinfo->mem.nr_banks < NR_MEM_BANKS )
+    if ( i == kinfo->mem.nr_banks && kinfo->mem.nr_banks < nr_mem_banks )
     {
         struct membank *bank = &kinfo->mem.bank[kinfo->mem.nr_banks];
 
@@ -253,6 +277,7 @@ static void allocate_memory(struct domain *d, struct kernel_info *kinfo)
     struct page_info *pg;
     unsigned int order = get_allocation_size(kinfo->unassigned_mem);
     int i;
+    bool hwdom = d->domain_id == 0;
 
     bool lowmem = true;
     unsigned int bits;
@@ -263,6 +288,12 @@ static void allocate_memory(struct domain *d, struct kernel_info *kinfo)
 
     kinfo->mem.nr_banks = 0;
 
+    if ( !hwdom )
+    {
+        lowmem = false;
+        goto got_bank0;
+    }
+
     /*
      * First try and allocate the largest thing we can as low as
      * possible to be bank 0.
@@ -274,7 +305,7 @@ static void allocate_memory(struct domain *d, struct kernel_info *kinfo)
             pg = alloc_domheap_pages(d, order, MEMF_bits(bits));
             if ( pg != NULL )
             {
-                if ( !insert_11_bank(d, kinfo, pg, order) )
+                if ( !insert_bank(d, kinfo, pg, order, hwdom) )
                     BUG(); /* Cannot fail for first bank */
 
                 goto got_bank0;
@@ -319,7 +350,7 @@ static void allocate_memory(struct domain *d, struct kernel_info *kinfo)
             break;
         }
 
-        if ( !insert_11_bank(d, kinfo, pg, order) )
+        if ( !insert_bank(d, kinfo, pg, order, hwdom) )
         {
             if ( kinfo->mem.nr_banks == NR_MEM_BANKS )
                 /* Nothing more we can do. */
-- 
1.9.1


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

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

* [PATCH v2 03/21] xen: allow console_io hypercalls from certain DomUs
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
  2018-07-06 23:11 ` [PATCH v2 01/21] xen/arm: rename get_11_allocation_size to get_allocation_size Stefano Stabellini
  2018-07-06 23:11 ` [PATCH v2 02/21] xen/arm: make allocate_memory work for non 1:1 mapped guests Stefano Stabellini
@ 2018-07-06 23:11 ` Stefano Stabellini
  2018-07-09 13:48   ` Julien Grall
  2018-07-06 23:11 ` [PATCH v2 04/21] xen/arm: move a few DT related defines to public/device_tree_defs.h Stefano Stabellini
                   ` (19 subsequent siblings)
  22 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:11 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, sstabellini, andrii_anisov, George.Dunlap,
	andrew.cooper3, ian.jackson, xen-devel, tim, jbeulich, wei.liu2,
	dgdegra

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

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
CC: andrew.cooper3@citrix.com
CC: George.Dunlap@eu.citrix.com
CC: ian.jackson@eu.citrix.com
CC: jbeulich@suse.com
CC: konrad.wilk@oracle.com
CC: tim@xen.org
CC: wei.liu2@citrix.com
CC: dgdegra@tycho.nsa.gov
---
Changes in v2:
- introduce is_console
- remove #ifdefs
---
 xen/include/xen/sched.h | 2 ++
 xen/include/xsm/dummy.h | 2 ++
 xen/xsm/flask/hooks.c   | 5 ++++-
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 99d2af2..d66cec0 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -379,6 +379,8 @@ struct domain
     bool             auto_node_affinity;
     /* Is this guest fully privileged (aka dom0)? */
     bool             is_privileged;
+    /* Can this guest access the Xen console? */
+    bool             is_console;
     /* Is this a xenstore domain (not dom0)? */
     bool             is_xenstore;
     /* Domain's VCPUs are pinned 1:1 to physical CPUs? */
diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index ff6b2db..3888817 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -230,6 +230,8 @@ static XSM_INLINE int xsm_memory_stat_reservation(XSM_DEFAULT_ARG struct domain
 static XSM_INLINE int xsm_console_io(XSM_DEFAULT_ARG struct domain *d, int cmd)
 {
     XSM_ASSERT_ACTION(XSM_OTHER);
+    if ( d->is_console )
+        return xsm_default_action(XSM_HOOK, d, NULL);
 #ifdef CONFIG_VERBOSE_DEBUG
     if ( cmd == CONSOLEIO_write )
         return xsm_default_action(XSM_HOOK, d, NULL);
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index 78bc326..2551e4e 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -443,7 +443,10 @@ static int flask_console_io(struct domain *d, int cmd)
         return avc_unknown_permission("console_io", cmd);
     }
 
-    return domain_has_xen(d, perm);
+    if ( !d->is_console )
+        return domain_has_xen(d, perm);
+    else
+        return 0;
 }
 
 static int flask_profile(struct domain *d, int op)
-- 
1.9.1


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

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

* [PATCH v2 04/21] xen/arm: move a few DT related defines to public/device_tree_defs.h
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (2 preceding siblings ...)
  2018-07-06 23:11 ` [PATCH v2 03/21] xen: allow console_io hypercalls from certain DomUs Stefano Stabellini
@ 2018-07-06 23:11 ` Stefano Stabellini
  2018-07-09 13:59   ` Julien Grall
  2018-07-06 23:12 ` [PATCH v2 05/21] xen/arm: extend device tree based multiboot protocol Stefano Stabellini
                   ` (18 subsequent siblings)
  22 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:11 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, sstabellini, andrii_anisov, ian.jackson,
	xen-devel, wei.liu2

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

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

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

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
CC: wei.liu2@citrix.com
CC: ian.jackson@eu.citrix.com
---
Changes in v2:
- introduce DT_IRQ_TYPE_* definitions in device_tree_guest.h
- prepend GUEST_ to other definitions moved to device_tree_guest.h
- redefine IRQ_TYPE_* as  DT_IRQ_TYPE_*
- use DT_IRQ_TYPE_* in Xen when dealing with DT
---
 tools/libxl/libxl_arm.c               | 59 ++++++++++-------------------------
 xen/arch/arm/domain_build.c           |  8 ++---
 xen/include/asm-arm/irq.h             | 16 ++++++++++
 xen/include/public/device_tree_defs.h | 39 +++++++++++++++++++++++
 xen/include/xen/device_tree.h         | 33 +++-----------------
 5 files changed, 80 insertions(+), 75 deletions(-)
 create mode 100644 xen/include/public/device_tree_defs.h

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


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

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

* [PATCH v2 05/21] xen/arm: extend device tree based multiboot protocol
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (3 preceding siblings ...)
  2018-07-06 23:11 ` [PATCH v2 04/21] xen/arm: move a few DT related defines to public/device_tree_defs.h Stefano Stabellini
@ 2018-07-06 23:12 ` Stefano Stabellini
  2018-07-09 14:07   ` Julien Grall
  2018-07-06 23:12 ` [PATCH v2 06/21] xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node Stefano Stabellini
                   ` (17 subsequent siblings)
  22 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:12 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

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

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

---
Changes in 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 | 108 ++++++++++++++++++++++++++++++++++
 1 file changed, 108 insertions(+)

diff --git a/docs/misc/arm/device-tree/booting.txt b/docs/misc/arm/device-tree/booting.txt
index ce2d0dc..5c3b8da 100644
--- a/docs/misc/arm/device-tree/booting.txt
+++ b/docs/misc/arm/device-tree/booting.txt
@@ -119,3 +119,111 @@ 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"
+    For dom0: "xen,domain", "xen,initial-domain"
+
+- memory
+
+    An integer specifying the amount of megabytes of RAM to allocate to
+    the guest.
+
+- cpus
+
+    An integer specifying the number of vcpus to allocate to the guest.
+
+- vpl011
+
+    An integer 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 = <128>;
+        cpus = <2>;
+        vpl011 = <1>;
+
+        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 = <64>;
+        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	[flat|nested] 92+ messages in thread

* [PATCH v2 06/21] xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (4 preceding siblings ...)
  2018-07-06 23:12 ` [PATCH v2 05/21] xen/arm: extend device tree based multiboot protocol Stefano Stabellini
@ 2018-07-06 23:12 ` Stefano Stabellini
  2018-07-09 14:11   ` Julien Grall
  2018-07-06 23:12 ` [PATCH v2 07/21] xen/arm: rename acpi_make_chosen_node to make_chosen_node Stefano Stabellini
                   ` (16 subsequent siblings)
  22 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:12 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

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

In make_hypervisor_node, assume that evtchn_irq has already been
allocated. Move the evtchn_allocate call to handle_node.

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

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

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index ae3ebc5..c349ce4 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -558,11 +558,11 @@ static int fdt_property_interrupts(void *fdt, gic_interrupt_t *intr,
 
 static int make_memory_node(const struct domain *d,
                             void *fdt,
-                            const struct dt_device_node *parent,
+                            int addrcells, int sizecells,
                             const struct kernel_info *kinfo)
 {
     int res, i;
-    int reg_size = dt_child_n_addr_cells(parent) + dt_child_n_size_cells(parent);
+    int reg_size = addrcells + sizecells;
     int nr_cells = reg_size*kinfo->mem.nr_banks;
     __be32 reg[nr_cells];
     __be32 *cells;
@@ -588,7 +588,7 @@ static int make_memory_node(const struct domain *d,
         dt_dprintk("  Bank %d: %#"PRIx64"->%#"PRIx64"\n",
                    i, start, start + size);
 
-        dt_child_set_range(&cells, parent, start, size);
+        dt_child_set_range(&cells, addrcells, sizecells, start, size);
     }
 
     res = fdt_property(fdt, "reg", reg, sizeof(reg));
@@ -604,7 +604,7 @@ static void evtchn_allocate(struct domain *d);
 
 static int make_hypervisor_node(struct domain *d,
                                 const struct kernel_info *kinfo,
-                                const struct dt_device_node *parent)
+                                int addrcells, int sizecells)
 {
     const char compat[] =
         "xen,xen-"__stringify(XEN_VERSION)"."__stringify(XEN_SUBVERSION)"\0"
@@ -613,9 +613,6 @@ static int make_hypervisor_node(struct domain *d,
     gic_interrupt_t intr;
     __be32 *cells;
     int res;
-    /* Convenience alias */
-    int addrcells = dt_child_n_addr_cells(parent);
-    int sizecells = dt_child_n_size_cells(parent);
     void *fdt = kinfo->fdt;
 
     dt_dprintk("Create hypervisor node\n");
@@ -640,19 +637,14 @@ static int make_hypervisor_node(struct domain *d,
 
     /* reg 0 is grant table space */
     cells = &reg[0];
-    dt_child_set_range(&cells, parent, kinfo->gnttab_start, kinfo->gnttab_size);
+    dt_child_set_range(&cells, addrcells, sizecells,
+                       kinfo->gnttab_start, kinfo->gnttab_size);
     res = fdt_property(fdt, "reg", reg,
                        dt_cells_to_size(addrcells + sizecells));
     if ( res )
         return res;
 
     /*
-     * It is safe to allocate the event channel here because all the
-     * PPIs used by the hardware domain have been registered.
-     */
-    evtchn_allocate(d);
-
-    /*
      * Interrupt event channel upcall:
      *  - Active-low level-sensitive
      *  - All CPUs
@@ -1317,11 +1309,23 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
 
     if ( node == dt_host )
     {
+        int addrcells = dt_child_n_addr_cells(node);
+        int sizecells = dt_child_n_size_cells(node);
+
+
+        /*
+         *      * It is safe to allocate the event channel here
+         *      because all the
+         *           * PPIs used by the hardware domain have been
+         *           registered.
+         *                */
+        evtchn_allocate(d);
+
         /*
          * The hypervisor node should always be created after all nodes
          * from the host DT have been parsed.
          */
-        res = make_hypervisor_node(d, kinfo, node);
+        res = make_hypervisor_node(d, kinfo, addrcells, sizecells);
         if ( res )
             return res;
 
@@ -1333,7 +1337,7 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
         if ( res )
             return res;
 
-        res = make_memory_node(d, kinfo->fdt, node, kinfo);
+        res = make_memory_node(d, kinfo->fdt, addrcells, sizecells, kinfo);
         if ( res )
             return res;
 
diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 7b009ea..8fc401d 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -112,11 +112,11 @@ void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
     dt_set_cell(cellp, dt_n_size_cells(np), size);
 }
 
-void dt_child_set_range(__be32 **cellp, const struct dt_device_node *parent,
+void dt_child_set_range(__be32 **cellp, int addrcells, int sizecells,
                         u64 address, u64 size)
 {
-    dt_set_cell(cellp, dt_child_n_addr_cells(parent), address);
-    dt_set_cell(cellp, dt_child_n_size_cells(parent), size);
+    dt_set_cell(cellp, addrcells, address);
+    dt_set_cell(cellp, sizecells, size);
 }
 
 static void __init *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index 638b926..91fa0b6 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -674,7 +674,7 @@ void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
  * Write a range into a series of cells and update cellp to point to the
  * cell just after.
  */
-void dt_child_set_range(__be32 **cellp, const struct dt_device_node *parent,
+void dt_child_set_range(__be32 **cellp, int addrcells, int sizecells,
                         u64 address, u64 size);
 
 /**
-- 
1.9.1


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

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

* [PATCH v2 07/21] xen/arm: rename acpi_make_chosen_node to make_chosen_node
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (5 preceding siblings ...)
  2018-07-06 23:12 ` [PATCH v2 06/21] xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node Stefano Stabellini
@ 2018-07-06 23:12 ` Stefano Stabellini
  2018-07-09 14:12   ` Julien Grall
  2018-07-06 23:12 ` [PATCH v2 08/21] xen/arm: increase MAX_MODULES Stefano Stabellini
                   ` (15 subsequent siblings)
  22 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:12 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

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

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

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


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

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

* [PATCH v2 08/21] xen/arm: increase MAX_MODULES
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (6 preceding siblings ...)
  2018-07-06 23:12 ` [PATCH v2 07/21] xen/arm: rename acpi_make_chosen_node to make_chosen_node Stefano Stabellini
@ 2018-07-06 23:12 ` Stefano Stabellini
  2018-07-06 23:12 ` [PATCH v2 09/21] xen/arm: move cmdline out of boot_modules Stefano Stabellini
                   ` (14 subsequent siblings)
  22 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:12 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

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

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

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


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

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

* [PATCH v2 09/21] xen/arm: move cmdline out of boot_modules
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (7 preceding siblings ...)
  2018-07-06 23:12 ` [PATCH v2 08/21] xen/arm: increase MAX_MODULES Stefano Stabellini
@ 2018-07-06 23:12 ` Stefano Stabellini
  2018-07-09 14:53   ` Julien Grall
  2018-07-06 23:12 ` [PATCH v2 10/21] xen/arm: don't add duplicate boot modules Stefano Stabellini
                   ` (13 subsequent siblings)
  22 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:12 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Remove the cmdline field from struct boot_module, cmdline is stored
independently out of the boot_modules array as dom0_cmdline.

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

boot_fdt_cmdline is only used to retrieve the Xen cmdline. Remove the
code to return the dom0 cmdline when the Xen cmdline is not available.

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

---
Changes in v2:
- new patch
---
 xen/arch/arm/bootfdt.c      | 25 +++++++------------------
 xen/arch/arm/domain_build.c | 11 +++++------
 xen/arch/arm/kernel.h       |  1 +
 xen/arch/arm/setup.c        | 10 +++-------
 xen/include/asm-arm/setup.h |  5 ++---
 5 files changed, 18 insertions(+), 34 deletions(-)

diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
index 8eba42c..b3e1e00 100644
--- a/xen/arch/arm/bootfdt.c
+++ b/xen/arch/arm/bootfdt.c
@@ -226,11 +226,10 @@ static void __init process_multiboot_node(const void *fdt, int node,
         if ( len > BOOTMOD_MAX_CMDLINE )
             panic("module %s command line too long\n", name);
         cmdline = prop->data;
+        safe_strcpy(dom0_cmdline, cmdline);
     }
-    else
-        cmdline = NULL;
-
-    add_boot_module(kind, start, size, cmdline);
+ 
+    add_boot_module(kind, start, size);
 }
 
 static void __init process_chosen_node(const void *fdt, int node,
@@ -276,7 +275,7 @@ static void __init process_chosen_node(const void *fdt, int node,
 
     printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end);
 
-    add_boot_module(BOOTMOD_RAMDISK, start, end-start, NULL);
+    add_boot_module(BOOTMOD_RAMDISK, start, end-start);
 }
 
 static int __init early_scan_node(const void *fdt,
@@ -307,12 +306,11 @@ static void __init early_print_info(void)
                      mi->bank[i].start + mi->bank[i].size - 1);
     printk("\n");
     for ( i = 0 ; i < mods->nr_mods; i++ )
-        printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s %s\n",
+        printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s\n",
                      i,
                      mods->module[i].start,
                      mods->module[i].start + mods->module[i].size,
-                     boot_module_kind_as_string(mods->module[i].kind),
-                     mods->module[i].cmdline);
+                     boot_module_kind_as_string(mods->module[i].kind));
     nr_rsvd = fdt_num_mem_rsv(device_tree_flattened);
     for ( i = 0; i < nr_rsvd; i++ )
     {
@@ -341,7 +339,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();
@@ -360,15 +358,6 @@ 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);
-
-        if (fdt_get_property(fdt, node, "xen,dom0-bootargs", NULL) ||
-            ( dom0_mod && dom0_mod->cmdline[0] ) )
-            prop = fdt_get_property(fdt, node, "bootargs", NULL);
-    }
-    if ( prop == NULL )
         return NULL;
 
     return prop->data;
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 4d06584..d7e642b 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -402,10 +402,8 @@ static int 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 ( dom0_cmdline[0] )
+        bootargs = &dom0_cmdline[0];
 
     dt_for_each_property_node (node, prop)
     {
@@ -971,9 +969,9 @@ static int 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;
@@ -2173,6 +2171,7 @@ int __init construct_dom0(struct domain *d)
 
 #endif
 
+    kinfo.cmdline = &dom0_cmdline[0];
     allocate_memory(d, &kinfo);
     find_gnttab_region(d, &kinfo);
 
diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
index 6d69509..a47aa4c 100644
--- a/xen/arch/arm/kernel.h
+++ b/xen/arch/arm/kernel.h
@@ -30,6 +30,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 1d6f6bf..188b2cb 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -51,6 +51,7 @@
 #include <asm/acpi.h>
 
 struct bootinfo __initdata bootinfo;
+char __initdata dom0_cmdline[BOOTMOD_MAX_CMDLINE];
 
 struct cpuinfo_arm __read_mostly boot_cpu_data;
 
@@ -202,8 +203,7 @@ void dt_unreserved_regions(paddr_t s, paddr_t e,
 }
 
 struct bootmodule *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;
@@ -219,10 +219,6 @@ struct bootmodule *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;
 }
@@ -725,7 +721,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..6d08eb4 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -35,13 +35,13 @@ struct bootmodule {
     bootmodule_kind kind;
     paddr_t start;
     paddr_t size;
-    char cmdline[BOOTMOD_MAX_CMDLINE];
 };
 
 struct bootmodules {
     int nr_mods;
     struct bootmodule module[MAX_MODULES];
 };
+extern char dom0_cmdline[BOOTMOD_MAX_CMDLINE];
 
 struct bootinfo {
     struct meminfo mem;
@@ -78,8 +78,7 @@ 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);
 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	[flat|nested] 92+ messages in thread

* [PATCH v2 10/21] xen/arm: don't add duplicate boot modules
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (8 preceding siblings ...)
  2018-07-06 23:12 ` [PATCH v2 09/21] xen/arm: move cmdline out of boot_modules Stefano Stabellini
@ 2018-07-06 23:12 ` Stefano Stabellini
  2018-07-06 23:12 ` [PATCH v2 11/21] xen/arm: probe domU kernels and initrds Stefano Stabellini
                   ` (12 subsequent siblings)
  22 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:12 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

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

Don't try to add cmdline for "xen,domain" compatible nodes. It will be
added later directly by kernel_probe.

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

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

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

diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
index b3e1e00..f005c50 100644
--- a/xen/arch/arm/bootfdt.c
+++ b/xen/arch/arm/bootfdt.c
@@ -174,7 +174,12 @@ static void __init process_multiboot_node(const void *fdt, int node,
     paddr_t start, size;
     const char *cmdline;
     int len;
+    int parent_node;
 
+    parent_node = fdt_parent_offset(fdt, node);
+    if ( parent_node < 0 )
+        panic("node %s missing a parent\n", name);
+ 
     prop = fdt_get_property(fdt, node, "reg", &len);
     if ( !prop )
         panic("node %s missing `reg' property\n", name);
@@ -220,13 +225,23 @@ 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 ( fdt_node_check_compatible(fdt, parent_node, "xen,domain") != 0 )
+    {
+        prop = fdt_get_property(fdt, node, "bootargs", &len);
+        if ( prop )
+        {
+            if ( len > BOOTMOD_MAX_CMDLINE )
+                panic("module %s command line too long\n", name);
+            cmdline = prop->data;
+            safe_strcpy(dom0_cmdline, cmdline);
+        }
+    }
+    else
     {
-        if ( len > BOOTMOD_MAX_CMDLINE )
-            panic("module %s command line too long\n", name);
-        cmdline = prop->data;
-        safe_strcpy(dom0_cmdline, cmdline);
+        if ( kind == BOOTMOD_KERNEL )
+            kind = BOOTMOD_KERNEL_DOMAIN;
+        if ( kind == BOOTMOD_RAMDISK )
+            kind = BOOTMOD_RAMDISK_DOMAIN;
     }
  
     add_boot_module(kind, start, size);
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 188b2cb..d4316c7 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -207,6 +207,7 @@ struct bootmodule *add_boot_module(bootmodule_kind kind,
 {
     struct bootmodules *mods = &bootinfo.modules;
     struct bootmodule *mod;
+    int i;
 
     if ( mods->nr_mods == MAX_MODULES )
     {
@@ -214,6 +215,12 @@ struct bootmodule *add_boot_module(bootmodule_kind kind,
                boot_module_kind_as_string(kind), start, start + size);
         return NULL;
     }
+    for ( i = 0 ; i < mods->nr_mods ; i++ )
+    {
+        mod = &mods->module[i];
+        if ( mod->kind == kind && mod->start == start )
+            return mod;
+    }
 
     mod = &mods->module[mods->nr_mods++];
     mod->kind = kind;
@@ -246,6 +253,8 @@ const char * __init boot_module_kind_as_string(bootmodule_kind kind)
     case BOOTMOD_KERNEL:  return "Kernel";
     case BOOTMOD_RAMDISK: return "Ramdisk";
     case BOOTMOD_XSM:     return "XSM";
+    case BOOTMOD_KERNEL_DOMAIN:  return "DomU Kernel";
+    case BOOTMOD_RAMDISK_DOMAIN: return "DomU Ramdisk";
     case BOOTMOD_UNKNOWN: return "Unknown";
     default: BUG();
     }
diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
index 6d08eb4..f8f3eff 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -16,6 +16,8 @@ typedef enum {
     BOOTMOD_KERNEL,
     BOOTMOD_RAMDISK,
     BOOTMOD_XSM,
+    BOOTMOD_KERNEL_DOMAIN,
+    BOOTMOD_RAMDISK_DOMAIN,
     BOOTMOD_UNKNOWN
 }  bootmodule_kind;
 
-- 
1.9.1


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

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

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

Find addresses, sizes and cmdlines on device tree from kernel_probe.

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.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
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       | 47 ++++++++++++++++++++++++++++++++++++++-------
 xen/arch/arm/kernel.h       |  2 +-
 xen/arch/arm/setup.c        | 15 +++++++++++++++
 xen/include/asm-arm/setup.h |  2 ++
 5 files changed, 59 insertions(+), 9 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index d7e642b..3ddaffb 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -2153,7 +2153,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 8fdfd91..a9fa540 100644
--- a/xen/arch/arm/kernel.c
+++ b/xen/arch/arm/kernel.c
@@ -496,22 +496,55 @@ err:
     return rc;
 }
 
-int kernel_probe(struct kernel_info *info)
+int kernel_probe(struct kernel_info *info, struct dt_device_node *domain) 
 {
-    struct bootmodule *mod = boot_module_find_by_kind(BOOTMOD_KERNEL);
+    struct bootmodule *mod;
+    struct dt_device_node *node;
+    u64 kernel_addr, initrd_addr, size;
+    const char *cmdline = NULL;
     int rc;
 
+    if ( domain == NULL )
+    {
+        mod = boot_module_find_by_kind(BOOTMOD_KERNEL);
+
+        info->kernel_bootmodule = mod;
+        info->initrd_bootmodule = boot_module_find_by_kind(BOOTMOD_RAMDISK);
+    } else {
+        dt_for_each_child_node(domain, node)
+        {
+            if ( dt_device_is_compatible(node, "multiboot,kernel") )
+            {
+                u32 len;
+                const __be32 *val;
+                val = dt_get_property(node, "reg", &len);
+                dt_get_range(&val, node, &kernel_addr, &size);
+                cmdline = dt_get_property(node, "bootargs", &len);
+            }
+            else if ( dt_device_is_compatible(node, "multiboot,ramdisk") )
+            {
+                u32 len;
+                const __be32 *val;
+                val = dt_get_property(node, "reg", &len);
+                dt_get_range(&val, node, &initrd_addr, &size);
+            }
+            else
+                continue;
+        }
+        info->kernel_bootmodule = mod = boot_module_find_by_addr_and_kind(
+                BOOTMOD_KERNEL_DOMAIN, kernel_addr);
+        info->initrd_bootmodule = boot_module_find_by_addr_and_kind(
+                BOOTMOD_RAMDISK_DOMAIN, initrd_addr);
+        info->cmdline = cmdline;
+    }
     if ( !mod || !mod->size )
     {
         printk(XENLOG_ERR "Missing kernel boot module?\n");
         return -ENOENT;
     }
 
-    info->kernel_bootmodule = mod;
-
-    printk("Loading kernel from boot module @ %"PRIpaddr"\n", mod->start);
-
-    info->initrd_bootmodule = boot_module_find_by_kind(BOOTMOD_RAMDISK);
+    printk("Loading DomU kernel from boot module @ %"PRIpaddr"\n",
+           info->kernel_bootmodule->start);
     if ( info->initrd_bootmodule )
         printk("Loading ramdisk from boot module @ %"PRIpaddr"\n",
                info->initrd_bootmodule->start);
diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
index a47aa4c..64b62e7 100644
--- a/xen/arch/arm/kernel.h
+++ b/xen/arch/arm/kernel.h
@@ -63,7 +63,7 @@ struct kernel_info {
  *  ->type
  *  ->load hook, and sets loader specific variables ->{zimage,elf}
  */
-int kernel_probe(struct kernel_info *info);
+int kernel_probe(struct kernel_info *info, struct dt_device_node *domain);
 
 /*
  * Loads the kernel into guest RAM.
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index d4316c7..7739a80 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -244,6 +244,21 @@ struct bootmodule * __init boot_module_find_by_kind(bootmodule_kind kind)
     return NULL;
 }
 
+struct bootmodule * __init boot_module_find_by_addr_and_kind(bootmodule_kind kind,
+                                                             paddr_t start)
+{
+    struct bootmodules *mods = &bootinfo.modules;
+    struct bootmodule *mod;
+    int i;
+    for (i = 0 ; i < mods->nr_mods ; i++ )
+    {
+        mod = &mods->module[i];
+        if ( mod->kind == kind && mod->start == start )
+            return mod;
+    }
+    return NULL;
+}
+
 const char * __init boot_module_kind_as_string(bootmodule_kind kind)
 {
     switch ( kind )
diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
index f8f3eff..d0e23f4 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -82,6 +82,8 @@ const char __init *boot_fdt_cmdline(const void *fdt);
 struct bootmodule *add_boot_module(bootmodule_kind kind,
                                    paddr_t start, paddr_t size);
 struct bootmodule *boot_module_find_by_kind(bootmodule_kind kind);
+struct bootmodule * __init boot_module_find_by_addr_and_kind(bootmodule_kind kind,
+                                                             paddr_t start);
 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	[flat|nested] 92+ messages in thread

* [PATCH v2 12/21] xen/arm: refactor construct_dom0
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (10 preceding siblings ...)
  2018-07-06 23:12 ` [PATCH v2 11/21] xen/arm: probe domU kernels and initrds Stefano Stabellini
@ 2018-07-06 23:12 ` Stefano Stabellini
  2018-07-06 23:12 ` [PATCH v2 13/21] xen/arm: introduce construct_domU Stefano Stabellini
                   ` (10 subsequent siblings)
  22 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:12 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

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

Rename prepare_dtb to prepare_dtb_hwdom to avoid confusion.

No functional changes in this patch.

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

---
Changes in 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 | 124 ++++++++++++++++++++++++--------------------
 1 file changed, 67 insertions(+), 57 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 3ddaffb..ae3b16c 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1392,7 +1392,7 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
     return res;
 }
 
-static int prepare_dtb(struct domain *d, struct kernel_info *kinfo)
+static int prepare_dtb_hwdom(struct domain *d, struct kernel_info *kinfo)
 {
     const p2m_type_t default_p2mt = p2m_mmio_direct_c;
     const void *fdt;
@@ -2124,74 +2124,31 @@ static void __init find_gnttab_region(struct domain *d,
            kinfo->gnttab_start, kinfo->gnttab_start + kinfo->gnttab_size);
 }
 
-int __init construct_dom0(struct domain *d)
+static int __init __construct_domain(struct domain *d, struct kernel_info *kinfo)
 {
-    struct kernel_info kinfo = {};
     struct vcpu *saved_current;
-    int rc, i, cpu;
-
+    int i, cpu;
+    struct cpu_user_regs *regs;
     struct vcpu *v = d->vcpu[0];
-    struct cpu_user_regs *regs = &v->arch.cpu_info->guest_cpu_user_regs;
 
-    /* Sanity! */
-    BUG_ON(d->domain_id != 0);
     BUG_ON(d->vcpu[0] == NULL);
     BUG_ON(v->is_initialised);
 
-    printk("*** LOADING DOMAIN 0 ***\n");
-    if ( dom0_mem <= 0 )
-    {
-        warning_add("PLEASE SPECIFY dom0_mem PARAMETER - USING 512M FOR NOW\n");
-        dom0_mem = MB(512);
-    }
-
-
-    iommu_hwdom_init(d);
-
-    d->max_pages = ~0U;
-
-    kinfo.unassigned_mem = dom0_mem;
-    kinfo.d = d;
-
-    rc = kernel_probe(&kinfo, NULL);
-    if ( rc < 0 )
-        return rc;
+    regs = &v->arch.cpu_info->guest_cpu_user_regs;
 
 #ifdef CONFIG_ARM_64
     /* if aarch32 mode is not supported at EL1 do not allow 32-bit domain */
-    if ( !(cpu_has_el1_32) && kinfo.type == DOMAIN_32BIT )
+    if ( !(cpu_has_el1_32) && kinfo->type == DOMAIN_32BIT )
     {
         printk("Platform does not support 32-bit domain\n");
         return -EINVAL;
     }
-    d->arch.type = kinfo.type;
 
     if ( is_64bit_domain(d) )
         vcpu_switch_to_aarch64_mode(v);
 
 #endif
 
-    kinfo.cmdline = &dom0_cmdline[0];
-    allocate_memory(d, &kinfo);
-    find_gnttab_region(d, &kinfo);
-
-    /* Map extra GIC MMIO, irqs and other hw stuffs to dom0. */
-    rc = gic_map_hwdom_extra_mappings(d);
-    if ( rc < 0 )
-        return rc;
-
-    rc = platform_specific_mapping(d);
-    if ( rc < 0 )
-        return rc;
-
-    if ( acpi_disabled )
-        rc = prepare_dtb(d, &kinfo);
-    else
-        rc = prepare_acpi(d, &kinfo);
-
-    if ( rc < 0 )
-        return rc;
-
     /*
      * The following loads use the domain's p2m and require current to
      * be a vcpu of the domain, temporarily switch
@@ -2204,20 +2161,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) )
     {
@@ -2235,14 +2190,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 */
@@ -2268,6 +2223,61 @@ int __init construct_dom0(struct domain *d)
     return 0;
 }
 
+int __init construct_dom0(struct domain *d)
+{
+    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 = &dom0_cmdline[0];
+    allocate_memory(d, &kinfo);
+    find_gnttab_region(d, &kinfo);
+
+    /* Map extra GIC MMIO, irqs and other hw stuffs to dom0. */
+    rc = gic_map_hwdom_extra_mappings(d);
+    if ( rc < 0 )
+        return rc;
+
+    rc = platform_specific_mapping(d);
+    if ( rc < 0 )
+        return rc;
+
+    d->arch.type = kinfo.type;
+
+    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	[flat|nested] 92+ messages in thread

* [PATCH v2 13/21] xen/arm: introduce construct_domU
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (11 preceding siblings ...)
  2018-07-06 23:12 ` [PATCH v2 12/21] xen/arm: refactor construct_dom0 Stefano Stabellini
@ 2018-07-06 23:12 ` Stefano Stabellini
  2018-07-06 23:12 ` [PATCH v2 14/21] xen/arm: generate a simple device tree for domUs Stefano Stabellini
                   ` (9 subsequent siblings)
  22 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:12 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Similar to construct_dom0, construct_domU creates a barebone DomU guest.

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

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

---
Changes in 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 | 38 ++++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/setup.h |  1 +
 2 files changed, 39 insertions(+)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index ae3b16c..a4bc8fd 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -2223,6 +2223,44 @@ static int __init __construct_domain(struct domain *d, struct kernel_info *kinfo
     return 0;
 }
 
+static int __init construct_domU(struct domain *d, struct dt_device_node *node)
+{
+    struct kernel_info kinfo = {};
+    int rc;
+    u32 mem, vpl011 = 0;
+
+    printk("*** LOADING DOMU ***\n");
+
+    rc = dt_property_read_u32(node, "cpus", &d->max_vcpus);
+    if ( !rc )
+        return -EINVAL;
+
+    rc = dt_property_read_u32(node, "memory", &mem);
+    if ( !rc )
+        return -EINVAL;
+    kinfo.unassigned_mem = (paddr_t)mem << 20;
+
+    dt_property_read_u32(node, "memory", &vpl011);
+
+    d->vcpu = xzalloc_array(struct vcpu *, d->max_vcpus);
+    if ( !d->vcpu )
+        return -ENOMEM;;
+    if ( alloc_vcpu(d, 0, 0) == NULL )
+        return -ENOMEM;
+    d->max_pages = ~0U;
+
+    kinfo.d = d;
+
+    rc = kernel_probe(&kinfo, node);
+    if ( rc < 0 )
+        return rc;
+
+    d->arch.type = kinfo.type;
+    allocate_memory(d, &kinfo);
+
+    return __construct_domain(d, &kinfo);
+}
+
 int __init construct_dom0(struct domain *d)
 {
     struct kernel_info kinfo = {};
diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
index d0e23f4..5ecfe27 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -2,6 +2,7 @@
 #define __ARM_SETUP_H_
 
 #include <public/version.h>
+#include <xen/device_tree.h>
 
 #define MIN_FDT_ALIGN 8
 #define MAX_FDT_SIZE SZ_2M
-- 
1.9.1


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

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

* [PATCH v2 14/21] xen/arm: generate a simple device tree for domUs
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (12 preceding siblings ...)
  2018-07-06 23:12 ` [PATCH v2 13/21] xen/arm: introduce construct_domU Stefano Stabellini
@ 2018-07-06 23:12 ` Stefano Stabellini
  2018-07-06 23:12 ` [PATCH v2 15/21] xen/arm: generate vpl011 node on device tree for domU Stefano Stabellini
                   ` (8 subsequent siblings)
  22 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:12 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

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

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
Changes in 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 | 213 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 213 insertions(+)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index a4bc8fd..48a91ad 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1392,6 +1392,215 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
     return res;
 }
 
+static int make_gic_domU_node(const struct domain *d, void *fdt, int addrcells, int sizecells)
+{
+    int res = 0;
+    int reg_size = addrcells + sizecells;
+    int nr_cells = reg_size * 2;
+    __be32 reg[nr_cells];
+    __be32 *cells;
+
+    switch ( gic_hw_version() )
+    {
+    case GIC_V3:
+        res = fdt_begin_node(fdt, "interrupt-controller@"__stringify(GUEST_GICV3_GICD_BASE));
+        break;
+    case GIC_V2:
+        res = fdt_begin_node(fdt, "interrupt-controller@"__stringify(GUEST_GICD_BASE));
+        break;
+    default:
+        panic("Unsupported GIC version");
+    }
+
+    if ( res )
+        return res;
+
+    res = fdt_property_cell(fdt, "#address-cells", 0);
+    if ( res )
+        return res;
+
+    res = fdt_property_cell(fdt, "#interrupt-cells", 3);
+    if ( res )
+        return res;
+
+    res = fdt_property(fdt, "interrupt-controller", NULL, 0);
+    if ( res )
+        return res;
+
+    switch ( gic_hw_version() )
+    {
+    case GIC_V3:
+    {
+        const uint64_t gicd_base = GUEST_GICV3_GICD_BASE;
+        const uint64_t gicd_size = GUEST_GICV3_GICD_SIZE;
+        const uint64_t gicr0_base = GUEST_GICV3_GICR0_BASE;
+        const uint64_t gicr0_size = GUEST_GICV3_GICR0_SIZE;
+
+        res = fdt_property_string(fdt, "compatible", "arm,gic-v3");
+        if ( res )
+            return res;
+
+        cells = &reg[0];
+        dt_child_set_range(&cells, addrcells, sizecells, gicd_base, gicd_size);
+        dt_child_set_range(&cells, addrcells, sizecells, gicr0_base, gicr0_size);
+        res = fdt_property(fdt, "reg", reg, sizeof(reg));
+        break;
+    }
+    case GIC_V2:
+    {
+        const uint64_t gicd_base = GUEST_GICD_BASE;
+        const uint64_t gicd_size = GUEST_GICD_SIZE;
+        const uint64_t gicc_base = GUEST_GICC_BASE;
+        const uint64_t gicc_size = GUEST_GICC_SIZE;
+
+        res = fdt_property_string(fdt, "compatible", "arm,gic-400");
+        if ( res )
+            return res;
+
+        cells = &reg[0];
+        dt_child_set_range(&cells, addrcells, sizecells, gicd_base, gicd_size);
+        dt_child_set_range(&cells, addrcells, sizecells, gicc_base, gicc_size);
+        break;
+    }
+    default:
+        break;
+    }
+
+    res = fdt_property(fdt, "reg", reg, sizeof(reg));
+    if (res)
+        return res;
+
+    res = fdt_property_cell(fdt, "linux,phandle", GUEST_PHANDLE_GIC);
+    if (res)
+        return res;
+
+    res = fdt_property_cell(fdt, "phandle", GUEST_PHANDLE_GIC);
+    if (res)
+        return res;
+
+    res = fdt_end_node(fdt);
+
+    return res;
+}
+
+static int make_timer_domU_node(const struct domain *d, void *fdt)
+{
+    int res;
+    gic_interrupt_t intrs[3];
+
+    res = fdt_begin_node(fdt, "timer");
+    if ( res )
+        return res;
+
+    if (!is_64bit_domain(d))
+    {
+        res = fdt_property_string(fdt, "compatible", "arm,armv7-timer");
+        if ( res )
+            return res;
+    } else {
+        res = fdt_property_string(fdt, "compatible", "arm,armv8-timer");
+        if ( res )
+            return res;
+    }
+
+    set_interrupt_ppi(intrs[0], GUEST_TIMER_PHYS_S_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
+    set_interrupt_ppi(intrs[1], GUEST_TIMER_PHYS_NS_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
+    set_interrupt_ppi(intrs[2], GUEST_TIMER_VIRT_PPI, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
+
+    res = fdt_property(fdt, "interrupts", intrs, sizeof (intrs[0]) * 3);
+    if ( res )
+        return res;
+
+    res = fdt_property_cell(fdt, "interrupt-parent",
+                            GUEST_PHANDLE_GIC);
+    if (res)
+        return res;
+
+    res = fdt_end_node(fdt);
+    return res;
+}
+
+/*
+ * The max size for DT is 2MB. However, the generated DT is small, 4KB
+ * are enough for now, but we might have to increase it in the feature.
+ */
+#define DOMU_DTB_SIZE 4096
+static int prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
+{
+    int addrcells, sizecells;
+    int ret;
+
+    addrcells = dt_child_n_addr_cells(dt_host);
+    sizecells = dt_child_n_size_cells(dt_host);
+
+    kinfo->fdt = xmalloc_bytes(DOMU_DTB_SIZE);
+    if ( kinfo->fdt == NULL )
+        return -ENOMEM;
+
+    ret = fdt_create(kinfo->fdt, DOMU_DTB_SIZE);
+    if ( ret < 0 )
+        goto err;
+
+    ret = fdt_finish_reservemap(kinfo->fdt);
+    if ( ret < 0 )
+        goto err;
+
+    ret = fdt_begin_node(kinfo->fdt, "/");
+    if ( ret < 0 )
+        goto err;
+
+    ret = fdt_property_cell(kinfo->fdt, "#address-cells", addrcells);
+    if ( ret )
+        goto err;
+
+    ret = fdt_property_cell(kinfo->fdt, "#size-cells", sizecells);
+    if ( ret )
+        goto err;
+
+    ret = make_chosen_node(kinfo);
+    if ( ret )
+        goto err;
+
+    ret = make_hypervisor_node(d, kinfo, addrcells, sizecells);
+    if ( ret )
+        goto err;
+
+    ret = make_psci_node(kinfo->fdt, NULL);
+    if ( ret )
+        goto err;
+
+    ret = make_cpus_node(d, kinfo->fdt, NULL);
+    if ( ret )
+        goto err;
+
+    ret = make_memory_node(d, kinfo->fdt, addrcells, sizecells, kinfo);
+    if ( ret )
+        goto err;
+
+    ret = make_gic_domU_node(d, kinfo->fdt, addrcells, sizecells);
+    if ( ret )
+        goto err;
+
+    ret = make_timer_domU_node(d, kinfo->fdt);
+    if ( ret )
+        goto err;
+
+    ret = fdt_end_node(kinfo->fdt);
+    if ( ret < 0 )
+        goto err;
+
+    ret = fdt_finish(kinfo->fdt);
+    if ( ret < 0 )
+        goto err;
+
+    return 0;
+
+  err:
+    printk("Device tree generation failed (%d).\n", ret);
+    xfree(kinfo->fdt);
+    return -EINVAL;
+}
+
 static int prepare_dtb_hwdom(struct domain *d, struct kernel_info *kinfo)
 {
     const p2m_type_t default_p2mt = p2m_mmio_direct_c;
@@ -2258,6 +2467,10 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
     d->arch.type = kinfo.type;
     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	[flat|nested] 92+ messages in thread

* [PATCH v2 15/21] xen/arm: generate vpl011 node on device tree for domU
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (13 preceding siblings ...)
  2018-07-06 23:12 ` [PATCH v2 14/21] xen/arm: generate a simple device tree for domUs Stefano Stabellini
@ 2018-07-06 23:12 ` Stefano Stabellini
  2018-07-12 18:14   ` Julien Grall
  2018-07-06 23:12 ` [PATCH v2 16/21] xen/arm: introduce a union in vpl011 Stefano Stabellini
                   ` (7 subsequent siblings)
  22 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:12 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

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

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

Enable vpl011 conditionally if the user requested it.

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

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
Changes in 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 | 90 +++++++++++++++++++++++++++++++++++++--------
 1 file changed, 75 insertions(+), 15 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 48a91ad..718be48 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -519,17 +519,17 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo,
 
 typedef __be32 gic_interrupt_t[3];
 
-static void set_interrupt_ppi(gic_interrupt_t interrupt, unsigned int irq,
-                              unsigned int cpumask, unsigned int level)
+static void set_interrupt(gic_interrupt_t interrupt, unsigned int irq,
+                          unsigned int cpumask, unsigned int level)
 {
     __be32 *cells = interrupt;
+    int 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);
 }
 
@@ -648,7 +648,7 @@ static int 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;
@@ -924,15 +924,15 @@ static int 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 )
@@ -1503,9 +1503,9 @@ static int 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 )
@@ -1520,12 +1520,63 @@ static int make_timer_domU_node(const struct domain *d, void *fdt)
     return res;
 }
 
+#ifdef CONFIG_SBSA_VUART_CONSOLE
+static int make_vpl011_uart_node(const struct domain *d, void *fdt,
+                                 int addrcells, int sizecells)
+{
+    int res;
+    gic_interrupt_t intr;
+    int reg_size = addrcells + sizecells;
+    int nr_cells = reg_size;
+    __be32 reg[nr_cells];
+    __be32 *cells;
+
+    res = fdt_begin_node(fdt, "sbsa-pl011");
+    if ( res )
+        return res;
+
+    res = fdt_property_string(fdt, "compatible", "arm,sbsa-uart");
+    if ( res )
+        return res;
+
+    cells = &reg[0];
+    dt_child_set_range(&cells, addrcells, sizecells, GUEST_PL011_BASE,
+                       GUEST_PL011_SIZE);
+    if ( res )
+        return res;
+    res = fdt_property(fdt, "reg", reg, sizeof(reg));
+    if ( res )
+        return res;
+
+    set_interrupt(intr, GUEST_VPL011_SPI, 0xf, DT_IRQ_TYPE_LEVEL_HIGH);
+
+    res = fdt_property(fdt, "interrupts", intr, sizeof (intr));
+    if ( res )
+        return res;
+
+    res = fdt_property_cell(fdt, "interrupt-parent",
+                            GUEST_PHANDLE_GIC);
+    if ( res )
+        return res;
+
+    /* Use a default baud rate of 115200. */
+    fdt_property_u32(fdt, "current-speed", 115200);
+
+    res = fdt_end_node(fdt);
+    if ( res )
+        return res;
+
+    return 0;
+}
+#endif
+
 /*
  * The max size for DT is 2MB. However, the generated DT is small, 4KB
  * are enough for now, but we might have to increase it in the feature.
  */
 #define DOMU_DTB_SIZE 4096
-static int prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
+static int prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo,
+                            bool vpl011)
 {
     int addrcells, sizecells;
     int ret;
@@ -1585,6 +1636,15 @@ static int prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
     if ( ret )
         goto err;
 
+#ifdef CONFIG_SBSA_VUART_CONSOLE
+    if ( vpl011 )
+    {
+        ret = make_vpl011_uart_node(d, kinfo->fdt, addrcells, sizecells);
+        if ( ret )
+            goto err;
+    }
+#endif
+
     ret = fdt_end_node(kinfo->fdt);
     if ( ret < 0 )
         goto err;
@@ -2467,7 +2527,7 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
     d->arch.type = kinfo.type;
     allocate_memory(d, &kinfo);
 
-    rc = prepare_dtb_domU(d, &kinfo);
+    rc = prepare_dtb_domU(d, &kinfo, vpl011);
     if ( rc < 0 )
         return rc;
 
-- 
1.9.1


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

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

* [PATCH v2 16/21] xen/arm: introduce a union in vpl011
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (14 preceding siblings ...)
  2018-07-06 23:12 ` [PATCH v2 15/21] xen/arm: generate vpl011 node on device tree for domU Stefano Stabellini
@ 2018-07-06 23:12 ` Stefano Stabellini
  2018-07-06 23:12 ` [PATCH v2 17/21] xen/arm: refactor vpl011_data_avail Stefano Stabellini
                   ` (6 subsequent siblings)
  22 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:12 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

Introduce a union in struct vpl011 to contain the console ring members.
A later patch will add another member of the union with a small ring
structure.

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
Changes in v2:
- new patch
---
 xen/arch/arm/vpl011.c        | 20 ++++++++++----------
 xen/include/asm-arm/vpl011.h |  8 ++++++--
 2 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index a281eab..33fcaa0 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->ring.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->ring.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->ring.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->ring.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->ring.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->ring.ring_page,
+                                  &vpl011->ring.ring_buf);
     if ( rc < 0 )
         goto out;
 
@@ -495,7 +495,7 @@ out2:
     vgic_free_virq(d, GUEST_VPL011_SPI);
 
 out1:
-    destroy_ring_for_helper(&vpl011->ring_buf, vpl011->ring_page);
+    destroy_ring_for_helper(&vpl011->ring.ring_buf, vpl011->ring.ring_page);
 
 out:
     return rc;
@@ -505,11 +505,11 @@ void domain_vpl011_deinit(struct domain *d)
 {
     struct vpl011 *vpl011 = &d->arch.vpl011;
 
-    if ( !vpl011->ring_buf )
+    if ( !vpl011->ring.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->ring.ring_buf, vpl011->ring.ring_page);
 }
 
 /*
diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
index db95ff8..c3d375b 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;
+        } ring;
+    };
     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	[flat|nested] 92+ messages in thread

* [PATCH v2 17/21] xen/arm: refactor vpl011_data_avail
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (15 preceding siblings ...)
  2018-07-06 23:12 ` [PATCH v2 16/21] xen/arm: introduce a union in vpl011 Stefano Stabellini
@ 2018-07-06 23:12 ` Stefano Stabellini
  2018-07-24  9:58   ` Julien Grall
  2018-07-06 23:12 ` [PATCH v2 18/21] xen/arm: Allow vpl011 to be used by DomU Stefano Stabellini
                   ` (5 subsequent siblings)
  22 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:12 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

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

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

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

diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index 33fcaa0..e75957f 100644
--- a/xen/arch/arm/vpl011.c
+++ b/xen/arch/arm/vpl011.c
@@ -34,6 +34,12 @@
 #include <asm/vgic-emul.h>
 #include <asm/vpl011.h>
 
+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);
+
 /*
  * Since pl011 registers are 32-bit registers, all registers
  * are handled similarly allowing 8-bit, 16-bit and 32-bit
@@ -378,30 +384,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->ring.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 +399,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 +416,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 +434,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->ring.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	[flat|nested] 92+ messages in thread

* [PATCH v2 18/21] xen/arm: Allow vpl011 to be used by DomU
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (16 preceding siblings ...)
  2018-07-06 23:12 ` [PATCH v2 17/21] xen/arm: refactor vpl011_data_avail Stefano Stabellini
@ 2018-07-06 23:12 ` Stefano Stabellini
  2018-07-24 11:00   ` Julien Grall
  2018-07-06 23:12 ` [PATCH v2 19/21] xen/arm: introduce create_domUs Stefano Stabellini
                   ` (4 subsequent siblings)
  22 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:12 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

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

Call domain_vpl011_init during construct_domU if vpl011 is enabled.

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

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
---
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  |  10 ++-
 xen/arch/arm/vpl011.c        | 185 ++++++++++++++++++++++++++++++++++++++-----
 xen/include/asm-arm/vpl011.h |  10 +++
 3 files changed, 182 insertions(+), 23 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 718be48..d7e9040 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -2531,7 +2531,15 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
     if ( rc < 0 )
         return rc;
 
-    return __construct_domain(d, &kinfo);
+    rc = __construct_domain(d, &kinfo);
+    if ( rc < 0 )
+        return rc;
+
+#ifdef CONFIG_SBSA_VUART_CONSOLE
+    if ( vpl011 )
+        rc = domain_vpl011_init(d, NULL);
+#endif
+    return rc;
 }
 
 int __init construct_dom0(struct domain *d)
diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index e75957f..d4aab64 100644
--- a/xen/arch/arm/vpl011.c
+++ b/xen/arch/arm/vpl011.c
@@ -83,6 +83,111 @@ static void vpl011_update_interrupt_status(struct domain *d)
 #endif
 }
 
+void vpl011_rx_char(struct domain *d, char c)
+{
+    unsigned long flags;
+    struct vpl011 *vpl011 = &d->arch.vpl011;
+    struct xencons_in *intf = vpl011->inring;
+    XENCONS_RING_IDX in_cons, in_prod, in_fifo_level;
+
+    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 + 1;
+
+    in_fifo_level = xencons_queued(in_prod,
+                                   in_cons,
+                                   sizeof(intf->in));
+
+    vpl011_data_avail(d, in_fifo_level, sizeof(intf->in), 0, 1024);
+    VPL011_UNLOCK(d, flags);
+}
+
+static void vpl011_write_data_noring(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);
+}
+
+static uint8_t vpl011_read_data_inring(struct domain *d)
+{
+    unsigned long flags;
+    uint8_t data = 0;
+    struct vpl011 *vpl011 = &d->arch.vpl011;
+    struct xencons_in *intf = vpl011->inring;
+    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;
@@ -246,7 +351,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->ring_enable )
+            *r = vreg_reg32_extract(vpl011_read_data(d), info);
+        else
+            *r = vreg_reg32_extract(vpl011_read_data_inring(d), info);
         return 1;
 
     case RSR:
@@ -331,7 +439,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->ring_enable )
+            vpl011_write_data(v->domain, data);
+        else
+            vpl011_write_data_noring(v->domain, data);
         return 1;
     }
 
@@ -476,27 +587,47 @@ int domain_vpl011_init(struct domain *d, struct vpl011_init_info *info)
     if ( vpl011->ring.ring_buf )
         return -EINVAL;
 
-    /* Map the guest PFN to Xen address space. */
-    rc =  prepare_ring_for_helper(d,
-                                  gfn_x(info->gfn),
-                                  &vpl011->ring.ring_page,
-                                  &vpl011->ring.ring_buf);
-    if ( rc < 0 )
-        goto out;
+    /*
+     * info is NULL for domUs started by Xen at boot time, with no
+     * corresponding userspace component in dom0
+     */
+    if ( info != NULL )
+    {
+        vpl011->ring_enable = true;
+
+        /* Map the guest PFN to Xen address space. */
+        rc =  prepare_ring_for_helper(d,
+                gfn_x(info->gfn),
+                &vpl011->ring.ring_page,
+                &vpl011->ring.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->ring_enable = false;
+
+        vpl011->inring = xzalloc(struct xencons_in);
+        if ( vpl011->inring == 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);
 
@@ -509,7 +640,10 @@ out2:
     vgic_free_virq(d, GUEST_VPL011_SPI);
 
 out1:
-    destroy_ring_for_helper(&vpl011->ring.ring_buf, vpl011->ring.ring_page);
+    if ( vpl011->ring_enable )
+        destroy_ring_for_helper(&vpl011->ring.ring_buf, vpl011->ring.ring_page);
+    else
+        xfree(vpl011->inring);
 
 out:
     return rc;
@@ -519,11 +653,18 @@ void domain_vpl011_deinit(struct domain *d)
 {
     struct vpl011 *vpl011 = &d->arch.vpl011;
 
-    if ( !vpl011->ring.ring_buf )
-        return;
+    if ( vpl011->ring_enable )
+    {
+        if ( !vpl011->ring.ring_buf )
+            return;
 
-    free_xen_event_channel(d, vpl011->evtchn);
-    destroy_ring_for_helper(&vpl011->ring.ring_buf, vpl011->ring.ring_page);
+        free_xen_event_channel(d, vpl011->evtchn);
+        destroy_ring_for_helper(&vpl011->ring.ring_buf, vpl011->ring.ring_page);
+    }
+    else
+    {
+        xfree(vpl011->inring);
+    }
 }
 
 /*
diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
index c3d375b..be43abf 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>
 
@@ -30,12 +31,19 @@
 
 #define SBSA_UART_FIFO_SIZE 32
 
+struct xencons_in {
+    char in[1024];
+    XENCONS_RING_IDX in_cons, in_prod;
+};
+
 struct vpl011 {
+    bool ring_enable;
     union {
         struct {
             void *ring_buf;
             struct page_info *ring_page;
         } ring;
+        struct xencons_in *inring;
     };
     uint32_t    uartfr;         /* Flag register */
     uint32_t    uartcr;         /* Control register */
@@ -57,6 +65,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(struct domain *d, char c);
 #else
 static inline int domain_vpl011_init(struct domain *d,
                                      struct vpl011_init_info *info)
@@ -65,6 +74,7 @@ static inline int domain_vpl011_init(struct domain *d,
 }
 
 static inline void domain_vpl011_deinit(struct domain *d) { }
+static inline void vpl011_rx_char(struct domain *d, char c) { }
 #endif
 #endif  /* _VPL011_H_ */
 
-- 
1.9.1


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

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

* [PATCH v2 19/21] xen/arm: introduce create_domUs
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (17 preceding siblings ...)
  2018-07-06 23:12 ` [PATCH v2 18/21] xen/arm: Allow vpl011 to be used by DomU Stefano Stabellini
@ 2018-07-06 23:12 ` Stefano Stabellini
  2018-07-16 16:10   ` Jan Beulich
  2018-07-24 13:53   ` Julien Grall
  2018-07-06 23:12 ` [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM Stefano Stabellini
                   ` (3 subsequent siblings)
  22 siblings, 2 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:12 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, sstabellini, andrii_anisov, andrew.cooper3,
	xen-devel, jbeulich

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

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

Introduce a simple global variable named max_init_domid to keep track of
the initial allocated domids.

Move the discard_initial_modules after DomUs have been built

Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
CC: andrew.cooper3@citrix.com
CC: jbeulich@suse.com
---
Changes in v2:
- coding style
- set nr_spis to 32
- introduce create_domUs
---
 xen/arch/arm/domain_build.c | 38 +++++++++++++++++++++++++++++++++++---
 xen/arch/arm/setup.c        |  8 +++++++-
 xen/include/asm-arm/setup.h |  3 +++
 xen/include/asm-x86/setup.h |  2 ++
 4 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index d7e9040..9f58002 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>
@@ -2542,6 +2543,39 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
     return rc;
 }
 
+void __init create_domUs(void)
+{
+    struct dt_device_node *node;
+    struct dt_device_node *chosen = dt_find_node_by_name(dt_host, "chosen");
+    if ( chosen != NULL )
+    {
+        dt_for_each_child_node(chosen, node)
+        {
+            struct domain *d;
+            struct xen_domctl_createdomain d_cfg = {};
+
+            if ( !dt_device_is_compatible(node, "xen,domain") )
+                continue;
+
+            d_cfg.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
+            d_cfg.arch.nr_spis = 32;
+
+            d = domain_create(max_init_domid++, &d_cfg);
+            if ( IS_ERR(d) )
+                panic("Error creating domU");
+
+            d->is_privileged = 0;
+            d->is_console = 1;
+            d->target = NULL;
+
+            if ( construct_domU(d, node) != 0 )
+                printk("Could not set up DOMU guest OS");
+
+            domain_unpause_by_systemcontroller(d);
+        }
+    }
+}
+
 int __init construct_dom0(struct domain *d)
 {
     struct kernel_info kinfo = {};
@@ -2592,9 +2626,7 @@ int __init construct_dom0(struct domain *d)
         return rc;
 
 
-    rc = __construct_domain(d, &kinfo);
-    discard_initial_modules();
-    return rc;
+    return __construct_domain(d, &kinfo);
 }
 
 /*
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 7739a80..0b08af2 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -64,6 +64,8 @@ static unsigned long opt_xenheap_megabytes __initdata;
 integer_param("xenheap_megabytes", opt_xenheap_megabytes);
 #endif
 
+domid_t __read_mostly max_init_domid = 0;
+
 static __used void init_done(void)
 {
     free_init_memory();
@@ -863,7 +865,7 @@ void __init start_xen(unsigned long boot_phys_offset,
     dom0_cfg.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
     dom0_cfg.arch.nr_spis = gic_number_lines() - 32;
 
-    dom0 = domain_create(0, &dom0_cfg);
+    dom0 = domain_create(max_init_domid++, &dom0_cfg);
     if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
             panic("Error creating domain 0");
 
@@ -889,6 +891,10 @@ void __init start_xen(unsigned long boot_phys_offset,
 
     domain_unpause_by_systemcontroller(dom0);
 
+    create_domUs();
+
+    discard_initial_modules();
+
     /* Switch on to the dynamically allocated stack for the idle vcpu
      * since the static one we're running on is about to be freed. */
     memcpy(idle_vcpu[0]->arch.cpu_info, get_cpu_info(),
diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
index 5ecfe27..21b9729 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -56,6 +56,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);
@@ -72,6 +74,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 19232af..2fb9529 100644
--- a/xen/include/asm-x86/setup.h
+++ b/xen/include/asm-x86/setup.h
@@ -73,4 +73,6 @@ extern bool opt_dom0_shadow;
 #endif
 extern bool dom0_pvh;
 
+#define max_init_domid (1)
+
 #endif
-- 
1.9.1


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

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

* [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (18 preceding siblings ...)
  2018-07-06 23:12 ` [PATCH v2 19/21] xen/arm: introduce create_domUs Stefano Stabellini
@ 2018-07-06 23:12 ` Stefano Stabellini
  2018-07-16 16:19   ` Jan Beulich
                     ` (2 more replies)
  2018-07-06 23:12 ` [PATCH v2 21/21] xen/arm: split domain_build.c Stefano Stabellini
                   ` (2 subsequent siblings)
  22 siblings, 3 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:12 UTC (permalink / raw)
  To: julien.grall
  Cc: Stefano Stabellini, sstabellini, andrii_anisov, George.Dunlap,
	andrew.cooper3, ian.jackson, xen-devel, tim, jbeulich, wei.liu2

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

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 v2:
- only call vpl011_rx_char if the vpl011 has been initialized
---
 xen/drivers/char/console.c | 50 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 35 insertions(+), 15 deletions(-)

diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 0f05369..d590bc0 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -31,10 +31,13 @@
 #include <xen/early_printk.h>
 #include <xen/warning.h>
 #include <xen/pv_console.h>
+#include <asm/setup.h>
 
 #ifdef CONFIG_X86
 #include <xen/consoled.h>
 #include <asm/guest.h>
+#else
+#include <asm/vpl011.h>
 #endif
 
 /* console: comma-separated list of console outputs. */
@@ -389,29 +392,49 @@ static void dump_console_ring_key(unsigned char key)
     free_xenheap_pages(buf, order);
 }
 
-/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
+/*
+ * CTRL-<switch_char> switches input direction between Xen, Dom0 and
+ * DomUs.
+ */
 #define switch_code (opt_conswitch[0]-'a'+1)
-static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain 0. */
+static int __read_mostly xen_rx = 1; /* 1 => input passed to domain 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]);
+    xen_rx++;
+    if ( xen_rx == max_init_domid + 1 )
+        xen_rx = 0;
+
+    if ( !xen_rx )
+        printk("*** Serial input xen_rx=%d -> %s", xen_rx, "Xen");
+    else
+        printk("*** Serial input xen_rx=%d -> DOM%d", xen_rx, xen_rx - 1);
+
     if ( switch_code )
-        printk(" (type 'CTRL-%c' three times to switch input to %s)",
-               opt_conswitch[0], input_str[!xen_rx]);
+        printk(" (type 'CTRL-%c' three times to switch input)",
+               opt_conswitch[0]);
     printk("\n");
 }
 
 static void __serial_rx(char c, struct cpu_user_regs *regs)
 {
-    if ( xen_rx )
+    if ( xen_rx == 0 )
         return handle_keypress(c, regs);
 
-    /* Deliver input to guest buffer, unless it is already full. */
-    if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
-        serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
+    if ( xen_rx == 1 )
+    {
+        /* Deliver input to guest buffer, unless it is already full. */
+        if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
+            serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
+    }
+#ifdef CONFIG_ARM
+    else
+    {
+        struct domain *d = get_domain_by_id(xen_rx - 1);
+        if ( !d->arch.vpl011.ring_enable && d->arch.vpl011.inring != NULL )
+            vpl011_rx_char(d, c);
+    }
+#endif
     /* Always notify the guest: prevents receive path from getting stuck. */
     send_global_virq(VIRQ_CONSOLE);
 
@@ -923,7 +946,7 @@ void __init console_endboot(void)
      * a useful 'how to switch' message.
      */
     if ( opt_conswitch[1] == 'x' )
-        xen_rx = !xen_rx;
+        xen_rx = 0;
 
     register_keyhandler('w', dump_console_ring_key,
                         "synchronously dump console ring buffer (dmesg)", 0);
@@ -933,9 +956,6 @@ void __init console_endboot(void)
                             "decrease log level threshold", 0);
     register_irq_keyhandler('G', &do_toggle_guest,
                             "toggle host/guest log level adjustment", 0);
-
-    /* Serial input is directed to DOM0 by default. */
-    switch_serial_input();
 }
 
 int __init console_has(const char *device)
-- 
1.9.1


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

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

* [PATCH v2 21/21] xen/arm: split domain_build.c
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (19 preceding siblings ...)
  2018-07-06 23:12 ` [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM Stefano Stabellini
@ 2018-07-06 23:12 ` Stefano Stabellini
  2018-07-12 18:18 ` [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Julien Grall
  2018-07-23 17:14 ` Andrii Anisov
  22 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-06 23:12 UTC (permalink / raw)
  To: julien.grall; +Cc: Stefano Stabellini, sstabellini, andrii_anisov, xen-devel

domain_build.c is too large.

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

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

diff --git a/xen/arch/arm/acpi/Makefile b/xen/arch/arm/acpi/Makefile
index 23963f8..ac0804b 100644
--- a/xen/arch/arm/acpi/Makefile
+++ b/xen/arch/arm/acpi/Makefile
@@ -1,2 +1,3 @@
 obj-y += lib.o
+obj-y += acpi_dt_build.o
 obj-y += boot.init.o
diff --git a/xen/arch/arm/acpi/acpi_dt_build.c b/xen/arch/arm/acpi/acpi_dt_build.c
new file mode 100644
index 0000000..19f70a1
--- /dev/null
+++ b/xen/arch/arm/acpi/acpi_dt_build.c
@@ -0,0 +1,588 @@
+#include <xen/mm.h>
+#include <xen/sched.h>
+#include <xen/acpi.h>
+#include <xen/event.h>
+#include <xen/iocap.h>
+#include <xen/device_tree.h>
+#include <xen/libfdt/libfdt.h>
+#include <xen/irq.h>
+#include <asm/irq.h>
+#include <acpi/actables.h>
+#include "acpi_dt_build.h"
+#include "../kernel.h"
+
+/* Override macros from asm/page.h to make them work with mfn_t */
+#undef virt_to_mfn
+#define virt_to_mfn(va) _mfn(__virt_to_mfn(va))
+
+#define ACPI_DOM0_FDT_MIN_SIZE 4096
+
+static int 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 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 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 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 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 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 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 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 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 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 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 estimate_acpi_efi_size(struct domain *d, struct kernel_info *kinfo)
+{
+    size_t efi_size, acpi_size, madt_size;
+    u64 addr;
+    struct acpi_table_rsdp *rsdp_tbl;
+    struct acpi_table_header *table;
+
+    efi_size = estimate_efi_size(kinfo->mem.nr_banks);
+
+    acpi_size = ROUNDUP(sizeof(struct acpi_table_fadt), 8);
+    acpi_size += ROUNDUP(sizeof(struct acpi_table_stao), 8);
+
+    madt_size = gic_get_hwdom_madt_size(d);
+    acpi_size += ROUNDUP(madt_size, 8);
+
+    addr = acpi_os_get_root_pointer();
+    if ( !addr )
+    {
+        printk("Unable to get acpi root pointer\n");
+        return -EINVAL;
+    }
+
+    rsdp_tbl = acpi_os_map_memory(addr, sizeof(struct acpi_table_rsdp));
+    if ( !rsdp_tbl )
+    {
+        printk("Unable to map RSDP table\n");
+        return -EINVAL;
+    }
+
+    table = acpi_os_map_memory(rsdp_tbl->xsdt_physical_address,
+                               sizeof(struct acpi_table_header));
+    acpi_os_unmap_memory(rsdp_tbl, sizeof(struct acpi_table_rsdp));
+    if ( !table )
+    {
+        printk("Unable to map XSDT table\n");
+        return -EINVAL;
+    }
+
+    /* Add place for STAO table in XSDT table */
+    acpi_size += ROUNDUP(table->length + sizeof(u64), 8);
+    acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
+
+    acpi_size += ROUNDUP(sizeof(struct acpi_table_rsdp), 8);
+    d->arch.efi_acpi_len = PAGE_ALIGN(ROUNDUP(efi_size, 8)
+                                      + ROUNDUP(acpi_size, 8));
+
+    return 0;
+}
+
+int prepare_acpi(struct domain *d, struct kernel_info *kinfo)
+{
+    int rc = 0;
+    int order;
+    struct membank tbl_add[TBL_MMAX] = {};
+
+    rc = estimate_acpi_efi_size(d, kinfo);
+    if ( rc != 0 )
+        return rc;
+
+    order = get_order_from_bytes(d->arch.efi_acpi_len);
+    d->arch.efi_acpi_table = alloc_xenheap_pages(order, 0);
+    if ( d->arch.efi_acpi_table == NULL )
+    {
+        printk("unable to allocate memory!\n");
+        return -ENOMEM;
+    }
+    memset(d->arch.efi_acpi_table, 0, d->arch.efi_acpi_len);
+
+    /*
+     * For ACPI, Dom0 doesn't use kinfo->gnttab_start to get the grant table
+     * region. So we use it as the ACPI table mapped address. Also it needs to
+     * check if the size of grant table region is enough for those ACPI tables.
+     */
+    d->arch.efi_acpi_gpa = kinfo->gnttab_start;
+    if ( kinfo->gnttab_size < d->arch.efi_acpi_len )
+    {
+        printk("The grant table region is not enough to fit the ACPI tables!\n");
+        return -EINVAL;
+    }
+
+    rc = acpi_create_fadt(d, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_create_madt(d, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_create_stao(d, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_create_xsdt(d, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_create_rsdp(d, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    acpi_map_other_tables(d);
+    acpi_create_efi_system_table(d, tbl_add);
+    acpi_create_efi_mmap_table(d, &kinfo->mem, tbl_add);
+
+    /* Map the EFI and ACPI tables to Dom0 */
+    rc = map_regions_p2mt(d,
+                          gaddr_to_gfn(d->arch.efi_acpi_gpa),
+                          PFN_UP(d->arch.efi_acpi_len),
+                          virt_to_mfn(d->arch.efi_acpi_table),
+                          p2m_mmio_direct_c);
+    if ( rc != 0 )
+    {
+        printk(XENLOG_ERR "Unable to map EFI/ACPI table 0x%"PRIx64
+               " - 0x%"PRIx64" in domain %d\n",
+               d->arch.efi_acpi_gpa & PAGE_MASK,
+               PAGE_ALIGN(d->arch.efi_acpi_gpa + d->arch.efi_acpi_len) - 1,
+               d->domain_id);
+        return rc;
+    }
+
+    /*
+     * Flush the cache for this region, otherwise DOM0 may read wrong data when
+     * the cache is disabled.
+     */
+    clean_and_invalidate_dcache_va_range(d->arch.efi_acpi_table,
+                                         d->arch.efi_acpi_len);
+
+    rc = create_acpi_dtb(kinfo, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_route_spis(d);
+    if ( rc != 0 )
+        return rc;
+
+    rc = acpi_iomem_deny_access(d);
+    if ( rc != 0 )
+        return rc;
+
+    /*
+     * All PPIs have been registered, allocate the event channel
+     * interrupts.
+     */
+    evtchn_allocate(d);
+
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/acpi/acpi_dt_build.h b/xen/arch/arm/acpi/acpi_dt_build.h
new file mode 100644
index 0000000..08e7aab
--- /dev/null
+++ b/xen/arch/arm/acpi/acpi_dt_build.h
@@ -0,0 +1,32 @@
+#ifndef __ARCH_ARM_ACPI_ACPI_DT_BUILD_H__
+#define __ARCH_ARM_ACPI_ACPI_DT_BUILD_H__
+
+#include <xen/sched.h>
+#include "../kernel.h"
+
+int map_irq_to_domain(struct domain *d, unsigned int irq,
+                      bool need_mapping, const char *devname);
+int make_chosen_node(const struct kernel_info *kinfo);
+void evtchn_allocate(struct domain *d);
+
+#ifndef CONFIG_ACPI
+static inline int prepare_acpi(struct domain *d, struct kernel_info *kinfo)
+{
+    /* Only booting with ACPI will hit here */
+    BUG();
+    return -EINVAL;
+}
+#else
+int prepare_acpi(struct domain *d, struct kernel_info *kinfo);
+#endif
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 9f58002..01aa0cf 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -24,6 +24,7 @@
 
 #include <xen/irq.h>
 #include <xen/grant_table.h>
+#include "acpi/acpi_dt_build.h"
 #include "kernel.h"
 
 static unsigned int __initdata opt_dom0_max_vcpus;
@@ -599,8 +600,6 @@ static int make_memory_node(const struct domain *d,
     return res;
 }
 
-static void evtchn_allocate(struct domain *d);
-
 static int make_hypervisor_node(struct domain *d,
                                 const struct kernel_info *kinfo,
                                 int addrcells, int sizecells)
@@ -958,7 +957,7 @@ static int 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 make_chosen_node(const struct kernel_info *kinfo)
+int make_chosen_node(const struct kernel_info *kinfo)
 {
     int res;
     const char *bootargs = NULL;
@@ -999,8 +998,8 @@ static int make_chosen_node(const struct kernel_info *kinfo)
     return res;
 }
 
-static int map_irq_to_domain(struct domain *d, unsigned int irq,
-                             bool need_mapping, const char *devname)
+int map_irq_to_domain(struct domain *d, unsigned int irq,
+                      bool need_mapping, const char *devname)
 
 {
     int res;
@@ -1700,577 +1699,6 @@ static int prepare_dtb_hwdom(struct domain *d, struct kernel_info *kinfo)
     return -EINVAL;
 }
 
-#ifdef CONFIG_ACPI
-#define ACPI_DOM0_FDT_MIN_SIZE 4096
-
-static int 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 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 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 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 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 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 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 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 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 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 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 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 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 prepare_acpi(struct domain *d, struct kernel_info *kinfo)
-{
-    /* Only booting with ACPI will hit here */
-    BUG();
-    return -EINVAL;
-}
-#endif
 static void dtb_load(struct kernel_info *kinfo)
 {
     unsigned long left;
@@ -2343,7 +1771,7 @@ static void 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 evtchn_allocate(struct domain *d)
+void evtchn_allocate(struct domain *d)
 {
     int res;
     u64 val;
-- 
1.9.1


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

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

* Re: [PATCH v2 01/21] xen/arm: rename get_11_allocation_size to get_allocation_size
  2018-07-06 23:11 ` [PATCH v2 01/21] xen/arm: rename get_11_allocation_size to get_allocation_size Stefano Stabellini
@ 2018-07-09 12:55   ` Julien Grall
  2018-07-11 20:09     ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-09 12:55 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 07/07/18 00:11, Stefano Stabellini wrote:
> ... and remove the BUG_ON(!dom0_11_mapping) in allocate_memory.

Please rebase your work on staging. This code has changed a bit since 
Xen 4.11-rc6.

> A follow-up patch will make the function work with non 1:1 mapped
> guests.
> 
> No functional changes.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> 
> ---
> Changes in v2:
> - new patch
> ---
>   xen/arch/arm/domain_build.c | 22 ++++++++--------------
>   1 file changed, 8 insertions(+), 14 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 11cdf05..182e3d5 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -79,7 +79,7 @@ struct vcpu *__init alloc_dom0_vcpu0(struct domain *dom0)
>       return alloc_vcpu(dom0, 0, 0);
>   }
>   
> -static unsigned int get_11_allocation_size(paddr_t size)
> +static unsigned int get_allocation_size(paddr_t size)
>   {
>       /*
>        * get_order_from_bytes returns the order greater than or equal to
> @@ -251,21 +251,15 @@ static void 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;
>       unsigned int bits;
>   
> -    /*
> -     * TODO: Implement memory bank allocation when DOM0 is not direct
> -     * mapped
> -     */
> -    BUG_ON(!dom0_11_mapping);

New code is using is_domain_direct_mapped(d).

> -
> -    printk("Allocating 1:1 mappings totalling %ldMB for dom0:\n",
> +    printk("Allocating 1:1 mappings totalling %ldMB for dom%d:\n",

This is not mention i nthe command message.

At the same time, please fix the typo s/totalling/totaling/

>              /* Don't want format this as PRIpaddr (16 digit hex) */
> -           (unsigned long)(kinfo->unassigned_mem >> 20));
> +           (unsigned long)(kinfo->unassigned_mem >> 20), d->domain_id);
>   
>       kinfo->mem.nr_banks = 0;
>   
> @@ -303,7 +297,7 @@ static void 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);
> @@ -314,7 +308,7 @@ static void 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;
>               }
> @@ -334,7 +328,7 @@ static void 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;
>               }
> @@ -349,7 +343,7 @@ static void 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 )
> 

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

* Re: [PATCH v2 02/21] xen/arm: make allocate_memory work for non 1:1 mapped guests
  2018-07-06 23:11 ` [PATCH v2 02/21] xen/arm: make allocate_memory work for non 1:1 mapped guests Stefano Stabellini
@ 2018-07-09 13:43   ` Julien Grall
  2018-07-09 23:02     ` Stefano Stabellini
  2018-07-09 13:58   ` Julien Grall
  2018-07-23 18:01   ` Andrii Anisov
  2 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-09 13:43 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 07/07/18 00:11, Stefano Stabellini wrote:
> Extend allocate_memory to work for non 1:1 mapped domUs. Specifically,
> memory allocated for domU will be mapped into the domU pseudo-physical
> address space at the appropriate addresses according to the guest memory
> map: GUEST_RAM0_BASE and GUEST_RAM1_BASE.
> 
> To do that, insert_11_bank has been extended to deal with non-dom0
> mappings starting from GUEST_RAM0_BASE. insert_11_bank has been renamed
> to insert_bank.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> 
> ---
> Changes in v2:
> - new patch
> ---
>   xen/arch/arm/domain_build.c | 57 ++++++++++++++++++++++++++++++++++-----------
>   1 file changed, 44 insertions(+), 13 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 182e3d5..2a6619a 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -97,27 +97,51 @@ static unsigned int get_allocation_size(paddr_t size)
>    * Returns false if the memory would be below bank 0 or we have run
>    * out of banks. In this case it will free the pages.
>    */
> -static bool insert_11_bank(struct domain *d,
> -                           struct kernel_info *kinfo,
> -                           struct page_info *pg,
> -                           unsigned int order)
> +static bool insert_bank(struct domain *d,
> +                        struct kernel_info *kinfo,
> +                        struct page_info *pg,
> +                        unsigned int order,
> +                        bool map_11)
>   {
> -    int res, i;
> +    int res, i, nr_mem_banks = map_11 ? NR_MEM_BANKS : 2;

nr_mem_banks should be unsigned. I also would drop "mem_" to shorten a 
bit the name.

>       mfn_t smfn;
>       paddr_t start, size;
> +    struct membank *bank;
>   
>       smfn = page_to_mfn(pg);
>       start = mfn_to_maddr(smfn);

The new code is pretty horrible to read. Can you please add some 
comments to help understanding it?

Here is already an example where you set start to MFN. But then override 
after with none comment to understand why.

Also, this code as always assumed MFN == GFN so start was making sense. 
Now, you re-purpose it to just the guest-physical address. So more 
likely you want to rework the code a bit.

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

I am not sure why map_11 would mean DomU? I don't see any reason to not 
allow that for Dom0. Note that I am not asking to do it, just having 
clearer name.

> +    {
> +        start = GUEST_RAM0_BASE;
> +        if ( kinfo->mem.nr_banks > 0 )
> +        {
> +            for( i = 0; i < kinfo->mem.nr_banks; i++ )
> +            {
> +                bank = &kinfo->mem.bank[i];
> +                start = bank->start + bank->size;
> +            }
> +            if ( bank->start == GUEST_RAM0_BASE &&
> +                    start + size > (GUEST_RAM0_BASE + GUEST_RAM0_SIZE) )

The indentation looks wrong.

> +                start = GUEST_RAM1_BASE;
> +            if ( bank->start == GUEST_RAM1_BASE &&
> +                    start + size > (GUEST_RAM1_BASE + GUEST_RAM1_SIZE) )
> +            {
> +                D11PRINT("Allocation of domain memory exceeds max amount\n");

This looks quite strange to use D11PRINT here as this related to 
direct-domain mapped.

> +                goto fail;
> +            }
> +        }
> +    }
>   
> -    D11PRINT("Allocated %#"PRIpaddr"-%#"PRIpaddr" (%ldMB/%ldMB, order %d)\n",
> +    D11PRINT("Allocated %#"PRIpaddr"-%#"PRIpaddr":%#"PRIpaddr"-%#"PRIpaddr" (%ldMB/%ldMB, order %d)\n",
> +             mfn_to_maddr(smfn), mfn_to_maddr(smfn) + size,
>                start, start + size,
>                1UL << (order + PAGE_SHIFT - 20),
>                /* Don't want format this as PRIpaddr (16 digit hex) */
>                (unsigned long)(kinfo->unassigned_mem >> 20),
>                order);
>   
> -    if ( kinfo->mem.nr_banks > 0 &&
> +    if ( map_11 && kinfo->mem.nr_banks > 0 &&

Why do you drop that check? It should be harmless for non-direct mapped 
domain.

>            size < MB(128) && >            start + size < kinfo->mem.bank[0].start )
>       {
> @@ -125,7 +149,7 @@ static bool insert_11_bank(struct domain *d,
>           goto fail;
>       }
>   
> -    res = guest_physmap_add_page(d, _gfn(mfn_x(smfn)), smfn, order);
> +    res = guest_physmap_add_page(d, gaddr_to_gfn(start), smfn, order);
>       if ( res )
>           panic("Failed map pages to DOM0: %d", res);
>   
> @@ -141,7 +165,7 @@ static bool insert_11_bank(struct domain *d,
>   
>       for( i = 0; i < kinfo->mem.nr_banks; i++ )
>       {
> -        struct membank *bank = &kinfo->mem.bank[i];
> +        bank = &kinfo->mem.bank[i];
>   
>           /* If possible merge new memory into the start of the bank */
>           if ( bank->start == start+size )
> @@ -164,7 +188,7 @@ static bool insert_11_bank(struct domain *d,
>            * could have inserted the memory into/before we would already
>            * have done so, so this must be the right place.
>            */
> -        if ( start + size < bank->start && kinfo->mem.nr_banks < NR_MEM_BANKS )
> +        if ( start + size < bank->start && kinfo->mem.nr_banks < nr_mem_banks )
>           {
>               memmove(bank + 1, bank,
>                       sizeof(*bank) * (kinfo->mem.nr_banks - i));
> @@ -175,7 +199,7 @@ static bool insert_11_bank(struct domain *d,
>           }
>       }
>   
> -    if ( i == kinfo->mem.nr_banks && kinfo->mem.nr_banks < NR_MEM_BANKS )
> +    if ( i == kinfo->mem.nr_banks && kinfo->mem.nr_banks < nr_mem_banks )
>       {
>           struct membank *bank = &kinfo->mem.bank[kinfo->mem.nr_banks];
>   
> @@ -253,6 +277,7 @@ static void allocate_memory(struct domain *d, struct kernel_info *kinfo)
>       struct page_info *pg;
>       unsigned int order = get_allocation_size(kinfo->unassigned_mem);
>       int i;
> +    bool hwdom = d->domain_id == 0;

You should use is_hardware_domain(...).

>   
>       bool lowmem = true;
>       unsigned int bits;
> @@ -263,6 +288,12 @@ static void allocate_memory(struct domain *d, struct kernel_info *kinfo)
>   
>       kinfo->mem.nr_banks = 0;
>   
> +    if ( !hwdom )
> +    {
> +        lowmem = false;
> +        goto got_bank0;
> +    }

Can you explain why you need this?

> +
>       /*
>        * First try and allocate the largest thing we can as low as
>        * possible to be bank 0.
> @@ -274,7 +305,7 @@ static void allocate_memory(struct domain *d, struct kernel_info *kinfo)
>               pg = alloc_domheap_pages(d, order, MEMF_bits(bits));
>               if ( pg != NULL )
>               {
> -                if ( !insert_11_bank(d, kinfo, pg, order) )
> +                if ( !insert_bank(d, kinfo, pg, order, hwdom) )
>                       BUG(); /* Cannot fail for first bank */
>   
>                   goto got_bank0;
> @@ -319,7 +350,7 @@ static void allocate_memory(struct domain *d, struct kernel_info *kinfo)
>               break;
>           }
>   
> -        if ( !insert_11_bank(d, kinfo, pg, order) )
> +        if ( !insert_bank(d, kinfo, pg, order, hwdom) )
>           {
>               if ( kinfo->mem.nr_banks == NR_MEM_BANKS )
>                   /* Nothing more we can do. */
> 

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

* Re: [PATCH v2 03/21] xen: allow console_io hypercalls from certain DomUs
  2018-07-06 23:11 ` [PATCH v2 03/21] xen: allow console_io hypercalls from certain DomUs Stefano Stabellini
@ 2018-07-09 13:48   ` Julien Grall
  2018-07-17 20:05     ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-09 13:48 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, andrii_anisov, George.Dunlap, andrew.cooper3,
	ian.jackson, xen-devel, tim, jbeulich, wei.liu2, dgdegra

Hi,

On 07/07/18 00:11, Stefano Stabellini wrote:
> Introduce an is_console option to allow certain classes of domUs to use
> the Xen console. Specifically, it will be used to give console access to
> all domUs started from Xen from information on device tree.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> 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 v2:
> - introduce is_console
> - remove #ifdefs
> ---
>   xen/include/xen/sched.h | 2 ++
>   xen/include/xsm/dummy.h | 2 ++
>   xen/xsm/flask/hooks.c   | 5 ++++-
>   3 files changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
> index 99d2af2..d66cec0 100644
> --- a/xen/include/xen/sched.h
> +++ b/xen/include/xen/sched.h
> @@ -379,6 +379,8 @@ struct domain
>       bool             auto_node_affinity;
>       /* Is this guest fully privileged (aka dom0)? */
>       bool             is_privileged;
> +    /* Can this guest access the Xen console? */
> +    bool             is_console;
>       /* Is this a xenstore domain (not dom0)? */
>       bool             is_xenstore;
>       /* Domain's VCPUs are pinned 1:1 to physical CPUs? */
> diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
> index ff6b2db..3888817 100644
> --- a/xen/include/xsm/dummy.h
> +++ b/xen/include/xsm/dummy.h
> @@ -230,6 +230,8 @@ static XSM_INLINE int xsm_memory_stat_reservation(XSM_DEFAULT_ARG struct domain
>   static XSM_INLINE int xsm_console_io(XSM_DEFAULT_ARG struct domain *d, int cmd)
>   {
>       XSM_ASSERT_ACTION(XSM_OTHER);
> +    if ( d->is_console )
> +        return xsm_default_action(XSM_HOOK, d, NULL);

I will let Daniel commenting on this change. However ...

>   #ifdef CONFIG_VERBOSE_DEBUG
>       if ( cmd == CONSOLEIO_write )
>           return xsm_default_action(XSM_HOOK, d, NULL);
> diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
> index 78bc326..2551e4e 100644
> --- a/xen/xsm/flask/hooks.c
> +++ b/xen/xsm/flask/hooks.c
> @@ -443,7 +443,10 @@ static int flask_console_io(struct domain *d, int cmd)
>           return avc_unknown_permission("console_io", cmd);
>       }
>   
> -    return domain_has_xen(d, perm);
> +    if ( !d->is_console )
> +        return domain_has_xen(d, perm);
> +    else
> +        return 0;

... I don't think this change is correct. When a policy is used, the 
user is free to define what is the behavior. With your solution, you 
impose the console access even if the user didn't to not give the 
permission.

>   }
>   
>   static int flask_profile(struct domain *d, int op)
> 

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

* Re: [PATCH v2 02/21] xen/arm: make allocate_memory work for non 1:1 mapped guests
  2018-07-06 23:11 ` [PATCH v2 02/21] xen/arm: make allocate_memory work for non 1:1 mapped guests Stefano Stabellini
  2018-07-09 13:43   ` Julien Grall
@ 2018-07-09 13:58   ` Julien Grall
  2018-07-09 23:10     ` Stefano Stabellini
  2018-07-23 18:01   ` Andrii Anisov
  2 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-09 13:58 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel



On 07/07/18 00:11, Stefano Stabellini wrote:
> @@ -263,6 +288,12 @@ static void allocate_memory(struct domain *d, struct kernel_info *kinfo)

I forgot to mention that very likely you want to update the big comment 
on top of this function.

Cheers,
-- 
Julien Grall

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

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

* Re: [PATCH v2 04/21] xen/arm: move a few DT related defines to public/device_tree_defs.h
  2018-07-06 23:11 ` [PATCH v2 04/21] xen/arm: move a few DT related defines to public/device_tree_defs.h Stefano Stabellini
@ 2018-07-09 13:59   ` Julien Grall
  0 siblings, 0 replies; 92+ messages in thread
From: Julien Grall @ 2018-07-09 13:59 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: ian.jackson, Stefano Stabellini, andrii_anisov, wei.liu2, xen-devel

Hi Stefano,

Thank you, this change looks better to me. Few comments below.

On 07/07/18 00:11, Stefano Stabellini wrote:
> Move a few constants defined by libxl_arm.c to
> xen/include/public/device_tree_defs.h, so that they can be used from Xen
> and libxl. Prepend GUEST_ to avoid conflicts.
> 
> Move the DT_IRQ_TYPE* definitions from libxl_arm.c to
> public/device_tree_defs.h. Use them in Xen where appropriate.
> 
> Re-define the existing Xen internal IRQ_TYPEs as DT_IRQ_TYPEs: they
> already happen to be the same, let make it clear.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> CC: wei.liu2@citrix.com
> CC: ian.jackson@eu.citrix.com
> ---
> Changes in v2:
> - introduce DT_IRQ_TYPE_* definitions in device_tree_guest.h
> - prepend GUEST_ to other definitions moved to device_tree_guest.h
> - redefine IRQ_TYPE_* as  DT_IRQ_TYPE_*
> - use DT_IRQ_TYPE_* in Xen when dealing with DT
> ---
>   tools/libxl/libxl_arm.c               | 59 ++++++++++-------------------------
>   xen/arch/arm/domain_build.c           |  8 ++---
>   xen/include/asm-arm/irq.h             | 16 ++++++++++
>   xen/include/public/device_tree_defs.h | 39 +++++++++++++++++++++++
>   xen/include/xen/device_tree.h         | 33 +++-----------------
>   5 files changed, 80 insertions(+), 75 deletions(-)
>   create mode 100644 xen/include/public/device_tree_defs.h
> 
> diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
> index 8af9f6f..01ce2ea 100644
> --- a/tools/libxl/libxl_arm.c
> +++ b/tools/libxl/libxl_arm.c
> @@ -7,23 +7,7 @@
>   #include <stdbool.h>
>   #include <libfdt.h>
>   #include <assert.h>
> -
> -/**
> - * IRQ line type.
> - * DT_IRQ_TYPE_NONE            - default, unspecified type
> - * DT_IRQ_TYPE_EDGE_RISING     - rising edge triggered
> - * DT_IRQ_TYPE_EDGE_FALLING    - falling edge triggered
> - * DT_IRQ_TYPE_EDGE_BOTH       - rising and falling edge triggered
> - * DT_IRQ_TYPE_LEVEL_HIGH      - high level triggered
> - * DT_IRQ_TYPE_LEVEL_LOW       - low level triggered
> - */
> -#define DT_IRQ_TYPE_NONE           0x00000000
> -#define DT_IRQ_TYPE_EDGE_RISING    0x00000001
> -#define DT_IRQ_TYPE_EDGE_FALLING   0x00000002
> -#define DT_IRQ_TYPE_EDGE_BOTH                           \
> -    (DT_IRQ_TYPE_EDGE_FALLING | DT_IRQ_TYPE_EDGE_RISING)
> -#define DT_IRQ_TYPE_LEVEL_HIGH     0x00000004
> -#define DT_IRQ_TYPE_LEVEL_LOW      0x00000008
> +#include <xen/device_tree_defs.h>
>   
>   static const char *gicv_to_string(libxl_gic_version gic_version)
>   {
> @@ -165,18 +149,9 @@ static struct arch_info {
>       {"xen-3.0-aarch64", "arm,armv8-timer", "arm,armv8" },
>   };
>   
> -/*
> - * The device tree compiler (DTC) is allocating the phandle from 1 to
> - * onwards. Reserve a high value for the GIC phandle.
> - */
> -#define PHANDLE_GIC (65000)
> -
>   typedef uint32_t be32;
>   typedef be32 gic_interrupt[3];
>   
> -#define ROOT_ADDRESS_CELLS 2
> -#define ROOT_SIZE_CELLS 2
> -
>   #define PROP_INITRD_START "linux,initrd-start"
>   #define PROP_INITRD_END "linux,initrd-end"
>   
> @@ -252,7 +227,7 @@ static int fdt_property_interrupts(libxl__gc *gc, void *fdt,
>       res = fdt_property(fdt, "interrupts", intr, sizeof (intr[0]) * num_irq);
>       if (res) return res;
>   
> -    res = fdt_property_cell(fdt, "interrupt-parent", PHANDLE_GIC);
> +    res = fdt_property_cell(fdt, "interrupt-parent", GUEST_PHANDLE_GIC);
>       if (res) return res;
>   
>       return 0;
> @@ -298,13 +273,13 @@ static int make_root_properties(libxl__gc *gc,
>                                 "xen,xenvm");
>       if (res) return res;
>   
> -    res = fdt_property_cell(fdt, "interrupt-parent", PHANDLE_GIC);
> +    res = fdt_property_cell(fdt, "interrupt-parent", GUEST_PHANDLE_GIC);
>       if (res) return res;
>   
> -    res = fdt_property_cell(fdt, "#address-cells", ROOT_ADDRESS_CELLS);
> +    res = fdt_property_cell(fdt, "#address-cells", GUEST_ROOT_ADDRESS_CELLS);
>       if (res) return res;
>   
> -    res = fdt_property_cell(fdt, "#size-cells", ROOT_SIZE_CELLS);
> +    res = fdt_property_cell(fdt, "#size-cells", GUEST_ROOT_SIZE_CELLS);
>       if (res) return res;
>   
>       return 0;
> @@ -346,7 +321,7 @@ static int make_chosen_node(libxl__gc *gc, void *fdt, bool ramdisk,
>                                     "multiboot,module");
>           if (res) return res;
>   
> -        res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
> +        res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
>                                   1, 0, 0);
>           if (res) return res;
>   
> @@ -450,7 +425,7 @@ static int make_memory_nodes(libxl__gc *gc, void *fdt,
>           res = fdt_property_string(fdt, "device_type", "memory");
>           if (res) return res;
>   
> -        res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
> +        res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
>                                   1, 0, 0);
>           if (res) return res;
>   
> @@ -486,16 +461,16 @@ static int make_gicv2_node(libxl__gc *gc, void *fdt,
>       res = fdt_property(fdt, "interrupt-controller", NULL, 0);
>       if (res) return res;
>   
> -    res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
> +    res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
>                               2,
>                               gicd_base, gicd_size,
>                               gicc_base, gicc_size);
>       if (res) return res;
>   
> -    res = fdt_property_cell(fdt, "linux,phandle", PHANDLE_GIC);
> +    res = fdt_property_cell(fdt, "linux,phandle", GUEST_PHANDLE_GIC);
>       if (res) return res;
>   
> -    res = fdt_property_cell(fdt, "phandle", PHANDLE_GIC);
> +    res = fdt_property_cell(fdt, "phandle", GUEST_PHANDLE_GIC);
>       if (res) return res;
>   
>       res = fdt_end_node(fdt);
> @@ -528,16 +503,16 @@ static int make_gicv3_node(libxl__gc *gc, void *fdt)
>       res = fdt_property(fdt, "interrupt-controller", NULL, 0);
>       if (res) return res;
>   
> -    res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
> +    res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
>                               2,
>                               gicd_base, gicd_size,
>                               gicr0_base, gicr0_size);
>       if (res) return res;
>   
> -    res = fdt_property_cell(fdt, "linux,phandle", PHANDLE_GIC);
> +    res = fdt_property_cell(fdt, "linux,phandle", GUEST_PHANDLE_GIC);
>       if (res) return res;
>   
> -    res = fdt_property_cell(fdt, "phandle", PHANDLE_GIC);
> +    res = fdt_property_cell(fdt, "phandle", GUEST_PHANDLE_GIC);
>       if (res) return res;
>   
>       res = fdt_end_node(fdt);
> @@ -593,7 +568,7 @@ static int make_hypervisor_node(libxl__gc *gc, void *fdt,
>       if (res) return res;
>   
>       /* reg 0 is grant table space */
> -    res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
> +    res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
>                               1,GUEST_GNTTAB_BASE, GUEST_GNTTAB_SIZE);
>       if (res) return res;
>   
> @@ -626,7 +601,7 @@ static int make_vpl011_uart_node(libxl__gc *gc, void *fdt,
>       res = fdt_property_compat(gc, fdt, 1, "arm,sbsa-uart");
>       if (res) return res;
>   
> -    res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
> +    res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
>                               1,
>                               GUEST_PL011_BASE, GUEST_PL011_SIZE);
>       if (res) return res;
> @@ -1027,12 +1002,12 @@ static void finalise_one_node(libxl__gc *gc, void *fdt, const char *uname,
>           LOG(DEBUG, "Nopping out placeholder node %s", name);
>           fdt_nop_node(fdt, node);
>       } else {
> -        uint32_t regs[ROOT_ADDRESS_CELLS+ROOT_SIZE_CELLS];
> +        uint32_t regs[GUEST_ROOT_ADDRESS_CELLS+GUEST_ROOT_SIZE_CELLS];
>           be32 *cells = &regs[0];
>   
>           LOG(DEBUG, "Populating placeholder node %s", name);
>   
> -        set_range(&cells, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS, base, size);
> +        set_range(&cells, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS, base, size);
>   
>           res = fdt_setprop_inplace(fdt, node, "reg", regs, sizeof(regs));
>           assert(!res);
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 2a6619a..ae3ebc5 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -658,7 +658,7 @@ static int make_hypervisor_node(struct domain *d,
>        *  - All CPUs
>        *  TODO: Handle properly the cpumask;
>        */
> -    set_interrupt_ppi(intr, d->arch.evtchn_irq, 0xf, IRQ_TYPE_LEVEL_LOW);
> +    set_interrupt_ppi(intr, d->arch.evtchn_irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
>       res = fdt_property_interrupts(fdt, &intr, 1);
>       if ( res )
>           return res;
> @@ -934,15 +934,15 @@ static int make_timer_node(const struct domain *d, void *fdt,
>   
>       irq = timer_get_irq(TIMER_PHYS_SECURE_PPI);
>       dt_dprintk("  Secure interrupt %u\n", irq);
> -    set_interrupt_ppi(intrs[0], irq, 0xf, IRQ_TYPE_LEVEL_LOW);
> +    set_interrupt_ppi(intrs[0], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
>   
>       irq = timer_get_irq(TIMER_PHYS_NONSECURE_PPI);
>       dt_dprintk("  Non secure interrupt %u\n", irq);
> -    set_interrupt_ppi(intrs[1], irq, 0xf, IRQ_TYPE_LEVEL_LOW);
> +    set_interrupt_ppi(intrs[1], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
>   
>       irq = timer_get_irq(TIMER_VIRT_PPI);
>       dt_dprintk("  Virt interrupt %u\n", irq);
> -    set_interrupt_ppi(intrs[2], irq, 0xf, IRQ_TYPE_LEVEL_LOW);
> +    set_interrupt_ppi(intrs[2], irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW);
>   
>       res = fdt_property_interrupts(fdt, intrs, 3);
>       if ( res )
> diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
> index 9d55e9b..e45d574 100644
> --- a/xen/include/asm-arm/irq.h
> +++ b/xen/include/asm-arm/irq.h
> @@ -2,6 +2,22 @@
>   #define _ASM_HW_IRQ_H
>   
>   #include <xen/device_tree.h>
> +#include <public/device_tree_defs.h>
> +
> +/*
> + * These defines correspond to the Xen internal representation of the
> + * IRQ types. We choose to make them the same as the existing device
> + * tree definitions for convenience.
> + */
> +#define IRQ_TYPE_NONE           DT_IRQ_TYPE_NONE
> +#define IRQ_TYPE_EDGE_RISING    DT_IRQ_TYPE_EDGE_RISING
> +#define IRQ_TYPE_EDGE_FALLING   DT_IRQ_TYPE_EDGE_FALLING
> +#define IRQ_TYPE_EDGE_BOTH      DT_IRQ_TYPE_EDGE_BOTH
> +#define IRQ_TYPE_LEVEL_HIGH     DT_IRQ_TYPE_LEVEL_HIGH
> +#define IRQ_TYPE_LEVEL_LOW      DT_IRQ_TYPE_LEVEL_LOW
> +#define IRQ_TYPE_LEVEL_MASK     DT_IRQ_TYPE_LEVEL_MASK
> +#define IRQ_TYPE_SENSE_MASK     DT_IRQ_TYPE_SENSE_MASK
> +#define IRQ_TYPE_INVALID        DT_IRQ_TYPE_INVALID
>   
>   #define NR_VECTORS 256 /* XXX */
>   
> diff --git a/xen/include/public/device_tree_defs.h b/xen/include/public/device_tree_defs.h
> new file mode 100644
> index 0000000..476b04d
> --- /dev/null
> +++ b/xen/include/public/device_tree_defs.h
> @@ -0,0 +1,39 @@
> +#ifndef __XEN_DEVICE_TREE_DEFS_H__
> +#define __XEN_DEVICE_TREE_DEFS_H__

This should only be exposed for Xen and Tools:

#if defined(__XEN__) || defined(__XEN_TOOLS__)

> +
> +/*
> + * The device tree compiler (DTC) is allocating the phandle from 1 to
> + * onwards. Reserve a high value for the GIC phandle.
> + */
> +#define GUEST_PHANDLE_GIC (65000)
> +
> +#define GUEST_ROOT_ADDRESS_CELLS 2
> +#define GUEST_ROOT_SIZE_CELLS 2
> +
> +/**
> + * IRQ line type.
> + *
> + * DT_IRQ_TYPE_NONE            - default, unspecified type
> + * DT_IRQ_TYPE_EDGE_RISING     - rising edge triggered
> + * DT_IRQ_TYPE_EDGE_FALLING    - falling edge triggered
> + * DT_IRQ_TYPE_EDGE_BOTH       - rising and falling edge triggered
> + * DT_IRQ_TYPE_LEVEL_HIGH      - high level triggered
> + * DT_IRQ_TYPE_LEVEL_LOW       - low level triggered
> + * DT_IRQ_TYPE_LEVEL_MASK      - Mask to filter out the level bits
> + * DT_IRQ_TYPE_SENSE_MASK      - Mask for all the above bits
> + * DT_IRQ_TYPE_INVALID         - Use to initialize the type
> + */
> +#define DT_IRQ_TYPE_NONE           0x00000000
> +#define DT_IRQ_TYPE_EDGE_RISING    0x00000001
> +#define DT_IRQ_TYPE_EDGE_FALLING   0x00000002
> +#define DT_IRQ_TYPE_EDGE_BOTH                           \
> +    (DT_IRQ_TYPE_EDGE_FALLING | DT_IRQ_TYPE_EDGE_RISING)
> +#define DT_IRQ_TYPE_LEVEL_HIGH     0x00000004
> +#define DT_IRQ_TYPE_LEVEL_LOW      0x00000008
> +#define DT_IRQ_TYPE_LEVEL_MASK                          \
> +    (DT_IRQ_TYPE_LEVEL_LOW | DT_IRQ_TYPE_LEVEL_HIGH)
> +#define DT_IRQ_TYPE_SENSE_MASK     0x0000000f
> +
> +#define DT_IRQ_TYPE_INVALID        0x00000010
> +
> +#endif
> diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
> index 0aecbe0..638b926 100644
> --- a/xen/include/xen/device_tree.h
> +++ b/xen/include/xen/device_tree.h
> @@ -13,6 +13,7 @@
>   #include <asm/byteorder.h>
>   #include <asm/device.h>
>   #include <public/xen.h>
> +#include <public/device_tree_defs.h>
>   #include <xen/kernel.h>
>   #include <xen/init.h>
>   #include <xen/string.h>
> @@ -114,35 +115,9 @@ struct dt_phandle_args {
>   };
>   
>   /**
> - * IRQ line type.
> - *
> - * IRQ_TYPE_NONE            - default, unspecified type
> - * IRQ_TYPE_EDGE_RISING     - rising edge triggered
> - * IRQ_TYPE_EDGE_FALLING    - falling edge triggered
> - * IRQ_TYPE_EDGE_BOTH       - rising and falling edge triggered
> - * IRQ_TYPE_LEVEL_HIGH      - high level triggered
> - * IRQ_TYPE_LEVEL_LOW       - low level triggered
> - * IRQ_TYPE_LEVEL_MASK      - Mask to filter out the level bits
> - * IRQ_TYPE_SENSE_MASK      - Mask for all the above bits
> - * IRQ_TYPE_INVALID         - Use to initialize the type
> - */
> -#define IRQ_TYPE_NONE           0x00000000
> -#define IRQ_TYPE_EDGE_RISING    0x00000001
> -#define IRQ_TYPE_EDGE_FALLING   0x00000002
> -#define IRQ_TYPE_EDGE_BOTH                           \
> -    (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
> -#define IRQ_TYPE_LEVEL_HIGH     0x00000004
> -#define IRQ_TYPE_LEVEL_LOW      0x00000008
> -#define IRQ_TYPE_LEVEL_MASK                          \
> -    (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)
> -#define IRQ_TYPE_SENSE_MASK     0x0000000f
> -
> -#define IRQ_TYPE_INVALID        0x00000010
> -
> -/**
>    * dt_irq - describe an IRQ in the device tree
>    * @irq: IRQ number
> - * @type: IRQ type (see IRQ_TYPE_*)
> + * @type: IRQ type (see DT_IRQ_TYPE_*)
>    *
>    * This structure is returned when an interrupt is mapped.
>    */
> @@ -151,12 +126,12 @@ struct dt_irq {
>       unsigned int type;
>   };
>   
> -/* If type == IRQ_TYPE_NONE, assume we use level triggered */
> +/* If type == DT_IRQ_TYPE_NONE, assume we use level triggered */
>   static inline bool_t dt_irq_is_level_triggered(const struct dt_irq *irq)
>   {
>       unsigned int type = irq->type;
>   
> -    return (type & IRQ_TYPE_LEVEL_MASK) || (type == IRQ_TYPE_NONE);
> +    return (type & DT_IRQ_TYPE_LEVEL_MASK) || (type == DT_IRQ_TYPE_NONE);
>   }
>   
>   /**
> 

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

* Re: [PATCH v2 05/21] xen/arm: extend device tree based multiboot protocol
  2018-07-06 23:12 ` [PATCH v2 05/21] xen/arm: extend device tree based multiboot protocol Stefano Stabellini
@ 2018-07-09 14:07   ` Julien Grall
  2018-07-13 22:41     ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-09 14:07 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi,

On 07/07/18 00:12, Stefano Stabellini wrote:
> 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 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 | 108 ++++++++++++++++++++++++++++++++++
>   1 file changed, 108 insertions(+)
> 
> diff --git a/docs/misc/arm/device-tree/booting.txt b/docs/misc/arm/device-tree/booting.txt
> index ce2d0dc..5c3b8da 100644
> --- a/docs/misc/arm/device-tree/booting.txt
> +++ b/docs/misc/arm/device-tree/booting.txt
> @@ -119,3 +119,111 @@ 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"
> +    For dom0: "xen,domain", "xen,initial-domain"

Looking briefly at the code, I don't see any support of 
"xen,initial-domain". Did I miss anything?

But, it is a bit strange to put that in compatible. Shouldn't this be a 
property?


> +
> +- memory
> +
> +    An integer specifying the amount of megabytes of RAM to allocate to
> +    the guest.

I would define this a KB. With Dom0less it would be easy to spawn a 
guest with less than a MB of memory. What matter is the amount of memory 
should be page-aligned.

> +
> +- cpus
> +
> +    An integer specifying the number of vcpus to allocate to the guest.
> +
> +- vpl011
> +
> +    An integer to enable/disable a virtual pl011 for the guest to use.

The interrupt is a bit confusing here. What value will enable? What 
value will disable?

I think you can just make an empty property.

> +
> +- #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 = <128>;
> +        cpus = <2>;
> +        vpl011 = <1>;
> +
> +        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 = <64>;
> +        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>;
> +        };
> +    };
> +};
> 

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

* Re: [PATCH v2 06/21] xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node
  2018-07-06 23:12 ` [PATCH v2 06/21] xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node Stefano Stabellini
@ 2018-07-09 14:11   ` Julien Grall
  2018-07-09 21:51     ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-09 14:11 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi,

On 07/07/18 00:12, Stefano Stabellini wrote:
> In order to make make_memory_node and make_hypervisor_node more
> reusable, do not pass them dt_host. As they only use it to calculate
> addrcells and sizecells, pass addrcells and sizecells directly.
> 
> In make_hypervisor_node, assume that evtchn_irq has already been
> allocated. Move the evtchn_allocate call to handle_node.

This needs a bit more explanation why. But I think this belongs to a 
separate patch.

> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> 
> ---
> Changes in v2:
> - add blank line
> - move evtchn_allocate to handle_node
> ---
>   xen/arch/arm/domain_build.c   | 36 ++++++++++++++++++++----------------
>   xen/common/device_tree.c      |  6 +++---
>   xen/include/xen/device_tree.h |  2 +-
>   3 files changed, 24 insertions(+), 20 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index ae3ebc5..c349ce4 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -558,11 +558,11 @@ static int fdt_property_interrupts(void *fdt, gic_interrupt_t *intr,
>   
>   static int make_memory_node(const struct domain *d,
>                               void *fdt,
> -                            const struct dt_device_node *parent,
> +                            int addrcells, int sizecells,
>                               const struct kernel_info *kinfo)
>   {
>       int res, i;
> -    int reg_size = dt_child_n_addr_cells(parent) + dt_child_n_size_cells(parent);
> +    int reg_size = addrcells + sizecells;
>       int nr_cells = reg_size*kinfo->mem.nr_banks;
>       __be32 reg[nr_cells];
>       __be32 *cells;
> @@ -588,7 +588,7 @@ static int make_memory_node(const struct domain *d,
>           dt_dprintk("  Bank %d: %#"PRIx64"->%#"PRIx64"\n",
>                      i, start, start + size);
>   
> -        dt_child_set_range(&cells, parent, start, size);
> +        dt_child_set_range(&cells, addrcells, sizecells, start, size);
>       }
>   
>       res = fdt_property(fdt, "reg", reg, sizeof(reg));
> @@ -604,7 +604,7 @@ static void evtchn_allocate(struct domain *d);
>   
>   static int make_hypervisor_node(struct domain *d,
>                                   const struct kernel_info *kinfo,
> -                                const struct dt_device_node *parent)
> +                                int addrcells, int sizecells)
>   {
>       const char compat[] =
>           "xen,xen-"__stringify(XEN_VERSION)"."__stringify(XEN_SUBVERSION)"\0"
> @@ -613,9 +613,6 @@ static int make_hypervisor_node(struct domain *d,
>       gic_interrupt_t intr;
>       __be32 *cells;
>       int res;
> -    /* Convenience alias */
> -    int addrcells = dt_child_n_addr_cells(parent);
> -    int sizecells = dt_child_n_size_cells(parent);
>       void *fdt = kinfo->fdt;
>   
>       dt_dprintk("Create hypervisor node\n");
> @@ -640,19 +637,14 @@ static int make_hypervisor_node(struct domain *d,
>   
>       /* reg 0 is grant table space */
>       cells = &reg[0];
> -    dt_child_set_range(&cells, parent, kinfo->gnttab_start, kinfo->gnttab_size);
> +    dt_child_set_range(&cells, addrcells, sizecells,
> +                       kinfo->gnttab_start, kinfo->gnttab_size);
>       res = fdt_property(fdt, "reg", reg,
>                          dt_cells_to_size(addrcells + sizecells));
>       if ( res )
>           return res;
>   
>       /*
> -     * It is safe to allocate the event channel here because all the
> -     * PPIs used by the hardware domain have been registered.
> -     */
> -    evtchn_allocate(d);

I would replace this with a BUG_ON(evtchn != 0).

> -
> -    /*
>        * Interrupt event channel upcall:
>        *  - Active-low level-sensitive
>        *  - All CPUs
> @@ -1317,11 +1309,23 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
>   
>       if ( node == dt_host )
>       {
> +        int addrcells = dt_child_n_addr_cells(node);
> +        int sizecells = dt_child_n_size_cells(node);
> +
> +
> +        /*
> +         *      * It is safe to allocate the event channel here
> +         *      because all the
> +         *           * PPIs used by the hardware domain have been
> +         *           registered.
> +         *                */

Please fix the comment.

> +        evtchn_allocate(d);
> +
>           /*
>            * The hypervisor node should always be created after all nodes
>            * from the host DT have been parsed.
>            */
> -        res = make_hypervisor_node(d, kinfo, node);
> +        res = make_hypervisor_node(d, kinfo, addrcells, sizecells);
>           if ( res )
>               return res;
>   
> @@ -1333,7 +1337,7 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
>           if ( res )
>               return res;
>   
> -        res = make_memory_node(d, kinfo->fdt, node, kinfo);
> +        res = make_memory_node(d, kinfo->fdt, addrcells, sizecells, kinfo);
>           if ( res )
>               return res;
>   
> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
> index 7b009ea..8fc401d 100644
> --- a/xen/common/device_tree.c
> +++ b/xen/common/device_tree.c
> @@ -112,11 +112,11 @@ void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
>       dt_set_cell(cellp, dt_n_size_cells(np), size);
>   }
>   
> -void dt_child_set_range(__be32 **cellp, const struct dt_device_node *parent,
> +void dt_child_set_range(__be32 **cellp, int addrcells, int sizecells,
>                           u64 address, u64 size)
>   {
> -    dt_set_cell(cellp, dt_child_n_addr_cells(parent), address);
> -    dt_set_cell(cellp, dt_child_n_size_cells(parent), size);
> +    dt_set_cell(cellp, addrcells, address);
> +    dt_set_cell(cellp, sizecells, size);
>   }
>   
>   static void __init *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
> diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
> index 638b926..91fa0b6 100644
> --- a/xen/include/xen/device_tree.h
> +++ b/xen/include/xen/device_tree.h
> @@ -674,7 +674,7 @@ void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
>    * Write a range into a series of cells and update cellp to point to the
>    * cell just after.
>    */
> -void dt_child_set_range(__be32 **cellp, const struct dt_device_node *parent,
> +void dt_child_set_range(__be32 **cellp, int addrcells, int sizecells,
>                           u64 address, u64 size);
>   
>   /**
> 

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

* Re: [PATCH v2 07/21] xen/arm: rename acpi_make_chosen_node to make_chosen_node
  2018-07-06 23:12 ` [PATCH v2 07/21] xen/arm: rename acpi_make_chosen_node to make_chosen_node Stefano Stabellini
@ 2018-07-09 14:12   ` Julien Grall
  0 siblings, 0 replies; 92+ messages in thread
From: Julien Grall @ 2018-07-09 14:12 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi,

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

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

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

* Re: [PATCH v2 09/21] xen/arm: move cmdline out of boot_modules
  2018-07-06 23:12 ` [PATCH v2 09/21] xen/arm: move cmdline out of boot_modules Stefano Stabellini
@ 2018-07-09 14:53   ` Julien Grall
  2018-07-10  0:00     ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-09 14:53 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi,

On 07/07/18 00:12, Stefano Stabellini wrote:
> Remove the cmdline field from struct boot_module, cmdline is stored
> independently out of the boot_modules array as dom0_cmdline.

I am not entirely convince of this patch, this does not seem to go 
towards a better code base because dom0_cmdline is only set if 
"bootargs". This may raise some confusing to the developer.

I would still prefer to keep the command-line in the boot module 
structure and find a way to associated the bootmodule with a node.

> 
> Add a pointer to struct kernel_info to point to the cmdline for a given
> kernel.
> 
> boot_fdt_cmdline is only used to retrieve the Xen cmdline. Remove the
> code to return the dom0 cmdline when the Xen cmdline is not available.

None of the code in boot_fdt_cmdline will return Dom0 cmdline. What the 
code does is looking whether xen,dom0-bootargs or "bootargs" in the boot 
kernel module has been defined. If not, it means "bootargs" of the 
chosen node will be used for Xen.

> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> 
> ---
> Changes in v2:
> - new patch
> ---
>   xen/arch/arm/bootfdt.c      | 25 +++++++------------------
>   xen/arch/arm/domain_build.c | 11 +++++------
>   xen/arch/arm/kernel.h       |  1 +
>   xen/arch/arm/setup.c        | 10 +++-------
>   xen/include/asm-arm/setup.h |  5 ++---
>   5 files changed, 18 insertions(+), 34 deletions(-)
> 
> diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
> index 8eba42c..b3e1e00 100644
> --- a/xen/arch/arm/bootfdt.c
> +++ b/xen/arch/arm/bootfdt.c
> @@ -226,11 +226,10 @@ static void __init process_multiboot_node(const void *fdt, int node,
>           if ( len > BOOTMOD_MAX_CMDLINE )
>               panic("module %s command line too long\n", name);
>           cmdline = prop->data;
> +        safe_strcpy(dom0_cmdline, cmdline);

I don't think anything promise you that "bootargs" will actually be for 
the kernel.

Looking at the documentation, the only wording is "Command line 
associated with this module".

>       }
> -    else
> -        cmdline = NULL;
> -
> -    add_boot_module(kind, start, size, cmdline);
> +
> +    add_boot_module(kind, start, size);
>   }
>   
>   static void __init process_chosen_node(const void *fdt, int node,
> @@ -276,7 +275,7 @@ static void __init process_chosen_node(const void *fdt, int node,
>   
>       printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end);
>   
> -    add_boot_module(BOOTMOD_RAMDISK, start, end-start, NULL);
> +    add_boot_module(BOOTMOD_RAMDISK, start, end-start);
>   }
>   
>   static int __init early_scan_node(const void *fdt,
> @@ -307,12 +306,11 @@ static void __init early_print_info(void)
>                        mi->bank[i].start + mi->bank[i].size - 1);
>       printk("\n");
>       for ( i = 0 ; i < mods->nr_mods; i++ )
> -        printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s %s\n",
> +        printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s\n",
>                        i,
>                        mods->module[i].start,
>                        mods->module[i].start + mods->module[i].size,
> -                     boot_module_kind_as_string(mods->module[i].kind),
> -                     mods->module[i].cmdline);
> +                     boot_module_kind_as_string(mods->module[i].kind));
>       nr_rsvd = fdt_num_mem_rsv(device_tree_flattened);
>       for ( i = 0; i < nr_rsvd; i++ )
>       {
> @@ -341,7 +339,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();
> @@ -360,15 +358,6 @@ 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);
> -
> -        if (fdt_get_property(fdt, node, "xen,dom0-bootargs", NULL) ||
> -            ( dom0_mod && dom0_mod->cmdline[0] ) )
> -            prop = fdt_get_property(fdt, node, "bootargs", NULL);
> -    }

See above, this code should not be dropped.

> -    if ( prop == NULL )
>           return NULL;
>   
>       return prop->data;
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 4d06584..d7e642b 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -402,10 +402,8 @@ static int 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 ( dom0_cmdline[0] )
> +        bootargs = &dom0_cmdline[0];
>   
>       dt_for_each_property_node (node, prop)
>       {
> @@ -971,9 +969,9 @@ static int 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;
> @@ -2173,6 +2171,7 @@ int __init construct_dom0(struct domain *d)
>   
>   #endif
>   
> +    kinfo.cmdline = &dom0_cmdline[0];
>       allocate_memory(d, &kinfo);
>       find_gnttab_region(d, &kinfo);
>   
> diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
> index 6d69509..a47aa4c 100644
> --- a/xen/arch/arm/kernel.h
> +++ b/xen/arch/arm/kernel.h
> @@ -30,6 +30,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 1d6f6bf..188b2cb 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -51,6 +51,7 @@
>   #include <asm/acpi.h>
>   
>   struct bootinfo __initdata bootinfo;
> +char __initdata dom0_cmdline[BOOTMOD_MAX_CMDLINE];
>   
>   struct cpuinfo_arm __read_mostly boot_cpu_data;
>   
> @@ -202,8 +203,7 @@ void dt_unreserved_regions(paddr_t s, paddr_t e,
>   }
>   
>   struct bootmodule *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;
> @@ -219,10 +219,6 @@ struct bootmodule *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;
>   }
> @@ -725,7 +721,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..6d08eb4 100644
> --- a/xen/include/asm-arm/setup.h
> +++ b/xen/include/asm-arm/setup.h
> @@ -35,13 +35,13 @@ struct bootmodule {
>       bootmodule_kind kind;
>       paddr_t start;
>       paddr_t size;
> -    char cmdline[BOOTMOD_MAX_CMDLINE];
>   };
>   
>   struct bootmodules {
>       int nr_mods;
>       struct bootmodule module[MAX_MODULES];
>   };
> +extern char dom0_cmdline[BOOTMOD_MAX_CMDLINE];
>   
>   struct bootinfo {
>       struct meminfo mem;
> @@ -78,8 +78,7 @@ 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);
>   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] 92+ messages in thread

* Re: [PATCH v2 06/21] xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node
  2018-07-09 14:11   ` Julien Grall
@ 2018-07-09 21:51     ` Stefano Stabellini
  2018-07-10 17:28       ` Julien Grall
  0 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-09 21:51 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Mon, 9 Jul 2018, Julien Grall wrote:
> Hi,
> 
> On 07/07/18 00:12, Stefano Stabellini wrote:
> > In order to make make_memory_node and make_hypervisor_node more
> > reusable, do not pass them dt_host. As they only use it to calculate
> > addrcells and sizecells, pass addrcells and sizecells directly.
> > 
> > In make_hypervisor_node, assume that evtchn_irq has already been
> > allocated. Move the evtchn_allocate call to handle_node.
> 
> This needs a bit more explanation why. But I think this belongs to a separate
> patch.

Sure


> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > 
> > ---
> > Changes in v2:
> > - add blank line
> > - move evtchn_allocate to handle_node
> > ---
> >   xen/arch/arm/domain_build.c   | 36 ++++++++++++++++++++----------------
> >   xen/common/device_tree.c      |  6 +++---
> >   xen/include/xen/device_tree.h |  2 +-
> >   3 files changed, 24 insertions(+), 20 deletions(-)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index ae3ebc5..c349ce4 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -558,11 +558,11 @@ static int fdt_property_interrupts(void *fdt,
> > gic_interrupt_t *intr,
> >     static int make_memory_node(const struct domain *d,
> >                               void *fdt,
> > -                            const struct dt_device_node *parent,
> > +                            int addrcells, int sizecells,
> >                               const struct kernel_info *kinfo)
> >   {
> >       int res, i;
> > -    int reg_size = dt_child_n_addr_cells(parent) +
> > dt_child_n_size_cells(parent);
> > +    int reg_size = addrcells + sizecells;
> >       int nr_cells = reg_size*kinfo->mem.nr_banks;
> >       __be32 reg[nr_cells];
> >       __be32 *cells;
> > @@ -588,7 +588,7 @@ static int make_memory_node(const struct domain *d,
> >           dt_dprintk("  Bank %d: %#"PRIx64"->%#"PRIx64"\n",
> >                      i, start, start + size);
> >   -        dt_child_set_range(&cells, parent, start, size);
> > +        dt_child_set_range(&cells, addrcells, sizecells, start, size);
> >       }
> >         res = fdt_property(fdt, "reg", reg, sizeof(reg));
> > @@ -604,7 +604,7 @@ static void evtchn_allocate(struct domain *d);
> >     static int make_hypervisor_node(struct domain *d,
> >                                   const struct kernel_info *kinfo,
> > -                                const struct dt_device_node *parent)
> > +                                int addrcells, int sizecells)
> >   {
> >       const char compat[] =
> >           "xen,xen-"__stringify(XEN_VERSION)"."__stringify(XEN_SUBVERSION)"\0"
> > @@ -613,9 +613,6 @@ static int make_hypervisor_node(struct domain *d,
> >       gic_interrupt_t intr;
> >       __be32 *cells;
> >       int res;
> > -    /* Convenience alias */
> > -    int addrcells = dt_child_n_addr_cells(parent);
> > -    int sizecells = dt_child_n_size_cells(parent);
> >       void *fdt = kinfo->fdt;
> >         dt_dprintk("Create hypervisor node\n");
> > @@ -640,19 +637,14 @@ static int make_hypervisor_node(struct domain *d,
> >         /* reg 0 is grant table space */
> >       cells = &reg[0];
> > -    dt_child_set_range(&cells, parent, kinfo->gnttab_start,
> > kinfo->gnttab_size);
> > +    dt_child_set_range(&cells, addrcells, sizecells,
> > +                       kinfo->gnttab_start, kinfo->gnttab_size);
> >       res = fdt_property(fdt, "reg", reg,
> >                          dt_cells_to_size(addrcells + sizecells));
> >       if ( res )
> >           return res;
> >         /*
> > -     * It is safe to allocate the event channel here because all the
> > -     * PPIs used by the hardware domain have been registered.
> > -     */
> > -    evtchn_allocate(d);
> 
> I would replace this with a BUG_ON(evtchn != 0).

I agree with the principle, but I think you meant
BUG_ON(d->arch.evtchn_irq <= 0) ?


> > -
> > -    /*
> >        * Interrupt event channel upcall:
> >        *  - Active-low level-sensitive
> >        *  - All CPUs
> > @@ -1317,11 +1309,23 @@ static int handle_node(struct domain *d, struct
> > kernel_info *kinfo,
> >         if ( node == dt_host )
> >       {
> > +        int addrcells = dt_child_n_addr_cells(node);
> > +        int sizecells = dt_child_n_size_cells(node);
> > +
> > +
> > +        /*
> > +         *      * It is safe to allocate the event channel here
> > +         *      because all the
> > +         *           * PPIs used by the hardware domain have been
> > +         *           registered.
> > +         *                */
> 
> Please fix the comment.

No idea what happened there :-)
I'll fix


> > +        evtchn_allocate(d);
> > +
> >           /*
> >            * The hypervisor node should always be created after all nodes
> >            * from the host DT have been parsed.
> >            */
> > -        res = make_hypervisor_node(d, kinfo, node);
> > +        res = make_hypervisor_node(d, kinfo, addrcells, sizecells);
> >           if ( res )
> >               return res;
> >   @@ -1333,7 +1337,7 @@ static int handle_node(struct domain *d, struct
> > kernel_info *kinfo,
> >           if ( res )
> >               return res;
> >   -        res = make_memory_node(d, kinfo->fdt, node, kinfo);
> > +        res = make_memory_node(d, kinfo->fdt, addrcells, sizecells, kinfo);
> >           if ( res )
> >               return res;
> >   diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
> > index 7b009ea..8fc401d 100644
> > --- a/xen/common/device_tree.c
> > +++ b/xen/common/device_tree.c
> > @@ -112,11 +112,11 @@ void dt_set_range(__be32 **cellp, const struct
> > dt_device_node *np,
> >       dt_set_cell(cellp, dt_n_size_cells(np), size);
> >   }
> >   -void dt_child_set_range(__be32 **cellp, const struct dt_device_node
> > *parent,
> > +void dt_child_set_range(__be32 **cellp, int addrcells, int sizecells,
> >                           u64 address, u64 size)
> >   {
> > -    dt_set_cell(cellp, dt_child_n_addr_cells(parent), address);
> > -    dt_set_cell(cellp, dt_child_n_size_cells(parent), size);
> > +    dt_set_cell(cellp, addrcells, address);
> > +    dt_set_cell(cellp, sizecells, size);
> >   }
> >     static void __init *unflatten_dt_alloc(unsigned long *mem, unsigned long
> > size,
> > diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
> > index 638b926..91fa0b6 100644
> > --- a/xen/include/xen/device_tree.h
> > +++ b/xen/include/xen/device_tree.h
> > @@ -674,7 +674,7 @@ void dt_set_range(__be32 **cellp, const struct
> > dt_device_node *np,
> >    * Write a range into a series of cells and update cellp to point to the
> >    * cell just after.
> >    */
> > -void dt_child_set_range(__be32 **cellp, const struct dt_device_node
> > *parent,
> > +void dt_child_set_range(__be32 **cellp, int addrcells, int sizecells,
> >                           u64 address, u64 size);
> >     /**
> > 
> 
> 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] 92+ messages in thread

* Re: [PATCH v2 02/21] xen/arm: make allocate_memory work for non 1:1 mapped guests
  2018-07-09 13:43   ` Julien Grall
@ 2018-07-09 23:02     ` Stefano Stabellini
  2018-07-10 17:57       ` Julien Grall
  0 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-09 23:02 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Mon, 9 Jul 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 07/07/18 00:11, Stefano Stabellini wrote:
> > Extend allocate_memory to work for non 1:1 mapped domUs. Specifically,
> > memory allocated for domU will be mapped into the domU pseudo-physical
> > address space at the appropriate addresses according to the guest memory
> > map: GUEST_RAM0_BASE and GUEST_RAM1_BASE.
> > 
> > To do that, insert_11_bank has been extended to deal with non-dom0
> > mappings starting from GUEST_RAM0_BASE. insert_11_bank has been renamed
> > to insert_bank.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > 
> > ---
> > Changes in v2:
> > - new patch
> > ---
> >   xen/arch/arm/domain_build.c | 57
> > ++++++++++++++++++++++++++++++++++-----------
> >   1 file changed, 44 insertions(+), 13 deletions(-)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 182e3d5..2a6619a 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -97,27 +97,51 @@ static unsigned int get_allocation_size(paddr_t size)
> >    * Returns false if the memory would be below bank 0 or we have run
> >    * out of banks. In this case it will free the pages.
> >    */
> > -static bool insert_11_bank(struct domain *d,
> > -                           struct kernel_info *kinfo,
> > -                           struct page_info *pg,
> > -                           unsigned int order)
> > +static bool insert_bank(struct domain *d,
> > +                        struct kernel_info *kinfo,
> > +                        struct page_info *pg,
> > +                        unsigned int order,
> > +                        bool map_11)
> >   {
> > -    int res, i;
> > +    int res, i, nr_mem_banks = map_11 ? NR_MEM_BANKS : 2;
> 
> nr_mem_banks should be unsigned. I also would drop "mem_" to shorten a bit the
> name.

OK


> >       mfn_t smfn;
> >       paddr_t start, size;
> > +    struct membank *bank;
> >         smfn = page_to_mfn(pg);
> >       start = mfn_to_maddr(smfn);
> 
> The new code is pretty horrible to read. Can you please add some comments to
> help understanding it?
> 
> Here is already an example where you set start to MFN. But then override after
> with none comment to understand why.
> 
> Also, this code as always assumed MFN == GFN so start was making sense. Now,
> you re-purpose it to just the guest-physical address. So more likely you want
> to rework the code a bit.

I'll add more comments in the code. Next time the patch will be clearer.
This is a snippet to give you an idea, but it might be best for you to
just wait for the next version before reading this again.

    /*
     * smfn: the address of the set of pages to map
     * start: the address in guest pseudo-physical memory where to map
     *        the pages
     */
    smfn = page_to_mfn(pg);
    start = mfn_to_maddr(smfn);
    size = pfn_to_paddr(1UL << order);
    if ( !is_hardware_domain(d) )
    {
        /*
         * Dom0 is 1:1 mapped, so start is the same as (smfn <<
         * PAGE_SHIFT).
         *
         * Instead, DomU memory is provided in two banks:
         *   GUEST_RAM0_BASE - GUEST_RAM0_BASE + GUEST_RAM0_SIZE
         *   GUEST_RAM1_BASE - GUEST_RAM1_BASE + GUEST_RAM1_SIZE
         * 
         * Find the right start address for DomUs accordingly.
         */
  


> >       size = pfn_to_paddr(1UL << order);
> > +    if ( !map_11 )
> 
> I am not sure why map_11 would mean DomU? I don't see any reason to not allow
> that for Dom0. Note that I am not asking to do it, just having clearer name.

Good point. I think I should just drop the option, which is just
confusing, and keep using is_hardware_domain(d) checks like in
allocate_memory. Otherwise let me know if you have a better idea.


> > +    {
> > +        start = GUEST_RAM0_BASE;
> > +        if ( kinfo->mem.nr_banks > 0 )
> > +        {
> > +            for( i = 0; i < kinfo->mem.nr_banks; i++ )
> > +            {
> > +                bank = &kinfo->mem.bank[i];
> > +                start = bank->start + bank->size;
> > +            }
> > +            if ( bank->start == GUEST_RAM0_BASE &&
> > +                    start + size > (GUEST_RAM0_BASE + GUEST_RAM0_SIZE) )
> 
> The indentation looks wrong.

OK


> > +                start = GUEST_RAM1_BASE;
> > +            if ( bank->start == GUEST_RAM1_BASE &&
> > +                    start + size > (GUEST_RAM1_BASE + GUEST_RAM1_SIZE) )
> > +            {
> > +                D11PRINT("Allocation of domain memory exceeds max
> > amount\n");
> 
> This looks quite strange to use D11PRINT here as this related to direct-domain
> mapped.
 
You are right, but I didn't feel like replacing all D11PRINT
occurrences. Should I do that? Or should I change just this instance? I
could also just drop this D11PRINT, given that the printk is not even
enabled by default. Let me know.


> > +                goto fail;
> > +            }
> > +        }
> > +    }
> >   -    D11PRINT("Allocated %#"PRIpaddr"-%#"PRIpaddr" (%ldMB/%ldMB, order
> > %d)\n",
> > +    D11PRINT("Allocated %#"PRIpaddr"-%#"PRIpaddr":%#"PRIpaddr"-%#"PRIpaddr"
> > (%ldMB/%ldMB, order %d)\n",
> > +             mfn_to_maddr(smfn), mfn_to_maddr(smfn) + size,
> >                start, start + size,
> >                1UL << (order + PAGE_SHIFT - 20),
> >                /* Don't want format this as PRIpaddr (16 digit hex) */
> >                (unsigned long)(kinfo->unassigned_mem >> 20),
> >                order);
> >   -    if ( kinfo->mem.nr_banks > 0 &&
> > +    if ( map_11 && kinfo->mem.nr_banks > 0 &&
> 
> Why do you drop that check? It should be harmless for non-direct mapped
> domain.

You are right. I'll remove this change.


> >            size < MB(128) && >            start + size <
> > kinfo->mem.bank[0].start )
> >       {
> > @@ -125,7 +149,7 @@ static bool insert_11_bank(struct domain *d,
> >           goto fail;
> >       }
> >   -    res = guest_physmap_add_page(d, _gfn(mfn_x(smfn)), smfn, order);
> > +    res = guest_physmap_add_page(d, gaddr_to_gfn(start), smfn, order);
> >       if ( res )
> >           panic("Failed map pages to DOM0: %d", res);
> >   @@ -141,7 +165,7 @@ static bool insert_11_bank(struct domain *d,
> >         for( i = 0; i < kinfo->mem.nr_banks; i++ )
> >       {
> > -        struct membank *bank = &kinfo->mem.bank[i];
> > +        bank = &kinfo->mem.bank[i];
> >             /* If possible merge new memory into the start of the bank */
> >           if ( bank->start == start+size )
> > @@ -164,7 +188,7 @@ static bool insert_11_bank(struct domain *d,
> >            * could have inserted the memory into/before we would already
> >            * have done so, so this must be the right place.
> >            */
> > -        if ( start + size < bank->start && kinfo->mem.nr_banks <
> > NR_MEM_BANKS )
> > +        if ( start + size < bank->start && kinfo->mem.nr_banks <
> > nr_mem_banks )
> >           {
> >               memmove(bank + 1, bank,
> >                       sizeof(*bank) * (kinfo->mem.nr_banks - i));
> > @@ -175,7 +199,7 @@ static bool insert_11_bank(struct domain *d,
> >           }
> >       }
> >   -    if ( i == kinfo->mem.nr_banks && kinfo->mem.nr_banks < NR_MEM_BANKS )
> > +    if ( i == kinfo->mem.nr_banks && kinfo->mem.nr_banks < nr_mem_banks )
> >       {
> >           struct membank *bank = &kinfo->mem.bank[kinfo->mem.nr_banks];
> >   @@ -253,6 +277,7 @@ static void allocate_memory(struct domain *d, struct
> > kernel_info *kinfo)
> >       struct page_info *pg;
> >       unsigned int order = get_allocation_size(kinfo->unassigned_mem);
> >       int i;
> > +    bool hwdom = d->domain_id == 0;
> 
> You should use is_hardware_domain(...).

Yes, I'll do that here and elsewhere in this patch


> >         bool lowmem = true;
> >       unsigned int bits;
> > @@ -263,6 +288,12 @@ static void allocate_memory(struct domain *d, struct
> > kernel_info *kinfo)
> >         kinfo->mem.nr_banks = 0;
> >   +    if ( !hwdom )
> > +    {
> > +        lowmem = false;
> > +        goto got_bank0;
> > +    }
> 
> Can you explain why you need this?

Yes, I'll add a comment. The first part of allocate_memory tries to
allocate memory as low as possible, which is fine for dom0 but it is
unnecessary for DomUs, given that they are not 1:1 mapped. So, this
check is meant to go straight to the regular allocation for DomUs,
skipping the special below-4G allocation loop.


> > +
> >       /*
> >        * First try and allocate the largest thing we can as low as
> >        * possible to be bank 0.
> > @@ -274,7 +305,7 @@ static void allocate_memory(struct domain *d, struct
> > kernel_info *kinfo)
> >               pg = alloc_domheap_pages(d, order, MEMF_bits(bits));
> >               if ( pg != NULL )
> >               {
> > -                if ( !insert_11_bank(d, kinfo, pg, order) )
> > +                if ( !insert_bank(d, kinfo, pg, order, hwdom) )
> >                       BUG(); /* Cannot fail for first bank */
> >                     goto got_bank0;
> > @@ -319,7 +350,7 @@ static void allocate_memory(struct domain *d, struct
> > kernel_info *kinfo)
> >               break;
> >           }
> >   -        if ( !insert_11_bank(d, kinfo, pg, order) )
> > +        if ( !insert_bank(d, kinfo, pg, order, hwdom) )
> >           {
> >               if ( kinfo->mem.nr_banks == NR_MEM_BANKS )
> >                   /* Nothing more we can do. */
> > 

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

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

* Re: [PATCH v2 02/21] xen/arm: make allocate_memory work for non 1:1 mapped guests
  2018-07-09 13:58   ` Julien Grall
@ 2018-07-09 23:10     ` Stefano Stabellini
  0 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-09 23:10 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Mon, 9 Jul 2018, Julien Grall wrote:
> On 07/07/18 00:11, Stefano Stabellini wrote:
> > @@ -263,6 +288,12 @@ static void allocate_memory(struct domain *d, struct
> > kernel_info *kinfo)
> 
> I forgot to mention that very likely you want to update the big comment on top
> of this function.

I'll do

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

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

* Re: [PATCH v2 09/21] xen/arm: move cmdline out of boot_modules
  2018-07-09 14:53   ` Julien Grall
@ 2018-07-10  0:00     ` Stefano Stabellini
  2018-07-10 21:11       ` Julien Grall
  0 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-10  0:00 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Mon, 9 Jul 2018, Julien Grall wrote:
> Hi,
> 
> On 07/07/18 00:12, Stefano Stabellini wrote:
> > Remove the cmdline field from struct boot_module, cmdline is stored
> > independently out of the boot_modules array as dom0_cmdline.
> 
> I am not entirely convince of this patch, this does not seem to go towards a
> better code base because dom0_cmdline is only set if "bootargs". This may
> raise some confusing to the developer.

I'll add a comment on top of dom0_cmdline to clarify its purpose:

/*
 * Dom0 command line as passed via Device Tree as "bootargs" for the
 * Dom0 kernel module.
 */


> I would still prefer to keep the command-line in the boot module structure and
> find a way to associated the bootmodule with a node.

How do you suggest we find a good way to associate a boot module with a
node? 

I have thought about this problem quite a bit. Although I admit this
patch is not super nice, it is the best option I found. I have actually
developed 2 other completely different implementations of this fix and
they were all worse than this. This is the third incarnation. It is
actually surprisingly easy to do worse than this patch.


> > Add a pointer to struct kernel_info to point to the cmdline for a given
> > kernel.
> > 
> > boot_fdt_cmdline is only used to retrieve the Xen cmdline. Remove the
> > code to return the dom0 cmdline when the Xen cmdline is not available.
> 
> None of the code in boot_fdt_cmdline will return Dom0 cmdline. What the code
> does is looking whether xen,dom0-bootargs or "bootargs" in the boot kernel
> module has been defined. If not, it means "bootargs" of the chosen node will
> be used for Xen.

I misread the function. I'll remove this part of the patch (it is
actually not needed, it is just something I thought I would fix along
the way).


> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > 
> > ---
> > Changes in v2:
> > - new patch
> > ---
> >   xen/arch/arm/bootfdt.c      | 25 +++++++------------------
> >   xen/arch/arm/domain_build.c | 11 +++++------
> >   xen/arch/arm/kernel.h       |  1 +
> >   xen/arch/arm/setup.c        | 10 +++-------
> >   xen/include/asm-arm/setup.h |  5 ++---
> >   5 files changed, 18 insertions(+), 34 deletions(-)
> > 
> > diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
> > index 8eba42c..b3e1e00 100644
> > --- a/xen/arch/arm/bootfdt.c
> > +++ b/xen/arch/arm/bootfdt.c
> > @@ -226,11 +226,10 @@ static void __init process_multiboot_node(const void
> > *fdt, int node,
> >           if ( len > BOOTMOD_MAX_CMDLINE )
> >               panic("module %s command line too long\n", name);
> >           cmdline = prop->data;
> > +        safe_strcpy(dom0_cmdline, cmdline);
> 
> I don't think anything promise you that "bootargs" will actually be for the
> kernel.
> 
> Looking at the documentation, the only wording is "Command line associated
> with this module".

You are right about that. But the dom0 kernel command line is the only
"command line associated with this module" that we know how to deal
with. For instance, we are not able to handle bootargs for the XSM
module (or any other kinds of modules). Currently we ignore them all. We
could simply keep on ignoring any bootargs unless they are for the dom0
kernel.

We do need an extra check here to make sure that we are dealing with the
dom0 kernel module before doing the safe_strcpy. I can make that change.


> >       }
> > -    else
> > -        cmdline = NULL;
> > -
> > -    add_boot_module(kind, start, size, cmdline);
> > +
> > +    add_boot_module(kind, start, size);
> >   }
> >     static void __init process_chosen_node(const void *fdt, int node,
> > @@ -276,7 +275,7 @@ static void __init process_chosen_node(const void *fdt,
> > int node,
> >         printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end);
> >   -    add_boot_module(BOOTMOD_RAMDISK, start, end-start, NULL);
> > +    add_boot_module(BOOTMOD_RAMDISK, start, end-start);
> >   }
> >     static int __init early_scan_node(const void *fdt,
> > @@ -307,12 +306,11 @@ static void __init early_print_info(void)
> >                        mi->bank[i].start + mi->bank[i].size - 1);
> >       printk("\n");
> >       for ( i = 0 ; i < mods->nr_mods; i++ )
> > -        printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s %s\n",
> > +        printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s\n",
> >                        i,
> >                        mods->module[i].start,
> >                        mods->module[i].start + mods->module[i].size,
> > -                     boot_module_kind_as_string(mods->module[i].kind),
> > -                     mods->module[i].cmdline);
> > +                     boot_module_kind_as_string(mods->module[i].kind));
> >       nr_rsvd = fdt_num_mem_rsv(device_tree_flattened);
> >       for ( i = 0; i < nr_rsvd; i++ )
> >       {
> > @@ -341,7 +339,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();
> > @@ -360,15 +358,6 @@ 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);
> > -
> > -        if (fdt_get_property(fdt, node, "xen,dom0-bootargs", NULL) ||
> > -            ( dom0_mod && dom0_mod->cmdline[0] ) )
> > -            prop = fdt_get_property(fdt, node, "bootargs", NULL);
> > -    }
> 
> See above, this code should not be dropped.

I'll fix


> > -    if ( prop == NULL )
> >           return NULL;
> >         return prop->data;
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 4d06584..d7e642b 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -402,10 +402,8 @@ static int 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 ( dom0_cmdline[0] )
> > +        bootargs = &dom0_cmdline[0];
> >         dt_for_each_property_node (node, prop)
> >       {
> > @@ -971,9 +969,9 @@ static int 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;
> > @@ -2173,6 +2171,7 @@ int __init construct_dom0(struct domain *d)
> >     #endif
> >   +    kinfo.cmdline = &dom0_cmdline[0];
> >       allocate_memory(d, &kinfo);
> >       find_gnttab_region(d, &kinfo);
> >   diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
> > index 6d69509..a47aa4c 100644
> > --- a/xen/arch/arm/kernel.h
> > +++ b/xen/arch/arm/kernel.h
> > @@ -30,6 +30,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 1d6f6bf..188b2cb 100644
> > --- a/xen/arch/arm/setup.c
> > +++ b/xen/arch/arm/setup.c
> > @@ -51,6 +51,7 @@
> >   #include <asm/acpi.h>
> >     struct bootinfo __initdata bootinfo;
> > +char __initdata dom0_cmdline[BOOTMOD_MAX_CMDLINE];
> >     struct cpuinfo_arm __read_mostly boot_cpu_data;
> >   @@ -202,8 +203,7 @@ void dt_unreserved_regions(paddr_t s, paddr_t e,
> >   }
> >     struct bootmodule *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;
> > @@ -219,10 +219,6 @@ struct bootmodule *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;
> >   }
> > @@ -725,7 +721,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..6d08eb4 100644
> > --- a/xen/include/asm-arm/setup.h
> > +++ b/xen/include/asm-arm/setup.h
> > @@ -35,13 +35,13 @@ struct bootmodule {
> >       bootmodule_kind kind;
> >       paddr_t start;
> >       paddr_t size;
> > -    char cmdline[BOOTMOD_MAX_CMDLINE];
> >   };
> >     struct bootmodules {
> >       int nr_mods;
> >       struct bootmodule module[MAX_MODULES];
> >   };
> > +extern char dom0_cmdline[BOOTMOD_MAX_CMDLINE];
> >     struct bootinfo {
> >       struct meminfo mem;
> > @@ -78,8 +78,7 @@ 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);
> >   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] 92+ messages in thread

* Re: [PATCH v2 06/21] xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node
  2018-07-09 21:51     ` Stefano Stabellini
@ 2018-07-10 17:28       ` Julien Grall
  2018-07-11 20:33         ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-10 17:28 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi,

On 09/07/18 22:51, Stefano Stabellini wrote:
>> I would replace this with a BUG_ON(evtchn != 0).
> 
> I agree with the principle, but I think you meant
> BUG_ON(d->arch.evtchn_irq <= 0) ?

The IRQ is an unsigned number. So why <= 0?

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

* Re: [PATCH v2 02/21] xen/arm: make allocate_memory work for non 1:1 mapped guests
  2018-07-09 23:02     ` Stefano Stabellini
@ 2018-07-10 17:57       ` Julien Grall
  2018-07-11 21:42         ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-10 17:57 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 10/07/18 00:02, Stefano Stabellini wrote:
> On Mon, 9 Jul 2018, Julien Grall wrote:
>> On 07/07/18 00:11, Stefano Stabellini wrote:
>>>        mfn_t smfn;
>>>        paddr_t start, size;
>>> +    struct membank *bank;
>>>          smfn = page_to_mfn(pg);
>>>        start = mfn_to_maddr(smfn);
>>
>> The new code is pretty horrible to read. Can you please add some comments to
>> help understanding it?
>>
>> Here is already an example where you set start to MFN. But then override after
>> with none comment to understand why.
>>
>> Also, this code as always assumed MFN == GFN so start was making sense. Now,
>> you re-purpose it to just the guest-physical address. So more likely you want
>> to rework the code a bit.
> 
> I'll add more comments in the code. Next time the patch will be clearer.
> This is a snippet to give you an idea, but it might be best for you to
> just wait for the next version before reading this again.
> 
>      /*
>       * smfn: the address of the set of pages to map
>       * start: the address in guest pseudo-physical memory where to map
>       *        the pages

The best way is to rename start to gaddr or better provide a frame. So 
there are no need for such self-explanatory comment. However, my main 
issue was not the name itself...

>       */
>      smfn = page_to_mfn(pg);
>      start = mfn_to_maddr(smfn);

... but this specific line. This should have been in a else.

>      size = pfn_to_paddr(1UL << order);
>      if ( !is_hardware_domain(d) )

Why is_hardware_domain(d)? None of the code below is assuming it is an 
hardware domain and we should not assume the 1:1 mapping. That was the 
exact reason of the BUG_ON(!is_domain_direct_mapped(d)) in the caller 
and not !is_hardware_domain(d).

>      {
>          /*
>           * Dom0 is 1:1 mapped, so start is the same as (smfn <<
>           * PAGE_SHIFT).

This comment is misplaced.

>           *
>           * Instead, DomU memory is provided in two banks:

Why instead? The comment should be split.

>           *   GUEST_RAM0_BASE - GUEST_RAM0_BASE + GUEST_RAM0_SIZE
>           *   GUEST_RAM1_BASE - GUEST_RAM1_BASE + GUEST_RAM1_SIZE
>           *
>           * Find the right start address for DomUs accordingly.
>           */
>    
> 
> 
>>>        size = pfn_to_paddr(1UL << order);
>>> +    if ( !map_11 )
>>
>> I am not sure why map_11 would mean DomU? I don't see any reason to not allow
>> that for Dom0. Note that I am not asking to do it, just having clearer name.
> 
> Good point. I think I should just drop the option, which is just
> confusing, and keep using is_hardware_domain(d) checks like in
> allocate_memory. Otherwise let me know if you have a better idea.

TBH, I dislike the way you re-purpose the 2 functions. 80% of this code 
is not necessary because you will never merge the range before the bank 
or deal with 1:1 mappings.

Furthermore, I just spotted a few issues with that code:
	1) If you request 4GB for a guest and the memory has been allocated in 
one chunk, all the RAM will be starting at GUEST_RAM1_SIZE. While we 
officially don't support guest with hardcoded memory layout, there are 
some existing. Such change will break them depending on your memory 
layout at boot.
	2) If in the future we decide to add more banks (this may happen with 
PCI passthrough), then you have to add yet another if.

What is the problem to provide a separate function to allocate memory 
for non-direct domain? You could just pass the base and the size of the 
region to populate.

> 
> 
>>> +    {
>>> +        start = GUEST_RAM0_BASE;
>>> +        if ( kinfo->mem.nr_banks > 0 )
>>> +        {
>>> +            for( i = 0; i < kinfo->mem.nr_banks; i++ )
>>> +            {
>>> +                bank = &kinfo->mem.bank[i];
>>> +                start = bank->start + bank->size;
>>> +            }
>>> +            if ( bank->start == GUEST_RAM0_BASE &&
>>> +                    start + size > (GUEST_RAM0_BASE + GUEST_RAM0_SIZE) )
>>
>> The indentation looks wrong.
> 
> OK
> 
> 
>>> +                start = GUEST_RAM1_BASE;
>>> +            if ( bank->start == GUEST_RAM1_BASE &&
>>> +                    start + size > (GUEST_RAM1_BASE + GUEST_RAM1_SIZE) )
>>> +            {
>>> +                D11PRINT("Allocation of domain memory exceeds max
>>> amount\n");
>>
>> This looks quite strange to use D11PRINT here as this related to direct-domain
>> mapped.
>   
> You are right, but I didn't feel like replacing all D11PRINT
> occurrences. Should I do that? Or should I change just this instance? I
> could also just drop this D11PRINT, given that the printk is not even
> enabled by default. Let me know.

But then, the D11PRINT below does not make any sense after your change. 
We should really aim to keep that code fairly sane. So I would rename 
D11PRINT unless you are doing what I suggested above.

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

* Re: [PATCH v2 09/21] xen/arm: move cmdline out of boot_modules
  2018-07-10  0:00     ` Stefano Stabellini
@ 2018-07-10 21:11       ` Julien Grall
  2018-07-13  0:04         ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-10 21:11 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, nd, andrii_anisov, xen-devel

Hi Stefano,

On 10/07/2018 01:00, Stefano Stabellini wrote:
> On Mon, 9 Jul 2018, Julien Grall wrote:
>> Hi,
>>
>> On 07/07/18 00:12, Stefano Stabellini wrote:
>>> Remove the cmdline field from struct boot_module, cmdline is stored
>>> independently out of the boot_modules array as dom0_cmdline.
>>
>> I am not entirely convince of this patch, this does not seem to go towards a
>> better code base because dom0_cmdline is only set if "bootargs". This may
>> raise some confusing to the developer.
> 
> I'll add a comment on top of dom0_cmdline to clarify its purpose:
> 
> /*
>   * Dom0 command line as passed via Device Tree as "bootargs" for the
>   * Dom0 kernel module.
>   */
> 
> 
>> I would still prefer to keep the command-line in the boot module structure and
>> find a way to associated the bootmodule with a node.
> 
> How do you suggest we find a good way to associate a boot module with a
> node?
> 
> I have thought about this problem quite a bit. Although I admit this
> patch is not super nice, it is the best option I found. I have actually
> developed 2 other completely different implementations of this fix and
> they were all worse than this. This is the third incarnation. It is
> actually surprisingly easy to do worse than this patch.

I actually have an idea. Looking at the Device-Tree specification [1], a 
path should always be unique. This means that for a given path a/b/c/d, 
d will always be unique.

Reading the binding you introduced, the multiboot node will be a child 
of a node with the compatible "xen,domain". As the name of the parent 
node will be unique, you can tag the boot-module with that name. No need 
for the full path as all the configuration node should follow the 
pattern /chosen/<domain-name>.

When the guest is built, you have the Device-Tree path of the 
configuration in hand. From that you can deduce the name that you could 
re-use to find the correct boot-module.

You may still require a separate handling similar to your next patch of 
Dom0 as with the current wording they could be a level deeper. But we 
can tight the wording for the new bindings (though, I think it is tight 
enough).

What do you think?

Now regarding the current implementation, it does not follow the defined 
specification. The multiboot nodes are looked everywhere in the DT 
rather than only /chosen. This is an implementation bug and should be fixed.

Cheers,

[1] https://www.devicetree.org/specifications/

-- 
Julien Grall

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

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

* Re: [PATCH v2 01/21] xen/arm: rename get_11_allocation_size to get_allocation_size
  2018-07-09 12:55   ` Julien Grall
@ 2018-07-11 20:09     ` Stefano Stabellini
  0 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-11 20:09 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Mon, 9 Jul 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 07/07/18 00:11, Stefano Stabellini wrote:
> > ... and remove the BUG_ON(!dom0_11_mapping) in allocate_memory.
> 
> Please rebase your work on staging. This code has changed a bit since Xen
> 4.11-rc6.

I'll do


> > A follow-up patch will make the function work with non 1:1 mapped
> > guests.
> > 
> > No functional changes.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > 
> > ---
> > Changes in v2:
> > - new patch
> > ---
> >   xen/arch/arm/domain_build.c | 22 ++++++++--------------
> >   1 file changed, 8 insertions(+), 14 deletions(-)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 11cdf05..182e3d5 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -79,7 +79,7 @@ struct vcpu *__init alloc_dom0_vcpu0(struct domain *dom0)
> >       return alloc_vcpu(dom0, 0, 0);
> >   }
> >   -static unsigned int get_11_allocation_size(paddr_t size)
> > +static unsigned int get_allocation_size(paddr_t size)
> >   {
> >       /*
> >        * get_order_from_bytes returns the order greater than or equal to
> > @@ -251,21 +251,15 @@ static void 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;
> >       unsigned int bits;
> >   -    /*
> > -     * TODO: Implement memory bank allocation when DOM0 is not direct
> > -     * mapped
> > -     */
> > -    BUG_ON(!dom0_11_mapping);
> 
> New code is using is_domain_direct_mapped(d).
 
Thanks for the head's up


> > -
> > -    printk("Allocating 1:1 mappings totalling %ldMB for dom0:\n",
> > +    printk("Allocating 1:1 mappings totalling %ldMB for dom%d:\n",
> 
> This is not mention i nthe command message.

I'll mention the change


> At the same time, please fix the typo s/totalling/totaling/

"Totalling" is actually accepted in British English.


> >              /* Don't want format this as PRIpaddr (16 digit hex) */
> > -           (unsigned long)(kinfo->unassigned_mem >> 20));
> > +           (unsigned long)(kinfo->unassigned_mem >> 20), d->domain_id);
> >         kinfo->mem.nr_banks = 0;
> >   @@ -303,7 +297,7 @@ static void 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);
> > @@ -314,7 +308,7 @@ static void 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;
> >               }
> > @@ -334,7 +328,7 @@ static void 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;
> >               }
> > @@ -349,7 +343,7 @@ static void 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 )
> > 
> 
> 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] 92+ messages in thread

* Re: [PATCH v2 06/21] xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node
  2018-07-10 17:28       ` Julien Grall
@ 2018-07-11 20:33         ` Stefano Stabellini
  0 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-11 20:33 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Tue, 10 Jul 2018, Julien Grall wrote:
> Hi,
> 
> On 09/07/18 22:51, Stefano Stabellini wrote:
> > > I would replace this with a BUG_ON(evtchn != 0).
> > 
> > I agree with the principle, but I think you meant
> > BUG_ON(d->arch.evtchn_irq <= 0) ?
> 
> The IRQ is an unsigned number. So why <= 0?

Ah yes, it should be BUG_ON(d->arch.evtchn_irq == 0).

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

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

* Re: [PATCH v2 02/21] xen/arm: make allocate_memory work for non 1:1 mapped guests
  2018-07-10 17:57       ` Julien Grall
@ 2018-07-11 21:42         ` Stefano Stabellini
  0 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-11 21:42 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Tue, 10 Jul 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 10/07/18 00:02, Stefano Stabellini wrote:
> > On Mon, 9 Jul 2018, Julien Grall wrote:
> > > On 07/07/18 00:11, Stefano Stabellini wrote:
> > > >        mfn_t smfn;
> > > >        paddr_t start, size;
> > > > +    struct membank *bank;
> > > >          smfn = page_to_mfn(pg);
> > > >        start = mfn_to_maddr(smfn);
> > > 
> > > The new code is pretty horrible to read. Can you please add some comments
> > > to
> > > help understanding it?
> > > 
> > > Here is already an example where you set start to MFN. But then override
> > > after
> > > with none comment to understand why.
> > > 
> > > Also, this code as always assumed MFN == GFN so start was making sense.
> > > Now,
> > > you re-purpose it to just the guest-physical address. So more likely you
> > > want
> > > to rework the code a bit.
> > 
> > I'll add more comments in the code. Next time the patch will be clearer.
> > This is a snippet to give you an idea, but it might be best for you to
> > just wait for the next version before reading this again.
> > 
> >      /*
> >       * smfn: the address of the set of pages to map
> >       * start: the address in guest pseudo-physical memory where to map
> >       *        the pages
> 
> The best way is to rename start to gaddr or better provide a frame. So there
> are no need for such self-explanatory comment. However, my main issue was not
> the name itself...

Sure, I can do


> >       */
> >      smfn = page_to_mfn(pg);
> >      start = mfn_to_maddr(smfn);
> 
> ... but this specific line. This should have been in a else.

This goes away with having separate functions for DomUs


> >      size = pfn_to_paddr(1UL << order);
> >      if ( !is_hardware_domain(d) )
> 
> Why is_hardware_domain(d)? None of the code below is assuming it is an
> hardware domain and we should not assume the 1:1 mapping. That was the exact
> reason of the BUG_ON(!is_domain_direct_mapped(d)) in the caller and not
> !is_hardware_domain(d).

Yeah, I should have used is_domain_direct_mapped. This also goes away
with having separate functions.


> >      {
> >          /*
> >           * Dom0 is 1:1 mapped, so start is the same as (smfn <<
> >           * PAGE_SHIFT).
> 
> This comment is misplaced.
>
> >           *
> >           * Instead, DomU memory is provided in two banks:
> 
> Why instead? The comment should be split.

OK


> >           *   GUEST_RAM0_BASE - GUEST_RAM0_BASE + GUEST_RAM0_SIZE
> >           *   GUEST_RAM1_BASE - GUEST_RAM1_BASE + GUEST_RAM1_SIZE
> >           *
> >           * Find the right start address for DomUs accordingly.
> >           */
> >    
> > 
> > > >        size = pfn_to_paddr(1UL << order);
> > > > +    if ( !map_11 )
> > > 
> > > I am not sure why map_11 would mean DomU? I don't see any reason to not
> > > allow
> > > that for Dom0. Note that I am not asking to do it, just having clearer
> > > name.
> > 
> > Good point. I think I should just drop the option, which is just
> > confusing, and keep using is_hardware_domain(d) checks like in
> > allocate_memory. Otherwise let me know if you have a better idea.
> 
> TBH, I dislike the way you re-purpose the 2 functions. 80% of this code is not
> necessary because you will never merge the range before the bank or deal with
> 1:1 mappings.

I have introduced two separate functions now, I am not so sure it's an
actual improvement.


> Furthermore, I just spotted a few issues with that code:
> 	1) If you request 4GB for a guest and the memory has been allocated in
> one chunk, all the RAM will be starting at GUEST_RAM1_SIZE. While we
> officially don't support guest with hardcoded memory layout, there are some
> existing. Such change will break them depending on your memory layout at boot.

I fixed this.


> 	2) If in the future we decide to add more banks (this may happen with
> PCI passthrough), then you have to add yet another if.
>
> What is the problem to provide a separate function to allocate memory for
> non-direct domain? You could just pass the base and the size of the region to
> populate.

You'll see the new functions in the next series. I think there is more
than 20% in common with the older functions. Anyhow, you'll have a
chance to comment on them on the next series.

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

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

* Re: [PATCH v2 15/21] xen/arm: generate vpl011 node on device tree for domU
  2018-07-06 23:12 ` [PATCH v2 15/21] xen/arm: generate vpl011 node on device tree for domU Stefano Stabellini
@ 2018-07-12 18:14   ` Julien Grall
  2018-07-13 21:24     ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-12 18:14 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, nd, andrii_anisov, xen-devel

Hi Stefano,

On 07/07/2018 00:12, Stefano Stabellini wrote:
> Introduce vpl011 support to guests started from Xen: it provides a
> simple way to print output from a guest, as most guests come with a
> pl011 driver. It is also able to provide a working console with
> interrupt support.
> 
> The UART exposed to the guest is a SBSA compatible UART and not a PL011.
> SBSA UART is a subset of PL011 r1p5. A full PL011 implementation in Xen
> would just be too difficult, so guests may require some drivers changes.
> 
> Enable vpl011 conditionally if the user requested it.
> 
> Make set_interrupt_ppi able to handle non-PPI and rename it
> set_interrupt.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> ---
> 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 | 90 +++++++++++++++++++++++++++++++++++++--------
>   1 file changed, 75 insertions(+), 15 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 48a91ad..718be48 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -519,17 +519,17 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo,
>   
>   typedef __be32 gic_interrupt_t[3];
>   
> -static void set_interrupt_ppi(gic_interrupt_t interrupt, unsigned int irq,
> -                              unsigned int cpumask, unsigned int level)
> +static void set_interrupt(gic_interrupt_t interrupt, unsigned int irq,
> +                          unsigned int cpumask, unsigned int level)
>   {
>       __be32 *cells = interrupt;
> +    int is_ppi = (irq < 32);

I was about to suggest a bool, but I am not entirely sure what would be 
the value when it is true.

However, I think you want this to be !!(irq < 32) to make ensure it will 
be 0/1.

>   
> -    BUG_ON(irq < 16);
> -    BUG_ON(irq >= 32);

Can we keep an ASSERT/BUG_ON to confirm no SGI is passed here?

> +    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);
>   }
>   
> @@ -648,7 +648,7 @@ static int 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;
> @@ -924,15 +924,15 @@ static int 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 )
> @@ -1503,9 +1503,9 @@ static int 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 )
> @@ -1520,12 +1520,63 @@ static int make_timer_domU_node(const struct domain *d, void *fdt)
>       return res;
>   }
>   
> +#ifdef CONFIG_SBSA_VUART_CONSOLE
> +static int make_vpl011_uart_node(const struct domain *d, void *fdt,
> +                                 int addrcells, int sizecells)
> +{
> +    int res;
> +    gic_interrupt_t intr;
> +    int reg_size = addrcells + sizecells;
> +    int nr_cells = reg_size;
> +    __be32 reg[nr_cells];
> +    __be32 *cells;
> +
> +    res = fdt_begin_node(fdt, "sbsa-pl011");
> +    if ( res )
> +        return res;
> +
> +    res = fdt_property_string(fdt, "compatible", "arm,sbsa-uart");
> +    if ( res )
> +        return res;
> +
> +    cells = &reg[0];
> +    dt_child_set_range(&cells, addrcells, sizecells, GUEST_PL011_BASE,
> +                       GUEST_PL011_SIZE);
> +    if ( res )
> +        return res;
> +    res = fdt_property(fdt, "reg", reg, sizeof(reg));
> +    if ( res )
> +        return res;
> +
> +    set_interrupt(intr, GUEST_VPL011_SPI, 0xf, DT_IRQ_TYPE_LEVEL_HIGH);
> +
> +    res = fdt_property(fdt, "interrupts", intr, sizeof (intr));
> +    if ( res )
> +        return res;
> +
> +    res = fdt_property_cell(fdt, "interrupt-parent",
> +                            GUEST_PHANDLE_GIC);
> +    if ( res )
> +        return res;
> +
> +    /* Use a default baud rate of 115200. */
> +    fdt_property_u32(fdt, "current-speed", 115200);
> +
> +    res = fdt_end_node(fdt);
> +    if ( res )
> +        return res;
> +
> +    return 0;
> +}
> +#endif
> +
>   /*
>    * The max size for DT is 2MB. However, the generated DT is small, 4KB
>    * are enough for now, but we might have to increase it in the feature.
>    */
>   #define DOMU_DTB_SIZE 4096
> -static int prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
> +static int prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo,
> +                            bool vpl011)

Could we store this boolean in kernel_info? Or could it be deduced from 
struct domain *d?

>   {
>       int addrcells, sizecells;
>       int ret;
> @@ -1585,6 +1636,15 @@ static int prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
>       if ( ret )
>           goto err;
>   
> +#ifdef CONFIG_SBSA_VUART_CONSOLE

I think I would prefer if you implement make_vpl011_uart_node(...) 
return an error above. So you would catch user requesting vpl011 without 
having the vpl011 built.

> +    if ( vpl011 )
> +    {
> +        ret = make_vpl011_uart_node(d, kinfo->fdt, addrcells, sizecells);
> +        if ( ret )
> +            goto err;
> +    }
> +#endif
> +
>       ret = fdt_end_node(kinfo->fdt);
>       if ( ret < 0 )
>           goto err;
> @@ -2467,7 +2527,7 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
>       d->arch.type = kinfo.type;
>       allocate_memory(d, &kinfo);
>   
> -    rc = prepare_dtb_domU(d, &kinfo);
> +    rc = prepare_dtb_domU(d, &kinfo, vpl011);
>       if ( rc < 0 )
>           return rc;
>   
> 

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

* Re: [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (20 preceding siblings ...)
  2018-07-06 23:12 ` [PATCH v2 21/21] xen/arm: split domain_build.c Stefano Stabellini
@ 2018-07-12 18:18 ` Julien Grall
  2018-07-13 20:54   ` Stefano Stabellini
  2018-07-23 17:14 ` Andrii Anisov
  22 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-12 18:18 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: andrew.cooper3, nd, andrii_anisov, jbeulich, xen-devel

Hi,

Would it be possible to provide a branch with the patch applied? It 
would be nice to have that for every version, so I can easily know on 
which version of you are based and avoid spending time trying to apply 
it :).

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

* Re: [PATCH v2 09/21] xen/arm: move cmdline out of boot_modules
  2018-07-10 21:11       ` Julien Grall
@ 2018-07-13  0:04         ` Stefano Stabellini
  0 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-13  0:04 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, nd, Stefano Stabellini, andrii_anisov, xen-devel

On Tue, 10 Jul 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 10/07/2018 01:00, Stefano Stabellini wrote:
> > On Mon, 9 Jul 2018, Julien Grall wrote:
> > > Hi,
> > > 
> > > On 07/07/18 00:12, Stefano Stabellini wrote:
> > > > Remove the cmdline field from struct boot_module, cmdline is stored
> > > > independently out of the boot_modules array as dom0_cmdline.
> > > 
> > > I am not entirely convince of this patch, this does not seem to go towards
> > > a
> > > better code base because dom0_cmdline is only set if "bootargs". This may
> > > raise some confusing to the developer.
> > 
> > I'll add a comment on top of dom0_cmdline to clarify its purpose:
> > 
> > /*
> >   * Dom0 command line as passed via Device Tree as "bootargs" for the
> >   * Dom0 kernel module.
> >   */
> > 
> > 
> > > I would still prefer to keep the command-line in the boot module structure
> > > and
> > > find a way to associated the bootmodule with a node.
> > 
> > How do you suggest we find a good way to associate a boot module with a
> > node?
> > 
> > I have thought about this problem quite a bit. Although I admit this
> > patch is not super nice, it is the best option I found. I have actually
> > developed 2 other completely different implementations of this fix and
> > they were all worse than this. This is the third incarnation. It is
> > actually surprisingly easy to do worse than this patch.
> 
> I actually have an idea. Looking at the Device-Tree specification [1], a path
> should always be unique. This means that for a given path a/b/c/d, d will
> always be unique.
> 
> Reading the binding you introduced, the multiboot node will be a child of a
> node with the compatible "xen,domain". As the name of the parent node will be
> unique, you can tag the boot-module with that name. No need for the full path
> as all the configuration node should follow the pattern /chosen/<domain-name>.
> 
> When the guest is built, you have the Device-Tree path of the configuration in
> hand. From that you can deduce the name that you could re-use to find the
> correct boot-module.
> 
> You may still require a separate handling similar to your next patch of Dom0
> as with the current wording they could be a level deeper. But we can tight the
> wording for the new bindings (though, I think it is tight enough).
> 
> What do you think?
> 
> Now regarding the current implementation, it does not follow the defined
> specification. The multiboot nodes are looked everywhere in the DT rather than
> only /chosen. This is an implementation bug and should be fixed.

After our discussion this morning, I introduced a separate array to
store the cmdline of the boot modules. The second array uses the device
tree node name as index.

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

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

* Re: [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree
  2018-07-12 18:18 ` [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Julien Grall
@ 2018-07-13 20:54   ` Stefano Stabellini
  2018-07-18 16:48     ` Julien Grall
  0 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-13 20:54 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, andrii_anisov, andrew.cooper3, xen-devel,
	jbeulich, nd

On Thu, 12 Jul 2018, Julien Grall wrote:
> Hi,
> 
> Would it be possible to provide a branch with the patch applied? It would be
> nice to have that for every version, so I can easily know on which version of
> you are based and avoid spending time trying to apply it :).

Makes sense, I'll do from next time

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

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

* Re: [PATCH v2 15/21] xen/arm: generate vpl011 node on device tree for domU
  2018-07-12 18:14   ` Julien Grall
@ 2018-07-13 21:24     ` Stefano Stabellini
  0 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-13 21:24 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, nd, Stefano Stabellini, andrii_anisov, xen-devel

On Thu, 12 Jul 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 07/07/2018 00:12, Stefano Stabellini wrote:
> > Introduce vpl011 support to guests started from Xen: it provides a
> > simple way to print output from a guest, as most guests come with a
> > pl011 driver. It is also able to provide a working console with
> > interrupt support.
> > 
> > The UART exposed to the guest is a SBSA compatible UART and not a PL011.
> > SBSA UART is a subset of PL011 r1p5. A full PL011 implementation in Xen
> > would just be too difficult, so guests may require some drivers changes.
> > 
> > Enable vpl011 conditionally if the user requested it.
> > 
> > Make set_interrupt_ppi able to handle non-PPI and rename it
> > set_interrupt.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > ---
> > 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 | 90
> > +++++++++++++++++++++++++++++++++++++--------
> >   1 file changed, 75 insertions(+), 15 deletions(-)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 48a91ad..718be48 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -519,17 +519,17 @@ static int write_properties(struct domain *d, struct
> > kernel_info *kinfo,
> >     typedef __be32 gic_interrupt_t[3];
> >   -static void set_interrupt_ppi(gic_interrupt_t interrupt, unsigned int
> > irq,
> > -                              unsigned int cpumask, unsigned int level)
> > +static void set_interrupt(gic_interrupt_t interrupt, unsigned int irq,
> > +                          unsigned int cpumask, unsigned int level)
> >   {
> >       __be32 *cells = interrupt;
> > +    int is_ppi = (irq < 32);
> 
> I was about to suggest a bool, but I am not entirely sure what would be the
> value when it is true.
> 
> However, I think you want this to be !!(irq < 32) to make ensure it will be
> 0/1.

OK


> >   -    BUG_ON(irq < 16);
> > -    BUG_ON(irq >= 32);
> 
> Can we keep an ASSERT/BUG_ON to confirm no SGI is passed here?

Yes


> > +    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);
> >   }
> >   @@ -648,7 +648,7 @@ static int 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;
> > @@ -924,15 +924,15 @@ static int 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 )
> > @@ -1503,9 +1503,9 @@ static int 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 )
> > @@ -1520,12 +1520,63 @@ static int make_timer_domU_node(const struct domain
> > *d, void *fdt)
> >       return res;
> >   }
> >   +#ifdef CONFIG_SBSA_VUART_CONSOLE
> > +static int make_vpl011_uart_node(const struct domain *d, void *fdt,
> > +                                 int addrcells, int sizecells)
> > +{
> > +    int res;
> > +    gic_interrupt_t intr;
> > +    int reg_size = addrcells + sizecells;
> > +    int nr_cells = reg_size;
> > +    __be32 reg[nr_cells];
> > +    __be32 *cells;
> > +
> > +    res = fdt_begin_node(fdt, "sbsa-pl011");
> > +    if ( res )
> > +        return res;
> > +
> > +    res = fdt_property_string(fdt, "compatible", "arm,sbsa-uart");
> > +    if ( res )
> > +        return res;
> > +
> > +    cells = &reg[0];
> > +    dt_child_set_range(&cells, addrcells, sizecells, GUEST_PL011_BASE,
> > +                       GUEST_PL011_SIZE);
> > +    if ( res )
> > +        return res;
> > +    res = fdt_property(fdt, "reg", reg, sizeof(reg));
> > +    if ( res )
> > +        return res;
> > +
> > +    set_interrupt(intr, GUEST_VPL011_SPI, 0xf, DT_IRQ_TYPE_LEVEL_HIGH);
> > +
> > +    res = fdt_property(fdt, "interrupts", intr, sizeof (intr));
> > +    if ( res )
> > +        return res;
> > +
> > +    res = fdt_property_cell(fdt, "interrupt-parent",
> > +                            GUEST_PHANDLE_GIC);
> > +    if ( res )
> > +        return res;
> > +
> > +    /* Use a default baud rate of 115200. */
> > +    fdt_property_u32(fdt, "current-speed", 115200);
> > +
> > +    res = fdt_end_node(fdt);
> > +    if ( res )
> > +        return res;
> > +
> > +    return 0;
> > +}
> > +#endif
> > +
> >   /*
> >    * The max size for DT is 2MB. However, the generated DT is small, 4KB
> >    * are enough for now, but we might have to increase it in the feature.
> >    */
> >   #define DOMU_DTB_SIZE 4096
> > -static int prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
> > +static int prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo,
> > +                            bool vpl011)
> 
> Could we store this boolean in kernel_info? Or could it be deduced from struct
> domain *d?

OK


> >   {
> >       int addrcells, sizecells;
> >       int ret;
> > @@ -1585,6 +1636,15 @@ static int prepare_dtb_domU(struct domain *d, struct
> > kernel_info *kinfo)
> >       if ( ret )
> >           goto err;
> >   +#ifdef CONFIG_SBSA_VUART_CONSOLE
> 
> I think I would prefer if you implement make_vpl011_uart_node(...) return an
> error above. So you would catch user requesting vpl011 without having the
> vpl011 built.

I can do that


> > +    if ( vpl011 )
> > +    {
> > +        ret = make_vpl011_uart_node(d, kinfo->fdt, addrcells, sizecells);
> > +        if ( ret )
> > +            goto err;
> > +    }
> > +#endif
> > +
> >       ret = fdt_end_node(kinfo->fdt);
> >       if ( ret < 0 )
> >           goto err;
> > @@ -2467,7 +2527,7 @@ static int __init construct_domU(struct domain *d,
> > struct dt_device_node *node)
> >       d->arch.type = kinfo.type;
> >       allocate_memory(d, &kinfo);
> >   -    rc = prepare_dtb_domU(d, &kinfo);
> > +    rc = prepare_dtb_domU(d, &kinfo, vpl011);
> >       if ( rc < 0 )
> >           return rc;
> >   

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

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

* Re: [PATCH v2 05/21] xen/arm: extend device tree based multiboot protocol
  2018-07-09 14:07   ` Julien Grall
@ 2018-07-13 22:41     ` Stefano Stabellini
  2018-07-16 14:14       ` Julien Grall
  0 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-13 22:41 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Mon, 9 Jul 2018, Julien Grall wrote:
> Hi,
> 
> On 07/07/18 00:12, Stefano Stabellini wrote:
> > 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 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 | 108
> > ++++++++++++++++++++++++++++++++++
> >   1 file changed, 108 insertions(+)
> > 
> > diff --git a/docs/misc/arm/device-tree/booting.txt
> > b/docs/misc/arm/device-tree/booting.txt
> > index ce2d0dc..5c3b8da 100644
> > --- a/docs/misc/arm/device-tree/booting.txt
> > +++ b/docs/misc/arm/device-tree/booting.txt
> > @@ -119,3 +119,111 @@ 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"
> > +    For dom0: "xen,domain", "xen,initial-domain"
> 
> Looking briefly at the code, I don't see any support of "xen,initial-domain".
> Did I miss anything?
> 
> But, it is a bit strange to put that in compatible. Shouldn't this be a
> property?

I haven't implemened this in this series yet. Let's add
"xen,initial-domain" to the spec together with the implementation in one
of the follow-up series.

 
> > +
> > +- memory
> > +
> > +    An integer specifying the amount of megabytes of RAM to allocate to
> > +    the guest.
> 
> I would define this a KB. With Dom0less it would be easy to spawn a guest with
> less than a MB of memory. What matter is the amount of memory should be
> page-aligned.

I think it would be good to allow users to specify the memory in KB, you
are right that we might be able to have <1MB guests. At the same time,
it is a pain to have to deal with KBs when allocating multi GBs guests.

Any suggestion on how to make this more user friendly? Maybe we could
find a way to support multiple units, for instance we could support
memory_mb (for MBs) and memory_kb (for KBs).

Or we could just suck it up and use KBs only. I mean, if we have to
support one unit only, it should probably be KBs. I wonder if it makes
sense to rename memory to memory_<unit> in any case for clarity.


> > +
> > +- cpus
> > +
> > +    An integer specifying the number of vcpus to allocate to the guest.
> > +
> > +- vpl011
> > +
> > +    An integer to enable/disable a virtual pl011 for the guest to use.
> 
> The interrupt is a bit confusing here. What value will enable? What value will
> disable?
> 
> I think you can just make an empty property.

OK

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

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

* Re: [PATCH v2 05/21] xen/arm: extend device tree based multiboot protocol
  2018-07-13 22:41     ` Stefano Stabellini
@ 2018-07-16 14:14       ` Julien Grall
  2018-07-16 22:02         ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-16 14:14 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 13/07/18 23:41, Stefano Stabellini wrote:
> On Mon, 9 Jul 2018, Julien Grall wrote:
>> On 07/07/18 00:12, Stefano Stabellini wrote:
>>> 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 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 | 108
>>> ++++++++++++++++++++++++++++++++++
>>>    1 file changed, 108 insertions(+)
>>>
>>> diff --git a/docs/misc/arm/device-tree/booting.txt
>>> b/docs/misc/arm/device-tree/booting.txt
>>> index ce2d0dc..5c3b8da 100644
>>> --- a/docs/misc/arm/device-tree/booting.txt
>>> +++ b/docs/misc/arm/device-tree/booting.txt
>>> @@ -119,3 +119,111 @@ 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"
>>> +    For dom0: "xen,domain", "xen,initial-domain"
>>
>> Looking briefly at the code, I don't see any support of "xen,initial-domain".
>> Did I miss anything?
>>
>> But, it is a bit strange to put that in compatible. Shouldn't this be a
>> property?
> 
> I haven't implemened this in this series yet. Let's add
> "xen,initial-domain" to the spec together with the implementation in one
> of the follow-up series.
> 
>   
>>> +
>>> +- memory
>>> +
>>> +    An integer specifying the amount of megabytes of RAM to allocate to
>>> +    the guest.
>>
>> I would define this a KB. With Dom0less it would be easy to spawn a guest with
>> less than a MB of memory. What matter is the amount of memory should be
>> page-aligned.
> 
> I think it would be good to allow users to specify the memory in KB, you
> are right that we might be able to have <1MB guests. At the same time,
> it is a pain to have to deal with KBs when allocating multi GBs guests.

It is not very difficult, You just use your wcalc (or any calculator) 
and do a shift 30.

> 
> Any suggestion on how to make this more user friendly? Maybe we could
> find a way to support multiple units, for instance we could support
> memory_mb (for MBs) and memory_kb (for KBs).

That's ugly because you know have to describe clearly what they are for 
or otherwise someone may think it would be fine to describe your 1.5GB 
guest as:

memory_gb = 1
memory_mb = 512

If you want to make user-friendly then provide macros to generate the 
device-tree. This is already used for describe GIC controller in Linux.

> 
> Or we could just suck it up and use KBs only. I mean, if we have to
> support one unit only, it should probably be KBs. I wonder if it makes
> sense to rename memory to memory_<unit> in any case for clarity.

I would prefer to keep "memory" and encourage users to read the 
associated documentation.

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

* Re: [PATCH v2 19/21] xen/arm: introduce create_domUs
  2018-07-06 23:12 ` [PATCH v2 19/21] xen/arm: introduce create_domUs Stefano Stabellini
@ 2018-07-16 16:10   ` Jan Beulich
  2018-07-16 21:44     ` Stefano Stabellini
  2018-07-24 13:53   ` Julien Grall
  1 sibling, 1 reply; 92+ messages in thread
From: Jan Beulich @ 2018-07-16 16:10 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Andrew Cooper, Julien Grall, andrii_anisov, Stefano Stabellini,
	xen-devel

>>> On 07.07.18 at 01:12, <sstabellini@kernel.org> wrote:
> --- a/xen/include/asm-x86/setup.h
> +++ b/xen/include/asm-x86/setup.h
> @@ -73,4 +73,6 @@ extern bool opt_dom0_shadow;
>  #endif
>  extern bool dom0_pvh;
>  
> +#define max_init_domid (1)

Why is this 1 rather than 0? Or is the name imprecise?

Jan



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

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

* Re: [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-06 23:12 ` [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM Stefano Stabellini
@ 2018-07-16 16:19   ` Jan Beulich
  2018-07-16 21:55     ` Stefano Stabellini
  2018-07-17 20:29   ` Julien Grall
  2018-07-17 20:34   ` Julien Grall
  2 siblings, 1 reply; 92+ messages in thread
From: Jan Beulich @ 2018-07-16 16:19 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Tim Deegan, Wei Liu, George Dunlap, Andrew Cooper,
	Stefano Stabellini, Ian Jackson, xen-devel, Julien Grall,
	andrii_anisov

>>> On 07.07.18 at 01:12, <sstabellini@kernel.org> wrote:
> @@ -389,29 +392,49 @@ static void dump_console_ring_key(unsigned char key)
>      free_xenheap_pages(buf, order);
>  }
>  
> -/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
> +/*
> + * CTRL-<switch_char> switches input direction between Xen, Dom0 and
> + * DomUs.
> + */
>  #define switch_code (opt_conswitch[0]-'a'+1)
> -static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain 0. */
> +static int __read_mostly xen_rx = 1; /* 1 => input passed to domain 0. */

I guess this variable wants renaming now.

>  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]);
> +    xen_rx++;
> +    if ( xen_rx == max_init_domid + 1 )
> +        xen_rx = 0;
> +
> +    if ( !xen_rx )
> +        printk("*** Serial input xen_rx=%d -> %s", xen_rx, "Xen");
> +    else
> +        printk("*** Serial input xen_rx=%d -> DOM%d", xen_rx, xen_rx - 1);

What are the xen_rx= doing in the format string? They weren't there before.

>      if ( switch_code )
> -        printk(" (type 'CTRL-%c' three times to switch input to %s)",
> -               opt_conswitch[0], input_str[!xen_rx]);
> +        printk(" (type 'CTRL-%c' three times to switch input)",
> +               opt_conswitch[0]);
>      printk("\n");
>  }
>  
>  static void __serial_rx(char c, struct cpu_user_regs *regs)
>  {
> -    if ( xen_rx )
> +    if ( xen_rx == 0 )
>          return handle_keypress(c, regs);
>  
> -    /* Deliver input to guest buffer, unless it is already full. */
> -    if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
> -        serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> +    if ( xen_rx == 1 )
> +    {
> +        /* Deliver input to guest buffer, unless it is already full. */
> +        if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )

Please add blanks around the - .

> +            serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> +    }
> +#ifdef CONFIG_ARM

CONFIG_HAS_PL011 ?

> +    else
> +    {
> +        struct domain *d = get_domain_by_id(xen_rx - 1);
> +        if ( !d->arch.vpl011.ring_enable && d->arch.vpl011.inring != NULL )

Blank line between these two lines please.

> @@ -933,9 +956,6 @@ void __init console_endboot(void)
>                              "decrease log level threshold", 0);
>      register_irq_keyhandler('G', &do_toggle_guest,
>                              "toggle host/guest log level adjustment", 0);
> -
> -    /* Serial input is directed to DOM0 by default. */
> -    switch_serial_input();

This removes an imo helpful boot time message. Is that intentional,
and if so why?

Jan



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

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

* Re: [PATCH v2 19/21] xen/arm: introduce create_domUs
  2018-07-16 16:10   ` Jan Beulich
@ 2018-07-16 21:44     ` Stefano Stabellini
  0 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-16 21:44 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov,
	Andrew Cooper, xen-devel, Julien Grall

On Mon, 16 Jul 2018, Jan Beulich wrote:
> >>> On 07.07.18 at 01:12, <sstabellini@kernel.org> wrote:
> > --- a/xen/include/asm-x86/setup.h
> > +++ b/xen/include/asm-x86/setup.h
> > @@ -73,4 +73,6 @@ extern bool opt_dom0_shadow;
> >  #endif
> >  extern bool dom0_pvh;
> >  
> > +#define max_init_domid (1)
> 
> Why is this 1 rather than 0? Or is the name imprecise?

Yeah, the name is imprecise. On x86 there is always only dom0 at boot,
so this variable is set to 0+1 = 1. I can change the variable to
actually match the name, so that on a system with only dom0 at boot,
max_init_domid would be (0). It makes more sense that way.

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

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

* Re: [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-16 16:19   ` Jan Beulich
@ 2018-07-16 21:55     ` Stefano Stabellini
  2018-07-17  6:37       ` Jan Beulich
  2018-07-17  8:40       ` Jan Beulich
  0 siblings, 2 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-16 21:55 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Stefano Stabellini, Ian Jackson, xen-devel,
	Julien Grall, andrii_anisov

On Mon, 16 Jul 2018, Jan Beulich wrote:
> >>> On 07.07.18 at 01:12, <sstabellini@kernel.org> wrote:
> > @@ -389,29 +392,49 @@ static void dump_console_ring_key(unsigned char key)
> >      free_xenheap_pages(buf, order);
> >  }
> >  
> > -/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
> > +/*
> > + * CTRL-<switch_char> switches input direction between Xen, Dom0 and
> > + * DomUs.
> > + */
> >  #define switch_code (opt_conswitch[0]-'a'+1)
> > -static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain 0. */
> > +static int __read_mostly xen_rx = 1; /* 1 => input passed to domain 0. */
> 
> I guess this variable wants renaming now.

Yeah. What about `console_rx'? 


> >  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]);
> > +    xen_rx++;
> > +    if ( xen_rx == max_init_domid + 1 )
> > +        xen_rx = 0;
> > +
> > +    if ( !xen_rx )
> > +        printk("*** Serial input xen_rx=%d -> %s", xen_rx, "Xen");
> > +    else
> > +        printk("*** Serial input xen_rx=%d -> DOM%d", xen_rx, xen_rx - 1);
> 
> What are the xen_rx= doing in the format string? They weren't there before.

Ah yes, we don't want to print "xen_rx" anywhere, it's a leftover from
my debugging. I'll remove it completely:

  if ( !xen_rx )
      printk("*** Serial input to Xen");
  else
      printk("*** Serial input to DOM%d", xen_rx - 1);


> >      if ( switch_code )
> > -        printk(" (type 'CTRL-%c' three times to switch input to %s)",
> > -               opt_conswitch[0], input_str[!xen_rx]);
> > +        printk(" (type 'CTRL-%c' three times to switch input)",
> > +               opt_conswitch[0]);
> >      printk("\n");
> >  }
> >  
> >  static void __serial_rx(char c, struct cpu_user_regs *regs)
> >  {
> > -    if ( xen_rx )
> > +    if ( xen_rx == 0 )
> >          return handle_keypress(c, regs);
> >  
> > -    /* Deliver input to guest buffer, unless it is already full. */
> > -    if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
> > -        serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> > +    if ( xen_rx == 1 )
> > +    {
> > +        /* Deliver input to guest buffer, unless it is already full. */
> > +        if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
> 
> Please add blanks around the - .

I'll do


> > +            serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> > +    }
> > +#ifdef CONFIG_ARM
> 
> CONFIG_HAS_PL011 ?

I had already spotted this problem. I turned it into:

  #if defined(CONFIG_ARM) && defined(CONFIG_SBSA_VUART_CONSOLE)

It's CONFIG_SBSA_VUART_CONSOLE rather than CONFIG_HAS_PL011 because this
has to do with the virtual pl011 implementation rather than the physical
driver in Xen.


> > +    else
> > +    {
> > +        struct domain *d = get_domain_by_id(xen_rx - 1);
> > +        if ( !d->arch.vpl011.ring_enable && d->arch.vpl011.inring != NULL )
> 
> Blank line between these two lines please.

OK


> > @@ -933,9 +956,6 @@ void __init console_endboot(void)
> >                              "decrease log level threshold", 0);
> >      register_irq_keyhandler('G', &do_toggle_guest,
> >                              "toggle host/guest log level adjustment", 0);
> > -
> > -    /* Serial input is directed to DOM0 by default. */
> > -    switch_serial_input();
> 
> This removes an imo helpful boot time message. Is that intentional,
> and if so why?
 
Yes, it was intentional. switch_serial_input increases xen_rx, I thought
it didn't make too much sense to do that at boot, and would be clearer
to just initialize xen_rx to the wanted value from the get go (the value
would be 1 for dom0). Also, in previous implementations of this patch it
was actually required, but not anymore.

In fact, if you prefer, I could also keep this switch_serial_input()
call as-is and change the initial value of xen_rx to 0. That would also
work, as the increase of xen_rx here would end up selecting still dom0
for input.

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

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

* Re: [PATCH v2 05/21] xen/arm: extend device tree based multiboot protocol
  2018-07-16 14:14       ` Julien Grall
@ 2018-07-16 22:02         ` Stefano Stabellini
  0 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-16 22:02 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Mon, 16 Jul 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 13/07/18 23:41, Stefano Stabellini wrote:
> > On Mon, 9 Jul 2018, Julien Grall wrote:
> > > On 07/07/18 00:12, Stefano Stabellini wrote:
> > > > 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 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 | 108
> > > > ++++++++++++++++++++++++++++++++++
> > > >    1 file changed, 108 insertions(+)
> > > > 
> > > > diff --git a/docs/misc/arm/device-tree/booting.txt
> > > > b/docs/misc/arm/device-tree/booting.txt
> > > > index ce2d0dc..5c3b8da 100644
> > > > --- a/docs/misc/arm/device-tree/booting.txt
> > > > +++ b/docs/misc/arm/device-tree/booting.txt
> > > > @@ -119,3 +119,111 @@ 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"
> > > > +    For dom0: "xen,domain", "xen,initial-domain"
> > > 
> > > Looking briefly at the code, I don't see any support of
> > > "xen,initial-domain".
> > > Did I miss anything?
> > > 
> > > But, it is a bit strange to put that in compatible. Shouldn't this be a
> > > property?
> > 
> > I haven't implemened this in this series yet. Let's add
> > "xen,initial-domain" to the spec together with the implementation in one
> > of the follow-up series.
> > 
> >   
> > > > +
> > > > +- memory
> > > > +
> > > > +    An integer specifying the amount of megabytes of RAM to allocate to
> > > > +    the guest.
> > > 
> > > I would define this a KB. With Dom0less it would be easy to spawn a guest
> > > with
> > > less than a MB of memory. What matter is the amount of memory should be
> > > page-aligned.
> > 
> > I think it would be good to allow users to specify the memory in KB, you
> > are right that we might be able to have <1MB guests. At the same time,
> > it is a pain to have to deal with KBs when allocating multi GBs guests.
> 
> It is not very difficult, You just use your wcalc (or any calculator) and do a
> shift 30.
> 
> > 
> > Any suggestion on how to make this more user friendly? Maybe we could
> > find a way to support multiple units, for instance we could support
> > memory_mb (for MBs) and memory_kb (for KBs).
> 
> That's ugly because you know have to describe clearly what they are for or
> otherwise someone may think it would be fine to describe your 1.5GB guest as:
> 
> memory_gb = 1
> memory_mb = 512

Yes, that would be bad


> If you want to make user-friendly then provide macros to generate the
> device-tree. This is already used for describe GIC controller in Linux.
>
> > Or we could just suck it up and use KBs only. I mean, if we have to
> > support one unit only, it should probably be KBs. I wonder if it makes
> > sense to rename memory to memory_<unit> in any case for clarity.
> 
> I would prefer to keep "memory" and encourage users to read the associated
> documentation.

I'll keep memory and only use kb for now. If somebody comes up with a
good idea we can switch to that in follow versions.

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

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

* Re: [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-16 21:55     ` Stefano Stabellini
@ 2018-07-17  6:37       ` Jan Beulich
  2018-07-17 16:43         ` Stefano Stabellini
  2018-07-17  8:40       ` Jan Beulich
  1 sibling, 1 reply; 92+ messages in thread
From: Jan Beulich @ 2018-07-17  6:37 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Tim Deegan, Wei Liu, George Dunlap, Andrew Cooper,
	Stefano Stabellini, Ian Jackson, xen-devel, Julien Grall,
	andrii_anisov

>>> On 16.07.18 at 23:55, <sstabellini@kernel.org> wrote:
> On Mon, 16 Jul 2018, Jan Beulich wrote:
>> >>> On 07.07.18 at 01:12, <sstabellini@kernel.org> wrote:
>> > @@ -389,29 +392,49 @@ static void dump_console_ring_key(unsigned char key)
>> >      free_xenheap_pages(buf, order);
>> >  }
>> >  
>> > -/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
>> > +/*
>> > + * CTRL-<switch_char> switches input direction between Xen, Dom0 and
>> > + * DomUs.
>> > + */
>> >  #define switch_code (opt_conswitch[0]-'a'+1)
>> > -static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain 0. */
>> > +static int __read_mostly xen_rx = 1; /* 1 => input passed to domain 0. */
>> 
>> I guess this variable wants renaming now.
> 
> Yeah. What about `console_rx'? 

That's reasonable. Another option would be to use rx_domid, and store
actual domain IDs there (DOMID_XEN for Xen). That'll make the switching
logic slightly larger, but perhaps provide a better understandable end
result.

>> > @@ -933,9 +956,6 @@ void __init console_endboot(void)
>> >                              "decrease log level threshold", 0);
>> >      register_irq_keyhandler('G', &do_toggle_guest,
>> >                              "toggle host/guest log level adjustment", 0);
>> > -
>> > -    /* Serial input is directed to DOM0 by default. */
>> > -    switch_serial_input();
>> 
>> This removes an imo helpful boot time message. Is that intentional,
>> and if so why?
>  
> Yes, it was intentional. switch_serial_input increases xen_rx, I thought
> it didn't make too much sense to do that at boot, and would be clearer
> to just initialize xen_rx to the wanted value from the get go (the value
> would be 1 for dom0). Also, in previous implementations of this patch it
> was actually required, but not anymore.
> 
> In fact, if you prefer, I could also keep this switch_serial_input()
> call as-is and change the initial value of xen_rx to 0. That would also
> work, as the increase of xen_rx here would end up selecting still dom0
> for input.

Yes, I'd prefer if you left it untouched. The idea after all is that prior
to reaching here input goes to Xen, and only from here on it goes to
Dom0.

Jan



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

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

* Re: [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-16 21:55     ` Stefano Stabellini
  2018-07-17  6:37       ` Jan Beulich
@ 2018-07-17  8:40       ` Jan Beulich
  2018-07-17 16:33         ` Stefano Stabellini
  1 sibling, 1 reply; 92+ messages in thread
From: Jan Beulich @ 2018-07-17  8:40 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Tim Deegan, Wei Liu, George Dunlap, Andrew Cooper,
	Stefano Stabellini, Ian Jackson, xen-devel, Julien Grall,
	andrii_anisov

>>> On 16.07.18 at 23:55, <sstabellini@kernel.org> wrote:
> On Mon, 16 Jul 2018, Jan Beulich wrote:
>> >>> On 07.07.18 at 01:12, <sstabellini@kernel.org> wrote:
>> > +            serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
>> > +    }
>> > +#ifdef CONFIG_ARM
>> 
>> CONFIG_HAS_PL011 ?
> 
> I had already spotted this problem. I turned it into:
> 
>   #if defined(CONFIG_ARM) && defined(CONFIG_SBSA_VUART_CONSOLE)
> 
> It's CONFIG_SBSA_VUART_CONSOLE rather than CONFIG_HAS_PL011 because this
> has to do with the virtual pl011 implementation rather than the physical
> driver in Xen.

I see. But why still the CONFIG_ARM?

Jan



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

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

* Re: [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-17  8:40       ` Jan Beulich
@ 2018-07-17 16:33         ` Stefano Stabellini
  0 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-17 16:33 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Stefano Stabellini, Ian Jackson, xen-devel,
	Julien Grall, andrii_anisov

On Tue, 17 Jul 2018, Jan Beulich wrote:
> >>> On 16.07.18 at 23:55, <sstabellini@kernel.org> wrote:
> > On Mon, 16 Jul 2018, Jan Beulich wrote:
> >> >>> On 07.07.18 at 01:12, <sstabellini@kernel.org> wrote:
> >> > +            serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> >> > +    }
> >> > +#ifdef CONFIG_ARM
> >> 
> >> CONFIG_HAS_PL011 ?
> > 
> > I had already spotted this problem. I turned it into:
> > 
> >   #if defined(CONFIG_ARM) && defined(CONFIG_SBSA_VUART_CONSOLE)
> > 
> > It's CONFIG_SBSA_VUART_CONSOLE rather than CONFIG_HAS_PL011 because this
> > has to do with the virtual pl011 implementation rather than the physical
> > driver in Xen.
> 
> I see. But why still the CONFIG_ARM?

Good point, I'll remove it.

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

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

* Re: [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-17  6:37       ` Jan Beulich
@ 2018-07-17 16:43         ` Stefano Stabellini
  2018-07-18  6:41           ` Jan Beulich
  0 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-17 16:43 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Stefano Stabellini, Ian Jackson, xen-devel,
	Julien Grall, andrii_anisov

On Tue, 17 Jul 2018, Jan Beulich wrote:
> >>> On 16.07.18 at 23:55, <sstabellini@kernel.org> wrote:
> > On Mon, 16 Jul 2018, Jan Beulich wrote:
> >> >>> On 07.07.18 at 01:12, <sstabellini@kernel.org> wrote:
> >> > @@ -389,29 +392,49 @@ static void dump_console_ring_key(unsigned char key)
> >> >      free_xenheap_pages(buf, order);
> >> >  }
> >> >  
> >> > -/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
> >> > +/*
> >> > + * CTRL-<switch_char> switches input direction between Xen, Dom0 and
> >> > + * DomUs.
> >> > + */
> >> >  #define switch_code (opt_conswitch[0]-'a'+1)
> >> > -static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain 0. */
> >> > +static int __read_mostly xen_rx = 1; /* 1 => input passed to domain 0. */
> >> 
> >> I guess this variable wants renaming now.
> > 
> > Yeah. What about `console_rx'? 
> 
> That's reasonable. Another option would be to use rx_domid, and store
> actual domain IDs there (DOMID_XEN for Xen). That'll make the switching
> logic slightly larger, but perhaps provide a better understandable end
> result.

What about keeping the logic simple and adding a better comment to
explain how console_rx works:

/*
 * console_rx=0 => input to xen
 * console_rx=1 => input to dom0
 * console_rx=N => input dom(N-1)
 */


> >> > @@ -933,9 +956,6 @@ void __init console_endboot(void)
> >> >                              "decrease log level threshold", 0);
> >> >      register_irq_keyhandler('G', &do_toggle_guest,
> >> >                              "toggle host/guest log level adjustment", 0);
> >> > -
> >> > -    /* Serial input is directed to DOM0 by default. */
> >> > -    switch_serial_input();
> >> 
> >> This removes an imo helpful boot time message. Is that intentional,
> >> and if so why?
> >  
> > Yes, it was intentional. switch_serial_input increases xen_rx, I thought
> > it didn't make too much sense to do that at boot, and would be clearer
> > to just initialize xen_rx to the wanted value from the get go (the value
> > would be 1 for dom0). Also, in previous implementations of this patch it
> > was actually required, but not anymore.
> > 
> > In fact, if you prefer, I could also keep this switch_serial_input()
> > call as-is and change the initial value of xen_rx to 0. That would also
> > work, as the increase of xen_rx here would end up selecting still dom0
> > for input.
> 
> Yes, I'd prefer if you left it untouched. The idea after all is that prior
> to reaching here input goes to Xen, and only from here on it goes to
> Dom0.
 
OK

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

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

* Re: [PATCH v2 03/21] xen: allow console_io hypercalls from certain DomUs
  2018-07-09 13:48   ` Julien Grall
@ 2018-07-17 20:05     ` Stefano Stabellini
  2018-07-17 20:26       ` Julien Grall
  0 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-17 20:05 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov,
	George.Dunlap, andrew.cooper3, ian.jackson, xen-devel, tim,
	jbeulich, wei.liu2, dgdegra

On Mon, 9 Jul 2018, Julien Grall wrote:
> Hi,
> 
> On 07/07/18 00:11, Stefano Stabellini wrote:
> > Introduce an is_console option to allow certain classes of domUs to use
> > the Xen console. Specifically, it will be used to give console access to
> > all domUs started from Xen from information on device tree.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > 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 v2:
> > - introduce is_console
> > - remove #ifdefs
> > ---
> >   xen/include/xen/sched.h | 2 ++
> >   xen/include/xsm/dummy.h | 2 ++
> >   xen/xsm/flask/hooks.c   | 5 ++++-
> >   3 files changed, 8 insertions(+), 1 deletion(-)
> > 
> > diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
> > index 99d2af2..d66cec0 100644
> > --- a/xen/include/xen/sched.h
> > +++ b/xen/include/xen/sched.h
> > @@ -379,6 +379,8 @@ struct domain
> >       bool             auto_node_affinity;
> >       /* Is this guest fully privileged (aka dom0)? */
> >       bool             is_privileged;
> > +    /* Can this guest access the Xen console? */
> > +    bool             is_console;
> >       /* Is this a xenstore domain (not dom0)? */
> >       bool             is_xenstore;
> >       /* Domain's VCPUs are pinned 1:1 to physical CPUs? */
> > diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
> > index ff6b2db..3888817 100644
> > --- a/xen/include/xsm/dummy.h
> > +++ b/xen/include/xsm/dummy.h
> > @@ -230,6 +230,8 @@ static XSM_INLINE int
> > xsm_memory_stat_reservation(XSM_DEFAULT_ARG struct domain
> >   static XSM_INLINE int xsm_console_io(XSM_DEFAULT_ARG struct domain *d, int
> > cmd)
> >   {
> >       XSM_ASSERT_ACTION(XSM_OTHER);
> > +    if ( d->is_console )
> > +        return xsm_default_action(XSM_HOOK, d, NULL);
> 
> I will let Daniel commenting on this change. However ...
> 
> >   #ifdef CONFIG_VERBOSE_DEBUG
> >       if ( cmd == CONSOLEIO_write )
> >           return xsm_default_action(XSM_HOOK, d, NULL);
> > diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
> > index 78bc326..2551e4e 100644
> > --- a/xen/xsm/flask/hooks.c
> > +++ b/xen/xsm/flask/hooks.c
> > @@ -443,7 +443,10 @@ static int flask_console_io(struct domain *d, int cmd)
> >           return avc_unknown_permission("console_io", cmd);
> >       }
> >   -    return domain_has_xen(d, perm);
> > +    if ( !d->is_console )
> > +        return domain_has_xen(d, perm);
> > +    else
> > +        return 0;
> 
> ... I don't think this change is correct. When a policy is used, the user is
> free to define what is the behavior. With your solution, you impose the
> console access even if the user didn't to not give the permission.

I was hoping Daniel would advise on the best way to do things here.

I thought that the idea was that granting a domain "is_console" is
equivalent to granting a domain XEN__READCONSOLE and XEN__WRITECONSOLE
permissions.  Thus, if is_console is set, we return 0 from
flask_console_io because the permissions check succeeds.

Given that I have accumulated many changes to this patch series, I'll
send out a new version now without making changes to this patch for now.

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

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

* Re: [PATCH v2 03/21] xen: allow console_io hypercalls from certain DomUs
  2018-07-17 20:05     ` Stefano Stabellini
@ 2018-07-17 20:26       ` Julien Grall
  2018-07-18 17:10         ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-17 20:26 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, andrii_anisov, George.Dunlap, andrew.cooper3,
	ian.jackson, xen-devel, tim, jbeulich, wei.liu2, dgdegra, nd

Hi Stefano,

On 17/07/2018 21:05, Stefano Stabellini wrote:
> On Mon, 9 Jul 2018, Julien Grall wrote:
>> Hi,
>>
>> On 07/07/18 00:11, Stefano Stabellini wrote:
>>> Introduce an is_console option to allow certain classes of domUs to use
>>> the Xen console. Specifically, it will be used to give console access to
>>> all domUs started from Xen from information on device tree.
>>>
>>> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
>>> 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 v2:
>>> - introduce is_console
>>> - remove #ifdefs
>>> ---
>>>    xen/include/xen/sched.h | 2 ++
>>>    xen/include/xsm/dummy.h | 2 ++
>>>    xen/xsm/flask/hooks.c   | 5 ++++-
>>>    3 files changed, 8 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
>>> index 99d2af2..d66cec0 100644
>>> --- a/xen/include/xen/sched.h
>>> +++ b/xen/include/xen/sched.h
>>> @@ -379,6 +379,8 @@ struct domain
>>>        bool             auto_node_affinity;
>>>        /* Is this guest fully privileged (aka dom0)? */
>>>        bool             is_privileged;
>>> +    /* Can this guest access the Xen console? */
>>> +    bool             is_console;
>>>        /* Is this a xenstore domain (not dom0)? */
>>>        bool             is_xenstore;
>>>        /* Domain's VCPUs are pinned 1:1 to physical CPUs? */
>>> diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
>>> index ff6b2db..3888817 100644
>>> --- a/xen/include/xsm/dummy.h
>>> +++ b/xen/include/xsm/dummy.h
>>> @@ -230,6 +230,8 @@ static XSM_INLINE int
>>> xsm_memory_stat_reservation(XSM_DEFAULT_ARG struct domain
>>>    static XSM_INLINE int xsm_console_io(XSM_DEFAULT_ARG struct domain *d, int
>>> cmd)
>>>    {
>>>        XSM_ASSERT_ACTION(XSM_OTHER);
>>> +    if ( d->is_console )
>>> +        return xsm_default_action(XSM_HOOK, d, NULL);
>>
>> I will let Daniel commenting on this change. However ...
>>
>>>    #ifdef CONFIG_VERBOSE_DEBUG
>>>        if ( cmd == CONSOLEIO_write )
>>>            return xsm_default_action(XSM_HOOK, d, NULL);
>>> diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
>>> index 78bc326..2551e4e 100644
>>> --- a/xen/xsm/flask/hooks.c
>>> +++ b/xen/xsm/flask/hooks.c
>>> @@ -443,7 +443,10 @@ static int flask_console_io(struct domain *d, int cmd)
>>>            return avc_unknown_permission("console_io", cmd);
>>>        }
>>>    -    return domain_has_xen(d, perm);
>>> +    if ( !d->is_console )
>>> +        return domain_has_xen(d, perm);
>>> +    else
>>> +        return 0;
>>
>> ... I don't think this change is correct. When a policy is used, the user is
>> free to define what is the behavior. With your solution, you impose the
>> console access even if the user didn't to not give the permission.
> 
> I was hoping Daniel would advise on the best way to do things here.
> 
> I thought that the idea was that granting a domain "is_console" is
> equivalent to granting a domain XEN__READCONSOLE and XEN__WRITECONSOLE
> permissions.  Thus, if is_console is set, we return 0 from
> flask_console_io because the permissions check succeeds.

Well, yes and no. That's equivalent when you use the dummy policy. When 
you have a flask policy you want to give the control to the user.

If you look at the code there are no such as d->is_privilege in that 
function. This means that the user define the policy for the hardware 
domain. Why would be d->is_console different here?

> 
> Given that I have accumulated many changes to this patch series, I'll
> send out a new version now without making changes to this patch for now.

I haven't finished to review the series yet and would appreciate some 
more time before resending it.

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

* Re: [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-06 23:12 ` [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM Stefano Stabellini
  2018-07-16 16:19   ` Jan Beulich
@ 2018-07-17 20:29   ` Julien Grall
  2018-07-18  7:12     ` Jan Beulich
  2018-07-17 20:34   ` Julien Grall
  2 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-17 20:29 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, andrii_anisov, George.Dunlap, andrew.cooper3,
	ian.jackson, xen-devel, tim, jbeulich, wei.liu2, nd

Hi Stefano,

On 07/07/2018 00:12, 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.
It feels a bit painful for the user to switch N times to get his domain 
console. Would it be possible to provide a new key binding where you 
type the domain ID you want to switch to?

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

* Re: [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-06 23:12 ` [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM Stefano Stabellini
  2018-07-16 16:19   ` Jan Beulich
  2018-07-17 20:29   ` Julien Grall
@ 2018-07-17 20:34   ` Julien Grall
  2018-07-18 17:31     ` Stefano Stabellini
  2 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-17 20:34 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, andrii_anisov, George.Dunlap, andrew.cooper3,
	ian.jackson, xen-devel, tim, jbeulich, wei.liu2, nd

Hi Stefano,

On 07/07/2018 00:12, 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.
> 
> 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 v2:
> - only call vpl011_rx_char if the vpl011 has been initialized
> ---
>   xen/drivers/char/console.c | 50 ++++++++++++++++++++++++++++++++--------------
>   1 file changed, 35 insertions(+), 15 deletions(-)
> 
> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> index 0f05369..d590bc0 100644
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -31,10 +31,13 @@
>   #include <xen/early_printk.h>
>   #include <xen/warning.h>
>   #include <xen/pv_console.h>
> +#include <asm/setup.h>
>   
>   #ifdef CONFIG_X86
>   #include <xen/consoled.h>
>   #include <asm/guest.h>
> +#else
> +#include <asm/vpl011.h>
>   #endif
>   
>   /* console: comma-separated list of console outputs. */
> @@ -389,29 +392,49 @@ static void dump_console_ring_key(unsigned char key)
>       free_xenheap_pages(buf, order);
>   }
>   
> -/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
> +/*
> + * CTRL-<switch_char> switches input direction between Xen, Dom0 and
> + * DomUs.
> + */
>   #define switch_code (opt_conswitch[0]-'a'+1)
> -static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain 0. */
> +static int __read_mostly xen_rx = 1; /* 1 => input passed to domain 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]);
> +    xen_rx++;
> +    if ( xen_rx == max_init_domid + 1 )
> +        xen_rx = 0;
> +
> +    if ( !xen_rx )
> +        printk("*** Serial input xen_rx=%d -> %s", xen_rx, "Xen");
> +    else
> +        printk("*** Serial input xen_rx=%d -> DOM%d", xen_rx, xen_rx - 1);
> +
>       if ( switch_code )
> -        printk(" (type 'CTRL-%c' three times to switch input to %s)",
> -               opt_conswitch[0], input_str[!xen_rx]);
> +        printk(" (type 'CTRL-%c' three times to switch input)",
> +               opt_conswitch[0]);
>       printk("\n");
>   }
>   
>   static void __serial_rx(char c, struct cpu_user_regs *regs)
>   {
> -    if ( xen_rx )
> +    if ( xen_rx == 0 )
>           return handle_keypress(c, regs);
>   
> -    /* Deliver input to guest buffer, unless it is already full. */
> -    if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
> -        serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> +    if ( xen_rx == 1 )
> +    {
> +        /* Deliver input to guest buffer, unless it is already full. */
> +        if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
> +            serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> +    }
> +#ifdef CONFIG_ARM
> +    else
> +    {
> +        struct domain *d = get_domain_by_id(xen_rx - 1);
> +        if ( !d->arch.vpl011.ring_enable && d->arch.vpl011.inring != NULL )

It sounds like you want to provide a macro here. So would make clearer 
what you are actually checking.

> +            vpl011_rx_char(d, c);

What happen in the case vpl011 is not enabled for that domain? Shouldn't 
you at least warn there are no console available?

> +    }
> +#endif
>       /* Always notify the guest: prevents receive path from getting stuck. */

This comment seems a bit wrong now, altough the comment seem to suggest 
may need to be taken care.

>       send_global_virq(VIRQ_CONSOLE);
>   
> @@ -923,7 +946,7 @@ void __init console_endboot(void)
>        * a useful 'how to switch' message.
>        */
>       if ( opt_conswitch[1] == 'x' )
> -        xen_rx = !xen_rx;
> +        xen_rx = 0;
>   
>       register_keyhandler('w', dump_console_ring_key,
>                           "synchronously dump console ring buffer (dmesg)", 0);
> @@ -933,9 +956,6 @@ void __init console_endboot(void)
>                               "decrease log level threshold", 0);
>       register_irq_keyhandler('G', &do_toggle_guest,
>                               "toggle host/guest log level adjustment", 0);
> -
> -    /* Serial input is directed to DOM0 by default. */
> -    switch_serial_input();
>   }
>   
>   int __init console_has(const char *device)
> 

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

* Re: [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-17 16:43         ` Stefano Stabellini
@ 2018-07-18  6:41           ` Jan Beulich
  2018-07-18 16:51             ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Jan Beulich @ 2018-07-18  6:41 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Tim Deegan, Wei Liu, George Dunlap, Andrew Cooper,
	Stefano Stabellini, Ian Jackson, xen-devel, Julien Grall,
	andrii_anisov

>>> On 17.07.18 at 18:43, <sstabellini@kernel.org> wrote:
> On Tue, 17 Jul 2018, Jan Beulich wrote:
>> >>> On 16.07.18 at 23:55, <sstabellini@kernel.org> wrote:
>> > On Mon, 16 Jul 2018, Jan Beulich wrote:
>> >> >>> On 07.07.18 at 01:12, <sstabellini@kernel.org> wrote:
>> >> > @@ -389,29 +392,49 @@ static void dump_console_ring_key(unsigned char key)
>> >> >      free_xenheap_pages(buf, order);
>> >> >  }
>> >> >  
>> >> > -/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
>> >> > +/*
>> >> > + * CTRL-<switch_char> switches input direction between Xen, Dom0 and
>> >> > + * DomUs.
>> >> > + */
>> >> >  #define switch_code (opt_conswitch[0]-'a'+1)
>> >> > -static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain 0. 
> */
>> >> > +static int __read_mostly xen_rx = 1; /* 1 => input passed to domain 0. */
>> >> 
>> >> I guess this variable wants renaming now.
>> > 
>> > Yeah. What about `console_rx'? 
>> 
>> That's reasonable. Another option would be to use rx_domid, and store
>> actual domain IDs there (DOMID_XEN for Xen). That'll make the switching
>> logic slightly larger, but perhaps provide a better understandable end
>> result.
> 
> What about keeping the logic simple and adding a better comment to
> explain how console_rx works:
> 
> /*
>  * console_rx=0 => input to xen
>  * console_rx=1 => input to dom0
>  * console_rx=N => input dom(N-1)
>  */

Well, as said - my suggestion is "another option", not something I'd insist
on. Unless others prefer on of them, I'd say it's up to you.

Jan



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

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

* Re: [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-17 20:29   ` Julien Grall
@ 2018-07-18  7:12     ` Jan Beulich
  2018-07-18 16:59       ` Julien Grall
  2018-07-18 17:01       ` Stefano Stabellini
  0 siblings, 2 replies; 92+ messages in thread
From: Jan Beulich @ 2018-07-18  7:12 UTC (permalink / raw)
  To: Julien Grall
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Stefano Stabellini, Ian Jackson, xen-devel,
	andrii_anisov, nd

>>> On 17.07.18 at 22:29, <julien.grall@arm.com> wrote:
> On 07/07/2018 00:12, 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.
> It feels a bit painful for the user to switch N times to get his domain 
> console. Would it be possible to provide a new key binding where you 
> type the domain ID you want to switch to?

Does that mean you'd want to use 0-9 for this purpose? I'd be
very hesitant to accept such, as we're pretty tight with available
characters already. And of course 0-9 wouldn't scale to Dom10
and beyond. If you have something else in mind, I think it would
help if you spelled this out.

Jan



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

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

* Re: [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree
  2018-07-13 20:54   ` Stefano Stabellini
@ 2018-07-18 16:48     ` Julien Grall
  2018-07-18 17:48       ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-18 16:48 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: andrew.cooper3, nd, andrii_anisov, jbeulich, xen-devel

Hi Stefano,

On 13/07/18 21:54, Stefano Stabellini wrote:
> On Thu, 12 Jul 2018, Julien Grall wrote:
>> Hi,
>>
>> Would it be possible to provide a branch with the patch applied? It would be
>> nice to have that for every version, so I can easily know on which version of
>> you are based and avoid spending time trying to apply it :).
> 
> Makes sense, I'll do from next time

Could you provide one from this version? So I can review some of your 
patches more easily.

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

* Re: [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-18  6:41           ` Jan Beulich
@ 2018-07-18 16:51             ` Stefano Stabellini
  0 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-18 16:51 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Stefano Stabellini, Ian Jackson, xen-devel,
	Julien Grall, andrii_anisov

On Wed, 18 Jul 2018, Jan Beulich wrote:
> >>> On 17.07.18 at 18:43, <sstabellini@kernel.org> wrote:
> > On Tue, 17 Jul 2018, Jan Beulich wrote:
> >> >>> On 16.07.18 at 23:55, <sstabellini@kernel.org> wrote:
> >> > On Mon, 16 Jul 2018, Jan Beulich wrote:
> >> >> >>> On 07.07.18 at 01:12, <sstabellini@kernel.org> wrote:
> >> >> > @@ -389,29 +392,49 @@ static void dump_console_ring_key(unsigned char key)
> >> >> >      free_xenheap_pages(buf, order);
> >> >> >  }
> >> >> >  
> >> >> > -/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
> >> >> > +/*
> >> >> > + * CTRL-<switch_char> switches input direction between Xen, Dom0 and
> >> >> > + * DomUs.
> >> >> > + */
> >> >> >  #define switch_code (opt_conswitch[0]-'a'+1)
> >> >> > -static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain 0. 
> > */
> >> >> > +static int __read_mostly xen_rx = 1; /* 1 => input passed to domain 0. */
> >> >> 
> >> >> I guess this variable wants renaming now.
> >> > 
> >> > Yeah. What about `console_rx'? 
> >> 
> >> That's reasonable. Another option would be to use rx_domid, and store
> >> actual domain IDs there (DOMID_XEN for Xen). That'll make the switching
> >> logic slightly larger, but perhaps provide a better understandable end
> >> result.
> > 
> > What about keeping the logic simple and adding a better comment to
> > explain how console_rx works:
> > 
> > /*
> >  * console_rx=0 => input to xen
> >  * console_rx=1 => input to dom0
> >  * console_rx=N => input dom(N-1)
> >  */
> 
> Well, as said - my suggestion is "another option", not something I'd insist
> on. Unless others prefer on of them, I'd say it's up to you.

Thank you, for being understanding. In that case, I'll keep it as is
(plus the comment) for the next version of the series. 

Of course, if you'll change your mind and decide that I have to change
it, I'll do in one of the follow-ups.

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

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

* Re: [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-18  7:12     ` Jan Beulich
@ 2018-07-18 16:59       ` Julien Grall
  2018-07-19  6:10         ` Jan Beulich
  2018-07-18 17:01       ` Stefano Stabellini
  1 sibling, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-18 16:59 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Stefano Stabellini, Ian Jackson, xen-devel,
	andrii_anisov, nd

Hi Jan,

On 18/07/18 08:12, Jan Beulich wrote:
>>>> On 17.07.18 at 22:29, <julien.grall@arm.com> wrote:
>> On 07/07/2018 00:12, 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.
>> It feels a bit painful for the user to switch N times to get his domain
>> console. Would it be possible to provide a new key binding where you
>> type the domain ID you want to switch to?
> 
> Does that mean you'd want to use 0-9 for this purpose? I'd be
> very hesitant to accept such, as we're pretty tight with available
> characters already. And of course 0-9 wouldn't scale to Dom10
> and beyond. If you have something else in mind, I think it would
> help if you spelled this out.

That what I had in mind. I agree that this solution would not scale to 
Dom10 and beyond. But that ring solution is not going to be any better.

Let's imagine you want to switch between domain 9 and 8. You would need 
to type CTRL-AAA N time before reaching the right console. N been the 
number of domain you have using the console.

It feels like, you want to provide a key for selecting the console (e.g 
'c') and then type the domain ID you want to access. Can you read 
another key when in the keyhandler?

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

* Re: [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-18  7:12     ` Jan Beulich
  2018-07-18 16:59       ` Julien Grall
@ 2018-07-18 17:01       ` Stefano Stabellini
  2018-07-18 20:37         ` George Dunlap
  1 sibling, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-18 17:01 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Stefano Stabellini, Ian Jackson, xen-devel,
	Julien Grall, andrii_anisov, nd

On Wed, 18 Jul 2018, Jan Beulich wrote:
> >>> On 17.07.18 at 22:29, <julien.grall@arm.com> wrote:
> > On 07/07/2018 00:12, 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.
> > It feels a bit painful for the user to switch N times to get his domain 
> > console. Would it be possible to provide a new key binding where you 
> > type the domain ID you want to switch to?
> 
> Does that mean you'd want to use 0-9 for this purpose? I'd be
> very hesitant to accept such, as we're pretty tight with available
> characters already. And of course 0-9 wouldn't scale to Dom10
> and beyond. If you have something else in mind, I think it would
> help if you spelled this out.

Let me premise that I think this is not important and the solution will
be fine even only with the existing Ctrl-AAA switching mechanism. In
fact, I would add that any usability improvements should NOT be part of
this series. I think we have more important things to add now before we
get to the console switching mechanism.

Let me also premise that the number of guests I imagine will be booted
using dom0less today is actually very limited. I doubt more than 4
guests. So it would be tolerable to rotate between them using Ctrl-AAA.


That said, I think that Julien's suggestion has merits. The fact that
it can only handle up to 10 guests is not an issue, because the number
of dom0less guests is lower than that in current scenarios. A similar
idea would be to introduce an Emacs-like binding such as:

  Ctrl-A + (domid number)

to switch to a given domid. But again, I would leave it for later
developments.

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

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

* Re: [PATCH v2 03/21] xen: allow console_io hypercalls from certain DomUs
  2018-07-17 20:26       ` Julien Grall
@ 2018-07-18 17:10         ` Stefano Stabellini
  2018-07-19  9:19           ` Julien Grall
  0 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-18 17:10 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov,
	George.Dunlap, andrew.cooper3, ian.jackson, xen-devel, tim,
	jbeulich, wei.liu2, dgdegra, nd

On Tue, 17 Jul 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 17/07/2018 21:05, Stefano Stabellini wrote:
> > On Mon, 9 Jul 2018, Julien Grall wrote:
> > > Hi,
> > > 
> > > On 07/07/18 00:11, Stefano Stabellini wrote:
> > > > Introduce an is_console option to allow certain classes of domUs to use
> > > > the Xen console. Specifically, it will be used to give console access to
> > > > all domUs started from Xen from information on device tree.
> > > > 
> > > > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > > > 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 v2:
> > > > - introduce is_console
> > > > - remove #ifdefs
> > > > ---
> > > >    xen/include/xen/sched.h | 2 ++
> > > >    xen/include/xsm/dummy.h | 2 ++
> > > >    xen/xsm/flask/hooks.c   | 5 ++++-
> > > >    3 files changed, 8 insertions(+), 1 deletion(-)
> > > > 
> > > > diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
> > > > index 99d2af2..d66cec0 100644
> > > > --- a/xen/include/xen/sched.h
> > > > +++ b/xen/include/xen/sched.h
> > > > @@ -379,6 +379,8 @@ struct domain
> > > >        bool             auto_node_affinity;
> > > >        /* Is this guest fully privileged (aka dom0)? */
> > > >        bool             is_privileged;
> > > > +    /* Can this guest access the Xen console? */
> > > > +    bool             is_console;
> > > >        /* Is this a xenstore domain (not dom0)? */
> > > >        bool             is_xenstore;
> > > >        /* Domain's VCPUs are pinned 1:1 to physical CPUs? */
> > > > diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
> > > > index ff6b2db..3888817 100644
> > > > --- a/xen/include/xsm/dummy.h
> > > > +++ b/xen/include/xsm/dummy.h
> > > > @@ -230,6 +230,8 @@ static XSM_INLINE int
> > > > xsm_memory_stat_reservation(XSM_DEFAULT_ARG struct domain
> > > >    static XSM_INLINE int xsm_console_io(XSM_DEFAULT_ARG struct domain
> > > > *d, int
> > > > cmd)
> > > >    {
> > > >        XSM_ASSERT_ACTION(XSM_OTHER);
> > > > +    if ( d->is_console )
> > > > +        return xsm_default_action(XSM_HOOK, d, NULL);
> > > 
> > > I will let Daniel commenting on this change. However ...
> > > 
> > > >    #ifdef CONFIG_VERBOSE_DEBUG
> > > >        if ( cmd == CONSOLEIO_write )
> > > >            return xsm_default_action(XSM_HOOK, d, NULL);
> > > > diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
> > > > index 78bc326..2551e4e 100644
> > > > --- a/xen/xsm/flask/hooks.c
> > > > +++ b/xen/xsm/flask/hooks.c
> > > > @@ -443,7 +443,10 @@ static int flask_console_io(struct domain *d, int
> > > > cmd)
> > > >            return avc_unknown_permission("console_io", cmd);
> > > >        }
> > > >    -    return domain_has_xen(d, perm);
> > > > +    if ( !d->is_console )
> > > > +        return domain_has_xen(d, perm);
> > > > +    else
> > > > +        return 0;
> > > 
> > > ... I don't think this change is correct. When a policy is used, the user
> > > is
> > > free to define what is the behavior. With your solution, you impose the
> > > console access even if the user didn't to not give the permission.
> > 
> > I was hoping Daniel would advise on the best way to do things here.
> > 
> > I thought that the idea was that granting a domain "is_console" is
> > equivalent to granting a domain XEN__READCONSOLE and XEN__WRITECONSOLE
> > permissions.  Thus, if is_console is set, we return 0 from
> > flask_console_io because the permissions check succeeds.
> 
> Well, yes and no. That's equivalent when you use the dummy policy. When you
> have a flask policy you want to give the control to the user.
> 
> If you look at the code there are no such as d->is_privilege in that function.
> This means that the user define the policy for the hardware domain. Why would
> be d->is_console different here?

You are saying that in hooks.c the check should remain exactly as is:

  return domain_has_xen(d, perm);

and d->is_console should not be tested? In that case, do you know if I
need to do anything special with XEN__READCONSOLE and XEN__WRITECONSOLE
permissions for the initial boot domains (such as adding those
permissions as the same time d->is_console is set)?

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

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

* Re: [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-17 20:34   ` Julien Grall
@ 2018-07-18 17:31     ` Stefano Stabellini
  0 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-18 17:31 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov,
	George.Dunlap, andrew.cooper3, ian.jackson, xen-devel, tim,
	jbeulich, wei.liu2, nd

On Tue, 17 Jul 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 07/07/2018 00:12, 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.
> > 
> > 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 v2:
> > - only call vpl011_rx_char if the vpl011 has been initialized
> > ---
> >   xen/drivers/char/console.c | 50
> > ++++++++++++++++++++++++++++++++--------------
> >   1 file changed, 35 insertions(+), 15 deletions(-)
> > 
> > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> > index 0f05369..d590bc0 100644
> > --- a/xen/drivers/char/console.c
> > +++ b/xen/drivers/char/console.c
> > @@ -31,10 +31,13 @@
> >   #include <xen/early_printk.h>
> >   #include <xen/warning.h>
> >   #include <xen/pv_console.h>
> > +#include <asm/setup.h>
> >     #ifdef CONFIG_X86
> >   #include <xen/consoled.h>
> >   #include <asm/guest.h>
> > +#else
> > +#include <asm/vpl011.h>
> >   #endif
> >     /* console: comma-separated list of console outputs. */
> > @@ -389,29 +392,49 @@ static void dump_console_ring_key(unsigned char key)
> >       free_xenheap_pages(buf, order);
> >   }
> >   -/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
> > +/*
> > + * CTRL-<switch_char> switches input direction between Xen, Dom0 and
> > + * DomUs.
> > + */
> >   #define switch_code (opt_conswitch[0]-'a'+1)
> > -static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain 0.
> > */
> > +static int __read_mostly xen_rx = 1; /* 1 => input passed to domain 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]);
> > +    xen_rx++;
> > +    if ( xen_rx == max_init_domid + 1 )
> > +        xen_rx = 0;
> > +
> > +    if ( !xen_rx )
> > +        printk("*** Serial input xen_rx=%d -> %s", xen_rx, "Xen");
> > +    else
> > +        printk("*** Serial input xen_rx=%d -> DOM%d", xen_rx, xen_rx - 1);
> > +
> >       if ( switch_code )
> > -        printk(" (type 'CTRL-%c' three times to switch input to %s)",
> > -               opt_conswitch[0], input_str[!xen_rx]);
> > +        printk(" (type 'CTRL-%c' three times to switch input)",
> > +               opt_conswitch[0]);
> >       printk("\n");
> >   }
> >     static void __serial_rx(char c, struct cpu_user_regs *regs)
> >   {
> > -    if ( xen_rx )
> > +    if ( xen_rx == 0 )
> >           return handle_keypress(c, regs);
> >   -    /* Deliver input to guest buffer, unless it is already full. */
> > -    if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
> > -        serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> > +    if ( xen_rx == 1 )
> > +    {
> > +        /* Deliver input to guest buffer, unless it is already full. */
> > +        if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
> > +            serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
> > +    }
> > +#ifdef CONFIG_ARM
> > +    else
> > +    {
> > +        struct domain *d = get_domain_by_id(xen_rx - 1);
> > +        if ( !d->arch.vpl011.ring_enable && d->arch.vpl011.inring != NULL )
> 
> It sounds like you want to provide a macro here. So would make clearer what
> you are actually checking.

I would rather add a in-code comment because it is the only instance of
this check in the codebase.


> > +            vpl011_rx_char(d, c);
> 
> What happen in the case vpl011 is not enabled for that domain?

Yes, that is a mistake in this version of the series. I have already
fixed the issue in my v3 dev branch.


> Shouldn't you at least warn there are no console available?

I'll add a warning


> > +    }
> > +#endif
> >       /* Always notify the guest: prevents receive path from getting stuck.
> > */
> 
> This comment seems a bit wrong now, altough the comment seem to suggest may
> need to be taken care.

I'll update the comment, it is only relevant to the hardware domain


> >       send_global_virq(VIRQ_CONSOLE);
> >   @@ -923,7 +946,7 @@ void __init console_endboot(void)
> >        * a useful 'how to switch' message.
> >        */
> >       if ( opt_conswitch[1] == 'x' )
> > -        xen_rx = !xen_rx;
> > +        xen_rx = 0;
> >         register_keyhandler('w', dump_console_ring_key,
> >                           "synchronously dump console ring buffer (dmesg)",
> > 0);
> > @@ -933,9 +956,6 @@ void __init console_endboot(void)
> >                               "decrease log level threshold", 0);
> >       register_irq_keyhandler('G', &do_toggle_guest,
> >                               "toggle host/guest log level adjustment", 0);
> > -
> > -    /* Serial input is directed to DOM0 by default. */
> > -    switch_serial_input();
> >   }
> >     int __init console_has(const char *device)

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

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

* Re: [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree
  2018-07-18 16:48     ` Julien Grall
@ 2018-07-18 17:48       ` Stefano Stabellini
  2018-07-23 17:13         ` Julien Grall
  0 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-18 17:48 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, andrii_anisov, andrew.cooper3, xen-devel,
	jbeulich, nd

On Wed, 18 Jul 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 13/07/18 21:54, Stefano Stabellini wrote:
> > On Thu, 12 Jul 2018, Julien Grall wrote:
> > > Hi,
> > > 
> > > Would it be possible to provide a branch with the patch applied? It would
> > > be
> > > nice to have that for every version, so I can easily know on which version
> > > of
> > > you are based and avoid spending time trying to apply it :).
> > 
> > Makes sense, I'll do from next time
> 
> Could you provide one from this version? So I can review some of your patches
> more easily.

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

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

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

* Re: [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-18 17:01       ` Stefano Stabellini
@ 2018-07-18 20:37         ` George Dunlap
  0 siblings, 0 replies; 92+ messages in thread
From: George Dunlap @ 2018-07-18 20:37 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Tim (Xen.org),
	George Dunlap, xen-devel, Julien Grall, Jan Beulich, Ian Jackson,
	andrii_anisov, nd



> On Jul 18, 2018, at 1:01 PM, Stefano Stabellini <sstabellini@kernel.org> wrote:
> 
> On Wed, 18 Jul 2018, Jan Beulich wrote:
>>>>> On 17.07.18 at 22:29, <julien.grall@arm.com> wrote:
>>> On 07/07/2018 00:12, 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.
>>> It feels a bit painful for the user to switch N times to get his domain 
>>> console. Would it be possible to provide a new key binding where you 
>>> type the domain ID you want to switch to?
>> 
>> Does that mean you'd want to use 0-9 for this purpose? I'd be
>> very hesitant to accept such, as we're pretty tight with available
>> characters already. And of course 0-9 wouldn't scale to Dom10
>> and beyond. If you have something else in mind, I think it would
>> help if you spelled this out.
> 
> Let me premise that I think this is not important and the solution will
> be fine even only with the existing Ctrl-AAA switching mechanism. In
> fact, I would add that any usability improvements should NOT be part of
> this series. I think we have more important things to add now before we
> get to the console switching mechanism.
> 
> Let me also premise that the number of guests I imagine will be booted
> using dom0less today is actually very limited. I doubt more than 4
> guests. So it would be tolerable to rotate between them using Ctrl-AAA.
> 
> 
> That said, I think that Julien's suggestion has merits. The fact that
> it can only handle up to 10 guests is not an issue, because the number
> of dom0less guests is lower than that in current scenarios. A similar
> idea would be to introduce an Emacs-like binding such as:
> 
>  Ctrl-A + (domid number)
> 
> to switch to a given domid.

FWIW I was thinking this as well.

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

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

* Re: [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-18 16:59       ` Julien Grall
@ 2018-07-19  6:10         ` Jan Beulich
  2018-07-19 17:18           ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Jan Beulich @ 2018-07-19  6:10 UTC (permalink / raw)
  To: Julien Grall
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Stefano Stabellini, Ian Jackson, xen-devel,
	andrii_anisov, nd

>>> On 18.07.18 at 18:59, <julien.grall@arm.com> wrote:
> On 18/07/18 08:12, Jan Beulich wrote:
>>>>> On 17.07.18 at 22:29, <julien.grall@arm.com> wrote:
>>> On 07/07/2018 00:12, 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.
>>> It feels a bit painful for the user to switch N times to get his domain
>>> console. Would it be possible to provide a new key binding where you
>>> type the domain ID you want to switch to?
>> 
>> Does that mean you'd want to use 0-9 for this purpose? I'd be
>> very hesitant to accept such, as we're pretty tight with available
>> characters already. And of course 0-9 wouldn't scale to Dom10
>> and beyond. If you have something else in mind, I think it would
>> help if you spelled this out.
> 
> That what I had in mind. I agree that this solution would not scale to 
> Dom10 and beyond. But that ring solution is not going to be any better.
> 
> Let's imagine you want to switch between domain 9 and 8. You would need 
> to type CTRL-AAA N time before reaching the right console. N been the 
> number of domain you have using the console.
> 
> It feels like, you want to provide a key for selecting the console (e.g 
> 'c') and then type the domain ID you want to access. Can you read 
> another key when in the keyhandler?

Well, as always - everything can be made work which is at least
theoretically possible. We don't have any example of this so far,
but I don't think it would be overly complicated.

Jan



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

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

* Re: [PATCH v2 03/21] xen: allow console_io hypercalls from certain DomUs
  2018-07-18 17:10         ` Stefano Stabellini
@ 2018-07-19  9:19           ` Julien Grall
  2018-08-17 19:41             ` Daniel De Graaf
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-19  9:19 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, andrii_anisov, George.Dunlap, andrew.cooper3,
	ian.jackson, xen-devel, tim, jbeulich, wei.liu2, dgdegra, nd

Hi Stefano,

On 18/07/18 18:10, Stefano Stabellini wrote:
> On Tue, 17 Jul 2018, Julien Grall wrote:
>> Hi Stefano,
>>
>> On 17/07/2018 21:05, Stefano Stabellini wrote:
>>> On Mon, 9 Jul 2018, Julien Grall wrote:
>>>> Hi,
>>>>
>>>> On 07/07/18 00:11, Stefano Stabellini wrote:
>>>>> Introduce an is_console option to allow certain classes of domUs to use
>>>>> the Xen console. Specifically, it will be used to give console access to
>>>>> all domUs started from Xen from information on device tree.
>>>>>
>>>>> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
>>>>> 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 v2:
>>>>> - introduce is_console
>>>>> - remove #ifdefs
>>>>> ---
>>>>>     xen/include/xen/sched.h | 2 ++
>>>>>     xen/include/xsm/dummy.h | 2 ++
>>>>>     xen/xsm/flask/hooks.c   | 5 ++++-
>>>>>     3 files changed, 8 insertions(+), 1 deletion(-)
>>>>>
>>>>> diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
>>>>> index 99d2af2..d66cec0 100644
>>>>> --- a/xen/include/xen/sched.h
>>>>> +++ b/xen/include/xen/sched.h
>>>>> @@ -379,6 +379,8 @@ struct domain
>>>>>         bool             auto_node_affinity;
>>>>>         /* Is this guest fully privileged (aka dom0)? */
>>>>>         bool             is_privileged;
>>>>> +    /* Can this guest access the Xen console? */
>>>>> +    bool             is_console;
>>>>>         /* Is this a xenstore domain (not dom0)? */
>>>>>         bool             is_xenstore;
>>>>>         /* Domain's VCPUs are pinned 1:1 to physical CPUs? */
>>>>> diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
>>>>> index ff6b2db..3888817 100644
>>>>> --- a/xen/include/xsm/dummy.h
>>>>> +++ b/xen/include/xsm/dummy.h
>>>>> @@ -230,6 +230,8 @@ static XSM_INLINE int
>>>>> xsm_memory_stat_reservation(XSM_DEFAULT_ARG struct domain
>>>>>     static XSM_INLINE int xsm_console_io(XSM_DEFAULT_ARG struct domain
>>>>> *d, int
>>>>> cmd)
>>>>>     {
>>>>>         XSM_ASSERT_ACTION(XSM_OTHER);
>>>>> +    if ( d->is_console )
>>>>> +        return xsm_default_action(XSM_HOOK, d, NULL);
>>>>
>>>> I will let Daniel commenting on this change. However ...
>>>>
>>>>>     #ifdef CONFIG_VERBOSE_DEBUG
>>>>>         if ( cmd == CONSOLEIO_write )
>>>>>             return xsm_default_action(XSM_HOOK, d, NULL);
>>>>> diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
>>>>> index 78bc326..2551e4e 100644
>>>>> --- a/xen/xsm/flask/hooks.c
>>>>> +++ b/xen/xsm/flask/hooks.c
>>>>> @@ -443,7 +443,10 @@ static int flask_console_io(struct domain *d, int
>>>>> cmd)
>>>>>             return avc_unknown_permission("console_io", cmd);
>>>>>         }
>>>>>     -    return domain_has_xen(d, perm);
>>>>> +    if ( !d->is_console )
>>>>> +        return domain_has_xen(d, perm);
>>>>> +    else
>>>>> +        return 0;
>>>>
>>>> ... I don't think this change is correct. When a policy is used, the user
>>>> is
>>>> free to define what is the behavior. With your solution, you impose the
>>>> console access even if the user didn't to not give the permission.
>>>
>>> I was hoping Daniel would advise on the best way to do things here.
>>>
>>> I thought that the idea was that granting a domain "is_console" is
>>> equivalent to granting a domain XEN__READCONSOLE and XEN__WRITECONSOLE
>>> permissions.  Thus, if is_console is set, we return 0 from
>>> flask_console_io because the permissions check succeeds.
>>
>> Well, yes and no. That's equivalent when you use the dummy policy. When you
>> have a flask policy you want to give the control to the user.
>>
>> If you look at the code there are no such as d->is_privilege in that function.
>> This means that the user define the policy for the hardware domain. Why would
>> be d->is_console different here?
> 
> You are saying that in hooks.c the check should remain exactly as is:
> 
>    return domain_has_xen(d, perm);
> 
> and d->is_console should not be tested?

Yes.

> In that case, do you know if I
> need to do anything special with XEN__READCONSOLE and XEN__WRITECONSOLE
> permissions for the initial boot domains (such as adding those
> permissions as the same time d->is_console is set)?

The main purpose of XSM is to provide a fine grain permission for the 
user to configure. For instance, a user may not console access for 
initial domain for security purpose. So you don't have anything to in 
the code.

However, when you have XSM enabled, you will have to write down in the 
policy that initial domains will have console access. Although, I am not 
sure how to write that in the policy.

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

* Re: [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM
  2018-07-19  6:10         ` Jan Beulich
@ 2018-07-19 17:18           ` Stefano Stabellini
  0 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-19 17:18 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Stefano Stabellini, Ian Jackson, xen-devel,
	Julien Grall, andrii_anisov, nd

On Thu, 19 Jul 2018, Jan Beulich wrote:
> >>> On 18.07.18 at 18:59, <julien.grall@arm.com> wrote:
> > On 18/07/18 08:12, Jan Beulich wrote:
> >>>>> On 17.07.18 at 22:29, <julien.grall@arm.com> wrote:
> >>> On 07/07/2018 00:12, 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.
> >>> It feels a bit painful for the user to switch N times to get his domain
> >>> console. Would it be possible to provide a new key binding where you
> >>> type the domain ID you want to switch to?
> >> 
> >> Does that mean you'd want to use 0-9 for this purpose? I'd be
> >> very hesitant to accept such, as we're pretty tight with available
> >> characters already. And of course 0-9 wouldn't scale to Dom10
> >> and beyond. If you have something else in mind, I think it would
> >> help if you spelled this out.
> > 
> > That what I had in mind. I agree that this solution would not scale to 
> > Dom10 and beyond. But that ring solution is not going to be any better.
> > 
> > Let's imagine you want to switch between domain 9 and 8. You would need 
> > to type CTRL-AAA N time before reaching the right console. N been the 
> > number of domain you have using the console.
> > 
> > It feels like, you want to provide a key for selecting the console (e.g 
> > 'c') and then type the domain ID you want to access. Can you read 
> > another key when in the keyhandler?
> 
> Well, as always - everything can be made work which is at least
> theoretically possible. We don't have any example of this so far,
> but I don't think it would be overly complicated.

All right -- I'll give it a try and see what happens.

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

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

* Re: [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree
  2018-07-18 17:48       ` Stefano Stabellini
@ 2018-07-23 17:13         ` Julien Grall
  2018-07-23 17:52           ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-23 17:13 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: andrew.cooper3, nd, andrii_anisov, jbeulich, xen-devel

On 18/07/18 18:48, Stefano Stabellini wrote:
> On Wed, 18 Jul 2018, Julien Grall wrote:
>> Hi Stefano,
>>
>> On 13/07/18 21:54, Stefano Stabellini wrote:
>>> On Thu, 12 Jul 2018, Julien Grall wrote:
>>>> Hi,
>>>>
>>>> Would it be possible to provide a branch with the patch applied? It would
>>>> be
>>>> nice to have that for every version, so I can easily know on which version
>>>> of
>>>> you are based and avoid spending time trying to apply it :).
>>>
>>> Makes sense, I'll do from next time
>>
>> Could you provide one from this version? So I can review some of your patches
>> more easily.
> 
> http://xenbits.xenproject.org/git-http/people/sstabellini/xen-unstable.git dom0less-v2

Thanks. I will have a look at the vpl011 patches. I think the rest is 
either reviewed or will require changes based on other comments.

Let me know if I missed anything.

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

* Re: [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree
  2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
                   ` (21 preceding siblings ...)
  2018-07-12 18:18 ` [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Julien Grall
@ 2018-07-23 17:14 ` Andrii Anisov
  2018-07-23 17:55   ` Stefano Stabellini
  22 siblings, 1 reply; 92+ messages in thread
From: Andrii Anisov @ 2018-07-23 17:14 UTC (permalink / raw)
  To: Stefano Stabellini, julien.grall; +Cc: andrew.cooper3, jbeulich, xen-devel

Hello Stefano,

On 07.07.18 02:11, Stefano Stabellini wrote:
> 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.
Please consider also status monitoring and restarting for those domains.

>   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.
But even a mission critical application does exchange some information 
with other entities in the system. So they would need interdomain 
communication anyway (i.e. built with event channels and shared pages, etc.)

-- 

*Andrii Anisov*


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

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

* Re: [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree
  2018-07-23 17:13         ` Julien Grall
@ 2018-07-23 17:52           ` Stefano Stabellini
  0 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-23 17:52 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, andrii_anisov, andrew.cooper3, xen-devel,
	jbeulich, nd

On Mon, 23 Jul 2018, Julien Grall wrote:
> On 18/07/18 18:48, Stefano Stabellini wrote:
> > On Wed, 18 Jul 2018, Julien Grall wrote:
> > > Hi Stefano,
> > > 
> > > On 13/07/18 21:54, Stefano Stabellini wrote:
> > > > On Thu, 12 Jul 2018, Julien Grall wrote:
> > > > > Hi,
> > > > > 
> > > > > Would it be possible to provide a branch with the patch applied? It
> > > > > would
> > > > > be
> > > > > nice to have that for every version, so I can easily know on which
> > > > > version
> > > > > of
> > > > > you are based and avoid spending time trying to apply it :).
> > > > 
> > > > Makes sense, I'll do from next time
> > > 
> > > Could you provide one from this version? So I can review some of your
> > > patches
> > > more easily.
> > 
> > http://xenbits.xenproject.org/git-http/people/sstabellini/xen-unstable.git
> > dom0less-v2
> 
> Thanks. I will have a look at the vpl011 patches. I think the rest is either
> reviewed or will require changes based on other comments.
> 
> Let me know if I missed anything.

No, I think it is OK. Thank you.

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

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

* Re: [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree
  2018-07-23 17:14 ` Andrii Anisov
@ 2018-07-23 17:55   ` Stefano Stabellini
  0 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-23 17:55 UTC (permalink / raw)
  To: Andrii Anisov
  Cc: andrew.cooper3, julien.grall, Stefano Stabellini, jbeulich, xen-devel

On Mon, 23 Jul 2018, Andrii Anisov wrote:
> Hello Stefano,
> 
> On 07.07.18 02:11, Stefano Stabellini wrote:
> > 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.
> Please consider also status monitoring and restarting for those domains.

It is possible to monitor these domains from Dom0. It is not possible to
restart them at the moment. However, with the appropriate configuration
in Dom0, it would certainly be possible to shutdown the domains started
at boot, and create them anew with xl. Of course to do that, the xl
configurations and related files in dom0 would have to be provided.


> >   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.
> But even a mission critical application does exchange some information with
> other entities in the system. So they would need interdomain communication
> anyway (i.e. built with event channels and shared pages, etc.)

It is on my todo list.

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

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

* Re: [PATCH v2 02/21] xen/arm: make allocate_memory work for non 1:1 mapped guests
  2018-07-06 23:11 ` [PATCH v2 02/21] xen/arm: make allocate_memory work for non 1:1 mapped guests Stefano Stabellini
  2018-07-09 13:43   ` Julien Grall
  2018-07-09 13:58   ` Julien Grall
@ 2018-07-23 18:01   ` Andrii Anisov
  2018-07-23 18:32     ` Stefano Stabellini
  2 siblings, 1 reply; 92+ messages in thread
From: Andrii Anisov @ 2018-07-23 18:01 UTC (permalink / raw)
  To: Stefano Stabellini, julien.grall; +Cc: Stefano Stabellini, xen-devel

Hello Stefano,


On 07.07.18 02:11, Stefano Stabellini wrote:
> Extend allocate_memory to work for non 1:1 mapped domUs. Specifically,
> memory allocated for domU will be mapped into the domU pseudo-physical
> address space at the appropriate addresses according to the guest memory
> map: GUEST_RAM0_BASE and GUEST_RAM1_BASE.
I would speculate about GUEST_RAMx_BASE and GUEST_RAMx_SIZE macros. 
Those values might not fit the real SoC memory map. And it becomes a 
problem once we decided to assign some peripheral directly to the guest 
because a RAM space specified to VM would overlap with IO range of the 
assigned device.
In my practice, we always align those macros with the SoC memory map. 
This becomes more convenient and practical than IO remapping.

It might be the moment to get those values configurable for the guests. 
At least for those, which are configured from the device tree. Here 
naturally fit making `memory` property similar to `reg` - the list of 
<base, size> values.

-- 

*Andrii Anisov*



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

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

* Re: [PATCH v2 02/21] xen/arm: make allocate_memory work for non 1:1 mapped guests
  2018-07-23 18:01   ` Andrii Anisov
@ 2018-07-23 18:32     ` Stefano Stabellini
  2018-07-24 12:09       ` Andrii Anisov
  0 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-23 18:32 UTC (permalink / raw)
  To: Andrii Anisov
  Cc: Stefano Stabellini, julien.grall, Stefano Stabellini, xen-devel

On Mon, 23 Jul 2018, Andrii Anisov wrote:
> Hello Stefano,
> 
> 
> On 07.07.18 02:11, Stefano Stabellini wrote:
> > Extend allocate_memory to work for non 1:1 mapped domUs. Specifically,
> > memory allocated for domU will be mapped into the domU pseudo-physical
> > address space at the appropriate addresses according to the guest memory
> > map: GUEST_RAM0_BASE and GUEST_RAM1_BASE.
> I would speculate about GUEST_RAMx_BASE and GUEST_RAMx_SIZE macros. Those
> values might not fit the real SoC memory map. And it becomes a problem once we
> decided to assign some peripheral directly to the guest because a RAM space
> specified to VM would overlap with IO range of the assigned device.
> In my practice, we always align those macros with the SoC memory map. This
> becomes more convenient and practical than IO remapping.
> 
> It might be the moment to get those values configurable for the guests. At
> least for those, which are configured from the device tree. Here naturally fit
> making `memory` property similar to `reg` - the list of <base, size> values.

Yes, you are right. Those value should be made configurable. It is
already on my roadmap. But I would keep it separate from this series: it
is not just about the position of RAM in the guest address space, also
the GIC and timer addresses need to be configurable. I usually refer to
this (future) feature as arbitrary guest memory map.

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

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

* Re: [PATCH v2 17/21] xen/arm: refactor vpl011_data_avail
  2018-07-06 23:12 ` [PATCH v2 17/21] xen/arm: refactor vpl011_data_avail Stefano Stabellini
@ 2018-07-24  9:58   ` Julien Grall
  2018-07-27 22:37     ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-24  9:58 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 07/07/18 00:12, Stefano Stabellini wrote:
> Move the code to calculate in_fifo_level and out_fifo_level out of
> vpl011_data_avail, to the caller.
> This change will make it possible to reuse vpl011_data_avail with
> different ring structures in a later patch.
> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> 
> ---
> Changes in v2:
> - new patch
> ---
>   xen/arch/arm/vpl011.c | 70 ++++++++++++++++++++++++++++++---------------------
>   1 file changed, 42 insertions(+), 28 deletions(-)
> 
> diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> index 33fcaa0..e75957f 100644
> --- a/xen/arch/arm/vpl011.c
> +++ b/xen/arch/arm/vpl011.c
> @@ -34,6 +34,12 @@
>   #include <asm/vgic-emul.h>
>   #include <asm/vpl011.h>
>   
> +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);
> +

Looking at the end code, I think you can avoid the declaration by adding 
vpl011_rx_char somewhere else.

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

* Re: [PATCH v2 18/21] xen/arm: Allow vpl011 to be used by DomU
  2018-07-06 23:12 ` [PATCH v2 18/21] xen/arm: Allow vpl011 to be used by DomU Stefano Stabellini
@ 2018-07-24 11:00   ` Julien Grall
  2018-07-27  0:10     ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-24 11:00 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 07/07/18 00:12, Stefano Stabellini wrote:
> Make vpl011 being able to be used without a userspace component in Dom0.
> In that case, output is printed to the Xen serial and input is received
> from the Xen serial one character at a time.
> 
> Call domain_vpl011_init during construct_domU if vpl011 is enabled.
> 
> Introduce a new ring struct with only the ring array to avoid a waste of
> memory. Introduce separate read_date and write_data functions for
> initial domains: vpl011_write_data_noring is very simple and just writes
> to the console, while vpl011_read_data_inring is a duplicate of
> vpl011_read_data. Although textually almost identical, we are forced to
> duplicate the functions because the struct layout is different.

Looking at the patches applied, I think there need some more comments in 
the code to help a reader differentiate which method is used.

> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> ---
> 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  |  10 ++-
>   xen/arch/arm/vpl011.c        | 185 ++++++++++++++++++++++++++++++++++++++-----
>   xen/include/asm-arm/vpl011.h |  10 +++
>   3 files changed, 182 insertions(+), 23 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 718be48..d7e9040 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -2531,7 +2531,15 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
>       if ( rc < 0 )
>           return rc;
>   
> -    return __construct_domain(d, &kinfo);
> +    rc = __construct_domain(d, &kinfo);
> +    if ( rc < 0 )
> +        return rc;
> +
> +#ifdef CONFIG_SBSA_VUART_CONSOLE
> +    if ( vpl011 )
> +        rc = domain_vpl011_init(d, NULL);
> +#endif
I don't think the #ifdef is necessary here. We want to return an error 
when vpl011 is set but not the emulation compiled in.

> +    return rc;
>   }
>   
>   int __init construct_dom0(struct domain *d)
> diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> index e75957f..d4aab64 100644
> --- a/xen/arch/arm/vpl011.c
> +++ b/xen/arch/arm/vpl011.c
> @@ -83,6 +83,111 @@ static void vpl011_update_interrupt_status(struct domain *d)
>   #endif
>   }
>   
> +void vpl011_rx_char(struct domain *d, char c)

Please add documentation explain what the use of this function. I would 
also rename it to clarify who can call it (i.e only in the case when the 
backend is in Xen).

> +{
> +    unsigned long flags;
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +    struct xencons_in *intf = vpl011->inring;
> +    XENCONS_RING_IDX in_cons, in_prod, in_fifo_level;
> +

ASSERT(!vpl011->ring_enable);

> +    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 + 1;
> +
> +    in_fifo_level = xencons_queued(in_prod,
> +                                   in_cons,
> +                                   sizeof(intf->in));
> +
> +    vpl011_data_avail(d, in_fifo_level, sizeof(intf->in), 0, 1024);

Where does the 1024 come from? Most likely, you want a define for it.

> +    VPL011_UNLOCK(d, flags);
> +}
> +
> +static void vpl011_write_data_noring(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);

You want to buffer the characters here and only print on newline or when 
the buffer is full. Otherwise characters will get mangled with the Xen 
console output or other domains output.

> +
> +    vpl011->uartris |= TXI;
> +    vpl011->uartfr &= ~TXFE;
> +    vpl011_update_interrupt_status(d);
> +
> +    VPL011_UNLOCK(d, flags);
> +}
> +
> +static uint8_t vpl011_read_data_inring(struct domain *d)
> +{

I think you can avoid the duplication here by using a macro.

> +    unsigned long flags;
> +    uint8_t data = 0;
> +    struct vpl011 *vpl011 = &d->arch.vpl011;
> +    struct xencons_in *intf = vpl011->inring;
> +    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;
> @@ -246,7 +351,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->ring_enable )
> +            *r = vreg_reg32_extract(vpl011_read_data(d), info);
> +        else
> +            *r = vreg_reg32_extract(vpl011_read_data_inring(d), info);

I think some renaming will improve the reading. This is quite 
unintuitive to see a function with "ring" in it, called when 
!vpl011->ring_enabled.

>           return 1;
>   
>       case RSR:
> @@ -331,7 +439,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->ring_enable )
> +            vpl011_write_data(v->domain, data);
> +        else
> +            vpl011_write_data_noring(v->domain, data);
>           return 1;
>       }
>   
> @@ -476,27 +587,47 @@ int domain_vpl011_init(struct domain *d, struct vpl011_init_info *info)
>       if ( vpl011->ring.ring_buf )
>           return -EINVAL;
>   
> -    /* Map the guest PFN to Xen address space. */
> -    rc =  prepare_ring_for_helper(d,
> -                                  gfn_x(info->gfn),
> -                                  &vpl011->ring.ring_page,
> -                                  &vpl011->ring.ring_buf);
> -    if ( rc < 0 )
> -        goto out;
> +    /*
> +     * info is NULL for domUs started by Xen at boot time, with no
> +     * corresponding userspace component in dom0 > +     */

I don't think you want to mention domUs at all here. The emulation 
should not care whether it is a guest or the hardware domain. It would 
theoretically possible to have the hardware domain re-using this code.

Furthermore, nothing in the emulation mandates to have the backend in
the hardware domain. This could be anywhere.

It looks like to me you want to offer 2 solutions:
	1) Console backend in a domain
	2) Console backend in the hypervisor

So probably a better naming for ring_enable would be "backend_in_domain" 
(or something similar).

> +    if ( info != NULL )
> +    {
> +        vpl011->ring_enable = true;
> +
> +        /* Map the guest PFN to Xen address space. */
> +        rc =  prepare_ring_for_helper(d,
> +                gfn_x(info->gfn),
> +                &vpl011->ring.ring_page,
> +                &vpl011->ring.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->ring_enable = false;
> +
> +        vpl011->inring = xzalloc(struct xencons_in);
> +        if ( vpl011->inring == 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);
>   
> @@ -509,7 +640,10 @@ out2:
>       vgic_free_virq(d, GUEST_VPL011_SPI);
>   
>   out1:
> -    destroy_ring_for_helper(&vpl011->ring.ring_buf, vpl011->ring.ring_page);
> +    if ( vpl011->ring_enable )
> +        destroy_ring_for_helper(&vpl011->ring.ring_buf, vpl011->ring.ring_page);
> +    else
> +        xfree(vpl011->inring);
>   
>   out:
>       return rc;
> @@ -519,11 +653,18 @@ void domain_vpl011_deinit(struct domain *d)
>   {
>       struct vpl011 *vpl011 = &d->arch.vpl011;
>   
> -    if ( !vpl011->ring.ring_buf )
> -        return;
> +    if ( vpl011->ring_enable )
> +    {
> +        if ( !vpl011->ring.ring_buf )
> +            return;
>   
> -    free_xen_event_channel(d, vpl011->evtchn);
> -    destroy_ring_for_helper(&vpl011->ring.ring_buf, vpl011->ring.ring_page);
> +        free_xen_event_channel(d, vpl011->evtchn);
> +        destroy_ring_for_helper(&vpl011->ring.ring_buf, vpl011->ring.ring_page);
> +    }
> +    else
> +    {
> +        xfree(vpl011->inring);
> +    }
>   }
>   
>   /*
> diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
> index c3d375b..be43abf 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>
>   
> @@ -30,12 +31,19 @@
>   
>   #define SBSA_UART_FIFO_SIZE 32
>   
> +struct xencons_in {

The name is too close to xencons_interface and I don't think the name is 
correct for the header it lives.

It probably should be vpl011_xen_backend or something similar.

> +    char in[1024];
> +    XENCONS_RING_IDX in_cons, in_prod;
> +};
> +
>   struct vpl011 {
> +    bool ring_enable;
>       union {
>           struct {
>               void *ring_buf;
>               struct page_info *ring_page;
>           } ring;
> +        struct xencons_in *inring;

The code is quite confusing. You have a field "ring_enabled" to know 
which bits of the union is used. But both name have "ring" in it.

You most likely want to rework the naming. If you follow my suggestion 
above it would be

union
{
     struct {
     } dom;
     struct vpl011_xen_backend xen;
} backend;

The different helpers would then need to be renamed accordingly.


>       };
>       uint32_t    uartfr;         /* Flag register */
>       uint32_t    uartcr;         /* Control register */
> @@ -57,6 +65,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(struct domain *d, char c);
>   #else
>   static inline int domain_vpl011_init(struct domain *d,
>                                        struct vpl011_init_info *info)
> @@ -65,6 +74,7 @@ static inline int domain_vpl011_init(struct domain *d,
>   }
>   
>   static inline void domain_vpl011_deinit(struct domain *d) { }
> +static inline void vpl011_rx_char(struct domain *d, char c) { }

I don't think this is necessary. IIRC, you already ifdef the caller.

>   #endif
>   #endif  /* _VPL011_H_ */
>   
> 

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

* Re: [PATCH v2 02/21] xen/arm: make allocate_memory work for non 1:1 mapped guests
  2018-07-23 18:32     ` Stefano Stabellini
@ 2018-07-24 12:09       ` Andrii Anisov
  0 siblings, 0 replies; 92+ messages in thread
From: Andrii Anisov @ 2018-07-24 12:09 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, julien.grall, xen-devel

Hello Stefano,


On 23.07.18 21:32, Stefano Stabellini wrote:
> also the GIC and timer addresses need to be configurable.
I don't remember we ever had a problem with them. But yes, this should 
be configurable as well.

> I usually refer to this (future) feature as arbitrary guest memory map.
I see.

-- 

*Andrii Anisov*



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

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

* Re: [PATCH v2 19/21] xen/arm: introduce create_domUs
  2018-07-06 23:12 ` [PATCH v2 19/21] xen/arm: introduce create_domUs Stefano Stabellini
  2018-07-16 16:10   ` Jan Beulich
@ 2018-07-24 13:53   ` Julien Grall
  2018-07-28  2:42     ` Stefano Stabellini
  1 sibling, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-24 13:53 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, andrew.cooper3, andrii_anisov, jbeulich, xen-devel

Hi Stefano,

On 07/07/18 00:12, Stefano Stabellini wrote:
> Call a new function, "create_domUs", from setup_xen to start DomU VMs.
> 
> Introduce support for the "xen,domU" compatible node on device tree.
> Create new DomU VMs based on the information found on device tree under
> "xen,domU". Calls construct_domU for each domain.
> 
> Introduce a simple global variable named max_init_domid to keep track of
> the initial allocated domids.
> 
> Move the discard_initial_modules after DomUs have been built

Nit: Missing full stop.

> 
> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> CC: andrew.cooper3@citrix.com
> CC: jbeulich@suse.com
> ---
> Changes in v2:
> - coding style
> - set nr_spis to 32
> - introduce create_domUs
> ---
>   xen/arch/arm/domain_build.c | 38 +++++++++++++++++++++++++++++++++++---
>   xen/arch/arm/setup.c        |  8 +++++++-
>   xen/include/asm-arm/setup.h |  3 +++
>   xen/include/asm-x86/setup.h |  2 ++
>   4 files changed, 47 insertions(+), 4 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index d7e9040..9f58002 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>
> @@ -2542,6 +2543,39 @@ static int __init construct_domU(struct domain *d, struct dt_device_node *node)
>       return rc;
>   }
>   
> +void __init create_domUs(void)
> +{
> +    struct dt_device_node *node;
> +    struct dt_device_node *chosen = dt_find_node_by_name(dt_host, "chosen");

newline here.

> +    if ( chosen != NULL )
> +    {
> +        dt_for_each_child_node(chosen, node)
> +        {
> +            struct domain *d;
> +            struct xen_domctl_createdomain d_cfg = {};
> +
> +            if ( !dt_device_is_compatible(node, "xen,domain") )
> +                continue;
> +
> +            d_cfg.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
> +            d_cfg.arch.nr_spis = 32;

You can set those fields directly when defining d_cfg above.

> +
> +            d = domain_create(max_init_domid++, &d_cfg);
> +            if ( IS_ERR(d) )
> +                panic("Error creating domU");

It is probably worth to add the node name in the message. So the user 
knows which guest failed.

> +
> +            d->is_privileged = 0;
> +            d->is_console = 1;
> +            d->target = NULL;
> +
> +            if ( construct_domU(d, node) != 0 )
> +                printk("Could not set up DOMU guest OS");

Should not it be a panic here? Also, the message is a little odd "DOMU 
guest" is a bit redundant and the function will load the kernel but 
that's not the only thing done.

Lastly, you probably want to add the node name in the message, so the 
user knows which guest failed.

> +
> +            domain_unpause_by_systemcontroller(d);

If a domain is bound to CPU0, then it will not boot until CPU0 is done 
with creating domain. Is that what you want?

> +        }
> +    }
> +}
> +
>   int __init construct_dom0(struct domain *d)
>   {
>       struct kernel_info kinfo = {};
> @@ -2592,9 +2626,7 @@ int __init construct_dom0(struct domain *d)
>           return rc;
>   
>   
> -    rc = __construct_domain(d, &kinfo);
> -    discard_initial_modules();
> -    return rc;
> +    return __construct_domain(d, &kinfo);
>   }
>   
>   /*
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index 7739a80..0b08af2 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -64,6 +64,8 @@ static unsigned long opt_xenheap_megabytes __initdata;
>   integer_param("xenheap_megabytes", opt_xenheap_megabytes);
>   #endif
>   
> +domid_t __read_mostly max_init_domid = 0;
> +
>   static __used void init_done(void)
>   {
>       free_init_memory();
> @@ -863,7 +865,7 @@ void __init start_xen(unsigned long boot_phys_offset,
>       dom0_cfg.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
>       dom0_cfg.arch.nr_spis = gic_number_lines() - 32;
>   
> -    dom0 = domain_create(0, &dom0_cfg);
> +    dom0 = domain_create(max_init_domid++, &dom0_cfg);
>       if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
>               panic("Error creating domain 0");
>   
> @@ -889,6 +891,10 @@ void __init start_xen(unsigned long boot_phys_offset,
>   
>       domain_unpause_by_systemcontroller(dom0);

Why do you unpause Dom0 and then create the guests? It feels like to me 
you want to create all the guests and then unpause dom0. dom0 would 
likely get blocked anyway has CPU0 will be busy creating domains.

>   
> +    create_domUs();
> +
> +    discard_initial_modules();

I think it would be better to move that in init_done. This is where all 
initial memory is freed.

> +
>       /* Switch on to the dynamically allocated stack for the idle vcpu
>        * since the static one we're running on is about to be freed. */
>       memcpy(idle_vcpu[0]->arch.cpu_info, get_cpu_info(),
> diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
> index 5ecfe27..21b9729 100644
> --- a/xen/include/asm-arm/setup.h
> +++ b/xen/include/asm-arm/setup.h
> @@ -56,6 +56,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);
> @@ -72,6 +74,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 19232af..2fb9529 100644
> --- a/xen/include/asm-x86/setup.h
> +++ b/xen/include/asm-x86/setup.h
> @@ -73,4 +73,6 @@ extern bool opt_dom0_shadow;
>   #endif
>   extern bool dom0_pvh;
>   
> +#define max_init_domid (1)
> +
>   #endif
> 

Cheers,

-- 
Julien Grall

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

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

* Re: [PATCH v2 18/21] xen/arm: Allow vpl011 to be used by DomU
  2018-07-24 11:00   ` Julien Grall
@ 2018-07-27  0:10     ` Stefano Stabellini
  2018-07-27 11:00       ` Julien Grall
  0 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-27  0:10 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

Thank you Julien. I addressed almost all comments. I had a problem with
the implementation of buffering the chars, and I have an alternative
comment on the function sharing. See below.


On Tue, 24 Jul 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 07/07/18 00:12, Stefano Stabellini wrote:
> > Make vpl011 being able to be used without a userspace component in Dom0.
> > In that case, output is printed to the Xen serial and input is received
> > from the Xen serial one character at a time.
> > 
> > Call domain_vpl011_init during construct_domU if vpl011 is enabled.
> > 
> > Introduce a new ring struct with only the ring array to avoid a waste of
> > memory. Introduce separate read_date and write_data functions for
> > initial domains: vpl011_write_data_noring is very simple and just writes
> > to the console, while vpl011_read_data_inring is a duplicate of
> > vpl011_read_data. Although textually almost identical, we are forced to
> > duplicate the functions because the struct layout is different.
> 
> Looking at the patches applied, I think there need some more comments in the
> code to help a reader differentiate which method is used.

OK


> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > ---
> > 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  |  10 ++-
> >   xen/arch/arm/vpl011.c        | 185
> > ++++++++++++++++++++++++++++++++++++++-----
> >   xen/include/asm-arm/vpl011.h |  10 +++
> >   3 files changed, 182 insertions(+), 23 deletions(-)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 718be48..d7e9040 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -2531,7 +2531,15 @@ static int __init construct_domU(struct domain *d,
> > struct dt_device_node *node)
> >       if ( rc < 0 )
> >           return rc;
> >   -    return __construct_domain(d, &kinfo);
> > +    rc = __construct_domain(d, &kinfo);
> > +    if ( rc < 0 )
> > +        return rc;
> > +
> > +#ifdef CONFIG_SBSA_VUART_CONSOLE
> > +    if ( vpl011 )
> > +        rc = domain_vpl011_init(d, NULL);
> > +#endif
> I don't think the #ifdef is necessary here. We want to return an error when
> vpl011 is set but not the emulation compiled in.

OK


> > +    return rc;
> >   }
> >     int __init construct_dom0(struct domain *d)
> > diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> > index e75957f..d4aab64 100644
> > --- a/xen/arch/arm/vpl011.c
> > +++ b/xen/arch/arm/vpl011.c
> > @@ -83,6 +83,111 @@ static void vpl011_update_interrupt_status(struct domain
> > *d)
> >   #endif
> >   }
> >   +void vpl011_rx_char(struct domain *d, char c)
> 
> Please add documentation explain what the use of this function. I would also
> rename it to clarify who can call it (i.e only in the case when the backend is
> in Xen).

OK


> > +{
> > +    unsigned long flags;
> > +    struct vpl011 *vpl011 = &d->arch.vpl011;
> > +    struct xencons_in *intf = vpl011->inring;
> > +    XENCONS_RING_IDX in_cons, in_prod, in_fifo_level;
> > +
> 
> ASSERT(!vpl011->ring_enable);

OK


> > +    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 + 1;
> > +
> > +    in_fifo_level = xencons_queued(in_prod,
> > +                                   in_cons,
> > +                                   sizeof(intf->in));
> > +
> > +    vpl011_data_avail(d, in_fifo_level, sizeof(intf->in), 0, 1024);
> 
> Where does the 1024 come from? Most likely, you want a define for it.

OK


> > +    VPL011_UNLOCK(d, flags);
> > +}
> > +
> > +static void vpl011_write_data_noring(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);
> 
> You want to buffer the characters here and only print on newline or when the
> buffer is full. Otherwise characters will get mangled with the Xen console
> output or other domains output.

I did the implementation, but then when I type characters at the domain
prompt, I don't see them anymore one by one. Only after I press
"enter". That makes the domain console not very usable. Should we keep
it as?


> > +
> > +    vpl011->uartris |= TXI;
> > +    vpl011->uartfr &= ~TXFE;
> > +    vpl011_update_interrupt_status(d);
> > +
> > +    VPL011_UNLOCK(d, flags);
> > +}
> > +
> > +static uint8_t vpl011_read_data_inring(struct domain *d)
> > +{
> 
> I think you can avoid the duplication here by using a macro.

I prefer to avoid MACROS for things like this. I would rather reuse the
existing function for both cases like in v1. Would you be OK to go back
to that?


> > +    unsigned long flags;
> > +    uint8_t data = 0;
> > +    struct vpl011 *vpl011 = &d->arch.vpl011;
> > +    struct xencons_in *intf = vpl011->inring;
> > +    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;
> > @@ -246,7 +351,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->ring_enable )
> > +            *r = vreg_reg32_extract(vpl011_read_data(d), info);
> > +        else
> > +            *r = vreg_reg32_extract(vpl011_read_data_inring(d), info);
> 
> I think some renaming will improve the reading. This is quite unintuitive to
> see a function with "ring" in it, called when !vpl011->ring_enabled.

OK


> >           return 1;
> >         case RSR:
> > @@ -331,7 +439,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->ring_enable )
> > +            vpl011_write_data(v->domain, data);
> > +        else
> > +            vpl011_write_data_noring(v->domain, data);
> >           return 1;
> >       }
> >   @@ -476,27 +587,47 @@ int domain_vpl011_init(struct domain *d, struct
> > vpl011_init_info *info)
> >       if ( vpl011->ring.ring_buf )
> >           return -EINVAL;
> >   -    /* Map the guest PFN to Xen address space. */
> > -    rc =  prepare_ring_for_helper(d,
> > -                                  gfn_x(info->gfn),
> > -                                  &vpl011->ring.ring_page,
> > -                                  &vpl011->ring.ring_buf);
> > -    if ( rc < 0 )
> > -        goto out;
> > +    /*
> > +     * info is NULL for domUs started by Xen at boot time, with no
> > +     * corresponding userspace component in dom0 > +     */
> 
> I don't think you want to mention domUs at all here. The emulation should not
> care whether it is a guest or the hardware domain. It would theoretically
> possible to have the hardware domain re-using this code.
> 
> Furthermore, nothing in the emulation mandates to have the backend in
> the hardware domain. This could be anywhere.
> 
> It looks like to me you want to offer 2 solutions:
> 	1) Console backend in a domain
> 	2) Console backend in the hypervisor
> 
> So probably a better naming for ring_enable would be "backend_in_domain" (or
> something similar).

I'll rename ring_enable to backend_in_domain, and improve the comment
above.


> > +    if ( info != NULL )
> > +    {
> > +        vpl011->ring_enable = true;
> > +
> > +        /* Map the guest PFN to Xen address space. */
> > +        rc =  prepare_ring_for_helper(d,
> > +                gfn_x(info->gfn),
> > +                &vpl011->ring.ring_page,
> > +                &vpl011->ring.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->ring_enable = false;
> > +
> > +        vpl011->inring = xzalloc(struct xencons_in);
> > +        if ( vpl011->inring == 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);
> >   @@ -509,7 +640,10 @@ out2:
> >       vgic_free_virq(d, GUEST_VPL011_SPI);
> >     out1:
> > -    destroy_ring_for_helper(&vpl011->ring.ring_buf,
> > vpl011->ring.ring_page);
> > +    if ( vpl011->ring_enable )
> > +        destroy_ring_for_helper(&vpl011->ring.ring_buf,
> > vpl011->ring.ring_page);
> > +    else
> > +        xfree(vpl011->inring);
> >     out:
> >       return rc;
> > @@ -519,11 +653,18 @@ void domain_vpl011_deinit(struct domain *d)
> >   {
> >       struct vpl011 *vpl011 = &d->arch.vpl011;
> >   -    if ( !vpl011->ring.ring_buf )
> > -        return;
> > +    if ( vpl011->ring_enable )
> > +    {
> > +        if ( !vpl011->ring.ring_buf )
> > +            return;
> >   -    free_xen_event_channel(d, vpl011->evtchn);
> > -    destroy_ring_for_helper(&vpl011->ring.ring_buf,
> > vpl011->ring.ring_page);
> > +        free_xen_event_channel(d, vpl011->evtchn);
> > +        destroy_ring_for_helper(&vpl011->ring.ring_buf,
> > vpl011->ring.ring_page);
> > +    }
> > +    else
> > +    {
> > +        xfree(vpl011->inring);
> > +    }
> >   }
> >     /*
> > diff --git a/xen/include/asm-arm/vpl011.h b/xen/include/asm-arm/vpl011.h
> > index c3d375b..be43abf 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>
> >   @@ -30,12 +31,19 @@
> >     #define SBSA_UART_FIFO_SIZE 32
> >   +struct xencons_in {
> 
> The name is too close to xencons_interface and I don't think the name is
> correct for the header it lives.
> 
> It probably should be vpl011_xen_backend or something similar.

I'll rename xencons_in to vpl011_xen_backend;


> > +    char in[1024];
> > +    XENCONS_RING_IDX in_cons, in_prod;
> > +};
> > +
> >   struct vpl011 {
> > +    bool ring_enable;
> >       union {
> >           struct {
> >               void *ring_buf;
> >               struct page_info *ring_page;
> >           } ring;
> > +        struct xencons_in *inring;
> 
> The code is quite confusing. You have a field "ring_enabled" to know which
> bits of the union is used. But both name have "ring" in it.
> 
> You most likely want to rework the naming. If you follow my suggestion above
> it would be
> 
> union
> {
>     struct {
>     } dom;
>     struct vpl011_xen_backend xen;
> } backend;

I'll follow this suggestion.


> The different helpers would then need to be renamed accordingly.

I'll do


> >       };
> >       uint32_t    uartfr;         /* Flag register */
> >       uint32_t    uartcr;         /* Control register */
> > @@ -57,6 +65,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(struct domain *d, char c);
> >   #else
> >   static inline int domain_vpl011_init(struct domain *d,
> >                                        struct vpl011_init_info *info)
> > @@ -65,6 +74,7 @@ static inline int domain_vpl011_init(struct domain *d,
> >   }
> >     static inline void domain_vpl011_deinit(struct domain *d) { }
> > +static inline void vpl011_rx_char(struct domain *d, char c) { }
> 
> I don't think this is necessary. IIRC, you already ifdef the caller.

OK

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

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

* Re: [PATCH v2 18/21] xen/arm: Allow vpl011 to be used by DomU
  2018-07-27  0:10     ` Stefano Stabellini
@ 2018-07-27 11:00       ` Julien Grall
  2018-07-27 21:42         ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-27 11:00 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: Stefano Stabellini, andrii_anisov, xen-devel

Hi Stefano,

On 27/07/18 01:10, Stefano Stabellini wrote:
> On Tue, 24 Jul 2018, Julien Grall wrote:
>> On 07/07/18 00:12, Stefano Stabellini wrote:
>>> +    VPL011_UNLOCK(d, flags);
>>> +}
>>> +
>>> +static void vpl011_write_data_noring(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);
>>
>> You want to buffer the characters here and only print on newline or when the
>> buffer is full. Otherwise characters will get mangled with the Xen console
>> output or other domains output.
> 
> I did the implementation, but then when I type characters at the domain
> prompt, I don't see them anymore one by one. Only after I press
> "enter". That makes the domain console not very usable. Should we keep
> it as?

I haven't thought about that case. However, if you don't implement the 
buffer solution, you will get all the domain consoles mangled during 
boot. This is not really nice for debugging. A potential solution is to 
buffer for all the domains but the one that is reading characters.

>>> +
>>> +    vpl011->uartris |= TXI;
>>> +    vpl011->uartfr &= ~TXFE;
>>> +    vpl011_update_interrupt_status(d);
>>> +
>>> +    VPL011_UNLOCK(d, flags);
>>> +}
>>> +
>>> +static uint8_t vpl011_read_data_inring(struct domain *d)
>>> +{
>>
>> I think you can avoid the duplication here by using a macro.
> 
> I prefer to avoid MACROS for things like this. I would rather reuse the
> existing function for both cases like in v1. Would you be OK to go back
> to that?

I would rather keep the duplication over going back to v1.

I may have another way to keep the code common, but let's look at that 
in a latter patch. For now, I will deal with the duplication.

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

* Re: [PATCH v2 18/21] xen/arm: Allow vpl011 to be used by DomU
  2018-07-27 11:00       ` Julien Grall
@ 2018-07-27 21:42         ` Stefano Stabellini
  0 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-27 21:42 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Fri, 27 Jul 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 27/07/18 01:10, Stefano Stabellini wrote:
> > On Tue, 24 Jul 2018, Julien Grall wrote:
> > > On 07/07/18 00:12, Stefano Stabellini wrote:
> > > > +    VPL011_UNLOCK(d, flags);
> > > > +}
> > > > +
> > > > +static void vpl011_write_data_noring(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);
> > > 
> > > You want to buffer the characters here and only print on newline or when
> > > the
> > > buffer is full. Otherwise characters will get mangled with the Xen console
> > > output or other domains output.
> > 
> > I did the implementation, but then when I type characters at the domain
> > prompt, I don't see them anymore one by one. Only after I press
> > "enter". That makes the domain console not very usable. Should we keep
> > it as?
> 
> I haven't thought about that case. However, if you don't implement the buffer
> solution, you will get all the domain consoles mangled during boot. This is
> not really nice for debugging. A potential solution is to buffer for all the
> domains but the one that is reading characters.

I think I found a good way to buffer the output, unless the console is
in focus. For our future reference, it will be implemented in a separate
patch for review clarity.


> > > > +
> > > > +    vpl011->uartris |= TXI;
> > > > +    vpl011->uartfr &= ~TXFE;
> > > > +    vpl011_update_interrupt_status(d);
> > > > +
> > > > +    VPL011_UNLOCK(d, flags);
> > > > +}
> > > > +
> > > > +static uint8_t vpl011_read_data_inring(struct domain *d)
> > > > +{
> > > 
> > > I think you can avoid the duplication here by using a macro.
> > 
> > I prefer to avoid MACROS for things like this. I would rather reuse the
> > existing function for both cases like in v1. Would you be OK to go back
> > to that?
> 
> I would rather keep the duplication over going back to v1.
> 
> I may have another way to keep the code common, but let's look at that in a
> latter patch. For now, I will deal with the duplication.

OK

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

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

* Re: [PATCH v2 17/21] xen/arm: refactor vpl011_data_avail
  2018-07-24  9:58   ` Julien Grall
@ 2018-07-27 22:37     ` Stefano Stabellini
  0 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-27 22:37 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov, xen-devel

On Tue, 24 Jul 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 07/07/18 00:12, Stefano Stabellini wrote:
> > Move the code to calculate in_fifo_level and out_fifo_level out of
> > vpl011_data_avail, to the caller.
> > This change will make it possible to reuse vpl011_data_avail with
> > different ring structures in a later patch.
> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > 
> > ---
> > Changes in v2:
> > - new patch
> > ---
> >   xen/arch/arm/vpl011.c | 70
> > ++++++++++++++++++++++++++++++---------------------
> >   1 file changed, 42 insertions(+), 28 deletions(-)
> > 
> > diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> > index 33fcaa0..e75957f 100644
> > --- a/xen/arch/arm/vpl011.c
> > +++ b/xen/arch/arm/vpl011.c
> > @@ -34,6 +34,12 @@
> >   #include <asm/vgic-emul.h>
> >   #include <asm/vpl011.h>
> >   +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);
> > +
> 
> Looking at the end code, I think you can avoid the declaration by adding
> vpl011_rx_char somewhere else.
 
Yes, you are right. I'll do that.

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

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

* Re: [PATCH v2 19/21] xen/arm: introduce create_domUs
  2018-07-24 13:53   ` Julien Grall
@ 2018-07-28  2:42     ` Stefano Stabellini
  2018-07-30 10:26       ` Julien Grall
  0 siblings, 1 reply; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-28  2:42 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov,
	andrew.cooper3, xen-devel, jbeulich

On Tue, 24 Jul 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 07/07/18 00:12, Stefano Stabellini wrote:
> > Call a new function, "create_domUs", from setup_xen to start DomU VMs.
> > 
> > Introduce support for the "xen,domU" compatible node on device tree.
> > Create new DomU VMs based on the information found on device tree under
> > "xen,domU". Calls construct_domU for each domain.
> > 
> > Introduce a simple global variable named max_init_domid to keep track of
> > the initial allocated domids.
> > 
> > Move the discard_initial_modules after DomUs have been built
> 
> Nit: Missing full stop.

OK


> > 
> > Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
> > CC: andrew.cooper3@citrix.com
> > CC: jbeulich@suse.com
> > ---
> > Changes in v2:
> > - coding style
> > - set nr_spis to 32
> > - introduce create_domUs
> > ---
> >   xen/arch/arm/domain_build.c | 38 +++++++++++++++++++++++++++++++++++---
> >   xen/arch/arm/setup.c        |  8 +++++++-
> >   xen/include/asm-arm/setup.h |  3 +++
> >   xen/include/asm-x86/setup.h |  2 ++
> >   4 files changed, 47 insertions(+), 4 deletions(-)
> > 
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index d7e9040..9f58002 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>
> > @@ -2542,6 +2543,39 @@ static int __init construct_domU(struct domain *d,
> > struct dt_device_node *node)
> >       return rc;
> >   }
> >   +void __init create_domUs(void)
> > +{
> > +    struct dt_device_node *node;
> > +    struct dt_device_node *chosen = dt_find_node_by_name(dt_host,
> > "chosen");
> 
> newline here.

OK


> > +    if ( chosen != NULL )
> > +    {
> > +        dt_for_each_child_node(chosen, node)
> > +        {
> > +            struct domain *d;
> > +            struct xen_domctl_createdomain d_cfg = {};
> > +
> > +            if ( !dt_device_is_compatible(node, "xen,domain") )
> > +                continue;
> > +
> > +            d_cfg.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
> > +            d_cfg.arch.nr_spis = 32;
> 
> You can set those fields directly when defining d_cfg above.

OK


> > +
> > +            d = domain_create(max_init_domid++, &d_cfg);
> > +            if ( IS_ERR(d) )
> > +                panic("Error creating domU");
> 
> It is probably worth to add the node name in the message. So the user knows
> which guest failed.

OK


> > +
> > +            d->is_privileged = 0;
> > +            d->is_console = 1;
> > +            d->target = NULL;
> > +
> > +            if ( construct_domU(d, node) != 0 )
> > +                printk("Could not set up DOMU guest OS");
> 
> Should not it be a panic here? Also, the message is a little odd "DOMU guest"
> is a bit redundant and the function will load the kernel but that's not the
> only thing done.
> 
> Lastly, you probably want to add the node name in the message, so the user
> knows which guest failed.

OK to all suggestions


> > +
> > +            domain_unpause_by_systemcontroller(d);
> 
> If a domain is bound to CPU0, then it will not boot until CPU0 is done with
> creating domain. Is that what you want?

Are you suggesting to move the domain_unpause_by_systemcontroller(d) to
a second loop after the domU creation loop?


> > +        }
> > +    }
> > +}
> > +
> >   int __init construct_dom0(struct domain *d)
> >   {
> >       struct kernel_info kinfo = {};
> > @@ -2592,9 +2626,7 @@ int __init construct_dom0(struct domain *d)
> >           return rc;
> >     -    rc = __construct_domain(d, &kinfo);
> > -    discard_initial_modules();
> > -    return rc;
> > +    return __construct_domain(d, &kinfo);
> >   }
> >     /*
> > diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> > index 7739a80..0b08af2 100644
> > --- a/xen/arch/arm/setup.c
> > +++ b/xen/arch/arm/setup.c
> > @@ -64,6 +64,8 @@ static unsigned long opt_xenheap_megabytes __initdata;
> >   integer_param("xenheap_megabytes", opt_xenheap_megabytes);
> >   #endif
> >   +domid_t __read_mostly max_init_domid = 0;
> > +
> >   static __used void init_done(void)
> >   {
> >       free_init_memory();
> > @@ -863,7 +865,7 @@ void __init start_xen(unsigned long boot_phys_offset,
> >       dom0_cfg.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
> >       dom0_cfg.arch.nr_spis = gic_number_lines() - 32;
> >   -    dom0 = domain_create(0, &dom0_cfg);
> > +    dom0 = domain_create(max_init_domid++, &dom0_cfg);
> >       if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
> >               panic("Error creating domain 0");
> >   @@ -889,6 +891,10 @@ void __init start_xen(unsigned long boot_phys_offset,
> >         domain_unpause_by_systemcontroller(dom0);
> 
> Why do you unpause Dom0 and then create the guests? It feels like to me you
> want to create all the guests and then unpause dom0. dom0 would likely get
> blocked anyway has CPU0 will be busy creating domains.

Right, I'll do that


> >   +    create_domUs();
> > +
> > +    discard_initial_modules();
> 
> I think it would be better to move that in init_done. This is where all
> initial memory is freed.

Good idea, I'll do that


> > +
> >       /* Switch on to the dynamically allocated stack for the idle vcpu
> >        * since the static one we're running on is about to be freed. */
> >       memcpy(idle_vcpu[0]->arch.cpu_info, get_cpu_info(),
> > diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
> > index 5ecfe27..21b9729 100644
> > --- a/xen/include/asm-arm/setup.h
> > +++ b/xen/include/asm-arm/setup.h
> > @@ -56,6 +56,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);
> > @@ -72,6 +74,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 19232af..2fb9529 100644
> > --- a/xen/include/asm-x86/setup.h
> > +++ b/xen/include/asm-x86/setup.h
> > @@ -73,4 +73,6 @@ extern bool opt_dom0_shadow;
> >   #endif
> >   extern bool dom0_pvh;
> >   +#define max_init_domid (1)
> > +
> >   #endif
 

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

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

* Re: [PATCH v2 19/21] xen/arm: introduce create_domUs
  2018-07-28  2:42     ` Stefano Stabellini
@ 2018-07-30 10:26       ` Julien Grall
  2018-07-30 18:15         ` Stefano Stabellini
  0 siblings, 1 reply; 92+ messages in thread
From: Julien Grall @ 2018-07-30 10:26 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Stefano Stabellini, andrew.cooper3, andrii_anisov, jbeulich, xen-devel

Hi Stefano,

On 28/07/18 03:42, Stefano Stabellini wrote:
> On Tue, 24 Jul 2018, Julien Grall wrote:
>>> +
>>> +            domain_unpause_by_systemcontroller(d);
>>
>> If a domain is bound to CPU0, then it will not boot until CPU0 is done with
>> creating domain. Is that what you want?
> 
> Are you suggesting to move the domain_unpause_by_systemcontroller(d) to
> a second loop after the domU creation loop?

I was trying to understand what are the pro/cons of unpausing a DomU 
here. Did you explore it?

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

* Re: [PATCH v2 19/21] xen/arm: introduce create_domUs
  2018-07-30 10:26       ` Julien Grall
@ 2018-07-30 18:15         ` Stefano Stabellini
  0 siblings, 0 replies; 92+ messages in thread
From: Stefano Stabellini @ 2018-07-30 18:15 UTC (permalink / raw)
  To: Julien Grall
  Cc: Stefano Stabellini, Stefano Stabellini, andrii_anisov,
	andrew.cooper3, xen-devel, jbeulich

On Mon, 30 Jul 2018, Julien Grall wrote:
> Hi Stefano,
> 
> On 28/07/18 03:42, Stefano Stabellini wrote:
> > On Tue, 24 Jul 2018, Julien Grall wrote:
> > > > +
> > > > +            domain_unpause_by_systemcontroller(d);
> > > 
> > > If a domain is bound to CPU0, then it will not boot until CPU0 is done
> > > with
> > > creating domain. Is that what you want?
> > 
> > Are you suggesting to move the domain_unpause_by_systemcontroller(d) to
> > a second loop after the domU creation loop?
> 
> I was trying to understand what are the pro/cons of unpausing a DomU here. Did
> you explore it?

OK, let's dig into it.

domain_unpause_by_systemcontroller doesn't actually trigger a DomU boot
right away. It only marks the vcpu as ready to be started.  Then, it is
up to Xen wanting to leave hypervisor mode and start running a guest
vcpu. So there should be no issues in unpausing the vcpus here, in fact,
it should make no difference whether it is done inside this loop or on a
second loop.

In my experiments, cpu1 starts first, running dom1v0, then cpu0 (after
completely start_xen) running dom0v0.

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

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

* Re: [PATCH v2 03/21] xen: allow console_io hypercalls from certain DomUs
  2018-07-19  9:19           ` Julien Grall
@ 2018-08-17 19:41             ` Daniel De Graaf
  0 siblings, 0 replies; 92+ messages in thread
From: Daniel De Graaf @ 2018-08-17 19:41 UTC (permalink / raw)
  To: Julien Grall, Stefano Stabellini
  Cc: Stefano Stabellini, andrii_anisov, George.Dunlap, andrew.cooper3,
	ian.jackson, xen-devel, tim, jbeulich, wei.liu2, nd

On 07/19/2018 05:19 AM, Julien Grall wrote:
> Hi Stefano,
> 
> On 18/07/18 18:10, Stefano Stabellini wrote:
>> On Tue, 17 Jul 2018, Julien Grall wrote:
>>> Hi Stefano,
>>>
>>> On 17/07/2018 21:05, Stefano Stabellini wrote:
>>>> On Mon, 9 Jul 2018, Julien Grall wrote:
>>>>> Hi,
>>>>>
>>>>> On 07/07/18 00:11, Stefano Stabellini wrote:
>>>>>> Introduce an is_console option to allow certain classes of domUs to use
>>>>>> the Xen console. Specifically, it will be used to give console access to
>>>>>> all domUs started from Xen from information on device tree.
>>>>>>
>>>>>> Signed-off-by: Stefano Stabellini <stefanos@xilinx.com>
>>>>>> 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 v2:
>>>>>> - introduce is_console
>>>>>> - remove #ifdefs
>>>>>> ---
>>>>>>     xen/include/xen/sched.h | 2 ++
>>>>>>     xen/include/xsm/dummy.h | 2 ++
>>>>>>     xen/xsm/flask/hooks.c   | 5 ++++-
>>>>>>     3 files changed, 8 insertions(+), 1 deletion(-)
>>>>>>
>>>>>> diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
>>>>>> index 99d2af2..d66cec0 100644
>>>>>> --- a/xen/include/xen/sched.h
>>>>>> +++ b/xen/include/xen/sched.h
>>>>>> @@ -379,6 +379,8 @@ struct domain
>>>>>>         bool             auto_node_affinity;
>>>>>>         /* Is this guest fully privileged (aka dom0)? */
>>>>>>         bool             is_privileged;
>>>>>> +    /* Can this guest access the Xen console? */
>>>>>> +    bool             is_console;
>>>>>>         /* Is this a xenstore domain (not dom0)? */
>>>>>>         bool             is_xenstore;
>>>>>>         /* Domain's VCPUs are pinned 1:1 to physical CPUs? */
>>>>>> diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
>>>>>> index ff6b2db..3888817 100644
>>>>>> --- a/xen/include/xsm/dummy.h
>>>>>> +++ b/xen/include/xsm/dummy.h
>>>>>> @@ -230,6 +230,8 @@ static XSM_INLINE int
>>>>>> xsm_memory_stat_reservation(XSM_DEFAULT_ARG struct domain
>>>>>>     static XSM_INLINE int xsm_console_io(XSM_DEFAULT_ARG struct domain
>>>>>> *d, int
>>>>>> cmd)
>>>>>>     {
>>>>>>         XSM_ASSERT_ACTION(XSM_OTHER);
>>>>>> +    if ( d->is_console )
>>>>>> +        return xsm_default_action(XSM_HOOK, d, NULL);
>>>>>
>>>>> I will let Daniel commenting on this change. However ...
>>>>>
>>>>>>     #ifdef CONFIG_VERBOSE_DEBUG
>>>>>>         if ( cmd == CONSOLEIO_write )
>>>>>>             return xsm_default_action(XSM_HOOK, d, NULL);
>>>>>> diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
>>>>>> index 78bc326..2551e4e 100644
>>>>>> --- a/xen/xsm/flask/hooks.c
>>>>>> +++ b/xen/xsm/flask/hooks.c
>>>>>> @@ -443,7 +443,10 @@ static int flask_console_io(struct domain *d, int
>>>>>> cmd)
>>>>>>             return avc_unknown_permission("console_io", cmd);
>>>>>>         }
>>>>>>     -    return domain_has_xen(d, perm);
>>>>>> +    if ( !d->is_console )
>>>>>> +        return domain_has_xen(d, perm);
>>>>>> +    else
>>>>>> +        return 0;
>>>>>
>>>>> ... I don't think this change is correct. When a policy is used, the user
>>>>> is
>>>>> free to define what is the behavior. With your solution, you impose the
>>>>> console access even if the user didn't to not give the permission.
>>>>
>>>> I was hoping Daniel would advise on the best way to do things here.
>>>>
>>>> I thought that the idea was that granting a domain "is_console" is
>>>> equivalent to granting a domain XEN__READCONSOLE and XEN__WRITECONSOLE
>>>> permissions.  Thus, if is_console is set, we return 0 from
>>>> flask_console_io because the permissions check succeeds.
>>>
>>> Well, yes and no. That's equivalent when you use the dummy policy. When you
>>> have a flask policy you want to give the control to the user.
>>>
>>> If you look at the code there are no such as d->is_privilege in that function.
>>> This means that the user define the policy for the hardware domain. Why would
>>> be d->is_console different here?
>>
>> You are saying that in hooks.c the check should remain exactly as is:
>>
>>    return domain_has_xen(d, perm);
>>
>> and d->is_console should not be tested?
> 
> Yes.
> 
>> In that case, do you know if I
>> need to do anything special with XEN__READCONSOLE and XEN__WRITECONSOLE
>> permissions for the initial boot domains (such as adding those
>> permissions as the same time d->is_console is set)?
> 
> The main purpose of XSM is to provide a fine grain permission for the user to configure. For instance, a user may not console access for initial domain for security purpose. So you don't have anything to in the code.
> 
> However, when you have XSM enabled, you will have to write down in the policy that initial domains will have console access. Although, I am not sure how to write that in the policy.

In a security policy that wishes to make this distinction, the initial domains will
have distinct security labels from domains created later.  Then, those types are
allowed console_write access (along with any other special rights they may need).

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

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

end of thread, other threads:[~2018-08-17 19:41 UTC | newest]

Thread overview: 92+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-06 23:11 [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Stefano Stabellini
2018-07-06 23:11 ` [PATCH v2 01/21] xen/arm: rename get_11_allocation_size to get_allocation_size Stefano Stabellini
2018-07-09 12:55   ` Julien Grall
2018-07-11 20:09     ` Stefano Stabellini
2018-07-06 23:11 ` [PATCH v2 02/21] xen/arm: make allocate_memory work for non 1:1 mapped guests Stefano Stabellini
2018-07-09 13:43   ` Julien Grall
2018-07-09 23:02     ` Stefano Stabellini
2018-07-10 17:57       ` Julien Grall
2018-07-11 21:42         ` Stefano Stabellini
2018-07-09 13:58   ` Julien Grall
2018-07-09 23:10     ` Stefano Stabellini
2018-07-23 18:01   ` Andrii Anisov
2018-07-23 18:32     ` Stefano Stabellini
2018-07-24 12:09       ` Andrii Anisov
2018-07-06 23:11 ` [PATCH v2 03/21] xen: allow console_io hypercalls from certain DomUs Stefano Stabellini
2018-07-09 13:48   ` Julien Grall
2018-07-17 20:05     ` Stefano Stabellini
2018-07-17 20:26       ` Julien Grall
2018-07-18 17:10         ` Stefano Stabellini
2018-07-19  9:19           ` Julien Grall
2018-08-17 19:41             ` Daniel De Graaf
2018-07-06 23:11 ` [PATCH v2 04/21] xen/arm: move a few DT related defines to public/device_tree_defs.h Stefano Stabellini
2018-07-09 13:59   ` Julien Grall
2018-07-06 23:12 ` [PATCH v2 05/21] xen/arm: extend device tree based multiboot protocol Stefano Stabellini
2018-07-09 14:07   ` Julien Grall
2018-07-13 22:41     ` Stefano Stabellini
2018-07-16 14:14       ` Julien Grall
2018-07-16 22:02         ` Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 06/21] xen/arm: do not pass dt_host to make_memory_node and make_hypervisor_node Stefano Stabellini
2018-07-09 14:11   ` Julien Grall
2018-07-09 21:51     ` Stefano Stabellini
2018-07-10 17:28       ` Julien Grall
2018-07-11 20:33         ` Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 07/21] xen/arm: rename acpi_make_chosen_node to make_chosen_node Stefano Stabellini
2018-07-09 14:12   ` Julien Grall
2018-07-06 23:12 ` [PATCH v2 08/21] xen/arm: increase MAX_MODULES Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 09/21] xen/arm: move cmdline out of boot_modules Stefano Stabellini
2018-07-09 14:53   ` Julien Grall
2018-07-10  0:00     ` Stefano Stabellini
2018-07-10 21:11       ` Julien Grall
2018-07-13  0:04         ` Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 10/21] xen/arm: don't add duplicate boot modules Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 11/21] xen/arm: probe domU kernels and initrds Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 12/21] xen/arm: refactor construct_dom0 Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 13/21] xen/arm: introduce construct_domU Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 14/21] xen/arm: generate a simple device tree for domUs Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 15/21] xen/arm: generate vpl011 node on device tree for domU Stefano Stabellini
2018-07-12 18:14   ` Julien Grall
2018-07-13 21:24     ` Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 16/21] xen/arm: introduce a union in vpl011 Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 17/21] xen/arm: refactor vpl011_data_avail Stefano Stabellini
2018-07-24  9:58   ` Julien Grall
2018-07-27 22:37     ` Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 18/21] xen/arm: Allow vpl011 to be used by DomU Stefano Stabellini
2018-07-24 11:00   ` Julien Grall
2018-07-27  0:10     ` Stefano Stabellini
2018-07-27 11:00       ` Julien Grall
2018-07-27 21:42         ` Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 19/21] xen/arm: introduce create_domUs Stefano Stabellini
2018-07-16 16:10   ` Jan Beulich
2018-07-16 21:44     ` Stefano Stabellini
2018-07-24 13:53   ` Julien Grall
2018-07-28  2:42     ` Stefano Stabellini
2018-07-30 10:26       ` Julien Grall
2018-07-30 18:15         ` Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 20/21] xen: support console_switching between Dom0 and DomUs on ARM Stefano Stabellini
2018-07-16 16:19   ` Jan Beulich
2018-07-16 21:55     ` Stefano Stabellini
2018-07-17  6:37       ` Jan Beulich
2018-07-17 16:43         ` Stefano Stabellini
2018-07-18  6:41           ` Jan Beulich
2018-07-18 16:51             ` Stefano Stabellini
2018-07-17  8:40       ` Jan Beulich
2018-07-17 16:33         ` Stefano Stabellini
2018-07-17 20:29   ` Julien Grall
2018-07-18  7:12     ` Jan Beulich
2018-07-18 16:59       ` Julien Grall
2018-07-19  6:10         ` Jan Beulich
2018-07-19 17:18           ` Stefano Stabellini
2018-07-18 17:01       ` Stefano Stabellini
2018-07-18 20:37         ` George Dunlap
2018-07-17 20:34   ` Julien Grall
2018-07-18 17:31     ` Stefano Stabellini
2018-07-06 23:12 ` [PATCH v2 21/21] xen/arm: split domain_build.c Stefano Stabellini
2018-07-12 18:18 ` [PATCH v2 00/21] dom0less step1: boot multiple domains from device tree Julien Grall
2018-07-13 20:54   ` Stefano Stabellini
2018-07-18 16:48     ` Julien Grall
2018-07-18 17:48       ` Stefano Stabellini
2018-07-23 17:13         ` Julien Grall
2018-07-23 17:52           ` Stefano Stabellini
2018-07-23 17:14 ` Andrii Anisov
2018-07-23 17:55   ` 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.