paging kernel and user address spaces

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
sigler
Posts: 15
Joined: Wed Oct 31, 2007 11:37 am

paging kernel and user address spaces

Post by sigler »

Hello,

I'm trying for my user programs running in ring3 to have their own address space. So I set up a different page directory for the user app, and in my timer interrupt, when switching to this task I set cr3 to point to the page directory of the task. So far I haven't gotten it to work, but for now my question is this:

How can this work? After I've set cr3, doesn't it take effect immediately? and I still need to access the kernel stack, perform iret etc. but I don't want the kernel stack to be available to the user program, so the kernel stack isn't in the page directory that I've just set.

what am I missing ?

thanks,

--
Sigurd Lerstad
User avatar
JAAman
Member
Member
Posts: 879
Joined: Wed Oct 27, 2004 11:00 pm
Location: WA

Post by JAAman »

After I've set cr3, doesn't it take effect immediately?
yes it does
and I still need to access the kernel stack, perform iret etc.
yes you do...
but I don't want the kernel stack to be available to the user program,
of course not, thats why its in ring0 not ring3...
so the kernel stack isn't in the page directory that I've just set.
thats your mistake


the way it normally works is, the page directory is divided into 2 parts (i use a 50/50 split: 2GB for each), and one (usually the higher portion) is given to the kernel, so that it is mapped identically into every page directory, the other portion is then given to the user application

the kernel stack will never be available to the user application, because its located in ring0, with the supervisor-only permissions selected in the page tables

suggested reading: 3A:4.11 (and really the entirety of chapter 4)
sigler
Posts: 15
Joined: Wed Oct 31, 2007 11:37 am

Post by sigler »

JAAman wrote:


the way it normally works is, the page directory is divided into 2 parts (i use a 50/50 split: 2GB for each), and one (usually the higher portion) is given to the kernel, so that it is mapped identically into every page directory, the other portion is then given to the user application

the kernel stack will never be available to the user application, because its located in ring0, with the supervisor-only permissions selected in the page tables

suggested reading: 3A:4.11 (and really the entirety of chapter 4)
What's the best way to give the kernel the upper half, it's physically in a low address, loaded by the bootloader. If I map it logically to other addresses, memory references in the kernel will start to malfunction.

Should I have a kernel that has been compiled to have it's image-base in upper-half memory? in the boot loader, load that kernel in physical ram, have a page_directory that maps that physical ram to upper half. Set cr3, then call the first instruction of the upper-half kernel?

thanks,

--
Sigurd Lerstad
User avatar
JAAman
Member
Member
Posts: 879
Joined: Wed Oct 27, 2004 11:00 pm
Location: WA

Post by JAAman »

its really quite simple:

1) link it to run at the higher location
2) load it into memory
3) use paging to map it to both the upper and lower portion
4) activate paging, while still in ASM code, jump to the higher portion

using this method is very simple, but requires that you enable paging from ASM code, at the very start -- but you must be sure to not reference any code or data since the linker will link it to the wrong address before paging is enabled -- this is a very simple step, and should be easy to implement with only a few lines of location-independent ASM code

there is another method, called 'the GDT trick' -- but its actually harder both to use and to understand

alternatively, you can enable paging in another section of code (in your second-stage loader for instance...), which is identity mapped, and simply removed from memory once your main code is running
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Post by egos »

What's the best way to give the kernel the upper half, it's physically in a low address, loaded by the bootloader. If I map it logically to other addresses, memory references in the kernel will start to malfunction.
If you don't need the low memory, you can map it to high addresses, otherwise allocate the memory and move the kernel to it.
Should I have a kernel that has been compiled to have it's image-base in upper-half memory? in the boot loader, load that kernel in physical ram, have a page_directory that maps that physical ram to upper half. Set cr3, then call the first instruction of the upper-half kernel?
You must have the kernel, which contains two parts. One has been compiled to have it's base in low addresses, another in high addresses. Set up cr3 before you pass control to the upper-half kernel.
User avatar
JAAman
Member
Member
Posts: 879
Joined: Wed Oct 27, 2004 11:00 pm
Location: WA

Post by JAAman »

you must have the kernel, which contains two parts. One has been compiled to have it's base in low addresses, another in high addresses. Set up cr3 before you pass control to the upper-half kernel.
its not actually necessary to compile it for the lower portion, if your careful
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Post by egos »

JAAman wrote:its not actually necessary to compile it for the lower portion, if your careful
Yes it is. The code usually is position-independent. But the data is not like this.
Last edited by egos on Mon Nov 19, 2007 5:21 pm, edited 1 time in total.
User avatar
JAAman
Member
Member
Posts: 879
Joined: Wed Oct 27, 2004 11:00 pm
Location: WA

Post by JAAman »

that is only true if you reference data by absolute references -- ie you allow the linker to resolve names into addresses -- if you dont do that, then its not necessary
Post Reply