Usermode and processes.
Usermode and processes.
I've reached a point in which I'm ready to get processes running in my system (got VFS with fstab working, floppy driver, FAT12 driver, full keyboard support, system calls and more..)
So I've been told that I should first move to usermode when I want to run user processes so I'm actually wondering how to do it.
There's a way of "faking" an interrupt return with iret, thus changing ds, cs and ss to my new segment selectors of usermode, declared in my GDT.
But I've tried it and I just have no idea where to set EIP to - where the hell should it return to?
Any other suggestions on how to move to usermode are blessed.
Thanks!
So I've been told that I should first move to usermode when I want to run user processes so I'm actually wondering how to do it.
There's a way of "faking" an interrupt return with iret, thus changing ds, cs and ss to my new segment selectors of usermode, declared in my GDT.
But I've tried it and I just have no idea where to set EIP to - where the hell should it return to?
Any other suggestions on how to move to usermode are blessed.
Thanks!
Re: Usermode and processes.
The iret method is fine. To begin with you can simply iret to a function (lets call it func) in your kernel code. Note that you will need a new stack for ring 3. Just push the 5 required items ( RING3_SS, ring3_stack, eflags, RING3_CS, func) and then do Thing's to remember (that I used to forget).
1. Make func very simple to begin with. You don't want errors in this function obscuring the fact that you made it to ring 3.
2. Make sure that interrupts are disabled in the eflags image that you push onto the stack.
3. Make sure that RING3_SS and RING3_CS selectors have a privilege level of 3. <== I always forget that !!
4. Make sure to rememeber that the stack on x86 grows down. Therfore ring3_stack should point somewhere near the end of your ring 3 stack.
Hope this is okay, I'm away from my dev-machine.
BTW, do you have working trap handlers ? They will need to be beefed up to handle traps from user mode.
Code: Select all
iret
1. Make func very simple to begin with. You don't want errors in this function obscuring the fact that you made it to ring 3.
Code: Select all
void func() {
while (1);
}
3. Make sure that RING3_SS and RING3_CS selectors have a privilege level of 3. <== I always forget that !!
4. Make sure to rememeber that the stack on x86 grows down. Therfore ring3_stack should point somewhere near the end of your ring 3 stack.
Hope this is okay, I'm away from my dev-machine.
BTW, do you have working trap handlers ? They will need to be beefed up to handle traps from user mode.
If a trainstation is where trains stop, what is a workstation ?
Re: Usermode and processes.
Real thanks mate!gerryg400 wrote:The iret method is fine. To begin with you can simply iret to a function (lets call it func) in your kernel code. Note that you will need a new stack for ring 3. Just push the 5 required items ( RING3_SS, ring3_stack, eflags, RING3_CS, func) and then doThing's to remember (that I used to forget).Code: Select all
iret
1. Make func very simple to begin with. You don't want errors in this function obscuring the fact that you made it to ring 3.2. Make sure that interrupts are disabled in the eflags image that you push onto the stack.Code: Select all
void func() { while (1); }
3. Make sure that RING3_SS and RING3_CS selectors have a privilege level of 3. <== I always forget that !!
4. Make sure to rememeber that the stack on x86 grows down. Therfore ring3_stack should point somewhere near the end of your ring 3 stack.
Hope this is okay, I'm away from my dev-machine.
BTW, do you have working trap handlers ? They will need to be beefed up to handle traps from user mode.
Questions:
1. Should I allocate pages for the ring3 stack with user attributes? (just verifying)
2. How can I make this func() reside over a page with user attributes? I basically could create a new section in the linker script and then use __attribute__section(("newsec")) to this function and also allocate enough pages marked as user to make it work but if there's an alternative, I would love to hear about it.
3. If I declared in my GDT that ss and cs selectors are for usermode, why should they have also an RPL of 3? (isn't RPL just an alternative for DPL in the GDT entry?)
4. Trap handlers? What do you mean? Exceptions?
BTW, Here's my code and it doesn't really work: (i've marked all kernel pages 0x7 (including user attributes), just for proof of concept) and it just reboots..
What I'm doing is calling usermode_switch, thus, the ret is pushed so in `cont` label I got back to it.
Since kernel code is user accessible, this should work, shouldn't it?
Code: Select all
global usermode_switch
usermode_switch:
cli
mov ax, 0x23
mov ds, ax
mov fs, ax
mov gs, ax
mov es, ax
push 0x23
mov eax, [esp+4]
push eax
pushf
pop eax ; when these 3 instructions are removed (to restore interrupts) it doesn't reboot. when they appear, like now, it reboots
or eax, 512
push eax
push 0x1B
push cont
iret
cont:
pop eax ; the ret from the C code
jmp eax ; back to kmain() (the function that called usermode_switch)
Last edited by eXeCuTeR on Tue Aug 17, 2010 5:02 pm, edited 3 times in total.
Re: Usermode and processes.
Yes, you must. I knew I would forget something. You could begin by going to ring 1 as a proof of concept. Then pages can remain supervisor level.Should I allocate pages for the ring3 stack with user attributes? (just verifying)
Your kernel will have to 'load' the usermode code. This means allocating some userlevel pages and copying (or mapping) the code there.How can I make this func() reside over a page with user attributes?
No it's not and alternative. More an over-ride. If you don't set the RPL of CS, you will not be in ring 3.If I declared in my GDT that ss and cs selectors are for usermode, why should they have also an RPL of 3? (isn't RPL just an alternative for DPL in the GDT entry?)
Yes.Trap handlers? What do you mean? Exceptions?
If a trainstation is where trains stop, what is a workstation ?
Re: Usermode and processes.
Hey, thanks again!gerryg400 wrote:Yes, you must. I knew I would forget something. You could begin by going to ring 1 as a proof of concept. Then pages can remain supervisor level.Should I allocate pages for the ring3 stack with user attributes? (just verifying)Your kernel will have to 'load' the usermode code. This means allocating some userlevel pages and copying (or mapping) the code there.How can I make this func() reside over a page with user attributes?No it's not and alternative. More an over-ride. If you don't set the RPL of CS, you will not be in ring 3.If I declared in my GDT that ss and cs selectors are for usermode, why should they have also an RPL of 3? (isn't RPL just an alternative for DPL in the GDT entry?)Yes.Trap handlers? What do you mean? Exceptions?
I'll be glad if you could look at my last posted (I edited it with code).
Questions:
1. Copying a function into userlevel pages - how's that done exactly? (the copying is what that bothers me)
2. So how does the DPL of GDT entries (say kernel cs & ds and user cs & ds) actually differ?
3. Yes, my trap handlers are supposed to work. Well, they have worked when faults were made.
Re: Usermode and processes.
Code: Select all
pushf
pop eax ; when these 3 instructions are removed (to restore interrupts) it doesn't reboot. when they appear, like now, it reboots
or eax, 512
push eax
If a trainstation is where trains stop, what is a workstation ?
Re: Usermode and processes.
Thanks.gerryg400 wrote:It looks like you are enabling interrupts. You can't do that untill you have set up the TSS etc.Code: Select all
pushf pop eax ; when these 3 instructions are removed (to restore interrupts) it doesn't reboot. when they appear, like now, it reboots or eax, 512 push eax
I actually have a TSS there but I don't do anything with it, it just sits there.
Anyways, I'm enabling interrupts but no interrupts should be called so why would it reboot?
Re: Usermode and processes.
Some piece of hardware (timer, keyboard etc) or even an interrupt pending from something before you got control. Have you initialised the PIC or IOAPIC ? In any event, keep ints diasabled until your TSS is set up.Anyways, I'm enabling interrupts but no interrupts should be called so why would it reboot?
If a trainstation is where trains stop, what is a workstation ?
Re: Usermode and processes.
PIC is initialized, yes. (I have a keyboard&floppy&PIT drivers)gerryg400 wrote:Some piece of hardware (timer, keyboard etc) or even an interrupt pending from something before you got control. Have you initialised the PIC or IOAPIC ?Anyways, I'm enabling interrupts but no interrupts should be called so why would it reboot?
I don't know what's IOAPIC but I guess it's for SMP system (mine is running over one core)
Re: Usermode and processes.
The PIC is okay. Get the TSS working, then enable interrupts. You'll find out then what the interrupt is.
If a trainstation is where trains stop, what is a workstation ?
Re: Usermode and processes.
EDIT: I think I got it. I'll give it some shots now. EDIT 2: didn't work tried updating esp0 in tss right before i push all parameters before the iret.gerryg400 wrote:The PIC is okay. Get the TSS working, then enable interrupts. You'll find out then what the interrupt is.
BTW, if you could refer to my previously asked question, I'd love to.
Last edited by eXeCuTeR on Tue Aug 17, 2010 5:03 pm, edited 1 time in total.
Re: Usermode and processes.
Which question ? This one ?BTW, if you could refer to my previously asked question, I'd love to.
Okay, so I assume you've got to ring 3 and you're executing your while (1) loop. You need to fill in just a few items in your TSS before you try an interrupt.Hmm, I do come up with a TSS (create a new entry and register it with `ltr` instruction) but what else could I do with it and when actually?
From what I remember (still not at my dev machine), the only fields that the processor reads during an interrupt to a higher privilege level are the SS and ESP entries for the destination ring. You will need a kernel stack. This is the stack that your interupts will execute on. Set tss->ss0 to the kernel SS, tss->esp0 to be the top of your kernel stack. You can clear the rest of the TSS. I don't think any of the other fields are read when the interrupt fires. I'm sure someone will correct me if that's wrong.
If a trainstation is where trains stop, what is a workstation ?
Re: Usermode and processes.
Hmm, I think it enters usermode but I'm not sure.gerryg400 wrote:Which question ? This one ?BTW, if you could refer to my previously asked question, I'd love to.Okay, so I assume you've got to ring 3 and you're executing your while (1) loop. You need to fill in just a few items in your TSS before you try an interrupt.Hmm, I do come up with a TSS (create a new entry and register it with `ltr` instruction) but what else could I do with it and when actually?
From what I remember (still not at my dev machine), the only fields that the processor reads during an interrupt to a higher privilege level are the SS and ESP entries for the destination ring. You will need a kernel stack. This is the stack that your interupts will execute on. Set tss->ss0 to the kernel SS, tss->esp0 to be the top of your kernel stack. You can clear the rest of the TSS. I don't think any of the other fields are read when the interrupt fires. I'm sure someone will correct me if that's wrong.
When I don't re-enable interrupts, it works. when I do, it reboots, probably TSS is damaged.
should ss0 point to 0x10 (kernel ds segment) and esp0 to the esp before I push these five values for iret?
I have got to figure a classic way to update the TSS whenever there's a switch. Any ideas?
Re: Usermode and processes.
Could you print to the screen something before the while loop ? Get this working first.Hmm, I think it enters usermode but I'm not sure.
The TSS, TSS descriptor and the TR must all be correct. Can you attach them ? Instead of enabling interrupts, use a SW interrupt. It's easier to control which vector will be used.When I don't re-enable interrupts, it works. when I do, it reboots, probably TSS is damaged.
That's okay if you're not using that stack any more. Remember you need 2 stacks. The one that you pushed before the iret and the one that esp0 points to.should ss0 point to 0x10 (kernel ds segment) and esp0 to the esp before I push these five values for iret?
Actually that's the easy part.I have got to figure a classic way to update the TSS whenever there's a switch. Any ideas?
If a trainstation is where trains stop, what is a workstation ?
Re: Usermode and processes.
I can print to screen before the while loop if I don't re-enable interrupts.gerryg400 wrote:Could you print to the screen something before the while loop ? Get this working first.Hmm, I think it enters usermode but I'm not sure.The TSS, TSS descriptor and the TR must all be correct. Can you attach them ? Instead of enabling interrupts, use a SW interrupt. It's easier to control which vector will be used.When I don't re-enable interrupts, it works. when I do, it reboots, probably TSS is damaged.That's okay if you're not using that stack any more. Remember you need 2 stacks. The one that you pushed before the iret and the one that esp0 points to.should ss0 point to 0x10 (kernel ds segment) and esp0 to the esp before I push these five values for iret?Actually that's the easy part.I have got to figure a classic way to update the TSS whenever there's a switch. Any ideas?
What do you mean to attach them?
Use a software interrupt without enabling interrupts? what do you mean?
And how's that the easy part? I just don't know when to call TSS update.
BTW, when creating a new stack..how do I deal with TSS here when I need to fill data for esp0? I mean, I push the new stack as SS for iret and before I do it, I update the TSS with esp (what esp is that? kernel's of course but what does it hold in essence) and btw, should I call ltr every time I update TSS to flush it, or just the first time so it knows where it is (more reasonable)?