claim_memory

XEN_DOMCTL_claim_memory

Hypercall command for installing claim sets for a domain.

This command allows domain builders to install a claim set for a domain, which the Xen hypervisor tracks and enforces during memory allocation.

The claimed memory is protected from other allocations and the domain’s memory requirements can be met even when other parallel domain builders are also allocating memory for other domains in parallel.

Claim set installation describes how the hypervisor processes the claim sets installed via this hypercall command.

Hypercall API

See Claim sets for more details on the claim sets data structure.

Definitions

Mode

XEN_DOMCTL_CLAIM_MEMORY_SET

Install the given claim set for the domain.

XEN_DOMCTL_CLAIM_MEMORY_GET

Retrieve the claim set for the current claims of the domain.

Target selectors

XEN_DOMCTL_CLAIM_MEMORY_HOST

Special target selector for host-wide claims, which can be satisfied from any NUMA node.

XEN_DOMCTL_CLAIM_MEMORY_LEGACY

Special target selector for legacy claims, which is interpreted as the total memory target for the domain, with existing allocations subtracted from it to determine the domain’s new total host-wide outstanding claim. It is provided for compatibility with existing domain builders and can only be used in a single-entry claim set.

domctl.h structure

struct xen_memory_claim {
    uint64_aligned_t pages; /* Number of pages to claim */
    uint32_t target; /* NUMA node or claim type like legacy or host-wide */
    uint32_t cmd;    /* Command reserved for future use, initialize to 0 */
};
typedef struct xen_memory_claim memory_claim_t;
DEFINE_XEN_GUEST_HANDLE(memory_claim_t);

/* Special claim targets for the target field of memory_claim_t */
#define XEN_DOMCTL_CLAIM_MEMORY_HOST     0x80000000U /* Host-wide claims */
#define XEN_DOMCTL_CLAIM_MEMORY_LEGACY   0x40000000U /* Legacy semantics */

/*
 * XEN_DOMCTL_claim_memory
 *
 * Install a claim set to claim memory for a guest domain. Claims work like
 * tickets in exchange for allocating memory for a domain later.
 */
struct xen_domctl_claim_memory {
    /* IN/OUT: Array of struct xen_memory_claim */
    XEN_GUEST_HANDLE_64(memory_claim_t) claim_set;
    /* IN/OUT: Number of records in the claim_set array handle. */
    uint32_t nr_entries;
    uint32_t mode;
#define XEN_DOMCTL_CLAIM_MEMORY_GET 0U /* Get a claim set for the domain. */
#define XEN_DOMCTL_CLAIM_MEMORY_SET 1U /* Set a claim set for the domain. */
};

C API by libxenctrl

int xc_domain_claim_memory(xch, domid, mode, nr_entries, claim_set)
Parameters:
  • xch (xc_interface*) – The libxenctrl interface to use for the hypercall

  • domid (uint32_t) – The ID of the domain for which to install the claim set

  • mode (uint32_t) – The mode for the claim set installation

  • nr_entries (uint32_t*) – The number of entries in the claim set

  • claim_set (memory_claim_t*) – The claim set to install for the domain

Returns:

0 on success, or a negative error code on failure.

C API function for installing or retrieving claim sets for a domain using the XEN_DOMCTL_claim_memory hypercall command.

This function allows domain builders to install a claim set for a domain, which the Xen hypervisor tracks and enforces during memory allocation and can also be used to retrieve the current claim set for a domain.

When mode is XEN_DOMCTL_CLAIM_MEMORY_SET, the former mode is used, where the function validates and installs the given claim set. nr_entries specifies the number of entries in the claim_set array, and claim_set points to the array of memory_claim_t entries.

When mode is XEN_DOMCTL_CLAIM_MEMORY_GET, the function retrieves the current claim set into the memory pointed to by claim_set. The number of claims retrieved is stored in the variable pointed to by nr_entries.

This function is part of the libxenctrl library.

Corresponding OCaml bindings are also available for this function in the Xenctrl OCaml library, providing a convenient interface for OCaml domain builders to install claim sets for a domain.

C API Usage example

The example below shows how a domain builder can install a claim set and later replace or clear it. memory_claim_t contains an additional field for future expansion; zero-initialise the structure or use designated initializers to ensure forward compatibility.

#include <xenctrl.h>

void install_example_claims(xc_interface *xch, uint32_t domid)
{
  /*
   * Claim 1024 pages on node 0, 1024 pages on node 1, and by setting
   * the total claim target to 3072 pages, an additional host-wide claim of
   * 1024 pages which is never bound to any specific node is also installed.
   */
  memory_claim_t claims[] = {
    {.pages = 1024, .target = 0},
    {.pages = 1024, .target = 1},
    {.pages = 1024, .target = XEN_DOMCTL_CLAIM_MEMORY_HOST},
  };
  xc_domain_claim_memory(xch, domid, ARRAY_SIZE(claims), claims);

  /* Replace the claim set with claims on nodes 1, 2, and 3 */
  memory_claim_t claims2[] = {
    {.pages = 1024, .target = 1},
    {.pages = 1024, .target = 2},
    {.pages = 1024, .target = 3},
  };
  xc_domain_claim_memory(xch, domid, ARRAY_SIZE(claims2), claims2);

  /* Release all remaining claims once the domain is built */
  memory_claim_t clear[] = {
    {.pages = 0, .target = XEN_DOMCTL_CLAIM_MEMORY_HOST}
  };
  xc_domain_claim_memory(xch, domid, ARRAY_SIZE(clear), clear);
}

