4b1b311f70afd31a3dce6e52154d19de2bb65ed3
[lunaix-os.git] / lunaix-os / kernel / mm / vmap.c
1 #include <lunaix/mm/pmm.h>
2 #include <lunaix/mm/vmm.h>
3 #include <lunaix/spike.h>
4
5 #include <sys/mm/mempart.h>
6
7 static ptr_t start = VMAP;
8
9 void*
10 vmm_vmap(ptr_t paddr, size_t size, pt_attr attr)
11 {
12     // next fit
13     assert_msg((paddr & 0xfff) == 0, "vmap: bad alignment");
14     size = ROUNDUP(size, PG_SIZE);
15
16     ptr_t current_addr = start;
17     size_t examed_size = 0, wrapped = 0;
18     x86_page_table* pd = (x86_page_table*)L1_BASE_VADDR;
19
20     while (!wrapped || current_addr >= start) {
21         size_t l1inx = L1_INDEX(current_addr);
22         if (!(pd->entry[l1inx])) {
23             // empty 4mb region
24             examed_size += MEM_4MB;
25             current_addr = (current_addr & 0xffc00000) + MEM_4MB;
26         } else {
27             x86_page_table* ptd = (x86_page_table*)(L2_VADDR(l1inx));
28             size_t i = L2_INDEX(current_addr), j = 0;
29             for (; i < PG_MAX_ENTRIES && examed_size < size; i++, j++) {
30                 if (!ptd->entry[i]) {
31                     examed_size += PG_SIZE;
32                 } else if (examed_size) {
33                     // found a discontinuity, start from beginning
34                     examed_size = 0;
35                     j++;
36                     break;
37                 }
38             }
39             current_addr += j << 12;
40         }
41
42         if (examed_size >= size) {
43             goto done;
44         }
45
46         if (current_addr >= VMAP_END) {
47             wrapped = 1;
48             examed_size = 0;
49             current_addr = VMAP;
50         }
51     }
52
53     return NULL;
54
55 done:
56     ptr_t alloc_begin = current_addr - examed_size;
57     for (size_t i = 0; i < size; i += PG_SIZE) {
58         vmm_set_mapping(VMS_SELF, alloc_begin + i, paddr + i, attr, 0);
59         pmm_ref_page(KERNEL_PID, paddr + i);
60     }
61     start = alloc_begin + size;
62
63     return (void*)alloc_begin;
64 }