kernel: mmu: implement z_phys_unmap()

This provides a counterpart to z_phys_map() which can be used
to temporary map memory region during boot process, and
subsequently discards the mapping.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
Daniel Leung 2021-04-14 12:57:03 -07:00 committed by Anas Nashif
commit e6df25f68c
2 changed files with 49 additions and 2 deletions

View file

@ -179,8 +179,6 @@ extern "C" {
* Portable code should never assume that phys_addr and linear_addr will
* be equal.
*
* Once created, mappings are permanent.
*
* Caching and access properties are controlled by the 'flags' parameter.
* Unused bits in 'flags' are reserved for future expansion.
* A caching mode must be selected. By default, the region is read-only
@ -210,6 +208,35 @@ extern "C" {
void z_phys_map(uint8_t **virt_ptr, uintptr_t phys, size_t size,
uint32_t flags);
/**
* Unmap a virtual memory region from kernel's virtual address space.
*
* This function is intended to be used by drivers and early boot routines
* where temporary memory mappings need to be made. This allows these
* memory mappings to be discarded once they are no longer needed.
*
* This function alters the active page tables in the area reserved
* for the kernel.
*
* This will align the input parameters to page boundaries so that
* this can be used with the virtual address as returned by
* z_phys_map().
*
* This API is only available if CONFIG_MMU is enabled.
*
* It is highly discouraged to use this function to unmap memory mappings.
* It may conflict with anonymous memory mappings and demand paging and
* produce undefined behavior. Do not use this unless you know exactly
* what you are doing.
*
* This API is part of infrastructure still under development and may
* change.
*
* @param virt Starting address of the virtual address region to be unmapped.
* @param size Size of the virtual address region
*/
void z_phys_unmap(uint8_t *virt, size_t size);
/*
* k_mem_map() control flags
*/

View file

@ -467,6 +467,26 @@ fail:
k_panic();
}
void z_phys_unmap(uint8_t *virt, size_t size)
{
uintptr_t aligned_virt, addr_offset;
size_t aligned_size;
k_spinlock_key_t key;
addr_offset = k_mem_region_align(&aligned_virt, &aligned_size,
POINTER_TO_UINT(virt), size,
CONFIG_MMU_PAGE_SIZE);
__ASSERT(aligned_size != 0U, "0-length mapping at 0x%lx", aligned_virt);
__ASSERT(aligned_virt < (aligned_virt + (aligned_size - 1)),
"wraparound for virtual address 0x%lx (size %zu)",
aligned_virt, aligned_size);
key = k_spin_lock(&z_mm_lock);
arch_mem_unmap(UINT_TO_POINTER(aligned_virt), aligned_size);
/* TODO: Need to reclaim the space allocated by virt_region_get(). */
k_spin_unlock(&z_mm_lock, key);
}
/*
* Miscellaneous
*/