kern

annotate src/mem.c @ 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 098b1cb5eeaa
children 369adbbd4bdd
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