Page 1 of 1
Global pages not working
Posted: Thu Sep 01, 2011 1:53 pm
by alex92
Hi,
I am trying to use global pages to map the kernel heap in all processes (this is necessary because all the thread and process linked lists are there). I enabled PGE (Page Global Enable, mask 0x80) in the CR4 register, made sure PGE is available (with CPUID), and set the page table entries as "global" (bitwise OR with 0x100) in the kernel page directory. However, as soon as a new page directory is loaded into CR3, all of those pages become "not present" as if they weren't global. Can anyone explain why this is happening? I tried running it in Bochs and QEMU.
Thanks in advance.
Re: Global pages not working
Posted: Thu Sep 01, 2011 2:07 pm
by Owen
Just because a page is global does not mean that it is not permissible for the CPU to flush it from the TLB at any point it wishes (Indeed, the architecture does not define the existence of a TLB)
Re: Global pages not working
Posted: Thu Sep 01, 2011 2:36 pm
by alex92
But if that is true, what is the purpose of the "global" flag?
The OSDev wiki article on paging states:
The Global, or 'G' above, flag, if set, prevents the TLB from updating the address in it's cache if CR3 is reset.
But if the CPU can flush the TLB entry when CR3 is reloaded, then the "global" flag has no effect.
Re: Global pages not working
Posted: Thu Sep 01, 2011 3:32 pm
by Brendan
Hi,
alex92 wrote:But if that is true, what is the purpose of the "global" flag?
The OSDev wiki article on paging states:
The Global, or 'G' above, flag, if set, prevents the TLB from updating the address in it's cache if CR3 is reset.
But if the CPU can flush the TLB entry when CR3 is reloaded, then the "global" flag has no effect.
CPU flushes TLB entries for a variety of reasons, including flushing a less recently used (global or non-global) TLB entry to make space for a more recently used (global or non-global) translation. Just because something is "global" doesn't mean it's permanently stuck in the TLB forever.
If you set the "global" flag for a page, then you're telling the CPU that you guarantee the same page is at the same address in all virtual address spaces. Based on your guarantee; the CPU can avoid flushing global TLB entries when CR3 is reloaded if it feels like it (to improve performance). If you start getting "not present" page faults for global pages when you change CR3, then you've guaranteed the pages are the same in all virtual address spaces and failed to live up to your own guarantee.
Cheers,
Brendan
Re: Global pages not working
Posted: Thu Sep 01, 2011 3:58 pm
by alex92
Thanks for your reply. Looks like the only way to map a block of memory into all processes is to change all of their page directories manually...
Re: Global pages not working
Posted: Fri Sep 02, 2011 12:16 pm
by AJ
Hi,
Yes and no. I have no idea whether you are writing a 32 or 64 bit kernel, but let's assume you are writing a 32 bit kernel which reserves the last GiB of the virtual address space for itself.
Taking this assumption, assign 1MiB of physical RAM for kernel page tables and write the corresponding PDE's (but leave the page tables zeroed until you need to page in). You now have your template page directory which can be used to create all page directories for new processes. Now, when you actually page in by adding the appropriate PTE, that change will automatically happen across all process spaces.
This example assumes 4K pages, but if you choose to use large pages for the kernel binary, it will work equally well. What doesn't work with this scheme is using large pages for the whole of kernel space - in that case, you would have to manually propagate a PDE across all PD's (you could do this by using a PFE, in which case any single PDE only causes a single exception for any one task space).
Cheers,
Adam
Re: Global pages not working
Posted: Fri Sep 02, 2011 5:24 pm
by Brendan
Hi,
AJ wrote:Yes and no. I have no idea whether you are writing a 32 or 64 bit kernel, but let's assume you are writing a 32 bit kernel which reserves the last GiB of the virtual address space for itself.
Best case for a 32-bit OS is PAE, where each virtual address space has a PDP that points to (up to) 4 page directories; where each page directory covers 1 GiB of the virtual address space. In this case you can have one page directory that is the same in all virtual address spaces (for the kernel and all its page tables, etc).
Cheers,
Brendan