[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 2/3] arm/mpu: Implement reference counting for inclusive regions


  • To: Harry Ramsey <harry.ramsey@xxxxxxx>, <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: "Orzel, Michal" <michal.orzel@xxxxxxx>
  • Date: Mon, 17 Nov 2025 14:04:26 +0100
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=arm.com smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0)
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=RY3G1kN8XBp108ReZMKdPSvu5GhXOk80ilCtWFY+Pz0=; b=QVxY4F7pjULz9KDy1feSizJc9wZTIVf2/cUvC9tdnQ9Vucu4wJNJsG1lueJAz/CKDTK0ma6LjauA6Cfem55EndnvvmWV3oYAWMS2G08SIxYIm7naHtYjrzlv6b703W6zgNoVMKNwj5AbdCX0mi7dRVriVMxHbqmUI+a6/RugkUzgSFVnGZtieCuITozba9LmhMR4P/A+9R6XCFBqkHqh6NBtAtaYXVejf9AYyofQ0zAooOEV46RNRkpVe+ghFZwzStOC7385Y1h64DuqlL2cAmQ0qHoWSd3OXkpnKosB7abI4DaJ7r+j070tQQOnSqO0hBL+PtDLn2wCCHzS9C0Cmw==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=UEbcW9b5rzjU2I8zTYzcBJGcGC2QbEexcR3l2NSc9nvnLJuu7/FfRKMBDhasQnAyL4l5Oqa2mxQbvQMUmvhJs9FbrizcWE3DJL5dCx/HodnrJl8S9b17li2dY+f1+mioeR2EVNNcvH/IqkCnQbFMvQcd0TaYabhiH85LGW6vt445zdCI1PDXuDxOQK9uZdiPP5QEr28W9FubO09QNwoCxFJ/9E1m4WLNxZTP11a+kmls8vxtKj5j7uy3anYdBx7jVntFShfCjoSHoE0zTrzeY5r99XAmXb/m9jB2APhTs0UmU5ACMzgPSiEx52KJRdVxIQjn8z4Y1zPUK5ONoS+j1Q==
  • Cc: <Luca.Fancellu@xxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Bertrand Marquis <bertrand.marquis@xxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>
  • Delivery-date: Mon, 17 Nov 2025 13:04:40 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>


On 11/11/2025 11:16, Harry Ramsey wrote:
> Implement reference counting to enable inclusive MPU regions. An
> inclusive region is defined as a region encapsulated inside a
> previously allocated region sharing the same permissions.
> 
> References are incremented and decremented in xen_mpumap_update_entry. A
> region will be destroyed 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 <harry.ramsey@xxxxxxx>
> ---
> Changes in v2:
> - Improve clarity with regards to MPU inclusive regions
> - Fix code format issues
> ---
>  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                    | 75 +++++++++++++++++++-----
>  6 files changed, 78 insertions(+), 16 deletions(-)
> 
> diff --git a/xen/arch/arm/arm32/asm-offsets.c 
> b/xen/arch/arm/arm32/asm-offsets.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-offsets.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/asm/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;
> 
>  #endif /* __ASSEMBLY__ */
> diff --git a/xen/arch/arm/include/asm/arm64/mpu.h 
> b/xen/arch/arm/include/asm/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;
> 
>  #endif /* __ASSEMBLY__ */
> diff --git a/xen/arch/arm/include/asm/mpu/regions.inc 
> b/xen/arch/arm/include/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
> 
>  #ifdef CONFIG_ARM_64
> -#define XEN_MPUMAP_ENTRY_SHIFT  0x4     /* 16 byte structure */
> 
>  .macro store_pair reg1, reg2, dst
>      stp \reg1, \reg2, [\dst]
>  .endm
> 
>  #else
> -#define XEN_MPUMAP_ENTRY_SHIFT  0x3     /* 8 byte structure */
> 
>  .macro store_pair reg1, reg2, dst
>      strd  \reg1, \reg2, [\dst]
> @@ -97,6 +95,15 @@
> 
>  3:
> 
> +    /* 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
> 
>  1:
> diff --git a/xen/arch/arm/mpu/mm.c b/xen/arch/arm/mpu/mm.c
> index b80edcf1ca..cd84f9e3c6 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 int 
> flags)
>      region = (pr_t) {
>          .prbar = prbar,
>          .prlar = prlar,
> +        .refcount = 0,
>      };
> 
>      /* Set base address and limit address. */
> @@ -170,6 +171,37 @@ int mpumap_contains_region(pr_t *table, uint8_t 
> nr_regions, paddr_t base,
>      return MPUMAP_REGION_NOTFOUND;
>  }
> 
> +static bool is_mm_attr_match(pr_t *region, unsigned int attributes)
> +{
> +    bool ret = true;
> +
> +    if ( region->prbar.reg.ro != PAGE_RO_MASK(attributes) )
> +    {
> +        printk(XENLOG_WARNING
> +               "Mismatched Access Permission attributes (%#x instead of 
> %#x)\n",
> +               region->prbar.reg.ro, PAGE_RO_MASK(attributes));
> +        ret = false;
NIT: I think it's more clear when you return false here. Otherwise after setting
ret to false, what's the point for checking additionally for below conditions?

> +    }
> +
> +    if ( region->prbar.reg.xn != 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 = false;
> +    }
> +
> +    if ( region->prlar.reg.ai != 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 = 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)
>  {
> @@ -284,22 +316,26 @@ static int xen_mpumap_update_entry(paddr_t base, 
> paddr_t limit,
> 
>      flags_has_page_present = flags & _PAGE_PRESENT;
> 
> -    /* Currently we don't support modifying an existing entry. */
> +    /*
> +    * 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 ( flags_has_page_present && (rc >= 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;
> +        }
> 
> -    /*
> -     * 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 == 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 == 0xFF )
> +        {
> +            printk("Cannot allocate region as it would cause reference 
> overflow\n");
s/reference/reference count or refcount/

Reviewed-by: Michal Orzel <michal.orzel@xxxxxxx>

~Michal





 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.