diff mbox series

[7/8] xen: introduce xen-evtchn dom0less property

Message ID f2bc792f8dea59648b011cda4fe7c42929c4e3d7.1655903088.git.rahul.singh@arm.com (mailing list archive)
State Superseded
Headers show
Series xen/evtchn: implement static event channel signaling | expand

Commit Message

Rahul Singh June 22, 2022, 2:38 p.m. UTC
Introduce a new sub-node under /chosen node to establish static event
channel communication between domains on dom0less systems.

An event channel will be created beforehand to allow the domains to
send notifications to each other.

Signed-off-by: Rahul Singh <rahul.singh@arm.com>
---
 docs/misc/arm/device-tree/booting.txt |  62 +++++++++++-
 xen/arch/arm/domain_build.c           | 139 ++++++++++++++++++++++++++
 xen/arch/arm/include/asm/domain.h     |   1 +
 xen/arch/arm/include/asm/setup.h      |   1 +
 xen/arch/arm/setup.c                  |   2 +
 5 files changed, 204 insertions(+), 1 deletion(-)

Comments

Rahul Singh Aug. 5, 2022, 4:10 p.m. UTC | #1
Hi , 

> On 22 Jun 2022, at 3:38 pm, Rahul Singh <Rahul.Singh@arm.com> wrote:
> 
> Introduce a new sub-node under /chosen node to establish static event
> channel communication between domains on dom0less systems.
> 
> An event channel will be created beforehand to allow the domains to
> send notifications to each other.
> 
> Signed-off-by: Rahul Singh <rahul.singh@arm.com>
> ---
> docs/misc/arm/device-tree/booting.txt |  62 +++++++++++-
> xen/arch/arm/domain_build.c           | 139 ++++++++++++++++++++++++++
> xen/arch/arm/include/asm/domain.h     |   1 +
> xen/arch/arm/include/asm/setup.h      |   1 +
> xen/arch/arm/setup.c                  |   2 +
> 5 files changed, 204 insertions(+), 1 deletion(-)

I am waiting for a review for this patch and the next patch in the series before
I send the next version. Sending this email as a gentle reminder.

Thanks in advance. 

Regards,
Rahul
Julien Grall Aug. 5, 2022, 4:14 p.m. UTC | #2
On 05/08/2022 17:10, Rahul Singh wrote:
> Hi ,

Hi Rahul,

>> On 22 Jun 2022, at 3:38 pm, Rahul Singh <Rahul.Singh@arm.com> wrote:
>>
>> Introduce a new sub-node under /chosen node to establish static event
>> channel communication between domains on dom0less systems.
>>
>> An event channel will be created beforehand to allow the domains to
>> send notifications to each other.
>>
>> Signed-off-by: Rahul Singh <rahul.singh@arm.com>
>> ---
>> docs/misc/arm/device-tree/booting.txt |  62 +++++++++++-
>> xen/arch/arm/domain_build.c           | 139 ++++++++++++++++++++++++++
>> xen/arch/arm/include/asm/domain.h     |   1 +
>> xen/arch/arm/include/asm/setup.h      |   1 +
>> xen/arch/arm/setup.c                  |   2 +
>> 5 files changed, 204 insertions(+), 1 deletion(-)
> 
> I am waiting for a review for this patch and the next patch in the series before
> I send the next version. Sending this email as a gentle reminder.

I wasn't planning to review this patch and the next one yet because this 
looks mostly parsing. I think this is more important to get patch #1-#6 
correct first.

Cheers,
Rahul Singh Aug. 8, 2022, 9:17 a.m. UTC | #3
Hi Julien,

> On 5 Aug 2022, at 5:14 pm, Julien Grall <julien@xen.org> wrote:
> 
> 
> 
> On 05/08/2022 17:10, Rahul Singh wrote:
>> Hi ,
> 
> Hi Rahul,
> 
>>> On 22 Jun 2022, at 3:38 pm, Rahul Singh <Rahul.Singh@arm.com> wrote:
>>> 
>>> Introduce a new sub-node under /chosen node to establish static event
>>> channel communication between domains on dom0less systems.
>>> 
>>> An event channel will be created beforehand to allow the domains to
>>> send notifications to each other.
>>> 
>>> Signed-off-by: Rahul Singh <rahul.singh@arm.com>
>>> ---
>>> docs/misc/arm/device-tree/booting.txt |  62 +++++++++++-
>>> xen/arch/arm/domain_build.c           | 139 ++++++++++++++++++++++++++
>>> xen/arch/arm/include/asm/domain.h     |   1 +
>>> xen/arch/arm/include/asm/setup.h      |   1 +
>>> xen/arch/arm/setup.c                  |   2 +
>>> 5 files changed, 204 insertions(+), 1 deletion(-)
>> I am waiting for a review for this patch and the next patch in the series before
>> I send the next version. Sending this email as a gentle reminder.
> 
> I wasn't planning to review this patch and the next one yet because this looks mostly parsing. I think this is more important to get patch #1-#6 correct first.

