Octacone wrote:Here is my paging structure:
You are statically allocating your entire table structure at compile time, but since it is not initialized it will be in your .bss section. Are you certain your loader is zero-ing out this structure? I saw you are zeroing the Page Directory but I did not see the individual Page Table and likely could have missed it.
Also, your structures are not tagged as packed (in C this would be "__attribute__((packed))" and since I am not quite as good in C++, I leave it to you to find the correct decoration). This will not make a technical difference, but it does not hurt to get in this habit when you do not want the compiler to align your structure members when at a higher optimization.
Finally, and probably the most important point, your structure has about a 1 in 1000 chance of being page aligned by accident. I see nothing to ensure this alignment in your snapshot and it is required. To be particularly redundant, the last 3 nibbles of the address of the Page Directory must be 0x000.
Now, gong back to your original question and subject line.... You are not packing a 32-bit address into a 20-bit page selector -- I trust you understand that after a these few days. Breaking it down, you can look at the 32-bit address in the following manner: 10-10-12, where the first 10 bits is an index into the Page Directory table (be sure not to confuse this with a byte offset) which results in a Page Table and the second 10 bits is an index into the Page Table. The remaining 12 bits is a byte-offset into the resulting Page of Virtual Memory Offset which will map byte-to-byte to your Physical Memory Frame.
I tend to keep my frames as integer numbers (meaning 20 bits long) and my addresses full 32 bits. This will make life easier when you know that to convert any frame to and addressed you can use:
and frames are never addresses and addresses are never frames.
So, it is no accident that the last 12 bits of a Page starting address must be 0x000, just like the last 3 nibbles of a frame must be 0x000. Similarly, it is no accident that a Page Table and a Page Directory must be page-aligned. Ultimately you are using 20 of the 32 bits to select a page and the remaining 12 bits to select a byte-offset therein.
Octacone wrote:Code: Select all
uint32_t kernel_end_address = Memory_Core.Page_Align_Address(kernel_end);
page_directory_address = PMM.Allocate_Blocks(1024 * 1024);
page_directory = (page_directory_t*) page_directory_address;
String.Memory_Set(page_directory, 0, 4096 * 1024 * 1024);
uint32_t current_address = 0;
while(current_address < kernel_end_address)
{
//& 0x3FF = % 1024
page_directory->page_tables[(current_address >> 22)]->pages[(current_address >> 12) % 1024].present = 1;
page_directory->page_tables[(current_address >> 22)]->pages[(current_address >> 12) % 1024].write_enabled = 1;
page_directory->page_tables[(current_address >> 22)]->pages[(current_address >> 12) % 1024].user_page = 0;
page_directory->page_tables[(current_address >> 22)]->pages[(current_address >> 12) % 1024].frame_address = current_address;
current_address += 0x1000;
};
Write_CR3(page_directory_address);
Set_Paging_Bit();
No. I want to map an address, let's say addr = 0x1023af65 to make the example more interesting. First of all, we map pages and not addresses, so immediately I would mask the address to a page address:
Code: Select all
addr &= (~0x00000fff) // my address is now 0x1023a000
Notice that this drops the last 12 bits of the address... I call this out as this is part of the 10-10-12 pattern I mentioned above. Also notice that we are left with 5 nibbles, or 20 bits... or the 10-10 part.
* the first 10 is 0b00 0100 0000 (or 64)
* the second 10 is 0b10 0011 1010 (or 314)
Now, it's just a matter of a pedantic walk through the paging tables:
Code: Select all
// -- Find the page table
pdEntry = &pd[addr >> 22]; // -- this is the first 10
// -- I did mention that pd must be page-aligned, right?
// -- TODO: check if we have a frame allocated for the Page Table (present?) and if not add a new one
ptFrame = pdEntry->frame;
ptAddr = (PageTable *)(ptFrame << 12);
// -- Find the Page Table Entry
ptEntry = &ptAddr[(addr >> 12) & 0x3ff]; // this is the second 10
// -- TODO: Is the frame present? what should you do if it is?
// -- identity map the address; TODO: set all the other relevant fields in the entry
ptEntry->frame = addr >> 12;
Notice the conversions between frames and addresses. Don't allow yourself to be confused between the address-to-frame conversion and the address-to-page-table-index conversion.
Now, I know you mentioned that you are doing this without any tutorials. My algorithm above is taken straight from this picture:
http://forum.osdev.org/viewtopic.php?f= ... 36#p276069
If you are still having trouble, maybe you can restate your problem.