[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v3 29/52] xen/mpu: introduce a pair helper read_protection_region()/write_protection_region()
Each EL2 MPU protection region could be configured using PRBAR<n>_EL2 and PRLAR<n>_EL2. This commit introduces a pair helper read_protection_region()/ write_protection_region() to read/write EL2 MPU protection region. As explained in section G1.3.18 of the reference manual for AArch64v8R, a set of system register PRBAR<n>_EL2 and PRLAR<n>_EL2 provide access to the EL2 MPU region which is determined by the value of 'n' and PRSELR_EL2.REGION as PRSELR_EL2.REGION<7:4>:n(n = 0, 1, 2, ... , 15). For example to access regions from 16 to 31: - Set PRSELR_EL2 to 0b1xxxx - Region 16 configuration is accessible through PRBAR0_EL2 and PRLAR0_EL2 - Region 17 configuration is accessible through PRBAR1_EL2 and PRLAR1_EL2 - Region 18 configuration is accessible through PRBAR2_EL2 and PRLAR2_EL2 - ... - Region 31 configuration is accessible through PRBAR15_EL2 and PRLAR15_EL2 Signed-off-by: Penny Zheng <penny.zheng@xxxxxxx> Signed-off-by: Wei Chen <wei.chen@xxxxxxx> --- v3: - use WRITE_SYSREG()/READ_SYSREG() to avoid open-coding - move the selection part outside of the macro, So it could be outside of the switch and reduce the code generation. - introduce two helpers (one for the read operation, the other for the write operation). This would make the code a bit easier to read. - error out when the caller pass a number higher than 15 --- xen/arch/arm/include/asm/arm64/sysregs.h | 32 +++++ xen/arch/arm/mpu/mm.c | 173 +++++++++++++++++++++++ 2 files changed, 205 insertions(+) diff --git a/xen/arch/arm/include/asm/arm64/sysregs.h b/xen/arch/arm/include/asm/arm64/sysregs.h index a249a660a8..c8a679afdd 100644 --- a/xen/arch/arm/include/asm/arm64/sysregs.h +++ b/xen/arch/arm/include/asm/arm64/sysregs.h @@ -467,9 +467,41 @@ /* EL2 MPU Protection Region Base Address Register encode */ #define PRBAR_EL2 S3_4_C6_C8_0 +#define PRBAR0_EL2 S3_4_C6_C8_0 +#define PRBAR1_EL2 S3_4_C6_C8_4 +#define PRBAR2_EL2 S3_4_C6_C9_0 +#define PRBAR3_EL2 S3_4_C6_C9_4 +#define PRBAR4_EL2 S3_4_C6_C10_0 +#define PRBAR5_EL2 S3_4_C6_C10_4 +#define PRBAR6_EL2 S3_4_C6_C11_0 +#define PRBAR7_EL2 S3_4_C6_C11_4 +#define PRBAR8_EL2 S3_4_C6_C12_0 +#define PRBAR9_EL2 S3_4_C6_C12_4 +#define PRBAR10_EL2 S3_4_C6_C13_0 +#define PRBAR11_EL2 S3_4_C6_C13_4 +#define PRBAR12_EL2 S3_4_C6_C14_0 +#define PRBAR13_EL2 S3_4_C6_C14_4 +#define PRBAR14_EL2 S3_4_C6_C15_0 +#define PRBAR15_EL2 S3_4_C6_C15_4 /* EL2 MPU Protection Region Limit Address Register encode */ #define PRLAR_EL2 S3_4_C6_C8_1 +#define PRLAR0_EL2 S3_4_C6_C8_1 +#define PRLAR1_EL2 S3_4_C6_C8_5 +#define PRLAR2_EL2 S3_4_C6_C9_1 +#define PRLAR3_EL2 S3_4_C6_C9_5 +#define PRLAR4_EL2 S3_4_C6_C10_1 +#define PRLAR5_EL2 S3_4_C6_C10_5 +#define PRLAR6_EL2 S3_4_C6_C11_1 +#define PRLAR7_EL2 S3_4_C6_C11_5 +#define PRLAR8_EL2 S3_4_C6_C12_1 +#define PRLAR9_EL2 S3_4_C6_C12_5 +#define PRLAR10_EL2 S3_4_C6_C13_1 +#define PRLAR11_EL2 S3_4_C6_C13_5 +#define PRLAR12_EL2 S3_4_C6_C14_1 +#define PRLAR13_EL2 S3_4_C6_C14_5 +#define PRLAR14_EL2 S3_4_C6_C15_1 +#define PRLAR15_EL2 S3_4_C6_C15_5 /* MPU Protection Region Selection Register encode */ #define PRSELR_EL2 S3_4_C6_C2_1 diff --git a/xen/arch/arm/mpu/mm.c b/xen/arch/arm/mpu/mm.c index e06a6e5810..7b1b5d6e27 100644 --- a/xen/arch/arm/mpu/mm.c +++ b/xen/arch/arm/mpu/mm.c @@ -39,6 +39,23 @@ uint8_t __ro_after_init max_xen_mpumap; */ static DECLARE_BITMAP(xen_mpumap_mask, ARM_MAX_MPU_MEMORY_REGIONS); +/* Write a MPU protection region */ +#define WRITE_PROTECTION_REGION(pr, prbar_el2, prlar_el2) ({ \ + const pr_t *_pr = pr; \ + \ + WRITE_SYSREG(_pr->prbar.bits, prbar_el2); \ + WRITE_SYSREG(_pr->prlar.bits, prlar_el2); \ +}) + +/* Read a MPU protection region */ +#define READ_PROTECTION_REGION(prbar_el2, prlar_el2) ({ \ + pr_t _pr; \ + \ + _pr.prbar.bits = READ_SYSREG(prbar_el2); \ + _pr.prlar.bits = READ_SYSREG(prlar_el2); \ + _pr; \ +}) + void __init setup_mm_mappings(unsigned long boot_phys_offset) { unsigned int nr_regions = REGION_UART_SEL, i = 0; @@ -57,6 +74,162 @@ void __init setup_mm_mappings(unsigned long boot_phys_offset) set_bit(i, xen_mpumap_mask); } +/* + * Armv8-R AArch64 at most supports 255 MPU protection regions. + * See section G1.3.18 of the reference manual for Armv8-R AArch64, + * PRBAR<n>_EL2 and PRLAR<n>_EL2 provide access to the EL2 MPU region + * determined by the value of 'n' and PRSELR_EL2.REGION as + * PRSELR_EL2.REGION<7:4>:n(n = 0, 1, 2, ... , 15) + * For example to access regions from 16 to 31 (0b10000 to 0b11111): + * - Set PRSELR_EL2 to 0b1xxxx + * - Region 16 configuration is accessible through PRBAR0_EL2 and PRLAR0_EL2 + * - Region 17 configuration is accessible through PRBAR1_EL2 and PRLAR1_EL2 + * - Region 18 configuration is accessible through PRBAR2_EL2 and PRLAR2_EL2 + * - ... + * - Region 31 configuration is accessible through PRBAR15_EL2 and PRLAR15_EL2 + */ +/* + * Read EL2 MPU Protection Region. + * + * @pr_read: mpu protection region returned by read op. + * @sel: mpu protection region selector + */ +static void read_protection_region(pr_t *pr_read, uint8_t sel) +{ + /* + * Before accessing EL2 MPU region register PRBAR_EL2/PRLAR_EL2, + * make sure PRSELR_EL2 is set, as it determines which MPU region + * is selected. + */ + WRITE_SYSREG(sel, PRSELR_EL2); + isb(); + + switch ( sel & 0x0f ) + { + case 0: + *pr_read = READ_PROTECTION_REGION(PRBAR0_EL2, PRLAR0_EL2); + break; + case 1: + *pr_read = READ_PROTECTION_REGION(PRBAR1_EL2, PRLAR1_EL2); + break; + case 2: + *pr_read = READ_PROTECTION_REGION(PRBAR2_EL2, PRLAR2_EL2); + break; + case 3: + *pr_read = READ_PROTECTION_REGION(PRBAR3_EL2, PRLAR3_EL2); + break; + case 4: + *pr_read = READ_PROTECTION_REGION(PRBAR4_EL2, PRLAR4_EL2); + break; + case 5: + *pr_read = READ_PROTECTION_REGION(PRBAR5_EL2, PRLAR5_EL2); + break; + case 6: + *pr_read = READ_PROTECTION_REGION(PRBAR6_EL2, PRLAR6_EL2); + break; + case 7: + *pr_read = READ_PROTECTION_REGION(PRBAR7_EL2, PRLAR7_EL2); + break; + case 8: + *pr_read = READ_PROTECTION_REGION(PRBAR8_EL2, PRLAR8_EL2); + break; + case 9: + *pr_read = READ_PROTECTION_REGION(PRBAR9_EL2, PRLAR9_EL2); + break; + case 10: + *pr_read = READ_PROTECTION_REGION(PRBAR10_EL2, PRLAR10_EL2); + break; + case 11: + *pr_read = READ_PROTECTION_REGION(PRBAR11_EL2, PRLAR11_EL2); + break; + case 12: + *pr_read = READ_PROTECTION_REGION(PRBAR12_EL2, PRLAR12_EL2); + break; + case 13: + *pr_read = READ_PROTECTION_REGION(PRBAR13_EL2, PRLAR13_EL2); + break; + case 14: + *pr_read = READ_PROTECTION_REGION(PRBAR14_EL2, PRLAR14_EL2); + break; + case 15: + *pr_read = READ_PROTECTION_REGION(PRBAR15_EL2, PRLAR15_EL2); + break; + default: + panic("Unsupported selector %u\n", sel); + } +} + +/* + * Write EL2 MPU Protection Region. + * + * @pr_write: const mpu protection region passed through write op. + * @sel: mpu protection region selector + */ +static void write_protection_region(const pr_t *pr_write, uint8_t sel) +{ + /* + * Before accessing EL2 MPU region register PRBAR_EL2/PRLAR_EL2, + * make sure PRSELR_EL2 is set, as it determines which MPU region + * is selected. + */ + WRITE_SYSREG(sel, PRSELR_EL2); + isb(); + + switch ( sel & 0x0f ) + { + case 0: + WRITE_PROTECTION_REGION(pr_write, PRBAR0_EL2, PRLAR0_EL2); + break; + case 1: + WRITE_PROTECTION_REGION(pr_write, PRBAR1_EL2, PRLAR1_EL2); + break; + case 2: + WRITE_PROTECTION_REGION(pr_write, PRBAR2_EL2, PRLAR2_EL2); + break; + case 3: + WRITE_PROTECTION_REGION(pr_write, PRBAR3_EL2, PRLAR3_EL2); + break; + case 4: + WRITE_PROTECTION_REGION(pr_write, PRBAR4_EL2, PRLAR4_EL2); + break; + case 5: + WRITE_PROTECTION_REGION(pr_write, PRBAR5_EL2, PRLAR5_EL2); + break; + case 6: + WRITE_PROTECTION_REGION(pr_write, PRBAR6_EL2, PRLAR6_EL2); + break; + case 7: + WRITE_PROTECTION_REGION(pr_write, PRBAR7_EL2, PRLAR7_EL2); + break; + case 8: + WRITE_PROTECTION_REGION(pr_write, PRBAR8_EL2, PRLAR8_EL2); + break; + case 9: + WRITE_PROTECTION_REGION(pr_write, PRBAR9_EL2, PRLAR9_EL2); + break; + case 10: + WRITE_PROTECTION_REGION(pr_write, PRBAR10_EL2, PRLAR10_EL2); + break; + case 11: + WRITE_PROTECTION_REGION(pr_write, PRBAR11_EL2, PRLAR11_EL2); + break; + case 12: + WRITE_PROTECTION_REGION(pr_write, PRBAR12_EL2, PRLAR12_EL2); + break; + case 13: + WRITE_PROTECTION_REGION(pr_write, PRBAR13_EL2, PRLAR13_EL2); + break; + case 14: + WRITE_PROTECTION_REGION(pr_write, PRBAR14_EL2, PRLAR14_EL2); + break; + case 15: + WRITE_PROTECTION_REGION(pr_write, PRBAR15_EL2, PRLAR15_EL2); + break; + default: + panic("Unsupported selector %u\n", sel); + } +} + /* * Local variables: * mode: C -- 2.25.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |