Hey all.
Ive been implementing my Paging system all night.
(Yay, such a beautiful DAAYYy...er NIGHT!).
Anywho.
Im getting the error in Bochs 'Page not Present'.
CR3 is pointing to the correct address for the Page Directory.
Also, Ive 'Mapped' Virtual Memory 0x00000000-0x00025000
to equal the same in Physical.
Ive also set the Directory Entry Present, Supervisor and ReadWrite, and the same with the Pages mapped.
Pllleeeease help.
I dont know what ive done wrong.
The source for the Kernel is here:
http://homepages.ihug.co.nz/~scroodle/citadel-src-280506.tar.gz
A little modification of the Makefile might be needed to work on all systems, as im using GCC Cross compiler (i586-elf), 3.4.3.
Its in a Source tree now, so.. hopefully itll be easier to find things.
The paging code is under the memory folder.
Thanks!
Page not Present.
Re:Page not Present.
Hello zeii,
I had a peek at /memory/citadel_kernel_memory_paging.c - here's a list of what I found:
hope that helps..
regards,
gaf
I had a peek at /memory/citadel_kernel_memory_paging.c - here's a list of what I found:
- line 22: -> kp_PageDirectory[clearCounter ] = 0;
- line 42: tableLocation = (kp_FreeAddress >> 12) << 12
This round down (0x1234 -> 0x1000) and not up, other memory structures might get overwritten:
tableLocation = (kp_FreeAddress + 0xfff) &0xFFFFF000;
Of course you have to do the same for the page-directory.. - line 66 + 97: The code is basically correct, although you shouldn't have to mask anything before shifting the bits:
thePageDirectory = Virtual >> 22;
thePageTable = Virtual >> 12;
To avoid confusion you should probably also change the variables' names (thePageDirectory -> ThePageTable, thePageTable -> ThePage). - line 102 + 103: Shouldn't you set the present flag for the page-table ? Apart from that aligning the address returned by kp_AddTable() is in my opinion not necessary.
- line 133: ThePageTable is the absolute number of the page - what you need is the index relative to the current table:
destination_table[thePagetable-thePageDirectroy*1024] = physical | flags;
hope that helps..
regards,
gaf
Re:Page not Present.
I've found a little problem in line 105 of citadel_kernel_memory_paging.c:
unsigned int* destinationTable = (unsigned int*)kp_PageDirectory[thePageDirectory];
should be
unsigned int* destinationTable = (unsigned int*)(kp_PageDirectory[thePageDirectory] & 0xFFFFF000);
because kp_PageDirectory[thePageDirectory] will contain destinationTable | SOME_FLAGS, and you need to ignore the flags. So destinationTable was a bit out, so the page tables were wrong.
When I changed that, it switched on paging quite happily. But it page faulted trying to print to the screen, because you don't seem to have mapped in 0xB8000. If you map in up to 0x100000 instead of up to 0x25000, that seems to work fine
(P.S. I like the style of your code, it seems really readable)
unsigned int* destinationTable = (unsigned int*)kp_PageDirectory[thePageDirectory];
should be
unsigned int* destinationTable = (unsigned int*)(kp_PageDirectory[thePageDirectory] & 0xFFFFF000);
because kp_PageDirectory[thePageDirectory] will contain destinationTable | SOME_FLAGS, and you need to ignore the flags. So destinationTable was a bit out, so the page tables were wrong.
When I changed that, it switched on paging quite happily. But it page faulted trying to print to the screen, because you don't seem to have mapped in 0xB8000. If you map in up to 0x100000 instead of up to 0x25000, that seems to work fine
(P.S. I like the style of your code, it seems really readable)
Re:Page not Present.
Thank you for helping me find my bugs! .
And thank you for the compliment .
Mapped-page-directory trick?
*listens*
About the inability to remap Mapped Pages, im going to put a command... so thats possible.
Or, Ill remove the 'protection' from the current Remap function.
Cheers!
And thank you for the compliment .
Mapped-page-directory trick?
*listens*
About the inability to remap Mapped Pages, im going to put a command... so thats possible.
Or, Ill remove the 'protection' from the current Remap function.
Cheers!
Re:Page not Present.
(Tim Robinsom, Memory Management I @ Bonafide)
"Map the page directory into itself. This might seem like a kind of weird fractal memory mapper, but it works well in practice. By setting one of the fixed PDEs to the physical address of the associated page directory, you can address PDEs and PTEs as separate addresses. If you set element 1023 of each page directory to the physical address of the page directory itself, the processor will see the page directory as the last page table. It will see the PDEs as PTEs, and it will see the PTEs as individual 32-bit words in the top 4MB of the address space. You can use the top 4KB of the address space as the entries in the original page directory. This has the advantage of being beautiful yet simple; it has the disadvantage that you can only access page mappings inside the current address space."
I know that this sounds quite confusing at first ???. Probably it would be a good idea if you tried to sketch the design on some paper to get some insight. I've also included some pseudo-code that might help to understand how it works:
The big advantage of the design is that you can always access the paging structures without having to worry about their actual location.
Your current code relies on page-directory and page-tables to be mapped idempotentially (physical address = virtual address) - this also means that can't really make much use of the advantages that paging has to offer:
uint* destinationTable = (uint*) the_PageDirectory[thePageDirectory] &0xFFFFF000;
The above line for example only works if the virtual-address of the page-table you're trying to access happends to be the same as its physical-address. With a more advanced memory manager, or a kernel that runs in highrt-memory (0-2 GB user-mode, 2-4 GB kernel), this assumption no longer holds. A page-table would always have to get mapped-in before it can be used. Mapping the paging structures statically to the upper-most 4 MB avoids some problems and probably also results in a somewhat cleaner design..
regards,
gaf
"Map the page directory into itself. This might seem like a kind of weird fractal memory mapper, but it works well in practice. By setting one of the fixed PDEs to the physical address of the associated page directory, you can address PDEs and PTEs as separate addresses. If you set element 1023 of each page directory to the physical address of the page directory itself, the processor will see the page directory as the last page table. It will see the PDEs as PTEs, and it will see the PTEs as individual 32-bit words in the top 4MB of the address space. You can use the top 4KB of the address space as the entries in the original page directory. This has the advantage of being beautiful yet simple; it has the disadvantage that you can only access page mappings inside the current address space."
I know that this sounds quite confusing at first ???. Probably it would be a good idea if you tried to sketch the design on some paper to get some insight. I've also included some pseudo-code that might help to understand how it works:
Code: Select all
// Allocate memory for the page-directory & page-table structures
uint* my_page_directory = Allocate(4096, ZERO_OUT_MEMORY);
uint* my_page_table = Allocate(4096, ZERO_OUT_MEMORY);
page_directory[1023] = (uint) page_directory; // self-map the directory
// Paging structures can now be accessed through the last 4 MB
uint* page_directory = (uint*) 0xFFFFF000; // last 4 kB
uint* page_tables = (uint*) 0xFFC00000; // last 4 MB
(virtual, physical -> parameters passed by the caller)
uint table_number = virtual >> 22;
uint page_number = virtual >> 12;
// Map our page using the self-map trick
page_directory[table_number] = (uint)my_page_directory | table_flags;
page_tables[page_number] = physical | page_flags;
Your current code relies on page-directory and page-tables to be mapped idempotentially (physical address = virtual address) - this also means that can't really make much use of the advantages that paging has to offer:
uint* destinationTable = (uint*) the_PageDirectory[thePageDirectory] &0xFFFFF000;
The above line for example only works if the virtual-address of the page-table you're trying to access happends to be the same as its physical-address. With a more advanced memory manager, or a kernel that runs in highrt-memory (0-2 GB user-mode, 2-4 GB kernel), this assumption no longer holds. A page-table would always have to get mapped-in before it can be used. Mapping the paging structures statically to the upper-most 4 MB avoids some problems and probably also results in a somewhat cleaner design..
regards,
gaf