tss and user space

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

tss and user space

Post by GLneo »

i know i need a tss to tell the cpu how to get back to kernel space, and i think it goes in the GDT but where ???
and what do i do to make a task run in user mode, is there a flag ???
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:tss and user space

Post by Brendan »

Hi,
GLneo wrote:i know i need a tss to tell the cpu how to get back to kernel space, and i think it goes in the GDT but where ???
Anywhere..

The TSS itself exists in memory, and there's a "TSS gate descriptor" that goes in the GDT and tells the CPU where the TSS is. This TSS gate descriptor can go anywhere in the GDT, just like a code or data segment.
GLneo wrote:and what do i do to make a task run in user mode, is there a flag ???
The CPL is stored in the lower 2 bits of CS, and the lower 2 bits of SS must match it.

To set these flags to CPL=3 you'd use a RETF or IRET instruction (possibly pushing the values on the stack first).

For example:

Code: Select all

   push dword USER_SS_DESCRIPTOR | 3
   push dword USER_ESP
   push dword USER_CS_DESCRIPTOR | 3
   push dword USER_EIP
   retf

Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
GLneo

Re:tss and user space

Post by GLneo »

thx, but how do i make it a tss discripter??? i have this to set my GDT's

Code: Select all

set_a_gdt(0, 0, 0, 0, 0);
set_a_gdt(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
set_a_gdt(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
so next i should do this:

Code: Select all

set_a_gdt(3, &tss, ???, ???, 0xCF);
or something

and what do i fill my tss struct(found one)with? is it the data for the task, the kernel, or does the prossesor auto fill it???, thx
carbonBased

Re:tss and user space

Post by carbonBased »

You're probably going to want different functions for creating segment descriptors and TSS descriptors, as they look a fair bit different.

Here's a TSS descriptor:

Code: Select all

       bits
       7 6 5 4 3 2 1
Byte 7 Base3
Byte 6 G 0 0 A SizeNib
Byte 5 P D S X 0 B 1
Byte 4 Base2
Byte 3 Base1
Byte 2 Base0
Byte 1 Size1
Byte 0 Size0
Where:
G - Granularity (same as memory descriptor)
A - Available for system use
P - Present
D - DPL
S - System bit. Must be 0 for TSS
X - TSS type (0 = 16 bit, 1 = 32 bit)
B - Busy bit - 1 for busy task (interrupted by ISR)
SizeNib = Upper nibble of size

Cheers,
Jeff
JAAman

Re:tss and user space

Post by JAAman »

get the intel manuals:

[url=http://developer.intel.com/design/pentium4/manuals/index_new.htm#sdm_vol1]
## ---- ----- ------ Intel Manuals[/url]
guest

Re:tss and user space

Post by guest »

For going to user space, you don?t need the tss. Like Brendan already said, you simply push some values on your stack, namely user_eip, user_cs, eflags, user_esp, user_ss similar an interrupt service routine would do. Then use IRET which pops of these values in the right place - if you pushed them in the right order. If you set up everything correct, you should then be in user space at position user_eip. IRET doesn?t pop user_ds, so you may wish to push and pop it manually...

For jumping back to the kernel (interrupt or syscall), you need a tss with the fields ss0 and esp0 set to your kernel_ss and kernel_esp0. Beside writing the tss-descriptor to your gdt, you also need to load its selector into the cpu?s task register with the LTR-instruction.

Then the values are automatically loaded when you jump to privilege level 0. For the jump itself you also need a gate, because you can?t go directly from privilege level 3 (user) to privilege level 0 (kernel)...which has some good reasons... :)
User avatar
kataklinger
Member
Member
Posts: 381
Joined: Fri Nov 04, 2005 12:00 am
Location: Serbia

Re:tss and user space

Post by kataklinger »

IA-32 Intel Architecture Software Developer?s Manual
Volume 3: System Programming Guide
CHAPTER 6: TASK MANAGEMENT

Have a nice reading :)
GLneo

Re:tss and user space

Post by GLneo »

o.k. a good read, so what i should do is make a new GDT entery for each task and make it user level then put the task in that space and the task will becoume less privlaged becouse it is in that space??? and what does the tss do, does it store the kernel state, so the prossesor can return to it??? and how do i tell the prossesor were it is and what task it is for???, thx
QuiTeVexat

Re:tss and user space

Post by QuiTeVexat »

GLneo wrote: so what i should do is make a new GDT entery for each task
If you plan on doing hardware task switching, yes. Software, no. For software task switching, you'll want one entry in your GDT for a single TSS, so you can define esp0 and ss0.
GLneo wrote: the task will becoume less privlaged becouse it is in that space???
The task will be less privileged if while it runs the descriptor describing its code segment is for a less privileged ring. If I have a descriptor in my GDT describing a ring3 code segment from 0 - 0xffffffff, and another descriptor describing a ring0 code segment from 0 to 0xffffffff, when CS is loaded with the former, the processor will run with the privileges of ring3, and when CS is loaded with the latter, the processor will run with the privileges of ring0.
GLneo wrote: and what does the tss do, does it store the kernel state, so the prossesor can return to it???
The TSS stores the state of the task, and the stack segment and stack pointer for more privileged code. This is done so that more privileged code can set up a stack for itself to be used when interrupts and other privilege changes happen.
GLneo wrote: and how do i tell the prossesor were it is and what task it is for???, thx
The ltr instruction. It's all in the manual. Note that the TSS doesn't really define a task, even when you use hardware task switching. What it does do is describe a processor state. It's the job of the OS writer to decide on the whole idea of tasks, threads, jobs, fibers, etc. and how to implement them appropriately.
GLneo

Re:tss and user space

Post by GLneo »

so i should make a GDT with user level and put my tasks in it??? so why do i need a tss if i'm software switching???, thx
QuiTeVexat

Re:tss and user space

Post by QuiTeVexat »

GLneo wrote: so i should make a GDT with user level and put my tasks in it???
I don't quite understand what you mean by "put my tasks in it". In order to get stuff to run in user mode, you need to have a user code segment defined, and when those tasks are running their code, CS will be set to that descriptor.
GLneo wrote: so why do i need a tss if i'm software switching???, thx
So you can define ss0 and esp0, which indicate the stack segment and stack pointer which will be used when there is a switch to ring0 code from the user code.
GLneo

Re:tss and user space

Post by GLneo »

but cant a task just change its cs to kernel level:

Code: Select all

mov cs, 0x08
and should i do it like this???:

Code: Select all

set_a_gdt(3,      \ //gdt number
    0x0,       \ //base
    0xffffffff, \ // limit
    0x92,      \ // sel
    0xCF);     \ // flags
    mov cs, 0x0F 
    jmp task entery
and why do you need to know ss0 and esp0???, thx
User avatar
kataklinger
Member
Member
Posts: 381
Joined: Fri Nov 04, 2005 12:00 am
Location: Serbia

Re:tss and user space

Post by kataklinger »

There is no such instruction like mov cs,ax. You cannot change CS like that, you can modify CS by executing CALL, JMP and RET(IRET) instruction. If you want to get from user land to kernel you must use software ints, or call gates, and when you do that CPU looks at ss0 & esp0 fields in current TSS and loads those values to SS & ESP register (it is called kernel stack).
QuiTeVexat

Re:tss and user space

Post by QuiTeVexat »

GLneo wrote: but cant a task just change its cs to kernel level:

Code: Select all

mov cs, 0x08
Nope, the processor will see that CPL < DPL, and raise a GPF. At which point control will be transfered to the GPF handler and you can decide what to do with the naughty little program (don't give it any presents, certainly).

GLneo wrote: and should i do it like this???:

Code: Select all

set_a_gdt(3,      \ //gdt number
     0x0,       \ //base
     0xffffffff, \ // limit
     0x92,      \ // sel
     0xCF);     \ // flags
It looks like that descriptor is going to describe a ring0 data descriptor rather than a ring3 code descriptor. Check the bits.
GLneo wrote:

Code: Select all

mov cs, 0x0F 
jmp task entery
No. You need to do what Brendan described earlier, that is, set up an appropriate stack and iret into the user code.
GLneo wrote: and why do you need to know ss0 and esp0???, thx
The ring0 code needs a stack. It can't use the user stack, because that could allow security to be violated. The ring3 code could provide the ring0 code with a bad stack, for example, or inspect its contents when the ring0 code returns and get information it shouldn't have. The ss0 and esp0 fields of the TSS allow the position of the stack to be defined by the ring0 code.
GLneo

Re:tss and user space

Post by GLneo »

so ss and esp are my kernels stack??? but how does the cpu know where to find the tss??? and was i corect with making a user level GDT starting at 0x0 and going to 0xFFFFFFFF then making my task cs and ds to 0x0F???

i hate to ask for this but could i have some code, plz
Post Reply