kernel: mmu: introduce arch_page_phys_get()

This adds a new function prototype for arch_page_phys_get()
which will be used to translate mapped virtual addresses back
to physical memory addresses. This is needed for the future
k_mem_unmap() function which requires this to find
the corresponding page frame. It is faster to look through
the page tables instead of doing linear search of the page
frame array.

A weak function is provided in case arch_page_phys_get()
is not implemented at the arch level. This simply goes
through all the page frame and find the one which has
mapped to the virtual address.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
Daniel Leung 2021-04-15 18:44:56 -07:00 committed by Anas Nashif
commit 085d3768e1
2 changed files with 54 additions and 0 deletions

View file

@ -310,6 +310,29 @@ void arch_mem_map(void *virt, uintptr_t phys, size_t size, uint32_t flags);
*/
void arch_mem_unmap(void *addr, size_t size);
/**
* Get the mapped physical memory address from virtual address.
*
* The function only needs to query the current set of page tables as
* the information it reports must be common to all of them if multiple
* page tables are in use. If multiple page tables are active it is unnecessary
* to iterate over all of them.
*
* Unless otherwise specified, virtual pages have the same mappings
* across all page tables. Calling this function on data pages that are
* exceptions to this rule (such as the scratch page) is undefined behavior.
* Just check the currently installed page tables and return the information
* in that.
*
* @param virt Page-aligned virtual address
* @param[out] phys Mapped physical address (can be NULL if only checking
* if virtual address is mapped)
*
* @retval 0 if mapping is found and valid
* @retval -EFAULT if virtual address is not mapped
*/
int arch_page_phys_get(void *virt, uintptr_t *phys);
#ifdef CONFIG_ARCH_HAS_RESERVED_PAGE_FRAMES
/**
* Update page frame database with reserved pages

View file

@ -13,6 +13,7 @@
#include <init.h>
#include <kernel_internal.h>
#include <syscall_handler.h>
#include <toolchain.h>
#include <linker/linker-defs.h>
#include <timing/timing.h>
#include <logging/log.h>
@ -277,6 +278,36 @@ static void frame_mapped_set(struct z_page_frame *pf, void *addr)
pf->addr = addr;
}
/* Go through page frames to find the physical address mapped
* by a virtual address.
*
* @param[in] virt Virtual Address
* @param[out] phys Physical address mapped to the input virtual address
* if such mapping exists.
*
* @retval 0 if mapping is found and valid
* @retval -EFAULT if virtual address is not mapped
*/
static int virt_to_page_frame(void *virt, uintptr_t *phys)
{
uintptr_t paddr;
struct z_page_frame *pf;
int ret = -EFAULT;
Z_PAGE_FRAME_FOREACH(paddr, pf) {
if (z_page_frame_is_mapped(pf)) {
if (virt == pf->addr) {
ret = 0;
*phys = z_page_frame_to_phys(pf);
break;
}
}
}
return ret;
}
__weak FUNC_ALIAS(virt_to_page_frame, arch_page_phys_get, int);
#ifdef CONFIG_DEMAND_PAGING
static int page_frame_prepare_locked(struct z_page_frame *pf, bool *dirty_ptr,
bool page_in, uintptr_t *location_ptr);