Page 1 of 1

Switching ring 0 <--> ring 3?

Posted: Tue May 20, 2008 4:43 am
by junkoi
Hi,

I am looking for a tutorial that deals with switching from ring 0 to ring 3 (and back). Anybody knows if there is any tutorial like that around?

Many thanks,
Jun

Posted: Tue May 20, 2008 5:24 am
by JamesM
Hi,

This sort of gives me a kick to start work on the documentation for my user mode tutorial. I'll do some writing now - the link to the download of documented code (tutorial style) is here.

Cheers,

James

Posted: Tue May 20, 2008 8:40 am
by JamesM
Hi,

After a few hours writing, draft version is now online here. I'm not fully happy with it as yet and I will add some spit and polish to it - there are also a few errata which magically appear fixed in this tutorial but have not been backported to the old ones yet - I need to do that.

Hope it helps, do give me a shout if you have any questions!

Cheers,

James

Posted: Tue May 20, 2008 9:52 am
by junkoi
James, excellent tutorial!!! Seriously, have you ever considered writting a book? You have a great ability, that is explain things in easy way. Believe me, not everybody can do that!

I spot some typos in the below code (syscall_handler() function)

.....
pop %%ebx; \
pop %%ebx; \
pop %%ebx; \
pop %%ebx; \
pop %%ebx; \
" : "=a" (ret) : "r" (regs->edi), "r" (regs->esi), "r" (regs->edx), "r" (regs->ecx), "r" (regs->ebx), "r" (location));

You must intend to pop %ecx, %edx, %esi, %edi here.

Keep up the good work. Your tutorials is excellent!!!

Thanks,
Jun

Posted: Tue May 20, 2008 12:29 pm
by JamesM
junkoi wrote:James, excellent tutorial!!! Seriously, have you ever considered writting a book? You have a great ability, that is explain things in easy way. Believe me, not everybody can do that!

I spot some typos in the below code (syscall_handler() function)

.....
pop %%ebx; \
pop %%ebx; \
pop %%ebx; \
pop %%ebx; \
pop %%ebx; \
" : "=a" (ret) : "r" (regs->edi), "r" (regs->esi), "r" (regs->edx), "r" (regs->ecx), "r" (regs->ebx), "r" (location));

You must intend to pop %ecx, %edx, %esi, %edi here.

Keep up the good work. Your tutorials is excellent!!!

Thanks,
Jun
Hi,

Thanks very much! :oops:

Actually, it doesn't matter what registers we pop to there as long as we pop to somewhere! The important thing is removing the items from the stack. Their values we no longer care about.

Cheers,

James

Posted: Tue May 20, 2008 2:02 pm
by lukem95
looks good, i'll read it properly at some point.

I implemented this in my OS in a similar (but probably less efficiant) way to you, so i may have a go at using some of your ideas :)

Posted: Tue May 20, 2008 8:16 pm
by junkoi
JamesM wrote:
junkoi wrote:James, excellent tutorial!!! Seriously, have you ever considered writting a book? You have a great ability, that is explain things in easy way. Believe me, not everybody can do that!

I spot some typos in the below code (syscall_handler() function)

.....
pop %%ebx; \
pop %%ebx; \
pop %%ebx; \
pop %%ebx; \
pop %%ebx; \
" : "=a" (ret) : "r" (regs->edi), "r" (regs->esi), "r" (regs->edx), "r" (regs->ecx), "r" (regs->ebx), "r" (location));

You must intend to pop %ecx, %edx, %esi, %edi here.

Keep up the good work. Your tutorials is excellent!!!

Thanks,
Jun
Hi,

Thanks very much! :oops:

Actually, it doesn't matter what registers we pop to there as long as we pop to somewhere! The important thing is removing the items from the stack. Their values we no longer care about.
James
That is true. I missed that we have no output from the inline code, except %eax.

A question: your code switch from ring 0 to ring 3 using IRET. I wonder if Linux uses the same way to switch from ring 0 to ring 3? Maybe that is how they execute /sbin/init to give control to ring 3?

Cant wait for your next tutorials!

Thanks,
Jun

Posted: Tue May 20, 2008 8:29 pm
by piranha
A question: your code switch from ring 0 to ring 3 using IRET. I wonder if Linux uses the same way to switch from ring 0 to ring 3? Maybe that is how they execute /sbin/init to give control to ring 3?
......The init program deals with runlevels, not rings. Those are 2 completely different subjects.

Runlevels are just what stuff is started.

-JL

Posted: Wed May 21, 2008 1:22 am
by JamesM
junkoi wrote: A question: your code switch from ring 0 to ring 3 using IRET. I wonder if Linux uses the same way to switch from ring 0 to ring 3? Maybe that is how they execute /sbin/init to give control to ring 3?
Hi,

IRET is the only way on x86 to change to ring 3. As piranha pointed out, INIT deals with runlevels which are linux specific.

Cheers,

James

Posted: Wed May 21, 2008 1:29 am
by junkoi
You missed my point. No, I dont mistake ring and level stuffs. My question is "Is this technique (IRET to return to ring 3 from ring 0) the way Linux gives control to /sbin/init, which is the first ring 3 process?"

Thanks,
Jun

Posted: Wed May 21, 2008 1:50 am
by JamesM
junkoi wrote:You missed my point. No, I dont mistake ring and level stuffs. My question is "Is this technique (IRET to return to ring 3 from ring 0) the way Linux gives control to /sbin/init, which is the first ring 3 process?"

Thanks,
Jun
Hi,

Yes. IRET is the only method of switching from ring0 to 3 on x86.

Cheers,

James

Posted: Wed May 21, 2008 4:20 am
by Combuster
JamesM wrote:IRET is the only method of switching from ring0 to 3 on x86.
I expected a bit better from you - there are many more alternatives. IRET is the most used one though:
  • IRET
  • Sysret
  • Sysexit
  • Far jump/far call using TSS
  • SMM, VM extensions, Loadall etc.

Posted: Wed May 21, 2008 6:04 am
by JamesM
Combuster wrote:
JamesM wrote:IRET is the only method of switching from ring0 to 3 on x86.
I expected a bit better from you - there are many more alternatives. IRET is the most used one though:
  • IRET
  • Sysret
  • Sysexit
  • Far jump/far call using TSS
  • SMM, VM extensions, Loadall etc.
Point taken - I've never investigated SMM etc. But I purposely avoided using sysexit as it's not available on all systems, and sysret is only on x86_64...

Posted: Fri May 23, 2008 1:10 am
by junkoi
Combuster wrote:
JamesM wrote:IRET is the only method of switching from ring0 to 3 on x86.
I expected a bit better from you - there are many more alternatives. IRET is the most used one though:
  • IRET
  • Sysret
  • Sysexit
  • Far jump/far call using TSS
  • SMM, VM extensions, Loadall etc.
Interesting! Can you elaborate about the "Far jmp/call using TSS"?

Thanks,
Jun

Posted: Fri May 23, 2008 1:49 am
by AJ
Hi,

This is basically hardware task switching (which is covered in the Intel Manuals in some depth). You do a far jump using the TSS descriptor as your segment selector. e.g. If you jump to PMode, you probably do:

Code: Select all

jmp 0x08:PModeFunction
Whereas here, if the TSS is your 5th GDT entry, you do:

Code: Select all

jmp 0x28:0x00000000
The offset is ignored by the CPU.

Cheers,
Adam