[RFC PATCH 3/4] arm64: mmu_change_region_attr() add an option not to break PTEs

Heinrich Schuchardt xypron.glpk at gmx.de
Thu Jan 30 11:12:59 CET 2025


On 1/30/25 07:20, Ilias Apalodimas wrote:
> The ARM ARM on section 8.17.1 describes the cases where
> break-before-make is required when changing live page tables.
> Since we can use this function to tweak block and page permssions,
> where BBM is not required add an extra argument to the function.
>
> While at it add a function we can use to change the attributes of normal
> memory without breaking the pages tables first
>
> Signed-off-by: Ilias Apalodimas <ilias.apalodimas at linaro.org>
> ---
>   arch/arm/cpu/armv8/cache_v8.c           | 27 ++++++++++++++++++++++++-
>   arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 10 ++++-----
>   arch/arm/include/asm/system.h           |  3 ++-
>   arch/arm/mach-snapdragon/board.c        |  2 +-
>   4 files changed, 34 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
> index a4ca56c8ed42..60d0870013e8 100644
> --- a/arch/arm/cpu/armv8/cache_v8.c
> +++ b/arch/arm/cpu/armv8/cache_v8.c
> @@ -968,11 +968,14 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
>    * The procecess is break-before-make. The target region will be marked as
>    * invalid during the process of changing.
>    */
> -void mmu_change_region_attr(phys_addr_t addr, size_t siz, u64 attrs)
> +void mmu_change_region_attr(phys_addr_t addr, size_t siz, u64 attrs, bool bbm)

The function description should be moved to the include or be completed
here.

>   {
>   	int level;
>   	u64 r, size, start;
>
> +	if (!bbm)
> +		goto skip_bbm;
> +
>   	start = addr;
>   	size = siz;
>   	/*
> @@ -997,6 +1000,7 @@ void mmu_change_region_attr(phys_addr_t addr, size_t siz, u64 attrs)
>   			   gd->arch.tlb_addr + gd->arch.tlb_size);
>   	__asm_invalidate_tlb_all();
>
> +skip_bbm:
>   	/*
>   	 * Loop through the address range until we find a page granule that fits
>   	 * our alignment constraints, then set it to the new cache attributes
> @@ -1020,6 +1024,27 @@ void mmu_change_region_attr(phys_addr_t addr, size_t siz, u64 attrs)
>   	__asm_invalidate_tlb_all();
>   }
>
> +void mmu_set_attrs(phys_addr_t addr, size_t size, int type)

Please, add a function description.

The function should either be static or added to an include file.

> +{
> +	u64 attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE | PTE_TYPE_VALID;
> +
> +	switch (type) {
> +	case 1:
> +	/* RO */
> +		attrs |= PTE_BLOCK_PXN | PTE_BLOCK_UXN | PTE_BLOCK_RO;
> +		break;
> +	case 2:
> +		/* RX */
> +		attrs |= PTE_BLOCK_RO;
> +		break;
> +	case 3:
> +		/* RW */
> +		attrs |= PTE_BLOCK_PXN | PTE_BLOCK_UXN;
> +	}
> +
> +	mmu_change_region_attr(addr, size, attrs, false);
> +}
> +
>   #else	/* !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) */
>
>   /*
> diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
> index d2d3e346a36f..caf1dab05936 100644
> --- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
> +++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
> @@ -1573,7 +1573,7 @@ void update_early_mmu_table(void)
>   					PTE_BLOCK_MEMTYPE(MT_NORMAL)	|
>   					PTE_BLOCK_OUTER_SHARE		|
>   					PTE_BLOCK_NS			|
> -					PTE_TYPE_VALID);
> +					PTE_TYPE_VALID, true);
>   	} else {
>   		mmu_change_region_attr(
>   					CFG_SYS_SDRAM_BASE,
> @@ -1581,7 +1581,7 @@ void update_early_mmu_table(void)
>   					PTE_BLOCK_MEMTYPE(MT_NORMAL)	|
>   					PTE_BLOCK_OUTER_SHARE		|
>   					PTE_BLOCK_NS			|
> -					PTE_TYPE_VALID);
> +					PTE_TYPE_VALID, true);
>   #ifdef CONFIG_SYS_DDR_BLOCK3_BASE
>   #ifndef CONFIG_SYS_DDR_BLOCK2_SIZE
>   #error "Missing CONFIG_SYS_DDR_BLOCK2_SIZE"
> @@ -1594,7 +1594,7 @@ void update_early_mmu_table(void)
>   					PTE_BLOCK_MEMTYPE(MT_NORMAL)	|
>   					PTE_BLOCK_OUTER_SHARE		|
>   					PTE_BLOCK_NS			|
> -					PTE_TYPE_VALID);
> +					PTE_TYPE_VALID, true);
>   			mmu_change_region_attr(
>   					CONFIG_SYS_DDR_BLOCK3_BASE,
>   					gd->ram_size -
> @@ -1603,7 +1603,7 @@ void update_early_mmu_table(void)
>   					PTE_BLOCK_MEMTYPE(MT_NORMAL)	|
>   					PTE_BLOCK_OUTER_SHARE		|
>   					PTE_BLOCK_NS			|
> -					PTE_TYPE_VALID);
> +					PTE_TYPE_VALID, true);
>   		} else
>   #endif
>   		{
> @@ -1614,7 +1614,7 @@ void update_early_mmu_table(void)
>   					PTE_BLOCK_MEMTYPE(MT_NORMAL)	|
>   					PTE_BLOCK_OUTER_SHARE		|
>   					PTE_BLOCK_NS			|
> -					PTE_TYPE_VALID);
> +					PTE_TYPE_VALID, true);
>   		}
>   	}
>   }
> diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
> index dbf9ab43e280..0a8ca19e45e9 100644
> --- a/arch/arm/include/asm/system.h
> +++ b/arch/arm/include/asm/system.h
> @@ -287,8 +287,9 @@ void flush_l3_cache(void);
>    * @emerg: Also map the region in the emergency table
>    */
>   void mmu_map_region(phys_addr_t start, u64 size, bool emerg);
> -void mmu_change_region_attr(phys_addr_t start, size_t size, u64 attrs);
> +void mmu_change_region_attr(phys_addr_t start, size_t size, u64 attrs, bool bbm);

Please, add a function description.

Best regards

Heinrich

>
> +void mmu_set_attrs(phys_addr_t addr, size_t size, int type);
>   /*
>    * smc_call() - issue a secure monitor call
>    *
> diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
> index 2ef936aab757..13f4e8e640ef 100644
> --- a/arch/arm/mach-snapdragon/board.c
> +++ b/arch/arm/mach-snapdragon/board.c
> @@ -577,7 +577,7 @@ static void carve_out_reserved_memory(void)
>   		if (i == count || start + size < res[i].start - SZ_2M) {
>   			debug("  0x%016llx - 0x%016llx: reserved\n",
>   			      start, start + size);
> -			mmu_change_region_attr(start, size, PTE_TYPE_FAULT);
> +			mmu_change_region_attr(start, size, PTE_TYPE_FAULT, true);
>   			/* If this is the final region then quit here before we index
>   			 * out of bounds...
>   			 */



More information about the U-Boot mailing list