optimize the menuconfig redrawing
[lunaix-os.git] / lunaix-os / arch / x86 / boot / i386 / kremap32.c
1 #define __BOOT_CODE__
2
3 #include <lunaix/mm/pagetable.h>
4 #include <lunaix/compiler.h>
5
6 #include <sys/boot/bstage.h>
7 #include <sys/mm/mm_defs.h>
8
9 bridge_farsym(__kexec_start);
10 bridge_farsym(__kexec_end);
11 bridge_farsym(__kexec_text_start);
12 bridge_farsym(__kexec_text_end);
13
14 // define the initial page table layout
15 struct kernel_map;
16
17 static struct kernel_map kernel_pt __section(".kpg");
18 export_symbol(debug, boot, kernel_pt);
19
20 struct kernel_map {
21     pte_t l0t[_PAGE_LEVEL_SIZE];
22     pte_t pg_mnt[_PAGE_LEVEL_SIZE];
23
24     struct {
25         pte_t _lft[_PAGE_LEVEL_SIZE];
26     } kernel_lfts[16];
27 } align(4);
28
29 static void boot_text
30 do_remap()
31 {
32     struct kernel_map* kpt_pa = (struct kernel_map*)to_kphysical(&kernel_pt);
33     
34     size_t mia_casa_i   = pfn_at(KERNEL_RESIDENT, L0T_SIZE);
35     pte_t* klptep       = (pte_t*) &kpt_pa->l0t[mia_casa_i];
36     pte_t* ktep         = (pte_t*)  kpt_pa->kernel_lfts;    
37     pte_t* boot_l0tep   = (pte_t*)  kpt_pa;
38
39     set_pte(boot_l0tep, pte_mkhuge(mkpte_prot(KERNEL_DATA)));
40
41     // --- 将内核重映射至高半区 ---
42
43     // Hook the kernel reserved LFTs onto L0T
44     pte_t pte = mkpte((ptr_t)ktep, KERNEL_DATA);
45     
46     for (u32_t i = 0; i < KEXEC_RSVD; i++) {
47         pte = pte_setpaddr(pte, (ptr_t)&kpt_pa->kernel_lfts[i]);
48         set_pte(klptep, pte);
49
50         klptep++;
51     }
52
53     // Ensure the size of kernel is within the reservation
54     pfn_t kimg_pagecount = 
55         pfn(__far(__kexec_end) - __far(__kexec_start));
56     if (kimg_pagecount > KEXEC_RSVD * _PAGE_LEVEL_SIZE) {
57         // ERROR: require more pages
58         //  here should do something else other than head into blocking
59         asm("ud2");
60     }
61
62     // Now, map the kernel
63
64     pfn_t kimg_end = pfn(to_kphysical(__far(__kexec_end)));
65     pfn_t i = pfn(to_kphysical(__far(__kexec_text_start)));
66     ktep += i;
67
68     // kernel .text
69     pte = pte_setprot(pte, KERNEL_EXEC);
70     pfn_t ktext_end = pfn(to_kphysical(__far(__kexec_text_end)));
71     for (; i < ktext_end; i++) {
72         pte = pte_setpaddr(pte, page_addr(i));
73         set_pte(ktep, pte);
74
75         ktep++;
76     }
77
78     // all remaining kernel sections
79     pte = pte_setprot(pte, KERNEL_DATA);
80     for (; i < kimg_end; i++) {
81         pte = pte_setpaddr(pte, page_addr(i));
82         set_pte(ktep, pte);
83
84         ktep++;
85     }
86
87     // XXX: Mapping the kernel .rodata section?
88
89     // set mount point
90     pte_t* kmntep = (pte_t*) &kpt_pa->l0t[pfn_at(PG_MOUNT_1, L0T_SIZE)];
91     set_pte(kmntep, mkpte((ptr_t)kpt_pa->pg_mnt, KERNEL_DATA));
92
93     // Build up self-reference
94     int level = (VMS_SELF / L0T_SIZE) & _PAGE_LEVEL_MASK;
95     
96     pte = mkpte_root((ptr_t)kpt_pa, KERNEL_DATA);
97     set_pte(&boot_l0tep[level], pte);
98 }
99
100 ptr_t boot_text
101 remap_kernel()
102 {
103     ptr_t kmap_pa = to_kphysical(&kernel_pt);
104     for (size_t i = 0; i < sizeof(kernel_pt); i++) {
105         ((u8_t*)kmap_pa)[i] = 0;
106     }
107
108     do_remap();
109
110     return kmap_pa;
111 }