arm64: mmu_change_region_attr() add an option not to break PTEs

The ARM ARM (Rev L.a) on section 8.17.1 describes the cases where
break-before-make is required when changing live page tables.
Since we can use a function to tweak block and page permissions,
where BBM is not required split the existing mmu_change_region_attr()
into two functions and create one that doesn't require BBM. Subsequent
patches will use the new function to map the U-Boot binary with proper
page permissions.
While at it add function descriptions in their header files.

Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
This commit is contained in:
Ilias Apalodimas 2025-02-20 15:54:41 +02:00
parent 1c7d0c411c
commit ff0a979fc3
2 changed files with 47 additions and 21 deletions

View File

@ -967,6 +967,34 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
flush_dcache_range(real_start, real_start + real_size);
}
void mmu_change_region_attr_nobreak(phys_addr_t addr, size_t siz, u64 attrs)
{
int level;
u64 r, size, start;
/*
* Loop through the address range until we find a page granule that fits
* our alignment constraints and set the new permissions
*/
start = addr;
size = siz;
while (size > 0) {
for (level = 1; level < 4; level++) {
/* Set PTE to new attributes */
r = set_one_region(start, size, attrs, true, level);
if (r) {
/* PTE successfully updated */
size -= r;
start += r;
break;
}
}
}
flush_dcache_range(gd->arch.tlb_addr,
gd->arch.tlb_addr + gd->arch.tlb_size);
__asm_invalidate_tlb_all();
}
/*
* Modify MMU table for a region with updated PXN/UXN/Memory type/valid bits.
* The procecess is break-before-make. The target region will be marked as
@ -1001,27 +1029,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();
/*
* Loop through the address range until we find a page granule that fits
* our alignment constraints, then set it to the new cache attributes
*/
start = addr;
size = siz;
while (size > 0) {
for (level = 1; level < 4; level++) {
/* Set PTE to new attributes */
r = set_one_region(start, size, attrs, true, level);
if (r) {
/* PTE successfully updated */
size -= r;
start += r;
break;
}
}
}
flush_dcache_range(gd->arch.tlb_addr,
gd->arch.tlb_addr + gd->arch.tlb_size);
__asm_invalidate_tlb_all();
mmu_change_region_attr_nobreak(addr, siz, attrs);
}
#else /* !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) */

View File

@ -303,8 +303,26 @@ 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);
/**
* mmu_change_region_attr() - change a mapped region attributes
*
* @start: Start address of the region
* @size: Size of the region
* @aatrs: New attributes
*/
void mmu_change_region_attr(phys_addr_t start, size_t size, u64 attrs);
/**
* mmu_change_region_attr_nobreak() - change a mapped region attributes without doing
* break-before-make
*
* @start: Start address of the region
* @size: Size of the region
* @aatrs: New attributes
*/
void mmu_change_region_attr_nobreak(phys_addr_t addr, size_t size, u64 attrs);
/*
* smc_call() - issue a secure monitor call
*