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:
parent
7741e9f7b0
commit
085d3768e1
2 changed files with 54 additions and 0 deletions
|
@ -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
|
||||
|
|
31
kernel/mmu.c
31
kernel/mmu.c
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue