mmu: introduce k_mem_update_flags()
It is sometimes necessary to modify/update memory permissions on some pages, especially with LLEXT where some allocated segments have to be executable. Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
parent
16b194a067
commit
c692136f21
2 changed files with 47 additions and 0 deletions
|
@ -258,6 +258,23 @@ static inline void k_mem_unmap(void *addr, size_t size)
|
|||
k_mem_unmap_phys_guard(addr, size, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify memory mapping attribute flags
|
||||
*
|
||||
* This updates caching, access and control flags for the provided
|
||||
* page-aligned memory region.
|
||||
*
|
||||
* Calling this function on a region which was not mapped to begin with is
|
||||
* undefined behavior. However system memory implicitly mapped at boot time
|
||||
* is supported.
|
||||
*
|
||||
* @param addr Page-aligned memory region base virtual address
|
||||
* @param size Page-aligned memory region size
|
||||
* @param flags K_MEM_PERM_*, K_MEM_MAP_* control flags.
|
||||
* @return 0 for success, negative error code otherwise.
|
||||
*/
|
||||
int k_mem_update_flags(void *addr, size_t size, uint32_t flags);
|
||||
|
||||
/**
|
||||
* Given an arbitrary region, provide a aligned region that covers it
|
||||
*
|
||||
|
|
30
kernel/mmu.c
30
kernel/mmu.c
|
@ -813,6 +813,36 @@ out:
|
|||
k_spin_unlock(&z_mm_lock, key);
|
||||
}
|
||||
|
||||
int k_mem_update_flags(void *addr, size_t size, uint32_t flags)
|
||||
{
|
||||
uintptr_t phys;
|
||||
k_spinlock_key_t key;
|
||||
int ret;
|
||||
|
||||
k_mem_assert_virtual_region(addr, size);
|
||||
|
||||
key = k_spin_lock(&z_mm_lock);
|
||||
|
||||
/*
|
||||
* We can achieve desired result without explicit architecture support
|
||||
* by unmapping and remapping the same physical memory using new flags.
|
||||
*/
|
||||
|
||||
ret = arch_page_phys_get(addr, &phys);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* TODO: detect and handle paged-out memory as well */
|
||||
|
||||
arch_mem_unmap(addr, size);
|
||||
arch_mem_map(addr, phys, size, flags);
|
||||
|
||||
out:
|
||||
k_spin_unlock(&z_mm_lock, key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t k_mem_free_get(void)
|
||||
{
|
||||
size_t ret;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue