[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v5 7/7] xen/arm: introduce xen-evtchn dom0less property
On Wed, 7 Sep 2022, Rahul Singh 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@xxxxxxx> For the DT binding: Reviewed-by: Stefano Stabellini <sstabellini@xxxxxxxxxx> > --- > Changes in v5: > - fix minor comments > Changes in v4: > - move documentation to common place for evtchn node in booting.txt > - Add comment why we use dt_device_static_evtchn_created() > - check if dt_get_parent() returns NULL > - fold process_static_evtchn_node() in alloc_static_evtchn() > Changes in v3: > - use device-tree used_by to find the domain id of the evtchn node. > - add new static_evtchn_create variable in struct dt_device_node to > hold the information if evtchn is already created. > - fix minor comments > Changes in v2: > - no change > --- > --- > docs/misc/arm/device-tree/booting.txt | 98 +++++++++++++++++ > xen/arch/arm/domain_build.c | 147 ++++++++++++++++++++++++++ > xen/arch/arm/include/asm/setup.h | 1 + > xen/arch/arm/setup.c | 2 + > xen/include/xen/device_tree.h | 16 +++ > 5 files changed, 264 insertions(+) > > diff --git a/docs/misc/arm/device-tree/booting.txt > b/docs/misc/arm/device-tree/booting.txt > index 47567b3906..e03e5e9e4c 100644 > --- a/docs/misc/arm/device-tree/booting.txt > +++ b/docs/misc/arm/device-tree/booting.txt > @@ -382,3 +382,101 @@ device-tree: > > This will reserve a 512MB region starting at the host physical address > 0x30000000 to be exclusively used by DomU1. > + > +Static Event Channel > +==================== > +The event channel communication will be established statically between two > +domains (dom0 and domU also). Event channel connection information between > +domains will be passed to Xen via the device tree node. The event channel > +will be created and established in Xen before the domain started. The domain > +does not need to do any operation to establish a connection. Domain only > +needs hypercall EVTCHNOP_send(local port) to send notifications to the > +remote guest. > + > +There is no need to describe the static event channel info in the domU device > +tree. Static event channels are only useful in fully static configurations, > +and in those configurations, the domU device tree dynamically generated by > Xen > +is not needed. > + > +To enable the event-channel interface for domU guests include the > +xen,enhanced = "no-xenstore" property in the domU Xen device tree node. > + > +Under the "xen,domain" compatible node for domU, there needs to be sub-nodes > +with compatible "xen,evtchn" that describe the event channel connection > +between two domUs. For dom0, there needs to be sub-nodes with compatible > +"xen,evtchn" under the chosen node. > + > +The static event channel 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. > + It is recommended to use low event channel IDs. > + > + link-to-foreign-evtchn is a single phandle to a remote evtchn to which > + local-evtchn will be connected. > + > +Example > +======= > + > +chosen { > + > + /* One sub-node per local event channel. This sub-node is for Dom0. */ > + ec1: evtchn@1 { > + compatible = "xen,evtchn-v1"; > + /* local-evtchn link-to-foreign-evtchn */ > + xen,evtchn = <0xa &ec2>; > + }; > + > + domU1 { > + compatible = "xen,domain"; > + #address-cells = <0x2>; > + #size-cells = <0x1>; > + xen,enhanced = "no-xenstore"; > + > + /* 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 { > + compatible = "xen,domain"; > + #address-cells = <0x2>; > + #size-cells = <0x1>; > + xen,enhanced = "no-xenstore"; > + > + /* 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 580ed70b9c..1a59bd7e29 100644 > --- a/xen/arch/arm/domain_build.c > +++ b/xen/arch/arm/domain_build.c > @@ -33,6 +33,8 @@ > #include <xen/grant_table.h> > #include <xen/serial.h> > > +#define STATIC_EVTCHN_NODE_SIZE_CELLS 2 > + > static unsigned int __initdata opt_dom0_max_vcpus; > integer_param("dom0_max_vcpus", opt_dom0_max_vcpus); > > @@ -3052,6 +3054,150 @@ void __init evtchn_allocate(struct domain *d) > d->arch.hvm.params[HVM_PARAM_CALLBACK_IRQ] = val; > } > > +static int __init get_evtchn_dt_property(const struct dt_device_node *np, > + uint32_t *port, uint32_t *phandle) > +{ > + const __be32 *prop = NULL; > + uint32_t len; > + > + prop = dt_get_property(np, "xen,evtchn", &len); > + if ( !prop ) > + { > + printk(XENLOG_ERR "xen,evtchn property should not be empty.\n"); > + return -EINVAL; > + } > + > + if ( !len || len < dt_cells_to_size(STATIC_EVTCHN_NODE_SIZE_CELLS) ) > + { > + printk(XENLOG_ERR "xen,evtchn property value is not valid.\n"); > + return -EINVAL; > + } > + > + *port = dt_next_cell(1, &prop); > + *phandle = dt_next_cell(1, &prop); > + > + return 0; > +} > + > +static int __init alloc_domain_evtchn(struct dt_device_node *node) > +{ > + int rc; > + uint32_t domU1_port, domU2_port, remote_phandle; > + struct dt_device_node *remote_node; > + const struct dt_device_node *p1_node, *p2_node; > + struct evtchn_alloc_unbound alloc_unbound; > + struct evtchn_bind_interdomain bind_interdomain; > + struct domain *d1 = NULL, *d2 = NULL; > + > + if ( !dt_device_is_compatible(node, "xen,evtchn-v1") ) > + return 0; > + > + /* > + * Event channel is already created while parsing the other side of > + * evtchn node. > + */ > + if ( dt_device_static_evtchn_created(node) ) > + return 0; > + > + rc = get_evtchn_dt_property(node, &domU1_port, &remote_phandle); > + if ( rc ) > + return rc; > + > + 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; > + } > + > + rc = get_evtchn_dt_property(remote_node, &domU2_port, &remote_phandle); > + if ( rc ) > + return rc; > + > + if ( node->phandle != remote_phandle ) > + { > + printk(XENLOG_ERR "xen,evtchn property is not setup correctly.\n"); > + return -EINVAL; > + } > + > + p1_node = dt_get_parent(node); > + if ( !p1_node ) > + { > + printk(XENLOG_ERR "evtchn: evtchn parent node is NULL\n" ); > + return -EINVAL; > + } > + > + p2_node = dt_get_parent(remote_node); > + if ( !p2_node ) > + { > + printk(XENLOG_ERR "evtchn: remote parent node is NULL\n" ); > + return -EINVAL; > + } > + > + d1 = get_domain_by_id(p1_node->used_by); > + d2 = get_domain_by_id(p2_node->used_by); > + > + if ( !d1 || !d2 ) > + { > + printk(XENLOG_ERR "evtchn: could not find domains\n" ); > + return -EINVAL; > + } > + > + alloc_unbound.dom = d1->domain_id; > + alloc_unbound.remote_dom = d2->domain_id; > + > + rc = evtchn_alloc_unbound(&alloc_unbound, domU1_port); > + if ( rc < 0 ) > + { > + 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); > + if ( rc < 0 ) > + { > + printk(XENLOG_ERR > + "evtchn_bind_interdomain() failure (Error %d) \n", rc); > + return rc; > + } > + > + dt_device_set_static_evtchn_created(node); > + dt_device_set_static_evtchn_created(remote_node); > + > + return 0; > +} > + > +void __init alloc_static_evtchn(void) > +{ > + struct dt_device_node *node, *evtchn_node; > + struct dt_device_node *chosen = dt_find_node_by_path("/chosen"); > + > + BUG_ON(chosen == NULL); > + > + if ( hardware_domain ) > + dt_device_set_used_by(chosen, hardware_domain->domain_id); > + > + dt_for_each_child_node(chosen, node) > + { > + if ( hardware_domain ) > + { > + if ( alloc_domain_evtchn(node) != 0 ) > + panic("Could not set up domains evtchn\n"); > + } > + > + dt_for_each_child_node(node, evtchn_node) > + { > + if ( alloc_domain_evtchn(evtchn_node) != 0 ) > + panic("Could not set up domains evtchn\n"); > + } > + } > +} > + > static void __init find_gnttab_region(struct domain *d, > struct kernel_info *kinfo) > { > @@ -3369,6 +3515,7 @@ void __init create_domUs(void) > panic("Error creating domain %s\n", dt_node_name(node)); > > d->is_console = true; > + dt_device_set_used_by(node, d->domain_id); > > 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/setup.h > b/xen/arch/arm/include/asm/setup.h > index 5815ccf8c5..5ee28b270f 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 alloc_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 7814fe323d..909013992e 100644 > --- a/xen/arch/arm/setup.c > +++ b/xen/arch/arm/setup.c > @@ -1078,6 +1078,8 @@ void __init start_xen(unsigned long boot_phys_offset, > if ( acpi_disabled ) > create_domUs(); > > + alloc_static_evtchn(); > + > /* > * This needs to be called **before** heap_init_late() so modules > * will be scrubbed (unless suppressed). > diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h > index 430a1ef445..a28937d12a 100644 > --- a/xen/include/xen/device_tree.h > +++ b/xen/include/xen/device_tree.h > @@ -92,6 +92,10 @@ struct dt_device_node { > > /* IOMMU specific fields */ > bool is_protected; > + > + /* HACK: Remove this if there is a need of space */ > + bool_t static_evtchn_created; > + > /* > * The main purpose of this list is to link the structure in the list > * of devices assigned to domain. > @@ -317,6 +321,18 @@ static inline bool_t dt_property_name_is_equal(const > struct dt_property *pp, > return !dt_prop_cmp(pp->name, name); > } > > +static inline void > +dt_device_set_static_evtchn_created(struct dt_device_node *device) > +{ > + device->static_evtchn_created = true; > +} > + > +static inline bool_t > +dt_device_static_evtchn_created(const struct dt_device_node *device) > +{ > + return device->static_evtchn_created; > +} > + > /** > * dt_find_compatible_node - Find a node based on type and one of the > * tokens in its "compatible" property > -- > 2.25.1 >
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |