14#define DBG_TAG "dfs.mmap"
15#define DBG_LVL DBG_WARNING
18#if defined(RT_USING_SMART) && defined(ARCH_MM_MMU) && defined(RT_USING_PAGECACHE)
26#include <lwp_user_mm.h>
35static rt_mem_obj_t dfs_get_mem_obj(
struct dfs_file *file);
36static void *dfs_mem_obj_get_file(rt_mem_obj_t mem_obj);
38static void *_do_mmap(
struct rt_lwp *lwp,
void *map_vaddr,
size_t map_size,
size_t attr,
39 mm_flag_t flags, off_t pgoffset,
void *data,
rt_err_t *code)
42 void *vaddr = map_vaddr;
43 rt_mem_obj_t mem_obj = dfs_get_mem_obj(data);
45 ret = rt_aspace_map(lwp->aspace, &vaddr, map_size,
46 attr, flags, mem_obj, pgoffset);
50 LOG_E(
"failed to map %lx with size %lx with errno %d", map_vaddr,
62static void *_map_data_to_uspace(
struct dfs_mmap2_args *mmap2,
void *data,
rt_err_t *code)
65 void *map_vaddr = mmap2->addr;
66 size_t map_size = mmap2->length;
67 struct rt_lwp *lwp = mmap2->lwp;
73 offset = (size_t)map_vaddr & ARCH_PAGE_MASK;
74 map_size += (offset + ARCH_PAGE_SIZE - 1);
75 map_size &= ~ARCH_PAGE_MASK;
76 map_vaddr = (
void *)((
size_t)map_vaddr & ~ARCH_PAGE_MASK);
78 k_flags = lwp_user_mm_flag_to_kernel(mmap2->flags);
79 k_attr = lwp_user_mm_attr_to_kernel(mmap2->prot);
81 map_vaddr = _do_mmap(lwp, map_vaddr, map_size, k_attr, k_flags, mmap2->pgoffset, data, code);
87static void hint_free(rt_mm_va_hint_t hint)
91static void on_page_fault(
struct rt_varea *varea,
struct rt_aspace_fault_msg *msg)
94 struct dfs_file *file = dfs_mem_obj_get_file(varea->mem_obj);
98 LOG_I(
"%s varea: %p", __func__, varea);
99 LOG_I(
"varea start: %p size: 0x%x offset: 0x%x attr: 0x%x flag: 0x%x",
100 varea->start, varea->size, varea->offset, varea->attr, varea->flag);
101 LOG_I(
"fault vaddr: %p", msg->fault_vaddr);
108 page = dfs_aspace_mmap(file, varea, msg->fault_vaddr);
111 msg->response.status = MM_FAULT_STATUS_OK_MAPPED;
112 msg->response.size = ARCH_PAGE_SIZE;
113 msg->response.vaddr = page;
117 LOG_E(
"%s varea %p mmap failed at vaddr %p", __func__, varea, msg->fault_vaddr);
122 LOG_E(
"%s varea %p not a file, vaddr %p", __func__, varea, varea->start);
127static void on_varea_open(
struct rt_varea *varea)
129 struct dfs_file *file = dfs_mem_obj_get_file(varea->mem_obj);
135static void on_varea_close(
struct rt_varea *varea)
137 struct dfs_file *file = dfs_mem_obj_get_file(varea->mem_obj);
141 LOG_I(
"%s varea: %p", __func__, varea);
142 LOG_I(
"varea start: %p size: 0x%x offset: 0x%x attr: 0x%x flag: 0x%x",
143 varea->start, varea->size, varea->offset, varea->attr, varea->flag);
150 dfs_aspace_unmap(file, varea);
164 LOG_E(
"%s varea %p not a file, vaddr %p", __func__, varea, varea->start);
168static const char *get_name(rt_varea_t varea)
170 struct dfs_file *file = dfs_mem_obj_get_file(varea->mem_obj);
175void page_read(
struct rt_varea *varea,
struct rt_aspace_io_msg *msg)
178 struct dfs_file *file = dfs_mem_obj_get_file(varea->mem_obj);
182 LOG_I(
"%s varea: %p", __func__, varea);
183 LOG_I(
"varea start: %p size: 0x%x offset: 0x%x attr: 0x%x flag: 0x%x",
184 varea->start, varea->size, varea->offset, varea->attr, varea->flag);
186 ret = dfs_aspace_mmap_read(file, varea, msg);
189 msg->response.status = MM_FAULT_STATUS_OK;
190 if (ret < ARCH_PAGE_SIZE)
192 memset((
char *)msg->buffer_vaddr + ret, 0, ARCH_PAGE_SIZE - ret);
198 LOG_E(
"%s varea %p not a file, vaddr %p", __func__, varea, varea->start);
202void page_write(
struct rt_varea *varea,
struct rt_aspace_io_msg *msg)
205 struct dfs_file *file = dfs_mem_obj_get_file(varea->mem_obj);
209 LOG_I(
"%s varea: %p", __func__, varea);
210 LOG_I(
"varea start: %p size: 0x%x offset: 0x%x attr: 0x%x flag: 0x%x",
211 varea->start, varea->size, varea->offset, varea->attr, varea->flag);
213 ret = dfs_aspace_mmap_write(file, varea, msg);
216 msg->response.status = MM_FAULT_STATUS_OK;
217 if (ret < ARCH_PAGE_SIZE)
219 memset((
char *)msg->buffer_vaddr + ret, 0, ARCH_PAGE_SIZE - ret);
225 LOG_E(
"%s varea %p not a file, vaddr %p", __func__, varea, varea->start);
229static rt_err_t unmap_pages(rt_varea_t varea,
void *rm_start,
void *rm_end)
231 struct dfs_file *file = dfs_mem_obj_get_file(varea->mem_obj);
235 LOG_I(
"%s varea: %p start: %p end: %p", __func__, varea, rm_start, rm_end);
239 while (rm_start != rm_end)
241 dfs_aspace_page_unmap(file, varea, rm_start);
242 rm_start += ARCH_PAGE_SIZE;
249 LOG_E(
"%s varea %p not a file, vaddr %p", __func__, varea, varea->start);
257 char *varea_start = varea->start;
261 LOG_I(
"%s varea: %p", __func__, varea);
262 LOG_I(
"varea start: %p size: 0x%x offset: 0x%x attr: 0x%x flag: 0x%x",
263 varea->start, varea->size, varea->offset, varea->attr, varea->flag);
264 LOG_I(
"new_vaddr: %p size: %p", new_vaddr, size);
266 if (varea_start == (
char *)new_vaddr)
268 rm_start = varea_start + size;
269 rm_end = varea_start + varea->size;
273 rm_start = varea_start;
277 return unmap_pages(varea, rm_start, rm_end);
282 LOG_I(
"%s varea: %p", __func__, varea);
283 LOG_I(
"varea start: %p size: 0x%x offset: 0x%x attr: 0x%x flag: 0x%x",
284 varea->start, varea->size, varea->offset, varea->attr, varea->flag);
285 LOG_I(
"new_vaddr: %p size: %p", new_vaddr, size);
290rt_err_t on_varea_split(
struct rt_varea *existed,
void *unmap_start,
rt_size_t unmap_len,
struct rt_varea *subset)
293 struct dfs_file *file = dfs_mem_obj_get_file(existed->mem_obj);
297 LOG_I(
"%s varea: %p", __func__, existed);
298 LOG_I(
"varea start: %p size: 0x%x offset: 0x%x attr: 0x%x flag: 0x%x",
299 existed->start, existed->size, existed->offset, existed->attr, existed->flag);
300 LOG_I(
"unmap_start: %p unmap_len: %p", unmap_start, unmap_len);
307 rc = unmap_pages(existed, unmap_start, (
char *)unmap_start + unmap_len);
310 rc = unmap_pages(existed, subset->start, (
char *)subset->start + subset->size);
312 on_varea_open(subset);
319 LOG_E(
"%s varea %p not a file, vaddr %p", __func__, existed, existed->start);
325rt_err_t on_varea_merge(
struct rt_varea *merge_to,
struct rt_varea *merge_from)
327 struct dfs_file *file = dfs_mem_obj_get_file(merge_from->mem_obj);
331 LOG_I(
"%s varea: %p", __func__, merge_from);
332 LOG_I(
"varea start: %p size: 0x%x offset: 0x%x attr: 0x%x flag: 0x%x",
333 merge_from->start, merge_from->size, merge_from->offset, merge_from->attr, merge_from->flag);
340 dfs_aspace_unmap(file, merge_from);
341 on_varea_close(merge_from);
347 LOG_E(
"%s varea %p not a file, vaddr %p", __func__, merge_from, merge_from->start);
353void *on_varea_mremap(
struct rt_varea *varea,
rt_size_t new_size,
int flags,
void *new_address)
356 struct dfs_file *file = dfs_mem_obj_get_file(varea->mem_obj);
358#ifndef MREMAP_MAYMOVE
359#define MREMAP_MAYMOVE 1
362 if (file &&
flags == MREMAP_MAYMOVE)
365 rt_mem_obj_t mem_obj = dfs_get_mem_obj(file);
367 vaddr = new_address ? new_address : varea->start;
368 new_size = (new_size + ARCH_PAGE_SIZE - 1);
369 new_size &= ~ARCH_PAGE_MASK;
370 ret = rt_aspace_map(varea->aspace, &vaddr, new_size, varea->attr, varea->flag, mem_obj, varea->offset);
373 LOG_E(
"failed to map %lx with size %lx with errno %d", vaddr, new_size, ret);
378 LOG_I(
"old: %p size: %p new: %p size: %p", varea->start, varea->size, vaddr, new_size);
385static struct rt_mem_obj _mem_obj =
387 .hint_free = hint_free,
388 .on_page_fault = on_page_fault,
389 .on_varea_open = on_varea_open,
390 .on_varea_close = on_varea_close,
391 .get_name = get_name,
393 .page_read = page_read,
394 .page_write = page_write,
396 .on_varea_shrink = on_varea_shrink,
397 .on_varea_expand = on_varea_expand,
398 .on_varea_split = on_varea_split,
399 .on_varea_merge = on_varea_merge,
401 .on_varea_mremap = on_varea_mremap,
405 struct rt_mem_obj mem_obj;
409static rt_mem_obj_t dfs_get_mem_obj(
struct dfs_file *file)
414 struct dfs_mem_obj *dfs_mobj;
419 dfs_mobj->file = file;
420 mobj = &dfs_mobj->mem_obj;
421 memcpy(mobj, &_mem_obj,
sizeof(*mobj));
429static void *dfs_mem_obj_get_file(rt_mem_obj_t mem_obj)
431 struct dfs_mem_obj *dfs_mobj;
433 return dfs_mobj->file;
441 LOG_I(
"mmap2 args addr: %p length: 0x%x prot: %d flags: 0x%x pgoffset: 0x%x",
442 mmap2->addr, mmap2->length, mmap2->prot, mmap2->flags, mmap2->pgoffset);
443 if (file && file->
vnode)
448 map_vaddr = _map_data_to_uspace(mmap2, file, &ret);
451 mmap2->ret = map_vaddr;
467 LOG_E(
"mmap2 args addr: %p length: 0x%x prot: %d flags: 0x%x pgoffset: 0x%x",
468 mmap2->addr, mmap2->length, mmap2->prot, mmap2->flags, mmap2->pgoffset);
int dfs_file_close(struct dfs_file *file)
int dfs_file_mmap(struct dfs_file *file, struct dfs_mmap2_args *mmap2)
void dfs_file_unlock(void)
rt_err_t dfs_file_lock(void)
rt_weak void * rt_malloc(rt_size_t size)
Allocate a block of memory with a minimum of 'size' bytes.
#define rt_container_of(ptr, type, member)
#define rt_atomic_sub(ptr, v)
#define rt_atomic_add(ptr, v)
#define rt_atomic_load(ptr)
struct dfs_dentry * dentry
struct dfs_aspace * aspace