luxos/SysCore/memory/mmngr_vi.c

140 lines
4.1 KiB
C

// +==============================================+
// | 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);
}