Skip to content

Commit

Permalink
Regarding #35
Browse files Browse the repository at this point in the history
  • Loading branch information
MirMohammadd committed Mar 21, 2024
1 parent 3a50f71 commit e02a445
Show file tree
Hide file tree
Showing 10 changed files with 1,310 additions and 0 deletions.
80 changes: 80 additions & 0 deletions kernel/mm/kheap.c
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);
}
191 changes: 191 additions & 0 deletions kernel/mm/mm.c
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;
}
68 changes: 68 additions & 0 deletions kernel/mm/paging.c
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;
}
Loading

0 comments on commit e02a445

Please sign in to comment.