@@ -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
@@ -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 */
@@ -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;
@@ -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];
@@ -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 */
@@ -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);
Currently the function setup_pagetables() take care to initialise the mappings on MMU system; MPU systems don't have page tables, but needs to track the status of the MPU programmed regions. So rename setup_pagetables() into setup_mappings() and implement the function on MPU systems, start introducing data structures and functions to track the MPU status from the C world. The xen_mpumap_mask bitmap is used to track which MPU region are enabled at runtime. Signed-off-by: Luca Fancellu <luca.fancellu@arm.com> --- xen/arch/arm/include/asm/arm64/mpu.h | 2 ++ xen/arch/arm/include/asm/mm.h | 2 +- xen/arch/arm/mmu/setup.c | 2 +- xen/arch/arm/mpu/mm.c | 12 +++++++++ xen/arch/arm/mpu/setup.c | 40 ++++++++++++++++++++++++++++ xen/arch/arm/setup.c | 2 +- 6 files changed, 57 insertions(+), 3 deletions(-)