Page Directory being set to all zeros after enabling paging?
Posted: Thu Jun 16, 2011 5:29 pm
Okay, I am now trying to get my page directory cloning functions to work. Well, i came across an error that i can only assume was there all along, but never showed itself. For some reason, after executing this bit:
all my PDE's are NULL!
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:
and pmm_enable_paging:
So after executing this function with the base kernel directory (the very first directory that just has the heap, and kernel memory mapped), my directory is cleared. All the PDE's are NULL. I have print atleast the first 15-20 just because I was frustrated, and they are all NULL! This causes a problem when I go to copy that directory!
Now I have temporarily fixed the problem like so:
which seems to work (no errors, I can copy the directory fine. and the new cloned directory is fine after calling vmm_switch_dir). Also, after that first call, that function never changes my kernel directories values again. So it depends on the parameter, but at the same time only effects certain parameters. It doesn't make sense! While this solution works, this is neither efficient nor correct.
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!
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!