1 #include <lunaix/mm/mmap.h>
2 #include <lunaix/mm/pmm.h>
3 #include <lunaix/mm/valloc.h>
4 #include <lunaix/mm/vmm.h>
5 #include <lunaix/spike.h>
7 #include <lunaix/syscall.h>
11 vm_regions_t* regions,
19 if (!length || (length & (PG_SIZE - 1)) || (offset & (PG_SIZE - 1))) {
20 __current->k_status = EINVAL;
24 // read_page is not supported
25 if (!file->ops->read_page) {
26 __current->k_status = ENODEV;
30 ptr_t last_end = USER_START;
31 struct mm_region *pos, *n;
32 llist_for_each(pos, n, regions, head)
34 if (pos->start - last_end >= length && last_end >= addr) {
40 __current->k_status = ENOMEM;
45 ptr_t end = addr + length;
47 struct mm_region* region =
48 region_create(addr, end, proct | (options & 0x1f));
50 region->offset = offset;
52 region_add(regions, region);
54 u32_t attr = PG_ALLOW_USER;
55 if ((proct & REGION_WRITE)) {
59 for (u32_t i = 0; i < length; i += PG_SIZE) {
60 vmm_set_mapping(mnt, addr + i, 0, attr, 0);
67 mem_unmap(ptr_t mnt, vm_regions_t* regions, void* addr, size_t length)
69 length = ROUNDUP(length, PG_SIZE);
70 ptr_t cur_addr = ROUNDDOWN((ptr_t)addr, PG_SIZE);
71 struct mm_region *pos, *n;
73 llist_for_each(pos, n, regions, head)
75 if (pos->start <= cur_addr) {
80 while (&pos->head != regions && cur_addr > pos->start) {
81 u32_t l = pos->end - cur_addr;
85 // unmap cause discontinunity in a memory region - do split
86 struct mm_region* region = valloc(sizeof(struct mm_region));
88 region->start = cur_addr + length;
89 llist_insert_after(&pos->head, ®ion->head);
93 // TODO for shared mappings, sync page content if modified. (also
96 for (size_t i = 0; i < l; i += PG_SIZE) {
97 ptr_t pa = vmm_del_mapping(mnt, cur_addr + i);
99 pmm_free_page(__current->pid, pa);
103 n = container_of(pos->head.next, typeof(*pos), head);
104 if (pos->end == pos->start) {
105 llist_delete(&pos->head);
115 __DEFINE_LXSYSCALL3(void*, sys_mmap, void*, addr, size_t, length, va_list, lst)
117 int proct = va_arg(lst, int);
118 int fd = va_arg(lst, u32_t);
119 off_t offset = va_arg(lst, off_t);
120 int options = va_arg(lst, int);
124 if ((errno = vfs_getfd(fd, &vfd))) {
125 __current->k_status = errno;
129 length = ROUNDUP(length, PG_SIZE);
131 return mem_map(PD_REFERENCED,
132 &__current->mm.regions,
141 __DEFINE_LXSYSCALL2(void, munmap, void*, addr, size_t, length)
143 return mem_unmap(PD_REFERENCED, &__current->mm.regions, addr, length);