Really having trouble understanding paging
Posted: Tue Feb 24, 2015 7:46 pm
I've been trying to implement paging for a while, and I'm having a really difficult time of it. I understand the general, overall, theory but there's something I'm missing that's keeping it from "clicking." I'm hoping you guys can help fill in the pieces of my understanding. What I'm basically needing is a step-by-step guide that's light on theory, but not actually code. I understand that most people seem to like doing things as a higher half kernel for various reasons, but I'm doing mine in the lower half. This is mainly because I want to understand paging before I start trying to remap things to funny locations. In the first 1M of memory I have the stuff that was put there by the boot loader, and Grub, which I'm not touching. I've just decided to leave that alone, and I'm putting my kernel right after that. My kernel ends wherever it happens to end, and I'm using values provided by the linker to determine where my kernel starts and ends.
You can see my code here. I've been conversing with people on other forums, and am aware that I've probably screwed up the physical memory manager. It's providing me with page aligned physical memory addresses that are available after the kernel. My allocate_block() function just gives me a page aligned address in physical memory after the kernel off a stack. Before I attempt to enable paging my memory looks like
0 - 1M: Bootloader and Grub stuff
1M - end as defined by the linker: My kernel
end - ?: A stack holding every 4096th address of the available memory. The ? is determined by the memory map provided by Grub when the system boots. Basically, it's the amount of upper memory in MB divided by 4. You can see exactly what I'm talking about here. I'm using Qemu to test things, and giving it 128 MB of memory, so my stack's holding 32768 addresses.
I'm wanting to make sure I have a good road map to follow before I attempt to redo my paging implementation for the umpteenth time. This is what I'm needing to do, as I understand it:
1. Get a physical memory address where my page directory will reside (this is the first page aligned address of physical memory after the ? from above)
2. Set all of the memory for that 4KB section to 0 to make sure there's no garbage in there.
3. Get a physical memory address where my first page table will reside. (the second page aligned address of physical memory after the ?)
4. Set all of the memory for that 4KB section to 0.
5. Start treating the 4KB sections of memory as arrays.
6. For each item on the page directory array set the attributes to 0 | 2.
7. For the 0th item on the page directory set the attributes to the address of the page table | 3.
8. Identity map all of the physical memory from 0 on up to whatever's available into the page table (which will give me 4GB of virtual memory addresses, buy only 128MB of them will actually be "real"). (How will I know which pages are present?)
9. Set the interrupt handler for my page fault handler.
10. Put the physical address of the page directory on the cr3 register.
11. Enable paging by doing | 0x80000000 on cr0.
From there I'll need to write the page fault handler, and functions to allocate, free, and map new pages as needed. How's all of that sound to you guys?
You can see my code here. I've been conversing with people on other forums, and am aware that I've probably screwed up the physical memory manager. It's providing me with page aligned physical memory addresses that are available after the kernel. My allocate_block() function just gives me a page aligned address in physical memory after the kernel off a stack. Before I attempt to enable paging my memory looks like
0 - 1M: Bootloader and Grub stuff
1M - end as defined by the linker: My kernel
end - ?: A stack holding every 4096th address of the available memory. The ? is determined by the memory map provided by Grub when the system boots. Basically, it's the amount of upper memory in MB divided by 4. You can see exactly what I'm talking about here. I'm using Qemu to test things, and giving it 128 MB of memory, so my stack's holding 32768 addresses.
I'm wanting to make sure I have a good road map to follow before I attempt to redo my paging implementation for the umpteenth time. This is what I'm needing to do, as I understand it:
1. Get a physical memory address where my page directory will reside (this is the first page aligned address of physical memory after the ? from above)
2. Set all of the memory for that 4KB section to 0 to make sure there's no garbage in there.
3. Get a physical memory address where my first page table will reside. (the second page aligned address of physical memory after the ?)
4. Set all of the memory for that 4KB section to 0.
5. Start treating the 4KB sections of memory as arrays.
6. For each item on the page directory array set the attributes to 0 | 2.
7. For the 0th item on the page directory set the attributes to the address of the page table | 3.
8. Identity map all of the physical memory from 0 on up to whatever's available into the page table (which will give me 4GB of virtual memory addresses, buy only 128MB of them will actually be "real"). (How will I know which pages are present?)
9. Set the interrupt handler for my page fault handler.
10. Put the physical address of the page directory on the cr3 register.
11. Enable paging by doing | 0x80000000 on cr0.
From there I'll need to write the page fault handler, and functions to allocate, free, and map new pages as needed. How's all of that sound to you guys?