|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] RE: [PATCH v2 11/40] xen/mpu: build up start-of-day Xen MPU memory region map
Hi Ayan
> -----Original Message-----
> From: Ayan Kumar Halder <ayankuma@xxxxxxx>
> Sent: Thursday, January 19, 2023 6:19 PM
> To: xen-devel@xxxxxxxxxxxxxxxxxxxx
> Cc: Wei Chen <Wei.Chen@xxxxxxx>; Penny Zheng
> <Penny.Zheng@xxxxxxx>; Stefano Stabellini <sstabellini@xxxxxxxxxx>; Julien
> Grall <julien@xxxxxxx>; Bertrand Marquis <Bertrand.Marquis@xxxxxxx>;
> Volodymyr_Babchuk@xxxxxxxx
> Subject: Re: [PATCH v2 11/40] xen/mpu: build up start-of-day Xen MPU
> memory region map
>
>
> On 13/01/2023 05:28, Penny Zheng wrote:
> > CAUTION: This message has originated from an External Source. Please use
> proper judgment and caution when opening attachments, clicking links, or
> responding to this email.
> >
> >
> > From: Penny Zheng <penny.zheng@xxxxxxx>
> >
> > The start-of-day Xen MPU memory region layout shall be like as follows:
> >
> > xen_mpumap[0] : Xen text
> > xen_mpumap[1] : Xen read-only data
> > xen_mpumap[2] : Xen read-only after init data xen_mpumap[3] : Xen
> > read-write data xen_mpumap[4] : Xen BSS ......
> > xen_mpumap[max_xen_mpumap - 2]: Xen init data
> > xen_mpumap[max_xen_mpumap - 1]: Xen init text
> >
> > max_xen_mpumap refers to the number of regions supported by the EL2
> MPU.
> > The layout shall be compliant with what we describe in xen.lds.S, or
> > the codes need adjustment.
> >
> > As MMU system and MPU system have different functions to create the
> > boot MMU/MPU memory management data, instead of introducing extra
> > #ifdef in main code flow, we introduce a neutral name
> > prepare_early_mappings for both, and also to replace create_page_tables
> for MMU.
> >
> > Signed-off-by: Penny Zheng <penny.zheng@xxxxxxx>
> > Signed-off-by: Wei Chen <wei.chen@xxxxxxx>
> > ---
> > xen/arch/arm/arm64/Makefile | 2 +
> > xen/arch/arm/arm64/head.S | 17 +-
> > xen/arch/arm/arm64/head_mmu.S | 4 +-
> > xen/arch/arm/arm64/head_mpu.S | 323
> +++++++++++++++++++++++
> > xen/arch/arm/include/asm/arm64/mpu.h | 63 +++++
> > xen/arch/arm/include/asm/arm64/sysregs.h | 49 ++++
> > xen/arch/arm/mm_mpu.c | 48 ++++
> > xen/arch/arm/xen.lds.S | 4 +
> > 8 files changed, 502 insertions(+), 8 deletions(-)
> > create mode 100644 xen/arch/arm/arm64/head_mpu.S
> > create mode 100644 xen/arch/arm/include/asm/arm64/mpu.h
> > create mode 100644 xen/arch/arm/mm_mpu.c
> >
> > 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
> > 782bd1f94c..145e3d53dc 100644
> > --- a/xen/arch/arm/arm64/head.S
> > +++ b/xen/arch/arm/arm64/head.S
> > @@ -68,9 +68,9 @@
> > * x24 -
> > * x25 -
> > * x26 - skip_zero_bss (boot cpu only)
> > - * x27 -
> > - * x28 -
> > - * x29 -
> > + * x27 - region selector (mpu only)
> > + * x28 - prbar (mpu only)
> > + * x29 - prlar (mpu only)
> > * x30 - lr
> > */
> >
> > @@ -82,7 +82,7 @@
> > * ---------------------------
> > *
> > * 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.
> > @@ -252,7 +252,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 memory 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. */ @@ -310,7 +315,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 6ff13c751c..2346f755df
> 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)
>
> NIT:- Can this renaming be done in a separate patch of its own (before this
> patch).
>
Yay, you're right. I'll put it in different commit.
> So that this patch can be only about the new functionality introduced.
>
> >
> > /*
> > * 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..0b97ce4646
> > --- /dev/null
> > +++ b/xen/arch/arm/arm64/head_mpu.S
> > @@ -0,0 +1,323 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Start-of-day code for an Armv8-R AArch64 MPU system.
> > + */
> > +
> > +#include <asm/arm64/mpu.h>
> > +#include <asm/early_printk.h>
> > +#include <asm/page.h>
> > +
> > +/*
> > + * One entry in Xen MPU memory region mapping table(xen_mpumap) is
> a
> > +structure
> > + * of pr_t, which is 16-bytes size, so the entry offset is the order of 4.
> > + */
> NIT :- It would be good to quote Arm ARM from which can be referred for
> the definitions.
> > +#define MPU_ENTRY_SHIFT 0x4
> > +
> > +#define REGION_SEL_MASK 0xf
> > +
> > +#define REGION_TEXT_PRBAR 0x38 /* SH=11 AP=10 XN=00 */
> > +#define REGION_RO_PRBAR 0x3A /* SH=11 AP=10 XN=10 */
> > +#define REGION_DATA_PRBAR 0x32 /* SH=11 AP=00 XN=10 */
> > +
> > +#define REGION_NORMAL_PRLAR 0x0f /* NS=0 ATTR=111 EN=1 */
> > +
> > +/*
> > + * Macro to round up the section address to be PAGE_SIZE aligned
> > + * Each section(e.g. .text, .data, etc) in xen.lds.S is page-aligned,
> > + * which is usually guarded with ". = ALIGN(PAGE_SIZE)" in the head,
> > + * or in the end
> > + */
> > +.macro roundup_section, xb
> > + add \xb, \xb, #(PAGE_SIZE-1)
> > + and \xb, \xb, #PAGE_MASK
> > +.endm
> > +
> > +/*
> > + * Macro to create a new MPU memory region entry, which is a
> > +structure
> > + * of pr_t, in \prmap.
> > + *
> > + * Inputs:
> > + * prmap: mpu memory region map table symbol
> > + * sel: region selector
> > + * prbar: preserve value for PRBAR_EL2
> > + * prlar preserve value for PRLAR_EL2
> > + *
> > + * Clobbers \tmp1, \tmp2
> > + *
> > + */
> > +.macro create_mpu_entry prmap, sel, prbar, prlar, tmp1, tmp2
> > + mov \tmp2, \sel
> > + lsl \tmp2, \tmp2, #MPU_ENTRY_SHIFT
> > + adr_l \tmp1, \prmap
> > + /* Write the first 8 bytes(prbar_t) of pr_t */
> > + str \prbar, [\tmp1, \tmp2]
> > +
> > + add \tmp2, \tmp2, #8
> > + /* Write the last 8 bytes(prlar_t) of pr_t */
> > + str \prlar, [\tmp1, \tmp2]
> > +.endm
> > +
> > +/*
> > + * Macro to store the maximum number of regions supported by the EL2
> > +MPU
> > + * in max_xen_mpumap, which is identified by MPUIR_EL2.
> > + *
> > + * Outputs:
> > + * nr_regions: preserve the maximum number of regions supported by
> > +the EL2 MPU
> > + *
> > + * Clobbers \tmp1
> > + *
> > + */
> > +.macro read_max_el2_regions, nr_regions, tmp1
> > + load_paddr \tmp1, max_xen_mpumap
> > + mrs \nr_regions, MPUIR_EL2
> > + isb
> > + str \nr_regions, [\tmp1]
> > +.endm
> > +
> > +/*
> > + * Macro to prepare and set a MPU memory region
> > + *
> > + * Inputs:
> > + * base: base address symbol (should be page-aligned)
> > + * limit: limit address symbol
> > + * sel: region selector
> > + * prbar: store computed PRBAR_EL2 value
> > + * prlar: store computed PRLAR_EL2 value
> > + * attr_prbar: PRBAR_EL2-related memory attributes. If not specified
> > +it will be REGION_DATA_PRBAR
> > + * attr_prlar: PRLAR_EL2-related memory attributes. If not specified
> > +it will be REGION_NORMAL_PRLAR
> > + *
> > + * Clobber \tmp1
> > + *
> > + */
> > +.macro prepare_xen_region, base, limit, sel, prbar, prlar, tmp1,
> attr_prbar=REGION_DATA_PRBAR, attr_prlar=REGION_NORMAL_PRLAR
> > + /* Prepare value for PRBAR_EL2 reg and preserve it in \prbar.*/
> > + load_paddr \prbar, \base
> > + and \prbar, \prbar, #MPU_REGION_MASK
> > + mov \tmp1, #\attr_prbar
> > + orr \prbar, \prbar, \tmp1
> > +
> > + /* Prepare value for PRLAR_EL2 reg and preserve it in \prlar.*/
> > + load_paddr \prlar, \limit
> > + /* Round up limit address to be PAGE_SIZE aligned */
> > + roundup_section \prlar
> > + /* Limit address should be inclusive */
> > + sub \prlar, \prlar, #1
> > + and \prlar, \prlar, #MPU_REGION_MASK
> > + mov \tmp1, #\attr_prlar
> > + orr \prlar, \prlar, \tmp1
> > +
> > + mov x27, \sel
> > + mov x28, \prbar
> > + mov x29, \prlar
>
> Any reasons for using x27, x28, x29 to pass function parameters.
>
> https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
> states x0..x7 should be used (Table 2, General-purpose registers and
> AAPCS64 usage).
>
These registers are documented and reserved in xen/arch/arm/arm64/head.S, like
how we reserve x26 to pass function parameter in skip_zero_bss, see
```
diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S
index 782bd1f94c..145e3d53dc 100644
--- a/xen/arch/arm/arm64/head.S
+++ b/xen/arch/arm/arm64/head.S
@@ -68,9 +68,9 @@
* x24 -
* x25 -
* x26 - skip_zero_bss (boot cpu only)
- * x27 -
- * x28 -
- * x29 -
+ * x27 - region selector (mpu only)
+ * x28 - prbar (mpu only)
+ * x29 - prlar (mpu only)
* x30 - lr
*/
```
x0...x7 are already commonly used in xen/arch/arm/arm64/head.S, it is difficult
for me
to preserve them only for write_pr.
If we are using x0...x7 as function parameter, I need to stack/pop them to
mutate
stack operation in write_pr to avoid corruption.
> > + /*
> > + * x2skip_zero7, x28, x29 are special registers designed as
> > + * inputs for function write_pr
> > + */
> > + bl write_pr
> > +.endm
> > +
[...]
> > --
> > 2.25.1
> >
> NIT:- Would you consider splitting this patch, something like this :-
>
> 1. Renaming of the mmu function
>
> 2. Define sysregs, prlar_t, prbar_t and other other hardware specific macros.
>
> 3. Define write_pr
>
> 4. The rest of the changes (ie prepare_early_mappings(), xen.lds.S, etc)
>
For 2, 3 and 4, it will break the rule of "Always define and introduce at the
first usage".
However, I know that this commit is very big ;/, so as long as maintainers are
also
in favor of your splitting suggestion, I'm happy to do the split too~
> - Ayan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |