[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v6 09/11] xen/arm64: create boot-time MPU protection regions
From: Penny Zheng <penny.zheng@xxxxxxx> Like boot-time page table in MMU system, we need a boot-time MPU protection region configuration in MPU system so Xen can fetch code and data from normal memory. This operation need to access Armv8-R MPU system registers, but these system registers are not supported in GCC version < 11. So we have to encode these Armv8-R MPU system registers in header file explicitly. As MMU system and MPU system have different functions to create the boot MMU/MPU data, this will introduce extra #ifdef in code flow, so we introduce a neutral name prepare_early_mappings to replace create_page_tables for MMU and MPU. Signed-off-by: Wei Chen <wei.chen@xxxxxxx> Signed-off-by: Penny Zheng <penny.zheng@xxxxxxx> --- xen/arch/arm/arm64/Makefile | 2 + xen/arch/arm/arm64/head.S | 13 ++-- xen/arch/arm/arm64/head_mmu.S | 4 +- xen/arch/arm/arm64/head_mpu.S | 70 +++++++++++++++++++ xen/arch/arm/include/asm/arm64/mpu.h | 13 ++++ xen/arch/arm/include/asm/arm64/sysregs.h | 89 ++++++++++++++++++++++++ 6 files changed, 185 insertions(+), 6 deletions(-) create mode 100644 xen/arch/arm/arm64/head_mpu.S create mode 100644 xen/arch/arm/include/asm/arm64/mpu.h diff --git a/xen/arch/arm/arm64/Makefile b/xen/arch/arm/arm64/Makefile index 22da2f54b5..438c9737ad 100644 --- a/xen/arch/arm/arm64/Makefile +++ b/xen/arch/arm/arm64/Makefile @@ -10,6 +10,8 @@ obj-y += entry.o obj-y += head.o ifneq ($(CONFIG_HAS_MPU),y) obj-y += head_mmu.o +else +obj-y += head_mpu.o endif obj-y += insn.o obj-$(CONFIG_LIVEPATCH) += livepatch.o diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S index d9a8da9120..6c1a5f74a1 100644 --- a/xen/arch/arm/arm64/head.S +++ b/xen/arch/arm/arm64/head.S @@ -79,12 +79,12 @@ * --------------------------- * * The requirements are: - * MMU = off, D-cache = off, I-cache = on or off, + * MMU/MPU = off, D-cache = off, I-cache = on or off, * x0 = physical address to the FDT blob. * * This must be the very first address in the loaded image. * It should be linked at XEN_VIRT_START, and loaded at any - * 4K-aligned address. All of text+data+bss must fit in 2MB, + * 4K-aligned address. All of text+data+bss must fit in 2MB, * or the initial pagetable code below will need adjustment. */ @@ -249,7 +249,12 @@ real_start_efi: bl check_cpu_mode bl cpu_init - bl create_page_tables + + /* + * Create boot memory management data, pagetable for MMU systems + * and protection regions for MPU systems. + */ + bl prepare_early_mappings bl enable_mmu /* We are still in the 1:1 mapping. Jump to the runtime Virtual Address. */ @@ -307,7 +312,7 @@ GLOBAL(init_secondary) #endif bl check_cpu_mode bl cpu_init - bl create_page_tables + bl prepare_early_mappings bl enable_mmu /* We are still in the 1:1 mapping. Jump to the runtime Virtual Address. */ diff --git a/xen/arch/arm/arm64/head_mmu.S b/xen/arch/arm/arm64/head_mmu.S index 1a3df81a38..fc64819a98 100644 --- a/xen/arch/arm/arm64/head_mmu.S +++ b/xen/arch/arm/arm64/head_mmu.S @@ -123,7 +123,7 @@ * * Clobbers x0 - x4 */ -ENTRY(create_page_tables) +ENTRY(prepare_early_mappings) /* Prepare the page-tables for mapping Xen */ ldr x0, =XEN_VIRT_START create_table_entry boot_pgtable, boot_first, x0, 0, x1, x2, x3 @@ -208,7 +208,7 @@ virtphys_clash: /* Identity map clashes with boot_third, which we cannot handle yet */ PRINT("- Unable to build boot page tables - virt and phys addresses clash. -\r\n") b fail -ENDPROC(create_page_tables) +ENDPROC(prepare_early_mappings) /* * Turn on the Data Cache and the MMU. The function will return on the 1:1 diff --git a/xen/arch/arm/arm64/head_mpu.S b/xen/arch/arm/arm64/head_mpu.S new file mode 100644 index 0000000000..f60611b556 --- /dev/null +++ b/xen/arch/arm/arm64/head_mpu.S @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Start-of-day code for an Armv8-R MPU system. + */ + +#include <asm/arm64/mpu.h> +#include <asm/page.h> +#include <asm/early_printk.h> + +/* + * From the requirements of head.S we know that Xen image should + * be linked at XEN_START_ADDRESS, and all of text + data + bss + * must fit in 2MB. On MPU systems, XEN_START_ADDRESS is also the + * address that Xen image should be loaded at. So for initial MPU + * regions setup, we use 2MB for Xen data memory to setup boot + * region, or the create boot regions code below will need adjustment. + */ +#define XEN_START_MEM_SIZE 0x200000 + +/* + * In boot stage, we will use 1 MPU region: + * Region#0: Normal memory for Xen text + data + bss (2MB) + */ +#define BOOT_NORMAL_REGION_IDX 0x0 + +/* MPU normal memory attributes. */ +#define PRBAR_NORMAL_MEM 0x30 /* SH=11 AP=00 XN=00 */ +#define PRLAR_NORMAL_MEM 0x0f /* NS=0 ATTR=111 EN=1 */ + +.macro write_pr, sel, prbar, prlar + msr PRSELR_EL2, \sel + dsb sy + msr PRBAR_EL2, \prbar + msr PRLAR_EL2, \prlar + dsb sy + isb +.endm + +.section .text.header, "ax", %progbits + +/* + * Static start-of-day EL2 MPU memory layout. + * + * It has a very simple structure, including: + * - 2MB normal memory mappings of xen at XEN_START_ADDRESS, which + * is the address where Xen was loaded by the bootloader. + */ +ENTRY(prepare_early_mappings) + /* Map Xen start memory to a normal memory region. */ + mov x0, #BOOT_NORMAL_REGION_IDX + ldr x1, =XEN_START_ADDRESS + and x1, x1, #MPU_REGION_MASK + mov x3, #PRBAR_NORMAL_MEM + orr x1, x1, x3 + + ldr x2, =XEN_START_ADDRESS + mov x3, #(XEN_START_MEM_SIZE - 1) + add x2, x2, x3 + and x2, x2, #MPU_REGION_MASK + mov x3, #PRLAR_NORMAL_MEM + orr x2, x2, x3 + + /* + * Write to MPU protection region: + * x0 for pr_sel, x1 for prbar x2 for prlar + */ + write_pr x0, x1, x2 + + ret +ENDPROC(prepare_early_mappings) diff --git a/xen/arch/arm/include/asm/arm64/mpu.h b/xen/arch/arm/include/asm/arm64/mpu.h new file mode 100644 index 0000000000..d209eef6db --- /dev/null +++ b/xen/arch/arm/include/asm/arm64/mpu.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * mpu.h: Arm Memory Protection Unit definitions. + */ + +#ifndef __ARM64_MPU_H__ +#define __ARM64_MPU_H__ + +#define MPU_REGION_SHIFT 6 +#define MPU_REGION_ALIGN (_AC(1, UL) << MPU_REGION_SHIFT) +#define MPU_REGION_MASK (~(MPU_REGION_ALIGN - 1)) + +#endif /* __ARM64_MPU_H__ */ diff --git a/xen/arch/arm/include/asm/arm64/sysregs.h b/xen/arch/arm/include/asm/arm64/sysregs.h index 54670084c3..a596042d6c 100644 --- a/xen/arch/arm/include/asm/arm64/sysregs.h +++ b/xen/arch/arm/include/asm/arm64/sysregs.h @@ -458,6 +458,95 @@ #define ZCR_ELx_LEN_SIZE 9 #define ZCR_ELx_LEN_MASK 0x1ff +/* System registers for AArch64 with PMSA */ +#ifdef CONFIG_HAS_MPU + +/* EL1 MPU Protection Region Base Address Register encode */ +#define PRBAR_EL1 S3_0_C6_C8_0 +#define PRBAR1_EL1 S3_0_C6_C8_4 +#define PRBAR2_EL1 S3_0_C6_C9_0 +#define PRBAR3_EL1 S3_0_C6_C9_4 +#define PRBAR4_EL1 S3_0_C6_C10_0 +#define PRBAR5_EL1 S3_0_C6_C10_4 +#define PRBAR6_EL1 S3_0_C6_C11_0 +#define PRBAR7_EL1 S3_0_C6_C11_4 +#define PRBAR8_EL1 S3_0_C6_C12_0 +#define PRBAR9_EL1 S3_0_C6_C12_4 +#define PRBAR10_EL1 S3_0_C6_C13_0 +#define PRBAR11_EL1 S3_0_C6_C13_4 +#define PRBAR12_EL1 S3_0_C6_C14_0 +#define PRBAR13_EL1 S3_0_C6_C14_4 +#define PRBAR14_EL1 S3_0_C6_C15_0 +#define PRBAR15_EL1 S3_0_C6_C15_4 + +/* EL1 MPU Protection Region Limit Address Register encode */ +#define PRLAR_EL1 S3_0_C6_C8_1 +#define PRLAR1_EL1 S3_0_C6_C8_5 +#define PRLAR2_EL1 S3_0_C6_C9_1 +#define PRLAR3_EL1 S3_0_C6_C9_5 +#define PRLAR4_EL1 S3_0_C6_C10_1 +#define PRLAR5_EL1 S3_0_C6_C10_5 +#define PRLAR6_EL1 S3_0_C6_C11_1 +#define PRLAR7_EL1 S3_0_C6_C11_5 +#define PRLAR8_EL1 S3_0_C6_C12_1 +#define PRLAR9_EL1 S3_0_C6_C12_5 +#define PRLAR10_EL1 S3_0_C6_C13_1 +#define PRLAR11_EL1 S3_0_C6_C13_5 +#define PRLAR12_EL1 S3_0_C6_C14_1 +#define PRLAR13_EL1 S3_0_C6_C14_5 +#define PRLAR14_EL1 S3_0_C6_C15_1 +#define PRLAR15_EL1 S3_0_C6_C15_5 + +/* EL2 MPU Protection Region Base Address Register encode */ +#define PRBAR_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 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 Enable Register encode */ +#define PRENR_EL1 S3_0_C6_C1_1 +#define PRENR_EL2 S3_4_C6_C1_1 + +/* MPU Protection Region Selection Register encode */ +#define PRSELR_EL1 S3_0_C6_C2_1 +#define PRSELR_EL2 S3_4_C6_C2_1 + +/* MPU Type registers encode */ +#define MPUIR_EL1 S3_0_C0_C0_4 +#define MPUIR_EL2 S3_4_C0_C0_4 + +#endif + /* Access to system registers */ #define WRITE_SYSREG64(v, name) do { \ -- 2.25.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |