117 lines
3.5 KiB
C
117 lines
3.5 KiB
C
//
|
|
// 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);
|
|
}
|
|
}
|