Clarifying some points regarding paging
Clarifying some points regarding paging
I think I understand most of it, but I'm just having trouble with one thing - if I'm only running the kernel (I.E. no other processes) and the memory is mapped 1:1 physical:virtual, there should be no difference between having paging enabled and not enabled, right?
I know there's a ton of paging questions here, sorry for adding one more!
I know there's a ton of paging questions here, sorry for adding one more!
Re: Clarifying some points regarding paging
If paging is enabled then there wil be permission checks, even for a one-to-one mapping.
If a trainstation is where trains stop, what is a workstation ?
Re: Clarifying some points regarding paging
Oh, right. But since everything running is in kernel-space, I still won't see a difference between paging and no-paging, right? Even though permission checking is happening behind the scenes?
Re: Clarifying some points regarding paging
Depending on the processor, if you write to a read-only page, or access an address that isn't mapped, or execute on a non-executable page then there is a difference.
If paging is enabled there is the possibility of a page fault.
If paging is enabled there is the possibility of a page fault.
If a trainstation is where trains stop, what is a workstation ?
Re: Clarifying some points regarding paging
Alright, that answers my question thank you
Last edited by Luns on Mon May 23, 2011 7:44 am, edited 2 times in total.
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Clarifying some points regarding paging
Unwritable pages cause a pagefault when written in ring3, and they do in ring0 as well depending on what the WP bit was set to. (Something tells me there was a caveat with the writeprotect bit but I can't recall what it was)
Re: Clarifying some points regarding paging
Right, that makes sense.
I thought I had everything setup alright, but now I'm not so sure. How can I test that paging is set up correctly? I've checked the CR3 register via Qemu's command line and it does have the correct physical address for my page directory. But when I try writing to some memory that should be read-only, it just gets written like normal. That means I set something up incorrectly, right?
I thought I had everything setup alright, but now I'm not so sure. How can I test that paging is set up correctly? I've checked the CR3 register via Qemu's command line and it does have the correct physical address for my page directory. But when I try writing to some memory that should be read-only, it just gets written like normal. That means I set something up incorrectly, right?
Re: Clarifying some points regarding paging
Try reading more on the Write Protect bit in CR0.Luns wrote:Right, that makes sense.
I thought I had everything setup alright, but now I'm not so sure. How can I test that paging is set up correctly? I've checked the CR3 register via Qemu's command line and it does have the correct physical address for my page directory. But when I try writing to some memory that should be read-only, it just gets written like normal. That means I set something up incorrectly, right?
Regards,
Shikhin
Re: Clarifying some points regarding paging
The WP bit is set in CR0 - according to the manuals, this means supervisor code cannot write to addresses with read-only access.
I checked the mappings with 'info mem' and sure enough, nothing I thought I was setting to read-only was actually being set to read only... I'll have to fiddle with my code for a bit. I made a bunch of upper memory set to read only though, and writing to that did cause a page fault! So I think once I'm setting everything to the correct permissions, I'll be good to go.
Thanks very much for the help!
I checked the mappings with 'info mem' and sure enough, nothing I thought I was setting to read-only was actually being set to read only... I'll have to fiddle with my code for a bit. I made a bunch of upper memory set to read only though, and writing to that did cause a page fault! So I think once I'm setting everything to the correct permissions, I'll be good to go.
Thanks very much for the help!
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Clarifying some points regarding paging
Did you try invalidating TLB entries before using them?
Re: Clarifying some points regarding paging
No, is that something that needs to be done? I'm quite certain the code I use to assign access modes (r/w or just r) to page table entries is incorrect, but if I need to invalidate everything first before assigning page table entries then that would be another problem with my code...
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Clarifying some points regarding paging
If the CPU could have been informed where your pagetables are before you set the read-only part, then yes it's possible that it saw them as writable and treat them as such afterwards. If that possibility exists, depends on how your code is written (it involves changing writable pages to non-writable ones while paging is active).
Re: Clarifying some points regarding paging
Alright, that makes sense.
After quite a few hours, I believe I now have paging enabled correctly. Thanks everyone for the help
After quite a few hours, I believe I now have paging enabled correctly. Thanks everyone for the help
Re: Clarifying some points regarding paging
Sorry to double post, but I have a new, somewhat related question that I thought outta go here rather than it's own topic - I'm trying to map my kernel to the 0xC0000000, and I'm not sure if I'm doing it correctly. I map my kernel (at physical 0x00100000) to 0xC0000000 using a method similar to the one on the Paging wiki page. Then I look at a few bytes of memory at 0x00100000 and 0xC0000000, and it's all the same. So does that mean I've successfully mapped my kernel to 0xC0000000? Can anyone tell if I'm missing something?
Thank you!
e: A thought - is there any reason to map the kernel to a different address in the kernel's own page directory? I understand why you would do it in a process's page directory, but not really why it's useful to the kernel process.
Thank you!
e: A thought - is there any reason to map the kernel to a different address in the kernel's own page directory? I understand why you would do it in a process's page directory, but not really why it's useful to the kernel process.
Re: Clarifying some points regarding paging
Hi,
You also want to use the CPU's "global pages" feature - make sure all of the kernel's pages are the same in all address spaces (regardless of whether it's a process' address space or the kernel's address space), then set the "global" bit for those pages, so that the CPU doesn't have to flush the kernel's TLB entries when you change address spaces. This improves performance (avoids unnecessary TLB misses when you switch virtual address spaces). You end up with "user space" (which may be unused when the kernel is using its own page directory) that isn't "global", and "kernel space" that is "global". Note: this is "all the kernel's pages", not just the kernel's ".text, .data, .rodata and .bss" - typically a kernel will dynamically allocate more RAM for things while it's running.
The 1:1 physical:virtual mapping that you did to begin with is mostly just a convenience during boot - you'd discard it once the kernel is running in its proper place. Some (most) OS's don't even both with a 1:1 physical:virtual mapping - just map the kernel at 0xC0000000 and identity map 1 page (that contains the code that enables paging and jumps to the kernel at 0xC0000000) - it means you need to do less work setting it up, and less work discarding it once the kernel is running in its proper place.
Cheers,
Brendan
Seems like it's at least partially correct - you could check the entire kernel rather than a few bytes, and check the permissions are right (e.g. try to write to something that should be "read only", try to execute something in that should be "no execute", etc).Luns wrote:Sorry to double post, but I have a new, somewhat related question that I thought outta go here rather than it's own topic - I'm trying to map my kernel to the 0xC0000000, and I'm not sure if I'm doing it correctly. I map my kernel (at physical 0x00100000) to 0xC0000000 using a method similar to the one on the Paging wiki page. Then I look at a few bytes of memory at 0x00100000 and 0xC0000000, and it's all the same. So does that mean I've successfully mapped my kernel to 0xC0000000? Can anyone tell if I'm missing something?
If you have the kernel mapped to 0xC0000000 when a process is running, then you must've compiled the kernel so that it expects to be mapped at 0xC0000000. When a process isn't running and the kernel is using its own page directory, you want to use the same kernel (and not recompile it with a different linker script or whatever so that it can run at a different address, and then have 2 versions of the same kernel at the same time, one for each virtual address).Luns wrote:e: A thought - is there any reason to map the kernel to a different address in the kernel's own page directory? I understand why you would do it in a process's page directory, but not really why it's useful to the kernel process.
You also want to use the CPU's "global pages" feature - make sure all of the kernel's pages are the same in all address spaces (regardless of whether it's a process' address space or the kernel's address space), then set the "global" bit for those pages, so that the CPU doesn't have to flush the kernel's TLB entries when you change address spaces. This improves performance (avoids unnecessary TLB misses when you switch virtual address spaces). You end up with "user space" (which may be unused when the kernel is using its own page directory) that isn't "global", and "kernel space" that is "global". Note: this is "all the kernel's pages", not just the kernel's ".text, .data, .rodata and .bss" - typically a kernel will dynamically allocate more RAM for things while it's running.
The 1:1 physical:virtual mapping that you did to begin with is mostly just a convenience during boot - you'd discard it once the kernel is running in its proper place. Some (most) OS's don't even both with a 1:1 physical:virtual mapping - just map the kernel at 0xC0000000 and identity map 1 page (that contains the code that enables paging and jumps to the kernel at 0xC0000000) - it means you need to do less work setting it up, and less work discarding it once the kernel is running in its proper place.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.