feat: initial paging setup

This commit is contained in:
2021-08-06 20:46:44 +02:00
parent 8152ad6e9a
commit f0cc2c73b7
15 changed files with 257 additions and 114 deletions

View File

@@ -6,7 +6,7 @@
#include <myke/tasks/task.h>
#include <myke/mem/malloc.h>
#include <myke/mem/pmm.h>
#include <myke/mem/pm.h>
// retrieved from https://github.com/blanham/liballoc
@@ -41,7 +41,7 @@ int liballoc_unlock() {
* \return A pointer to the allocated memory.
*/
void *liballoc_alloc(size_t size) {
return pmm_get_pages(size);
return pm_get_pages(size);
}
/** This frees previously allocated memory. The void* parameter passed
@@ -53,7 +53,7 @@ void *liballoc_alloc(size_t size) {
* \return 0 if the memory was successfully freed.
*/
int liballoc_free(void *addr, size_t size) {
pmm_free_pages(addr, size);
pm_free_pages(addr, size);
return 0;
}

View File

@@ -8,7 +8,7 @@
#include <myke/libk/libk.h>
#include <myke/mem/mem.h>
#include <myke/mem/pmm.h>
#include <myke/mem/pm.h>
#define MEMMAP_ENTRIES 16
@@ -84,7 +84,7 @@ void mmap_init_multiboot(struct multiboot_mmap_entry *entries, uint32_t count) {
continue; // skip for now
}
pmm_init((void *) entry->address, entry->length);
pm_init((void *) entry->address, entry->length);
entry->type = MMAP_TYPE_PAGING;
}
}

View File

@@ -1,59 +0,0 @@
//
// Created by rick on 21-02-21.
//
#include <attributes.h>
#include <stdbool.h>
#include <sys/types.h>
#include <myke/mem/paging.h>
#define TABLE_ADDR_MASK 0xFFFFF000
#define DIRECTORY_SIZE 1024
const uint32_t x = TABLE_ADDR_MASK;
typedef struct {
union {
struct {
bool present: 1;
bool read_write: 1;
bool user_mode: 1;
bool write_through: 1;
bool cache_disabled: 1;
bool accessed: 1;
char ignored: 1;
bool page_size: 1;
bool global: 1; // ignored
uint8_t avail: 3;
} att_packed;
uint32_t addr;
};
} att_packed page_directory_entry;
typedef struct {
union {
struct {
bool present: 1;
bool read_write: 1;
bool user_supervisor: 1;
bool write_through: 1;
bool cache_disabled: 1;
bool accessed: 1;
bool dirty: 1;
char ignored: 1;
bool global: 1;
uint8_t available: 3;
} att_packed;
uint32_t addr;
};
} att_packed page_table_entry;
page_directory_entry page_directory[DIRECTORY_SIZE] att_aligned(4096);
void page_pre_init() {
for (int i = 0; i < DIRECTORY_SIZE; ++i) {
page_directory[i].read_write = true;
page_directory[i].user_mode = false;
page_directory[i].present = false;
}
}

View File

