[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] RE: [PATCH v6 09/11] xen/arm64: create boot-time MPU protection regions
Hi Julien > -----Original Message----- > From: Julien Grall <julien@xxxxxxx> > Sent: Monday, November 7, 2022 4:47 AM > To: Wei Chen <Wei.Chen@xxxxxxx>; xen-devel@xxxxxxxxxxxxxxxxxxxx > Cc: nd <nd@xxxxxxx>; Penny Zheng <Penny.Zheng@xxxxxxx>; Stefano > Stabellini <sstabellini@xxxxxxxxxx>; Bertrand Marquis > <Bertrand.Marquis@xxxxxxx>; Volodymyr Babchuk > <Volodymyr_Babchuk@xxxxxxxx> > Subject: Re: [PATCH v6 09/11] xen/arm64: create boot-time MPU protection > regions > > Hi Wei, > > On 04/11/2022 10:07, Wei Chen wrote: > > 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> > > If Penny is the original author, then her signed-off-by should be first. > > > --- > > 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, > > The double space after the final point was valid. This is fairly common to use > it and this is a spurious change. > > > > * 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. > > + */ > > head.S is now meant to be generic. So I would prefer if we keep comment > as generic as possible. IOW, anything after the first comma should be > dropped. > > > + 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 > > Coding style: > > /* SPDX ... */ > > > +/* > > + * Start-of-day code for an Armv8-R MPU system. > > + */ > > + > > +#include <asm/arm64/mpu.h> > > +#include <asm/page.h> > > +#include <asm/early_printk.h> > > Headers should be included in alphabetical order. > > > + > > +/* > > + * 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 > > It sounds like something that should be defined in the header. Also, I > think the size should be common between MPU and MMU. > > In [1], I was going to name it XEN_VIRT_SIZE. I would be OK to remove > "VIRT" in the name. > Thx and please, then I will replace it with XEN_SIZE > > + > > +/* > > + * In boot stage, we will use 1 MPU region: > > + * Region#0: Normal memory for Xen text + data + bss (2MB) > > + */ > > Are we only going to modify the MPU in head.S? If not, then I would > define the layout in config_mpu.h so there are a single point where you > can read how this works. > We will remap Xen in C codes in setup_mm(). The whole strategy is aligned with MMU: a very simple setup(map xen with the maximum size, 2M) at start-of-the-day, and a fit map in setup_mm. All the following variables will be only used at head_mpu.S. It is not very generic, later, when introducing MPU memory region management in C codes, we will define different macros for various memory attributes. > > +#define BOOT_NORMAL_REGION_IDX 0x0 > > + > > +/* MPU normal memory attributes. */ > > +#define PRBAR_NORMAL_MEM 0x30 /* SH=11 AP=00 XN=00 */ > > IIUC, this means that Xen will be mapped write-executable. Is this going > to be forever? If not, when can't we already mapped Xen properly? > No, this setup is the start-of-day setup, and will only last for a very short time. To be aligned with MMU system, in which L3 memory attributes is as follows: #define PT_MEM_L3 0xf7f /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=1 P=1 */ Xen shall be mapped read-only-executable here, and I will fix it. > > +#define PRLAR_NORMAL_MEM 0x0f /* NS=0 ATTR=111 EN=1 */ > > To me, it feels like this should be fined outside of head.S because this > could be re-used by other part of Xen. > It is like PT_MEM_L3 in head_mmu.S. It will be only used in compiler codes. MMU is defining macro like PAGE_HYPERVISOR_RW, for memory attributes management in C codes, and we intend to follow the same strategy. > > + > > +.macro write_pr, sel, prbar, prlar > > + msr PRSELR_EL2, \sel > > + dsb sy > > Is it really necessary to use "sy" here? Also, it would be good to > explain the logic. I.e. why do you need two dsb but only one isb? > > In fact, I was expecting an "isb" here than "dsb" to wait for the > completion of the instruction. > > > + 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. > > Missing details on the clobberred registers. > > > + */ > > +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 > > It looks like to me there are a potential for a macro to compute the > register. > > > + > > + ldr x2, =XEN_START_ADDRESS > > + mov x3, #(XEN_START_MEM_SIZE - 1) > > XEN_START_MEM_SIZE is the maximum size of Xen. IOW, Xen may be > smaller > and you will map memory that may not be part of Xen. Therefore, you > likely want to compute the real size to avoid mapping too much. > Later, in setup_mm we will map XEN components by components, such as, one MPU memory region for read-only-executable text section, one MPU memory region for read-only data section, etc, etc. So in there, XEN will be mapped fitly. IMHO, the mapping in compiler with maximum size of Xen is also what MMU does. > > > + add x2, x2, x > > + 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 > > This is not a very useful comment because this can be inferred from the > prototype of write_pr. What would be more interesting is to explain the > logic within this function in the same way we do in head.S and head_mmu.S. > > > + */ > > + 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 > > In the context of this patch, it would be better to only define the > registers you need. If you want to define all of them, then please > define them in a separate patch before this one. > > > @@ -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 > > The #ifdef here seems unnecessary. > > > + > > +/* 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 { \ > > Cheers, > > [1] https://lore.kernel.org/all/20221022150422.17707-2-julien@xxxxxxx/ > > -- > Julien Grall Cheers, -- Penny Zheng
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |