From nobody Fri Oct 31 03:42:48 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 1753086760560807.7447220019915; Mon, 21 Jul 2025 01:32:40 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1051151.1419451 (Exim 4.92) (envelope-from ) id 1udlwh-0006SF-Rm; Mon, 21 Jul 2025 08:32:27 +0000 Received: by outflank-mailman (output) from mailman id 1051151.1419451; Mon, 21 Jul 2025 08:32:27 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1udlwh-0006S5-OI; Mon, 21 Jul 2025 08:32:27 +0000 Received: by outflank-mailman (input) for mailman id 1051151; Mon, 21 Jul 2025 08:32:27 +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 1udlwh-0005OI-1w for xen-devel@lists.xenproject.org; Mon, 21 Jul 2025 08:32:27 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-flk1.inumbo.com (Halon) with ESMTP id 3a7f46fb-660d-11f0-b894-0df219b8e170; Mon, 21 Jul 2025 10:32:25 +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 B4EE4153B; Mon, 21 Jul 2025 01:32:18 -0700 (PDT) Received: from PWQ0QT7DJ1.arm.com (unknown [10.57.71.32]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id C6F333F66E; Mon, 21 Jul 2025 01:32:22 -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: 3a7f46fb-660d-11f0-b894-0df219b8e170 From: Hari Limaye To: xen-devel@lists.xenproject.org Cc: luca.fancellu@arm.com, Penny Zheng , Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk , Penny Zheng , Wei Chen Subject: [PATCH v4 3/6] arm/mpu: Populate a new region in Xen MPU mapping table Date: Mon, 21 Jul 2025 09:31:44 +0100 Message-ID: <740a990a7579a53f69bb2b27b55a74093fd52d7e.1753084737.git.hari.limaye@arm.com> X-Mailer: git-send-email 2.42.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1753086762635116600 Content-Type: text/plain; charset="utf-8" From: Penny Zheng Introduce map_pages_to_xen() that is implemented using a new helper, xen_mpumap_update(), which is responsible for updating Xen MPU memory mapping table(xen_mpumap), including creating a new entry, updating or destroying an existing one, it is equivalent to xen_pt_update in MMU. This commit only implements populating a new entry in Xen MPU memory mapping table(xen_mpumap). Signed-off-by: Penny Zheng Signed-off-by: Wei Chen Signed-off-by: Luca Fancellu Signed-off-by: Hari Limaye Reviewed-by: Michal Orzel --- Changes from v1: - Simplify if condition - Use normal printk - Use %# over 0x% - Add same asserts as in Patch 4 Changes from v2: - Improve clarity in xen_mpumap_alloc_entry comment - Simplify if condition - Remove redundant ASSERT statements - Add check for `base >=3D limit` - Pass virt directly in map_pages_to_xen - Move call to `context_sync_mpu` inside locked section of `xen_mpumap_upda= te` - Move _PAGE_PRESENT check before calling `mpumap_contains_region` Changes from v3: - Add Michal's R-b --- xen/arch/arm/include/asm/mpu/mm.h | 12 ++++ xen/arch/arm/mpu/mm.c | 103 ++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/xen/arch/arm/include/asm/mpu/mm.h b/xen/arch/arm/include/asm/m= pu/mm.h index 5a2b9b498b..c32fac8905 100644 --- a/xen/arch/arm/include/asm/mpu/mm.h +++ b/xen/arch/arm/include/asm/mpu/mm.h @@ -64,6 +64,7 @@ static inline void context_sync_mpu(void) * The following API requires context_sync_mpu() after being used to modif= y MPU * regions: * - write_protection_region + * - xen_mpumap_update */ =20 /* Reads the MPU region (into @pr_read) with index @sel from the HW */ @@ -72,6 +73,17 @@ void read_protection_region(pr_t *pr_read, uint8_t sel); /* Writes the MPU region (from @pr_write) with index @sel to the HW */ void write_protection_region(const pr_t *pr_write, uint8_t sel); =20 +/* + * Maps an address range into the MPU data structure and updates the HW. + * Equivalent to xen_pt_update in an MMU system. + * + * @param base Base address of the range to map (inclusive). + * @param limit Limit address of the range to map (exclusive). + * @param flags Flags for the memory range to map. + * @return 0 on success, negative on error. + */ +int xen_mpumap_update(paddr_t base, paddr_t limit, unsigned int flags); + /* * Creates a pr_t structure describing a protection region. * diff --git a/xen/arch/arm/mpu/mm.c b/xen/arch/arm/mpu/mm.c index 407264a88c..d5426525af 100644 --- a/xen/arch/arm/mpu/mm.c +++ b/xen/arch/arm/mpu/mm.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -29,6 +30,8 @@ DECLARE_BITMAP(xen_mpumap_mask, MAX_MPU_REGION_NR) \ /* EL2 Xen MPU memory region mapping table. */ pr_t __cacheline_aligned __section(".data") xen_mpumap[MAX_MPU_REGION_NR]; =20 +static DEFINE_SPINLOCK(xen_mpumap_lock); + static void __init __maybe_unused build_assertions(void) { /* @@ -165,6 +168,106 @@ int mpumap_contains_region(pr_t *table, uint8_t nr_re= gions, paddr_t base, return MPUMAP_REGION_NOTFOUND; } =20 +/* + * Allocate an entry for a new EL2 MPU region in the bitmap xen_mpumap_mas= k. + * @param idx Set to the index of the allocated EL2 MPU region on succes= s. + * @return 0 on success, otherwise -ENOENT on failure. + */ +static int xen_mpumap_alloc_entry(uint8_t *idx) +{ + ASSERT(spin_is_locked(&xen_mpumap_lock)); + + *idx =3D find_first_zero_bit(xen_mpumap_mask, max_mpu_regions); + if ( *idx =3D=3D max_mpu_regions ) + { + printk(XENLOG_ERR "mpu: EL2 MPU memory region mapping pool exhaust= ed\n"); + return -ENOENT; + } + + set_bit(*idx, xen_mpumap_mask); + + return 0; +} + +/* + * Update the entry in the MPU memory region mapping table (xen_mpumap) fo= r the + * given memory range and flags, creating one if none exists. + * + * @param base Base address (inclusive). + * @param limit Limit address (exclusive). + * @param flags Region attributes (a combination of PAGE_HYPERVISOR_XXX) + * @return 0 on success, otherwise negative on error. + */ +static int xen_mpumap_update_entry(paddr_t base, paddr_t limit, + unsigned int flags) +{ + uint8_t idx; + int rc; + + ASSERT(spin_is_locked(&xen_mpumap_lock)); + + /* Currently only region creation is supported. */ + if ( !(flags & _PAGE_PRESENT) ) + return -EINVAL; + + rc =3D mpumap_contains_region(xen_mpumap, max_mpu_regions, base, limit= , &idx); + if ( rc !=3D MPUMAP_REGION_NOTFOUND ) + return -EINVAL; + + /* We are inserting a mapping =3D> Create new region. */ + rc =3D xen_mpumap_alloc_entry(&idx); + if ( rc ) + return -ENOENT; + + xen_mpumap[idx] =3D pr_of_addr(base, limit, flags); + + write_protection_region(&xen_mpumap[idx], idx); + + return 0; +} + +int xen_mpumap_update(paddr_t base, paddr_t limit, unsigned int flags) +{ + int rc; + + if ( flags_has_rwx(flags) ) + { + printk("Mappings should not be both Writeable and Executable\n"); + return -EINVAL; + } + + if ( base >=3D limit ) + { + printk("Base address %#"PRIpaddr" must be smaller than limit addre= ss %#"PRIpaddr"\n", + base, limit); + return -EINVAL; + } + + if ( !IS_ALIGNED(base, PAGE_SIZE) || !IS_ALIGNED(limit, PAGE_SIZE) ) + { + printk("base address %#"PRIpaddr", or limit address %#"PRIpaddr" i= s not page aligned\n", + base, limit); + return -EINVAL; + } + + spin_lock(&xen_mpumap_lock); + + rc =3D xen_mpumap_update_entry(base, limit, flags); + if ( !rc ) + context_sync_mpu(); + + spin_unlock(&xen_mpumap_lock); + + return rc; +} + +int map_pages_to_xen(unsigned long virt, mfn_t mfn, unsigned long nr_mfns, + unsigned int flags) +{ + /* MPU systems have no translation, ma =3D=3D va, so pass virt directl= y */ + return xen_mpumap_update(virt, mfn_to_maddr(mfn_add(mfn, nr_mfns)), fl= ags); +} + void __init setup_mm(void) { BUG_ON("unimplemented"); --=20 2.34.1