All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/3] Enable R52 support for the first chunk of MPU support
@ 2025-06-19 11:31 Ayan Kumar Halder
  2025-06-19 11:31 ` [PATCH v5 1/3] arm/mpu: Move the functions to arm64 specific files Ayan Kumar Halder
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Ayan Kumar Halder @ 2025-06-19 11:31 UTC (permalink / raw)
  To: xen-devel
  Cc: Ayan Kumar Halder, Stefano Stabellini, Julien Grall,
	Bertrand Marquis, Michal Orzel, Volodymyr Babchuk

Hi all,

This patch serie enables R52 support based on Luca's series.
"[PATCH v6 0/6] First chunk for Arm R82 and MPU support".

Changes from :-

v1 - Changes mentioned in individual patches

v2 - Split "arm/mpu: Provide access to the MPU region from the C code"
into 4 patches.

v3 - Patches 1,2 are merged. Patch 3 is dropped.

v4 - Add R-b, A-b, T-b tags to the individual patches.

Ayan Kumar Halder (3):
  arm/mpu: Move the functions to arm64 specific files
  arm/mpu: Define arm32 system registers
  arm/mpu: Enable read/write to protection regions for arm32

 xen/arch/arm/include/asm/mpu.h        |   2 -
 xen/arch/arm/include/asm/mpu/cpregs.h |  68 ++++++++++-
 xen/arch/arm/mpu/Makefile             |   2 +
 xen/arch/arm/mpu/arm32/Makefile       |   1 +
 xen/arch/arm/mpu/arm32/mm.c           | 164 ++++++++++++++++++++++++++
 xen/arch/arm/mpu/arm64/Makefile       |   1 +
 xen/arch/arm/mpu/arm64/mm.c           | 130 ++++++++++++++++++++
 xen/arch/arm/mpu/mm.c                 | 119 -------------------
 8 files changed, 365 insertions(+), 122 deletions(-)
 create mode 100644 xen/arch/arm/mpu/arm32/Makefile
 create mode 100644 xen/arch/arm/mpu/arm32/mm.c
 create mode 100644 xen/arch/arm/mpu/arm64/Makefile
 create mode 100644 xen/arch/arm/mpu/arm64/mm.c

-- 
2.25.1



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v5 1/3] arm/mpu: Move the functions to arm64 specific files
  2025-06-19 11:31 [PATCH v5 0/3] Enable R52 support for the first chunk of MPU support Ayan Kumar Halder
@ 2025-06-19 11:31 ` Ayan Kumar Halder
  2025-06-19 11:31 ` [PATCH v5 2/3] arm/mpu: Define arm32 system registers Ayan Kumar Halder
  2025-06-19 11:31 ` [PATCH v5 3/3] arm/mpu: Enable read/write to protection regions for arm32 Ayan Kumar Halder
  2 siblings, 0 replies; 4+ messages in thread
From: Ayan Kumar Halder @ 2025-06-19 11:31 UTC (permalink / raw)
  To: xen-devel
  Cc: Ayan Kumar Halder, Stefano Stabellini, Julien Grall,
	Bertrand Marquis, Michal Orzel, Volodymyr Babchuk, Luca Fancellu

prepare_selector(), read_protection_region() and write_protection_region()
differ significantly between arm32 and arm64. Thus, move these functions
to their sub-arch specific folder.

Also the macro GENERATE_{WRITE/READ}_PR_REG_CASE are moved, in order to
keep them in the same file of their usage and improve readability.

Signed-off-by: Ayan Kumar Halder <ayan.kumar.halder@amd.com>
Reviewed-by: Luca Fancellu <luca.fancellu@arm.com>
Acked-by: Michal Orzel <michal.orzel@amd.com>
---
Changes from -

v2 - New patch introduced in v3.

v3 - 1. Add Luca's R-b.

v4 - 1. Reorder entries in mpu/Makefile alphabetically.
2. Add Michal's A-b.

 xen/arch/arm/mpu/Makefile       |   1 +
 xen/arch/arm/mpu/arm64/Makefile |   1 +
 xen/arch/arm/mpu/arm64/mm.c     | 130 ++++++++++++++++++++++++++++++++
 xen/arch/arm/mpu/mm.c           | 117 ----------------------------
 4 files changed, 132 insertions(+), 117 deletions(-)
 create mode 100644 xen/arch/arm/mpu/arm64/Makefile
 create mode 100644 xen/arch/arm/mpu/arm64/mm.c

diff --git a/xen/arch/arm/mpu/Makefile b/xen/arch/arm/mpu/Makefile
index 808e3e2cb3..09326a5248 100644
--- a/xen/arch/arm/mpu/Makefile
+++ b/xen/arch/arm/mpu/Makefile
@@ -1,3 +1,4 @@
+obj-$(CONFIG_ARM_64) += arm64/
 obj-$(CONFIG_ARM_32) += domain-page.o
 obj-y += mm.o
 obj-y += p2m.o
diff --git a/xen/arch/arm/mpu/arm64/Makefile b/xen/arch/arm/mpu/arm64/Makefile
new file mode 100644
index 0000000000..b18cec4836
--- /dev/null
+++ b/xen/arch/arm/mpu/arm64/Makefile
@@ -0,0 +1 @@
+obj-y += mm.o
diff --git a/xen/arch/arm/mpu/arm64/mm.c b/xen/arch/arm/mpu/arm64/mm.c
new file mode 100644
index 0000000000..ed643cad40
--- /dev/null
+++ b/xen/arch/arm/mpu/arm64/mm.c
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <xen/bug.h>
+#include <xen/types.h>
+#include <asm/mpu.h>
+#include <asm/sysregs.h>
+#include <asm/system.h>
+
+/*
+ * The following are needed for the cases: GENERATE_WRITE_PR_REG_CASE
+ * and GENERATE_READ_PR_REG_CASE with num==0
+ */
+#define PRBAR0_EL2 PRBAR_EL2
+#define PRLAR0_EL2 PRLAR_EL2
+
+#define PRBAR_EL2_(n)   PRBAR##n##_EL2
+#define PRLAR_EL2_(n)   PRLAR##n##_EL2
+
+#define GENERATE_WRITE_PR_REG_CASE(num, pr)                                 \
+    case num:                                                               \
+    {                                                                       \
+        WRITE_SYSREG(pr->prbar.bits & ~MPU_REGION_RES0, PRBAR_EL2_(num));   \
+        WRITE_SYSREG(pr->prlar.bits & ~MPU_REGION_RES0, PRLAR_EL2_(num));   \
+        break;                                                              \
+    }
+
+#define GENERATE_READ_PR_REG_CASE(num, pr)                      \
+    case num:                                                   \
+    {                                                           \
+        pr->prbar.bits = READ_SYSREG(PRBAR_EL2_(num));          \
+        pr->prlar.bits = READ_SYSREG(PRLAR_EL2_(num));          \
+        break;                                                  \
+    }
+
+/*
+ * Armv8-R supports direct access and indirect access to the MPU regions through
+ * registers:
+ *  - indirect access involves changing the MPU region selector, issuing an isb
+ *    barrier and accessing the selected region through specific registers
+ *  - direct access involves accessing specific registers that point to
+ *    specific MPU regions, without changing the selector, avoiding the use of
+ *    a barrier.
+ * For Arm64 the PR{B,L}AR_ELx (for n=0) and PR{B,L}AR<n>_ELx (for n=1..15) are
+ * used for the direct access to the regions selected by
+ * PRSELR_EL2.REGION<7:4>:n, so 16 regions can be directly accessed when the
+ * selector is a multiple of 16, giving access to all the supported memory
+ * regions.
+ */
+static void prepare_selector(uint8_t *sel)
+{
+    uint8_t cur_sel = *sel;
+
+    /*
+     * {read,write}_protection_region works using the direct access to the 0..15
+     * regions, so in order to save the isb() overhead, change the PRSELR_EL2
+     * only when needed, so when the upper 4 bits of the selector will change.
+     */
+    cur_sel &= 0xF0U;
+    if ( READ_SYSREG(PRSELR_EL2) != cur_sel )
+    {
+        WRITE_SYSREG(cur_sel, PRSELR_EL2);
+        isb();
+    }
+    *sel &= 0xFU;
+}
+
+void read_protection_region(pr_t *pr_read, uint8_t sel)
+{
+    prepare_selector(&sel);
+
+    switch ( sel )
+    {
+        GENERATE_READ_PR_REG_CASE(0, pr_read);
+        GENERATE_READ_PR_REG_CASE(1, pr_read);
+        GENERATE_READ_PR_REG_CASE(2, pr_read);
+        GENERATE_READ_PR_REG_CASE(3, pr_read);
+        GENERATE_READ_PR_REG_CASE(4, pr_read);
+        GENERATE_READ_PR_REG_CASE(5, pr_read);
+        GENERATE_READ_PR_REG_CASE(6, pr_read);
+        GENERATE_READ_PR_REG_CASE(7, pr_read);
+        GENERATE_READ_PR_REG_CASE(8, pr_read);
+        GENERATE_READ_PR_REG_CASE(9, pr_read);
+        GENERATE_READ_PR_REG_CASE(10, pr_read);
+        GENERATE_READ_PR_REG_CASE(11, pr_read);
+        GENERATE_READ_PR_REG_CASE(12, pr_read);
+        GENERATE_READ_PR_REG_CASE(13, pr_read);
+        GENERATE_READ_PR_REG_CASE(14, pr_read);
+        GENERATE_READ_PR_REG_CASE(15, pr_read);
+    default:
+        BUG(); /* Can't happen */
+        break;
+    }
+}
+
+void write_protection_region(const pr_t *pr_write, uint8_t sel)
+{
+    prepare_selector(&sel);
+
+    switch ( sel )
+    {
+        GENERATE_WRITE_PR_REG_CASE(0, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(1, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(2, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(3, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(4, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(5, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(6, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(7, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(8, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(9, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(10, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(11, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(12, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(13, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(14, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(15, pr_write);
+    default:
+        BUG(); /* Can't happen */
+        break;
+    }
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/mpu/mm.c b/xen/arch/arm/mpu/mm.c
index 3d37beab57..7ab68fc8c7 100644
--- a/xen/arch/arm/mpu/mm.c
+++ b/xen/arch/arm/mpu/mm.c
@@ -29,35 +29,6 @@ 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];
 
-#ifdef CONFIG_ARM_64
-/*
- * The following are needed for the cases: GENERATE_WRITE_PR_REG_CASE
- * and GENERATE_READ_PR_REG_CASE with num==0
- */
-#define PRBAR0_EL2 PRBAR_EL2
-#define PRLAR0_EL2 PRLAR_EL2
-
-#define PRBAR_EL2_(n)   PRBAR##n##_EL2
-#define PRLAR_EL2_(n)   PRLAR##n##_EL2
-
-#endif /* CONFIG_ARM_64 */
-
-#define GENERATE_WRITE_PR_REG_CASE(num, pr)                                 \
-    case num:                                                               \
-    {                                                                       \
-        WRITE_SYSREG(pr->prbar.bits & ~MPU_REGION_RES0, PRBAR_EL2_(num));   \
-        WRITE_SYSREG(pr->prlar.bits & ~MPU_REGION_RES0, PRLAR_EL2_(num));   \
-        break;                                                              \
-    }
-
-#define GENERATE_READ_PR_REG_CASE(num, pr)                      \
-    case num:                                                   \
-    {                                                           \
-        pr->prbar.bits = READ_SYSREG(PRBAR_EL2_(num));          \
-        pr->prlar.bits = READ_SYSREG(PRLAR_EL2_(num));          \
-        break;                                                  \
-    }
-
 static void __init __maybe_unused build_assertions(void)
 {
     /*
@@ -69,94 +40,6 @@ static void __init __maybe_unused build_assertions(void)
 }
 
 #ifdef CONFIG_ARM_64
-/*
- * Armv8-R supports direct access and indirect access to the MPU regions through
- * registers:
- *  - indirect access involves changing the MPU region selector, issuing an isb
- *    barrier and accessing the selected region through specific registers
- *  - direct access involves accessing specific registers that point to
- *    specific MPU regions, without changing the selector, avoiding the use of
- *    a barrier.
- * For Arm64 the PR{B,L}AR_ELx (for n=0) and PR{B,L}AR<n>_ELx (for n=1..15) are
- * used for the direct access to the regions selected by
- * PRSELR_EL2.REGION<7:4>:n, so 16 regions can be directly accessed when the
- * selector is a multiple of 16, giving access to all the supported memory
- * regions.
- */
-static void prepare_selector(uint8_t *sel)
-{
-    uint8_t cur_sel = *sel;
-
-    /*
-     * {read,write}_protection_region works using the direct access to the 0..15
-     * regions, so in order to save the isb() overhead, change the PRSELR_EL2
-     * only when needed, so when the upper 4 bits of the selector will change.
-     */
-    cur_sel &= 0xF0U;
-    if ( READ_SYSREG(PRSELR_EL2) != cur_sel )
-    {
-        WRITE_SYSREG(cur_sel, PRSELR_EL2);
-        isb();
-    }
-    *sel &= 0xFU;
-}
-
-void read_protection_region(pr_t *pr_read, uint8_t sel)
-{
-    prepare_selector(&sel);
-
-    switch ( sel )
-    {
-        GENERATE_READ_PR_REG_CASE(0, pr_read);
-        GENERATE_READ_PR_REG_CASE(1, pr_read);
-        GENERATE_READ_PR_REG_CASE(2, pr_read);
-        GENERATE_READ_PR_REG_CASE(3, pr_read);
-        GENERATE_READ_PR_REG_CASE(4, pr_read);
-        GENERATE_READ_PR_REG_CASE(5, pr_read);
-        GENERATE_READ_PR_REG_CASE(6, pr_read);
-        GENERATE_READ_PR_REG_CASE(7, pr_read);
-        GENERATE_READ_PR_REG_CASE(8, pr_read);
-        GENERATE_READ_PR_REG_CASE(9, pr_read);
-        GENERATE_READ_PR_REG_CASE(10, pr_read);
-        GENERATE_READ_PR_REG_CASE(11, pr_read);
-        GENERATE_READ_PR_REG_CASE(12, pr_read);
-        GENERATE_READ_PR_REG_CASE(13, pr_read);
-        GENERATE_READ_PR_REG_CASE(14, pr_read);
-        GENERATE_READ_PR_REG_CASE(15, pr_read);
-    default:
-        BUG(); /* Can't happen */
-        break;
-    }
-}
-
-void write_protection_region(const pr_t *pr_write, uint8_t sel)
-{
-    prepare_selector(&sel);
-
-    switch ( sel )
-    {
-        GENERATE_WRITE_PR_REG_CASE(0, pr_write);
-        GENERATE_WRITE_PR_REG_CASE(1, pr_write);
-        GENERATE_WRITE_PR_REG_CASE(2, pr_write);
-        GENERATE_WRITE_PR_REG_CASE(3, pr_write);
-        GENERATE_WRITE_PR_REG_CASE(4, pr_write);
-        GENERATE_WRITE_PR_REG_CASE(5, pr_write);
-        GENERATE_WRITE_PR_REG_CASE(6, pr_write);
-        GENERATE_WRITE_PR_REG_CASE(7, pr_write);
-        GENERATE_WRITE_PR_REG_CASE(8, pr_write);
-        GENERATE_WRITE_PR_REG_CASE(9, pr_write);
-        GENERATE_WRITE_PR_REG_CASE(10, pr_write);
-        GENERATE_WRITE_PR_REG_CASE(11, pr_write);
-        GENERATE_WRITE_PR_REG_CASE(12, pr_write);
-        GENERATE_WRITE_PR_REG_CASE(13, pr_write);
-        GENERATE_WRITE_PR_REG_CASE(14, pr_write);
-        GENERATE_WRITE_PR_REG_CASE(15, pr_write);
-    default:
-        BUG(); /* Can't happen */
-        break;
-    }
-}
-
 pr_t pr_of_addr(paddr_t base, paddr_t limit, unsigned int flags)
 {
     unsigned int attr_idx = PAGE_AI_MASK(flags);
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v5 2/3] arm/mpu: Define arm32 system registers
  2025-06-19 11:31 [PATCH v5 0/3] Enable R52 support for the first chunk of MPU support Ayan Kumar Halder
  2025-06-19 11:31 ` [PATCH v5 1/3] arm/mpu: Move the functions to arm64 specific files Ayan Kumar Halder
@ 2025-06-19 11:31 ` Ayan Kumar Halder
  2025-06-19 11:31 ` [PATCH v5 3/3] arm/mpu: Enable read/write to protection regions for arm32 Ayan Kumar Halder
  2 siblings, 0 replies; 4+ messages in thread
From: Ayan Kumar Halder @ 2025-06-19 11:31 UTC (permalink / raw)
  To: xen-devel
  Cc: Ayan Kumar Halder, Stefano Stabellini, Julien Grall,
	Bertrand Marquis, Michal Orzel, Volodymyr Babchuk, Hari Limaye

Fix the definition for HPRLAR.
Define the base/limit address registers to access the first 32 protection
regions.

Signed-off-by: Ayan Kumar Halder <ayan.kumar.halder@amd.com>
Reviewed-by: Hari Limaye <hari.limaye@arm.com>
Acked-by: Michal Orzel <michal.orzel@amd.com>
---
Changes from :-

v2 - New patch introduced in v3 (Extracted from 
"arm/mpu: Provide access to the MPU region from the C code").

v3 - Add Hari's R-b.

v4 - Add Michal's A-b.

 xen/arch/arm/include/asm/mpu/cpregs.h | 68 ++++++++++++++++++++++++++-
 1 file changed, 67 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/include/asm/mpu/cpregs.h b/xen/arch/arm/include/asm/mpu/cpregs.h
index d5cd0e04d5..bb15e02df6 100644
--- a/xen/arch/arm/include/asm/mpu/cpregs.h
+++ b/xen/arch/arm/include/asm/mpu/cpregs.h
@@ -9,7 +9,73 @@
 /* CP15 CR6: MPU Protection Region Base/Limit/Select Address Register */
 #define HPRSELR         p15,4,c6,c2,1
 #define HPRBAR          p15,4,c6,c3,0
-#define HPRLAR          p15,4,c6,c8,1
+#define HPRLAR          p15,4,c6,c3,1
+
+/* CP15 CR6: MPU Protection Region Base/Limit Address Register */
+#define HPRBAR0         p15,4,c6,c8,0
+#define HPRLAR0         p15,4,c6,c8,1
+#define HPRBAR1         p15,4,c6,c8,4
+#define HPRLAR1         p15,4,c6,c8,5
+#define HPRBAR2         p15,4,c6,c9,0
+#define HPRLAR2         p15,4,c6,c9,1
+#define HPRBAR3         p15,4,c6,c9,4
+#define HPRLAR3         p15,4,c6,c9,5
+#define HPRBAR4         p15,4,c6,c10,0
+#define HPRLAR4         p15,4,c6,c10,1
+#define HPRBAR5         p15,4,c6,c10,4
+#define HPRLAR5         p15,4,c6,c10,5
+#define HPRBAR6         p15,4,c6,c11,0
+#define HPRLAR6         p15,4,c6,c11,1
+#define HPRBAR7         p15,4,c6,c11,4
+#define HPRLAR7         p15,4,c6,c11,5
+#define HPRBAR8         p15,4,c6,c12,0
+#define HPRLAR8         p15,4,c6,c12,1
+#define HPRBAR9         p15,4,c6,c12,4
+#define HPRLAR9         p15,4,c6,c12,5
+#define HPRBAR10        p15,4,c6,c13,0
+#define HPRLAR10        p15,4,c6,c13,1
+#define HPRBAR11        p15,4,c6,c13,4
+#define HPRLAR11        p15,4,c6,c13,5
+#define HPRBAR12        p15,4,c6,c14,0
+#define HPRLAR12        p15,4,c6,c14,1
+#define HPRBAR13        p15,4,c6,c14,4
+#define HPRLAR13        p15,4,c6,c14,5
+#define HPRBAR14        p15,4,c6,c15,0
+#define HPRLAR14        p15,4,c6,c15,1
+#define HPRBAR15        p15,4,c6,c15,4
+#define HPRLAR15        p15,4,c6,c15,5
+#define HPRBAR16        p15,5,c6,c8,0
+#define HPRLAR16        p15,5,c6,c8,1
+#define HPRBAR17        p15,5,c6,c8,4
+#define HPRLAR17        p15,5,c6,c8,5
+#define HPRBAR18        p15,5,c6,c9,0
+#define HPRLAR18        p15,5,c6,c9,1
+#define HPRBAR19        p15,5,c6,c9,4
+#define HPRLAR19        p15,5,c6,c9,5
+#define HPRBAR20        p15,5,c6,c10,0
+#define HPRLAR20        p15,5,c6,c10,1
+#define HPRBAR21        p15,5,c6,c10,4
+#define HPRLAR21        p15,5,c6,c10,5
+#define HPRBAR22        p15,5,c6,c11,0
+#define HPRLAR22        p15,5,c6,c11,1
+#define HPRBAR23        p15,5,c6,c11,4
+#define HPRLAR23        p15,5,c6,c11,5
+#define HPRBAR24        p15,5,c6,c12,0
+#define HPRLAR24        p15,5,c6,c12,1
+#define HPRBAR25        p15,5,c6,c12,4
+#define HPRLAR25        p15,5,c6,c12,5
+#define HPRBAR26        p15,5,c6,c13,0
+#define HPRLAR26        p15,5,c6,c13,1
+#define HPRBAR27        p15,5,c6,c13,4
+#define HPRLAR27        p15,5,c6,c13,5
+#define HPRBAR28        p15,5,c6,c14,0
+#define HPRLAR28        p15,5,c6,c14,1
+#define HPRBAR29        p15,5,c6,c14,4
+#define HPRLAR29        p15,5,c6,c14,5
+#define HPRBAR30        p15,5,c6,c15,0
+#define HPRLAR30        p15,5,c6,c15,1
+#define HPRBAR31        p15,5,c6,c15,4
+#define HPRLAR31        p15,5,c6,c15,5
 
 /* Aliases of AArch64 names for use in common code */
 #ifdef CONFIG_ARM_32
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v5 3/3] arm/mpu: Enable read/write to protection regions for arm32
  2025-06-19 11:31 [PATCH v5 0/3] Enable R52 support for the first chunk of MPU support Ayan Kumar Halder
  2025-06-19 11:31 ` [PATCH v5 1/3] arm/mpu: Move the functions to arm64 specific files Ayan Kumar Halder
  2025-06-19 11:31 ` [PATCH v5 2/3] arm/mpu: Define arm32 system registers Ayan Kumar Halder
@ 2025-06-19 11:31 ` Ayan Kumar Halder
  2 siblings, 0 replies; 4+ messages in thread
From: Ayan Kumar Halder @ 2025-06-19 11:31 UTC (permalink / raw)
  To: xen-devel
  Cc: Ayan Kumar Halder, Stefano Stabellini, Julien Grall,
	Bertrand Marquis, Michal Orzel, Volodymyr Babchuk, Luca Fancellu,
	Hari Limaye, Julien Grall

Define prepare_selector(), read_protection_region() and
write_protection_region() for arm32. Also, define
GENERATE_{READ/WRITE}_PR_REG_OTHERS to access MPU regions from 32 to 254.

Enable pr_{get/set}_{base/limit}(), region_is_valid() for arm32.
Enable pr_of_addr() for arm32.

The maximum number of regions supported is 255 (which corresponds to the
maximum value in HMPUIR).

Signed-off-by: Ayan Kumar Halder <ayan.kumar.halder@amd.com>
Reviewed-by: Luca Fancellu <luca.fancellu@arm.com>
Reviewed-by: Hari Limaye <hari.limaye@arm.com>
Tested-by: Hari Limaye <hari.limaye@arm.com>
Acked-by: Julien Grall <jgrall@amazon.com>
---
Changes from :-

v1 - 1. Enable write_protection_region() for aarch32.

v2 - 1. Enable access to protection regions from 0 - 255.

v3 - 1. The maximum number of regions is 255. Thus, regions numbered 0 - 254
are supported.

2. prepare_selector() is modified to ensure HPRSELR is written when accessing
any region beyond 31 and the current value differs from the region number to
be accessed.

v4 - 1. Add R-b, A-b and T-b.

 xen/arch/arm/include/asm/mpu.h  |   2 -
 xen/arch/arm/mpu/Makefile       |   1 +
 xen/arch/arm/mpu/arm32/Makefile |   1 +
 xen/arch/arm/mpu/arm32/mm.c     | 164 ++++++++++++++++++++++++++++++++
 xen/arch/arm/mpu/mm.c           |   2 -
 5 files changed, 166 insertions(+), 4 deletions(-)
 create mode 100644 xen/arch/arm/mpu/arm32/Makefile
 create mode 100644 xen/arch/arm/mpu/arm32/mm.c

diff --git a/xen/arch/arm/include/asm/mpu.h b/xen/arch/arm/include/asm/mpu.h
index 8f06ddac0f..63560c613b 100644
--- a/xen/arch/arm/include/asm/mpu.h
+++ b/xen/arch/arm/include/asm/mpu.h
@@ -25,7 +25,6 @@
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_ARM_64
 /*
  * Set base address of MPU protection region.
  *
@@ -85,7 +84,6 @@ static inline bool region_is_valid(const pr_t *pr)
 {
     return pr->prlar.reg.en;
 }
-#endif /* CONFIG_ARM_64 */
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/xen/arch/arm/mpu/Makefile b/xen/arch/arm/mpu/Makefile
index 09326a5248..50f8fe4326 100644
--- a/xen/arch/arm/mpu/Makefile
+++ b/xen/arch/arm/mpu/Makefile
@@ -1,3 +1,4 @@
+obj-$(CONFIG_ARM_32) += arm32/
 obj-$(CONFIG_ARM_64) += arm64/
 obj-$(CONFIG_ARM_32) += domain-page.o
 obj-y += mm.o
diff --git a/xen/arch/arm/mpu/arm32/Makefile b/xen/arch/arm/mpu/arm32/Makefile
new file mode 100644
index 0000000000..b18cec4836
--- /dev/null
+++ b/xen/arch/arm/mpu/arm32/Makefile
@@ -0,0 +1 @@
+obj-y += mm.o
diff --git a/xen/arch/arm/mpu/arm32/mm.c b/xen/arch/arm/mpu/arm32/mm.c
new file mode 100644
index 0000000000..a4673c3511
--- /dev/null
+++ b/xen/arch/arm/mpu/arm32/mm.c
@@ -0,0 +1,164 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <xen/bug.h>
+#include <xen/types.h>
+#include <asm/mpu.h>
+#include <asm/sysregs.h>
+#include <asm/system.h>
+
+#define GENERATE_WRITE_PR_REG_CASE(num, pr)               \
+    case num:                                             \
+    {                                                     \
+        WRITE_SYSREG(pr->prbar.bits, HPRBAR##num);        \
+        WRITE_SYSREG(pr->prlar.bits, HPRLAR##num);        \
+        break;                                            \
+    }
+
+#define GENERATE_WRITE_PR_REG_OTHERS(num, pr)             \
+    case num:                                             \
+    {                                                     \
+        WRITE_SYSREG(pr->prbar.bits, HPRBAR);             \
+        WRITE_SYSREG(pr->prlar.bits, HPRLAR);             \
+        break;                                            \
+    }
+
+#define GENERATE_READ_PR_REG_CASE(num, pr)                \
+    case num:                                             \
+    {                                                     \
+        pr->prbar.bits = READ_SYSREG(HPRBAR##num);        \
+        pr->prlar.bits = READ_SYSREG(HPRLAR##num);        \
+        break;                                            \
+    }
+
+#define GENERATE_READ_PR_REG_OTHERS(num, pr)              \
+    case num:                                             \
+    {                                                     \
+        pr->prbar.bits = READ_SYSREG(HPRBAR);             \
+        pr->prlar.bits = READ_SYSREG(HPRLAR);             \
+        break;                                            \
+    }
+
+/*
+ * Armv8-R supports direct access and indirect access to the MPU regions through
+ * registers:
+ *  - indirect access involves changing the MPU region selector, issuing an isb
+ *    barrier and accessing the selected region through specific registers
+ *  - direct access involves accessing specific registers that point to
+ *    specific MPU regions, without changing the selector, avoiding the use of
+ *    a barrier.
+ * For Arm32 the HPR{B,L}AR<n> (for n=0..31) are used for direct access to the
+ * first 32 MPU regions.
+ * For MPU regions numbered 32..254, one needs to set the region number in
+ * HPRSELR, followed by configuring HPR{B,L}AR.
+ */
+static void prepare_selector(uint8_t *sel)
+{
+    uint8_t cur_sel = *sel;
+    /* The top 24 bits of HPRSELR are RES0. */
+    uint8_t val = READ_SYSREG(HPRSELR) & 0xff;
+
+    if ( (cur_sel > 31) && (cur_sel != val) )
+    {
+        WRITE_SYSREG(cur_sel, HPRSELR);
+        isb();
+    }
+}
+
+void read_protection_region(pr_t *pr_read, uint8_t sel)
+{
+    prepare_selector(&sel);
+
+    switch ( sel )
+    {
+        GENERATE_READ_PR_REG_CASE(0, pr_read);
+        GENERATE_READ_PR_REG_CASE(1, pr_read);
+        GENERATE_READ_PR_REG_CASE(2, pr_read);
+        GENERATE_READ_PR_REG_CASE(3, pr_read);
+        GENERATE_READ_PR_REG_CASE(4, pr_read);
+        GENERATE_READ_PR_REG_CASE(5, pr_read);
+        GENERATE_READ_PR_REG_CASE(6, pr_read);
+        GENERATE_READ_PR_REG_CASE(7, pr_read);
+        GENERATE_READ_PR_REG_CASE(8, pr_read);
+        GENERATE_READ_PR_REG_CASE(9, pr_read);
+        GENERATE_READ_PR_REG_CASE(10, pr_read);
+        GENERATE_READ_PR_REG_CASE(11, pr_read);
+        GENERATE_READ_PR_REG_CASE(12, pr_read);
+        GENERATE_READ_PR_REG_CASE(13, pr_read);
+        GENERATE_READ_PR_REG_CASE(14, pr_read);
+        GENERATE_READ_PR_REG_CASE(15, pr_read);
+        GENERATE_READ_PR_REG_CASE(16, pr_read);
+        GENERATE_READ_PR_REG_CASE(17, pr_read);
+        GENERATE_READ_PR_REG_CASE(18, pr_read);
+        GENERATE_READ_PR_REG_CASE(19, pr_read);
+        GENERATE_READ_PR_REG_CASE(20, pr_read);
+        GENERATE_READ_PR_REG_CASE(21, pr_read);
+        GENERATE_READ_PR_REG_CASE(22, pr_read);
+        GENERATE_READ_PR_REG_CASE(23, pr_read);
+        GENERATE_READ_PR_REG_CASE(24, pr_read);
+        GENERATE_READ_PR_REG_CASE(25, pr_read);
+        GENERATE_READ_PR_REG_CASE(26, pr_read);
+        GENERATE_READ_PR_REG_CASE(27, pr_read);
+        GENERATE_READ_PR_REG_CASE(28, pr_read);
+        GENERATE_READ_PR_REG_CASE(29, pr_read);
+        GENERATE_READ_PR_REG_CASE(30, pr_read);
+        GENERATE_READ_PR_REG_CASE(31, pr_read);
+        GENERATE_READ_PR_REG_OTHERS(32 ... 254, pr_read);
+    default:
+        BUG(); /* Can't happen */
+        break;
+    }
+}
+
+void write_protection_region(const pr_t *pr_write, uint8_t sel)
+{
+    prepare_selector(&sel);
+
+    switch ( sel )
+    {
+        GENERATE_WRITE_PR_REG_CASE(0, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(1, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(2, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(3, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(4, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(5, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(6, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(7, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(8, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(9, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(10, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(11, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(12, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(13, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(14, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(15, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(16, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(17, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(18, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(19, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(20, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(21, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(22, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(23, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(24, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(25, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(26, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(27, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(28, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(29, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(30, pr_write);
+        GENERATE_WRITE_PR_REG_CASE(31, pr_write);
+        GENERATE_WRITE_PR_REG_OTHERS(32 ... 254, pr_write);
+    default:
+        BUG(); /* Can't happen */
+        break;
+    }
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/mpu/mm.c b/xen/arch/arm/mpu/mm.c
index 7ab68fc8c7..ccfb37a67b 100644
--- a/xen/arch/arm/mpu/mm.c
+++ b/xen/arch/arm/mpu/mm.c
@@ -39,7 +39,6 @@ static void __init __maybe_unused build_assertions(void)
     BUILD_BUG_ON(PAGE_SIZE != SZ_4K);
 }
 
-#ifdef CONFIG_ARM_64
 pr_t pr_of_addr(paddr_t base, paddr_t limit, unsigned int flags)
 {
     unsigned int attr_idx = PAGE_AI_MASK(flags);
@@ -110,7 +109,6 @@ pr_t pr_of_addr(paddr_t base, paddr_t limit, unsigned int flags)
 
     return region;
 }
-#endif /* CONFIG_ARM_64 */
 
 void __init setup_mm(void)
 {
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-06-19 11:32 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-19 11:31 [PATCH v5 0/3] Enable R52 support for the first chunk of MPU support Ayan Kumar Halder
2025-06-19 11:31 ` [PATCH v5 1/3] arm/mpu: Move the functions to arm64 specific files Ayan Kumar Halder
2025-06-19 11:31 ` [PATCH v5 2/3] arm/mpu: Define arm32 system registers Ayan Kumar Halder
2025-06-19 11:31 ` [PATCH v5 3/3] arm/mpu: Enable read/write to protection regions for arm32 Ayan Kumar Halder

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.