Page 2 of 2
Posted: Tue Apr 29, 2008 11:02 pm
by Cognition
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.
Posted: Fri May 02, 2008 1:55 am
by jal
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.
Not to mention that your TLBs would be trashed every time.
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.
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).
JAL
Posted: Fri May 02, 2008 2:56 am
by cyr1x
Nevertheless you'll need some supervisor-code because of the IDT / ISR's.
If an interrupt occurs there would be no IDT loaded, hence tripple fault !
Posted: Fri May 02, 2008 3:11 am
by JamesM
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).
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...
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.
Posted: Fri May 02, 2008 8:02 am
by Cognition
JamesM wrote: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).
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...
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.
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.
Posted: Sat May 03, 2008 9:01 am
by pacman
cyr1x wrote:
If an interrupt occurs there would be no IDT loaded, hence tripple fault !
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.
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?
Posted: Sat May 03, 2008 11:15 am
by Combuster
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.
Sorry, wrong. It's a
linear address, and hence subject to paging.
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?
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.
Posted: Sun May 04, 2008 4:13 am
by pacman
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:
Code: Select all
unsigned int *a = (unsigned int *) 0xC0100000
or just to 0x100000
Code: Select all
unsigned int *a = (unsigned int *) 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].