réplica de
https://github.com/Arnau478/quark.git
synced 2024-05-19 20:36:31 +02:00
143 líneas
4,7 KiB
C
143 líneas
4,7 KiB
C
#include "vmm.h"
|
|
#include "pmm.h"
|
|
#include "../../../lib/memory.h"
|
|
|
|
i686_vmm_page_directory_t *g_vmm_current_dir = 0;
|
|
i686_phys_addr g_vmm_current_pdbr = 0;
|
|
|
|
void __attribute__((cdecl)) i686_vmm_flush_tlb_entry(i686_virt_addr addr);
|
|
|
|
static inline i686_pt_entry_t *i686_vmm_ptable_lookup_entry(i686_vmm_page_table_t *p, i686_virt_addr addr){
|
|
if(p) return &p->entries[i686_PAGE_TABLE_INDEX(addr)];
|
|
return 0;
|
|
}
|
|
|
|
static inline i686_pd_entry_t *i686_vmm_pdirectory_lookup_entry(i686_vmm_page_directory_t *p, i686_virt_addr addr){
|
|
if(p) return &p->entries[i686_PAGE_DIRECTORY_INDEX(addr)];
|
|
return 0;
|
|
}
|
|
|
|
static inline bool i686_vmm_switch_pdirectory(i686_vmm_page_directory_t *dir){
|
|
if(!dir) return false;
|
|
|
|
g_vmm_current_dir = dir;
|
|
i686_pmm_load_pdbr(g_vmm_current_pdbr);
|
|
return true;
|
|
}
|
|
|
|
static inline i686_vmm_page_directory_t *i686_vmm_get_pdirectory(){
|
|
return g_vmm_current_dir;
|
|
}
|
|
|
|
bool i686_vmm_alloc_page(i686_pt_entry_t *entry){
|
|
void *p = i686_pmm_alloc_block();
|
|
if(!p) return false;
|
|
|
|
i686_pt_entry_set_frame(entry, (i686_phys_addr)p);
|
|
i686_pt_entry_add_attr(entry, i686_PTE_PRESENT);
|
|
|
|
return true;
|
|
}
|
|
|
|
void i686_vmm_free_page(i686_pt_entry_t *entry){
|
|
void *p = (void *)i686_pt_entry_get_frame(*entry);
|
|
if(p) i686_pmm_free_block(p);
|
|
|
|
i686_pt_entry_del_attr(entry, i686_PTE_PRESENT);
|
|
}
|
|
|
|
void i686_vmm_map_page(void *phys, void *virt){
|
|
// Get page directory
|
|
i686_vmm_page_directory_t *page_dir = i686_vmm_get_pdirectory();
|
|
|
|
// Get page table
|
|
i686_pd_entry_t *e = &page_dir->entries[i686_PAGE_DIRECTORY_INDEX((uint32_t)virt)];
|
|
if((*e & i686_PTE_PRESENT) != i686_PTE_PRESENT){
|
|
// Must allocate
|
|
i686_vmm_page_table_t *table = (i686_vmm_page_table_t *)i686_pmm_alloc_block();
|
|
if(!table) return;
|
|
|
|
// Clear page table
|
|
memset(table, 0, sizeof(i686_vmm_page_table_t));
|
|
|
|
// Create a new entry
|
|
i686_pd_entry_t *entry = &page_dir->entries[i686_PAGE_DIRECTORY_INDEX((uint32_t)virt)];
|
|
|
|
// Map in the table
|
|
i686_pd_entry_add_attr(entry, i686_PDE_PRESENT);
|
|
i686_pd_entry_add_attr(entry, i686_PDE_WRITABLE);
|
|
i686_pd_entry_set_frame(entry, (i686_phys_addr)table);
|
|
}
|
|
|
|
// Get table
|
|
i686_vmm_page_table_t *table = (i686_vmm_page_table_t *)i686_PAGE_GET_PHYS_ADDR(e);
|
|
|
|
// Get page
|
|
i686_pt_entry_t *page = &table->entries[i686_PAGE_TABLE_INDEX((uint32_t)virt)];
|
|
|
|
// Map it
|
|
i686_pt_entry_set_frame(page, (i686_phys_addr)phys);
|
|
i686_pt_entry_add_attr(page, i686_PTE_PRESENT);
|
|
}
|
|
|
|
void i686_vmm_initialize(){
|
|
// Allocate default page table
|
|
i686_vmm_page_table_t *table = (i686_vmm_page_table_t *)i686_pmm_alloc_block();
|
|
if(!table) return;
|
|
|
|
// Allocate 3GB page table
|
|
i686_vmm_page_table_t *table2 = (i686_vmm_page_table_t *)i686_pmm_alloc_block();
|
|
if(!table2) return;
|
|
|
|
// Clear default table
|
|
memset(table, 0, sizeof(i686_vmm_page_table_t));
|
|
|
|
// First 4MB are identity mapped
|
|
for(int i = 0, frame = 0x0, virt = 0x00000000; i<1024; i++, frame += 4096, virt += 4096){
|
|
// Create a new page
|
|
i686_pt_entry_t page = 0;
|
|
i686_pt_entry_add_attr(&page, i686_PTE_PRESENT);
|
|
i686_pt_entry_set_frame(&page, frame);
|
|
|
|
// Add the page to the page table
|
|
table2->entries[i686_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
|
|
i686_pt_entry_t page = 0;
|
|
i686_pt_entry_add_attr(&page, i686_PTE_PRESENT);
|
|
i686_pt_entry_set_frame(&page, frame);
|
|
|
|
// Add the page to the page table
|
|
table->entries[i686_PAGE_TABLE_INDEX(virt)] = page;
|
|
}
|
|
|
|
// Create default directory table
|
|
i686_vmm_page_directory_t *dir = (i686_vmm_page_directory_t *)i686_pmm_alloc_blocks(3);
|
|
if(!dir) return;
|
|
|
|
// Clear directory table and set it as current
|
|
memset(dir, 0, sizeof(i686_vmm_page_directory_t));
|
|
|
|
i686_pd_entry_t *entry = &dir->entries[i686_PAGE_DIRECTORY_INDEX(0xc0000000)];
|
|
i686_pd_entry_add_attr(entry, i686_PDE_PRESENT);
|
|
i686_pd_entry_add_attr(entry, i686_PDE_WRITABLE);
|
|
i686_pd_entry_set_frame(entry, (i686_phys_addr)table);
|
|
|
|
i686_pd_entry_t *entry2 = &dir->entries[i686_PAGE_DIRECTORY_INDEX(0x00000000)];
|
|
i686_pd_entry_add_attr(entry2, i686_PDE_PRESENT);
|
|
i686_pd_entry_add_attr(entry2, i686_PDE_WRITABLE);
|
|
i686_pd_entry_set_frame(entry2, (i686_phys_addr)table2);
|
|
|
|
// Store current PDBR
|
|
g_vmm_current_pdbr = (i686_phys_addr)&dir->entries;
|
|
|
|
// Switch to our page directory
|
|
i686_vmm_switch_pdirectory(dir);
|
|
|
|
// Enable paging
|
|
i686_pmm_paging_enable(true);
|
|
}
|