PCI 16x50 UART Controller, O2 Enablement (#39)
[lunaix-os.git] / lunaix-os / arch / x86 / mm / pmm.c
1 #include <lunaix/mm/page.h>
2 #include <lunaix/mm/pagetable.h>
3
4 extern unsigned int __kexec_end[];
5
6 void
7 pmm_arch_init_pool(struct pmem* memory)
8 {
9     pmm_declare_pool(POOL_UNIFIED, 1, memory->list_len);
10 }
11
12 ptr_t
13 pmm_arch_init_remap(struct pmem* memory, struct boot_handoff* bctx)
14 {
15     size_t ppfn_total = pfn(bctx->mem.size) + 1;
16     size_t pool_size  = ppfn_total * sizeof(struct ppage);
17     
18     size_t i = 0;
19     struct boot_mmapent* ent;
20     for (; i < bctx->mem.mmap_len; i++) {
21         ent = &bctx->mem.mmap[i];
22         if (free_memregion(ent) && ent->size > pool_size) {
23             goto found;
24         }
25     }
26
27     // fail to find a viable free region to host pplist
28     return 0;
29
30 found:;
31     ptr_t kexec_end = to_kphysical(__kexec_end);
32     ptr_t aligned_pplist = MAX(ent->start, kexec_end);
33
34 #ifdef CONFIG_ARCH_X86_64
35     aligned_pplist = napot_upaligned(aligned_pplist, L2T_SIZE);
36 #else
37     aligned_pplist = napot_upaligned(aligned_pplist, L0T_SIZE);
38 #endif
39
40     if (aligned_pplist + pool_size > ent->start + ent->size) {
41         return 0;
42     }
43
44     // for x86_32, the upper bound of memory requirement for pplist
45     //  is sizeof(struct ppage) * 1MiB. For simplicity (as well as 
46     //  efficiency), we limit the granule to 4M huge page, thus, 
47     //  it will take away at least 4M worth of vm address resource 
48     //  regardless the actual physical memory size
49
50     // anchor the pplist at vmap location (right after kernel)
51     memory->pplist = (struct ppage*)PMAP;
52     memory->list_len = ppfn_total;
53
54     pfn_t nhuge;
55     pte_t* ptep;
56
57     pte_t pte   = mkpte(aligned_pplist, KERNEL_DATA);
58
59 #ifdef CONFIG_ARCH_X86_64
60     nhuge = page_count(pool_size, L2T_SIZE);
61     ptep = mkl2tep_va(VMS_SELF, PMAP);
62     vmm_set_ptes_contig(ptep, pte_mkhuge(pte), L2T_SIZE, nhuge);
63 #else
64     nhuge = page_count(pool_size, L0T_SIZE);
65     ptep = mkl0tep_va(VMS_SELF, PMAP);
66     
67     // since VMAP and PMAP share same address space
68     // we need to shift VMAP to make room
69     vmap_set_start(VMAP + nhuge * L0T_SIZE);
70     vmm_set_ptes_contig(ptep, pte_mkhuge(pte), L0T_SIZE, nhuge);
71 #endif
72
73     tlb_flush_kernel(PMAP);
74     return aligned_pplist;
75 }