Code: Select all
static unsigned int *_page_directory = 0;
static unsigned int *_page_directory_phys = 0;
int vmmngr_initialize () {
// allocate a new block for the new page directory
unsigned int *_new_page_dir = (unsigned int *) pmmngr_alloc_block ();
// get the ptr to the virtual and physical address of the original page directory (set up in kboot.asm)
_page_directory = (unsigned int *) 0xfffff000;
_page_directory_phys = (unsigned int *) (_page_directory[1023] &~ 0xfff);
// temporarily map the new page directory so we can modify it
if (vmmngr_map_page ((physical_addr) _new_page_dir, (virtual_addr) 0xD0000000) == -1)
return -1;
// copy the contents of the original directory to the new directory
memcpy ((void *) 0xD0000000, _page_directory, 1024*sizeof(unsigned int));
// map the last entry of the new directory to itself
_new_page_dir[1023] = (unsigned int) _new_page_dir | 3;
// place the new page directory into the pdbr
vmmngr_set_pdbr (_new_page_dir);
_page_directory_phys = _new_page_dir;
// now point the page directory * to the virtual addr of the pdir
_page_directory = (unsigned int *) 0xfffff000;
// unmap the temporary page and quit
vmmngr_unmap_page ((virtual_addr) 0xD0000000);
return 0;
}
Code: Select all
int vmmngr_map_page (physical_addr phys, virtual_addr virt) {
pageinf page_data = vmmngr_virt_to_page_index (virt);
// if the page is already allocated, just map it
if (_page_directory[page_data.ptable] & 1) {
unsigned int *p_table = (unsigned int *) (0xffc00000 + (page_data.ptable * 0x1000));
// if the page isn't mapped, map it
if (!(p_table[page_data.page] & 1))
p_table [page_data.page] = phys | 3;
else
return -1;
}
// otherwise, allocate a new page table then map
else {
unsigned int *p_table = (unsigned int *) pmmngr_alloc_block ();
unsigned int *new_entry = (unsigned int *) (0xffc00000 + (page_data.ptable * 0x1000));
_page_directory[page_data.ptable] = (unsigned int) p_table | 3;
new_entry[page_data.page] = phys | 3;
}
return 0;
}
physical_addr vmmngr_unmap_page (virtual_addr virt) {
pageinf page_data = vmmngr_virt_to_page_index (virt);
physical_addr phys = (physical_addr) 0;
// if the directory entry is mapped
if (_page_directory[page_data.ptable] & 1) {
unsigned int *p_table = (unsigned int *) (0xffc00000 + (page_data.ptable * 0x1000));
// the page is mapped, unmap it
if (ptable[page_data.page] & 1) {
phys = (physical_addr) (p_table[page_data.page] &~ 0xfff); // mask the lower bits
p_table[page_data.page] = 0x00;
}
int i;
// check for more ptes
for (i = 0; i < 1024; i++)
if (p_table[i] & 1)
break;
// if there were no ptes in the table, deallocate the table
if (i >= 1024) {
pmmngr_free_block ((void *) (_page_directory[page_data.ptable] & 0xfffff000));
_page_directory[page_data.ptable] = 0x00;
}
}
return phys;
}
Code: Select all
vmmngr_initialize () // it succeeds and everything works
char *block = (char *) pmmngr_alloc_block ();
if (block) {
vmmngr_map_page ((physical_addr) block, (virtual_addr) 0xD0000000);
char *block2 = (char *) 0xD0000000;
*block2 = 'H'; // PF here!!
}
Code: Select all
vmmngr_set_pdbr (_page_directory_phys);