Make sense, then I will send the next version of patches #1-#6 for review.

Regards,
Rahul 
> 
> Cheers,
> 
> -- 
> Julien Grall
diff mbox series

Patch

diff --git a/docs/misc/arm/device-tree/booting.txt b/docs/misc/arm/device-tree/booting.txt
index 98253414b8..83e914b505 100644
--- a/docs/misc/arm/device-tree/booting.txt
+++ b/docs/misc/arm/device-tree/booting.txt
@@ -212,7 +212,7 @@  with the following properties:
     enable only selected interfaces.
 
 Under the "xen,domain" compatible node, one or more sub-nodes are present
-for the DomU kernel and ramdisk.
+for the DomU kernel, ramdisk and static event channel.
 
 The kernel sub-node has the following properties:
 
@@ -254,11 +254,42 @@  The ramdisk sub-node has the following properties:
     property because it will be created by the UEFI stub on boot.
     This option is needed only when UEFI boot is used.
 
+The static event channel sub-node has the following properties:
+
+- compatible
+
+    "xen,evtchn"
+
+- xen,evtchn
+
+    The property is tuples of two numbers
+    (local-evtchn link-to-foreign-evtchn) where:
+
+    local-evtchn is an integer value that will be used to allocate local port
+    for a domain to send and receive event notifications to/from the remote
+    domain. Maximum supported value is 2^17 for FIFO ABI and 4096 for 2L ABI.
+
+    link-to-foreign-evtchn is a single phandle to a remote evtchn to which
+    local-evtchn will be connected.
 
 Example
 =======
 
 chosen {
+
+    module@0 {
+        compatible = "multiboot,kernel", "multiboot,module";
+        xen,uefi-binary = "...";
+        bootargs = "...";
+
+        /* one sub-node per local event channel */
+        ec1: evtchn@1 {
+            compatible = "xen,evtchn-v1";
+            /* local-evtchn link-to-foreign-evtchn */
+            xen,evtchn = <0xa &ec2>;
+        };
+    };
+
     domU1 {
         compatible = "xen,domain";
         #address-cells = <0x2>;
@@ -277,6 +308,23 @@  chosen {
             compatible = "multiboot,ramdisk", "multiboot,module";
             reg = <0x0 0x4b000000 0xffffff>;
         };
+
+        /* one sub-node per local event channel */
+        ec2: evtchn@2 {
+            compatible = "xen,evtchn-v1";
+            /* local-evtchn link-to-foreign-evtchn */
+            xen,evtchn = <0xa &ec1>;
+        };
+
+        ec3: evtchn@3 {
+            compatible = "xen,evtchn-v1";
+            xen,evtchn = <0xb &ec5>;
+        };
+
+        ec4: evtchn@4 {
+            compatible = "xen,evtchn-v1";
+            xen,evtchn = <0xc &ec6>;
+        };
     };
 
     domU2 {
@@ -296,6 +344,18 @@  chosen {
             compatible = "multiboot,ramdisk", "multiboot,module";
             reg = <0x0 0x4d000000 0xffffff>;
         };
+
+        /* one sub-node per local event channel */
+        ec5: evtchn@5 {
+            compatible = "xen,evtchn-v1";
+            /* local-evtchn link-to-foreign-evtchn */
+            xen,evtchn = <0xb &ec3>;
+        };
+
+        ec6: evtchn@6 {
+            compatible = "xen,evtchn-v1";
+            xen,evtchn = <0xd &ec4>;
+        };
     };
 };
 
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 89195b042c..8925f0d80c 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -3052,6 +3052,144 @@  void __init evtchn_allocate(struct domain *d)
     d->arch.hvm.params[HVM_PARAM_CALLBACK_IRQ] = val;
 }
 
