It's good because it reduces the overhead of user->kernel calls and back. It takes a good amount of time for a processor to load a TSS or a new page table (the more entries the longer it takes). Ideally you want to reduce this for performance reasons, I don't have exact numbers but I've read this can amount to around 3 microseconds or around ~975 cycles minimum. You'd have that overhead everytime a system call or kernel handled interrupt fired. Basically your processor would spend a lot of time simply switching tasks instead of actually running them.
It's worth noting that two of the things you listed as problems aren't really that big of ones.
Mapping kernel pages: Global pages pretty much accomplish this iirc, there's some special rules when invalidating them, but it definetly cuts down on the overhead.
Security: Any attempt to read to or write from a kernel page will generate a page fault if it's done from a user space process. The processor can see your kernel, but userspace apps can never really access it outside of system/interrupt calls that have to be enabled through the operating system to begin with. Nothing is really less secure with this approach, it might technically be less flexible then segmentation due to only having 2 privelege levels but that's it. But with segmentation essentially disabled in long mode it's probably better to use primarily page level protection to keep your code portable.
PDBR During Interrupts
Not to mention that your TLBs would be trashed every time.Cognition wrote:I don't have exact numbers but I've read this can amount to around 3 microseconds or around ~975 cycles minimum. You'd have that overhead everytime a system call or kernel handled interrupt fired. Basically your processor would spend a lot of time simply switching tasks instead of actually running them.
The user apps don't see anything, since both reading and writing should be prohibited. The memory space is consumed, but apps needing more than 2Gb of memory are extremely rare (and if you'd have many of them, you'd need a 64 bit environment anyway).Security: Any attempt to read to or write from a kernel page will generate a page fault if it's done from a user space process. The processor can see your kernel, but userspace apps can never really access it outside of system/interrupt calls that have to be enabled through the operating system to begin with.
JAL
Please quote your sources. Changing page table is just a TLB flush/refill. Refilling the TLB takes a maximum time of n memory loads, where n is the size of the TLB, and it's usually not massive! Not to mention the fact that many of those refill memops will actually hit one of the caches...It takes a good amount of time for a processor to load a TSS or a new page table (the more entries the longer it takes).
I'm not sure if the x86 creates implicit ASIDs for its TLB entries - I assume not, but if it did it would decrease the page table swap time down by a dramatic amount too.
Typo there, that should be "and a". I apologize for that, I can see where it would be misleading.JamesM wrote:Please quote your sources. Changing page table is just a TLB flush/refill. Refilling the TLB takes a maximum time of n memory loads, where n is the size of the TLB, and it's usually not massive! Not to mention the fact that many of those refill memops will actually hit one of the caches...It takes a good amount of time for a processor to load a TSS or a new page table (the more entries the longer it takes).
I'm not sure if the x86 creates implicit ASIDs for its TLB entries - I assume not, but if it did it would decrease the page table swap time down by a dramatic amount too.
Source: http://www.osdev.org/osfaq2/index.php/C ... 0Switching
If you have better/aditional information I wouldn't mind seeing it personally. I haven't found an official manual on these types of things and really would love to have some credible numbers regarding the overhead of issuing IPI's and anything that causes a context switch really.
Afaik, the IDTR is loaded with a physical address. So even if the IDT is not mapped in the page tables, an interrupt will still occur without a triple fault.cyr1x wrote: If an interrupt occurs there would be no IDT loaded, hence tripple fault !
Edit: If I map the kernel to every process' address space, if the kernel's number of page tables/page frames changes, wouldn't I have to update every process' page tables?
- 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:
Sorry, wrong. It's a linear address, and hence subject to paging.pacman wrote:Afaik, the IDTR is loaded with a physical address. So even if the IDT is not mapped in the page tables, an interrupt will still occur without a triple fault.
Not necessarily. If you share the kernel page tables, you'd never change anything for every process. You'd only need to point each page directory to the same set of pages.Edit: If I map the kernel to every process' address space, if the kernel's number of page tables/page frames changes, wouldn't I have to update every process' page tables?
So I (finally) got my kernel to successfully start in the higher half. Now, if I want a pointer which points to the virtual address 0x100000, do I make it point to 0xC0100000:
or just to 0x100000
Am I correct in saying that if I need to allocate an additional page table for the kernel, I'd enable page table 769 in the page directory (when setting up the higher half, I enabled page_dir[768] and page_dir[0].
Code: Select all
unsigned int *a = (unsigned int *) 0xC0100000
Code: Select all
unsigned int *a = (unsigned int *) 0x100000