Skip to content

Commit

Permalink
[mm] feat: cleanup codes & bugs fixup
Browse files Browse the repository at this point in the history
feat: moving varea pgmgr to anon.
Page manager is only a internal structure of anonymous mapping
currently. So it's moved to mm_anon.c now.
This patch also includes a bug fix of extra cleanup of varea in page
manager while doing varea_merge operations.

feat: remove restriction on page install

fixup: mm test case.
Using the assertion uassert_true(!(lwp_ref_dec(lwp) - 1)) instead of
uassert_true(!(lwp_ref_dec(lwp))) since the lwp_ref_dev returns the
previous value of the lwp reference

Signed-off-by: Shell <[email protected]>
  • Loading branch information
polarvid committed Oct 31, 2023
1 parent 70cc7a1 commit 8f9c70b
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 82 deletions.
93 changes: 88 additions & 5 deletions components/mm/mm_anon.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,67 @@ rt_err_t rt_aspace_anon_ref_dec(rt_mem_obj_t aobj)
return rc;
}

void rt_varea_pgmgr_insert(rt_varea_t varea, void *page_addr)
{
/* each mapping of page frame in the varea is binding with a reference */
rt_page_ref_inc(page_addr, 0);
}

/**
* Private unmapping of address space
*/
static void _pgmgr_pop_all(rt_varea_t varea)
{
rt_aspace_t aspace = varea->aspace;
char *iter = varea->start;
char *end_addr = iter + varea->size;

RT_ASSERT(iter < end_addr);
RT_ASSERT(!((long)iter & ARCH_PAGE_MASK));
RT_ASSERT(!((long)end_addr & ARCH_PAGE_MASK));

for (; iter != end_addr; iter += ARCH_PAGE_SIZE)
{
void *page_pa = rt_hw_mmu_v2p(aspace, iter);
char *page_va = rt_kmem_p2v(page_pa);
if (page_pa != ARCH_MAP_FAILED && page_va)
{
rt_hw_mmu_unmap(aspace, iter, ARCH_PAGE_SIZE);
rt_pages_free(page_va, 0);
}
}
}

static void _pgmgr_pop_range(rt_varea_t varea, void *rm_start, void *rm_end)
{
void *page_va;

RT_ASSERT(!((rt_ubase_t)rm_start & ARCH_PAGE_MASK));
RT_ASSERT(!((rt_ubase_t)rm_end & ARCH_PAGE_MASK));
while (rm_start != rm_end)
{
page_va = rt_hw_mmu_v2p(varea->aspace, rm_start);

if (page_va != ARCH_MAP_FAILED)
{
page_va -= PV_OFFSET;
LOG_D("%s: free page %p", __func__, page_va);
rt_varea_unmap_page(varea, rm_start);
rt_pages_free(page_va, 0);
}
rm_start += ARCH_PAGE_SIZE;
}
}

static const char *_anon_get_name(rt_varea_t varea)
{
return varea->aspace == _anon_obj_get_backup(varea->mem_obj) ? "anonymous" : "reference";
}

/**
* Migration handler on varea re-construction
*/

