On 06/06/2025 18:48, Ayan Kumar Halder wrote:
> Modify Arm32 assembly boot code to reset any unused MPU region, initialise
> 'max_mpu_regions' with the number of supported MPU regions and set/clear the
> bitmap 'xen_mpumap_mask' used to track the enabled regions.
>
> Use the macro definition for "dcache_line_size" from linux.
>
> Signed-off-by: Ayan Kumar Halder <ayan.kumar.hal...@amd.com>
> ---
> Changes from v1 :-
>
> 1. Introduce cache.S to hold arm32 cache initialization instructions.
>
> 2. Use dcache_line_size macro definition from linux.
>
> 3. Use mov_w instead of ldr.
>
> 4. Use a single stm instruction for 'store_pair' macro definition.
>
> xen/arch/arm/arm32/Makefile | 1 +
> xen/arch/arm/arm32/asm-offsets.c | 6 ++++
> xen/arch/arm/arm32/cache.S | 41 ++++++++++++++++++++++++
> xen/arch/arm/arm32/mpu/head.S | 25 +++++++++++++++
> xen/arch/arm/include/asm/mpu/regions.inc | 2 +-
> 5 files changed, 74 insertions(+), 1 deletion(-)
> create mode 100644 xen/arch/arm/arm32/cache.S
>
> diff --git a/xen/arch/arm/arm32/Makefile b/xen/arch/arm/arm32/Makefile
> index 537969d753..531168f58a 100644
> --- a/xen/arch/arm/arm32/Makefile
> +++ b/xen/arch/arm/arm32/Makefile
> @@ -2,6 +2,7 @@ obj-y += lib/
> obj-$(CONFIG_MMU) += mmu/
> obj-$(CONFIG_MPU) += mpu/
>
> +obj-y += cache.o
> obj-$(CONFIG_EARLY_PRINTK) += debug.o
> obj-y += domctl.o
> obj-y += domain.o
> diff --git a/xen/arch/arm/arm32/asm-offsets.c
> b/xen/arch/arm/arm32/asm-offsets.c
> index 8bbb0f938e..c203ce269d 100644
> --- a/xen/arch/arm/arm32/asm-offsets.c
> +++ b/xen/arch/arm/arm32/asm-offsets.c
> @@ -75,6 +75,12 @@ void __dummy__(void)
>
> OFFSET(INITINFO_stack, struct init_info, stack);
> BLANK();
> +
> +#ifdef CONFIG_MPU
> + DEFINE(XEN_MPUMAP_MASK_sizeof, sizeof(xen_mpumap_mask));
> + DEFINE(XEN_MPUMAP_sizeof, sizeof(xen_mpumap));
> + BLANK();
> +#endif
> }
>
> /*
> diff --git a/xen/arch/arm/arm32/cache.S b/xen/arch/arm/arm32/cache.S
> new file mode 100644
> index 0000000000..00ea390ce4
> --- /dev/null
> +++ b/xen/arch/arm/arm32/cache.S
> @@ -0,0 +1,41 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/* Cache maintenance */
> +
> +#include <asm/arm32/sysregs.h>
> +
> +/* dcache_line_size - get the minimum D-cache line size from the CTR
> register */
> + .macro dcache_line_size, reg, tmp
> + mrc p15, 0, \tmp, c0, c0, 1 /* read ctr */
Why open coding macro CTR? Especially if below you use DCIMVAC.
> + lsr \tmp, \tmp, #16
> + and \tmp, \tmp, #0xf /* cache line size encoding */
> + mov \reg, #4 /* bytes per word */
> + mov \reg, \reg, lsl \tmp /* actual cache line size */
> + .endm
> +
> +/*
> + * __invalidate_dcache_area(addr, size)
> + *
> + * Ensure that the data held in the cache for the buffer is invalidated.
> + *
> + * - addr - start address of the buffer
> + * - size - size of the buffer
> + */
I do think that for new functions in assembly we should write what registers are
clobbered. Arm64 cache.S originated from Linux, hence it lacks this information.
> +FUNC(__invalidate_dcache_area)
> + dcache_line_size r2, r3
> + add r1, r0, r1
> + sub r3, r2, #1
> + bic r0, r0, r3
> +1: mcr CP32(r0, DCIMVAC) /* invalidate D line / unified line */
> + add r0, r0, r2
> + cmp r0, r1
> + blo 1b
> + dsb sy
> + ret
> +END(__invalidate_dcache_area)
> +
> +/*
> + * Local variables:
> + * mode: ASM
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/arch/arm/arm32/mpu/head.S b/xen/arch/arm/arm32/mpu/head.S
> index b2c5245e51..435b140d09 100644
> --- a/xen/arch/arm/arm32/mpu/head.S
> +++ b/xen/arch/arm/arm32/mpu/head.S
> @@ -49,6 +49,10 @@ FUNC(enable_boot_cpu_mm)
> mrc CP32(r5, MPUIR_EL2)
> and r5, r5, #NUM_MPU_REGIONS_MASK
>
> + mov_w r0, max_mpu_regions
> + str r5, [r0]
> + mcr CP32(r0, DCIMVAC) /* Invalidate cache for max_mpu_regions addr */
> +
> /* x0: region sel */
> mov r0, #0
> /* Xen text section. */
> @@ -83,6 +87,27 @@ FUNC(enable_boot_cpu_mm)
> prepare_xen_region r0, r1, r2, r3, r4, r5,
> attr_prbar=REGION_DEVICE_PRBAR, attr_prlar=REGION_DEVICE_PRLAR
> #endif
>
> +zero_mpu:
> + /* Reset remaining MPU regions */
> + cmp r0, r5
> + beq out_zero_mpu
> + mov r1, #0
> + mov r2, #1
> + prepare_xen_region r0, r1, r2, r3, r4, r5,
> attr_prlar=REGION_DISABLED_PRLAR
> + b zero_mpu
> +
> +out_zero_mpu:
> + /* Invalidate data cache for MPU data structures */
> + mov r4, lr
> + mov_w r0, xen_mpumap_mask
> + mov r1, #XEN_MPUMAP_MASK_sizeof
> + bl __invalidate_dcache_area
> +
> + ldr r0, =xen_mpumap
> + mov r1, #XEN_MPUMAP_sizeof
> + bl __invalidate_dcache_area
> + mov lr, r4
> +
> b enable_mpu
> END(enable_boot_cpu_mm)
>
> diff --git a/xen/arch/arm/include/asm/mpu/regions.inc
> b/xen/arch/arm/include/asm/mpu/regions.inc
> index 6b8c233e6c..631b0b2b86 100644
> --- a/xen/arch/arm/include/asm/mpu/regions.inc
> +++ b/xen/arch/arm/include/asm/mpu/regions.inc
> @@ -24,7 +24,7 @@
> #define XEN_MPUMAP_ENTRY_SHIFT 0x3 /* 8 byte structure */
>
> .macro store_pair reg1, reg2, dst
> - .word 0xe7f000f0 /* unimplemented */
> + stm \dst, {\reg1, \reg2} /* reg2 should be a higher register than reg1
> */
Didn't we agree not to use STM (I suggested it but then Julien pointed out that
it's use in macro might not be the best)?
~Michal