arm/mpu: Move the functions to arm64 specific files

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>
This commit is contained in:
Ayan Kumar Halder committed 2025-06-19 11:59:42 +01:00
1 parent 3c36a5a0df
commit 78afa06cf8
4 files changed
+132 -117

No files matched your search

+1
View File
@@ -1,3 +1,4 @@
obj-$(CONFIG_ARM_64) += arm64/
obj-$(CONFIG_ARM_32) += domain-page.o
obj-y += mm.o
obj-y += p2m.o
+1
View File
@@ -0,0 +1 @@
obj-y += mm.o
+130
View File
@@ -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:
*/
-117
View File
@@ -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);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.