static void _anon_varea_open(struct rt_varea *varea)
{
rt_aspace_anon_ref_inc(varea->mem_obj);
Expand All @@ -127,7 +183,9 @@ static void _anon_varea_open(struct rt_varea *varea)
static void _anon_varea_close(struct rt_varea *varea)
{
rt_aspace_anon_ref_dec(varea->mem_obj);
rt_mm_dummy_mapper.on_varea_close(varea);

/* unmap and dereference page frames in the varea region */
_pgmgr_pop_all(varea);
}

static rt_err_t _anon_varea_expand(struct rt_varea *varea, void *new_vaddr, rt_size_t size)
Expand All @@ -137,21 +195,45 @@ static rt_err_t _anon_varea_expand(struct rt_varea *varea, void *new_vaddr, rt_s

static rt_err_t _anon_varea_shrink(rt_varea_t varea, void *new_start, rt_size_t size)
{
return rt_mm_dummy_mapper.on_varea_shrink(varea, new_start, size);
char *varea_start = varea->start;
void *rm_start;
void *rm_end;

if (varea_start == (char *)new_start)
{
rm_start = varea_start + size;
rm_end = varea_start + varea->size;
}
else /* if (varea_start < (char *)new_start) */
{
RT_ASSERT(varea_start < (char *)new_start);
rm_start = varea_start;
rm_end = new_start;
}

_pgmgr_pop_range(varea, rm_start, rm_end);
return RT_EOK;
}

static rt_err_t _anon_varea_split(struct rt_varea *existed, void *unmap_start, rt_size_t unmap_len, struct rt_varea *subset)
{
/* remove the resource in the unmap region, and do nothing for the subset */
_pgmgr_pop_range(existed, unmap_start, (char *)unmap_start + unmap_len);

_anon_varea_open(subset);
return rt_mm_dummy_mapper.on_varea_split(existed, unmap_start, unmap_len, subset);
return RT_EOK;
}

static rt_err_t _anon_varea_merge(struct rt_varea *merge_to, struct rt_varea *merge_from)
{
_anon_varea_close(merge_from);
return rt_mm_dummy_mapper.on_varea_merge(merge_to, merge_from);
/* do nothing for the varea merge */
return RT_EOK;
}

/**
* Private mapping of address space
*/

rt_inline void _map_page_in_varea(rt_aspace_t asapce, rt_varea_t varea,
struct rt_aspace_fault_msg *msg, char *fault_addr)
{
Expand All @@ -168,6 +250,7 @@ rt_inline void _map_page_in_varea(rt_aspace_t asapce, rt_varea_t varea,
}
}

/* page frame inquiry or allocation in backup address space */
static void *_get_page_from_backup(rt_aspace_t backup, rt_base_t offset_in_mobj)
{
void *frame_pa;
Expand Down
71 changes: 1 addition & 70 deletions components/mm/mm_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

#define DBG_TAG "mm.object"
#define DBG_LVL DBG_INFO
#include "rtdbg.h"
#include <rtdbg.h>

#include <rtthread.h>

Expand All @@ -31,31 +31,6 @@ static const char *get_name(rt_varea_t varea)
return "dummy-mapper";
}

void rt_varea_pgmgr_insert(rt_varea_t varea, void *page_addr)
{
/* each mapping of page frame in the varea is binding with a reference */
rt_page_ref_inc(page_addr, 0);
}

/* resource recycling of page frames */
void rt_varea_pgmgr_pop_all(rt_varea_t varea)
{
rt_aspace_t aspace = varea->aspace;
char *end_addr = varea->start + varea->size;
RT_ASSERT(!((long)end_addr & ARCH_PAGE_MASK));

for (char *iter = varea->start; iter != end_addr; iter += ARCH_PAGE_SIZE)
{
void *page_pa = rt_hw_mmu_v2p(aspace, iter);
char *page_va = rt_kmem_p2v(page_pa);
if (page_pa != ARCH_MAP_FAILED && page_va)
{
rt_hw_mmu_unmap(aspace, iter, ARCH_PAGE_SIZE);
rt_pages_free(page_va, 0);
}
}
}

static void on_page_fault(struct rt_varea *varea, struct rt_aspace_fault_msg *msg)
{
void *page;
Expand All @@ -79,69 +54,25 @@ static void on_varea_open(struct rt_varea *varea)

static void on_varea_close(struct rt_varea *varea)
{
/* unmap and dereference page frames in the varea region */
rt_varea_pgmgr_pop_all(varea);
}

static rt_err_t on_varea_expand(struct rt_varea *varea, void *new_vaddr, rt_size_t size)
{
return RT_EOK;
}

static void _remove_pages(rt_varea_t varea, void *rm_start, void *rm_end)
{
void *page_va;

RT_ASSERT(!((rt_ubase_t)rm_start & ARCH_PAGE_MASK));
RT_ASSERT(!((rt_ubase_t)rm_end & ARCH_PAGE_MASK));
while (rm_start != rm_end)
{
page_va = rt_hw_mmu_v2p(varea->aspace, rm_start);

if (page_va != ARCH_MAP_FAILED)
{
page_va -= PV_OFFSET;
LOG_D("%s: free page %p", __func__, page_va);
rt_varea_unmap_page(varea, rm_start);
rt_pages_free(page_va, 0);
}
rm_start += ARCH_PAGE_SIZE;
}
}

static rt_err_t on_varea_shrink(rt_varea_t varea, void *new_start, rt_size_t size)
{
char *varea_start = varea->start;
void *rm_start;
void *rm_end;

if (varea_start == (char *)new_start)
{
rm_start = varea_start + size;
rm_end = varea_start + varea->size;
}
else /* if (varea_start < (char *)new_start) */
{
RT_ASSERT(varea_start < (char *)new_start);
rm_start = varea_start;
rm_end = new_start;
}

_remove_pages(varea, rm_start, rm_end);
return RT_EOK;
}

static rt_err_t on_varea_split(struct rt_varea *existed, void *unmap_start, rt_size_t unmap_len, struct rt_varea *subset)
{
/* remove the resource in the unmap region, and do nothing for the subset */
_remove_pages(existed, unmap_start, (char *)unmap_start + unmap_len);

return RT_EOK;
}

static rt_err_t on_varea_merge(struct rt_varea *merge_to, struct rt_varea *merge_from)
{
/* do nothing for the migration */
return RT_EOK;
}

Expand Down
3 changes: 1 addition & 2 deletions components/mm/mm_page.c
Original file line number Diff line number Diff line change
Expand Up @@ -863,8 +863,7 @@ int rt_page_install(rt_region_t region)
{
int err = -RT_EINVAL;
if (region.end != region.start && !(region.start & ARCH_PAGE_MASK) &&
!(region.end & ARCH_PAGE_MASK) &&
!((region.end - region.start) & shadow_mask))
!(region.end & ARCH_PAGE_MASK))
{
void *head = addr_to_page(page_start, (void *)region.start);
void *tail = addr_to_page(page_start, (void *)region.end);
Expand Down
2 changes: 0 additions & 2 deletions components/mm/mm_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@ void _aspace_bst_insert(struct rt_aspace *aspace, struct rt_varea *varea);
*/
void _aspace_bst_remove(struct rt_aspace *aspace, struct rt_varea *varea);

void rt_varea_pgmgr_pop_all(rt_varea_t varea);

int rt_varea_fix_private_locked(rt_varea_t ex_varea, void *pa,
struct rt_aspace_fault_msg *msg,
rt_bool_t dont_copy);
Expand Down
4 changes: 2 additions & 2 deletions examples/utest/testcases/mm/mm_lwp_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ static void test_user_map_varea(void)
uassert_true(varea->start != 0);
uassert_true(varea->start >= (void *)USER_VADDR_START && varea->start < (void *)USER_VADDR_TOP);

uassert_true(!lwp_ref_dec(lwp));
uassert_true(!(lwp_ref_dec(lwp) - 1));
}

static void test_user_map_varea_ext(void)
Expand All @@ -91,7 +91,7 @@ static void test_user_map_varea_ext(void)
uassert_true(varea->start != 0);
uassert_true(varea->start >= (void *)USER_VADDR_START && varea->start < (void *)USER_VADDR_TOP);

uassert_true(!lwp_ref_dec(lwp));
uassert_true(!(lwp_ref_dec(lwp) - 1));
}

static void user_map_varea_tc(void)
Expand Down
2 changes: 1 addition & 1 deletion libcpu/aarch64/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ bsp_path = Dir('#').abspath

if not os.path.exists(bsp_path + "/link.lds"):
Env['LINKFLAGS'] = Env['LINKFLAGS'].replace('link.lds', cwd + "/link.lds")
# fix the linker with crtx.o
Preprocessing("link.lds.S", ".lds", CPPPATH=[bsp_path])

# fix the linker with crtx.o
Env['LINKFLAGS'] += ' -nostartfiles'

# add common code files
Expand Down

0 comments on commit 8f9c70b

Please sign in to comment.