rev |
line source |
nuclear@17
|
1 #include <stdio.h>
|
nuclear@19
|
2 #include <string.h>
|
nuclear@17
|
3 #include "mem.h"
|
nuclear@17
|
4 #include "panic.h"
|
nuclear@17
|
5 #include "vm.h"
|
nuclear@17
|
6
|
nuclear@19
|
7 #define FREE 0
|
nuclear@19
|
8 #define USED 1
|
nuclear@19
|
9
|
nuclear@19
|
10 #define BM_IDX(pg) ((pg) / 32)
|
nuclear@19
|
11 #define BM_BIT(pg) ((pg) & 0x1f)
|
nuclear@19
|
12
|
nuclear@19
|
13 #define IS_FREE(pg) ((bitmap[BM_IDX(pg)] & (1 << BM_BIT(pg))) == 0)
|
nuclear@19
|
14
|
nuclear@19
|
15 static void mark_page(int pg, int free);
|
nuclear@19
|
16 static void add_memory(uint32_t start, size_t size);
|
nuclear@19
|
17
|
nuclear@17
|
18 /* end of kernel image */
|
nuclear@17
|
19 extern int _end;
|
nuclear@17
|
20
|
nuclear@19
|
21 static uint32_t *bitmap;
|
nuclear@19
|
22 static int bmsize, last_alloc_idx;
|
nuclear@17
|
23
|
nuclear@17
|
24 void init_mem(struct mboot_info *mb)
|
nuclear@17
|
25 {
|
nuclear@19
|
26 int i, num_pages, max_pg = 0;
|
nuclear@19
|
27 uint32_t used_end;
|
nuclear@19
|
28
|
nuclear@19
|
29 num_pages = 0;
|
nuclear@19
|
30 last_alloc_idx = 0;
|
nuclear@19
|
31
|
nuclear@19
|
32 bitmap = (uint32_t*)&_end;
|
nuclear@19
|
33
|
nuclear@19
|
34 /* start by marking all posible pages as used */
|
nuclear@19
|
35 memset(bitmap, 0xff, 1024 * 1024 / 8);
|
nuclear@19
|
36
|
nuclear@19
|
37 /* build the memory map */
|
nuclear@19
|
38 if(mb->flags & MB_MMAP) {
|
nuclear@19
|
39 struct mboot_mmap *mem, *mmap_end;
|
nuclear@19
|
40
|
nuclear@19
|
41 mem = mb->mmap;
|
nuclear@19
|
42 mmap_end = (struct mboot_mmap*)((char*)mb->mmap + mb->mmap_len);
|
nuclear@19
|
43
|
nuclear@19
|
44 printf("memory map:\n");
|
nuclear@19
|
45 while(mem < mmap_end) {
|
nuclear@19
|
46 char *type;
|
nuclear@19
|
47 unsigned int end = mem->base_low + mem->length_low;
|
nuclear@19
|
48
|
nuclear@19
|
49 if(mem->type == MB_MEM_VALID) {
|
nuclear@19
|
50 type = "free:";
|
nuclear@19
|
51 add_memory(mem->base_low, mem->length_low);
|
nuclear@19
|
52
|
nuclear@19
|
53 num_pages = ADDR_TO_PAGE(mem->base_low + mem->length_low);
|
nuclear@19
|
54 if(max_pg < num_pages) {
|
nuclear@19
|
55 max_pg = num_pages;
|
nuclear@19
|
56 }
|
nuclear@19
|
57 } else {
|
nuclear@19
|
58 type = "hole:";
|
nuclear@19
|
59 }
|
nuclear@19
|
60
|
nuclear@19
|
61 printf(" %s %x - %x (%u bytes)\n", type, mem->base_low, end, mem->length_low);
|
nuclear@19
|
62 mem = (struct mboot_mmap*)((char*)mem + mem->skip + sizeof mem->skip);
|
nuclear@19
|
63 }
|
nuclear@19
|
64 } else if(mb->flags & MB_MEM) {
|
nuclear@19
|
65 add_memory(0, mb->mem_lower);
|
nuclear@19
|
66 add_memory(0x100000, mb->mem_upper * 1024);
|
nuclear@19
|
67 max_pg = mb->mem_upper / 4;
|
nuclear@19
|
68
|
nuclear@19
|
69 printf("lower memory: %ukb, upper mem: %ukb\n", mb->mem_lower, mb->mem_upper);
|
nuclear@19
|
70 } else {
|
nuclear@19
|
71 panic("didn't get any memory info from the boot loader, I give up\n");
|
nuclear@19
|
72 }
|
nuclear@19
|
73
|
nuclear@19
|
74 bmsize = max_pg / 8; /* size of the bitmap in bytes */
|
nuclear@19
|
75
|
nuclear@19
|
76 /* mark all the used pages as ... well ... used */
|
nuclear@19
|
77 used_end = ((uint32_t)bitmap + bmsize - 1);
|
nuclear@19
|
78
|
nuclear@19
|
79 printf("marking pages up to %x ", used_end);
|
nuclear@19
|
80 used_end = ADDR_TO_PAGE(used_end);
|
nuclear@19
|
81 printf("(page: %d) inclusive as used\n", used_end);
|
nuclear@19
|
82
|
nuclear@19
|
83 for(i=0; i<=used_end; i++) {
|
nuclear@19
|
84 mark_page(i, USED);
|
nuclear@19
|
85 }
|
nuclear@19
|
86
|
nuclear@19
|
87 /*for(i=0; i<bmsize / 4; i++) {
|
nuclear@19
|
88 printf("%3d [%x]\n", i, bitmap[i]);
|
nuclear@19
|
89 asm("hlt");
|
nuclear@19
|
90 }
|
nuclear@19
|
91 putchar('\n');*/
|
nuclear@17
|
92 }
|
nuclear@17
|
93
|
nuclear@17
|
94 uint32_t alloc_phys_page(void)
|
nuclear@17
|
95 {
|
nuclear@19
|
96 int i, idx, max;
|
nuclear@17
|
97
|
nuclear@19
|
98 idx = last_alloc_idx;
|
nuclear@19
|
99 max = bmsize / 4;
|
nuclear@19
|
100
|
nuclear@19
|
101 while(idx <= max) {
|
nuclear@19
|
102 /* if at least one bit is 0 then we have at least
|
nuclear@19
|
103 * one free page. find it and allocate it.
|
nuclear@19
|
104 */
|
nuclear@19
|
105 if(bitmap[idx] != 0xffffffff) {
|
nuclear@19
|
106 for(i=0; i<32; i++) {
|
nuclear@19
|
107 int pg = idx * 32 + i;
|
nuclear@19
|
108
|
nuclear@19
|
109 if(IS_FREE(pg)) {
|
nuclear@19
|
110 mark_page(pg, USED);
|
nuclear@19
|
111
|
nuclear@19
|
112 last_alloc_idx = idx;
|
nuclear@19
|
113
|
nuclear@19
|
114 printf("alloc_phys_page() -> %x (page: %d)\n", PAGE_TO_ADDR(pg), pg);
|
nuclear@19
|
115 return PAGE_TO_ADDR(pg);
|
nuclear@19
|
116 }
|
nuclear@19
|
117 }
|
nuclear@19
|
118 panic("can't happen: alloc_phys_page (mem.c)\n");
|
nuclear@19
|
119 }
|
nuclear@19
|
120 idx++;
|
nuclear@17
|
121 }
|
nuclear@17
|
122
|
nuclear@19
|
123 panic("alloc_phys_page(): out of memory\n");
|
nuclear@19
|
124 return 0;
|
nuclear@19
|
125 }
|
nuclear@19
|
126
|
nuclear@19
|
127 void free_phys_page(uint32_t addr)
|
nuclear@19
|
128 {
|
nuclear@19
|
129 int pg = ADDR_TO_PAGE(addr);
|
nuclear@19
|
130 int bmidx = BM_IDX(pg);
|
nuclear@19
|
131
|
nuclear@19
|
132 if(!IS_FREE(pg)) {
|
nuclear@19
|
133 panic("free_phys_page(%d): I thought that was already free!\n", pg);
|
nuclear@17
|
134 }
|
nuclear@17
|
135
|
nuclear@19
|
136 mark_page(pg, FREE);
|
nuclear@19
|
137 if(bmidx < last_alloc_idx) {
|
nuclear@19
|
138 last_alloc_idx = bmidx;
|
nuclear@19
|
139 }
|
nuclear@19
|
140 }
|
nuclear@17
|
141
|
nuclear@19
|
142 void get_kernel_mem_range(uint32_t *start, uint32_t *end)
|
nuclear@19
|
143 {
|
nuclear@19
|
144 if(start) {
|
nuclear@19
|
145 *start = 0x100000;
|
nuclear@19
|
146 }
|
nuclear@19
|
147 if(end) {
|
nuclear@19
|
148 uint32_t e = (uint32_t)bitmap + bmsize;
|
nuclear@19
|
149
|
nuclear@19
|
150 if(e & PGOFFS_MASK) {
|
nuclear@19
|
151 *end = (e + 4096) & PGOFFS_MASK;
|
nuclear@19
|
152 } else {
|
nuclear@19
|
153 *end = e;
|
nuclear@19
|
154 }
|
nuclear@19
|
155 }
|
nuclear@17
|
156 }
|
nuclear@19
|
157
|
nuclear@19
|
158 static void add_memory(uint32_t start, size_t sz)
|
nuclear@19
|
159 {
|
nuclear@19
|
160 int i, szpg, pg;
|
nuclear@19
|
161
|
nuclear@19
|
162 szpg = ADDR_TO_PAGE(sz);
|
nuclear@19
|
163 pg = ADDR_TO_PAGE(start);
|
nuclear@19
|
164
|
nuclear@19
|
165 for(i=0; i<szpg; i++) {
|
nuclear@19
|
166 mark_page(pg++, FREE);
|
nuclear@19
|
167 }
|
nuclear@19
|
168 }
|
nuclear@19
|
169
|
nuclear@19
|
170 static void mark_page(int pg, int used)
|
nuclear@19
|
171 {
|
nuclear@19
|
172 int idx = BM_IDX(pg);
|
nuclear@19
|
173 int bit = BM_BIT(pg);
|
nuclear@19
|
174
|
nuclear@19
|
175 if(used) {
|
nuclear@19
|
176 bitmap[idx] |= 1 << bit;
|
nuclear@19
|
177 } else {
|
nuclear@19
|
178 bitmap[idx] &= ~(1 << bit);
|
nuclear@19
|
179 }
|
nuclear@19
|
180 }
|
nuclear@19
|
181
|