From nobody Wed Sep 10 08:38:04 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=reject dis=none) header.from=cloud.com ARC-Seal: i=1; a=rsa-sha256; t=1757261838; cv=none; d=zohomail.com; s=zohoarc; b=Ujp7HDsYXFacjxtRgYHMdJ7JxPkgbwpmWa+9VPONYFwa60btckJCQUVmwlveAm5FFBSxqB9CZDj8VI9aXhQEOrV1Cg6QOhFhF0psHTV2IXCj2ecf7Hu8O39JfOFHk2tDob2jI6e1ss0CRW4g2iomv3HFsEuT8dSWbEJxUPhzgmw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1757261838; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=6FiQwP0VdUGmMFkU0uIYAV7JnXqoktiIQH9nuSROebE=; b=jCmbhcyV+K1qeUhSFwiDTa3K8OHf9Wgw2+AcBMobuq6+dy9qX3wy5BtlpGjIZg5Bi6KMcaSFrR8DePLRi+a3NyQ5AMKgprDpe48TGrKfvD2q4EGRi4dWOVsBbf15hQ6QehnV8Am5G/NnV3cEXk+lVZ74Kggj8zt49RE8qDSZsHg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1757261838168690.2274571967656; Sun, 7 Sep 2025 09:17:18 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1114166.1461323 (Exim 4.92) (envelope-from ) id 1uvI4i-0002H4-Fj; Sun, 07 Sep 2025 16:17:08 +0000 Received: by outflank-mailman (output) from mailman id 1114166.1461323; Sun, 07 Sep 2025 16:17:08 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1uvI4i-0002Gx-CA; Sun, 07 Sep 2025 16:17:08 +0000 Received: by outflank-mailman (input) for mailman id 1114166; Sun, 07 Sep 2025 16:17:07 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1uvI4g-0002Gl-UL for xen-devel@lists.xenproject.org; Sun, 07 Sep 2025 16:17:07 +0000 Received: from mail-ej1-x62c.google.com (mail-ej1-x62c.google.com [2a00:1450:4864:20::62c]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 17f8bfc5-8c06-11f0-9809-7dc792cee155; Sun, 07 Sep 2025 18:17:05 +0200 (CEST) Received: by mail-ej1-x62c.google.com with SMTP id a640c23a62f3a-afcb7ae31caso616594566b.3 for ; Sun, 07 Sep 2025 09:17:05 -0700 (PDT) Received: from MinisforumBD795m.phoenix-carat.ts.net ([2a02:1748:f7df:8cb1:5474:d7c3:6edd:e683]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b047b61cf00sm908263766b.15.2025.09.07.09.16.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 07 Sep 2025 09:17:03 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 17f8bfc5-8c06-11f0-9809-7dc792cee155 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloud.com; s=cloud; t=1757261824; x=1757866624; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=6FiQwP0VdUGmMFkU0uIYAV7JnXqoktiIQH9nuSROebE=; b=NMW6bFbACu43o7wvBgzu33iydiwRwevxL/DzodDQONkl39IhPYtKpC6KbfiDq2r+1J 6gpiveF/YsP90HxaV2kTAnqdm9UxLGOBCrw66FgkKbhXPd1Htt5Qb8u2E2vuZnpRngBq 5sALD2zbaGX8qfd/ZiZeiH4WRA5u1T9hU/d+k= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1757261824; x=1757866624; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=6FiQwP0VdUGmMFkU0uIYAV7JnXqoktiIQH9nuSROebE=; b=FvRYSUKHmRlRJiVuHCsKNUS2IBQZ5/fv+XyIo+yoNxk8uszgGJ5kSuD6hjPqCk3W2J mw5M6afPNx5IC/qg1dGeg65r2urHOm11u5Mw/SW9+XbjXm5mFNPpAT4/9meYvS0AhWuw eXGz4PbtsrWUjwkKaZEQsUUAkMK7wbCE4pM/9hsbIvTAnA6tuBPe2me6TYiH+w2Hi+3o 6zpdIVfcROjYbqQ+XYRlRv+IGNkQGYiQfKayfXdWXZXX8+OpGMQMkPoMrb0AyVmwj2gD eGABnwjIP/B6Yq2VfbxAJwCmxX8Ce92MD++xkS/lsy9h6C5zFi8UkcvQ9TH9tSCbZsaZ vCvA== X-Gm-Message-State: AOJu0YyPnr+BUy2rf7jJeebbmfOz9EgbCMldQRR3anuZbKPmAj+0bH6P Vhmwh+TsY6hsvXD6nXs1dO3D1INeV1x9wx8Zntoa2JgGv4Wt4biOGN2GIcW9jSsP+Kf2hk6keSO xlcsCmwE= X-Gm-Gg: ASbGncv4HhjyGMrIYccHjLVTgfpFluru0d1UXWBrmUIoRpAoAiZz4hKR+QgJz/JPx7+ SXV+U7j1n8ayZA9PPqknyTCl6dyvT1oekukq3oqxVJNiQe1e+wpDBr3rwCFN/Sg35uHXZFrFJj7 71mRHDRCXcZJtRdYZInJbIOTaaxvSXfRXAXbRx5t6TJ85Dkc3ZhPAuQKx8g0esqTAYgj+tMt4Pk vkO4vsqJn5SOb7wytfMuM2Lu+nz2dJBWcGFrYdAGfS65N7jLP/lPO4gd2fzOnHs41oV1TwRuSX2 nAjjBqkvVbtYzmmHzM6ZTjkNpa0x8J5EkNs6vsOv95s8uXfUPES6YNiMRnhzT4dgKEEk2pamMVU hebjqBNLdczpz0oakyeQVPdgg8Mfl4zfAhqDlnjAX0h8ysrzV/PUo//USCM9PQPJSQnQ= X-Google-Smtp-Source: AGHT+IHQ41CzQUwsGmIiJ1de/f1zmmWKWPxtBh6Y9WUIDTwFCa8uQ+VvzK+oXvx3Q1NVWFYCh8wBSw== X-Received: by 2002:a17:907:6d0d:b0:b04:ae7c:703e with SMTP id a640c23a62f3a-b04b140a770mr473628766b.24.1757261823683; Sun, 07 Sep 2025 09:17:03 -0700 (PDT) From: Bernhard Kaindl To: xen-devel@lists.xenproject.org Cc: Alejandro Vallejo , Bernhard Kaindl , "Daniel P. Smith" , Anthony PERARD , Andrew Cooper , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini , Juergen Gross , Christian Lindig , David Scott Subject: [PATCH v3 7/7] xen: New hypercall to claim memory using XEN_DOMCTL_claim_memory Date: Sun, 7 Sep 2025 18:15:22 +0200 Message-ID: X-Mailer: git-send-email 2.43.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @cloud.com) X-ZM-MESSAGEID: 1757261840996124100 Content-Type: text/plain; charset="utf-8" Add the new hypercall requested during the review of the v1 series do not require changing the API for multi-node claims. The hypercall receives a number of claims, intented to be one claim per NUMA node, and limited to one claim for now. The changes to update the NUMA claims management to handle updating the claims for multiple NUMA nodes of a domain at once are deferred to the next series. Cc: Alejandro Vallejo Signed-off-by: Bernhard Kaindl --- Changes in v3: - As a review to check nr_claims to be > 0 (but uint =3D superflous), but to avoid a raised eyebrow, add "> 0", which the compiler will optimise away anyway. --- tools/flask/policy/modules/dom0.te | 1 + tools/flask/policy/modules/xen.if | 1 + tools/include/xenctrl.h | 4 +++ tools/libs/ctrl/xc_domain.c | 42 +++++++++++++++++++++++++++++ tools/ocaml/libs/xc/xenctrl.ml | 9 +++++++ tools/ocaml/libs/xc/xenctrl.mli | 9 +++++++ tools/ocaml/libs/xc/xenctrl_stubs.c | 21 +++++++++++++++ xen/common/domain.c | 29 ++++++++++++++++++++ xen/common/domctl.c | 8 ++++++ xen/include/public/domctl.h | 17 ++++++++++++ xen/include/xen/domain.h | 2 ++ xen/xsm/flask/hooks.c | 3 +++ xen/xsm/flask/policy/access_vectors | 2 ++ 13 files changed, 148 insertions(+) diff --git a/tools/flask/policy/modules/dom0.te b/tools/flask/policy/module= s/dom0.te index ad2b4f9ea7..8801cb24f2 100644 --- a/tools/flask/policy/modules/dom0.te +++ b/tools/flask/policy/modules/dom0.te @@ -105,6 +105,7 @@ allow dom0_t dom0_t:domain2 { get_cpu_policy dt_overlay get_domain_state + claim_memory }; allow dom0_t dom0_t:resource { add diff --git a/tools/flask/policy/modules/xen.if b/tools/flask/policy/modules= /xen.if index ef7d8f438c..8e2dceb505 100644 --- a/tools/flask/policy/modules/xen.if +++ b/tools/flask/policy/modules/xen.if @@ -98,6 +98,7 @@ define(`create_domain_common', ` vuart_op set_llc_colors get_domain_state + claim_memory }; allow $1 $2:security check_context; allow $1 $2:shadow enable; diff --git a/tools/include/xenctrl.h b/tools/include/xenctrl.h index 965d3b585a..43ece3f2a7 100644 --- a/tools/include/xenctrl.h +++ b/tools/include/xenctrl.h @@ -2660,6 +2660,10 @@ int xc_domain_set_llc_colors(xc_interface *xch, uint= 32_t domid, const uint32_t *llc_colors, uint32_t num_llc_colors); =20 +int xc_domain_claim_memory(xc_interface *xch, uint32_t domid, + uint32_t nr_claims, + const memory_claim_t *claims); + #if defined(__arm__) || defined(__aarch64__) int xc_dt_overlay(xc_interface *xch, void *overlay_fdt, uint32_t overlay_fdt_size, uint8_t overlay_op); diff --git a/tools/libs/ctrl/xc_domain.c b/tools/libs/ctrl/xc_domain.c index 2ddc3f4f42..e022b76430 100644 --- a/tools/libs/ctrl/xc_domain.c +++ b/tools/libs/ctrl/xc_domain.c @@ -2229,6 +2229,48 @@ out: =20 return ret; } + +/* + * Claim memory for a domain. A Domain can only have one type of claim: + * + * If the number of claims is 0, existing claims are cancelled. + * Updating claims is not supported, cancel the existing claim first. + * + * Memory allocations consume the outstanding claim and if not enough memo= ry is + * free, the allocation must be satisfied from the remaining outstanding c= laim. + */ +int xc_domain_claim_memory(xc_interface *xch, uint32_t domid, + uint32_t nr_claims, + const memory_claim_t *claims) +{ + struct xen_domctl domctl =3D { + .cmd =3D XEN_DOMCTL_claim_memory, + .domain =3D domid, + .u.claim_memory.nr_claims =3D nr_claims, + }; + int ret; + DECLARE_HYPERCALL_BUFFER(struct xen_domctl_claim_memory, buffer); + + /* Use an array to not need changes for multi-node claims in the futur= e */ + if ( nr_claims > 0 ) + { + size_t bytes =3D sizeof(memory_claim_t) * nr_claims; + + buffer =3D xc_hypercall_buffer_alloc(xch, buffer, bytes); + if ( buffer =3D=3D NULL ) + { + PERROR("Could not allocate memory for xc_domain_claim_memory"); + return -1; + } + memcpy(buffer, claims, bytes); + set_xen_guest_handle(domctl.u.claim_memory.claims, buffer); + } + + ret =3D do_domctl(xch, &domctl); + xc_hypercall_buffer_free(xch, buffer); + return ret; +} + /* * Local variables: * mode: C diff --git a/tools/ocaml/libs/xc/xenctrl.ml b/tools/ocaml/libs/xc/xenctrl.ml index 97108b9d86..c8692fb169 100644 --- a/tools/ocaml/libs/xc/xenctrl.ml +++ b/tools/ocaml/libs/xc/xenctrl.ml @@ -370,6 +370,15 @@ external domain_deassign_device: handle -> domid -> (i= nt * int * int * int) -> u external domain_test_assign_device: handle -> domid -> (int * int * int * = int) -> bool =3D "stub_xc_domain_test_assign_device" =20 +type claim =3D + { + node: int; + nr_pages: int64; + } + +external domain_claim_memory: handle -> domid -> int -> claim array -> unit + =3D "stub_xc_domain_claim_memory" + external version: handle -> version =3D "stub_xc_version_version" external version_compile_info: handle -> compile_info =3D "stub_xc_version_compile_info" diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.= mli index 9fccb2c2c2..82d59fc80d 100644 --- a/tools/ocaml/libs/xc/xenctrl.mli +++ b/tools/ocaml/libs/xc/xenctrl.mli @@ -297,6 +297,15 @@ external domain_deassign_device: handle -> domid -> (i= nt * int * int * int) -> u external domain_test_assign_device: handle -> domid -> (int * int * int * = int) -> bool =3D "stub_xc_domain_test_assign_device" =20 +type claim =3D + { + node: int; + nr_pages: int64; + } + +external domain_claim_memory: handle -> domid -> int -> claim array -> unit + =3D "stub_xc_domain_claim_memory" + external version : handle -> version =3D "stub_xc_version_version" external version_compile_info : handle -> compile_info =3D "stub_xc_version_compile_info" diff --git a/tools/ocaml/libs/xc/xenctrl_stubs.c b/tools/ocaml/libs/xc/xenc= trl_stubs.c index ac2a7537d6..53f56c5437 100644 --- a/tools/ocaml/libs/xc/xenctrl_stubs.c +++ b/tools/ocaml/libs/xc/xenctrl_stubs.c @@ -1435,6 +1435,27 @@ CAMLprim value stub_xc_watchdog(value xch_val, value= domid, value timeout) CAMLreturn(Val_int(ret)); } =20 +/* Claim memory for a domain. See xc_domain_claim_memory() for details. */ +CAMLprim value stub_xc_domain_claim_memory(value xch_val, value domid, + value num_claims, value desc) +{ + CAMLparam4(xch_val, domid, num_claims, desc); + xc_interface *xch =3D xch_of_val(xch_val); + int i, retval, nr_claims =3D Int_val(num_claims); + memory_claim_t claim[nr_claims]; + + for (i =3D 0; i < nr_claims; i++) { + claim[i].node =3D Int_val(Field(desc, i*2)); + claim[i].nr_pages =3D Int64_val(Field(desc, i*2 + 1)); + } + + retval =3D xc_domain_claim_memory(xch, Int_val(domid), nr_claims, claim); + if (retval < 0) + failwith_xc(xch); + + CAMLreturn(Val_unit); +} + /* * Local variables: * indent-tabs-mode: t diff --git a/xen/common/domain.c b/xen/common/domain.c index 6ee9f23b10..39f1c3718c 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -267,6 +267,35 @@ int get_domain_state(struct xen_domctl_get_domain_stat= e *info, struct domain *d, return rc; } =20 +/* XEN_DOMCTL_claim_memory: Claim an amount of memory for a domain */ +int claim_memory(struct domain *d, const struct xen_domctl_claim_memory *u= info) +{ + memory_claim_t claim; + int rc; + + switch ( uinfo->nr_claims ) + { + case 0: + /* Cancel existing claim. */ + rc =3D domain_claim_pages(d, 0, 0); + break; + + case 1: + /* Only single node claims supported at the moment. */ + if ( copy_from_guest(&claim, uinfo->claims, 1) ) + return -EFAULT; + + rc =3D domain_claim_pages(d, claim.node, claim.nr_pages); + break; + + default: + rc =3D -EOPNOTSUPP; + break; + } + + return rc; +} + static void __domain_finalise_shutdown(struct domain *d) { struct vcpu *v; diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 71e712c1f3..cf9537b02c 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -863,6 +863,14 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_= domctl) ret =3D get_domain_state(&op->u.get_domain_state, d, &op->domain); break; =20 + case XEN_DOMCTL_claim_memory: + ret =3D xsm_claim_pages(XSM_PRIV, d); + if ( ret ) + break; + + ret =3D claim_memory(d, &op->u.claim_memory); + break; + default: ret =3D arch_do_domctl(op, d, u_domctl); break; diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 8f6708c0a7..1cebbb878e 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -1276,6 +1276,21 @@ struct xen_domctl_get_domain_state { uint64_t unique_id; /* Unique domain identifier. */ }; =20 +struct xen_memory_claim { + unsigned int node; /* NUMA node, XC_NUMA_NO_NODE for a host claim= */ + unsigned long nr_pages; /* Number of pages to claim */ +}; +typedef struct xen_memory_claim memory_claim_t; +DEFINE_XEN_GUEST_HANDLE(memory_claim_t); + +/* XEN_DOMCTL_claim_memory: Claim an amount of memory for a domain */ +struct xen_domctl_claim_memory { + /* IN: array of memory claims */ + XEN_GUEST_HANDLE_64(memory_claim_t) claims; + /* IN: number of claims */ + unsigned int nr_claims; +}; + struct xen_domctl { /* Stable domctl ops: interface_version is required to be 0. */ uint32_t cmd; @@ -1368,6 +1383,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 +1452,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 8aab05ae93..cd3e933fbf 100644 --- a/xen/include/xen/domain.h +++ b/xen/include/xen/domain.h @@ -195,4 +195,6 @@ extern bool vmtrace_available; =20 extern bool vpmu_is_available; =20 +int claim_memory(struct domain *d, const struct xen_domctl_claim_memory *u= info); + #endif /* __XEN_DOMAIN_H__ */ diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index b0308e1b26..6b2535b666 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -853,6 +853,9 @@ static int cf_check flask_domctl(struct domain *d, unsi= gned int cmd, case XEN_DOMCTL_set_llc_colors: return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__SET_LLC_COLO= RS); =20 + case XEN_DOMCTL_claim_memory: + return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__CLAIM_MEMORY= ); + default: return avc_unknown_permission("domctl", cmd); } diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/acc= ess_vectors index 51a1577a66..87338b5c2a 100644 --- a/xen/xsm/flask/policy/access_vectors +++ b/xen/xsm/flask/policy/access_vectors @@ -259,6 +259,8 @@ class domain2 set_llc_colors # XEN_DOMCTL_get_domain_state get_domain_state +# XEN_DOMCTL_claim_memory + claim_memory } =20 # Similar to class domain, but primarily contains domctls related to HVM d= omains --=20 2.43.0