mm: introduce CONFIG_KERNEL_VM_USE_CUSTOM_MEM_RANGE_CHECK

Sometimes the generic address range checker is not adequate
(think Xtensa cached/uncached pointers). This provides a way
to implement custom memory range checkers for those
situations. When enabled, sys_mm_is_phys_addr_in_range()
and sys_mm_is_virt_addr_in_range() must be implemented.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
Daniel Leung 2023-10-12 10:50:53 -07:00 committed by Carles Cufí
parent 68dfd819c1
commit 943e434559
2 changed files with 56 additions and 1 deletions

View file

@ -143,12 +143,53 @@ struct k_mem_paging_histogram_t {
#endif /* CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM */ #endif /* CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM */
}; };
/**
* @brief Check if a physical address is within range of physical memory.
*
* This checks if the physical address (@p virt) is within
* permissible range, e.g. between
* :kconfig:option:`CONFIG_SRAM_BASE_ADDRESS` and
* (:kconfig:option:`CONFIG_SRAM_BASE_ADDRESS` +
* :kconfig:option:`CONFIG_SRAM_SIZE`).
*
* @note Only used if
* :kconfig:option:`CONFIG_KERNEL_VM_USE_CUSTOM_MEM_RANGE_CHECK`
* is enabled.
*
* @param phys Physical address to be checked.
*
* @return True if physical address is within range, false if not.
*/
bool sys_mm_is_phys_addr_in_range(uintptr_t phys);
/**
* @brief Check if a virtual address is within range of virtual memory.
*
* This checks if the virtual address (@p virt) is within
* permissible range, e.g. between
* :kconfig:option:`CONFIG_KERNEL_VM_BASE` and
* (:kconfig:option:`CONFIG_KERNEL_VM_BASE` +
* :kconfig:option:`CONFIG_KERNEL_VM_SIZE`).
*
* @note Only used if
* :kconfig:option:`CONFIG_KERNEL_VM_USE_CUSTOM_MEM_RANGE_CHECK`
* is enabled.
*
* @param virt Virtual address to be checked.
*
* @return True if virtual address is within range, false if not.
*/
bool sys_mm_is_virt_addr_in_range(void *virt);
/* Just like Z_MEM_PHYS_ADDR() but with type safety and assertions */ /* Just like Z_MEM_PHYS_ADDR() but with type safety and assertions */
static inline uintptr_t z_mem_phys_addr(void *virt) static inline uintptr_t z_mem_phys_addr(void *virt)
{ {
uintptr_t addr = (uintptr_t)virt; uintptr_t addr = (uintptr_t)virt;
#ifdef CONFIG_MMU #if defined(CONFIG_KERNEL_VM_USE_CUSTOM_MEM_RANGE_CHECK)
__ASSERT(sys_mm_is_virt_addr_in_range(virt),
"address %p not in permanent mappings", virt);
#elif defined(CONFIG_MMU)
__ASSERT( __ASSERT(
#if CONFIG_KERNEL_VM_BASE != 0 #if CONFIG_KERNEL_VM_BASE != 0
(addr >= CONFIG_KERNEL_VM_BASE) && (addr >= CONFIG_KERNEL_VM_BASE) &&
@ -178,6 +219,10 @@ static inline uintptr_t z_mem_phys_addr(void *virt)
/* Just like Z_MEM_VIRT_ADDR() but with type safety and assertions */ /* Just like Z_MEM_VIRT_ADDR() but with type safety and assertions */
static inline void *z_mem_virt_addr(uintptr_t phys) static inline void *z_mem_virt_addr(uintptr_t phys)
{ {
#if defined(CONFIG_KERNEL_VM_USE_CUSTOM_MEM_RANGE_CHECK)
__ASSERT(sys_mm_is_phys_addr_in_range(phys),
"physical address 0x%lx not in RAM", (unsigned long)phys);
#else
__ASSERT( __ASSERT(
#if CONFIG_SRAM_BASE_ADDRESS != 0 #if CONFIG_SRAM_BASE_ADDRESS != 0
(phys >= CONFIG_SRAM_BASE_ADDRESS) && (phys >= CONFIG_SRAM_BASE_ADDRESS) &&
@ -185,6 +230,7 @@ static inline void *z_mem_virt_addr(uintptr_t phys)
(phys < (CONFIG_SRAM_BASE_ADDRESS + (phys < (CONFIG_SRAM_BASE_ADDRESS +
(CONFIG_SRAM_SIZE * 1024UL))), (CONFIG_SRAM_SIZE * 1024UL))),
"physical address 0x%lx not in RAM", (unsigned long)phys); "physical address 0x%lx not in RAM", (unsigned long)phys);
#endif
/* TODO add assertion that this page frame is pinned to boot mapping, /* TODO add assertion that this page frame is pinned to boot mapping,
* the above check won't be sufficient with demand paging * the above check won't be sufficient with demand paging

View file

@ -198,4 +198,13 @@ config DEMAND_PAGING_TIMING_HISTOGRAM_NUM_BINS
endif # DEMAND_PAGING endif # DEMAND_PAGING
endif # MMU endif # MMU
config KERNEL_VM_USE_CUSTOM_MEM_RANGE_CHECK
bool
help
Use custom memory range check functions instead of the generic
checks in z_mem_phys_addr() and z_mem_virt_addr().
sys_mm_is_phys_addr_in_range() and
sys_mm_is_virt_addr_in_range() must be implemented.
endmenu # Virtual Memory Support endmenu # Virtual Memory Support