mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-20 17:44:20 +08:00
[rt-smart] testcase & improvements for memory management (#7099)
* [utest/mm] add testcase for create/init format codes of create/init in components/mm * [libcpu/aarch64] fix user stack check routine * [kservice] export API for utest * [utest/mm] testcase for aspace_map format & modify the files under components/mm related with aspace_map * [lwp/user_mm] add user_map_varea for mmap feature * [mm] rename rt_mm_fault_try_fix to rt_aspace_fault_try_fix * [utest/mm] testcase for synchronization * [mm] modify unmap api to improve throughput * [utest/mm] testcases for cache and varea map * [format] remove extra space * [utest/mm] fix testcase problem in header * [lwp] extend map_user_varea with a flag * [utest/mm] testcase for lwp_map_user_varea * [libcpu/arm/cortex-a] fix kernel space layout * [utest/mm] adjust for armv7 arch
This commit is contained in:
@@ -117,6 +117,7 @@ rt_varea_t _aspace_bst_search_exceed(struct rt_aspace *aspace, void *start)
|
||||
|
||||
if (cmp < 0)
|
||||
{
|
||||
/* varae exceed start */
|
||||
ptrdiff_t off = va_s - start;
|
||||
if (off < min_off)
|
||||
{
|
||||
@@ -127,6 +128,7 @@ rt_varea_t _aspace_bst_search_exceed(struct rt_aspace *aspace, void *start)
|
||||
}
|
||||
else if (cmp > 0)
|
||||
{
|
||||
/* find the next huger varea */
|
||||
node = node->avl_right;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -98,7 +98,7 @@ void *rt_ioremap_cached(void *paddr, size_t size)
|
||||
|
||||
void rt_iounmap(volatile void *vaddr)
|
||||
{
|
||||
rt_aspace_unmap(&rt_kernel_space, (void *)vaddr, 1);
|
||||
rt_aspace_unmap(&rt_kernel_space, (void *)vaddr);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
+303
-147
File diff suppressed because it is too large
Load Diff
@@ -90,7 +90,7 @@ typedef struct rt_mm_va_hint
|
||||
typedef struct rt_mem_obj
|
||||
{
|
||||
void (*hint_free)(rt_mm_va_hint_t hint);
|
||||
void (*on_page_fault)(struct rt_varea *varea, struct rt_mm_fault_msg *msg);
|
||||
void (*on_page_fault)(struct rt_varea *varea, struct rt_aspace_fault_msg *msg);
|
||||
|
||||
/* do pre open bushiness like inc a ref */
|
||||
void (*on_varea_open)(struct rt_varea *varea);
|
||||
@@ -127,8 +127,7 @@ enum rt_mmu_cntl
|
||||
|
||||
rt_aspace_t rt_aspace_create(void *start, rt_size_t length, void *pgtbl);
|
||||
|
||||
rt_aspace_t rt_aspace_init(rt_aspace_t aspace, void *start, rt_size_t length,
|
||||
void *pgtbl);
|
||||
rt_err_t rt_aspace_init(rt_aspace_t aspace, void *start, rt_size_t length, void *pgtbl);
|
||||
|
||||
void rt_aspace_delete(rt_aspace_t aspace);
|
||||
|
||||
@@ -182,12 +181,11 @@ int rt_aspace_map_phy_static(rt_aspace_t aspace, rt_varea_t varea,
|
||||
*
|
||||
* @param aspace
|
||||
* @param addr
|
||||
* @param length
|
||||
* @return int
|
||||
*/
|
||||
int rt_aspace_unmap(rt_aspace_t aspace, void *addr, rt_size_t length);
|
||||
int rt_aspace_unmap(rt_aspace_t aspace, void *addr);
|
||||
|
||||
int mm_aspace_control(rt_aspace_t aspace, void *addr, enum rt_mmu_cntl cmd);
|
||||
int rt_aspace_control(rt_aspace_t aspace, void *addr, enum rt_mmu_cntl cmd);
|
||||
|
||||
int rt_aspace_load_page(rt_aspace_t aspace, void *addr, rt_size_t npage);
|
||||
|
||||
@@ -198,11 +196,35 @@ int rt_aspace_traversal(rt_aspace_t aspace,
|
||||
|
||||
void rt_aspace_print_all(rt_aspace_t aspace);
|
||||
|
||||
void rt_varea_insert_page(rt_varea_t varea, void *page_addr);
|
||||
/**
|
||||
* @brief Map one page to varea
|
||||
*
|
||||
* @param varea target varea
|
||||
* @param addr user address
|
||||
* @param page the page frame to be mapped
|
||||
* @return int
|
||||
*/
|
||||
int rt_varea_map_page(rt_varea_t varea, void *vaddr, void *page);
|
||||
|
||||
void rt_varea_free_pages(rt_varea_t varea);
|
||||
/**
|
||||
* @brief Map a range of physical address to varea
|
||||
*
|
||||
* @param varea target varea
|
||||
* @param vaddr user address
|
||||
* @param paddr physical address
|
||||
* @param length map range
|
||||
* @return int
|
||||
*/
|
||||
int rt_varea_map_range(rt_varea_t varea, void *vaddr, void *paddr, rt_size_t length);
|
||||
|
||||
void rt_varea_offload_page(rt_varea_t varea, void *vaddr, rt_size_t size);
|
||||
/**
|
||||
* @brief Insert page to page manager of varea
|
||||
* The page will be freed by varea on uninstall automatically
|
||||
*
|
||||
* @param varea target varea
|
||||
* @param page_addr the page frame to be added
|
||||
*/
|
||||
void rt_varea_pgmgr_insert(rt_varea_t varea, void *page_addr);
|
||||
|
||||
rt_ubase_t rt_kmem_pvoff(void);
|
||||
|
||||
@@ -212,4 +234,6 @@ int rt_kmem_map_phy(void *va, void *pa, rt_size_t length, rt_size_t attr);
|
||||
|
||||
void *rt_kmem_v2p(void *vaddr);
|
||||
|
||||
void rt_kmem_list(void);
|
||||
|
||||
#endif /* __MM_ASPACE_H__ */
|
||||
|
||||
+19
-29
@@ -26,40 +26,28 @@
|
||||
#define UNRECOVERABLE 0
|
||||
#define RECOVERABLE 1
|
||||
|
||||
static int _fetch_page(rt_varea_t varea, struct rt_mm_fault_msg *msg)
|
||||
static int _fetch_page(rt_varea_t varea, struct rt_aspace_fault_msg *msg)
|
||||
{
|
||||
int err = UNRECOVERABLE;
|
||||
int err;
|
||||
msg->response.status = MM_FAULT_STATUS_UNRECOVERABLE;
|
||||
msg->response.vaddr = 0;
|
||||
msg->response.size = 0;
|
||||
if (varea->mem_obj && varea->mem_obj->on_page_fault)
|
||||
{
|
||||
varea->mem_obj->on_page_fault(varea, msg);
|
||||
if (msg->response.status == MM_FAULT_STATUS_OK)
|
||||
{
|
||||
void *store = msg->response.vaddr;
|
||||
rt_size_t store_sz = msg->response.size;
|
||||
|
||||
if (msg->vaddr + store_sz > varea->start + varea->size)
|
||||
{
|
||||
LOG_W("%s more size of buffer is provided than varea", __func__);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_hw_mmu_map(varea->aspace, msg->vaddr, store + PV_OFFSET,
|
||||
store_sz, varea->attr);
|
||||
rt_hw_tlb_invalidate_range(varea->aspace, msg->vaddr, store_sz,
|
||||
ARCH_PAGE_SIZE);
|
||||
err = RECOVERABLE;
|
||||
}
|
||||
}
|
||||
err = _varea_map_with_msg(varea, msg);
|
||||
err = (err == RT_EOK ? RECOVERABLE : UNRECOVERABLE);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int _read_fault(rt_varea_t varea, void *pa, struct rt_mm_fault_msg *msg)
|
||||
static int _read_fault(rt_varea_t varea, void *pa, struct rt_aspace_fault_msg *msg)
|
||||
{
|
||||
int err = UNRECOVERABLE;
|
||||
if (msg->fault_type == MM_FAULT_TYPE_PAGE_FAULT)
|
||||
{
|
||||
RT_ASSERT(pa == ARCH_MAP_FAILED);
|
||||
RT_ASSERT(!(varea->flag & MMF_PREFETCH));
|
||||
err = _fetch_page(varea, msg);
|
||||
}
|
||||
else
|
||||
@@ -69,12 +57,13 @@ static int _read_fault(rt_varea_t varea, void *pa, struct rt_mm_fault_msg *msg)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int _write_fault(rt_varea_t varea, void *pa, struct rt_mm_fault_msg *msg)
|
||||
static int _write_fault(rt_varea_t varea, void *pa, struct rt_aspace_fault_msg *msg)
|
||||
{
|
||||
int err = UNRECOVERABLE;
|
||||
if (msg->fault_type == MM_FAULT_TYPE_PAGE_FAULT)
|
||||
{
|
||||
RT_ASSERT(pa == ARCH_MAP_FAILED);
|
||||
RT_ASSERT(!(varea->flag & MMF_PREFETCH));
|
||||
err = _fetch_page(varea, msg);
|
||||
}
|
||||
else if (msg->fault_type == MM_FAULT_TYPE_ACCESS_FAULT &&
|
||||
@@ -88,33 +77,34 @@ static int _write_fault(rt_varea_t varea, void *pa, struct rt_mm_fault_msg *msg)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int _exec_fault(rt_varea_t varea, void *pa, struct rt_mm_fault_msg *msg)
|
||||
static int _exec_fault(rt_varea_t varea, void *pa, struct rt_aspace_fault_msg *msg)
|
||||
{
|
||||
int err = UNRECOVERABLE;
|
||||
if (msg->fault_type == MM_FAULT_TYPE_PAGE_FAULT)
|
||||
{
|
||||
RT_ASSERT(pa == ARCH_MAP_FAILED);
|
||||
RT_ASSERT(!(varea->flag & MMF_PREFETCH));
|
||||
err = _fetch_page(varea, msg);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int rt_mm_fault_try_fix(struct rt_mm_fault_msg *msg)
|
||||
int rt_aspace_fault_try_fix(struct rt_aspace_fault_msg *msg)
|
||||
{
|
||||
struct rt_lwp *lwp = lwp_self();
|
||||
int err = UNRECOVERABLE;
|
||||
uintptr_t va = (uintptr_t)msg->vaddr;
|
||||
uintptr_t va = (uintptr_t)msg->fault_vaddr;
|
||||
va &= ~ARCH_PAGE_MASK;
|
||||
msg->vaddr = (void *)va;
|
||||
msg->fault_vaddr = (void *)va;
|
||||
|
||||
if (lwp)
|
||||
{
|
||||
rt_aspace_t aspace = lwp->aspace;
|
||||
rt_varea_t varea = _aspace_bst_search(aspace, msg->vaddr);
|
||||
rt_varea_t varea = _aspace_bst_search(aspace, msg->fault_vaddr);
|
||||
if (varea)
|
||||
{
|
||||
void *pa = rt_hw_mmu_v2p(aspace, msg->vaddr);
|
||||
msg->off = (msg->vaddr - varea->start) >> ARCH_PAGE_SHIFT;
|
||||
void *pa = rt_hw_mmu_v2p(aspace, msg->fault_vaddr);
|
||||
msg->off = (msg->fault_vaddr - varea->start) >> ARCH_PAGE_SHIFT;
|
||||
|
||||
/* permission checked by fault op */
|
||||
switch (msg->fault_op)
|
||||
|
||||
@@ -14,8 +14,11 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define MM_FAULT_STATUS_OK 0
|
||||
#define MM_FAULT_STATUS_UNRECOVERABLE 1
|
||||
/* fast path fault handler, a page frame on kernel space is returned */
|
||||
#define MM_FAULT_STATUS_OK 0
|
||||
/* customized fault handler, done by using rt_varea_map_* */
|
||||
#define MM_FAULT_STATUS_OK_MAPPED 1
|
||||
#define MM_FAULT_STATUS_UNRECOVERABLE 4
|
||||
|
||||
struct rt_mm_fault_res
|
||||
{
|
||||
@@ -39,17 +42,17 @@ enum rt_mm_fault_type
|
||||
MM_FAULT_TYPE_GENERIC,
|
||||
};
|
||||
|
||||
struct rt_mm_fault_msg
|
||||
struct rt_aspace_fault_msg
|
||||
{
|
||||
enum rt_mm_fault_op fault_op;
|
||||
enum rt_mm_fault_type fault_type;
|
||||
rt_size_t off;
|
||||
void *vaddr;
|
||||
void *fault_vaddr;
|
||||
|
||||
struct rt_mm_fault_res response;
|
||||
};
|
||||
|
||||
/* MMU base page fault handler, return 1 is */
|
||||
int rt_mm_fault_try_fix(struct rt_mm_fault_msg *msg);
|
||||
int rt_aspace_fault_try_fix(struct rt_aspace_fault_msg *msg);
|
||||
|
||||
#endif /* __MM_FAULT_H__ */
|
||||
|
||||
@@ -82,9 +82,9 @@ enum mm_flag_cntl
|
||||
*
|
||||
* Direct use of flag is also acceptable: (MMF_MAP_FIXED | MMF_PREFETCH)
|
||||
*/
|
||||
#define MMF_CREATE(cntl, align) \
|
||||
(align ? (MMF_SET_CNTL((mm_flag_t)0, (cntl) | MMF_REQUEST_ALIGN) | \
|
||||
MMF_SET_ALIGN((mm_flag_t)0, align)) \
|
||||
#define MMF_CREATE(cntl, align) \
|
||||
((align) ? (MMF_SET_CNTL((mm_flag_t)0, (cntl) | MMF_REQUEST_ALIGN) | \
|
||||
MMF_SET_ALIGN((mm_flag_t)0, (align))) \
|
||||
: (MMF_SET_CNTL((mm_flag_t)0, (cntl) & ~MMF_REQUEST_ALIGN)))
|
||||
|
||||
#undef _DEF_FLAG
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
#include "mm_private.h"
|
||||
#include <mmu.h>
|
||||
|
||||
static void list_kernel_space(void)
|
||||
static void list_kmem(void)
|
||||
{
|
||||
rt_aspace_print_all(&rt_kernel_space);
|
||||
}
|
||||
MSH_CMD_EXPORT(list_kernel_space, List varea in kernel space);
|
||||
MSH_CMD_EXPORT(list_kmem, List varea in kernel virtual memory space);
|
||||
|
||||
void rt_kmem_list_varea(void) __attribute__((alias("list_kernel_space")));
|
||||
void rt_kmem_list(void) __attribute__((alias("list_kmem")));
|
||||
|
||||
static rt_ubase_t rt_pv_offset;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ static const char *get_name(rt_varea_t varea)
|
||||
return "dummy-mapper";
|
||||
}
|
||||
|
||||
void rt_varea_insert_page(rt_varea_t varea, void *page_addr)
|
||||
void rt_varea_pgmgr_insert(rt_varea_t varea, void *page_addr)
|
||||
{
|
||||
rt_page_t page = rt_page_addr2page(page_addr);
|
||||
|
||||
@@ -41,7 +41,7 @@ void rt_varea_insert_page(rt_varea_t varea, void *page_addr)
|
||||
}
|
||||
}
|
||||
|
||||
void rt_varea_free_pages(rt_varea_t varea)
|
||||
void rt_varea_pgmgr_pop_all(rt_varea_t varea)
|
||||
{
|
||||
rt_page_t page = varea->frames;
|
||||
|
||||
@@ -54,7 +54,7 @@ void rt_varea_free_pages(rt_varea_t varea)
|
||||
}
|
||||
}
|
||||
|
||||
void rt_varea_offload_page(rt_varea_t varea, void *vaddr, rt_size_t size)
|
||||
void rt_varea_pgmgr_pop(rt_varea_t varea, void *vaddr, rt_size_t size)
|
||||
{
|
||||
void *vend = vaddr + size;
|
||||
while (vaddr != vend)
|
||||
@@ -67,7 +67,7 @@ void rt_varea_offload_page(rt_varea_t varea, void *vaddr, rt_size_t size)
|
||||
}
|
||||
}
|
||||
|
||||
static void on_page_fault(struct rt_varea *varea, struct rt_mm_fault_msg *msg)
|
||||
static void on_page_fault(struct rt_varea *varea, struct rt_aspace_fault_msg *msg)
|
||||
{
|
||||
void *page;
|
||||
page = rt_pages_alloc(0);
|
||||
@@ -82,7 +82,7 @@ static void on_page_fault(struct rt_varea *varea, struct rt_mm_fault_msg *msg)
|
||||
msg->response.size = ARCH_PAGE_SIZE;
|
||||
msg->response.vaddr = page;
|
||||
|
||||
rt_varea_insert_page(varea, page);
|
||||
rt_varea_pgmgr_insert(varea, page);
|
||||
}
|
||||
|
||||
static void on_varea_open(struct rt_varea *varea)
|
||||
@@ -96,7 +96,7 @@ static void on_varea_close(struct rt_varea *varea)
|
||||
|
||||
static void on_page_offload(rt_varea_t varea, void *vaddr, rt_size_t size)
|
||||
{
|
||||
rt_varea_offload_page(varea, vaddr, size);
|
||||
rt_varea_pgmgr_pop(varea, vaddr, size);
|
||||
}
|
||||
|
||||
struct rt_mem_obj rt_mm_dummy_mapper = {
|
||||
|
||||
@@ -59,13 +59,13 @@ static void hint_free(rt_mm_va_hint_t hint)
|
||||
hint->prefer = rt_mpr_start;
|
||||
}
|
||||
|
||||
static void on_page_fault(struct rt_varea *varea, struct rt_mm_fault_msg *msg)
|
||||
static void on_page_fault(struct rt_varea *varea, struct rt_aspace_fault_msg *msg)
|
||||
{
|
||||
void *init_start = (void *)init_mpr_align_start;
|
||||
void *init_end = (void *)init_mpr_align_end;
|
||||
if (msg->vaddr < init_end && msg->vaddr >= init_start)
|
||||
if (msg->fault_vaddr < init_end && msg->fault_vaddr >= init_start)
|
||||
{
|
||||
rt_size_t offset = msg->vaddr - init_start;
|
||||
rt_size_t offset = msg->fault_vaddr - init_start;
|
||||
msg->response.status = MM_FAULT_STATUS_OK;
|
||||
msg->response.vaddr = init_mpr_cont_start + offset;
|
||||
msg->response.size = ARCH_PAGE_SIZE;
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
* Date Author Notes
|
||||
* 2022-11-14 WangXiaoyao the first version
|
||||
*/
|
||||
#ifndef __MM_INTERN_H__
|
||||
#define __MM_INTERN_H__
|
||||
#ifndef __MM_PRIVATE_H__
|
||||
#define __MM_PRIVATE_H__
|
||||
|
||||
#include "mm_aspace.h"
|
||||
#include <rtdef.h>
|
||||
@@ -44,7 +44,7 @@ struct _mm_range
|
||||
rt_err_t _aspace_bst_init(struct rt_aspace *aspace);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @brief Retrieve any varea if start in [varea->start, varea->end]
|
||||
*
|
||||
* @param aspace
|
||||
* @param start
|
||||
@@ -53,8 +53,7 @@ rt_err_t _aspace_bst_init(struct rt_aspace *aspace);
|
||||
struct rt_varea *_aspace_bst_search(struct rt_aspace *aspace, void *start);
|
||||
|
||||
/**
|
||||
* @brief Retrieve lowest varea satisfies
|
||||
* ((varea->start >= start) || (varea->end >= start))
|
||||
* @brief Retrieve lowest varea satisfies (varea->start >= start)
|
||||
*
|
||||
* @param aspace
|
||||
* @param length
|
||||
@@ -91,4 +90,10 @@ void _aspace_bst_insert(struct rt_aspace *aspace, struct rt_varea *varea);
|
||||
*/
|
||||
void _aspace_bst_remove(struct rt_aspace *aspace, struct rt_varea *varea);
|
||||
|
||||
#endif /* __MM_INTERN_H__ */
|
||||
void rt_varea_pgmgr_pop(rt_varea_t varea, void *vaddr, rt_size_t size);
|
||||
|
||||
void rt_varea_pgmgr_pop_all(rt_varea_t varea);
|
||||
|
||||
int _varea_map_with_msg(rt_varea_t varea, struct rt_aspace_fault_msg *msg);
|
||||
|
||||
#endif /* __MM_PRIVATE_H__ */
|
||||
|
||||
Reference in New Issue
Block a user