From nobody Fri Oct 31 09:32:49 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=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1751399706; cv=none; d=zohomail.com; s=zohoarc; b=nqINJTdoIQzk60NeLaU9BM6EZujq2d7Hpd4l+V7DR/uG0Rd4UwS1GW4y6xFIyLO2P0GVqMh+ALex+Luv5qNyIZxUpAtEGXIdeHP3bK8eRlErDnHLKGm/K8NwYtucK1B9/Vekejyxf3K4+uk9IWEBAA94ZF8klDA4nWSXbUyhVE4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751399706; h=Content-Type: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=L2cnHrrzD+wqGofUm4sfDRu9d8822/NadKBk0KDrtvY=; b=fUFZ/fhSJZMvto1MTB+LaLh83s+vQjIEKbUgVRh+YBPt8EBLBj6vaTtwmNHdTGM65x2S77/318jROWF9Xu7S/chGt5JTv1h9uQgqDXOh2+eu8muWoPph+aw+BND2xxuycHQUqpxmPKkyj7OdrDQgZTDiJjuYlwKsr5tlML6+Tjs= 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=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1751399706297699.0252138595059; Tue, 1 Jul 2025 12:55:06 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1029946.1403682 (Exim 4.92) (envelope-from ) id 1uWh41-0000xJ-RF; Tue, 01 Jul 2025 19:54:45 +0000 Received: by outflank-mailman (output) from mailman id 1029946.1403682; Tue, 01 Jul 2025 19:54:45 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1uWh41-0000wu-NF; Tue, 01 Jul 2025 19:54:45 +0000 Received: by outflank-mailman (input) for mailman id 1029946; Tue, 01 Jul 2025 19:54:44 +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 1uWh40-0000D0-6e for xen-devel@lists.xenproject.org; Tue, 01 Jul 2025 19:54:44 +0000 Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [2a00:1450:4864:20::435]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 3aacf556-56b5-11f0-b894-0df219b8e170; Tue, 01 Jul 2025 21:54:42 +0200 (CEST) Received: by mail-wr1-x435.google.com with SMTP id ffacd0b85a97d-3a4eb4dfd8eso925777f8f.2 for ; Tue, 01 Jul 2025 12:54:42 -0700 (PDT) Received: from lab.home (dynamic-2a00-1028-83a4-4bca-c0bb-96ff-feed-9d50.ipv6.o2.cz. [2a00:1028:83a4:4bca:c0bb:96ff:feed:9d50]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3a88c7e9d1csm14291644f8f.13.2025.07.01.12.54.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 12:54:40 -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: 3aacf556-56b5-11f0-b894-0df219b8e170 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1751399681; x=1752004481; 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=L2cnHrrzD+wqGofUm4sfDRu9d8822/NadKBk0KDrtvY=; b=dqZGPmOxak7f6Og69vf7vb92JBg+9ql6bOA8i21uaT0Lv8xGVgQWlBHjsdHByXR6oR LFP1S026adRybEUENGG7U1hcRZw8+2EGfWRAs9NX3dGYw0fGPEJEaPgXxeZkkaCV/iHR k7G4zWZzyq9n/gWSMN+aRJC/OrzT0xRqLGN04vSXuOH1UeSTrm60BhwYl4ilpNyYedTG wV3P6nwsYo65WEYSZccMUl3oBkQE8z7YYzqwy+K+iMYR8fcSC/piZDQZpXlupvZViqYX zsh/4VX5WAmJjZyCDJ2nhnCL70uUzXE+OXgnZ//qS9JhErwH43fI6wZtskWqUgmRc+KT Isxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751399681; x=1752004481; 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=L2cnHrrzD+wqGofUm4sfDRu9d8822/NadKBk0KDrtvY=; b=AS9WikTq1w+unzDwkpoM4QhEhd/zY9LsXBTsqwHJ+acWb4xCXNUAPZ3HCPB0SN6+a7 INcl0DdGVVm9rUAsUqYwODmfQCt2jK3TJyWCqNMoBgD6ccPRe9joRb1p61ZZrPJyuHqr 2NmUxiLVUfhjoOwbqRvtbqUh17nvmhszGnQSl9HNvYe7P5bKMSFsHXPR3984O6X3OeLK 5HIgL4dJhr3Lx21pXu3mhopXDpFF5Pr7+maXOa0gOhdxtmGm+L7dO3xWFJuY0j8qjmMM iPdUbAwvquO/KzTMy8THBg/L6y4BLWxKVYyuUq2llJfcwggApUbBJkYtpguuQdcj/cqU iaJw== X-Gm-Message-State: AOJu0YyX/Fftf60IBpInNupKsAFG4yhmceB+IIZuKNUk6LNkN5fYGHZX 3foOm9Ckt6DX4fZmR+hvW13s0/YlLJlZvcvDkh4MZj96L/JjpJq3ADU213jq2g== X-Gm-Gg: ASbGncvJFGC5vx1GmmcVHcQ9n5gbWhK558UqaHURqRMJRbXdRHAHSPtFvSHo99Mys6C XYkoSoKf3bQl9g0fLfE2e0bz+csxkMekxR4LKBa2RKcCjtufddnwqgU1XbjtlbS//sWa0UfT8Kt l14OcK5jjCJE29fulOddIE1P7o9UZE/ICxkqLG0uKkTUXAOxyC0MWVxyD2JzbcedFCkW33uGs7j +n95ISirSTHVdlm7EPYaPWy/z+ylOiP5ozwZFO1N7UdYKMhQItmYUslLNXOHXVXWyQHNHuEjamN S+uAKr4UvasmKKjYH/s7u6Q/eFI0V9CmL4+C3nKoX8KB67Di5bmPLXUMiAzGVDzbH+tMsXZV4EC 1OneCWtrJokLK2hr/sNJf2vgjn4J0SJaDe+rP0+Y1+PRF8f3QQ7Yt2ySfHxKeZQ== X-Google-Smtp-Source: AGHT+IFcBIX+sX5UmOzW9aZyGvPE+iEHcIpKkjaUil7iRuHC2/Cy2eTaQa6mOa7WbuwaXiJWi4Faew== X-Received: by 2002:a05:6000:3103:b0:3a4:f8a9:a03e with SMTP id ffacd0b85a97d-3af23ad0767mr1323866f8f.3.1751399680871; Tue, 01 Jul 2025 12:54:40 -0700 (PDT) From: "=?UTF-8?q?Petr=20Bene=C5=A1?=" X-Google-Original-From: =?UTF-8?q?Petr=20Bene=C5=A1?= To: xen-devel@lists.xenproject.org Cc: =?UTF-8?q?Petr=20Bene=C5=A1?= , Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk , Andrew Cooper , Anthony PERARD , Jan Beulich , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Tamas K Lengyel , Alexandru Isaila , Petre Pircalabu Subject: [PATCH v7 4/7] xen: Make the maximum number of altp2m views configurable for x86 Date: Tue, 1 Jul 2025 19:54:26 +0000 Message-Id: X-Mailer: git-send-email 2.34.1 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1751399709113116600 From: Petr Bene=C5=A1 This commit introduces the ability to configure the maximum number of altp2m views for the domain during its creation. Previously, the limits were hardc= oded to a maximum of 10. This change allows for greater flexibility in environme= nts that require more or fewer altp2m views. The maximum configurable limit for nr_altp2m on x86 is now set to MAX_NR_ALTP2M (which currently holds the MAX_EPTP value - 512). This cap is linked to the architectural limit of the EPTP-switching VMFUNC, which suppo= rts up to 512 entries. Despite there being no inherent need for limiting nr_alt= p2m in scenarios not utilizing VMFUNC, decoupling these components would necess= itate substantial code changes. xen_domctl_createdomain::altp2m is extended for a new field `nr`, that will configure this limit for a domain. Additionally, previous altp2m.opts value has been reduced from uint32_t to uint16_t so that both of these fields occ= upy as little space as possible. Accesses to the altp2m_p2m array are modified to respect the new nr_altp2m value. Accesses to the altp2m_(visible_)eptp arrays are unmodified, since these arrays always have fixed size of MAX_EPTP. A dummy hvm_altp2m_supported() function is introduced for non-HVM builds, so that the compilation won't fail for them. Additional sanitization is introduced in the x86/arch_sanitise_domain_config to fix the altp2m.nr value to 10 if it is previously set to 0. This behavior is only temporary and immediately removed in the upcoming commit (which will disallow creating a domain with enabled altp2m with zero nr_altp2m). The reason for this temporary workaround is to retain the legacy behavior until the feature is fully activated in libxl. Also, arm/arch_sanitise_domain_config is extended to not allow requesting non-zero altp2ms. Signed-off-by: Petr Bene=C5=A1 --- xen/arch/arm/domain.c | 2 +- xen/arch/x86/domain.c | 40 ++++++++++++++--- xen/arch/x86/hvm/hvm.c | 8 +++- xen/arch/x86/hvm/vmx/vmx.c | 2 +- xen/arch/x86/include/asm/altp2m.h | 28 ++++++++++-- xen/arch/x86/include/asm/domain.h | 9 ++-- xen/arch/x86/include/asm/p2m.h | 4 +- xen/arch/x86/mm/altp2m.c | 74 +++++++++++++++++-------------- xen/arch/x86/mm/hap/hap.c | 6 +-- xen/arch/x86/mm/mem_access.c | 20 +++------ xen/arch/x86/mm/mem_sharing.c | 2 +- xen/arch/x86/mm/p2m-ept.c | 7 +-- xen/arch/x86/mm/p2m.c | 8 ++-- xen/common/domain.c | 1 + xen/include/public/domctl.h | 5 ++- xen/include/xen/sched.h | 2 + 16 files changed, 140 insertions(+), 78 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 79a144e61b..9a4f72c62b 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -693,7 +693,7 @@ int arch_sanitise_domain_config(struct xen_domctl_creat= edomain *config) return -EINVAL; } =20 - if ( config->altp2m.opts ) + if ( config->altp2m.opts || config->altp2m.nr ) { dprintk(XENLOG_INFO, "Altp2m not supported\n"); return -EINVAL; diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 56c3816187..155ea1f79f 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -716,16 +716,42 @@ int arch_sanitise_domain_config(struct xen_domctl_cre= atedomain *config) return -EINVAL; } =20 - if ( altp2m_mode && nested_virt ) + if ( altp2m_mode ) { - dprintk(XENLOG_INFO, - "Nested virt and altp2m are not supported together\n"); - return -EINVAL; - } + if ( !hvm_altp2m_supported() ) + { + dprintk(XENLOG_INFO, "altp2m is not supported\n"); + return -EINVAL; + } + + if ( !hap ) + { + dprintk(XENLOG_INFO, "altp2m is only supported with HAP\n"); + return -EINVAL; + } + + if ( nested_virt ) + { + dprintk(XENLOG_INFO, + "Nested virt and altp2m are not supported together\n"); + return -EINVAL; + } + + if ( !config->altp2m.nr ) + { + /* Fix the value to the legacy default */ + config->altp2m.nr =3D 10; + } =20 - if ( altp2m_mode && !hap ) + if ( config->altp2m.nr > MAX_NR_ALTP2M ) + { + dprintk(XENLOG_INFO, "altp2m.nr must be <=3D %lu\n", MAX_NR_AL= TP2M); + return -EINVAL; + } + } + else if ( config->altp2m.nr ) { - dprintk(XENLOG_INFO, "altp2m is only supported with HAP\n"); + dprintk(XENLOG_INFO, "altp2m.nr must be zero when altp2m is off\n"= ); return -EINVAL; } =20 diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 56c7de3977..f4bf0c8374 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -4674,6 +4674,12 @@ static int do_altp2m_op( goto out; } =20 + if ( d->nr_altp2m =3D=3D 0 ) + { + rc =3D -EINVAL; + goto out; + } + if ( (rc =3D xsm_hvm_altp2mhvm_op(XSM_OTHER, d, mode, a.cmd)) ) goto out; =20 @@ -5266,7 +5272,7 @@ void hvm_fast_singlestep(struct vcpu *v, uint16_t p2m= idx) if ( !hvm_is_singlestep_supported() ) return; =20 - if ( p2midx >=3D MAX_ALTP2M ) + if ( p2midx >=3D v->domain->nr_altp2m ) return; =20 v->arch.hvm.single_step =3D true; diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 218cb2c1af..3b63ac8b54 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -4967,7 +4967,7 @@ bool asmlinkage vmx_vmenter_helper(const struct cpu_u= ser_regs *regs) { unsigned int i; =20 - for ( i =3D 0; i < MAX_ALTP2M; ++i ) + for ( i =3D 0; i < currd->nr_altp2m; ++i ) { if ( currd->arch.altp2m_eptp[i] =3D=3D mfn_x(INVALID_MFN) ) continue; diff --git a/xen/arch/x86/include/asm/altp2m.h b/xen/arch/x86/include/asm/a= ltp2m.h index c57a8c5588..2882b3e7f0 100644 --- a/xen/arch/x86/include/asm/altp2m.h +++ b/xen/arch/x86/include/asm/altp2m.h @@ -13,12 +13,32 @@ #include /* for struct vcpu, struct domain */ #include /* for vcpu_altp2m */ =20 +static inline bool altp2m_is_eptp_valid(const struct domain *d, + unsigned int idx) +{ + ASSERT(d->nr_altp2m <=3D MAX_EPTP); + + /* + * EPTP index is correlated with altp2m index and should not exceed + * d->nr_altp2m. + */ + + return idx < d->nr_altp2m && + d->arch.altp2m_eptp[array_index_nospec(idx, MAX_EPTP)] !=3D + mfn_x(INVALID_MFN); +} + /* Alternate p2m HVM on/off per domain */ static inline bool altp2m_active(const struct domain *d) { return d->arch.altp2m_active; } =20 +static inline uint16_t altp2m_vcpu_idx(const struct vcpu *v) +{ + return vcpu_altp2m(v).p2midx; +} + /* Alternate p2m VCPU */ void altp2m_vcpu_initialise(struct vcpu *v); void altp2m_vcpu_destroy(struct vcpu *v); @@ -26,11 +46,13 @@ void altp2m_vcpu_destroy(struct vcpu *v); int altp2m_vcpu_enable_ve(struct vcpu *v, gfn_t gfn); void altp2m_vcpu_disable_ve(struct vcpu *v); =20 -static inline uint16_t altp2m_vcpu_idx(const struct vcpu *v) +#else + +static inline bool altp2m_is_eptp_valid(const struct domain *d, + unsigned int idx) { - return vcpu_altp2m(v).p2midx; + return false; } -#else =20 static inline bool altp2m_active(const struct domain *d) { diff --git a/xen/arch/x86/include/asm/domain.h b/xen/arch/x86/include/asm/d= omain.h index 8c0dea12a5..deb247480e 100644 --- a/xen/arch/x86/include/asm/domain.h +++ b/xen/arch/x86/include/asm/domain.h @@ -258,11 +258,12 @@ struct paging_vcpu { struct shadow_vcpu shadow; }; =20 -#define MAX_NESTEDP2M 10 +#define MAX_EPTP (PAGE_SIZE / sizeof(uint64_t)) +#define MAX_NR_ALTP2M MAX_EPTP +#define MAX_NESTEDP2M 10 =20 -#define MAX_ALTP2M 10 /* arbitrary */ #define INVALID_ALTP2M 0xffff -#define MAX_EPTP (PAGE_SIZE / sizeof(uint64_t)) + struct p2m_domain; struct time_scale { int shift; @@ -353,7 +354,7 @@ struct arch_domain =20 /* altp2m: allow multiple copies of host p2m */ bool altp2m_active; - struct p2m_domain *altp2m_p2m[MAX_ALTP2M]; + struct p2m_domain **altp2m_p2m; mm_lock_t altp2m_list_lock; uint64_t *altp2m_eptp; uint64_t *altp2m_visible_eptp; diff --git a/xen/arch/x86/include/asm/p2m.h b/xen/arch/x86/include/asm/p2m.h index 4358cc15a2..a2d7483602 100644 --- a/xen/arch/x86/include/asm/p2m.h +++ b/xen/arch/x86/include/asm/p2m.h @@ -901,7 +901,7 @@ static inline struct p2m_domain *p2m_get_altp2m(struct = vcpu *v) if ( index =3D=3D INVALID_ALTP2M ) return NULL; =20 - BUG_ON(index >=3D MAX_ALTP2M); + BUG_ON(index >=3D v->domain->nr_altp2m); =20 return v->domain->arch.altp2m_p2m[index]; } @@ -911,7 +911,7 @@ static inline bool p2m_set_altp2m(struct vcpu *v, unsig= ned int idx) { struct p2m_domain *orig; =20 - BUG_ON(idx >=3D MAX_ALTP2M); + BUG_ON(idx >=3D v->domain->nr_altp2m); =20 if ( idx =3D=3D vcpu_altp2m(v).p2midx ) return false; diff --git a/xen/arch/x86/mm/altp2m.c b/xen/arch/x86/mm/altp2m.c index 6fe1e9ed6b..2b1a05fc0d 100644 --- a/xen/arch/x86/mm/altp2m.c +++ b/xen/arch/x86/mm/altp2m.c @@ -15,6 +15,9 @@ void altp2m_vcpu_initialise(struct vcpu *v) { + if ( v->domain->nr_altp2m =3D=3D 0 ) + return; + if ( v !=3D current ) vcpu_pause(v); =20 @@ -32,6 +35,9 @@ altp2m_vcpu_destroy(struct vcpu *v) { struct p2m_domain *p2m; =20 + if ( v->domain->nr_altp2m =3D=3D 0 ) + return; + if ( v !=3D current ) vcpu_pause(v); =20 @@ -122,7 +128,12 @@ int p2m_init_altp2m(struct domain *d) struct p2m_domain *hostp2m =3D p2m_get_hostp2m(d); =20 mm_lock_init(&d->arch.altp2m_list_lock); - for ( i =3D 0; i < MAX_ALTP2M; i++ ) + d->arch.altp2m_p2m =3D xzalloc_array(struct p2m_domain *, d->nr_altp2m= ); + + if ( !d->arch.altp2m_p2m ) + return -ENOMEM; + + for ( i =3D 0; i < d->nr_altp2m; i++ ) { d->arch.altp2m_p2m[i] =3D p2m =3D p2m_init_one(d); if ( p2m =3D=3D NULL ) @@ -143,7 +154,10 @@ void p2m_teardown_altp2m(struct domain *d) unsigned int i; struct p2m_domain *p2m; =20 - for ( i =3D 0; i < MAX_ALTP2M; i++ ) + if ( !d->arch.altp2m_p2m ) + return; + + for ( i =3D 0; i < d->nr_altp2m; i++ ) { if ( !d->arch.altp2m_p2m[i] ) continue; @@ -151,6 +165,8 @@ void p2m_teardown_altp2m(struct domain *d) d->arch.altp2m_p2m[i] =3D NULL; p2m_free_one(p2m); } + + XFREE(d->arch.altp2m_p2m); } =20 int altp2m_get_effective_entry(struct p2m_domain *ap2m, gfn_t gfn, mfn_t *= mfn, @@ -200,7 +216,7 @@ bool p2m_switch_vcpu_altp2m_by_id(struct vcpu *v, unsig= ned int idx) struct domain *d =3D v->domain; bool rc =3D false; =20 - if ( idx >=3D MAX_ALTP2M ) + if ( idx >=3D d->nr_altp2m ) return rc; =20 altp2m_list_lock(d); @@ -306,8 +322,8 @@ static void p2m_reset_altp2m(struct domain *d, unsigned= int idx, { struct p2m_domain *p2m; =20 - ASSERT(idx < MAX_ALTP2M); - p2m =3D array_access_nospec(d->arch.altp2m_p2m, idx); + ASSERT(idx < d->nr_altp2m); + p2m =3D d->arch.altp2m_p2m[array_index_nospec(idx, d->nr_altp2m)]; =20 p2m_lock(p2m); =20 @@ -332,7 +348,7 @@ void p2m_flush_altp2m(struct domain *d) =20 altp2m_list_lock(d); =20 - for ( i =3D 0; i < MAX_ALTP2M; i++ ) + for ( i =3D 0; i < d->nr_altp2m; i++ ) { p2m_reset_altp2m(d, i, ALTP2M_DEACTIVATE); d->arch.altp2m_eptp[i] =3D mfn_x(INVALID_MFN); @@ -348,9 +364,9 @@ static int p2m_activate_altp2m(struct domain *d, unsign= ed int idx, struct p2m_domain *hostp2m, *p2m; int rc; =20 - ASSERT(idx < MAX_ALTP2M); + ASSERT(idx < d->nr_altp2m); =20 - p2m =3D array_access_nospec(d->arch.altp2m_p2m, idx); + p2m =3D d->arch.altp2m_p2m[array_index_nospec(idx, d->nr_altp2m)]; hostp2m =3D p2m_get_hostp2m(d); =20 p2m_lock(p2m); @@ -388,7 +404,7 @@ int p2m_init_altp2m_by_id(struct domain *d, unsigned in= t idx) int rc =3D -EINVAL; struct p2m_domain *hostp2m =3D p2m_get_hostp2m(d); =20 - if ( idx >=3D min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP) ) + if ( idx >=3D d->nr_altp2m ) return rc; =20 altp2m_list_lock(d); @@ -415,7 +431,7 @@ int p2m_init_next_altp2m(struct domain *d, uint16_t *id= x, =20 altp2m_list_lock(d); =20 - for ( i =3D 0; i < MAX_ALTP2M; i++ ) + for ( i =3D 0; i < d->nr_altp2m; i++ ) { if ( d->arch.altp2m_eptp[i] !=3D mfn_x(INVALID_MFN) ) continue; @@ -437,7 +453,7 @@ int p2m_destroy_altp2m_by_id(struct domain *d, unsigned= int idx) struct p2m_domain *p2m; int rc =3D -EBUSY; =20 - if ( !idx || idx >=3D min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP) ) + if ( !idx || idx >=3D d->nr_altp2m ) return rc; =20 rc =3D domain_pause_except_self(d); @@ -450,7 +466,7 @@ int p2m_destroy_altp2m_by_id(struct domain *d, unsigned= int idx) if ( d->arch.altp2m_eptp[array_index_nospec(idx, MAX_EPTP)] !=3D mfn_x(INVALID_MFN) ) { - p2m =3D array_access_nospec(d->arch.altp2m_p2m, idx); + p2m =3D d->arch.altp2m_p2m[array_index_nospec(idx, d->nr_altp2m)]; =20 if ( !_atomic_read(p2m->active_vcpus) ) { @@ -475,7 +491,7 @@ int p2m_switch_domain_altp2m_by_id(struct domain *d, un= signed int idx) struct vcpu *v; int rc =3D -EINVAL; =20 - if ( idx >=3D MAX_ALTP2M ) + if ( idx >=3D d->nr_altp2m ) return rc; =20 rc =3D domain_pause_except_self(d); @@ -510,13 +526,11 @@ int p2m_change_altp2m_gfn(struct domain *d, unsigned = int idx, mfn_t mfn; int rc =3D -EINVAL; =20 - if ( idx >=3D min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP) || - d->arch.altp2m_eptp[array_index_nospec(idx, MAX_EPTP)] =3D=3D - mfn_x(INVALID_MFN) ) + if ( !altp2m_is_eptp_valid(d, idx) ) return rc; =20 hp2m =3D p2m_get_hostp2m(d); - ap2m =3D array_access_nospec(d->arch.altp2m_p2m, idx); + ap2m =3D d->arch.altp2m_p2m[array_index_nospec(idx, d->nr_altp2m)]; =20 p2m_lock(hp2m); p2m_lock(ap2m); @@ -572,7 +586,7 @@ int p2m_altp2m_propagate_change(struct domain *d, gfn_t= gfn, =20 altp2m_list_lock(d); =20 - for ( i =3D 0; i < MAX_ALTP2M; i++ ) + for ( i =3D 0; i < d->nr_altp2m; i++ ) { p2m_type_t t; p2m_access_t a; @@ -595,7 +609,7 @@ int p2m_altp2m_propagate_change(struct domain *d, gfn_t= gfn, else { /* At least 2 altp2m's impacted, so reset everything */ - for ( i =3D 0; i < MAX_ALTP2M; i++ ) + for ( i =3D 0; i < d->nr_altp2m; i++ ) { if ( i =3D=3D last_reset_idx || d->arch.altp2m_eptp[i] =3D=3D mfn_x(INVALID_MFN) ) @@ -659,12 +673,11 @@ int p2m_set_suppress_ve_multi(struct domain *d, =20 if ( sve->view > 0 ) { - if ( sve->view >=3D min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP) = || - d->arch.altp2m_eptp[array_index_nospec(sve->view, MAX_EPTP)] = =3D=3D - mfn_x(INVALID_MFN) ) + if ( !altp2m_is_eptp_valid(d, sve->view) ) return -EINVAL; =20 - p2m =3D ap2m =3D array_access_nospec(d->arch.altp2m_p2m, sve->view= ); + p2m =3D ap2m =3D + d->arch.altp2m_p2m[array_index_nospec(sve->view, d->nr_altp2m)= ]; } =20 p2m_lock(host_p2m); @@ -727,12 +740,11 @@ int p2m_get_suppress_ve(struct domain *d, gfn_t gfn, = bool *suppress_ve, =20 if ( altp2m_idx > 0 ) { - if ( altp2m_idx >=3D min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP)= || - d->arch.altp2m_eptp[array_index_nospec(altp2m_idx, MAX_EPTP)]= =3D=3D - mfn_x(INVALID_MFN) ) + if ( !altp2m_is_eptp_valid(d, altp2m_idx) ) return -EINVAL; =20 - p2m =3D ap2m =3D array_access_nospec(d->arch.altp2m_p2m, altp2m_id= x); + p2m =3D ap2m =3D + d->arch.altp2m_p2m[array_index_nospec(altp2m_idx, d->nr_altp2m= )]; } else p2m =3D host_p2m; @@ -761,13 +773,7 @@ int p2m_set_altp2m_view_visibility(struct domain *d, u= nsigned int altp2m_idx, =20 altp2m_list_lock(d); =20 - /* - * Eptp index is correlated with altp2m index and should not exceed - * min(MAX_ALTP2M, MAX_EPTP). - */ - if ( altp2m_idx >=3D min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP) || - d->arch.altp2m_eptp[array_index_nospec(altp2m_idx, MAX_EPTP)] =3D= =3D - mfn_x(INVALID_MFN) ) + if ( !altp2m_is_eptp_valid(d, altp2m_idx) ) rc =3D -EINVAL; else if ( visible ) d->arch.altp2m_visible_eptp[array_index_nospec(altp2m_idx, MAX_EPT= P)] =3D diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c index ec5043a8aa..dcc15d6f1a 100644 --- a/xen/arch/x86/mm/hap/hap.c +++ b/xen/arch/x86/mm/hap/hap.c @@ -515,7 +515,7 @@ int hap_enable(struct domain *d, u32 mode) d->arch.altp2m_visible_eptp[i] =3D mfn_x(INVALID_MFN); } =20 - for ( i =3D 0; i < MAX_ALTP2M; i++ ) + for ( i =3D 0; i < d->nr_altp2m; i++ ) { rv =3D p2m_alloc_table(d->arch.altp2m_p2m[i]); if ( rv !=3D 0 ) @@ -538,7 +538,7 @@ void hap_final_teardown(struct domain *d) unsigned int i; =20 if ( hvm_altp2m_supported() ) - for ( i =3D 0; i < MAX_ALTP2M; i++ ) + for ( i =3D 0; i < d->nr_altp2m; i++ ) p2m_teardown(d->arch.altp2m_p2m[i], true, NULL); =20 /* Destroy nestedp2m's first */ @@ -590,7 +590,7 @@ void hap_teardown(struct domain *d, bool *preempted) FREE_XENHEAP_PAGE(d->arch.altp2m_eptp); FREE_XENHEAP_PAGE(d->arch.altp2m_visible_eptp); =20 - for ( i =3D 0; i < MAX_ALTP2M; i++ ) + for ( i =3D 0; i < d->nr_altp2m; i++ ) { p2m_teardown(d->arch.altp2m_p2m[i], false, preempted); if ( preempted && *preempted ) diff --git a/xen/arch/x86/mm/mem_access.c b/xen/arch/x86/mm/mem_access.c index 21b5b7ecda..3208b34925 100644 --- a/xen/arch/x86/mm/mem_access.c +++ b/xen/arch/x86/mm/mem_access.c @@ -350,12 +350,10 @@ long p2m_set_mem_access(struct domain *d, gfn_t gfn, = uint32_t nr, /* altp2m view 0 is treated as the hostp2m */ if ( altp2m_idx ) { - if ( altp2m_idx >=3D min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP)= || - d->arch.altp2m_eptp[array_index_nospec(altp2m_idx, MAX_EPTP)]= =3D=3D - mfn_x(INVALID_MFN) ) + if ( !altp2m_is_eptp_valid(d, altp2m_idx) ) return -EINVAL; =20 - ap2m =3D array_access_nospec(d->arch.altp2m_p2m, altp2m_idx); + ap2m =3D d->arch.altp2m_p2m[array_index_nospec(altp2m_idx, d->nr_a= ltp2m)]; } =20 if ( !xenmem_access_to_p2m_access(p2m, access, &a) ) @@ -406,12 +404,10 @@ long p2m_set_mem_access_multi(struct domain *d, /* altp2m view 0 is treated as the hostp2m */ if ( altp2m_idx ) { - if ( altp2m_idx >=3D min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP)= || - d->arch.altp2m_eptp[array_index_nospec(altp2m_idx, MAX_EPTP)]= =3D=3D - mfn_x(INVALID_MFN) ) + if ( !altp2m_is_eptp_valid(d, altp2m_idx) ) return -EINVAL; =20 - ap2m =3D array_access_nospec(d->arch.altp2m_p2m, altp2m_idx); + ap2m =3D d->arch.altp2m_p2m[array_index_nospec(altp2m_idx, d->nr_a= ltp2m)]; } =20 p2m_lock(p2m); @@ -469,12 +465,10 @@ int p2m_get_mem_access(struct domain *d, gfn_t gfn, x= enmem_access_t *access, } else if ( altp2m_idx ) /* altp2m view 0 is treated as the hostp2m */ { - if ( altp2m_idx >=3D min(ARRAY_SIZE(d->arch.altp2m_p2m), MAX_EPTP)= || - d->arch.altp2m_eptp[array_index_nospec(altp2m_idx, MAX_EPTP)]= =3D=3D - mfn_x(INVALID_MFN) ) + if ( !altp2m_is_eptp_valid(d, altp2m_idx) ) return -EINVAL; =20 - p2m =3D array_access_nospec(d->arch.altp2m_p2m, altp2m_idx); + p2m =3D d->arch.altp2m_p2m[array_index_nospec(altp2m_idx, d->nr_al= tp2m)]; } =20 return _p2m_get_mem_access(p2m, gfn, access); @@ -489,7 +483,7 @@ void arch_p2m_set_access_required(struct domain *d, boo= l access_required) if ( altp2m_active(d) ) { unsigned int i; - for ( i =3D 0; i < MAX_ALTP2M; i++ ) + for ( i =3D 0; i < d->nr_altp2m; i++ ) { struct p2m_domain *p2m =3D d->arch.altp2m_p2m[i]; =20 diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c index da28266ef0..83bb9dd5df 100644 --- a/xen/arch/x86/mm/mem_sharing.c +++ b/xen/arch/x86/mm/mem_sharing.c @@ -912,7 +912,7 @@ static int nominate_page(struct domain *d, gfn_t gfn, =20 altp2m_list_lock(d); =20 - for ( i =3D 0; i < MAX_ALTP2M; i++ ) + for ( i =3D 0; i < d->nr_altp2m; i++ ) { ap2m =3D d->arch.altp2m_p2m[i]; if ( !ap2m ) diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c index 0cf6818c13..305404f392 100644 --- a/xen/arch/x86/mm/p2m-ept.c +++ b/xen/arch/x86/mm/p2m-ept.c @@ -1301,7 +1301,7 @@ static void ept_set_ad_sync(struct domain *d, bool va= lue) { unsigned int i; =20 - for ( i =3D 0; i < MAX_ALTP2M; i++ ) + for ( i =3D 0; i < d->nr_altp2m; i++ ) { struct p2m_domain *p2m; =20 @@ -1508,7 +1508,8 @@ void __init setup_ept_dump(void) =20 void p2m_init_altp2m_ept(struct domain *d, unsigned int i) { - struct p2m_domain *p2m =3D array_access_nospec(d->arch.altp2m_p2m, i); + struct p2m_domain *p2m =3D + d->arch.altp2m_p2m[array_index_nospec(i, d->nr_altp2m)]; struct p2m_domain *hostp2m =3D p2m_get_hostp2m(d); struct ept_data *ept; =20 @@ -1527,7 +1528,7 @@ unsigned int p2m_find_altp2m_by_eptp(struct domain *d= , uint64_t eptp) =20 altp2m_list_lock(d); =20 - for ( i =3D 0; i < MAX_ALTP2M; i++ ) + for ( i =3D 0; i < d->nr_altp2m; i++ ) { if ( d->arch.altp2m_eptp[i] =3D=3D mfn_x(INVALID_MFN) ) continue; diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index b9a7c2dc53..b4dd12433e 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -105,7 +105,7 @@ void p2m_change_entry_type_global(struct domain *d, { unsigned int i; =20 - for ( i =3D 0; i < MAX_ALTP2M; i++ ) + for ( i =3D 0; i < d->nr_altp2m; i++ ) { if ( d->arch.altp2m_eptp[i] !=3D mfn_x(INVALID_MFN) ) { @@ -149,7 +149,7 @@ bool p2m_memory_type_changed(struct domain *d) { unsigned int i; =20 - for ( i =3D 0; i < MAX_ALTP2M; i++ ) + for ( i =3D 0; i < d->nr_altp2m; i++ ) { if ( d->arch.altp2m_eptp[i] !=3D mfn_x(INVALID_MFN) ) { @@ -934,7 +934,7 @@ void p2m_change_type_range(struct domain *d, { unsigned int i; =20 - for ( i =3D 0; i < MAX_ALTP2M; i++ ) + for ( i =3D 0; i < d->nr_altp2m; i++ ) { if ( d->arch.altp2m_eptp[i] !=3D mfn_x(INVALID_MFN) ) { @@ -1007,7 +1007,7 @@ int p2m_finish_type_change(struct domain *d, { unsigned int i; =20 - for ( i =3D 0; i < MAX_ALTP2M; i++ ) + for ( i =3D 0; i < d->nr_altp2m; i++ ) { if ( d->arch.altp2m_eptp[i] !=3D mfn_x(INVALID_MFN) ) { diff --git a/xen/common/domain.c b/xen/common/domain.c index 303c338ef2..77c3486065 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -811,6 +811,7 @@ struct domain *domain_create(domid_t domid, if ( config ) { d->options =3D config->flags; + d->nr_altp2m =3D config->altp2m.nr; d->vmtrace_size =3D config->vmtrace_size; } =20 diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index a69dd96084..573d34f239 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -116,7 +116,10 @@ struct xen_domctl_createdomain { /* Altp2m mode signaling uses bits [0, 1]. */ #define XEN_DOMCTL_ALTP2M_mode_mask (0x3U) #define XEN_DOMCTL_ALTP2M_mode(m) ((m) & XEN_DOMCTL_ALTP2M_mode_mask) - uint32_t opts; + uint16_t opts; + + /* Number of altp2ms to permit. */ + uint16_t nr; } altp2m; =20 /* Per-vCPU buffer size in bytes. 0 to disable. */ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index fe53d4fab7..f8be4ea1d9 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -619,6 +619,8 @@ struct domain unsigned int guest_request_sync : 1; } monitor; =20 + unsigned int nr_altp2m; /* Number of altp2m tables. */ + unsigned int vmtrace_size; /* Buffer size in bytes, or 0 to disable. */ =20 #ifdef CONFIG_ARGO --=20 2.34.1