réplica de
https://github.com/Arnau478/quark.git
synced 2024-05-20 04:46:30 +02:00
143 líneas
4,2 KiB
C
143 líneas
4,2 KiB
C
#include "vmm.h"
|
|
#include "pmm.h"
|
|
#include "../lib/memory.h"
|
|
|
|
vmm_page_directory_t *g_vmm_current_dir = 0;
|
|
phys_addr g_vmm_current_pdbr = 0;
|
|
|
|
void __attribute__((cdecl)) vmm_flush_tlb_entry(virt_addr addr);
|
|
|
|
static inline pt_entry_t *vmm_ptable_lookup_entry(vmm_page_table_t *p, virt_addr addr){
|
|
if(p) return &p->entries[PAGE_TABLE_INDEX(addr)];
|
|
return 0;
|
|
}
|
|
|
|
static inline pd_entry_t *vmm_pdirectory_lookup_entry(vmm_page_directory_t *p, virt_addr addr){
|
|
if(p) return &p->entries[PAGE_DIRECTORY_INDEX(addr)];
|
|
return 0;
|
|
}
|
|
|
|
static inline bool vmm_switch_pdirectory(vmm_page_directory_t *dir){
|
|
if(!dir) return false;
|
|
|
|
g_vmm_current_dir = dir;
|
|
pmm_load_pdbr(g_vmm_current_pdbr);
|
|
return true;
|
|
}
|
|
|
|
static inline vmm_page_directory_t *vmm_get_pdirectory(){
|
|
return g_vmm_current_dir;
|
|
}
|
|
|
|
bool vmm_alloc_page(pt_entry_t *entry){
|
|
void *p = pmm_alloc_block();
|
|
if(!p) return false;
|
|
|
|
pt_entry_set_frame(entry, (phys_addr)p);
|
|
pt_entry_add_attr(entry, PTE_PRESENT);
|
|
|
|
return true;
|
|
}
|
|
|
|
void vmm_free_page(pt_entry_t *entry){
|
|
void *p = (void *)pt_entry_get_frame(*entry);
|
|
if(p) pmm_free_block(p);
|
|
|
|
pt_entry_del_attr(entry, PTE_PRESENT);
|
|
}
|
|
|
|
void vmm_map_page(void *phys, void *virt){
|
|
// Get page directory
|
|
vmm_page_directory_t *page_dir = vmm_get_pdirectory();
|
|
|
|
// Get page table
|
|
pd_entry_t *e = &page_dir->entries[PAGE_DIRECTORY_INDEX((uint32_t)virt)];
|
|
if((*e & PTE_PRESENT) != PTE_PRESENT){
|
|
// Must allocate
|
|
vmm_page_table_t *table = (vmm_page_table_t *)pmm_alloc_block();
|
|
if(!table) return;
|
|
|
|
// Clear page table
|
|
memset(table, 0, sizeof(vmm_page_table_t));
|
|
|
|
// Create a new entry
|
|
pd_entry_t *entry = &page_dir->entries[PAGE_DIRECTORY_INDEX((uint32_t)virt)];
|
|
|
|
// Map in the table
|
|
pd_entry_add_attr(entry, PDE_PRESENT);
|
|
pd_entry_add_attr(entry, PDE_WRITABLE);
|
|
pd_entry_set_frame(entry, (phys_addr)table);
|
|
}
|
|
|
|
// Get table
|
|
vmm_page_table_t *table = (vmm_page_table_t *)PAGE_GET_PHYS_ADDR(e);
|
|
|
|
// Get page
|
|
pt_entry_t *page = &table->entries[PAGE_TABLE_INDEX((uint32_t)virt)];
|
|
|
|
// Map it
|
|
pt_entry_set_frame(page, (phys_addr)phys);
|
|
pt_entry_add_attr(page, PTE_PRESENT);
|
|
}
|
|
|
|
void vmm_initialize(){
|
|
// Allocate default page table
|
|
vmm_page_table_t *table = (vmm_page_table_t *)pmm_alloc_block();
|
|
if(!table) return;
|
|
|
|
// Allocate 3GB page table
|
|
vmm_page_table_t *table2 = (vmm_page_table_t *)pmm_alloc_block();
|
|
if(!table2) return;
|
|
|
|
// Clear default table
|
|
memset(table, 0, sizeof(vmm_page_table_t));
|
|
|
|
// First 1MB are identity mapped
|
|
for(int i = 0, frame = 0x0, virt = 0x00000000; i<1024; i++, frame += 4096, virt += 4096){
|
|
// Create a new page
|
|
pt_entry_t page = 0;
|
|
pt_entry_add_attr(&page, PTE_PRESENT);
|
|
pt_entry_set_frame(&page, frame);
|
|
|
|
// Add the page to the page table
|
|
table2->entries[PAGE_TABLE_INDEX(virt)] = page;
|
|
}
|
|
|
|
// Map 1MB to 3GB
|
|
for(int i = 0, frame = 0x100000, virt = 0xc0000000; i<1024; i++, frame += 4096, virt += 4096){
|
|
// Create a new page
|
|
pt_entry_t page = 0;
|
|
pt_entry_add_attr(&page, PTE_PRESENT);
|
|
pt_entry_set_frame(&page, frame);
|
|
|
|
// Add the page to the page table
|
|
table->entries[PAGE_TABLE_INDEX(virt)] = page;
|
|
}
|
|
|
|
// Create default directory table
|
|
vmm_page_directory_t *dir = (vmm_page_directory_t *)pmm_alloc_blocks(3);
|
|
if(!dir) return;
|
|
|
|
// Clear directory table and set it as current
|
|
memset(dir, 0, sizeof(vmm_page_directory_t));
|
|
|
|
pd_entry_t *entry = &dir->entries[PAGE_DIRECTORY_INDEX(0xc0000000)];
|
|
pd_entry_add_attr(entry, PDE_PRESENT);
|
|
pd_entry_add_attr(entry, PDE_WRITABLE);
|
|
pd_entry_set_frame(entry, (phys_addr)table);
|
|
|
|
pd_entry_t *entry2 = &dir->entries[PAGE_DIRECTORY_INDEX(0x00000000)];
|
|
pd_entry_add_attr(entry2, PDE_PRESENT);
|
|
pd_entry_add_attr(entry2, PDE_WRITABLE);
|
|
pd_entry_set_frame(entry2, (phys_addr)table2);
|
|
|
|
// Store current PDBR
|
|
g_vmm_current_pdbr = (phys_addr)&dir->entries;
|
|
|
|
// Switch to our page directory
|
|
vmm_switch_pdirectory(dir);
|
|
|
|
// Enable paging
|
|
pmm_paging_enable(true);
|
|
}
|