kernel: mmu: add direct-map support in z_phys_map()

Many RTOS applications assume the virtual and physical address
is 1:1 mapping, so add the 1:1 mapping support in z_phys_map()
to easy adapt these applications.

Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
This commit is contained in:
Hou Zhiqiang 2023-05-18 18:29:35 +08:00 committed by Anas Nashif
parent 5ab14730f5
commit 41520e8b5b
3 changed files with 47 additions and 4 deletions

View file

@ -54,6 +54,13 @@
/** Region will be accessible to user mode (normally supervisor-only) */
#define K_MEM_PERM_USER BIT(5)
/*
* Region mapping behaviour attributes
*/
/** Region will be mapped to 1:1 virtual and physical address */
#define K_MEM_DIRECT_MAP BIT(6)
/*
* This is the offset to subtract from a virtual address mapped in the
* kernel's permanent mapping of RAM, to obtain its physical address.

View file

@ -80,6 +80,22 @@ config KERNEL_VM_SIZE
implement a notion of "high" memory in Zephyr to work around physical
RAM size larger than the defined bounds of the virtual address space.
config KERNEL_DIRECT_MAP
bool "Memory region direct-map support"
depends on MMU
help
This enables the direct-map support, namely the region can be 1:1
mapping between virtual address and physical address.
If the specific memory region is in the virtual memory space and
there isn't overlap with the existed mappings, it will reserve the
region from the virtual memory space and do the mapping, otherwise
it will fail. And any attempt across the boundary of the virtual
memory space will fail.
Note that this is for compatibility and portable apps shouldn't
be using it.
endif # KERNEL_VM_SUPPORT
menuconfig MMU

View file

@ -237,9 +237,11 @@ static void virt_region_free(void *vaddr, size_t size)
virt_region_init();
}
#ifndef CONFIG_KERNEL_DIRECT_MAP
__ASSERT((vaddr_u8 >= Z_VIRT_REGION_START_ADDR)
&& ((vaddr_u8 + size - 1) < Z_VIRT_REGION_END_ADDR),
"invalid virtual address region %p (%zu)", vaddr_u8, size);
#endif
if (!((vaddr_u8 >= Z_VIRT_REGION_START_ADDR)
&& ((vaddr_u8 + size - 1) < Z_VIRT_REGION_END_ADDR))) {
return;
@ -721,7 +723,12 @@ void z_phys_map(uint8_t **virt_ptr, uintptr_t phys, size_t size, uint32_t flags)
size_t aligned_size, align_boundary;
k_spinlock_key_t key;
uint8_t *dest_addr;
size_t num_bits;
size_t offset;
#ifndef CONFIG_KERNEL_DIRECT_MAP
__ASSERT(!(flags & K_MEM_DIRECT_MAP), "The direct-map is not enabled");
#endif
addr_offset = k_mem_region_align(&aligned_phys, &aligned_size,
phys, size,
CONFIG_MMU_PAGE_SIZE);
@ -733,10 +740,23 @@ void z_phys_map(uint8_t **virt_ptr, uintptr_t phys, size_t size, uint32_t flags)
align_boundary = arch_virt_region_align(aligned_phys, aligned_size);
key = k_spin_lock(&z_mm_lock);
/* Obtain an appropriately sized chunk of virtual memory */
dest_addr = virt_region_alloc(aligned_size, align_boundary);
if (!dest_addr) {
goto fail;
if (flags & K_MEM_DIRECT_MAP) {
dest_addr = (uint8_t *)aligned_phys;
/* Reserve from the virtual memory space */
if (!(dest_addr + aligned_size < Z_VIRT_RAM_START ||
dest_addr > Z_VIRT_RAM_END)) {
num_bits = aligned_size / CONFIG_MMU_PAGE_SIZE;
offset = virt_to_bitmap_offset(dest_addr, aligned_size);
if (sys_bitarray_test_and_set_region(
&virt_region_bitmap, num_bits, offset, true))
goto fail;
}
} else {
/* Obtain an appropriately sized chunk of virtual memory */
dest_addr = virt_region_alloc(aligned_size, align_boundary);
if (!dest_addr) {
goto fail;
}
}
/* If this fails there's something amiss with virt_region_get */