From nobody Mon Apr 13 00:05:42 2026 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=arm.com ARC-Seal: i=1; a=rsa-sha256; t=1775656586; cv=none; d=zohomail.com; s=zohoarc; b=EZOTyWUQQsPXmeTf+lXXWGBzT4xmX/8EhV4gsrdQaM3CQk35dgDxRWUQUodcdEoAWzlNrnYhsIxow43rD+md3LO2+pEkTHriq4scJkYZoUzRKTzj30+OW3AOZuqzUyGyFCQcLv9YFXuqE8eMAOSCGbluRIyRy3z+dafj79buuTM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1775656586; 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=A9YHpO3hdJC7jXO9sB94hRprcM8NZRc2DaotMYDyPhg=; b=QayCR8aXuxQHEXGV9/NIzVi19UYumcSuB2T1eEZG4MjHPytbUQRzaHU4SIb9k5sSmSsuKJ6w0dIKgFoFKbBWV0naTF2GpbrRa6ic9ig8bWV1DVAnAlEUBsIAva7iJ7P74VTy5BQSnp1/nvwr22IhIy0yvRldA0D+3oYBMwEr4KQ= 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 1775656586378408.58344505504624; Wed, 8 Apr 2026 06:56:26 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1276215.1561780 (Exim 4.92) (envelope-from ) id 1wATNp-0002AP-FF; Wed, 08 Apr 2026 13:55:53 +0000 Received: by outflank-mailman (output) from mailman id 1276215.1561780; Wed, 08 Apr 2026 13:55:53 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wATNp-0002AI-Br; Wed, 08 Apr 2026 13:55:53 +0000 Received: by outflank-mailman (input) for mailman id 1276215; Wed, 08 Apr 2026 13:55:51 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wATNn-0001w4-C5 for xen-devel@lists.xenproject.org; Wed, 08 Apr 2026 13:55:51 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wATNm-00AFz6-OB for xen-devel@lists.xenproject.org; Wed, 08 Apr 2026 15:55:50 +0200 Received: from [10.42.69.2] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 69d65e54-e002-0a2a0a5209dd-0a2a4502d0da-48 for ; Wed, 08 Apr 2026 15:55:50 +0200 Received: from [217.140.110.172] (helo=foss.arm.com) by tlsNG-720697.mxtls.expurgate.net with ESMTP (eXpurgate 4.56.0) (envelope-from ) id 69d65e65-42fa-0a2a45020019-d98c6eacbcc8-1 for ; Wed, 08 Apr 2026 15:55:50 +0200 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id AE14A2D95; Wed, 8 Apr 2026 06:55:43 -0700 (PDT) Received: from e125770.cambridge.arm.com (e125770.arm.com [10.1.199.43]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 538EB3F641; Wed, 8 Apr 2026 06:55:48 -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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=foss header.d=arm.com header.i="@arm.com" header.h="From:To:Cc:Subject:Date:In-Reply-To:References" DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1775656549; bh=MZfKdfd+Fjj1nByHopUcpOrzmuP31AXPE7A1SX/KVCM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Kece+ckOVuHEDt+c/9tCpgkrxKngvpG1tEBgmcyidiwZ3p1OHEQHQUAHP7pPUU3A2 gxKcYy1aY2+wxvShLu/vmmgvoENvxwEt87duuVzn1GeC6DZWaByS+0awZahbr9/+V4 50lnYBTq18dbPms5Uro++lahgvoc/jiRQBeU3zHM= From: Luca Fancellu To: xen-devel@lists.xenproject.org Cc: Harry Ramsey , Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk Subject: [PATCH v3 3/3] arm/mpu: Implement p2m tables Date: Wed, 8 Apr 2026 14:55:31 +0100 Message-Id: <20260408135531.1744388-4-luca.fancellu@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260408135531.1744388-1-luca.fancellu@arm.com> References: <20260408135531.1744388-1-luca.fancellu@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-720697/1775656550-ACB37CD1-35573629/0/0 X-purgate-type: clean X-purgate-size: 5725 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1775656588251158500 Content-Type: text/plain; charset="utf-8" From: Harry Ramsey Implement `p2m_alloc_table`, `p2m_init` and `p2m_final_teardown` for MPU systems. Signed-off-by: Harry Ramsey Signed-off-by: Luca Fancellu --- v3: - Check for alloc_xenheap_pages allocation - Clear additional page allocated for ARM64 - Add check for INVALID_VCPU_ID - Remove unnecessary function generate_vsctlr - Code formatting fixes --- xen/arch/arm/include/asm/arm32/mpu.h | 2 + xen/arch/arm/include/asm/arm64/mpu.h | 2 + xen/arch/arm/include/asm/mpu/p2m.h | 12 +++++ xen/arch/arm/include/asm/p2m.h | 5 ++ xen/arch/arm/mpu/p2m.c | 78 ++++++++++++++++++++++++++-- 5 files changed, 96 insertions(+), 3 deletions(-) diff --git a/xen/arch/arm/include/asm/arm32/mpu.h b/xen/arch/arm/include/as= m/arm32/mpu.h index 2cf0f8cbacae..d565230f84ee 100644 --- a/xen/arch/arm/include/asm/arm32/mpu.h +++ b/xen/arch/arm/include/asm/arm32/mpu.h @@ -11,6 +11,8 @@ */ #define MPU_REGION_RES0 0x0 =20 +#define VSCTLR_VMID_SHIFT 16 + /* Hypervisor Protection Region Base Address Register */ typedef union { struct { diff --git a/xen/arch/arm/include/asm/arm64/mpu.h b/xen/arch/arm/include/as= m/arm64/mpu.h index 4f694190a8a3..8b86a03fee44 100644 --- a/xen/arch/arm/include/asm/arm64/mpu.h +++ b/xen/arch/arm/include/asm/arm64/mpu.h @@ -7,6 +7,8 @@ =20 #define MPU_REGION_RES0 (0xFFFFULL << 48) =20 +#define VSCTLR_VMID_SHIFT 48 + /* Protection Region Base Address Register */ typedef union { struct __packed { diff --git a/xen/arch/arm/include/asm/mpu/p2m.h b/xen/arch/arm/include/asm/= mpu/p2m.h index e46d9e757a1d..39fc0c944916 100644 --- a/xen/arch/arm/include/asm/mpu/p2m.h +++ b/xen/arch/arm/include/asm/mpu/p2m.h @@ -3,8 +3,20 @@ #ifndef __ARM_MPU_P2M_H__ #define __ARM_MPU_P2M_H__ =20 +#include +#include +#include + struct p2m_domain; =20 +/* + * The architecture allows at most 255 EL2 MPU memory regions. The size of= the + * MPU structure entry (pr_t) is 32 Bytes on AArch64 (requiring two 4KB pa= ges) + * and 16 bytes on AArch32 (requiring one 4KB page). + */ +#define P2M_ROOT_PAGES DIV_ROUND_UP(255 * sizeof(pr_t), PAGE_SIZE) +#define P2M_ROOT_ORDER get_count_order(P2M_ROOT_PAGES) + static inline void p2m_clear_root_pages(struct p2m_domain *p2m) {} =20 static inline void p2m_tlb_flush_sync(struct p2m_domain *p2m) {} diff --git a/xen/arch/arm/include/asm/p2m.h b/xen/arch/arm/include/asm/p2m.h index 010ce8c9ebbd..ed1b6dd40f40 100644 --- a/xen/arch/arm/include/asm/p2m.h +++ b/xen/arch/arm/include/asm/p2m.h @@ -48,8 +48,13 @@ struct p2m_domain { /* Current VMID in use */ uint16_t vmid; =20 +#ifdef CONFIG_MMU /* Current Translation Table Base Register for the p2m */ uint64_t vttbr; +#else + /* Current Virtualization System Control Register for the p2m */ + register_t vsctlr; +#endif =20 /* Highest guest frame that's ever been mapped in the p2m */ gfn_t max_mapped_gfn; diff --git a/xen/arch/arm/mpu/p2m.c b/xen/arch/arm/mpu/p2m.c index f7fb58ab6aa8..ec8f630acd90 100644 --- a/xen/arch/arm/mpu/p2m.c +++ b/xen/arch/arm/mpu/p2m.c @@ -28,10 +28,69 @@ void p2m_dump_info(struct domain *d) BUG_ON("unimplemented"); } =20 +static int p2m_alloc_table(struct domain *d) +{ + struct p2m_domain *p2m =3D p2m_get_hostp2m(d); + void *table =3D alloc_xenheap_pages(P2M_ROOT_ORDER, 0); + + if ( !table ) + { + printk(XENLOG_G_ERR "%pd: p2m: unable to allocate P2M MPU mapping = table\n", + d); + return -ENOMEM; + } + + p2m->root =3D virt_to_page(table); + + for (int i =3D 0; i < P2M_ROOT_PAGES; i++) + clear_page(page_to_virt(p2m->root + i)); + + return 0; +} + int p2m_init(struct domain *d) { - BUG_ON("unimplemented"); - return -EINVAL; + struct p2m_domain *p2m =3D p2m_get_hostp2m(d); + int rc =3D 0; + unsigned int cpu; + + rwlock_init(&p2m->lock); + + p2m->vmid =3D INVALID_VMID; + p2m->max_mapped_gfn =3D _gfn(0); + p2m->lowest_mapped_gfn =3D _gfn(ULONG_MAX); + + p2m->default_access =3D p2m_access_rwx; + /* mem_access is NOT supported in MPU system. */ + p2m->mem_access_enabled =3D false; + + /* Ensure that the type chosen is large enough for MAX_VIRT_CPUS. */ + BUILD_BUG_ON((1 << (sizeof(p2m->last_vcpu_ran[0]) * 8)) < MAX_VIRT_CPU= S); + BUILD_BUG_ON((1 << (sizeof(p2m->last_vcpu_ran[0]) * 8)) < INVALID_VCPU= _ID); + + for_each_possible_cpu(cpu) + p2m->last_vcpu_ran[cpu] =3D INVALID_VCPU_ID; + + /* + * "Trivial" initialization is now complete. Set the backpointer so th= at + * p2m_teardown() and related functions know to do something. + */ + p2m->domain =3D d; + + rc =3D p2m_alloc_vmid(d); + if ( rc ) + return rc; + + p2m->vsctlr =3D ((register_t)p2m->vmid << VSCTLR_VMID_SHIFT); + + rc =3D p2m_alloc_table(d); + if ( rc ) + { + p2m_free_vmid(d); + return rc; + } + + return 0; } =20 void p2m_save_state(struct vcpu *p) @@ -46,7 +105,20 @@ void p2m_restore_state(struct vcpu *n) =20 void p2m_final_teardown(struct domain *d) { - BUG_ON("unimplemented"); + struct p2m_domain *p2m =3D p2m_get_hostp2m(d); + + /* p2m not actually initialized */ + if ( !p2m->domain ) + return; + + if ( p2m->root ) + free_xenheap_pages(page_to_virt(p2m->root), P2M_ROOT_ORDER); + + p2m->root =3D NULL; + + p2m_free_vmid(d); + + p2m->domain =3D NULL; } =20 bool p2m_resolve_translation_fault(struct domain *d, gfn_t gfn) --=20 2.34.1