tss and user space
tss and user space
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 ???
and what do i do to make a task run in user mode, is there a flag ???
Re:tss and user space
Hi,
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.
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:
Cheers,
Brendan
Anywhere..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 ???
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.
The CPL is stored in the lower 2 bits of CS, and the lower 2 bits of SS must match it.GLneo wrote:and what do i do to make a task run in user mode, is there a flag ???
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.
Re:tss and user space
thx, but how do i make it a tss discripter??? i have this to set my GDT's
so next i should do this:
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
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);
Code: Select all
set_a_gdt(3, &tss, ???, ???, 0xCF);
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
Re:tss and user space
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:
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
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
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
Re:tss and user space
get the intel manuals:
[url=http://developer.intel.com/design/pentium4/manuals/index_new.htm#sdm_vol1]
## ---- ----- ------ Intel Manuals[/url]
[url=http://developer.intel.com/design/pentium4/manuals/index_new.htm#sdm_vol1]
## ---- ----- ------ Intel Manuals[/url]
Re:tss and user space
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...
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...

- kataklinger
- Member
- Posts: 381
- Joined: Fri Nov 04, 2005 12:00 am
- Location: Serbia
Re:tss and user space
IA-32 Intel Architecture Software Developer?s Manual
Volume 3: System Programming Guide
CHAPTER 6: TASK MANAGEMENT
Have a nice reading
Volume 3: System Programming Guide
CHAPTER 6: TASK MANAGEMENT
Have a nice reading

Re:tss and user space
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
Re:tss and user space
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: so what i should do is make a new GDT entery for each task
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: the task will becoume less privlaged becouse it is in that space???
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 what does the tss do, does it store the kernel state, so the prossesor can return to it???
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 wrote: and how do i tell the prossesor were it is and what task it is for???, thx
Re:tss and user space
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
Re:tss and user space
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 i should make a GDT with user level and put my tasks in it???
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 wrote: so why do i need a tss if i'm software switching???, thx
Re:tss and user space
but cant a task just change its cs to kernel level:
and should i do it like this???:
and why do you need to know ss0 and esp0???, thx
Code: Select all
mov cs, 0x08
Code: Select all
set_a_gdt(3, \ //gdt number
0x0, \ //base
0xffffffff, \ // limit
0x92, \ // sel
0xCF); \ // flags
mov cs, 0x0F
jmp task entery
- kataklinger
- Member
- Posts: 381
- Joined: Fri Nov 04, 2005 12:00 am
- Location: Serbia
Re:tss and user space
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).
Re:tss and user space
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: but cant a task just change its cs to kernel level:Code: Select all
mov cs, 0x08
It looks like that descriptor is going to describe a ring0 data descriptor rather than a ring3 code descriptor. Check the bits.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
No. You need to do what Brendan described earlier, that is, set up an appropriate stack and iret into the user code.GLneo wrote:Code: Select all
mov cs, 0x0F jmp task entery
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 wrote: and why do you need to know ss0 and esp0???, thx
Re:tss and user space
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
i hate to ask for this but could i have some code, plz