+static int __init allocate_domain_evtchn(const struct dt_device_node *node)
+{
+    const void *prop = NULL;
+    const __be32 *cell;
+    uint32_t len, domU1_port, domU2_port, remote_phandle;
+    const struct dt_device_node *evtchn_node, *remote_node;
+    struct evtchn_alloc_unbound alloc_unbound;
+    struct evtchn_bind_interdomain bind_interdomain;
+    int rc;
+
+    dt_for_each_child_node(node, evtchn_node)
+    {
+        struct domain *d, *d1 = NULL, *d2 = NULL;
+
+        if ( !dt_device_is_compatible(evtchn_node, "xen,evtchn-v1") )
+            continue;
+
+        prop = dt_get_property(evtchn_node, "xen,evtchn", &len);
+        /* If the property is not found, return without errors */
+        if ( !prop )
+            return 0;
+
+        if ( !len )
+        {
+            printk(XENLOG_ERR "xen,evtchn property cannot be empty.\n");
+            return -EINVAL;
+        }
+
+        cell = (const __be32 *)prop;
+        domU1_port = dt_next_cell(1, &cell);
+        remote_phandle = dt_next_cell(1, &cell);
+
+        remote_node = dt_find_node_by_phandle(remote_phandle);
+        if ( !remote_node )
+        {
+            printk(XENLOG_ERR
+                   "evtchn: could not find remote evtchn phandle\n");
+            return -EINVAL;
+        }
+
+        prop = dt_get_property(remote_node, "xen,evtchn", &len);
+        /* If the property is not found, return without errors */
+        if ( !prop )
+            return 0;
+
+        if ( !len )
+        {
+            printk(XENLOG_ERR "xen,evtchn property cannot be empty.\n");
+            return -EINVAL;
+        }
+
+        cell = (const __be32 *)prop;
+        domU2_port = dt_next_cell(1, &cell);
+        remote_phandle = dt_next_cell(1, &cell);
+
+        if ( evtchn_node->phandle != remote_phandle )
+        {
+            printk(XENLOG_ERR "xen,evtchn property is not setup correctly.\n");
+            return -EINVAL;
+        }
+
+        for_each_domain ( d )
+        {
+            if ( d->arch.node == node )
+            {
+                d1 = d;
+                continue;
+            }
+            if ( d->arch.node == dt_get_parent(remote_node) )
+                d2 = d;
+        }
+
+        if ( d1 == NULL )
+        {
+            if ( dt_device_is_compatible(node, "multiboot,kernel") )
+                d1 = hardware_domain;
+            else
+            {
+                printk(XENLOG_ERR "evtchn: could not find domain\n" );
+                return -EINVAL;
+            }
+        }
+
+        if ( d2 == NULL )
+        {
+            if ( dt_device_is_compatible(dt_get_parent(remote_node),
+                                         "multiboot,kernel") )
+                d2 = hardware_domain;
+            else
+            {
+                printk(XENLOG_ERR "evtchn: could not find domain\n" );
+                return -EINVAL;
+            }
+        }
+
+        alloc_unbound.dom = d1->domain_id;
+        alloc_unbound.remote_dom = d2->domain_id;
+
+        rc = evtchn_alloc_unbound(&alloc_unbound, domU1_port, true);
+        if ( rc < 0 && rc != -EBUSY )
+        {
+            printk(XENLOG_ERR
+                   "evtchn_alloc_unbound() failure (Error %d) \n", rc);
+            return rc;
+        }
+
+        bind_interdomain.remote_dom  = d1->domain_id;
+        bind_interdomain.remote_port = domU1_port;
+
+        rc = evtchn_bind_interdomain(&bind_interdomain, d2, domU2_port, true);
+        if ( rc < 0 && rc != -EBUSY )
+        {
+            printk(XENLOG_ERR
+                   "evtchn_bind_interdomain() failure (Error %d) \n", rc);
+            return rc;
+        }
+    }
+
+    return 0;
+}
+
+void __init allocate_static_evtchn(void)
+{
+    struct dt_device_node *node;
+    const struct dt_device_node *chosen = dt_find_node_by_path("/chosen");
+
+    BUG_ON(chosen == NULL);
+    dt_for_each_child_node(chosen, node)
+    {
+        if ( dt_device_is_compatible(node, "xen,domain") ||
+             dt_device_is_compatible(node, "multiboot,kernel") )
+        {
+            if ( allocate_domain_evtchn(node) != 0 )
+                panic("Could not set up domains evtchn\n");
+        }
+    }
+}
+
 static void __init find_gnttab_region(struct domain *d,
                                       struct kernel_info *kinfo)
 {
@@ -3358,6 +3496,7 @@  void __init create_domUs(void)
             panic("Error creating domain %s\n", dt_node_name(node));
 
         d->is_console = true;
+        d->arch.node = node;
 
         if ( construct_domU(d, node) != 0 )
             panic("Could not set up domain %s\n", dt_node_name(node));
diff --git a/xen/arch/arm/include/asm/domain.h b/xen/arch/arm/include/asm/domain.h
index ed63c2b6f9..7c22cbabcc 100644
--- a/xen/arch/arm/include/asm/domain.h
+++ b/xen/arch/arm/include/asm/domain.h
@@ -104,6 +104,7 @@  struct arch_domain
 #endif
 
     bool directmap;
+    struct dt_device_node *node;
 }  __cacheline_aligned;
 
 struct arch_vcpu
diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h
index 2bb01ecfa8..bac876e68e 100644
--- a/xen/arch/arm/include/asm/setup.h
+++ b/xen/arch/arm/include/asm/setup.h
@@ -106,6 +106,7 @@  int acpi_make_efi_nodes(void *fdt, struct membank tbl_add[]);
 
 void create_domUs(void);
 void create_dom0(void);
+void allocate_static_evtchn(void);
 
 void discard_initial_modules(void);
 void fw_unreserved_regions(paddr_t s, paddr_t e,
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 05d97a1cfb..0936db58b2 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -1046,6 +1046,8 @@  void __init start_xen(unsigned long boot_phys_offset,
     if ( acpi_disabled )
         create_domUs();
 
+    allocate_static_evtchn();
+
     /*
      * This needs to be called **before** heap_init_late() so modules
      * will be scrubbed (unless suppressed).