193 lines
6.0 KiB
C
193 lines
6.0 KiB
C
// +==============================================+
|
|
// | HEADERS |
|
|
// +===================================== cta os =+
|
|
#include "mmngr_vi.h"
|
|
#include "mmngr_ph.h"
|
|
|
|
// +==============================================+
|
|
// | DEFINITIONS & MACROS |
|
|
// +===================================== cta os =+
|
|
#define PAGE_SIZE 4096
|
|
#define PTABLE_ADDR_SPACE_SIZE 0x400000
|
|
#define DTABLE_ADDR_SPACE_SIZE 0xffffffff
|
|
#define PAGE_DIRECTORY_INDEX(x) (((x) >> 22) & 0x3ff)
|
|
#define PAGE_TABLE_INDEX(x) (((x) >> 12) & 0x3ff)
|
|
#define PAGE_GET_PHYSICAL_ADDRESS(x) (*x & ~0xfff)
|
|
|
|
pdirectory* _current_directory;
|
|
unsigned _current_page_directory_base_register;
|
|
extern unsigned char *memset (unsigned char *dest, unsigned char val, int count);
|
|
|
|
// +==============================================+
|
|
// | 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;
|
|
}
|
|
|
|
|
|
unsigned char vmmngr_map_page (unsigned phys, unsigned virt)
|
|
{
|
|
pdirectory* dir = _current_directory; // get page directory
|
|
pd_entry* e = &dir->m_entries [PAGE_DIRECTORY_INDEX (virt)]; // get page table
|
|
|
|
if ((*e & _I86_PTE_PRESENT) != _I86_PTE_PRESENT) {
|
|
|
|
// Page table not present, allocate it
|
|
ptable* table = (ptable *)pmmngr_alloc_block();
|
|
if (!table) return 0;
|
|
|
|
// Clear it
|
|
vmmngr_ptable_clear(table);
|
|
|
|
// Create new entry
|
|
pd_entry* entry = &dir->m_entries [PAGE_DIRECTORY_INDEX (virt)];
|
|
|
|
// Map in the table
|
|
pd_entry_add_attrib (entry, _I86_PDE_PRESENT);
|
|
pd_entry_add_attrib (entry, _I86_PDE_WRITABLE);
|
|
pd_entry_set_frame (entry, (unsigned) table);
|
|
}
|
|
|
|
// get table
|
|
ptable* table = (ptable*) PAGE_GET_PHYSICAL_ADDRESS(e);
|
|
|
|
// get page
|
|
pt_entry* page = &table->m_entries [PAGE_TABLE_INDEX (virt)];
|
|
|
|
pt_entry_set_frame (page, phys);
|
|
pt_entry_add_attrib (page, _I86_PTE_PRESENT);
|
|
|
|
return 1;
|
|
}
|
|
|
|
unsigned char vmmngr_initialize()
|
|
{
|
|
unsigned int i, virt, frame;
|
|
|
|
// Allocate default page & directory table(s)
|
|
ptable* table = (ptable*) pmmngr_alloc_block();
|
|
ptable* table2 = (ptable*) pmmngr_alloc_block();
|
|
pdirectory* dir = (pdirectory*) pmmngr_alloc_blocks(3);
|
|
|
|
if (!table || !table2 || !dir) return 0;
|
|
|
|
// Clear page & directory tables
|
|
vmmngr_ptable_clear(table);
|
|
vmmngr_ptable_clear(table2);
|
|
vmmngr_pdirectory_clear(dir);
|
|
|
|
// Identity map the first page table
|
|
virt = 0; frame = 0;
|
|
for (i = 0; i < 1024; i++, virt+=4096, frame += 4096)
|
|
{
|
|
pt_entry* page = &table2->m_entries[PAGE_TABLE_INDEX(virt)];
|
|
*page = 0;
|
|
pt_entry_add_attrib (page, _I86_PTE_PRESENT);
|
|
pt_entry_set_frame (page, frame);
|
|
}
|
|
|
|
// Map 0x100000 to 0xC0000000
|
|
virt = 0xC0000000; frame = 0x100000;
|
|
for (i = 0; i < 1024; i++, virt+=4096, frame += 4096)
|
|
{
|
|
pt_entry* page = &table->m_entries[PAGE_TABLE_INDEX(virt)];
|
|
*page = 0;
|
|
pt_entry_add_attrib (page, _I86_PTE_PRESENT);
|
|
pt_entry_set_frame (page, frame);
|
|
}
|
|
|
|
// Get tables in dir table and point them to our tables
|
|
pd_entry* entry = &dir->m_entries [PAGE_DIRECTORY_INDEX (0xC0000000)];
|
|
pd_entry_add_attrib (entry, _I86_PDE_PRESENT);
|
|
pd_entry_add_attrib (entry, _I86_PDE_WRITABLE);
|
|
pd_entry_set_frame (entry, (unsigned) table);
|
|
|
|
entry = &dir->m_entries [PAGE_DIRECTORY_INDEX (0x00000000)];
|
|
pd_entry_add_attrib (entry, _I86_PDE_PRESENT);
|
|
pd_entry_add_attrib (entry, _I86_PDE_WRITABLE);
|
|
pd_entry_set_frame (entry, (unsigned) table2);
|
|
|
|
// 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);
|
|
|
|
return 1;
|
|
} |