mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-24 05:04:10 +08:00
[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:
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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),
|
||||
|
||||
+279
-244
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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__*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user