Created
November 2, 2009 03:58
-
-
Save ldunn/223923 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <system.h> | |
#include <dux/mm/memory.h> | |
#define END_MEMORY 0x1000000 | |
extern unsigned int end; | |
unsigned int placement = 0; | |
/* malloc(size, flags) | |
* Simple placement based allocator. This allocates off the end of the kernel. | |
* Potential bugs: This has no bound, and does not check with the final heap allocator | |
*/ | |
void *kmalloc_int(unsigned int size, unsigned int flags) | |
{ | |
unsigned int tmp; | |
// Initialize if needed. | |
if (placement == 0) | |
placement = end; | |
// Align on a page if needed. | |
if ((flags & MALLOC_ALIGN) && (placement & 0xfffff000)) { | |
placement &= 0xfffff000; | |
placement += 0x1000; | |
} | |
// Return the address of allocation and increment the next placement address to whatever. | |
tmp = placement; | |
placement += size; | |
return (void*) placement; | |
} | |
static unsigned int *frames; | |
/* set_frame(addr) | |
* Allocates a frame in the frames array. It is assumed to be large enough to | |
* hold whatever address you are allocating! | |
*/ | |
void set_frame(unsigned int addr) | |
{ | |
unsigned int frame = addr/0x1000; | |
frames[frame/32] |= 0x1<<frame%32; | |
} | |
/* clear_frame(addr) | |
* Clears a frame in the frames array. It is assumed to be large enough to | |
* hold whatever address you are clearing! | |
*/ | |
void clear_frame(unsigned int addr) | |
{ | |
unsigned int frame = addr/0x1000; | |
frames[frame/32] &= ~(0x1<<frame%32); | |
} | |
/* test_frame(addr) | |
* Returns 0 if a frame is free or anything else if a frame is not free. It | |
* will not cause data loss is frames is not large enough, but will produce | |
* erratic results. | |
*/ | |
unsigned int test_frame(unsigned int addr) | |
{ | |
unsigned int frame = addr/0x1000; | |
return frames[frame/32] & (0x1<<frame%32); | |
} | |
unsigned int first_frame() | |
{ | |
unsigned int i; | |
for (i = 0; i < END_MEMORY; i+=0x1000) { | |
if (!test_frame(i)) { | |
return i; | |
} | |
} | |
// Control does not reach end in this function, unless you count | |
// The infinite loop that panic will enter. So compiler, I have a | |
// message for you: "You are stupid." | |
panic("No free frames.\n"); | |
// I also added the extra 7 bytes (on IA-32 anyway) to shut you up: | |
return 0; | |
} | |
/* alloc_frame(page, is_kernel, is_writable) | |
* Obtains a physical frame and allocates it to the page table given. | |
*/ | |
unsigned int alloc_frame(PageTableEntry *page, int is_kernel, int is_writable) | |
{ | |
unsigned int addr; | |
// Was the frame already allocated? | |
if (page->address != 0) | |
return -1; | |
addr = first_frame(); | |
set_frame(addr); | |
page->present = 1; | |
page->user = is_kernel ? 0 : 1; | |
page->readwrite = is_writable ? 1 : 0; | |
page->address = addr>>12; | |
return 0; | |
} | |
/* free_frame(page) | |
* Clears the allocation on the physical frame | |
*/ | |
void free_frame(PageTableEntry *page) | |
{ | |
clear_frame(page->address<<12); | |
page->address = 0x0; | |
} | |
PageDirEntry *cur_page_directory; | |
/* clear_page_directory(page_directory) | |
* Clears the page directory given. | |
*/ | |
void clear_page_directory(PageDirEntry* page_directory) | |
{ | |
unsigned int i; | |
for (i = 0; i < 1024; i++) { | |
page_directory[i].present = 0; | |
page_directory[i].readwrite = 1; | |
page_directory[i].user = 0; | |
} | |
} | |
/* idmap_page_table(page_table, address) | |
* Identity maps the page table given to address. | |
*/ | |
void idmap_page_table(PageTableEntry* page_table, unsigned int address) | |
{ | |
unsigned int i; | |
for (i = 0; i < 1024; i++, address += 0x1000) { | |
page_table[i].address = address >> 12; | |
page_table[i].present = 1; | |
page_table[i].readwrite = 1; | |
page_table[i].user = 0; | |
} | |
} | |
void init_mm() | |
{ | |
PageTableEntry* page_table; | |
// Memory is assumed to be 16 MB. | |
frames = (unsigned int*) kmalloc_int(END_MEMORY/0x1000, NULL); | |
memset(frames, 0, END_MEMORY/0x1000/8); | |
// Create page directory | |
cur_page_directory = (PageDirEntry*) kmalloc_int(sizeof(PageDirEntry)*1024, MALLOC_ALIGN); | |
clear_page_directory(cur_page_directory); | |
// Create a page table. | |
page_table = (PageTableEntry*) kmalloc_int(sizeof(PageTableEntry)*1024, MALLOC_ALIGN); | |
idmap_page_table(page_table, 0); | |
// Add that page table to the page directory. | |
cur_page_directory[0].address = (unsigned int) page_table >> 12; | |
cur_page_directory[0].present = 1; | |
cur_page_directory[0].readwrite = 1; | |
cur_page_directory[0].user = 0; | |
// Enable paging. | |
asm volatile("mov %0, %%cr3":: "b"(cur_page_directory)); | |
unsigned int cr0; | |
asm volatile("mov %%cr0, %0": "=b"(cr0)); | |
cr0 |= 0x80000000; | |
asm volatile("mov %0, %%cr0":: "b"(cr0)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment