[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v6 1/2] xen/domain: unify domain ID allocation
On Fri, May 16, 2025 at 09:35:35PM +0100, Julien Grall wrote: > Hi Denis and Teddy, > > I haven't looked at the rest of the series. Just answering > to the discussion between both of you. > > On 16/05/2025 19:06, dmkhn@xxxxxxxxx wrote: > > On Fri, May 16, 2025 at 08:43:35AM +0000, Teddy Astie wrote: > >>> diff --git a/xen/common/device-tree/dom0less-build.c > >>> b/xen/common/device-tree/dom0less-build.c > >>> index 2c56f13771..9236dbae11 100644 > >>> --- a/xen/common/device-tree/dom0less-build.c > >>> +++ b/xen/common/device-tree/dom0less-build.c > >>> @@ -850,15 +850,13 @@ void __init create_domUs(void) > >>> struct xen_domctl_createdomain d_cfg = {0}; > >>> unsigned int flags = 0U; > >>> bool has_dtb = false; > >>> + domid_t domid; > >>> uint32_t val; > >>> int rc; > >>> > >>> if ( !dt_device_is_compatible(node, "xen,domain") ) > >>> continue; > >>> > >>> - if ( (max_init_domid + 1) >= DOMID_FIRST_RESERVED ) > >>> - panic("No more domain IDs available\n"); > >>> - > >>> d_cfg.max_evtchn_port = 1023; > >>> d_cfg.max_grant_frames = -1; > >>> d_cfg.max_maptrack_frames = -1; > >>> @@ -981,7 +979,11 @@ void __init create_domUs(void) > >>> * very important to use the pre-increment operator to call > >>> * domain_create() with a domid > 0. (domid == 0 is reserved > >>> for Dom0) > >>> */ > >>> - d = domain_create(++max_init_domid, &d_cfg, flags); > >>> + domid = domid_alloc(++max_init_domid); > >>> + if ( domid == DOMID_INVALID ) > >>> + panic("Error allocating ID for domain %s\n", > >>> dt_node_name(node)); > >>> + > >>> + d = domain_create(domid, &d_cfg, flags); > >>> if ( IS_ERR(d) ) > >>> panic("Error creating domain %s (rc = %ld)\n", > >>> dt_node_name(node), PTR_ERR(d)); > >>> diff --git a/xen/common/domain.c b/xen/common/domain.c > >>> index abf1969e60..0ba3cdc47d 100644 > >>> --- a/xen/common/domain.c > >>> +++ b/xen/common/domain.c > >>> @@ -66,6 +66,74 @@ DEFINE_RCU_READ_LOCK(domlist_read_lock); > >>> static struct domain *domain_hash[DOMAIN_HASH_SIZE]; > >>> struct domain *domain_list; > >>> > >>> +/* Non-system domain ID allocator. */ > >>> +static DEFINE_SPINLOCK(domid_lock); > >>> +static struct rangeset *domid_rangeset; > >>> +static unsigned int domid_last; > >>> + > >>> +void __init domid_init(void) > >>> +{ > >>> + domid_rangeset = rangeset_new(NULL, "domid", > >>> RANGESETF_prettyprint_hex); > >>> + if ( !domid_rangeset ) > >>> + panic("cannot allocate domain ID rangeset\n"); > >>> + > >>> + rangeset_limit(domid_rangeset, DOMID_FIRST_RESERVED); > >>> +} > >>> + > >>> +/* > >>> + * Allocate new non-system domain ID based on the hint. > >>> + * > >>> + * If hint is outside of valid [0..DOMID_FIRST_RESERVED - 1] range of > >>> IDs, > >>> + * perform an exhaustive search starting from the end of the used domain > >>> ID > >>> + * range. > >>> + */ > >>> +domid_t domid_alloc(domid_t domid) > >>> +{ > >>> + spin_lock(&domid_lock); > >>> + > >>> + if ( domid < DOMID_FIRST_RESERVED ) > >>> + { > >>> + if ( rangeset_contains_singleton(domid_rangeset, domid) ) > >>> + domid = DOMID_INVALID; > >>> + } > >>> + else > >>> + { > >>> + for ( domid = domid_last + 1; domid != domid_last; domid++ ) > >>> + { > >>> + if ( domid == DOMID_FIRST_RESERVED ) > >>> + domid = 0; > >>> + > >>> + if ( !rangeset_contains_singleton(domid_rangeset, domid) ) > >>> + break; > >>> + } > >>> + > >>> + if ( domid == domid_last ) > >>> + domid = DOMID_INVALID; > >>> + } > >>> + > >>> + if ( domid != DOMID_INVALID ) > >>> + { > >>> + ASSERT(!rangeset_add_singleton(domid_rangeset, domid)); > >>> + > >>> + if ( domid != domid_last ) > >>> + domid_last = domid; > >>> + } > >>> + > >>> + spin_unlock(&domid_lock); > >>> + > >>> + return domid; > >>> +} > >> > >> It's mostly a matter of implementation choice, but I am not really fan > >> of relying on rangesets, which to me are meant for address ranges or > >> something similar but at least large. > >> > >> I would rather rely on a bitmap using find_first_zero_bit+set_bit which > >> avoids doing a per-domid test, and may be simpler overall. The bitmap > >> size for 0x3FF0 domains is almost 4KB, which looks acceptable. > > I guess you meant 0x7FF0? > > >> > >> I don't know what other thinks. > > > > Thanks for taking a look! > > > > TBH, I was initially considering using a bitmap. But then I chose use > > rangesets > > because statically defined bitmap will increase the binary size, which may > > be > > indesirable; and for dynamic allocation, rangeset has all convenience APIs > > implemented... > > The bitmap helpers have been optimized for fast lookup and insertion. > They could also potentially be used lockless. > > On the other hand, the rangeset is a linear search from start. So for > instance, AFAIU, "rangeset_contains_singleton()" will start looking up > from the first range until it found the highest range lower or > containing the singleton. It also contains an internal read-write lock. > So we are taking two locks now. > > This means the loop: > > > for ( domid = domid_last + 1; domid != domid_last; domid++ ) > > [...] > > if ( !rangeset_contains_singleton(...) ) > > is going to be fairly ineffient. I haven't check whether we can do > better with the rangeset. > > Also, the overhead of a range is actually quite high if the domain IDs > are not contiguous (for Arm 64-bit, it is 16-byte per range and 72-byte > for the the rangeset structure). > > Lastly, as you pointed out this is requiring dynamic allocation. Which > means domid_alloc() could now fail because Xen is out of memory. This > feels a little be odd to have domid_alloc() returning -ENOMEM. > > BTW, I noticed in your code you are using: > > ASSERT(!rangeset_add_singleton(...)) > > In production build, ASSERTs() behaves like a NOP: > > #define ASSERT(p) do { if ( 0 && (p) ) {} } while (0) > > So rangeset_add_singleton() would not be called at all. This is also not > the right way to handle failure that can happen at runtime. Instead, the > error should be propagated. > > Overall, I think a bitmap is more suitable to keep track of the domids > allocated. > > To make clear, I think increase the binary by 4KB is fine in this case. > If someone is really concern of the increase, they would most likely not > try to run 4KB domains, so we could potentially introduce > CONFIG_MAX_DOMAIN to reduce the bitmap size and the number of domains > (it is not a ask for this series). Thanks for taking a look! I will drop ASSERT()s and switch to bitmaps. > > Cheers, > > -- > Julien Grall > >
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |