feat: introduced tasking, added paging (no vm), moved malloc, added

syscalls, other stuff
This commit is contained in:
2021-02-27 11:46:26 +01:00
parent 8f615b259c
commit 9f72d4bb1a
42 changed files with 907 additions and 292 deletions

90
kernel/mem/malloc.c Normal file
View File

@@ -0,0 +1,90 @@
//
// Created by rick on 23-02-21.
//
#include <libc/kprintf.h>
#include <tasks/task.h>
#include "malloc.h"
#include "pmm.h"
#define MALLOC_TYPE_FREE 0
#define MALLOC_TYPE_USED 1
int malloc_entries = 0;
int malloc_used = 0;
typedef struct malloc_map {
struct malloc_map *next;
struct malloc_map *prev;
uint32_t size;
int type;
} malloc_map;
malloc_map *first_malloc_entry;
void malloc_init() {
first_malloc_entry = pmm_get_pages(16);
first_malloc_entry->next = first_malloc_entry;
first_malloc_entry->prev = first_malloc_entry;
first_malloc_entry->size = PAGE_SIZE * 16;
first_malloc_entry->type = MALLOC_TYPE_FREE;
malloc_entries++;
}
void split_malloc_map(malloc_map *entry, unsigned int size) {
malloc_entries++;
malloc_map *new_entry = entry + sizeof(malloc_map) + size;
new_entry->size = entry->size - size - sizeof(malloc_map);
new_entry->next = entry->next;
new_entry->prev = entry;
new_entry->type = MALLOC_TYPE_FREE;
entry->next->prev = new_entry;
entry->next = new_entry;
entry->size = size;
}
void *malloc(size_t size) {
// todo replace this horrible mess!
// this lacks any page alignment and what so ever
void* result = NULL;
task_lock_acquire();
malloc_map *current_map = first_malloc_entry;
// iterate through maps
do {
if (current_map->type == MALLOC_TYPE_USED) {
goto malloc_find_next;
}
if ((unsigned int) current_map->size < size) {
goto malloc_find_next;
}
if ((unsigned int) current_map->size > (size + sizeof(malloc_map))) {
// big enough to split
split_malloc_map(current_map, size);
}
malloc_used++;
current_map->type = MALLOC_TYPE_USED;
result = ((void *) current_map) + sizeof(malloc_map);
break;
malloc_find_next:
current_map = current_map->next;
} while (current_map != first_malloc_entry);
task_lock_free();
return result;
}
void free(void *mem) {
if (mem == NULL) {
return;
}
malloc_used--;
malloc_map *map = (mem - sizeof(malloc_map));
map->type = MALLOC_TYPE_FREE;
};
void print_malloc_info() {
printf("Malloc avail entries: %d\n"
"Malloc used entries: %d\n", malloc_entries, malloc_used);
}

17
kernel/mem/malloc.h Normal file
View File

@@ -0,0 +1,17 @@
//
// Created by rick on 23-02-21.
//
#ifndef NEW_KERNEL_MALLOC_H
#define NEW_KERNEL_MALLOC_H
#include <types.h>
void malloc_init();
void print_malloc_info();
void *malloc(size_t size);
void free(void *mem);
#endif //NEW_KERNEL_MALLOC_H

View File

@@ -2,9 +2,12 @@
// Created by rick on 22-04-20.
//
#include "pmm.h"
#include <types.h>
#include <mem/mem.h>
#include <libc/kprintf.h>
#include <libk.h>
#include <attributes.h>
#define MEMMAP_ENTRIES 16
@@ -15,26 +18,13 @@
#define MMAP_TYPE_NVS 4
#define MMAP_TYPE_BADRAM 5
#define MMAP_TYPE_KERNEL 6
#define MMAP_TYPE_MALLOC 7
#define MALLOC_TYPE_FREE 0
#define MALLOC_TYPE_USED 1
#define kilobyte (1024)
//#define kernel_start (one_meg)
#define kernel_size (32 * kilobyte)
#define kernel_end (kernel_start + kernel_size)
extern void *kernel_start;
//extern void *kernel_end;
#define MMAP_TYPE_PAGING 7
typedef struct {
void *address;
uint32_t address;
uint32_t length;
uint32_t type;
} __attribute((packed)) mmap_entry;
int malloc_entries = 0;
int malloc_used = 0;
} packed mmap_entry;
int last_memmap_entry = 0;
mmap_entry memmap[MEMMAP_ENTRIES] = {
@@ -56,114 +46,51 @@ mmap_entry memmap[MEMMAP_ENTRIES] = {
{0, 0, 0},
};
typedef struct malloc_map {
struct malloc_map *next;
struct malloc_map *pref;
uint32_t size;
int type;
} malloc_map;
void use_mmap_entry(struct multiboot_mmap_entry *entry) {
mmap_entry *mm_entry = &memmap[last_memmap_entry++];
mm_entry->address = (void *) entry->addr;
mm_entry->length = entry->len;
mm_entry->type = entry->type;
if (last_memmap_entry == 1) {
// not using first map entry for now
return;
}
// check if the entry overlaps with the kernel address space
if (kernel_start >= mm_entry->address && kernel_start <= mm_entry->address + mm_entry->length) {
uint32_t page_after_kernel = kernel_end + PAGE_SIZE & ~(PAGE_SIZE - 1);
uint32_t kernel_size_full_pages = page_after_kernel - mm_entry->address;
// todo make this something proper
struct multiboot_mmap_entry extra_entry;
extra_entry.size = entry->size;
extra_entry.type = entry->type;
extra_entry.addr = entry->addr + kernel_size;
extra_entry.len = entry->size - kernel_size;
extra_entry.addr = page_after_kernel;
extra_entry.len = entry->size - kernel_size_full_pages;
use_mmap_entry(&extra_entry);
mm_entry->length = kernel_size;
mm_entry->length = kernel_size_full_pages;
mm_entry->type = MMAP_TYPE_KERNEL;
}
if (mm_entry->type == MMAP_TYPE_AVAILABLE && (unsigned int) mm_entry->length > sizeof(malloc_map)) {
mm_entry->type = MMAP_TYPE_MALLOC;
malloc_map *map = (malloc_map *) mm_entry->address;
map->type = MALLOC_TYPE_FREE;
map->size = mm_entry->length - sizeof(malloc_map);
map->pref = map;
map->next = map;
malloc_entries++;
}
}
void init_mmap_multiboot(struct multiboot_mmap_entry *entries, uint32_t count) {
void mmap_init_multiboot(struct multiboot_mmap_entry *entries, uint32_t count) {
for (uint32_t i = 0; i < count; ++i) {
use_mmap_entry(&entries[i]);
}
}
void split_malloc_map(malloc_map *entry, unsigned int size) {
malloc_entries++;
malloc_map *new_entry = entry + sizeof(malloc_map) + size;
new_entry->size = entry->size - size - sizeof(malloc_map);
new_entry->next = entry->next;
new_entry->pref = entry;
new_entry->type = MALLOC_TYPE_FREE;
entry->next->pref = new_entry;
entry->next = new_entry;
entry->size = size;
}
void *malloc(size_t size) {
// todo replace this horrible mess!
// this lacks any page alignment and what so ever
for (int i = 0; i < MEMMAP_ENTRIES; ++i) {
if (memmap[i].type != MMAP_TYPE_MALLOC) {
// init page manager
for (int i = 0; i < last_memmap_entry; ++i) {
mmap_entry *entry = &memmap[i];
if (entry->type != MMAP_TYPE_AVAILABLE) {
continue;
}
// get first first_map of address
malloc_map *first_map = (malloc_map *) memmap[i].address;
malloc_map *current_map = first_map;
// iterate through maps
do {
if (current_map->type == MALLOC_TYPE_USED) {
goto malloc_find_next;
}
if ((unsigned int) current_map->size < size) {
goto malloc_find_next;
}
if ((unsigned int) current_map->size > (size + sizeof(malloc_map))) {
// big enough to split
split_malloc_map(current_map, size);
}
malloc_used++;
current_map->type = MALLOC_TYPE_USED;
return ((void *) current_map) + sizeof(malloc_map);
if (entry->address < kernel_start) {
continue; // skip for now
}
malloc_find_next:
current_map = current_map->next;
} while (current_map != first_map);
pmm_init((void *) entry->address, entry->length);
entry->type = MMAP_TYPE_PAGING;
}
return NULL;
}
void free(void *mem) {
if (mem == NULL) {
return;
}
malloc_used--;
malloc_map *map = (mem - sizeof(malloc_map));
map->type = MALLOC_TYPE_FREE;
};
void print_malloc_info() {
printf("Malloc avail entries: %d\n"
"Malloc used entries: %d\n", malloc_entries, malloc_used);
}
void print_mmap_info() {
printf("Kernel start: %8x\n"
"Kernel end: %8x\n", kernel_start, kernel_end);
for (int i = 0; i < 16; ++i) {
if (memmap[i].type == 0) {
break;

View File

@@ -7,14 +7,8 @@
#include <multiboot.h>
void init_mmap_multiboot(struct multiboot_mmap_entry *entries, uint32_t count);
void print_malloc_info();
void mmap_init_multiboot(struct multiboot_mmap_entry *entries, uint32_t count);
void print_mmap_info();
void *malloc(size_t size);
void free(void *mem);
#endif //NEW_KERNEL_MEM_H

98
kernel/mem/pmm.c Normal file
View File

@@ -0,0 +1,98 @@
//
// Created by rick on 23-02-21.
//
#include <stdbool.h>
#include <libc/libc.h>
#include <libk.h>
#include "pmm.h"
#define NUM_PAGING_INFOS 16
#define BLOCK_USED 1
#define BLOCK_FREE 0
#define bitmap_block_byte(block) ((block) / 8)
#define bitmap_block_bit(block) ((block) % 8)
#define bitmap_set(addr, block) (addr)[bitmap_block_byte(block)] = ((addr)[bitmap_block_byte(block)] | (1 << (bitmap_block_bit(block))))
#define bitmap_unset(addr, block) (addr)[bitmap_block_byte(block)] = ((addr)[bitmap_block_byte(block)] & ~(1 << (bitmap_block_bit(block))))
#define bitmap_get(addr, block) ((addr)[bitmap_block_byte(block)] >> bitmap_block_bit(block))
#define page_to_addr(base_addr, block) ((base_addr) + ((block) * PAGE_SIZE))
#define addr_to_page(base_addr, addr) (((addr) - (base_addr)) / PAGE_SIZE)
typedef struct {
union {
uint8_t *page_bitmap;
void *first_page;
};
uint32_t num_pages;
size_t size;
struct {
bool present: 1;
} flags;
} paging_info;
uint8_t last_paging_info = 0;
paging_info paging_infos[NUM_PAGING_INFOS];
void pmm_init(void *start_addr, size_t size) {
uint32_t num_pages = size / PAGE_SIZE;
uint32_t bitmap_size = num_pages / 8;
uint32_t bitmap_pages = bitmap_size / PAGE_SIZE;
paging_infos[last_paging_info].page_bitmap = start_addr;
paging_infos[last_paging_info].num_pages = num_pages;
paging_infos[last_paging_info].size = size;
paging_infos[last_paging_info].flags.present = true;
memset(start_addr, BLOCK_FREE, bitmap_pages);
for (uint32_t i = 0; i < bitmap_pages; ++i) {
bitmap_set((uint8_t *) start_addr, i);
}
last_paging_info++;
}
void *pmm_get_pages(uint32_t num_pages) {
for (int i = 0; i < last_paging_info; ++i) {
paging_info *info = &paging_infos[i];
if (!info->flags.present) continue;
for (uint32_t j = 0; j < info->num_pages; ++j) {
if (bitmap_get(info->page_bitmap, j) == BLOCK_FREE) {
uint32_t k;
bool usable = true;
for (k = j + 1; k < j + num_pages; ++k) {
if (bitmap_get(info->page_bitmap, k) == BLOCK_USED) {
usable = false;
j = k; // skip ahead
break;
}
}
if (!usable) break;
for (k = j; k < j + num_pages; ++k) {
bitmap_set(info->page_bitmap, k);
}
return page_to_addr(info->first_page, j);
}
}
}
k_panics("No page found!");
return NULL;
}
void pmm_free_pages(void *page, uint32_t num_pages) {
for (int i = 0; i < last_paging_info; ++i) {
paging_info *info = &paging_infos[i];
if (!info->flags.present) continue;
// check if page is in memory area
if (page < info->first_page || page > (info->first_page + info->size)) continue;
// free page
uint32_t first_page = addr_to_page(info->first_page, page);
for (uint32_t current_page = first_page; current_page < first_page + num_pages; ++current_page) {
bitmap_unset(info->page_bitmap, current_page);
}
}
}

16
kernel/mem/pmm.h Normal file
View File

@@ -0,0 +1,16 @@
//
// Created by rick on 23-02-21.
//
#ifndef NEW_KERNEL_PMM_H
#define NEW_KERNEL_PMM_H
#include <types.h>
// 4k blocks
#define PAGE_SIZE 4096
void pmm_init(void* start_addr, size_t size);
void *pmm_get_pages(uint32_t num_pages);
void pmm_free_pages(void* page, uint32_t num_pages);
#endif //NEW_KERNEL_PMM_H