make log a bit verbose for some useful information
[lunaix-os.git] / lunaix-os / arch / generic / kremap.c
1 #include <lunaix/mm/pagetable.h>
2 #include <lunaix/sections.h>
3
4 #include <asm/boot_stage.h>
5 #include <asm/mm_defs.h>
6 #include <asm-generic/init_pagetable.h>
7
8 ptr_t boot_text
9 kpt_alloc_table(struct pt_alloc* alloc)
10 {
11     if (alloc->index >= alloc->total) {
12         return 0;
13     }
14
15     ptr_t next;
16
17     next = alloc->base + alloc->index * PAGE_SIZE;
18     alloc->index++;
19
20     return next;
21 }
22
23 static bool boot_text
24 __walk(struct ptw_state* state, ptr_t addr, 
25        unsigned long level_size, bool create)
26 {
27     pte_t pte, *pt;
28     int level, pt_index;
29     unsigned long lsize;
30     ptr_t  next_level;
31
32     pt = state->root;
33     level = 0;
34
35     do {
36         lsize    = lnt_page_size(level);
37         pt_index = va_level_index(addr, lsize);
38
39         pte = pt[pt_index];
40         if (!pte_isnull(pte)) {
41             next_level = pte_paddr(pte);
42             goto cont;
43         }
44
45         if (pt_last_level(level) || lsize == level_size) {
46             break;
47         }
48
49         if (!create) {
50             goto fail;
51         }
52
53         next_level = kpt_alloc_table(state->alloc);
54         if (!next_level) {
55             state->lntp = NULL;
56             goto fail;
57         }
58
59         pte = mkpte(next_level, KERNEL_PGTAB);
60         pt[pt_index] = pte;
61
62     cont:
63         pt = (pte_t*) next_level;
64         level++;
65     }
66     while (lsize > level_size);
67
68     state->lntp  = pt;
69     state->level = level;
70     state->tab_index = pt_index;
71
72     return true;
73
74 fail:
75     state->lntp = NULL;
76     return false;
77 }
78
79 unsigned int boot_text
80 kpt_set_ptes_flatten(struct ptw_state* state, ptr_t addr, 
81                 pte_t pte, unsigned long lsize, unsigned int nr)
82 {
83     unsigned int tab_i, _n;
84     pte_t *lntp;
85
86     _n = 0;
87     addr = addr & ~(lsize - 1);
88
89     do {
90         if (!__walk(state, addr, lsize, true)) {
91             break;
92         }
93
94         lntp  = state->lntp;
95         tab_i = state->tab_index;
96         while (_n < nr && tab_i < LEVEL_SIZE) {
97             lntp[tab_i++] = pte;
98             pte = pte_advance(pte, lsize);
99
100             addr += lsize;
101             _n++;
102         }
103     }
104     while (_n < nr);
105
106     return _n;
107 }
108
109 #define ksection_maps autogen_name(ksecmap)
110 #define PF_X 0x1
111 #define PF_W 0x2
112
113 extern_autogen(ksecmap);
114
115 bridge_farsym(__kexec_text_start);
116 bridge_farsym(ksection_maps);
117
118 void boot_text
119 kpt_migrate_highmem(struct ptw_state* state)
120 {
121     pte_t pte;
122     struct ksecmap* maps;
123     struct ksection* section;
124     pfn_t pgs;
125
126     maps = (struct ksecmap*)to_kphysical(__far(ksection_maps));
127
128     for (unsigned int i = 0; i < maps->num; i++)
129     {
130         section = &maps->secs[i];
131         
132         if (section->va < KERNEL_RESIDENT) {
133             continue;
134         }
135
136         pte = mkpte(section->pa, KERNEL_RDONLY);
137         if ((section->flags & PF_X)) {
138             pte = pte_mkexec(pte);
139         }
140         if ((section->flags & PF_W)) {
141             pte = pte_mkwritable(pte);
142         }
143
144         pgs = leaf_count(section->size);
145         kpt_set_ptes(state, section->va, pte, LFT_SIZE, pgs);
146     }
147 }