nckernel  0.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
onetime_map.c
Go to the documentation of this file.
1 #include <sys/types.h>
2 #include <string.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <stddef.h>
6 #include <stdint.h>
7 #include <unistd.h>
8 #include <pthread.h>
9 #include <assert.h>
10 
11 #include <object.h>
12 #include <list.h>
13 #include <initm.h>
14 #include <onetime_map.h>
15 #include <thread.h>
16 #include <paging.h>
17 #include <segment.h> /* For the IO_BITMAP_SIZE */
18 #include <x86.h> /* struct x86_arch_data */
19 
20 #include <debug.h>
21 
22 struct info {
25 
28 } s_info = {
29  .vma_start = 0,
30  .vma_end = 0,
31 
32  .bitmap = NULL,
33  .bitmap_sz = 0,
34 };
35 
36 static inline void *set_pgt(uint32_t idx, void *pma)
37 {
38  void *vma;
39  uint32_t pgt_idx;
40  struct thread *thid;
41  struct pgte *pgt;
42  struct pgde *pgd;
43  struct x86_arch_data *arch_data;
44 
45  vma = (void *)(idx * sysconf(_SC_PAGESIZE) + s_info.vma_start);
46  TO_IDX(vma, pgt_idx, idx);
47 
48  thid = (struct thread *)pthread_self();
49  if (!thid) {
50  return NULL;
51  }
52 
53  thid = thid->root;
54  if (!thid) {
55  return NULL;
56  }
57 
58  arch_data = thid->arch_data;
59 
66  pgd = initm_find_vma(arch_data->pma_pgd);
67  assert(pgd && pgd[pgt_idx].p && "Failed to get valid PGD");
68 
69  pgt = (struct pgte *)(pgd[pgt_idx].pt_base * sysconf(_SC_PAGESIZE));
75  pgt = initm_find_vma(pgt);
76 
82  assert(!pgt[idx].p && "Page table is already in use");
83 
84  pgt[idx].p = 1;
85  pgt[idx].rw = 1;
86  pgt[idx].page_base = (uint32_t)pma / sysconf(_SC_PAGESIZE);
87 
88  return vma;
89 }
90 
91 void *onetime_map(void *pma)
92 {
93  uint32_t idx;
94  register int i;
95  register int j;
96  void *vma = NULL;
97  char *byte;
98 
99  /* 더블 워드 단위로 접근 */
100  idx = s_info.bitmap_sz >> 2;
101  for (i = 0; i < idx; i++) {
102  if ((s_info.bitmap[i] & 0xFFFFFFFF) == 0xFFFFFFFF) {
103  continue; /* 빈 곳이 없다 */
104  }
105 
106  for (j = 0; j < 32; j++) {
107  idx = 0x01 << j;
108  if ((s_info.bitmap[i] & idx) == idx) {
109  continue;
110  }
111 
112  /* 빈 곳을 찾았다
113  * 마크 하고, 위치를 찾아서,
114  * 실제 주소를 계산한다.
115  */
116  s_info.bitmap[i] |= idx;
117 
118  idx = (i << 5) + j;
119 
120  vma = set_pgt(idx, pma);
121  return vma;
122  }
123  }
124 
125  /* 바이트 단위로 접근 */
126  byte = (char *)s_info.bitmap;
127  for (i <<= 2; i < s_info.bitmap_sz; i++) {
128  if ((byte[i] & 0xFF) == 0xFF) {
129  continue;
130  }
131 
132  for (j = 0; j < 8; j++) {
133  idx = 0x01 << j;
134  if ((byte[i] & idx) == idx) {
135  continue;
136  }
137 
138  byte[i] |= idx;
139 
140  idx = (i << 3) + j;
141 
142  vma = set_pgt(idx, pma);
143  return vma;
144  }
145  }
146 
147  return NULL;
148 }
149 
150 void *onetime_unmap(void *vma)
151 {
152  uint32_t idx;
153  uint32_t pgt_idx;
154  struct thread *thid;
155  struct x86_arch_data *arch_data;
156  struct pgde *pgd;
157  struct pgte *pgt;
158  void *pma;
159 
160  if ((uint32_t)vma < s_info.vma_start || (uint32_t)vma > s_info.vma_end) {
161  return NULL;
162  }
163 
164  thid = (struct thread *)pthread_self();
165  if (!thid) {
166  return NULL;
167  }
168 
169  thid = thid->root;
170  if (!thid) {
171  return NULL;
172  }
173 
174  arch_data = thid->arch_data;
175 
176  pgd = initm_find_vma(arch_data->pma_pgd);
177  if (!pgd) {
178  return NULL;
179  }
180 
181  TO_IDX(vma, pgt_idx, idx);
182 
183  pgt = (struct pgte *)(pgd[pgt_idx].pt_base * sysconf(_SC_PAGESIZE));
184  pgt = initm_find_vma(pgt);
185 
186  /* 응? 페이지가 할당 되어 있지 않다고? */
187  assert(pgt && pgt[idx].p && "Page table is not valid");
188 
189  /* 페이지 테이블 정보 갱신 */
190  pgt[idx].p = 0;
191  pma = (void *)(pgt[idx].page_base * sysconf(_SC_PAGESIZE));
192 
193  idx = ((uint32_t)vma - s_info.vma_start) / sysconf(_SC_PAGESIZE);
194 
195  s_info.bitmap[idx >> 5] &= ~(0x01 << (idx & 0x01F));
196  return pma;
197 }
198 
208 void onetime_map_init(void *vma_start, void *vma_end)
209 {
210  struct pgde *pgd;
211  struct pgte *pgt;
212  int pgt_idx;
213  int idx;
214  struct thread *thid;
215  struct x86_arch_data *arch_data;
216  uint32_t iterator;
217  void *initm;
218 
223  thid = (struct thread *)pthread_self();
224  if (!thid) {
225  return;
226  }
227 
228  thid = thid->root;
229  if (!thid) {
230  return;
231  }
232 
233  arch_data = thid->arch_data;
234  pgd = initm_find_vma(arch_data->pma_pgd);
235  if (!pgd) {
236  return;
237  }
238 
239  s_info.vma_start = (uint32_t)vma_start;
240  s_info.vma_end = (uint32_t)vma_end;
241 
243  s_info.bitmap_sz =
248  s_info.bitmap_sz >>= 3;
249  s_info.bitmap_sz += !!(s_info.bitmap_sz & 0x07);
250 
252  if (!s_info.bitmap) {
253  return;
254  }
255 
257 
270  initm = initm_vma();
271 
272  iterator = s_info.vma_start;
273  while ((s_info.vma_end - iterator) >= sysconf(_SC_PAGESIZE)) {
274  TO_IDX(iterator, pgt_idx, idx);
275  iterator += sysconf(_SC_PAGESIZE);
276 
277  if (pgd[pgt_idx].p) {
278  continue;
279  }
280 
281  pgt = initm_alloc(initm);
282  if (!pgt) {
283  break;
284  }
285 
286  memset(pgt, 0, sysconf(_SC_PAGESIZE));
287  pgd[pgt_idx].pt_base = ((uint32_t)initm_find_pma(pgt) / sysconf(_SC_PAGESIZE));
288  pgd[pgt_idx].p = 1;
289  pgd[pgt_idx].rw = 1;
290  }
291 }
292 
293 /* End of a file */