Usermode and processes.

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.
eXeCuTeR
Member
Member
Posts: 63
Joined: Tue Dec 09, 2008 12:43 pm

Usermode and processes.

Post by eXeCuTeR »

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!
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Usermode and processes.

Post by gerryg400 »

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

Code: Select all

    iret
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.

Code: Select all

    void func() {
        while (1);
    }
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.
If a trainstation is where trains stop, what is a workstation ?
eXeCuTeR
Member
Member
Posts: 63
Joined: Tue Dec 09, 2008 12:43 pm

Re: Usermode and processes.

Post by eXeCuTeR »

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 do

Code: Select all

    iret
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.

Code: Select all

    void func() {
        while (1);
    }
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.
Real thanks mate!
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.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Usermode and processes.

Post by gerryg400 »

Should I allocate pages for the ring3 stack with user attributes? (just verifying)
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.
How can I make this func() reside over a page with user attributes?
Your kernel will have to 'load' the usermode code. This means allocating some userlevel pages and copying (or mapping) the code there.
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?)
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.
Trap handlers? What do you mean? Exceptions?
Yes.
If a trainstation is where trains stop, what is a workstation ?
eXeCuTeR
Member
Member
Posts: 63
Joined: Tue Dec 09, 2008 12:43 pm

Re: Usermode and processes.

Post by eXeCuTeR »

gerryg400 wrote:
Should I allocate pages for the ring3 stack with user attributes? (just verifying)
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.
How can I make this func() reside over a page with user attributes?
Your kernel will have to 'load' the usermode code. This means allocating some userlevel pages and copying (or mapping) the code there.
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?)
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.
Trap handlers? What do you mean? Exceptions?
Yes.
Hey, thanks again!
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.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Usermode and processes.

Post by gerryg400 »

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
It looks like you are enabling interrupts. You can't do that untill you have set up the TSS etc.
If a trainstation is where trains stop, what is a workstation ?
eXeCuTeR
Member
Member
Posts: 63
Joined: Tue Dec 09, 2008 12:43 pm

Re: Usermode and processes.

Post by eXeCuTeR »

gerryg400 wrote:

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
It looks like you are enabling interrupts. You can't do that untill you have set up the TSS etc.
Thanks.
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?
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Usermode and processes.

Post by gerryg400 »

Anyways, I'm enabling interrupts but no interrupts should be called so why would it reboot?
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.
If a trainstation is where trains stop, what is a workstation ?
eXeCuTeR
Member
Member
Posts: 63
Joined: Tue Dec 09, 2008 12:43 pm

Re: Usermode and processes.

Post by eXeCuTeR »

gerryg400 wrote:
Anyways, I'm enabling interrupts but no interrupts should be called so why would it reboot?
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 ?
PIC is initialized, yes. (I have a keyboard&floppy&PIT drivers)
I don't know what's IOAPIC but I guess it's for SMP system (mine is running over one core)
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Usermode and processes.

Post by gerryg400 »

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 ?
eXeCuTeR
Member
Member
Posts: 63
Joined: Tue Dec 09, 2008 12:43 pm

Re: Usermode and processes.

Post by eXeCuTeR »

gerryg400 wrote:The PIC is okay. Get the TSS working, then enable interrupts. You'll find out then what the interrupt is.
EDIT: I think I got it. I'll give it some shots now. EDIT 2: didn't work :o tried updating esp0 in tss right before i push all parameters before the iret.
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.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Usermode and processes.

Post by gerryg400 »

BTW, if you could refer to my previously asked question, I'd love to.
Which question ? This one ?
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?
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.

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 ?
eXeCuTeR
Member
Member
Posts: 63
Joined: Tue Dec 09, 2008 12:43 pm

Re: Usermode and processes.

Post by eXeCuTeR »

gerryg400 wrote:
BTW, if you could refer to my previously asked question, I'd love to.
Which question ? This one ?
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?
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.

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.
Hmm, I think it enters usermode but I'm not sure.
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?
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Usermode and processes.

Post by gerryg400 »

Hmm, I think it enters usermode but I'm not sure.
Could you print to the screen something before the while loop ? Get this working first.
When I don't re-enable interrupts, it works. when I do, it reboots, probably TSS is damaged.
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.
should ss0 point to 0x10 (kernel ds segment) and esp0 to the esp before I push these five values for iret?
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.
I have got to figure a classic way to update the TSS whenever there's a switch. Any ideas?
Actually that's the easy part.
If a trainstation is where trains stop, what is a workstation ?
eXeCuTeR
Member
Member
Posts: 63
Joined: Tue Dec 09, 2008 12:43 pm

Re: Usermode and processes.

Post by eXeCuTeR »

gerryg400 wrote:
Hmm, I think it enters usermode but I'm not sure.
Could you print to the screen something before the while loop ? Get this working first.
When I don't re-enable interrupts, it works. when I do, it reboots, probably TSS is damaged.
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.
should ss0 point to 0x10 (kernel ds segment) and esp0 to the esp before I push these five values for iret?
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.
I have got to figure a classic way to update the TSS whenever there's a switch. Any ideas?
Actually that's the easy part.
I can print to screen before the while loop if I don't re-enable interrupts.
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)?
Post Reply