Le 26/02/2026 à 15:54, Bernhard Kaindl a écrit : > Add a DOMCTL handler for claiming memory with NUMA awareness. It > rejects claims when LLC coloring (does not support claims) is enabled > and translates the public constant to the internal NUMA_NO_NODE. > > The request is forwarded to domain_set_outstanding_pages() for the > actual claim processing. The handler uses the same XSM hook as the > legacy XENMEM_claim_pages hypercall. > > While the underlying infrastructure currently supports only a single > claim, the public hypercall interface is designed to be extensible for > multiple claims in the future without breaking the API. >
I'm not sure about the idea of introducing a new hypercall for this operation. Though I may be missing some context about the reasons of introducing a new hypercall. XENMEM_claim_pages doesn't have actual support for NUMA, but the hypercall interface seems to define it (e.g you can pass XENMEMF_exact_node(n) to mem_flags). Would it be preferable instead to make XENMEM_claim_pages aware of NUMA-related XENMEMF flags ? > Signed-off-by: Bernhard Kaindl <[email protected]> > --- > xen/common/domain.c | 29 ++++++++++++++++++++++++++++ > xen/common/domctl.c | 9 +++++++++ > xen/include/public/domctl.h | 38 +++++++++++++++++++++++++++++++++++++ > xen/include/xen/domain.h | 2 ++ > 4 files changed, 78 insertions(+) > > diff --git a/xen/common/domain.c b/xen/common/domain.c > index e7861259a2b3..ac1b091f5574 100644 > --- a/xen/common/domain.c > +++ b/xen/common/domain.c > @@ -268,6 +268,35 @@ int get_domain_state(struct xen_domctl_get_domain_state > *info, struct domain *d, > return rc; > } > > +/* Claim memory for a domain or reset the claim */ > +int claim_memory(struct domain *d, const struct xen_domctl_claim_memory > *uinfo) > +{ > + memory_claim_t claim; > + > + /* alloc_color_heap_page() does not handle claims, so reject LLC > coloring */ > + if ( llc_coloring_enabled ) > + return -EOPNOTSUPP; > + /* > + * We only support single claims at the moment, and if the domain is > + * dying (d->is_dying is set), its claims have already been released > + */ > + if ( uinfo->pad || uinfo->nr_claims != 1 || d->is_dying ) > + return -EINVAL; > + > + if ( copy_from_guest(&claim, uinfo->claims, 1) ) > + return -EFAULT; > + > + if ( claim.pad ) > + return -EINVAL; > + > + /* Convert the API tag for a host-wide claim to the NUMA_NO_NODE > constant */ > + if ( claim.node == XEN_DOMCTL_CLAIM_MEMORY_NO_NODE ) > + claim.node = NUMA_NO_NODE; > + > + /* NB. domain_set_outstanding_pages() has the checks to validate its > args */ > + return domain_set_outstanding_pages(d, claim.pages, claim.node); > +} > + > static void __domain_finalise_shutdown(struct domain *d) > { > struct vcpu *v; > diff --git a/xen/common/domctl.c b/xen/common/domctl.c > index 29a7726d32d0..9e858f631aaf 100644 > --- a/xen/common/domctl.c > +++ b/xen/common/domctl.c > @@ -868,6 +868,15 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) > u_domctl) > ret = get_domain_state(&op->u.get_domain_state, d, &op->domain); > break; > > + case XEN_DOMCTL_claim_memory: > + /* Use the same XSM hook as XENMEM_claim_pages */ > + ret = xsm_claim_pages(XSM_PRIV, d); > + if ( ret ) > + break; > + > + ret = claim_memory(d, &op->u.claim_memory); > + break; > + > default: > ret = arch_do_domctl(op, d, u_domctl); > break; > diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h > index 8f6708c0a7cd..610806c8b6e0 100644 > --- a/xen/include/public/domctl.h > +++ b/xen/include/public/domctl.h > @@ -1276,6 +1276,42 @@ struct xen_domctl_get_domain_state { > uint64_t unique_id; /* Unique domain identifier. */ > }; > > +/* > + * XEN_DOMCTL_claim_memory > + * > + * Claim memory for a guest domain. The claimed memory is converted into > actual > + * memory pages by allocating it. Except for the option to pass claims for > + * multiple NUMA nodes, the semantics are based on host-wide claims as > + * provided by XENMEM_claim_pages, and are identical for host-wide claims. > + * > + * The initial implementation supports a claim for the host or a NUMA node, > but > + * using an array, the API is designed to be extensible to support more > claims. > + */ > +struct xen_memory_claim { > + uint64_aligned_t pages; /* Amount of pages to be allotted to the > domain */ > + uint32_t node; /* NUMA node, or XEN_DOMCTL_CLAIM_MEMORY_NO_NODE for > host */ > + uint32_t pad; /* padding for alignment, set to 0 on > input */ > +}; > +typedef struct xen_memory_claim memory_claim_t; > +#define XEN_DOMCTL_CLAIM_MEMORY_NO_NODE 0xFFFFFFFF /* No node: host > claim */ > + > +/* Use XEN_NODE_CLAIM_INIT to initialize a memory_claim_t structure */ > +#define XEN_NODE_CLAIM_INIT(_pages, _node) { \ > + .pages = (_pages), \ > + .node = (_node), \ > + .pad = 0 \ > +} > +DEFINE_XEN_GUEST_HANDLE(memory_claim_t); > + > +struct xen_domctl_claim_memory { > + /* IN: array of struct xen_memory_claim */ > + XEN_GUEST_HANDLE_64(memory_claim_t) claims; > + /* IN: number of claims in the claims array handle. See the claims > field. */ > + uint32_t nr_claims; > +#define XEN_DOMCTL_MAX_CLAIMS UINT8_MAX /* More claims require changes in > Xen */ > + uint32_t pad; /* padding for alignment, set it to > 0 */ > +}; > + > struct xen_domctl { > /* Stable domctl ops: interface_version is required to be 0. */ > uint32_t cmd; > @@ -1368,6 +1404,7 @@ struct xen_domctl { > #define XEN_DOMCTL_gsi_permission 88 > #define XEN_DOMCTL_set_llc_colors 89 > #define XEN_DOMCTL_get_domain_state 90 /* stable interface */ > +#define XEN_DOMCTL_claim_memory 91 > #define XEN_DOMCTL_gdbsx_guestmemio 1000 > #define XEN_DOMCTL_gdbsx_pausevcpu 1001 > #define XEN_DOMCTL_gdbsx_unpausevcpu 1002 > @@ -1436,6 +1473,7 @@ struct xen_domctl { > #endif > struct xen_domctl_set_llc_colors set_llc_colors; > struct xen_domctl_get_domain_state get_domain_state; > + struct xen_domctl_claim_memory claim_memory; > uint8_t pad[128]; > } u; > }; > diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h > index 93c0fd00c1d7..79e8932c4530 100644 > --- a/xen/include/xen/domain.h > +++ b/xen/include/xen/domain.h > @@ -193,4 +193,6 @@ extern bool vmtrace_available; > > extern bool vpmu_is_available; > > +int claim_memory(struct domain *d, const struct xen_domctl_claim_memory > *uinfo); > + > #endif /* __XEN_DOMAIN_H__ */ Teddy -- | Vates XCP-ng & Xen Orchestra - Vates solutions web: https://vates.tech
