From nobody Thu Oct 30 19:00:05 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; 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=fail(p=none dis=none) header.from=arm.com Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1761320287942327.98964969607596; Fri, 24 Oct 2025 08:38:07 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1150561.1481667 (Exim 4.92) (envelope-from ) id 1vCJrL-00047F-Ti; Fri, 24 Oct 2025 15:37:43 +0000 Received: by outflank-mailman (output) from mailman id 1150561.1481667; Fri, 24 Oct 2025 15:37:43 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vCJrL-000478-R5; Fri, 24 Oct 2025 15:37:43 +0000 Received: by outflank-mailman (input) for mailman id 1150561; Fri, 24 Oct 2025 15:37:42 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vCJrK-0003pW-LQ for xen-devel@lists.xenproject.org; Fri, 24 Oct 2025 15:37:42 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 60c17ecd-b0ef-11f0-9d16-b5c5bf9af7f9; Fri, 24 Oct 2025 17:37:41 +0200 (CEST) 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 475521E2F; Fri, 24 Oct 2025 08:37:33 -0700 (PDT) Received: from e134099.cambridge.arm.com (e134099.arm.com [10.1.198.34]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id E14CD3F63F; Fri, 24 Oct 2025 08:37:39 -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: 60c17ecd-b0ef-11f0-9d16-b5c5bf9af7f9 From: Harry Ramsey To: xen-devel@lists.xenproject.org Cc: luca.fancellu@arm.com, Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk Subject: [PATCH 2/3] arm: Implement reference counting for overlapping regions Date: Fri, 24 Oct 2025 16:37:18 +0100 Message-ID: <20251024153719.408806-3-harry.ramsey@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251024153719.408806-1-harry.ramsey@arm.com> References: <20251024153719.408806-1-harry.ramsey@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1761320290576158500 Content-Type: text/plain; charset="utf-8" Implement reference counting to enable overlapping MPU regions. References are incremented and decremented in xen_mpumap_update_entry. A region will be destoryed if the reference count is 0 upon calling destroy_xen_mappings and if the full region range is specified. Additionally XEN_MPUMAP_ENTRY_SHIFT and XEN_MPUMAP_ENTRY_SHIFT_ZERO are no longer hardcoded and defined inside asm-offsets.c. Signed-off-by: Harry Ramsey --- xen/arch/arm/arm32/asm-offsets.c | 2 + xen/arch/arm/arm64/asm-offsets.c | 2 + xen/arch/arm/include/asm/arm32/mpu.h | 2 + xen/arch/arm/include/asm/arm64/mpu.h | 2 + xen/arch/arm/include/asm/mpu/regions.inc | 11 +++- xen/arch/arm/mpu/mm.c | 73 +++++++++++++++++++----- 6 files changed, 77 insertions(+), 15 deletions(-) diff --git a/xen/arch/arm/arm32/asm-offsets.c b/xen/arch/arm/arm32/asm-offs= ets.c index c203ce269d..951f8d03f3 100644 --- a/xen/arch/arm/arm32/asm-offsets.c +++ b/xen/arch/arm/arm32/asm-offsets.c @@ -79,6 +79,8 @@ void __dummy__(void) #ifdef CONFIG_MPU DEFINE(XEN_MPUMAP_MASK_sizeof, sizeof(xen_mpumap_mask)); DEFINE(XEN_MPUMAP_sizeof, sizeof(xen_mpumap)); + DEFINE(XEN_MPUMAP_ENTRY_SHIFT, ilog2(sizeof(pr_t))); + DEFINE(XEN_MPUMAP_ENTRY_ZERO_OFFSET, sizeof(prbar_t) + sizeof(prlar_t)); BLANK(); #endif } diff --git a/xen/arch/arm/arm64/asm-offsets.c b/xen/arch/arm/arm64/asm-offs= ets.c index 320289b281..38a3894a3b 100644 --- a/xen/arch/arm/arm64/asm-offsets.c +++ b/xen/arch/arm/arm64/asm-offsets.c @@ -73,6 +73,8 @@ void __dummy__(void) #ifdef CONFIG_MPU DEFINE(XEN_MPUMAP_MASK_sizeof, sizeof(xen_mpumap_mask)); DEFINE(XEN_MPUMAP_sizeof, sizeof(xen_mpumap)); + DEFINE(XEN_MPUMAP_ENTRY_SHIFT, ilog2(sizeof(pr_t))); + DEFINE(XEN_MPUMAP_ENTRY_ZERO_OFFSET, sizeof(prbar_t) + sizeof(prlar_t)); BLANK(); #endif } diff --git a/xen/arch/arm/include/asm/arm32/mpu.h b/xen/arch/arm/include/as= m/arm32/mpu.h index 0a6930b3a0..137022d922 100644 --- a/xen/arch/arm/include/asm/arm32/mpu.h +++ b/xen/arch/arm/include/asm/arm32/mpu.h @@ -39,6 +39,8 @@ typedef union { typedef struct { prbar_t prbar; prlar_t prlar; + uint8_t refcount; + uint8_t pad[7]; /* Pad structure to 16 Bytes */ } pr_t; =20 #endif /* __ASSEMBLY__ */ diff --git a/xen/arch/arm/include/asm/arm64/mpu.h b/xen/arch/arm/include/as= m/arm64/mpu.h index f0ce344e78..17f62ccaf6 100644 --- a/xen/arch/arm/include/asm/arm64/mpu.h +++ b/xen/arch/arm/include/asm/arm64/mpu.h @@ -38,6 +38,8 @@ typedef union { typedef struct { prbar_t prbar; prlar_t prlar; + uint8_t refcount; + uint8_t pad[15]; /* Pad structure to 32 Bytes */ } pr_t; =20 #endif /* __ASSEMBLY__ */ diff --git a/xen/arch/arm/include/asm/mpu/regions.inc b/xen/arch/arm/includ= e/asm/mpu/regions.inc index 23fead3b21..0cdbb17bc3 100644 --- a/xen/arch/arm/include/asm/mpu/regions.inc +++ b/xen/arch/arm/include/asm/mpu/regions.inc @@ -14,14 +14,12 @@ #define PRLAR_ELx_EN 0x1 =20 #ifdef CONFIG_ARM_64 -#define XEN_MPUMAP_ENTRY_SHIFT 0x4 /* 16 byte structure */ =20 .macro store_pair reg1, reg2, dst stp \reg1, \reg2, [\dst] .endm =20 #else -#define XEN_MPUMAP_ENTRY_SHIFT 0x3 /* 8 byte structure */ =20 .macro store_pair reg1, reg2, dst strd \reg1, \reg2, [\dst] @@ -97,6 +95,15 @@ =20 3: =20 + /* Clear the rest of the xen_mpumap entry. */ +#ifdef CONFIG_ARM_64 + stp xzr, xzr, [\base, #XEN_MPUMAP_ENTRY_ZERO_OFFSET] +#else + mov \prbar, #0 + mov \prlar, #0 + strd \prbar, \prlar, [\base, #XEN_MPUMAP_ENTRY_ZERO_OFFSET] +#endif + add \sel, \sel, #1 =20 1: diff --git a/xen/arch/arm/mpu/mm.c b/xen/arch/arm/mpu/mm.c index a058db19ef..c5128244b7 100644 --- a/xen/arch/arm/mpu/mm.c +++ b/xen/arch/arm/mpu/mm.c @@ -106,6 +106,7 @@ pr_t pr_of_addr(paddr_t base, paddr_t limit, unsigned i= nt flags) region =3D (pr_t) { .prbar =3D prbar, .prlar =3D prlar, + .refcount =3D 0, }; =20 /* Set base address and limit address. */ @@ -170,6 +171,37 @@ int mpumap_contains_region(pr_t *table, uint8_t nr_reg= ions, paddr_t base, return MPUMAP_REGION_NOTFOUND; } =20 +static bool is_mm_attr_match(pr_t *region, unsigned int attributes) +{ + bool ret =3D true; + + if ( region->prbar.reg.ro !=3D PAGE_RO_MASK(attributes) ) + { + printk(XENLOG_WARNING + "Mismatched Access Permission attributes (%#x0 instead of %= #x0)\n", + region->prbar.reg.ro, PAGE_RO_MASK(attributes)); + ret =3D false; + } + + if ( region->prbar.reg.xn !=3D PAGE_XN_MASK(attributes) ) + { + printk(XENLOG_WARNING + "Mismatched Execute Never attributes (%#x instead of %#x)\n= ", + region->prbar.reg.xn, PAGE_XN_MASK(attributes)); + ret =3D false; + } + + if ( region->prlar.reg.ai !=3D PAGE_AI_MASK(attributes) ) + { + printk(XENLOG_WARNING + "Mismatched Memory Attribute Index (%#x instead of %#x)\n", + region->prlar.reg.ai, PAGE_AI_MASK(attributes)); + ret =3D false; + } + + return ret; +} + /* Map a frame table to cover physical addresses ps through pe */ void __init setup_frametable_mappings(paddr_t ps, paddr_t pe) { @@ -287,19 +319,19 @@ static int xen_mpumap_update_entry(paddr_t base, padd= r_t limit, /* Currently we don't support modifying an existing entry. */ if ( flags_has_page_present && (rc >=3D MPUMAP_REGION_FOUND) ) { - printk("Modifying an existing entry is not supported\n"); - return -EINVAL; - } + if ( !is_mm_attr_match(&xen_mpumap[idx], flags) ) + { + printk("Modifying an existing entry is not supported\n"); + return -EINVAL; + } =20 - /* - * Currently, we only support removing/modifying a *WHOLE* MPU memory - * region. Part-region removal/modification is not supported as in the= worst - * case it will leave two/three fragments behind. - */ - if ( rc =3D=3D MPUMAP_REGION_INCLUSIVE ) - { - printk("Part-region removal/modification is not supported\n"); - return -EINVAL; + /* Check for overflow of refcount before incrementing. */ + if ( xen_mpumap[idx].refcount =3D=3D 0xFF ) + { + printk("Cannot allocate region as it would cause reference ove= rflow\n"); + return -ENOENT; + } + xen_mpumap[idx].refcount +=3D 1; } =20 /* We are inserting a mapping =3D> Create new region. */ @@ -323,7 +355,22 @@ static int xen_mpumap_update_entry(paddr_t base, paddr= _t limit, return -EINVAL; } =20 - disable_mpu_region_from_index(idx); + if ( xen_mpumap[idx].refcount =3D=3D 0 ) + { + if (MPUMAP_REGION_FOUND =3D=3D rc) + { + disable_mpu_region_from_index(idx); + } + else + { + printk("Cannot remove a partial region\n"); + return -EINVAL; + } + } + else + { + xen_mpumap[idx].refcount -=3D 1; + } } =20 return 0; --=20 2.43.0