-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3a50f71
commit e02a445
Showing
10 changed files
with
1,310 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
#include <hal/hal.h> | ||
#include <mm/kheap.h> | ||
#include <mm/mm.h> | ||
#include <mm/paging.h> | ||
#include <drivers/video.h> | ||
|
||
#define HEAP_END 0x200000 | ||
|
||
heap_info_t heap_info; | ||
|
||
/** | ||
* Init the kernel heap memory | ||
*/ | ||
void kheap_init() { | ||
heap_info.start = (vmm_addr_t *) &kernel_end; | ||
heap_info.size = HEAP_END - (int) &kernel_end; | ||
heap_info.used = sizeof(heap_header_t); | ||
heap_info.first_header = (heap_header_t *) heap_info.start; | ||
heap_info.first_header->magic = HEAP_MAGIC; | ||
heap_info.first_header->size = heap_info.size - heap_info.used; | ||
heap_info.first_header->is_free = 1; | ||
heap_info.first_header->next = NULL; | ||
} | ||
|
||
void *kmalloc(size_t len) { | ||
return first_free(len); | ||
} | ||
|
||
void kfree(void *ptr) { | ||
heap_header_t *head = ptr - sizeof(heap_header_t); | ||
if((head->is_free == 0) && (head->magic == HEAP_MAGIC)) { | ||
head->is_free = 1; | ||
heap_info.used -= head->size; | ||
|
||
// Merge contiguous free sections | ||
heap_header_t *app = head->next; | ||
while((app != NULL) && (app->is_free == 1)) { | ||
head->size += app->size + sizeof(heap_header_t); | ||
head->next = app->next; | ||
|
||
app = app->next; | ||
} | ||
} | ||
} | ||
|
||
void *first_free(size_t len) { | ||
heap_header_t *head = (heap_header_t *) heap_info.first_header; | ||
|
||
if(heap_info.used >= heap_info.size) | ||
return NULL; | ||
|
||
while(head != NULL) { | ||
if((head->size >= len) && (head->is_free == 1) && (head->magic == HEAP_MAGIC)) { | ||
head->is_free = 0; | ||
heap_header_t *head2 = (heap_header_t *) head + len + sizeof(heap_header_t); | ||
head2->size = head->size - len - sizeof(heap_header_t); | ||
head2->magic = HEAP_MAGIC; | ||
head2->is_free = 1; | ||
head2->next = NULL; | ||
head->next = head2; | ||
head->size = len; | ||
heap_info.used += len + sizeof(heap_header_t); | ||
return (void *) head + sizeof(heap_header_t); | ||
} | ||
head = head->next; | ||
} | ||
return NULL; | ||
} | ||
|
||
int get_heap_size() { | ||
return heap_info.size; | ||
} | ||
|
||
int get_used_heap() { | ||
return heap_info.used; | ||
} | ||
|
||
void print_header(heap_header_t *head) { | ||
printk("Size: %d Is free: %d Next: %x\n", head->size, head->is_free, head->next); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
#include <hal/hal.h> | ||
#include <lib/string.h> | ||
#include <drivers/video.h> | ||
|
||
mem_info_t pmm; | ||
|
||
// 32KB for the bitmap to reserve up to 4GB | ||
static uint32_t bitmap[BITMAP_LEN] __attribute__((aligned(BLOCKS_LEN))); | ||
|
||
/** | ||
* Initializes the physical memory manager | ||
* Every bit in the pmm.map indicates if a 4096 byte block is free or not | ||
* mem_size is in KB | ||
*/ | ||
void pmm_init(uint32_t mem_size, mm_addr_t *mmap_addr, uint32_t mmap_len) { | ||
// Get the blocks number | ||
pmm.max_blocks = pmm.used_blocks = mem_size / 4; | ||
// Set the address for the memory map | ||
pmm.map = bitmap; | ||
// Set all the blocks as used | ||
memset(pmm.map, BYTE_SET, BITMAP_LEN); | ||
|
||
mem_region_t *mm_reg = (mem_region_t *) mmap_addr; | ||
|
||
// Parse the memory map | ||
while(mm_reg < (mem_region_t *) mmap_addr + mmap_len) { | ||
// Check if the memory region is available | ||
if(mm_reg->type == 1) | ||
pmm_init_reg(mm_reg->addr_low, mm_reg->len_low); | ||
|
||
// Increment the pointer to the next map entry | ||
mm_reg = (mem_region_t *) ((uint32_t) mm_reg + mm_reg->size + sizeof(mm_reg->size)); | ||
} | ||
pmm_deinit_reg(0x0, KERNEL_SPACE_END); | ||
pmm.size = (pmm.max_blocks - pmm.used_blocks) * 4; | ||
} | ||
|
||
/** | ||
* Sets the block as used | ||
*/ | ||
void pmm_set_bit(int bit) { | ||
pmm.map[bit / 32] |= (1 << (bit % 32)); | ||
} | ||
|
||
/** | ||
* Sets the block as free | ||
*/ | ||
void pmm_unset_bit(int bit) { | ||
pmm.map[bit / 32] &= ~(1 << (bit % 32)); | ||
} | ||
|
||
/** | ||
* Gets the first free block | ||
*/ | ||
int pmm_first_free() { | ||
uint32_t i; | ||
int j; | ||
|
||
for(i = 0; i < pmm.max_blocks / 32; i++) { | ||
if(pmm.map[i] != BYTE_SET) { | ||
for(j = 0; j < 32; j++) { | ||
if(!(pmm.map[i] & (1 << j))) { | ||
return (i * 32) + j; | ||
} | ||
} | ||
} | ||
} | ||
return -1; | ||
} | ||
|
||
/** | ||
* Initializes a memory region to be used | ||
*/ | ||
void pmm_init_reg(mm_addr_t addr, uint32_t size) { | ||
uint32_t i; | ||
uint32_t blocks = size / BLOCKS_LEN; | ||
uint32_t align = addr / BLOCKS_LEN; | ||
for(i = 0; i < blocks; i++) { | ||
pmm_unset_bit(align++); | ||
pmm.used_blocks--; | ||
} | ||
pmm_set_bit(0); | ||
} | ||
|
||
/** | ||
* Deinitializes a reserved memory region | ||
*/ | ||
void pmm_deinit_reg(mm_addr_t addr, uint32_t size) { | ||
uint32_t i; | ||
uint32_t blocks = size / BLOCKS_LEN; | ||
uint32_t align; | ||
if(addr == 0) { | ||
align = 0; | ||
} else { | ||
align = addr / BLOCKS_LEN; | ||
} | ||
for(i = 0; i < blocks; i++) { | ||
pmm_set_bit(align++); | ||
pmm.used_blocks++; | ||
} | ||
} | ||
|
||
/** | ||
* Returns a usable block | ||
*/ | ||
void *pmm_malloc() { | ||
int p = pmm_first_free(); | ||
if(!p) | ||
return NULL; | ||
pmm_set_bit(p); | ||
pmm.used_blocks++; | ||
return (void *) (BLOCKS_LEN * p); | ||
} | ||
|
||
/** | ||
* Frees a block | ||
*/ | ||
void pmm_free(mm_addr_t *addr) { | ||
if((uint32_t) addr < KERNEL_SPACE_END) | ||
return; | ||
pmm_unset_bit((uint32_t) addr / BLOCKS_LEN); | ||
pmm.used_blocks--; | ||
} | ||
|
||
mm_addr_t *get_mem_map() { | ||
return pmm.map; | ||
} | ||
|
||
uint32_t get_mem_size() { | ||
return pmm.size; | ||
} | ||
|
||
uint32_t get_used_blocks() { | ||
return pmm.used_blocks; | ||
} | ||
|
||
uint32_t get_max_blocks() { | ||
return pmm.max_blocks; | ||
} | ||
|
||
/** | ||
* Enables paging | ||
*/ | ||
void enable_paging() { | ||
uint32_t reg; | ||
// Enable paging | ||
asm volatile("mov %%cr0, %0" : "=r" (reg)); | ||
reg |= 0x80000000; | ||
asm volatile("mov %0, %%cr0" : : "r" (reg)); | ||
} | ||
|
||
/** | ||
* Loads the pdbr register with a physical address to a page directory | ||
*/ | ||
void load_pdbr(mm_addr_t addr) { | ||
asm volatile("mov %0, %%cr3" : : "r" (addr)); | ||
} | ||
|
||
/** | ||
* Gets the pdbr value | ||
*/ | ||
mm_addr_t get_pdbr() { | ||
mm_addr_t ret; | ||
asm volatile("mov %%cr3, %0" : "=r" (ret)); | ||
return ret; | ||
} | ||
|
||
/** | ||
* Flushes the TLB cache | ||
*/ | ||
void flush_tlb(vmm_addr_t addr) { | ||
asm volatile("cli; invlpg (%0); sti" : : "r" (addr)); | ||
} | ||
|
||
/** | ||
* Gets the value of the cr0 register | ||
*/ | ||
int get_cr0() { | ||
int ret; | ||
asm volatile("mov %%cr0, %0" : "=r" (ret)); | ||
return ret; | ||
} | ||
|
||
/** | ||
* Gets the value of the cr2 register | ||
*/ | ||
int get_cr2() { | ||
int ret; | ||
asm volatile("mov %%cr2, %0" : "=r" (ret)); | ||
return ret; | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#include <lib/string.h> | ||
#include <mm/memory.h> | ||
|
||
#define MAX_BLOCKS 512 | ||
#define PAGE_START 0x200000 | ||
|
||
// 16B to hold up 2 MB of paging structures | ||
static uint32_t bitmap[0x10]; | ||
static int used_blocks = 0; | ||
|
||
/** | ||
* Allocates space for a page table | ||
*/ | ||
void *page_table_malloc() { | ||
int p = paging_first_free(); | ||
if(p == -1) | ||
return NULL; | ||
paging_set_bit(p); | ||
used_blocks++; | ||
void *addr = (void *) ((BLOCKS_LEN * p) + PAGE_START); | ||
memset(addr, 0, PAGE_SIZE); | ||
return addr; | ||
} | ||
|
||
/** | ||
* Sets the block as used | ||
*/ | ||
void paging_set_bit(int bit) { | ||
bitmap[bit / 32] |= (1 << (bit % 32)); | ||
} | ||
|
||
/** | ||
* Sets the block as free | ||
*/ | ||
void paging_unset_bit(int bit) { | ||
bitmap[bit / 32] &= ~(1 << (bit % 32)); | ||
} | ||
|
||
/** | ||
* Gets the first free block | ||
*/ | ||
int paging_first_free() { | ||
uint32_t i; | ||
int j; | ||
|
||
for(i = 0; i < MAX_BLOCKS / 32; i++) { | ||
if(bitmap[i] != BYTE_SET) { | ||
for(j = 0; j < 32; j++) { | ||
if(!(bitmap[i] & (1 << j))) { | ||
return (i * 32) + j; | ||
} | ||
} | ||
} | ||
} | ||
return -1; | ||
} | ||
|
||
/** | ||
* Frees a block | ||
*/ | ||
void page_table_free(void *addr) { | ||
paging_unset_bit(((uint32_t) addr / BLOCKS_LEN) - PAGE_START); | ||
used_blocks--; | ||
} | ||
|
||
uint32_t *get_page_table_bitmap() { | ||
return bitmap; | ||
} |
Oops, something went wrong.