@@ -6,7 +6,8 @@
#include <string.h>
#include <myke/libk/libk.h>
#include <myke/mem/pmm.h>
#include <myke/mem/pm.h>
#include <myke/mem/vmm.h>
#define NUM_PAGING_INFOS 16
@@ -39,7 +40,7 @@ typedef struct {
uint8_t last_paging_info = 0;
paging_info paging_infos[NUM_PAGING_INFOS];
void pmm_init(void *start_addr, size_t size) {
void pm_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;
@@ -48,6 +49,10 @@ void pmm_init(void *start_addr, size_t size) {
paging_infos[last_paging_info].size = size;
paging_infos[last_paging_info].flags.present = true;
// map into memory
vmm_assign_page(start_addr, start_addr, bitmap_pages);
// set state
memset(start_addr, BLOCK_FREE, bitmap_pages);
for (uint32_t i = 0; i < bitmap_pages; ++i) {
bitmap_set((uint8_t *) start_addr, i);
@@ -55,7 +60,7 @@ void pmm_init(void *start_addr, size_t size) {
last_paging_info++;
}
void *pmm_get_pages(uint32_t num_pages) {
void *pm_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;
@@ -75,7 +80,9 @@ void *pmm_get_pages(uint32_t num_pages) {
for (k = j; k < j + num_pages; ++k) {
bitmap_set(info->page_bitmap, k);
}
return page_to_addr(info->first_page, j);
void *paddr = page_to_addr(info->first_page, j);
vmm_assign_page(paddr, paddr, num_pages);
return paddr;
}
}
}
@@ -83,7 +90,7 @@ void *pmm_get_pages(uint32_t num_pages) {
return NULL;
}
void pmm_free_pages(void *page, uint32_t num_pages) {
void pm_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;
@@ -95,5 +102,6 @@ void pmm_free_pages(void *page, uint32_t num_pages) {
for (uint32_t current_page = first_page; current_page < first_page + num_pages; ++current_page) {
bitmap_unset(info->page_bitmap, current_page);
}
vmm_unassign_page(page, num_pages);
}
}

6
kernel/mem/vmm.S Normal file
View File

@@ -0,0 +1,6 @@
.code32
.section .text
.global vmm_get_current_page_directory
vmm_get_current_page_directory:
movl %cr3, %eax
ret

116
kernel/mem/vmm.c Normal file
View File

@@ -0,0 +1,116 @@
//
// Created by rick on 21-02-21.
//
#include <attributes.h>
#include <stdbool.h>
#include <sys/types.h>
#include <myke/mem/vmm.h>
#include <myke/mem/pm.h>
#include <myke/libk/libk.h>
#define TABLE_ADDR_MASK 0xFFFFF000
#define TABLE_ADDR_IMASK ~TABLE_ADDR_MASK
#define DIRECTORY_SIZE 1024
const uint32_t x = TABLE_ADDR_MASK;
typedef struct {
union {
struct {
bool present: 1;
bool read_write: 1;
bool user_mode: 1;
bool write_through: 1;
bool cache_disabled: 1;
bool accessed: 1;
char: 1;
bool page_size: 1;
bool global: 1; // ignored
uint8_t avail: 3;
} att_packed;
uint32_t addr;
};
} att_packed page_directory_entry;
typedef struct {
union {
struct {
bool present: 1;
bool read_write: 1;
bool user_supervisor: 1;
bool write_through: 1;
bool cache_disabled: 1;
bool accessed: 1;
bool dirty: 1;
char: 1;
bool global: 1;
uint8_t available: 3;
} att_packed;
uint32_t addr;
};
} att_packed page_table_entry;
//#define in_dir(dir, vaddr) ((page_table_entry*)(((page_directory_entry*)((dir)[(vaddr)/4096/1024].addr & TABLE_ADDR_MASK))[(vaddr)/4096%1024]))
#define dir_index(vaddr) (((uint32_t)(vaddr)) / PAGE_SIZE / DIRECTORY_SIZE)
#define page_index(vaddr) (((uint32_t)(vaddr)) / PAGE_SIZE % DIRECTORY_SIZE)
page_directory_entry boot_paging_directory[DIRECTORY_SIZE] att_aligned(4096);
page_table_entry boot_primary_table[DIRECTORY_SIZE] att_aligned(4096);
extern page_directory_entry *vmm_get_current_page_directory();
void vmm_assign_page_one(uint32_t paddr, uint32_t vaddr) {
page_directory_entry *curr = vmm_get_current_page_directory();
page_directory_entry *dentry = &curr[dir_index(vaddr)];
if (!dentry->present || (dentry->addr & TABLE_ADDR_MASK) == 0) {
// todo allocate table
k_panics("need to allocate new table");
}
page_table_entry *first_entry = (page_table_entry *) (dentry->addr & TABLE_ADDR_MASK);
page_table_entry *pentry = &first_entry[page_index(vaddr)];
if (pentry->present) {
// todo already present
k_panics("virtual address already in use");
}
pentry->addr = (pentry->addr & TABLE_ADDR_IMASK) | paddr;
pentry->present = true;
pentry->read_write = true;
}
void vmm_unassign_page_one(uint32_t vaddr) {
page_directory_entry *curr = vmm_get_current_page_directory();
page_directory_entry *dentry = &curr[dir_index(vaddr)];
if (!dentry->present || (dentry->addr & TABLE_ADDR_MASK) == 0) {
// todo allocate table
k_panics("need to allocate new table");
}
page_table_entry *first_entry = (page_table_entry *) (dentry->addr & TABLE_ADDR_MASK);
page_table_entry *pentry = &first_entry[page_index(vaddr)];
if (!pentry->present) {
// todo already present
k_panics("virtual address not in use");
}
pentry->present = false;
pentry->read_write = false;
pentry->addr = pentry->addr & TABLE_ADDR_IMASK;
}
void vmm_assign_page(void *paddr, void *vaddr, size_t number_of_pages) {
for (size_t i = 0; i < number_of_pages; ++i) {
vmm_assign_page_one(((uint32_t) paddr) + PAGE_SIZE * i, ((uint32_t) vaddr) + PAGE_SIZE * i);
}
}
void vmm_unassign_page(void *vaddr, size_t number_of_pages) {
for (size_t i = 0; i < number_of_pages; ++i) {
vmm_unassign_page_one(((uint32_t) vaddr) + PAGE_SIZE * i);
}
}