Code: Select all
/*! Switch to a page directory (essentially, set CR3 to dir) */
void vmm_switch_dir(pdir* dir)
{
pmm_set_pdbr(vmm_get_phys((virt_addr)dir, _curdir));
_curdir = dir;
pmm_enable_paging(); // Modifying the CR0 forces a TLB flush
}
I know, it might look a little wierd to call "vmm_get_phys" (which translates a virtual address into a physical one, with a given directory) in the function that also enables paging, but it makes sense. Every page directory is, at the beginning, a clone of the kernel directory, which has the kernel memory and heap mapped in it. Also, the page directories are allocated on the kernel heap (or in the case of the original one, it's in the base kernel memory). So no matter what directory we use, we can assume that the physical address of any new directory is mapped inside it.
Here is the definition of pmm_set_pdbr:
Code: Select all
pmm_set_pdbr:
mov ebx,dword[esp+4]
and ebx,0xFFFFF000 ; We only want the first 20 bits according to the intel manuals
mov ecx,cr3
or ecx,ebx
mov cr3,ecx
ret
Code: Select all
pmm_enable_paging:
mov ebx,cr0
or ebx,80000000h ; Add the paging bit to cr0
mov cr0,ebx ; Restore cr0
ret
Now I have temporarily fixed the problem like so:
Code: Select all
kdir = (pdir*)pmm_alloc_block(); // Each directory is an array of 1024 4byte integers (1024*4 = 4096 = page size = block size, 1 block...)
pdir* tmpdir = (pdir*)pmm_alloc_block();
...
memcpy(tmpdir, kdir, 4096);
vmm_switch_dir(kdir);
memcpy(kdir, tmpdir, 4096);
It's one thing when it happens every time I use that function, but it's a totally different thing when it only happens after I execute it with a specific parameter.
If you need any more information, let me know. I'm not very secretive when it comes to code xD If anyone can help (which from what I've seen, if anyone can, you guys can ) I would greatly appreciate it!