Using the Xenctrl OCaml bindings

The OCaml bindings for libxenctrl also provide an interface for installing claim sets using the XEN_DOMCTL_claim_memory hypercall command.

The example below shows how to install a claim set and later release it using the OCaml bindings.

let install_example_claims xch domid =
  let claims = [|
    { Xenctrl.pages = 1024L; node = 0l };
    { Xenctrl.pages = 1024L; node = 1l };
    { Xenctrl.pages = 3072L; node = XEN_DOMCTL_CLAIM_MEMORY_TOTAL };
  |] in
  Xenctrl.domain_claim_memory xch domid claims;

let release_all_claims xch domid =
  let clear = [|
    { Xenctrl.pages = 0L; node = XEN_DOMCTL_CLAIM_MEMORY_TOTAL };
  |] in
  Xenctrl.domain_claim_memory xch domid clear

Call sequence diagram

The following sequence diagram illustrates the call flow for claiming memory for a domain using this hypercall command from an OCaml domain builder:

        %% SPDX-License-Identifier: CC-BY-4.0
sequenceDiagram

actor DomainBuilder
participant OcamlStub as OCaml stub for<br>xc_domain<br>claim_memory
participant Libxc as xc_domain<br>claim_memory
participant Domctl as XEN_DOMCTL<br>claim_memory
#participant DomainLogic as claim_memory
participant Alloc as domain<br>set<br>outstanding_pages

DomainBuilder->>OcamlStub: claims
OcamlStub->>OcamlStub: marshall claims -----> OCaml to C
OcamlStub->>Libxc: claims

Libxc->>Domctl: do_domctl

Domctl->>Domctl: copy_from_guest(claim)
Domctl->>Domctl: validate claim
Domctl->>Alloc: set<br>outstanding_pages
Alloc-->>Domctl: result
Domctl-->>Libxc: rc
Libxc-->>OcamlStub: rc
OcamlStub-->>DomainBuilder: claim_result

    

Sequence diagram: Call flow for claiming memory for a domain

Claim workflow

This diagram illustrates a workflow for claiming and populating memory:

        %% SPDX-License-Identifier: CC-BY-4.0
sequenceDiagram

participant Toolstack
participant Xen
participant NUMA Node memory

Toolstack->>Xen: XEN_DOMCTL_createdomain
Toolstack->>Xen: XEN_DOMCTL_max_mem(max_pages)

Toolstack->>Xen: XEN_DOMCTL_claim_memory(pages, node)
Xen->>NUMA Node memory: Claim pages on node
Xen-->>Toolstack: Claim granted

Toolstack->>Xen: XEN_DOMCTL_set_nodeaffinity(node)

loop Populate domain memory
    Toolstack->>Xen: XENMEM_populate_physmap(memflags:node)
    Xen->>NUMA Node memory: alloc from claimed node
end

Toolstack->>Xen: XEN_DOMCTL_claim_memory(0, NO_NODE)
Xen-->>Toolstack: Remaining claims released

    

Workflow diagram: Claiming and populating memory for a domain

Used functions & data structures

This diagram illustrates the key functions and data structures involved in installing claims via the XEN_DOMCTL_claim_memory hypercall command:

        %% SPDX-License-Identifier: CC-BY-4.0
classDiagram
class do_domctl["Args passed to <tt>do_domctl()</tt>"] {
    +uint32_t cmd: XEN_DOMCTL_claim_memory
    +uint32_t domain: Domain ID
    +xen_domctl_claim_memory: Claim set
}
class xen_domctl_claim_memory["Claim set passed to <tt>do_domctl()</tt>"] {
    +memory_claim_t* claims: Claim entries
    +uint32_t nr_claims: Number of claim entries
    +uint32_t pad: always 0 for future use
}
class memory_claim_t["Claim set: Array of claim entries"] {
    +pages: Pages to claim
    +node: Claim selector or node
    +pad: always 0 for future use
}
class xc_domain_claim_memory["xc_domain_claim_memory()"] {
    +xc_interface* xch
    +uint32_t domid
    +uint32_t nr_claims
    +memory_claim_t* claims
}
class outstanding_pages["Total claims of domains"] {
    global free = total_avail_pages - outstanding_claims
    node free = node_avail_pages[node] - node_outstanding_claims[node]
}
class claim["XEN_DOMCTL_claim_memory"] {
    +domain_set_outstanding_pages()
    +domain_set_node_claims()
}
class domain["Claim fields in struct domain"] {
    +outstanding_pages - Total outstanding claims of the domain
    +node_claims - Sum of claims on all nodes of the domain
    +claims[] - Array of claims on specific nodes
}
xen_domctl_claim_memory o--> memory_claim_t
do_domctl o--> xen_domctl_claim_memory
xc_domain_claim_memory ..> do_domctl: passes<br> <tt>Claim set</tt>
xc_domain_claim_memory ..> claim : calls <tt>do_domctl()</tt>
claim ..> xen_domctl_claim_memory : reads
claim ..> domain : sets
domain ..> outstanding_pages : updates outstanding claims

    

Diagram: Function and data relationships for installing claims