nckernel  0.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
initm.c
Go to the documentation of this file.
1 #include <sys/types.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <stddef.h>
6 #include <stdarg.h>
7 #include <stdint.h>
8 #include <unistd.h>
9 #include <errno.h>
10 
11 #include <arch.h>
12 #include <paging.h>
13 #include <initm.h>
14 #include <debug.h>
15 
20 static struct info {
21  void *initm_pma;
22  void *initm_vma;
23 } s_info;
24 
54 struct head_info;
55 
65 struct tail_info {
66  size_t sz;
67  size_t free_sz;
68  size_t nr_of_chunks;
69  char *data;
70  struct head_info *head;
71 }; /* size = sysconf(_SC_PAGESIZE) */
72 
73 struct head_info {
74  struct tail_info *tail;
75  char bitmap[];
76 };
77 
78 int initm_init(void *initm, size_t size)
79 {
80  struct head_info *head;
81  struct tail_info *tail;
82  uint32_t pagesize;
83 
84  pagesize = sysconf(_SC_PAGESIZE);
85 
86  tail = (struct tail_info *)((char *)initm + size - pagesize);
87  tail->sz = size;
88 
89  /* pagesize << 1 == HEAD + TAIL block */
90  tail->free_sz = tail->sz - (pagesize << 1);
91 
92  tail->nr_of_chunks = tail->free_sz / pagesize;
93 
94  /* HEAD 영역을 제외한 부분 부터 Data 영역 시작 */
95  tail->data = (char *)initm + pagesize;
96  tail->head = initm;
97 
98  head = tail->head;
99  head->tail = tail;
100  memset(head->bitmap, 0, pagesize - sizeof(*head));
101 
102  return 0;
103 }
104 
105 size_t initm_size(void *initm)
106 {
107  struct head_info *head;
108  struct tail_info *tail;
109 
110  head = initm;
111  tail = head->tail;
112 
113  return tail->sz;
114 }
115 
116 size_t initm_free_size(void *initm)
117 {
118  struct head_info *head;
119  struct tail_info *tail;
120 
121  head = initm;
122  tail = head->tail;
123 
124  return tail->free_sz;
125 }
126 
127 void *initm_alloc(void *initm)
128 {
129  char *data;
130  register int idx;
131  register unsigned char bit;
132  register int byte;
133  struct tail_info *tail;
134  struct head_info *head;
135 
136  head = (struct head_info*)initm;
137  tail = head->tail;
138  data = tail->data;
139 
140  for (idx = 0; idx < tail->nr_of_chunks; idx++) {
141  byte = idx >> 3;
142  bit = 0x01 << (idx & 0x07);
143 
144  if (!(head->bitmap[byte] & bit)) {
145  head->bitmap[byte] |= bit;
146  tail->free_sz -= sysconf(_SC_PAGESIZE);
147  return data + idx * sysconf(_SC_PAGESIZE);
148  }
149  }
150 
151  return NULL;
152 }
153 
154 int initm_free(void *initm, void *addr)
155 {
156  char *data;
157  unsigned char bit_idx;
158  int byte_idx;
159  struct tail_info *tail;
160  struct head_info *head;
161 
162  head = (struct head_info*)initm;
163  tail = head->tail;
164  data = tail->data;
165 
166  byte_idx = ((char *)addr - data) >> 3;
167  bit_idx = ((char *)addr - data) & 0x07;
168 
169  if (!(head->bitmap[byte_idx] & (0x01 << bit_idx))) {
170  return -ENOENT;
171  }
172 
173  head->bitmap[byte_idx] &= ~(0x01 << bit_idx);
174  tail->free_sz += sysconf(_SC_PAGESIZE);
175  return 0;
176 }
177 
178 void *initm_vma(void)
179 {
180  return s_info.initm_vma;
181 }
182 
183 /* initm_find_vma 함수를 사용하기 전에, initm_set_pma 함수를 이용해
184  * Physical memory 상의 INITM 시작 주소를 지정해 주어야 한다
185  *
186  * 가상 메모리가 활성화 된 이후에 호출 되어야 한다.
187  * s_info.initm_pma 는 가상 메모리상의 주소를 가지고 있기 때문에
188  * 가상 메모리가 활성화 되기 전에 사용하면 문제가 발생한다.
189  */
190 void initm_set_pma(void *initm)
191 {
192  s_info.initm_pma = initm;
193 }
194 
195 void initm_set_vma(void *initm)
196 {
197  s_info.initm_vma = initm;
198 }
199 
200 void *initm_pma(void)
201 {
202  return s_info.initm_pma;
203 }
204 
205 /*
206  * 반드시 initm_set_pma 가 호출 되어 있어야 한다.
207  */
208 void *initm_find_vma(void *pma)
209 {
210  char *vma;
211  uint32_t gap;
212 
213  gap = (uint32_t)pma - (uint32_t)s_info.initm_pma;
214  vma = (char *)initm_vma() + gap;
215 
216  return vma;
217 }
218 
219 void *initm_find_pma(void *vma)
220 {
221  char *pma;
222 
223  uint32_t gap;
224  gap = (uint32_t)vma - (uint32_t)initm_vma();
225  pma = (char *)initm_pma() + gap;
226 
227  return pma;
228 }
229 
230 /*
231  * 반드시 initm_set_pma 가 호출 되어 있어야 한다.
232  */
234 {
235  struct tail_info *tail;
236  struct head_info *head;
237 
238  head = initm_vma();
239  head->tail = initm_find_vma(head->tail);
240  tail = head->tail;
241  tail->head = head;
242  tail->data = initm_find_vma(tail->data);
243 }
244 
245 /* End of a file */