All of lore.kernel.org
 help / color / mirror / Atom feed
From: dmkhn@proton.me
To: Julien Grall <julien@xen.org>
Cc: Teddy Astie <teddy.astie@vates.tech>,
	xen-devel@lists.xenproject.org, andrew.cooper3@citrix.com,
	anthony.perard@vates.tech, jbeulich@suse.com,
	michal.orzel@amd.com, roger.pau@citrix.com,
	sstabellini@kernel.org, dmukhin@ford.com
Subject: Re: [PATCH v6 1/2] xen/domain: unify domain ID allocation
Date: Fri, 16 May 2025 21:14:10 +0000	[thread overview]
Message-ID: <aCeqnVcXIV3dyPBg@kraken> (raw)
In-Reply-To: <2e5afdf1-3913-4b6f-86ea-21b3ccd0833c@xen.org>

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@proton.me 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
> 
> 



  reply	other threads:[~2025-05-16 21:14 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-16  2:04 [PATCH v6 0/2] xen/domain: domain ID allocation dmkhn
2025-05-16  2:04 ` [PATCH v6 1/2] xen/domain: unify " dmkhn
2025-05-16  8:43   ` Teddy Astie
2025-05-16 18:06     ` dmkhn
2025-05-16 20:35       ` Julien Grall
2025-05-16 21:14         ` dmkhn [this message]
2025-05-18  8:52   ` Jan Beulich
2025-05-19 19:31     ` dmkhn
2025-05-16  2:04 ` [PATCH v6 2/2] xen/domain: adjust domain ID allocation for Arm dmkhn
2025-05-18  8:57   ` Jan Beulich
2025-05-19 19:28     ` dmkhn

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aCeqnVcXIV3dyPBg@kraken \
    --to=dmkhn@proton.me \
    --cc=andrew.cooper3@citrix.com \
    --cc=anthony.perard@vates.tech \
    --cc=dmukhin@ford.com \
    --cc=jbeulich@suse.com \
    --cc=julien@xen.org \
    --cc=michal.orzel@amd.com \
    --cc=roger.pau@citrix.com \
    --cc=sstabellini@kernel.org \
    --cc=teddy.astie@vates.tech \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.