diff --git a/xen/arch/arm/include/asm/arm64/mpu.h b/xen/arch/arm/include/asm/arm64/mpu.h
index dce77da60110..4b7579d0ce18 100644
--- a/xen/arch/arm/include/asm/arm64/mpu.h
+++ b/xen/arch/arm/include/asm/arm64/mpu.h
@@ -17,6 +17,8 @@
 
 #define MAX_MPU_REGIONS         NUM_MPU_REGIONS_MASK
 
+#define PRENR_MASK              GENMASK(31, 0)
+
 /* Access permission attributes. */
 /* Read/Write at EL2, No Access at EL1/EL0. */
 #define AP_RW_EL2 0x0
diff --git a/xen/arch/arm/include/asm/mm.h b/xen/arch/arm/include/asm/mm.h
index e7767cdab493..370054554432 100644
--- a/xen/arch/arm/include/asm/mm.h
+++ b/xen/arch/arm/include/asm/mm.h
@@ -206,7 +206,7 @@ extern unsigned long frametable_base_pdx;
 #define PDX_GROUP_SHIFT SECOND_SHIFT
 
 /* Boot-time pagetable setup */
-extern void setup_pagetables(void);
+extern void setup_mappings(void);
 /* Map FDT in boot pagetable */
 extern void *early_fdt_map(paddr_t fdt_paddr);
 /* Remove early mappings */
diff --git a/xen/arch/arm/mmu/setup.c b/xen/arch/arm/mmu/setup.c
index 30afe9778194..35ffa5479dd3 100644
--- a/xen/arch/arm/mmu/setup.c
+++ b/xen/arch/arm/mmu/setup.c
@@ -354,7 +354,7 @@ static void __init create_llc_coloring_mappings(void)
  * Boot-time pagetable setup.
  * Changes here may need matching changes in head.S
  */
-void __init setup_pagetables(void)
+void __init setup_mappings(void)
 {
     uint64_t ttbr;
     lpae_t pte, *p;
diff --git a/xen/arch/arm/mpu/mm.c b/xen/arch/arm/mpu/mm.c
index fb94f5d1d93d..4614c36f04cc 100644
--- a/xen/arch/arm/mpu/mm.c
+++ b/xen/arch/arm/mpu/mm.c
@@ -8,10 +8,22 @@
  *
  */
 
+#include <xen/init.h>
 #include <asm/mpu/mm.h>
 #include <asm/page.h>
 #include <asm/sysregs.h>
 
+/* Maximum number of supported MPU memory regions by the EL2 MPU. */
+uint8_t __ro_after_init max_xen_mpumap;
+
+/*
+ * Bitmap xen_mpumap_mask is to record the usage of EL2 MPU memory regions.
+ * Bit 0 represents MPU memory region 0, bit 1 represents MPU memory
+ * region 1, ..., and so on.
+ * If a MPU memory region gets enabled, set the according bit to 1.
+ */
+DECLARE_BITMAP(xen_mpumap_mask, MAX_MPU_REGIONS);
+
 /* EL2 Xen MPU memory region mapping table. */
 pr_t xen_mpumap[MAX_MPU_REGIONS];
 
diff --git a/xen/arch/arm/mpu/setup.c b/xen/arch/arm/mpu/setup.c
index 290baaca9fd7..b37f309ec8e3 100644
--- a/xen/arch/arm/mpu/setup.c
+++ b/xen/arch/arm/mpu/setup.c
@@ -14,6 +14,46 @@
 /* Needs to be kept in sync with the regions programmed in arm64/mpu/head.S */
 #define EARLY_FDT_MAP_REGION_NUMBER 6
 
+extern uint8_t max_xen_mpumap;
+extern DECLARE_BITMAP(xen_mpumap_mask, MAX_MPU_REGIONS);
+extern pr_t xen_mpumap[MAX_MPU_REGIONS];
+
+/*
+ * The code in this function needs to track the regions programmed in
+ * arm64/mpu/head.S
+ */
+void __init setup_mappings(void)
+{
+    register_t prenr;
+    unsigned int i = 0;
+
+    /*
+     * MPUIR_EL2.Region[0:7] identifies the number of regions supported by
+     * the EL2 MPU.
+     */
+    max_xen_mpumap = (uint8_t)(READ_SYSREG(MPUIR_EL2) & NUM_MPU_REGIONS_MASK);
+
+    /* PRENR_EL2 has the N bit set if the N region is enabled, N < 32 */
+    prenr = (READ_SYSREG(PRENR_EL2) & PRENR_MASK);
+
+    /*
+     * Set the bitfield for regions enabled in assembly boot-time.
+     * This code works under the assumption that the code in head.S has
+     * allocated and enabled regions below 32 (N < 32).
+     */
+    while ( prenr > 0 )
+    {
+        if (prenr & 0x1)
+        {
+            set_bit(i, xen_mpumap_mask);
+            read_protection_region(&xen_mpumap[i], i);
+        }
+
+        prenr >>= 1;
+        i++;
+    }
+}
+
 void * __init early_fdt_map(paddr_t fdt_paddr)
 {
     /* Map at least a page containing the DTB address, exclusive range */
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index c1f2d1b89d43..fc6c9456bc2e 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -340,7 +340,7 @@ void asmlinkage __init start_xen(unsigned long fdt_paddr)
      * Page tables must be setup after LLC coloring initialization because
      * coloring info are required in order to create colored mappings
      */
-    setup_pagetables();
+    setup_mappings();
     /* Device-tree was mapped in boot page tables, remap it in the new tables */
     device_tree_flattened = early_fdt_map(fdt_paddr);
 
