Page 1 of 2
PDBR During Interrupts
Posted: Mon Apr 28, 2008 3:21 am
by pacman
Hi
During an interrupt, dont I have to save the PDBR and then load CR3 with the PDBR of the kernel?
Thanks
Posted: Mon Apr 28, 2008 3:25 am
by Combuster
Have you thought through:
1) what loading CR3 does
2) why you would actually want to do that
3) whether that is the best way to solve the problem in 2)
Posted: Mon Apr 28, 2008 3:36 am
by pacman
From my understanding....
1) what loading CR3 does
- CR3 contains the address of the Page Directory
2) why you would actually want to do that
- If the CPU is running process A, CR3 would contain the address of process A's Page Directory.
- When an interrupt occurs, to use kernel functions, I would need to load CR3 with the Page Directory of the kernel.
3) whether that is the best way to solve the problem in 2)
- One of the reasons why I'm posting here
Thanks
Posted: Mon Apr 28, 2008 3:47 am
by Combuster
Next question:
Why isn't the kernel mapped in every process' page tables?
Posted: Mon Apr 28, 2008 4:03 am
by pacman
Combuster wrote:Why isn't the kernel mapped in every process' page tables?
I haven't thought of that, but it makes sense...
Ok I've just read about mapping the kernel to every process' address space. Now if the kernel is mapped to the virtual address 0x500000 (I know its a wierd address, but to make things easier to understand) of every process' address space, would'nt it refuse to work since every memory reference would now have to be: <memory reference>+0x500000?
Posted: Mon Apr 28, 2008 5:02 am
by jal
pacman wrote:[Now if the kernel is mapped to the virtual address 0x500000 (I know its a wierd address, but to make things easier to understand) of every process' address space, would'nt it refuse to work since every memory reference would now have to be: <memory reference>+0x500000?
Of course not. You can tell your linker that your kernel start address is 0x500000 (still don't know why that's easier, but ok), and it will link it for you using that address. Alternatively, you can use e.g. a relocatable ELF for your kernel image and relocate it yourself.
JAL
Posted: Mon Apr 28, 2008 6:51 am
by pacman
You can tell your linker that your kernel start address is 0x500000
What if I wanted my kernel to be located (in virtual memory) from 2GB? I would tell my linkerscript that the start address is 2GB. Then, when GRUB tries to load my kernel, wouldn't it refuse to work since virtual memory is not enabled at that time (hence, the 2GB address doesnt actually exist)?
Also, if I didnt map my kernel to each address space, would interrupts still work? If they did, couldnt I simply change CR3 at each interrupt?
Posted: Mon Apr 28, 2008 8:41 am
by jal
pacman wrote:What if I wanted my kernel to be located (in virtual memory) from 2GB?
That is so common, there's a Wiki page about it. It's called "higher half kernel". Go check it out, and come back if you have more questions.
JAL
Posted: Mon Apr 28, 2008 9:15 am
by bewing
Combuster wrote:Next question:
Why isn't the kernel mapped in every process' page tables?
Because that seems like a serious weakening of kernel security? I am looking to
separate the kernel from userspace -- not bring them closer.
Posted: Mon Apr 28, 2008 10:54 am
by Korona
There are some flags in every page table entry to restrict access to pages to ring0/1/2 tasks. That way the kernel can be mapped into all page directories without any security problems.
Posted: Mon Apr 28, 2008 12:50 pm
by bewing
Which is precisely the problem. I don't want ring 1 (untrusted) drivers having kernel access. Which means I can't map the kernel into the memory of those tasks using that mechanism. Which means I might as well not map it into the memory of any task -- since no task except the scheduler (in my OS) is allowed to call the kernel directly anyway.
Posted: Mon Apr 28, 2008 3:11 pm
by Combuster
I wouldn't want to use ring 1 because of the same reasons.
Posted: Tue Apr 29, 2008 6:21 am
by jal
bewing wrote:Which is precisely the problem. I don't want ring 1 (untrusted) drivers having kernel access.
I think the whole ring 0/1/2/3 is a result of the 286 segmentation model (or did it start with the 386?), and is rather obsolete by now. Most architectures have only two levels, so you put your drivers either in ring 0 (kernel space) or ring 3 (user space). Ring 1/2 can be ignored, also because it's not very portable.
JAL
Posted: Tue Apr 29, 2008 9:15 pm
by Zenith
Kind of hijacking this thread, but:
What's the advantage of mapping the kernel into every user process? I mean, it adds the additional overhead of having to:
- Actually mapping the kernel virtual memory to every user page directory
- (Depending on kernel type) Having to deal with the hassle of higher-half addressing
- Weakened security, entwining the kernel/userspace, and loss of address space for an application
All the wiki article (on higher half kernels) says is that it's "traditional" and "generally good" to map the kernel to every user process, but can anyone give me reasons why someone would do this?
Posted: Tue Apr 29, 2008 10:58 pm
by bewing
It is one way of handling this problem:
- When an interrupt occurs, to use kernel functions, I would need to load CR3 with the Page Directory of the kernel.
If every process has the kernel mapped, and an interrupt happens, then Ring 0 handlers have immediate access to kernelspace.
Also, if your API allows (for speed reasons) userspace apps to call kernelspace functions directly (at a reduced privelege level?) -- then you need the kernelspace mappng to call the functions.