[rt-smart] kernel virtual memory management layer (#6809)

synchronize virtual memory system works.
adding kernel virtual memory management layer for page-based MMU enabled architecture
porting libcpu MMU codes
porting lwp memory related codes
This commit is contained in:
Shell
2023-01-08 21:08:55 -05:00
committed by GitHub
parent 7f9ccd3c80
commit 7450ef6c4d
121 changed files with 5947 additions and 7041 deletions
+18 -16
View File
@@ -8,16 +8,13 @@
* 2021-05-18 Jesven first version
*/
#include <rtthread.h>
#include <rthw.h>
#include <rtthread.h>
#ifdef ARCH_MM_MMU
#include <mmu.h>
#include <page.h>
#include <lwp_mm_area.h>
#include <lwp_user_mm.h>
#include <lwp_arch.h>
#include <lwp_user_mm.h>
extern size_t MMUTable[];
@@ -25,7 +22,7 @@ int arch_user_space_init(struct rt_lwp *lwp)
{
size_t *mmu_table;
mmu_table = (size_t*)rt_pages_alloc(0);
mmu_table = (size_t *)rt_pages_alloc(0);
if (!mmu_table)
{
return -1;
@@ -34,25 +31,28 @@ int arch_user_space_init(struct rt_lwp *lwp)
lwp->end_heap = USER_HEAP_VADDR;
memset(mmu_table, 0, ARCH_PAGE_SIZE);
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, ARCH_PAGE_SIZE);
rt_hw_mmu_map_init(&lwp->mmu_info, (void*)USER_VADDR_START, USER_VADDR_TOP - USER_VADDR_START, mmu_table, PV_OFFSET);
lwp->aspace = rt_aspace_create(
(void *)USER_VADDR_START, USER_VADDR_TOP - USER_VADDR_START, mmu_table);
if (!lwp->aspace)
{
return -1;
}
return 0;
}
void *arch_kernel_mmu_table_get(void)
{
return (void*)NULL;
}
void arch_kuser_init(rt_mmu_info *mmu_info, void *vectors)
{
return (void *)NULL;
}
void arch_user_space_vtable_free(struct rt_lwp *lwp)
{
if (lwp && lwp->mmu_info.vtable)
if (lwp && lwp->aspace->page_table)
{
rt_pages_free(lwp->mmu_info.vtable, 0);
rt_pages_free(lwp->aspace->page_table, 0);
lwp->aspace->page_table = NULL;
}
}
@@ -62,9 +62,11 @@ int arch_expand_user_stack(void *addr)
size_t stack_addr = (size_t)addr;
stack_addr &= ~ARCH_PAGE_MASK;
if ((stack_addr >= (size_t)USER_STACK_VSTART) && (stack_addr < (size_t)USER_STACK_VEND))
if ((stack_addr >= (size_t)USER_STACK_VSTART) &&
(stack_addr < (size_t)USER_STACK_VEND))
{
void *map = lwp_map_user(lwp_self(), (void*)stack_addr, ARCH_PAGE_SIZE, 0);
void *map =
lwp_map_user(lwp_self(), (void *)stack_addr, ARCH_PAGE_SIZE, 0);
if (map || lwp_user_accessable(addr, 1))
{
+6 -5
View File
@@ -1,3 +1,4 @@
#include "mm_aspace.h"
#include <rtthread.h>
#include <stdint.h>
#include <string.h>
@@ -18,7 +19,7 @@ typedef struct
} Elf32_sym;
#ifdef ARCH_MM_MMU
void arch_elf_reloc(rt_mmu_info *m_info, void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf32_sym *dynsym)
void arch_elf_reloc(rt_aspace_t aspace, void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf32_sym *dynsym)
{
size_t rel_off;
void* addr;
@@ -36,14 +37,14 @@ void arch_elf_reloc(rt_mmu_info *m_info, void *text_start, void *rel_dyn_start,
memcpy(&v2, rel_dyn_start + rel_off + 4, 4);
*/
addr = rt_hw_mmu_v2p(m_info, (void*)((char*)rel_dyn_start + rel_off));
addr = rt_hw_mmu_v2p(aspace, (void*)((char*)rel_dyn_start + rel_off));
addr = (void*)((char*)addr - PV_OFFSET);
memcpy(&v1, addr, 4);
addr = rt_hw_mmu_v2p(m_info, (void*)((char*)rel_dyn_start + rel_off + 4));
addr = rt_hw_mmu_v2p(aspace, (void*)((char*)rel_dyn_start + rel_off + 4));
addr = (void*)((char*)addr - PV_OFFSET);
memcpy(&v2, addr, 4);
addr = rt_hw_mmu_v2p(m_info, (void*)((char*)text_start + v1));
addr = rt_hw_mmu_v2p(aspace, (void*)((char*)text_start + v1));
addr = (void*)((char*)addr - PV_OFFSET);
if ((v2 & 0xff) == R_ARM_RELATIVE)
{
@@ -69,7 +70,7 @@ void arch_elf_reloc(rt_mmu_info *m_info, void *text_start, void *rel_dyn_start,
for (rel_off = 0; rel_off < got_size; rel_off += 4, got_item++)
{
//*got_item += (uint32_t)text_start;
addr = rt_hw_mmu_v2p(m_info, got_item);
addr = rt_hw_mmu_v2p(aspace, got_item);
addr = (void*)((char*)addr - PV_OFFSET);
*(uint32_t *)addr += (uint32_t)text_start;
}
+29 -21
View File
@@ -8,64 +8,72 @@
* 2019-10-28 Jesven first version
*/
#include <rtthread.h>
#include <rthw.h>
#include <rtthread.h>
#include <stddef.h>
#ifdef ARCH_MM_MMU
#include <mmu.h>
#include <page.h>
#include <lwp_mm_area.h>
#include <lwp_user_mm.h>
#include <lwp_arch.h>
#include <lwp_user_mm.h>
extern size_t MMUTable[];
#define KPTE_START (KERNEL_VADDR_START >> ARCH_SECTION_SHIFT)
int arch_user_space_init(struct rt_lwp *lwp)
{
size_t *mmu_table;
mmu_table = (size_t*)rt_pages_alloc(2);
mmu_table = (size_t *)rt_pages_alloc(2);
if (!mmu_table)
{
return -1;
}
lwp->end_heap = USER_HEAP_VADDR;
rt_memcpy(mmu_table + (KERNEL_VADDR_START >> ARCH_SECTION_SHIFT), MMUTable + (KERNEL_VADDR_START >> ARCH_SECTION_SHIFT), ARCH_PAGE_SIZE);
rt_memcpy(mmu_table + KPTE_START, (size_t *)rt_kernel_space.page_table + KPTE_START, ARCH_PAGE_SIZE);
rt_memset(mmu_table, 0, 3 * ARCH_PAGE_SIZE);
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, 4 * ARCH_PAGE_SIZE);
rt_hw_mmu_map_init(&lwp->mmu_info, (void*)USER_VADDR_START, USER_VADDR_TOP - USER_VADDR_START, mmu_table, PV_OFFSET);
lwp->aspace = rt_aspace_create((void *)USER_VADDR_START, USER_VADDR_TOP - USER_VADDR_START, mmu_table);
if (!lwp->aspace)
{
return -1;
}
return 0;
}
void *arch_kernel_mmu_table_get(void)
{
return (void*)((char*)MMUTable + PV_OFFSET);
}
static struct rt_varea kuser_varea;
void arch_kuser_init(rt_mmu_info *mmu_info, void *vectors)
void arch_kuser_init(rt_aspace_t aspace, void *vectors)
{
const size_t kuser_size = 0x1000;
int err;
extern char __kuser_helper_start[], __kuser_helper_end[];
int kuser_sz = __kuser_helper_end - __kuser_helper_start;
rt_hw_mmu_map_auto(mmu_info, vectors, 0x1000, MMU_MAP_U_RO);
err = rt_aspace_map_static(aspace, &kuser_varea, &vectors, kuser_size,
MMU_MAP_U_RO, MMF_MAP_FIXED | MMF_PREFETCH,
&rt_mm_dummy_mapper, 0);
if (err != 0)
while (1)
; // early failed
rt_memcpy((void*)((char*)vectors + 0x1000 - kuser_sz), __kuser_helper_start, kuser_sz);
rt_memcpy((void *)((char *)vectors + 0x1000 - kuser_sz), __kuser_helper_start, kuser_sz);
/*
* vectors + 0xfe0 = __kuser_get_tls
* vectors + 0xfe8 = hardware TLS instruction at 0xffff0fe8
*/
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, (void*)((char*)vectors + 0x1000 - kuser_sz), kuser_sz);
rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, (void*)((char*)vectors + 0x1000 - kuser_sz), kuser_sz);
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, (void *)((char *)vectors + 0x1000 - kuser_sz), kuser_sz);
rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, (void *)((char *)vectors + 0x1000 - kuser_sz), kuser_sz);
}
void arch_user_space_vtable_free(struct rt_lwp *lwp)
{
if (lwp && lwp->mmu_info.vtable)
if (lwp && lwp->aspace->page_table)
{
rt_pages_free(lwp->mmu_info.vtable, 2);
rt_pages_free(lwp->aspace->page_table, 2);
lwp->aspace->page_table = NULL;
}
}
@@ -77,7 +85,7 @@ int arch_expand_user_stack(void *addr)
stack_addr &= ~ARCH_PAGE_MASK;
if ((stack_addr >= (size_t)USER_STACK_VSTART) && (stack_addr < (size_t)USER_STACK_VEND))
{
void *map = lwp_map_user(lwp_self(), (void*)stack_addr, ARCH_PAGE_SIZE, 0);
void *map = lwp_map_user(lwp_self(), (void *)stack_addr, ARCH_PAGE_SIZE, 0);
if (map || lwp_user_accessable(addr, 1))
{
+18 -37
View File
@@ -15,42 +15,24 @@
* 2021-11-22 JasonHu add lwp_set_thread_context
* 2021-11-30 JasonHu add clone/fork support
*/
#include <rthw.h>
#include <rtthread.h>
#include <stddef.h>
#ifdef ARCH_MM_MMU
#include <mmu.h>
#include <page.h>
#include <lwp_mm_area.h>
#include <lwp_user_mm.h>
#include <lwp.h>
#include <lwp_arch.h>
#include <lwp_user_mm.h>
#include <page.h>
#include <stack.h>
#include <cpuport.h>
#include <encoding.h>
#include <stack.h>
extern rt_ubase_t MMUTable[];
int arch_expand_user_stack(void *addr)
{
int ret = 0;
rt_ubase_t stack_addr = (rt_ubase_t)addr;
stack_addr &= ~PAGE_OFFSET_MASK;
if ((stack_addr >= (rt_ubase_t)USER_STACK_VSTART) && (stack_addr < (rt_ubase_t)USER_STACK_VEND))
{
void *map = lwp_map_user(lwp_self(), (void *)stack_addr, PAGE_SIZE, RT_FALSE);
if (map || lwp_user_accessable(addr, 1))
{
ret = 1;
}
}
return ret;
}
void *lwp_copy_return_code_to_user_stack()
{
void lwp_thread_return();
@@ -68,13 +50,6 @@ void *lwp_copy_return_code_to_user_stack()
return RT_NULL;
}
rt_mmu_info *arch_kernel_get_mmu_info(void)
{
extern rt_mmu_info *mmu_info;
return mmu_info;
}
rt_ubase_t lwp_fix_sp(rt_ubase_t cursp)
{
void lwp_thread_return();
@@ -120,9 +95,14 @@ int arch_user_space_init(struct rt_lwp *lwp)
lwp->end_heap = USER_HEAP_VADDR;
rt_memcpy(mmu_table, MMUTable, PAGE_SIZE);
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, 4 * PAGE_SIZE);
rt_hw_mmu_map_init(&lwp->mmu_info, (void *)USER_VADDR_START, USER_VADDR_TOP - USER_VADDR_START, (rt_size_t *)mmu_table, 0);
rt_memcpy(mmu_table, MMUTable, ARCH_PAGE_SIZE);
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, ARCH_PAGE_SIZE);
lwp->aspace = rt_aspace_create(
(void *)USER_VADDR_START, USER_VADDR_TOP - USER_VADDR_START, mmu_table);
if (!lwp->aspace)
{
return -1;
}
return 0;
}
@@ -134,9 +114,10 @@ void *arch_kernel_mmu_table_get(void)
void arch_user_space_vtable_free(struct rt_lwp *lwp)
{
if (lwp && lwp->mmu_info.vtable)
if (lwp && lwp->aspace->page_table)
{
rt_pages_free(lwp->mmu_info.vtable, 0);
rt_pages_free(lwp->aspace->page_table, 0);
lwp->aspace->page_table = NULL;
}
}
@@ -253,7 +234,7 @@ int arch_set_thread_context(void (*exit)(void), void *new_thread_stack,
*/
void lwp_exec_user(void *args, void *kernel_stack, void *user_entry)
{
arch_start_umode(args, user_entry, (void*)USER_STACK_VEND, kernel_stack);
arch_start_umode(args, user_entry, (void *)USER_STACK_VEND, kernel_stack);
}
void *arch_get_usp_from_uctx(struct rt_user_context *uctx)
+3 -6
View File
@@ -10,9 +10,9 @@
#ifndef LWP_ARCH_H__
#define LWP_ARCH_H__
#include <rthw.h>
#include <lwp.h>
#include <lwp_arch_comm.h>
#include <riscv_mmu.h>
#ifdef ARCH_MM_MMU
@@ -30,7 +30,7 @@
#define USER_HEAP_VEND 0xffffffffffff0000UL
#define USER_STACK_VSTART 0x270000000UL
#define USER_STACK_VEND USER_HEAP_VADDR
#define USER_VADDR_START 0x100000000UL
#define USER_VADDR_START 0x200000000UL
#define USER_VADDR_TOP 0xfffffffffffff000UL
#define USER_LOAD_VADDR 0x200000000
#define LDSO_LOAD_VADDR 0x200000000
@@ -49,9 +49,6 @@
extern "C" {
#endif
rt_mmu_info* arch_kernel_get_mmu_info(void);
int arch_expand_user_stack(void *addr);
rt_inline unsigned long rt_hw_ffz(unsigned long x)
{
return __builtin_ffsl(~x) - 1;
@@ -59,7 +56,7 @@ rt_inline unsigned long rt_hw_ffz(unsigned long x)
rt_inline void icache_invalid_all(void)
{
//TODO:
rt_hw_cpu_icache_invalidate_all();
}
#ifdef __cplusplus
+6 -5
View File
@@ -1,3 +1,4 @@
#include "mm_aspace.h"
#include <rtthread.h>
#include <stdint.h>
#include <string.h>
@@ -18,7 +19,7 @@ typedef struct
} Elf64_sym;
#ifdef ARCH_MM_MMU
void arch_elf_reloc(rt_mmu_info *m_info, void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf64_sym *dynsym)
void arch_elf_reloc(rt_aspace_t aspace, void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf64_sym *dynsym)
{
size_t rel_off;
void* addr;
@@ -31,12 +32,12 @@ void arch_elf_reloc(rt_mmu_info *m_info, void *text_start, void *rel_dyn_start,
{
uint32_t v1, v2;
addr = rt_hw_mmu_v2p(m_info, (void *)(((rt_size_t)rel_dyn_start) + rel_off));
addr = rt_hw_mmu_v2p(aspace, (void *)(((rt_size_t)rel_dyn_start) + rel_off));
memcpy(&v1, addr, 4);
addr = rt_hw_mmu_v2p(m_info, (void *)(((rt_size_t)rel_dyn_start) + rel_off + 4));
addr = rt_hw_mmu_v2p(aspace, (void *)(((rt_size_t)rel_dyn_start) + rel_off + 4));
memcpy(&v2, addr, 4);
addr = rt_hw_mmu_v2p(m_info, (void *)((rt_size_t)text_start + v1));
addr = rt_hw_mmu_v2p(aspace, (void *)((rt_size_t)text_start + v1));
if ((v2 & 0xff) == R_ARM_RELATIVE)
{
*(rt_size_t*)addr += (rt_size_t)text_start;
@@ -58,7 +59,7 @@ void arch_elf_reloc(rt_mmu_info *m_info, void *text_start, void *rel_dyn_start,
for (rel_off = 0; rel_off < got_size; rel_off += 4, got_item++)
{
addr = rt_hw_mmu_v2p(m_info, got_item);
addr = rt_hw_mmu_v2p(aspace, got_item);
*(rt_size_t *)addr += (rt_size_t)text_start;
}
}
+33 -39
View File
@@ -12,33 +12,40 @@
#include <ioremap.h>
#ifdef ARCH_MM_MMU
#ifdef RT_USING_SMART
#include <mmu.h>
#include <lwp_mm_area.h>
#include <lwp_mm.h>
#include <mm_aspace.h>
static struct lwp_avl_struct *k_map_area;
extern rt_mmu_info mmu_info;
#define DBG_TAG "mm.ioremap"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
static void _iounmap_range(void *addr, size_t size)
enum ioremap_type
{
void *va = RT_NULL, *pa = RT_NULL;
int i = 0;
MM_AREA_TYPE_PHY,
MM_AREA_TYPE_PHY_CACHED
};
for (va = addr, i = 0; i < size; va = (void *)((char *)va + ARCH_PAGE_SIZE), i += ARCH_PAGE_SIZE)
{
pa = rt_hw_mmu_v2p(&mmu_info, va);
if (pa)
{
rt_hw_mmu_unmap(&mmu_info, va, ARCH_PAGE_SIZE);
}
}
}
void *rt_ioremap_start;
size_t rt_ioremap_size;
static void *_ioremap_type(void *paddr, size_t size, int type)
static void *_ioremap_type(void *paddr, size_t size, enum ioremap_type type)
{
void *v_addr = NULL;
size_t attr;
size_t lo_off;
int err;
lo_off = (uintptr_t)paddr & ARCH_PAGE_MASK;
struct rt_mm_va_hint hint = {
.prefer = ARCH_MAP_FAILED,
.map_size = RT_ALIGN(size + lo_off, ARCH_PAGE_SIZE),
.flags = 0,
.limit_start = rt_ioremap_start,
.limit_range_size = rt_ioremap_size,
};
switch (type)
{
@@ -51,19 +58,17 @@ static void *_ioremap_type(void *paddr, size_t size, int type)
default:
return v_addr;
}
err = rt_aspace_map_phy(&rt_kernel_space, &hint, attr, MM_PA_TO_OFF(paddr), &v_addr);
rt_mm_lock();
v_addr = rt_hw_mmu_map(&mmu_info, 0, paddr, size, attr);
if (v_addr)
if (err)
{
int ret = lwp_map_area_insert(&k_map_area, (size_t)v_addr, size, type);
if (ret != 0)
{
_iounmap_range(v_addr, size);
v_addr = NULL;
}
LOG_W("IOREMAP 0x%lx failed", paddr);
v_addr = NULL;
}
else
{
v_addr = v_addr + lo_off;
}
rt_mm_unlock();
return v_addr;
}
@@ -84,18 +89,7 @@ void *rt_ioremap_cached(void *paddr, size_t size)
void rt_iounmap(volatile void *vaddr)
{
struct lwp_avl_struct *ma_avl_node;
rt_mm_lock();
ma_avl_node = lwp_map_find(k_map_area, (size_t)vaddr);
if (ma_avl_node)
{
struct rt_mm_area_struct *ma = (struct rt_mm_area_struct *)ma_avl_node->data;
_iounmap_range((void *)ma->addr, ma->size);
lwp_map_area_remove(&k_map_area, (size_t)vaddr);
}
rt_mm_unlock();
rt_aspace_unmap(&rt_kernel_space, (void *)vaddr, 1);
}
#else
+5
View File
@@ -10,6 +10,8 @@
#ifndef __IOREMAP_H__
#define __IOREMAP_H__
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
@@ -19,6 +21,9 @@ void *rt_ioremap_nocache(void *paddr, size_t size);
void *rt_ioremap_cached (void *paddr, size_t size);
void rt_iounmap(volatile void *addr);
extern void *rt_ioremap_start;
extern size_t rt_ioremap_size;
#ifdef __cplusplus
}
#endif
+8 -10
View File
@@ -37,7 +37,6 @@
#include <rtdbg.h>
#ifdef ARCH_MM_MMU
#include <lwp_mm_area.h>
#include <lwp_user_mm.h>
#endif /* end of ARCH_MM_MMU */
@@ -183,7 +182,7 @@ struct process_aux *lwp_argscopy(struct rt_lwp *lwp, int argc, char **argv, char
return RT_NULL;
}
args_k = (size_t *)rt_hw_mmu_v2p(&lwp->mmu_info, args);
args_k = (size_t *)lwp_v2p(lwp, args);
args_k = (size_t *)((size_t)args_k - PV_OFFSET);
/* argc, argv[], 0, envp[], 0 , aux[] */
@@ -511,7 +510,6 @@ static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, str
void *pa, *va;
void *va_self;
rt_mmu_info *m_info = &lwp->mmu_info;
#endif
if (len < sizeof eheader)
@@ -613,7 +611,7 @@ static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, str
LOG_E("lwp map user failed!");
return -RT_ERROR;
}
pa = rt_hw_mmu_v2p(m_info, va);
pa = lwp_v2p(lwp, va);
process_header = (uint8_t *)pa - PV_OFFSET;
#else
process_header = (uint8_t *)rt_malloc(process_header_size + sizeof(char[16]));
@@ -646,7 +644,7 @@ static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, str
random = (uint8_t *)(USER_VADDR_TOP - ARCH_PAGE_SIZE - sizeof(char[16]));
krandom = (uint8_t *)rt_hw_mmu_v2p(m_info, random);
krandom = (uint8_t *)lwp_v2p(lwp, random);
krandom = (uint8_t *)krandom - PV_OFFSET;
rt_memcpy(krandom, &random_value, sizeof random_value);
#else
@@ -738,7 +736,7 @@ static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, str
{
if (user_area[i].size != 0)
{
va = lwp_map_user(lwp, user_area[i].start, user_area[i].size, (int)(i == 0));
va = lwp_map_user(lwp, user_area[i].start, user_area[i].size, (i == 0));
if (!va || (va != user_area[i].start))
{
result = -RT_ERROR;
@@ -836,7 +834,7 @@ static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, str
read_len = 0;
while (size)
{
pa = rt_hw_mmu_v2p(m_info, va);
pa = lwp_v2p(lwp, va);
va_self = (void *)((char *)pa - PV_OFFSET);
LOG_D("va_self = %p pa = %p", va_self, pa);
tmp_len = (size < ARCH_PAGE_SIZE) ? size : ARCH_PAGE_SIZE;
@@ -864,7 +862,7 @@ static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, str
while (size)
{
size_s = (size < ARCH_PAGE_SIZE - off) ? size : ARCH_PAGE_SIZE - off;
pa = rt_hw_mmu_v2p(m_info, va);
pa = lwp_v2p(lwp, va);
va_self = (void *)((char *)pa - PV_OFFSET);
memset((void *)((char *)va_self + off), 0, size_s);
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, (void *)((char *)va_self + off), size_s);
@@ -942,7 +940,7 @@ static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, str
check_read(read_len, dynsym_size);
}
#ifdef ARCH_MM_MMU
arch_elf_reloc(m_info, (void *)load_off, rel_dyn_start, rel_dyn_size, got_start, got_size, dynsym);
arch_elf_reloc(lwp->aspace, (void *)load_off, rel_dyn_start, rel_dyn_size, got_start, got_size, dynsym);
#else
arch_elf_reloc((void *)load_off, rel_dyn_start, rel_dyn_size, got_start, got_size, dynsym);
@@ -1151,7 +1149,7 @@ pid_t lwp_execve(char *filename, int debug, int argc, char **argv, char **envp)
return -ENOMEM;
}
#ifdef ARCH_MM_MMU
if (lwp_user_space_init(lwp) != 0)
if (lwp_user_space_init(lwp, 0) != 0)
{
lwp_tid_put(tid);
lwp_ref_dec(lwp);
+10 -3
View File
@@ -28,6 +28,7 @@
#include "lwp_signal.h"
#include "lwp_syscall.h"
#include "lwp_avl.h"
#include "mm_aspace.h"
#ifdef ARCH_MM_MMU
#include "lwp_shm.h"
@@ -57,12 +58,18 @@ extern "C" {
#define LWP_ARG_MAX 8
struct rt_lwp_objs
{
rt_aspace_t source;
struct rt_mem_obj mem_obj;
};
struct rt_lwp
{
#ifdef ARCH_MM_MMU
rt_mmu_info mmu_info;
struct lwp_avl_struct *map_area;
size_t end_heap;
rt_aspace_t aspace;
struct rt_lwp_objs *lwp_obj;
#else
#ifdef ARCH_MM_MPU
struct rt_mpu_info mpu_info;
@@ -154,7 +161,7 @@ int lwp_execve(char *filename, int debug, int argc, char **argv, char **envp);
/*create by lwp_setsid.c*/
int setsid(void);
#ifdef ARCH_MM_MMU
void lwp_mmu_switch(struct rt_thread *thread);
void lwp_aspace_switch(struct rt_thread *thread);
#endif
void lwp_user_setting_save(rt_thread_t thread);
void lwp_user_setting_restore(rt_thread_t thread);
+6 -2
View File
@@ -10,7 +10,9 @@
#ifndef __LWP_ARCH_COMM__
#define __LWP_ARCH_COMM__
#include <mm_aspace.h>
#include <rtthread.h>
#include <mmu.h>
/**
* APIs that must port to all architectures
@@ -24,7 +26,9 @@ void arch_ret_to_user();
/* ELF relocation */
#ifdef ARCH_MM_MMU
void arch_elf_reloc(rt_mmu_info *m_info, void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, void *dynsym);
struct rt_lwp;
void arch_elf_reloc(rt_aspace_t aspace, void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, void *dynsym);
#else
void arch_elf_reloc(void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, void *dynsym);
#endif
@@ -42,7 +46,7 @@ void *arch_get_user_sp(void);
int arch_user_space_init(struct rt_lwp *lwp);
void arch_user_space_vtable_free(struct rt_lwp *lwp);
void *arch_kernel_mmu_table_get(void);
void arch_kuser_init(rt_mmu_info *mmu_info, void *vectors);
void arch_kuser_init(rt_aspace_t aspace, void *vectors);
int arch_expand_user_stack(void *addr);
/* thread id register */
-122
View File
@@ -1,122 +0,0 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-10-28 Jesven first version
*/
#include <rtthread.h>
#ifdef ARCH_MM_MMU
#include <lwp_mm_area.h>
int lwp_map_area_insert(struct lwp_avl_struct **avl_tree, size_t addr, size_t size, int ma_type)
{
struct lwp_avl_struct *node = RT_NULL;
struct rt_mm_area_struct *ma = RT_NULL;
if (!size)
{
return -1;
}
ma = (struct rt_mm_area_struct *)rt_malloc(sizeof(struct rt_mm_area_struct));
if (!ma)
{
return -1;
}
ma->addr = addr;
ma->size = size;
ma->type = ma_type;
node = (struct lwp_avl_struct *)rt_malloc(sizeof(struct lwp_avl_struct));
if (!node)
{
rt_free(ma);
return -1;
}
memset(node, 0, sizeof(struct lwp_avl_struct));
node->avl_key = ma->addr;
node->data = (void *)ma;
lwp_avl_insert(node, avl_tree);
return 0;
}
void lwp_map_area_remove(struct lwp_avl_struct **avl_tree, size_t addr)
{
struct lwp_avl_struct *node = RT_NULL;
node = lwp_avl_find(addr, *avl_tree);
if (!node)
{
return;
}
lwp_avl_remove(node, avl_tree);
rt_free(node->data);
rt_free(node);
}
struct lwp_avl_struct* lwp_map_find(struct lwp_avl_struct* ptree, size_t addr)
{
struct lwp_avl_struct *node = ptree;
while (1)
{
if (!node)
{
return node;
}
if ((size_t)node->avl_key <= addr)
{
struct rt_mm_area_struct *ma = (struct rt_mm_area_struct *)node->data;
if ((ma->addr <= addr) && (addr < ma->addr + ma->size))
{
/* find area */
break;
}
node = node->avl_right;
}
else
{
node = node->avl_left;
}
}
return node;
}
struct lwp_avl_struct* lwp_map_find_first(struct lwp_avl_struct* ptree)
{
if (ptree == AVL_EMPTY)
{
return (struct lwp_avl_struct *)0;
}
while (1)
{
if (!ptree->avl_left)
{
break;
}
ptree = ptree->avl_left;
}
return ptree;
}
int top_mem_fun(struct lwp_avl_struct* ptree, void *arg)
{
size_t *vs = (size_t *)arg;
struct rt_mm_area_struct *ma;
ma = (struct rt_mm_area_struct *)ptree->data;
*vs += ma->size;
return 0;
}
size_t lwp_vmem_count(struct lwp_avl_struct *ptree)
{
size_t vsize = 0;
lwp_avl_traversal(ptree, top_mem_fun, &vsize);
return vsize;
}
#endif
-53
View File
@@ -1,53 +0,0 @@
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-10-28 Jesven first version
*/
#ifndef __LWP_MM_AREA_H__
#define __LWP_MM_AREA_H__
#include <string.h>
#include <stdint.h>
#include <lwp_avl.h>
#ifdef ARCH_MM_MMU
#ifdef __cplusplus
extern "C" {
#endif
enum
{
MM_AREA_TYPE_PHY = 0, /* mm_area physical address is IO register or reserved memory no cached*/
MM_AREA_TYPE_PHY_CACHED, /* mm_area physical address is IO register or reserved memory with cached */
MM_AREA_TYPE_SHM, /* mm_area physical address is shared memory */
MM_AREA_TYPE_DATA, /* mm_area physical address is alloced from page manager for data */
MM_AREA_TYPE_TEXT, /* mm_area physical address is alloced from page manager for text */
MM_AREA_TYPE_UNKNOW,
};
struct rt_mm_area_struct
{
size_t addr;
size_t size;
int type;
};
int lwp_map_area_insert(struct lwp_avl_struct **avl_tree, size_t addr, size_t size, int ma_type);
void lwp_map_area_remove(struct lwp_avl_struct **avl_tree, size_t addr);
struct lwp_avl_struct* lwp_map_find(struct lwp_avl_struct* ptree, size_t addr);
struct lwp_avl_struct* lwp_map_find_first(struct lwp_avl_struct* ptree);
size_t lwp_vmem_count(struct lwp_avl_struct *ptree);
#ifdef __cplusplus
}
#endif
#endif
#endif /*__LWP_MM_AREA_H__*/
+59 -14
View File
@@ -15,12 +15,15 @@
#include <lwp_shm.h>
#include <lwp_mm.h>
#include <lwp_mm_area.h>
#include <lwp_user_mm.h>
#include <mmu.h>
#include <mm_aspace.h>
#include <mm_flag.h>
/* the kernel structure to represent a share-memory */
struct lwp_shm_struct
{
struct rt_mem_obj mem_obj;
size_t addr; /* point to the next item in the free list when not used */
size_t size;
int ref;
@@ -34,6 +37,35 @@ static int shm_free_list = -1; /* the single-direct list of freed items */
static int shm_id_used = 0; /* the latest allocated item in the array */
static struct lwp_shm_struct _shm_ary[RT_LWP_SHM_MAX_NR];
static const char *get_shm_name(rt_varea_t varea)
{
return "user.shm";
}
static void on_shm_varea_open(struct rt_varea *varea)
{
struct lwp_shm_struct *shm;
shm = rt_container_of(varea->mem_obj, struct lwp_shm_struct, mem_obj);
shm->ref += 1;
}
static void on_shm_varea_close(struct rt_varea *varea)
{
struct lwp_shm_struct *shm;
shm = rt_container_of(varea->mem_obj, struct lwp_shm_struct, mem_obj);
shm->ref -= 1;
}
static void on_shm_page_fault(struct rt_varea *varea, struct rt_mm_fault_msg *msg)
{
struct lwp_shm_struct *shm;
shm = rt_container_of(varea->mem_obj, struct lwp_shm_struct, mem_obj);
msg->response.status = MM_FAULT_STATUS_OK;
msg->response.vaddr = (void *)shm->addr;
msg->response.size = shm->size;
return ;
}
/*
* Try to allocate an structure 'lwp_shm_struct' from the freed list or the
* static array.
@@ -110,6 +142,12 @@ static int _lwp_shmget(size_t key, size_t size, int create)
p->size = (1UL << (bit + ARCH_PAGE_SHIFT));
p->ref = 0;
p->key = key;
p->mem_obj.get_name = get_shm_name;
p->mem_obj.on_page_fault = on_shm_page_fault;
p->mem_obj.on_varea_open = on_shm_varea_open;
p->mem_obj.on_varea_close = on_shm_varea_close;
p->mem_obj.hint_free = NULL;
p->mem_obj.on_page_offload = NULL;
/* then insert it into the balancing binary tree */
node_key = (struct lwp_avl_struct *)rt_malloc(sizeof(struct lwp_avl_struct) * 2);
@@ -212,15 +250,15 @@ int lwp_shmrm(int id)
{
int ret = 0;
rt_mm_lock();
ret = _lwp_shmrm(id);
rt_mm_unlock();
return ret;
}
/* Map the shared memory specified by 'id' to the specified virtual address. */
static void *_lwp_shmat(int id, void *shm_vaddr)
{
int err;
struct rt_lwp *lwp = RT_NULL;
struct lwp_avl_struct *node_key = RT_NULL;
struct lwp_shm_struct *p = RT_NULL;
@@ -244,10 +282,16 @@ static void *_lwp_shmat(int id, void *shm_vaddr)
{
return RT_NULL;
}
va = lwp_map_user_type(lwp, shm_vaddr, (void *)p->addr, p->size, 1, MM_AREA_TYPE_SHM);
if (va)
if (shm_vaddr == 0)
va = ARCH_MAP_FAILED;
else
va = shm_vaddr;
err = rt_aspace_map(lwp->aspace, &va, p->size, MMU_MAP_U_RWCB, MMF_PREFETCH,
&p->mem_obj, 0);
if (err != RT_EOK)
{
p->ref++;
va = 0;
}
return va;
}
@@ -261,9 +305,9 @@ void *lwp_shmat(int id, void *shm_vaddr)
{
return RT_NULL;
}
rt_mm_lock();
ret = _lwp_shmat(id, shm_vaddr);
rt_mm_unlock();
return ret;
}
@@ -276,7 +320,7 @@ static struct lwp_shm_struct *_lwp_shm_struct_get(struct rt_lwp *lwp, void *shm_
{
return RT_NULL;
}
pa = rt_hw_mmu_v2p(&lwp->mmu_info, shm_vaddr); /* physical memory */
pa = lwp_v2p(lwp, shm_vaddr); /* physical memory */
node_pa = lwp_avl_find((size_t)pa, shm_tree_pa);
if (!node_pa)
@@ -343,14 +387,15 @@ int _lwp_shmdt(void *shm_vaddr)
{
return -1;
}
ret = _lwp_shm_ref_dec(lwp, shm_vaddr);
if (ret >= 0)
ret = rt_aspace_unmap(lwp->aspace, shm_vaddr, 1);
if (ret != RT_EOK)
{
lwp_unmap_user_phy(lwp, shm_vaddr);
return 0;
ret = -1;
}
return -1;
return ret;
}
/* A wrapping function: detach the mapped shared memory. */
int lwp_shmdt(void *shm_vaddr)
{
+20 -12
View File
@@ -13,8 +13,11 @@
*/
#define _GNU_SOURCE
/* RT-Thread System call */
#include <rtthread.h>
#include <rthw.h>
#include <board.h>
#include <mm_aspace.h>
#include <string.h>
#include <lwp.h>
#ifdef ARCH_MM_MMU
@@ -1282,7 +1285,7 @@ rt_err_t sys_timer_create(clockid_t clockid, struct sigevent *restrict sevp, tim
#ifdef ARCH_MM_MMU
struct sigevent sevp_k;
timer_t timerid_k;
struct sigevent evp_default;
if (sevp == NULL)
{
sevp_k.sigev_notify = SIGEV_SIGNAL;
@@ -1362,7 +1365,7 @@ rt_thread_t sys_thread_create(void *arg[])
lwp = rt_thread_self()->lwp;
lwp_ref_inc(lwp);
#ifdef ARCH_MM_MMU
user_stack = lwp_map_user(lwp, 0, (size_t)arg[3], 0);
user_stack = lwp_map_user(lwp, 0, (size_t)arg[3], 0);
if (!user_stack)
{
goto fail;
@@ -1605,11 +1608,15 @@ rt_weak long sys_clone(void *arg[])
return _sys_clone(arg);
}
int lwp_dup_user(struct lwp_avl_struct* ptree, void *arg);
int lwp_dup_user(rt_varea_t varea, void *arg);
static int _copy_process(struct rt_lwp *dest_lwp, struct rt_lwp *src_lwp)
{
return lwp_avl_traversal(src_lwp->map_area, lwp_dup_user, dest_lwp);
int err;
dest_lwp->lwp_obj->source = src_lwp->aspace;
err = rt_aspace_traversal(src_lwp->aspace, lwp_dup_user, dest_lwp);
dest_lwp->lwp_obj->source = NULL;
return err;
}
static void lwp_struct_copy(struct rt_lwp *dst, struct rt_lwp *src)
@@ -1694,7 +1701,7 @@ int _sys_fork(void)
}
/* user space init */
if (lwp_user_space_init(lwp) != 0)
if (lwp_user_space_init(lwp, 1) != 0)
{
SET_ERRNO(ENOMEM);
goto fail;
@@ -2302,7 +2309,7 @@ int sys_execve(const char *path, char *const argv[], char *const envp[])
rt_memset(new_lwp, 0, sizeof(struct rt_lwp));
new_lwp->ref = 1;
lwp_user_object_lock_init(new_lwp);
ret = arch_user_space_init(new_lwp);
ret = lwp_user_space_init(new_lwp, 0);
if (ret != 0)
{
SET_ERRNO(ENOMEM);
@@ -2371,8 +2378,9 @@ int sys_execve(const char *path, char *const argv[], char *const envp[])
rt_pages_free(page, 0);
#ifdef ARCH_MM_MMU
_swap_lwp_data(lwp, new_lwp, rt_mmu_info, mmu_info);
_swap_lwp_data(lwp, new_lwp, struct lwp_avl_struct *, map_area);
_swap_lwp_data(lwp, new_lwp, struct rt_aspace *, aspace);
_swap_lwp_data(lwp, new_lwp, struct rt_lwp_objs *, lwp_obj);
_swap_lwp_data(lwp, new_lwp, size_t, end_heap);
#endif
_swap_lwp_data(lwp, new_lwp, uint8_t, lwp_type);
@@ -2392,7 +2400,7 @@ int sys_execve(const char *path, char *const argv[], char *const envp[])
/* to do: clsoe files with flag CLOEXEC */
lwp_mmu_switch(thread);
lwp_aspace_switch(thread);
rt_hw_interrupt_enable(level);
@@ -4562,17 +4570,17 @@ const static void* func_table[] =
SYSCALL_USPACE(SYSCALL_SIGN(sys_madvise)),
SYSCALL_SIGN(sys_sched_setparam),
SYSCALL_SIGN(sys_sched_getparam),
SYSCALL_SIGN(sys_sched_get_priority_max),
SYSCALL_SIGN(sys_sched_get_priority_max), /* 150 */
SYSCALL_SIGN(sys_sched_get_priority_min),
SYSCALL_SIGN(sys_sched_setscheduler),
SYSCALL_SIGN(sys_sched_getscheduler),
SYSCALL_SIGN(sys_setaffinity),
SYSCALL_SIGN(sys_fsync),
SYSCALL_SIGN(sys_fsync), /* 155 */
SYSCALL_SIGN(sys_clock_nanosleep),
SYSCALL_SIGN(sys_timer_create),
SYSCALL_SIGN(sys_timer_delete),
SYSCALL_SIGN(sys_timer_settime),
SYSCALL_SIGN(sys_timer_gettime),
SYSCALL_SIGN(sys_timer_gettime), /* 160 */
SYSCALL_SIGN(sys_timer_getoverrun),
SYSCALL_SIGN(sys_mq_open),
SYSCALL_SIGN(sys_mq_unlink),
File diff suppressed because it is too large Load Diff
+23 -10
View File
@@ -16,24 +16,24 @@
#ifdef ARCH_MM_MMU
#include <lwp.h>
#include <lwp_mm_area.h>
#include <mmu.h>
#include <mm_aspace.h>
#include <mm_fault.h>
#include <mm_page.h>
#ifdef __cplusplus
extern "C" {
#endif
int lwp_user_space_init(struct rt_lwp *lwp);
int lwp_user_space_init(struct rt_lwp *lwp, rt_bool_t is_fork);
void lwp_unmap_user_space(struct rt_lwp *lwp);
int lwp_unmap_user(struct rt_lwp *lwp, void *va);
void *lwp_map_user(struct rt_lwp *lwp, void *map_va, size_t map_size, int text);
void *lwp_map_user(struct rt_lwp *lwp, void *map_va, size_t map_size, rt_bool_t text);
void *lwp_map_user_phy(struct rt_lwp *lwp, void *map_va, void *map_pa, size_t map_size, int cached);
void *lwp_map_user_phy(struct rt_lwp *lwp, void *map_va, void *map_pa, size_t map_size, rt_bool_t cached);
int lwp_unmap_user_phy(struct rt_lwp *lwp, void *va);
void *lwp_map_user_type(struct rt_lwp *lwp, void *map_va, void *map_pa, size_t map_size, int cached, int type);
int lwp_unmap_user_type(struct rt_lwp *lwp, void *va);
rt_base_t lwp_brk(void *addr);
void* lwp_mmap2(void *addr, size_t length, int prot, int flags, int fd, off_t pgoffset);
int lwp_munmap(void *addr);
@@ -42,9 +42,22 @@ size_t lwp_get_from_user(void *dst, void *src, size_t size);
size_t lwp_put_to_user(void *dst, void *src, size_t size);
int lwp_user_accessable(void *addr, size_t size);
size_t lwp_data_get(rt_mmu_info *mmu_info, void *dst, void *src, size_t size);
size_t lwp_data_put(rt_mmu_info *mmu_info, void *dst, void *src, size_t size);
void lwp_data_cache_flush(rt_mmu_info *mmu_info, void *vaddr, size_t size);
size_t lwp_data_get(struct rt_lwp *lwp, void *dst, void *src, size_t size);
size_t lwp_data_put(struct rt_lwp *lwp, void *dst, void *src, size_t size);
void lwp_data_cache_flush(struct rt_lwp *lwp, void *vaddr, size_t size);
static inline void *_lwp_v2p(struct rt_lwp *lwp, void *vaddr)
{
return rt_hw_mmu_v2p(lwp->aspace, vaddr);
}
static inline void *lwp_v2p(struct rt_lwp *lwp, void *vaddr)
{
RD_LOCK(lwp->aspace);
void *paddr = _lwp_v2p(lwp, vaddr);
RD_UNLOCK(lwp->aspace);
return paddr;
}
#ifdef __cplusplus
}
-424
View File
@@ -1,424 +0,0 @@
/*
* Copyright (c) 2006-2019, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-11-01 Jesven The first version
*/
#include <stdint.h>
#include <rthw.h>
#include <rtthread.h>
#ifdef ARCH_MM_MMU
#include <page.h>
#include <mmu.h>
#define ARCH_PAGE_LIST_SIZE (ARCH_ADDRESS_WIDTH_BITS - ARCH_PAGE_SHIFT)
#define DBG_TAG "PAGE"
#define DBG_LVL DBG_WARNING
#include <rtdbg.h>
struct page
{
struct page *next; /* same level next */
struct page *pre; /* same level pre */
uint32_t size_bits; /* if is ARCH_ADDRESS_WIDTH_BITS, means not free */
int ref_cnt; /* page group ref count */
};
static struct page* page_start;
static void* page_addr;
static size_t page_nr;
static struct page *page_list[ARCH_PAGE_LIST_SIZE];
rt_weak int rt_hw_clz(size_t n)
{
int bits = sizeof(size_t) * 8;
n |= (n >> 1);
n |= (n >> 2);
n |= (n >> 4);
n |= (n >> 8);
n |= (n >> 16);
#ifdef ARCH_CPU_64BIT
n |= (n >> 32);
n = (n & 0x5555555555555555UL) + ((n >> 1) & 0x5555555555555555UL);
n = (n & 0x3333333333333333UL) + ((n >> 2) & 0x3333333333333333UL);
n = (n & 0x0707070707070707UL) + ((n >> 4) & 0x0707070707070707UL);
n = (n & 0x000f000f000f000fUL) + ((n >> 8) & 0x000f000f000f000fUL);
n = (n & 0x0000001f0000001fUL) + ((n >> 16) & 0x0000001f0000001fUL);
n = (n & 0x000000000000003fUL) + ((n >> 32) & 0x000000000000003fUL);
#else
n = (n & 0x55555555UL) + ((n >> 1) & 0x55555555UL);
n = (n & 0x33333333UL) + ((n >> 2) & 0x33333333UL);
n = (n & 0x07070707UL) + ((n >> 4) & 0x07070707UL);
n = (n & 0x000f000fUL) + ((n >> 8) & 0x000f000fUL);
n = (n & 0x0000001fUL) + ((n >> 16) & 0x0000001fUL);
#endif
return bits - n;
}
rt_weak int rt_hw_ctz(size_t n)
{
int ret = sizeof(size_t) * 8;
if (n)
{
ret -= (rt_hw_clz(n ^ (n - 1)) + 1);
}
return ret;
}
size_t rt_page_bits(size_t size)
{
int bit = sizeof(size_t) * 8 - rt_hw_clz(size) - 1;
if ((size ^ (1UL << bit)) != 0)
{
bit++;
}
bit -= ARCH_PAGE_SHIFT;
if (bit < 0)
{
bit = 0;
}
return bit;
}
static struct page * addr_to_page(void *addr)
{
size_t off;
if (addr < page_addr)
{
return 0;
}
off = (size_t)((char*)addr - (char*)page_addr);
off >>= ARCH_PAGE_SHIFT;
if (off >= page_nr)
{
return 0;
}
return &page_start[off];
}
static void* page_to_addr(struct page* p)
{
if (!p)
{
return 0;
}
return (void*)((char*)page_addr + ((p - page_start) << ARCH_PAGE_SHIFT));
}
static inline struct page *buddy_get(struct page *p, uint32_t size_bits)
{
size_t addr;
addr = (size_t)page_to_addr(p);
addr ^= (1UL << (size_bits + ARCH_PAGE_SHIFT));
return addr_to_page((void*)addr);
}
static void page_remove(struct page *p, uint32_t size_bits)
{
if (p->pre)
{
p->pre->next = p->next;
}
else
{
page_list[size_bits] = p->next;
}
if (p->next)
{
p->next->pre = p->pre;
}
p->size_bits = ARCH_ADDRESS_WIDTH_BITS;
}
static void page_insert(struct page *p, uint32_t size_bits)
{
p->next = page_list[size_bits];
if (p->next)
{
p->next->pre = p;
}
p->pre = 0;
page_list[size_bits] = p;
p->size_bits = size_bits;
}
static void _pages_ref_inc(struct page *p, uint32_t size_bits)
{
struct page *page_head;
int idx;
/* find page group head */
idx = p - page_start;
if (idx < 0 || idx >= page_nr)
{
return;
}
idx = idx & ~((1UL << size_bits) - 1);
page_head = page_start + idx;
page_head->ref_cnt++;
}
static int _pages_ref_get(struct page *p, uint32_t size_bits)
{
struct page *page_head;
int idx;
/* find page group head */
idx = p - page_start;
if (idx < 0 || idx >= page_nr)
{
return 0;
}
idx = idx & ~((1UL << size_bits) - 1);
page_head = page_start + idx;
return page_head->ref_cnt;
}
static int _pages_free(struct page *p, uint32_t size_bits)
{
uint32_t level = size_bits;
struct page *buddy;
RT_ASSERT(p->ref_cnt > 0);
RT_ASSERT(p->size_bits == ARCH_ADDRESS_WIDTH_BITS);
p->ref_cnt--;
if (p->ref_cnt != 0)
{
return 0;
}
while (level < ARCH_PAGE_LIST_SIZE)
{
buddy = buddy_get(p, level);
if (buddy && buddy->size_bits == level)
{
page_remove(buddy, level);
p = (p < buddy) ? p : buddy;
level++;
}
else
{
break;
}
}
page_insert(p, level);
return 1;
}
static struct page *_pages_alloc(uint32_t size_bits)
{
struct page *p;
if (page_list[size_bits])
{
p = page_list[size_bits];
page_remove(p, size_bits);
}
else
{
uint32_t level;
for (level = size_bits + 1; level < ARCH_PAGE_LIST_SIZE; level++)
{
if (page_list[level])
{
break;
}
}
if (level == ARCH_PAGE_LIST_SIZE)
{
return 0;
}
p = page_list[level];
page_remove(p, level);
while (level > size_bits)
{
page_insert(p, level - 1);
p = buddy_get(p, level - 1);
level--;
}
}
p->size_bits = ARCH_ADDRESS_WIDTH_BITS;
p->ref_cnt = 1;
return p;
}
int rt_page_ref_get(void *addr, uint32_t size_bits)
{
struct page *p;
rt_base_t level;
int ref;
p = addr_to_page(addr);
level = rt_hw_interrupt_disable();
ref = _pages_ref_get(p, size_bits);
rt_hw_interrupt_enable(level);
return ref;
}
void rt_page_ref_inc(void *addr, uint32_t size_bits)
{
struct page *p;
rt_base_t level;
p = addr_to_page(addr);
level = rt_hw_interrupt_disable();
_pages_ref_inc(p, size_bits);
rt_hw_interrupt_enable(level);
}
void *rt_pages_alloc(uint32_t size_bits)
{
struct page *p;
rt_base_t level;
level = rt_hw_interrupt_disable();
p = _pages_alloc(size_bits);
rt_hw_interrupt_enable(level);
return page_to_addr(p);
}
int rt_pages_free(void *addr, uint32_t size_bits)
{
struct page *p;
int real_free = 0;
p = addr_to_page(addr);
if (p)
{
rt_base_t level;
level = rt_hw_interrupt_disable();
real_free = _pages_free(p, size_bits);
rt_hw_interrupt_enable(level);
}
return real_free;
}
void list_page(void)
{
int i;
size_t total = 0;
rt_base_t level;
level = rt_hw_interrupt_disable();
for (i = 0; i < ARCH_PAGE_LIST_SIZE; i++)
{
struct page *p = page_list[i];
rt_kprintf("level %d ", i);
while (p)
{
total += (1UL << i);
rt_kprintf("[0x%08p]", page_to_addr(p));
p = p->next;
}
rt_kprintf("\n");
}
rt_hw_interrupt_enable(level);
rt_kprintf("free pages is %08x\n", total);
rt_kprintf("-------------------------------\n");
}
MSH_CMD_EXPORT(list_page, show page info);
void rt_page_get_info(size_t *total_nr, size_t *free_nr)
{
int i;
size_t total_free = 0;
rt_base_t level;
level = rt_hw_interrupt_disable();
for (i = 0; i < ARCH_PAGE_LIST_SIZE; i++)
{
struct page *p = page_list[i];
while (p)
{
total_free += (1UL << i);
p = p->next;
}
}
rt_hw_interrupt_enable(level);
*total_nr = page_nr;
*free_nr = total_free;
}
void rt_page_init(rt_region_t reg)
{
int i;
LOG_D("split 0x%08x 0x%08x\n", reg.start, reg.end);
reg.start += ARCH_PAGE_MASK;
reg.start &= ~ARCH_PAGE_MASK;
reg.end &= ~ARCH_PAGE_MASK;
{
int nr = ARCH_PAGE_SIZE / sizeof(struct page);
int total = (reg.end - reg.start) >> ARCH_PAGE_SHIFT;
int mnr = (total + nr) / (nr + 1);
LOG_D("nr = 0x%08x\n", nr);
LOG_D("total = 0x%08x\n", total);
LOG_D("mnr = 0x%08x\n", mnr);
RT_ASSERT(mnr < total);
page_start = (struct page*)reg.start;
reg.start += (mnr << ARCH_PAGE_SHIFT);
page_addr = (void*)reg.start;
page_nr = (reg.end - reg.start) >> ARCH_PAGE_SHIFT;
}
LOG_D("align 0x%08x 0x%08x\n", reg.start, reg.end);
/* init free list */
for (i = 0; i < ARCH_PAGE_LIST_SIZE; i++)
{
page_list[i] = 0;
}
/* add pages to free list */
while (reg.start != reg.end)
{
struct page *p;
int align_bits;
int size_bits;
size_bits = ARCH_ADDRESS_WIDTH_BITS - 1 - rt_hw_clz(reg.end - reg.start);
align_bits = rt_hw_ctz(reg.start);
if (align_bits < size_bits)
{
size_bits = align_bits;
}
p = addr_to_page((void*)reg.start);
p->size_bits = ARCH_ADDRESS_WIDTH_BITS;
p->ref_cnt = 1;
_pages_free(p, size_bits - ARCH_PAGE_SHIFT);
reg.start += (1UL << size_bits);
}
}
#endif
+2 -26
View File
@@ -11,30 +11,6 @@
#ifndef __PAGE_H__
#define __PAGE_H__
#ifdef ARCH_MM_MMU
typedef struct tag_region
{
size_t start;
size_t end;
} rt_region_t;
void rt_page_init(rt_region_t reg);
void *rt_pages_alloc(uint32_t size_bits);
void rt_page_ref_inc(void *addr, uint32_t size_bits);
int rt_page_ref_get(void *addr, uint32_t size_bits);
int rt_pages_free(void *addr, uint32_t size_bits);
void rt_pageinfo_dump(void);
size_t rt_page_bits(size_t size);
void rt_page_get_info(size_t *total_nr, size_t *free_nr);
#endif
#include <mm_page.h>
#endif /*__PAGE_H__*/