// +==============================================+ // | HEADERS | // +===================================== cta os =+ #include "mmngr_vi.h" #include "mmngr_ph.h" // +==============================================+ // | DEFINITIONS | // +===================================== cta os =+ #define PAGE_SIZE 4096 #define PTABLE_ADDR_SPACE_SIZE 0x400000 #define DTABLE_ADDR_SPACE_SIZE 0xffffffff pdirectory* _current_directory; unsigned _current_page_directory_base_register; extern unsigned char *memset (unsigned char *dest, unsigned char val, int count); extern char getch(); // +==============================================+ // | PAGE FUNCTIONS | // +===================================== cta os =+ unsigned char vmmngr_alloc_page (pt_entry* entry) { void* p = pmmngr_alloc_block (); if (!p) return 0; pt_entry_set_frame(entry, (unsigned)p); pt_entry_add_attrib (entry, _I86_PTE_PRESENT); return 1; } void vmmngr_free_page (pt_entry* entry) { void* p = (void*) pt_entry_get_frame(*entry); if (p) pmmngr_free_block (p); pt_entry_del_attrib (entry, _I86_PTE_PRESENT); } // +==============================================+ // | PAGE TABLE FUNCTIONS | // +===================================== cta os =+ inline void vmmngr_ptable_clear(ptable* p) { if(p) memset ((unsigned char*)p, 0, sizeof(ptable)); } inline unsigned vmmngr_ptable_virt_to_index (unsigned addr) { return (addr >= PTABLE_ADDR_SPACE_SIZE) ? 0 : addr/PAGE_SIZE; } inline pt_entry* vmmngr_ptable_lookup_entry (ptable* p, unsigned addr) { if (p) return &p->m_entries[vmmngr_ptable_virt_to_index(addr)]; return 0; } // +==============================================+ // | PAGE DIRECTORY FUNCTIONS | // +===================================== cta os =+ inline void vmmngr_pdirectory_clear(pdirectory* dir) { if(dir) memset ((unsigned char*)dir, 0, sizeof(pdirectory)); } inline unsigned vmmngr_pdirectory_virt_to_index (unsigned addr) { return (addr > DTABLE_ADDR_SPACE_SIZE) ? 0 : addr/PAGE_SIZE; } inline pd_entry* vmmngr_pdirectory_lookup_entry (pdirectory* dir, unsigned addr) { if (dir) return &dir->m_entries[vmmngr_ptable_virt_to_index(addr)]; return 0; } // +==============================================+ // | VIRTUAL MEMORY MANAGER | // +===================================== cta os =+ inline unsigned char vmmngr_switch_pdirectory (pdirectory* dir) { if (!dir) return 0; _current_directory = dir; write_cr3 (_current_page_directory_base_register); return 1; } pdirectory* vmmngr_get_directory() { return _current_directory; } void vmmngr_initialize() { // Allocate default page table ptable* table = (ptable*) pmmngr_alloc_block(); if (!table) return; // Clear page table vmmngr_ptable_clear(table); // Identity map the first page table int i, frame; for (i = 0, frame = 0; i < 1024; i++, frame += 4096) { // Create a new page pt_entry page = 0; pt_entry_add_attrib (&page, _I86_PTE_PRESENT); pt_entry_set_frame (&page, frame); table->m_entries[vmmngr_ptable_virt_to_index(frame)] = page; } // Create default directory table pdirectory* dir = (pdirectory*) pmmngr_alloc_blocks(3); if (!dir) return; // Clear directory table and set it as current vmmngr_pdirectory_clear(dir); // Get first entry in dir table and set it up to point to our table pd_entry* entry = vmmngr_pdirectory_lookup_entry(dir, 0); pd_entry_add_attrib (entry, _I86_PDE_PRESENT); pd_entry_add_attrib (entry, _I86_PDE_WRITABLE); pd_entry_set_frame (entry, (unsigned) table); // Store current PDBR _current_page_directory_base_register = (unsigned) &dir->m_entries; // Switch to our page directory vmmngr_switch_pdirectory (dir); // Enable paging pmmngr_paging_enable (1); }