Completed kheap and added some parts of paging.h

This commit is contained in:
ice-bit 2019-09-23 12:23:50 +02:00
parent 07eff0e48c
commit 3eacf3ea21
4 changed files with 182 additions and 3 deletions

View File

@ -2,10 +2,52 @@
// Extern variables are declared in the linker script
extern uint32_t end;
uint32_t placement_addr = (uint32_t)&end;
extern page_directory_t *kernel_directory; // FIXME:
uint32_t placement_addr = (uint32_t)&end;
heap_t *kheap = 0;
uint32_t kmalloc_init(uint32_t sz, int32_t align, uint32_t *phys) {
if(kheap != 0) {
void *addr = alloc(sz, (uint8_t)align, &kheap);
if(phys != 0) {
page_t *page = get_page((uint32_t)addr, 0, kernel_directory);
*phys = page->frame*0x1000 + (uint32_t)addr&0xFFF;
}
return (uint32_t)addr;
} else {
if(align == 1 && (placement_addr & 0xFFFFF000)) {
// Align
placement_addr &= 0xFFFFF000;
placement_addr += 0x1000;
}
if(phys)
*phys = placement_addr;
uint32_t tmp = placement_addr;
placement_addr += sz;
return tmp;
}
}
void kfree(void *p) {
free(p, kheap);
}
uint32_t kmalloc_a(uint32_t sz) {
return kmalloc_int(sz, 1, 0);
}
uint32_t kmalloc_p(uint32_t sz, uint32_t *phys) {
return kmalloc_int(sz, 0, phys);
}
uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys) {
return kmalloc_int(sz, 1, phys);
}
uint32_t kmalloc(uint32_t sz) {
return kmalloc_int(sz, 0, 0);
}
/* The following function is a simple method to find the smallest hole that
* fit user space request, since we will do this process many times, it's a good
* idea to wrap it in a function */
@ -37,7 +79,7 @@ static int8_t header_t_less_than(void *a, void *b) {
}
heap_t *create_heap(uint32_t start, uint32_t end, uint32_t max, uint8_t supervisor, uint8_t readonly) {
heap_t *heap = (heap_t*)kmalloc(sizeof(heap_t)); //TODO: implement kmalloc
heap_t *heap = (heap_t*)kmalloc(sizeof(heap_t));
ASSERT(start%0x1000 == 0);
ASSERT(end%0x1000 == 0);
@ -224,7 +266,7 @@ void free(void *p, heap_t *heap) {
// Add header to free hole's index.
int8_t add_to_free_hole = 1;
// If left-most thing is a footer, then:
// If left-most thing is a footer, then perform left unification
footer_t *test_footer = (footer_t*) ((uint32_t)head - sizeof(footer_t));
if(test_footer->magic == HEAP_MAGIC &&
test_footer->header->is_hole == 1) {
@ -235,5 +277,42 @@ void free(void *p, heap_t *heap) {
add_to_free_hole = 0;
}
header_t *test_header = (header_t*) ((uint32_t)foot + sizeof(footer_t));
if(test_header->magic == HEAP_MAGIC && test_header->is_hole) {
head->size += test_header->size; // Increase size
test_footer = (footer_t*) ((uint32_t)test_header * test_header->size - sizeof(footer_t));
foot = test_footer;
// remove this header from the index
uint32_t it = 0;
while((it < heap->index.size) && (lookup_ordered_list(it, &heap->index) != (void*)test_header))
it++;
// Check if we found the item
ASSERT(it < heap->index.size);
// Then remove it
remove_ordered_list(it, &heap->index);
}
// Contract footer if it is at end address
if((uint32_t)foot+sizeof(footer_t) == heap->end_address) {
uint32_t old_len = heap->end_address-heap->start_address;
uint32_t new_len = contract((uint32_t)head - heap->start_address, heap);
// Check header size after resizing
if(head->size - (old_len-new_len) > 0) {
head->size -= old_len-new_len;
foot = (footer_t*) ((uint32_t)head + head->size - sizeof(footer_t));
foot->magic = HEAP_MAGIC;
foot->header = head;
} else { // Remove empty holes, this reduce fragmentation
uint32_t it = 0;
while((it < heap->index.size) && (lookup_ordered_list(it, &heap->index) != (void*)test_header))
it++;
// If nothing has been found, nothing will be removed
if(it < heap->index.size)
remove_ordered_list(it, &heap->index);
}
}
if(add_to_free_hole == 1)
insert_ordered_list((void*) head, &heap->index);
}

View File

@ -60,5 +60,12 @@ typedef struct {
heap_t *create_heap(uint32_t start, uint32_t end, uint32_t max, uint8_t supervisor, uint8_t readonly);
void *alloc(uint32_t size, uint8_t page_align, heap_t *heap);
void free(void *p, heap_t *heap);
// Public heap functions
uint32_t kmalloc_init(uint32_t sz, int32_t align, uint32_t *phys);
void kfree(void *p);
uint32_t kmalloc_a(uint32_t sz);
uint32_t kmalloc_p(uint32_t sz, uint32_t *phys);
uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys);
uint32_t kmalloc(uint32_t sz);
#endif

56
kernel/drivers/paging.c Normal file
View File

@ -0,0 +1,56 @@
#include "paging.h"
// Macros for bitset algorithms
#define INDEX_FROM_BIT(a) (a/(8*4))
#define OFFSET_FROM_BIT(a) (a%(8*4))
// Kernel's page directory
page_directory_t *kernel_directory = 0;
// Current page directory
page_directory_t *current_directory = 0;
// Bitset of frames, used or free
uint32_t *frames;
uint32_t nframes;
// From kheap.c
extern uint32_t placement_address;
extern heap_t *kheap;
// Set a bit in the frame bitset
static void set_frame(uint32_t frame_addr) {
uint32_t frame = frame_addr / 0x1000;
uint32_t idx = INDEX_FROM_BIT(frame);
uint32_t off = OFFSET_FROM_BIT(frame);
frames[idx] |= (0x1 << off);
}
// clear a bit in the frame bitset
static void clear_frame(uint32_t frame_addr) {
uint32_t frame = frame_addr / 0x1000;
uint32_t idx = INDEX_FROM_BIT(frame);
uint32_t off = OFFSET_FROM_BIT(frame);
frames[idx] &= ~(0x1 << off);
}
// Test if a bit is set
static uint32_t test_frame(uint32_t frame_addr) {
uint32_t frame = frame_addr / 0x1000;
uint32_t idx = INDEX_FROM_BIT(frame);
uint32_t off = OFFSET_FROM_BIT(frame);
return (frames[idx] & (0x1 << off));
}
// Find the first three frames
static uint32_t first_frame() {
for(uint32_t i = 0; i < INDEX_FROM_BIT(nframes); i++) {
if(frames[i] != 0xFFFFFFFF) { // If nothing is free, exit
for(uint32_t j = 0; j < 32; j++) {
uint32_t to_test = 0x1 << j;
if (!(frames[i]&to_test))
return i*4*8+j;
}
}
}
}

37
kernel/drivers/paging.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef PAGING_H
#define PAGING_G
#include <stdint.h>
#include "isr.h"
#include "kheap.h"
typedef struct page {
uint32_t present : 1; // Presence in memory of single page
uint32_t fw : 1; // if set read write otherwise read only
uint32_t user : 1; // Supervisored mode only if cleared
uint32_t accessed : 1; // true if page has been accessed since last refresh
uint32_t dirty : 1; // Same as above for write.
uint32_t unused : 7; // unused bits
uint32_t frame : 20; // Frame address (shifted to the right)
} page_t;
typedef struct page_table {
page_t pages[1024];
} page_table_t;
typedef struct page_directory {
page_table_t *tables[1024]; // array of pointers to page tables
uint32_t tables_physical[1024]; // address of tables physical.
uint32_t physical_addr;
} page_directory_t;
// Setup the environment
void init_paging();
// Load specified page directory into CR3 register
void switch_page_directory(page_directory_t *new);
// Retrieve pointer to specified page address
page_t *get_page(uint32_t addr, int32_t make, page_directory_t *dir);
// Handle page faults
void page_fault(registers_t regs);
#endif