kern
changeset 19:8be069e6bb05
I think I'm done with the physical memory page allocator
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 30 Mar 2011 22:42:16 +0300 |
parents | 096807345aa2 |
children | 369adbbd4bdd |
files | src/main.c src/mem.c src/mem.h src/vm.c |
diffstat | 4 files changed, 172 insertions(+), 45 deletions(-) [+] |
line diff
1.1 --- a/src/main.c Sun Mar 27 06:28:26 2011 +0300 1.2 +++ b/src/main.c Wed Mar 30 22:42:16 2011 +0300 1.3 @@ -53,11 +53,13 @@ 1.4 1.5 init_segm(); 1.6 init_intr(); 1.7 - init_vm(mbinf); 1.8 1.9 /* silence the blasted timer interrupt */ 1.10 interrupt(32, do_nothing); 1.11 1.12 + init_vm(mbinf); 1.13 + 1.14 + 1.15 for(;;) { 1.16 char c, keypress; 1.17 do {
2.1 --- a/src/mem.c Sun Mar 27 06:28:26 2011 +0300 2.2 +++ b/src/mem.c Wed Mar 30 22:42:16 2011 +0300 2.3 @@ -1,40 +1,181 @@ 2.4 #include <stdio.h> 2.5 +#include <string.h> 2.6 #include "mem.h" 2.7 #include "panic.h" 2.8 #include "vm.h" 2.9 2.10 +#define FREE 0 2.11 +#define USED 1 2.12 + 2.13 +#define BM_IDX(pg) ((pg) / 32) 2.14 +#define BM_BIT(pg) ((pg) & 0x1f) 2.15 + 2.16 +#define IS_FREE(pg) ((bitmap[BM_IDX(pg)] & (1 << BM_BIT(pg))) == 0) 2.17 + 2.18 +static void mark_page(int pg, int free); 2.19 +static void add_memory(uint32_t start, size_t size); 2.20 + 2.21 /* end of kernel image */ 2.22 extern int _end; 2.23 2.24 -static uint32_t brk; 2.25 +static uint32_t *bitmap; 2.26 +static int bmsize, last_alloc_idx; 2.27 2.28 void init_mem(struct mboot_info *mb) 2.29 { 2.30 - /* start the physical allocated break at the end of 2.31 - * the kernel image 2.32 - */ 2.33 - brk = (uint32_t)&_end; 2.34 + int i, num_pages, max_pg = 0; 2.35 + uint32_t used_end; 2.36 + 2.37 + num_pages = 0; 2.38 + last_alloc_idx = 0; 2.39 + 2.40 + bitmap = (uint32_t*)&_end; 2.41 + 2.42 + /* start by marking all posible pages as used */ 2.43 + memset(bitmap, 0xff, 1024 * 1024 / 8); 2.44 + 2.45 + /* build the memory map */ 2.46 + if(mb->flags & MB_MMAP) { 2.47 + struct mboot_mmap *mem, *mmap_end; 2.48 + 2.49 + mem = mb->mmap; 2.50 + mmap_end = (struct mboot_mmap*)((char*)mb->mmap + mb->mmap_len); 2.51 + 2.52 + printf("memory map:\n"); 2.53 + while(mem < mmap_end) { 2.54 + char *type; 2.55 + unsigned int end = mem->base_low + mem->length_low; 2.56 + 2.57 + if(mem->type == MB_MEM_VALID) { 2.58 + type = "free:"; 2.59 + add_memory(mem->base_low, mem->length_low); 2.60 + 2.61 + num_pages = ADDR_TO_PAGE(mem->base_low + mem->length_low); 2.62 + if(max_pg < num_pages) { 2.63 + max_pg = num_pages; 2.64 + } 2.65 + } else { 2.66 + type = "hole:"; 2.67 + } 2.68 + 2.69 + printf(" %s %x - %x (%u bytes)\n", type, mem->base_low, end, mem->length_low); 2.70 + mem = (struct mboot_mmap*)((char*)mem + mem->skip + sizeof mem->skip); 2.71 + } 2.72 + } else if(mb->flags & MB_MEM) { 2.73 + add_memory(0, mb->mem_lower); 2.74 + add_memory(0x100000, mb->mem_upper * 1024); 2.75 + max_pg = mb->mem_upper / 4; 2.76 + 2.77 + printf("lower memory: %ukb, upper mem: %ukb\n", mb->mem_lower, mb->mem_upper); 2.78 + } else { 2.79 + panic("didn't get any memory info from the boot loader, I give up\n"); 2.80 + } 2.81 + 2.82 + bmsize = max_pg / 8; /* size of the bitmap in bytes */ 2.83 + 2.84 + /* mark all the used pages as ... well ... used */ 2.85 + used_end = ((uint32_t)bitmap + bmsize - 1); 2.86 + 2.87 + printf("marking pages up to %x ", used_end); 2.88 + used_end = ADDR_TO_PAGE(used_end); 2.89 + printf("(page: %d) inclusive as used\n", used_end); 2.90 + 2.91 + for(i=0; i<=used_end; i++) { 2.92 + mark_page(i, USED); 2.93 + } 2.94 + 2.95 + /*for(i=0; i<bmsize / 4; i++) { 2.96 + printf("%3d [%x]\n", i, bitmap[i]); 2.97 + asm("hlt"); 2.98 + } 2.99 + putchar('\n');*/ 2.100 } 2.101 2.102 uint32_t alloc_phys_page(void) 2.103 { 2.104 - uint32_t addr, dbg_prev_brk; 2.105 + int i, idx, max; 2.106 2.107 - if(ADDR_TO_PGOFFS(brk)) { 2.108 - /* brk is not aligned, find the next page-aligned address */ 2.109 - addr = (brk + PGSIZE) & ~PGOFFS_MASK; 2.110 - } else { 2.111 - /* brk is aligned, so we can use that address directly */ 2.112 - addr = brk; 2.113 + idx = last_alloc_idx; 2.114 + max = bmsize / 4; 2.115 + 2.116 + while(idx <= max) { 2.117 + /* if at least one bit is 0 then we have at least 2.118 + * one free page. find it and allocate it. 2.119 + */ 2.120 + if(bitmap[idx] != 0xffffffff) { 2.121 + for(i=0; i<32; i++) { 2.122 + int pg = idx * 32 + i; 2.123 + 2.124 + if(IS_FREE(pg)) { 2.125 + mark_page(pg, USED); 2.126 + 2.127 + last_alloc_idx = idx; 2.128 + 2.129 + printf("alloc_phys_page() -> %x (page: %d)\n", PAGE_TO_ADDR(pg), pg); 2.130 + return PAGE_TO_ADDR(pg); 2.131 + } 2.132 + } 2.133 + panic("can't happen: alloc_phys_page (mem.c)\n"); 2.134 + } 2.135 + idx++; 2.136 } 2.137 2.138 - if(addr >= MAX_BRK) { 2.139 - panic("alloc_phys_page() out of early alloc space"); 2.140 + panic("alloc_phys_page(): out of memory\n"); 2.141 + return 0; 2.142 +} 2.143 + 2.144 +void free_phys_page(uint32_t addr) 2.145 +{ 2.146 + int pg = ADDR_TO_PAGE(addr); 2.147 + int bmidx = BM_IDX(pg); 2.148 + 2.149 + if(!IS_FREE(pg)) { 2.150 + panic("free_phys_page(%d): I thought that was already free!\n", pg); 2.151 } 2.152 2.153 - dbg_prev_brk = brk; 2.154 - brk = addr + PGSIZE; /* move the break to the end of the page */ 2.155 + mark_page(pg, FREE); 2.156 + if(bmidx < last_alloc_idx) { 2.157 + last_alloc_idx = bmidx; 2.158 + } 2.159 +} 2.160 2.161 - printf("DBG: alloc_phys_page(): %x (brk %x -> %x)\n", addr, dbg_prev_brk, brk); 2.162 - return addr; 2.163 +void get_kernel_mem_range(uint32_t *start, uint32_t *end) 2.164 +{ 2.165 + if(start) { 2.166 + *start = 0x100000; 2.167 + } 2.168 + if(end) { 2.169 + uint32_t e = (uint32_t)bitmap + bmsize; 2.170 + 2.171 + if(e & PGOFFS_MASK) { 2.172 + *end = (e + 4096) & PGOFFS_MASK; 2.173 + } else { 2.174 + *end = e; 2.175 + } 2.176 + } 2.177 } 2.178 + 2.179 +static void add_memory(uint32_t start, size_t sz) 2.180 +{ 2.181 + int i, szpg, pg; 2.182 + 2.183 + szpg = ADDR_TO_PAGE(sz); 2.184 + pg = ADDR_TO_PAGE(start); 2.185 + 2.186 + for(i=0; i<szpg; i++) { 2.187 + mark_page(pg++, FREE); 2.188 + } 2.189 +} 2.190 + 2.191 +static void mark_page(int pg, int used) 2.192 +{ 2.193 + int idx = BM_IDX(pg); 2.194 + int bit = BM_BIT(pg); 2.195 + 2.196 + if(used) { 2.197 + bitmap[idx] |= 1 << bit; 2.198 + } else { 2.199 + bitmap[idx] &= ~(1 << bit); 2.200 + } 2.201 +} 2.202 +
3.1 --- a/src/mem.h Sun Mar 27 06:28:26 2011 +0300 3.2 +++ b/src/mem.h Wed Mar 30 22:42:16 2011 +0300 3.3 @@ -3,10 +3,11 @@ 3.4 3.5 #include "mboot.h" 3.6 3.7 -/* maximum break for the early allocator */ 3.8 -#define MAX_BRK 0x400000 3.9 +void init_mem(struct mboot_info *mb); 3.10 3.11 -void init_mem(struct mboot_info *mb); 3.12 uint32_t alloc_phys_page(void); 3.13 +void free_phys_page(uint32_t addr); 3.14 + 3.15 +void get_kernel_mem_range(uint32_t *start, uint32_t *end); 3.16 3.17 #endif /* MEM_H_ */
4.1 --- a/src/vm.c Sun Mar 27 06:28:26 2011 +0300 4.2 +++ b/src/vm.c Wed Mar 30 22:42:16 2011 +0300 4.3 @@ -29,13 +29,16 @@ 4.4 4.5 void init_vm(struct mboot_info *mb) 4.6 { 4.7 + uint32_t idmap_end; 4.8 + 4.9 init_mem(mb); 4.10 4.11 pgdir = (uint32_t*)alloc_phys_page(); 4.12 memset(pgdir, 0, sizeof pgdir); 4.13 4.14 /* map the video memory and kernel code 1-1 */ 4.15 - map_mem_range(IDMAP_START, MAX_BRK - IDMAP_START, IDMAP_START, 0); 4.16 + get_kernel_mem_range(0, &idmap_end); 4.17 + map_mem_range(IDMAP_START, idmap_end - IDMAP_START, IDMAP_START, 0); 4.18 4.19 interrupt(PAGEFAULT, pgfault); 4.20 4.21 @@ -109,28 +112,6 @@ 4.22 map_page_range(vpg_start, num_pages, ppg_start, attr); 4.23 } 4.24 4.25 - 4.26 -/* if(mb->flags & MB_MMAP) { 4.27 - struct mboot_mmap *mem, *mmap_end; 4.28 - 4.29 - mem = mb->mmap; 4.30 - mmap_end = (struct mboot_mmap*)((char*)mb->mmap + mb->mmap_len); 4.31 - 4.32 - printf("memory map:\n"); 4.33 - while(mem < mmap_end) { 4.34 - unsigned int end = mem->base_low + mem->length_low; 4.35 - char *type = mem->type == MB_MEM_VALID ? "free:" : "hole:"; 4.36 - 4.37 - printf(" %s %x - %x (%u bytes)\n", type, mem->base_low, end, mem->length_low); 4.38 - mem = (struct mboot_mmap*)((char*)mem + mem->skip + sizeof mem->skip); 4.39 - } 4.40 - } 4.41 - 4.42 - if(mb->flags & MB_MEM) { 4.43 - printf("lower memory: %ukb, upper mem: %ukb\n", mb->mem_lower, mb->mem_upper); 4.44 - } 4.45 -*/ 4.46 - 4.47 uint32_t virt_to_phys(uint32_t vaddr) 4.48 { 4.49 uint32_t pgaddr, *pgtbl; 4.50 @@ -166,4 +147,6 @@ 4.51 } else { 4.52 printf("page not present\n"); 4.53 } 4.54 + 4.55 + panic("unhandled page fault\n"); 4.56 }