a few questions about TSS

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.
Post Reply
Pyrofan1
Member
Member
Posts: 234
Joined: Sun Apr 29, 2007 1:13 am

a few questions about TSS

Post by Pyrofan1 »

i'm trying to learn about TSS so that i can implement multitasking in my kernel and i have a few questions about it.

in the intel mans, it says that a TSS must have esp0, esp1 and esp2. does this mean that i have to have 3 stacks? what values do i put in the ss*? do i have to have a GDT entry for each TSS? and it says that the task link holds the segment selector for the previous task, what does this mean?
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Re: a few questions about TSS

Post by AJ »

Hi,
Pyrofan1 wrote: in the intel mans, it says that a TSS must have esp0, esp1 and esp2. does this mean that i have to have 3 stacks?
No. If you are only planning on using PL0 and PL3 and are software multitasking, you only need to worry about SS0 and ESP0. SS0 contains a valid ring 0 stack segment and ESP0 should contain a pointer to your desired value of ESP when the next interrupt occurs.

Basically, if a ring 3 task is running and a ring 0 interrupt occurs, the CPU will switch to SS0:ESP0. If a ring 0 task is running and an interrupt occurs, this is not needed as the processor is already using a ring 0 stack anyway.

ESP1 and ESP2 are only required if you need to run PL1 and PL2 code in an interrupt handler called from a higer ring task.
Pyrofan1 wrote: do i have to have a GDT entry for each TSS? and it says that the task link holds the segment selector for the previous task, what does this mean?
Again, no - the GDT is global. You typically have a single GDT and use LDTs to provide separate task spaces. I would advise ignoring the GDT altogether (once it is set up initially!) and switching task spaces by changing CR3.

If you are hardware multitasking and a task switch happens by an INT or long CALL, the TSS 'backlink' is filled with the selector of the outgoing TSS. This means that the callee can return to the caller by doing an IRET or long RET.

HTH
Adam
Pyrofan1
Member
Member
Posts: 234
Joined: Sun Apr 29, 2007 1:13 am

Post by Pyrofan1 »

the TSS 'backlink' is filled with the selector of the outgoing TSS.
okay, but what is the selector? is it the address of the TSS or something else?
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Sorry I wasn't clear :oops:

The selector is the segment selector. So if your TSS descriptor is the 5th entry in the GDT, the selector is 0x20, just like with code and data segments. The TSS descriptor 'base' field then points to the actual TSS.

Cheers,
Adam
Pyrofan1
Member
Member
Posts: 234
Joined: Sun Apr 29, 2007 1:13 am

Post by Pyrofan1 »

thank you, you have been very helpful, but i have a few more questions.
when using ltr do i load the selector? how would i find out the value of the selector? and would this work as a tss structure?

Code: Select all

struct tss
{
	unsigned int task_link;
	unsigned int esp0;
	unsigned int ss0;
	unsigned int esp1;
	unsigned int ss1;
	unsigned int esp2;
	unsigned int ss2;
	unsigned int cr3;
	unsigned int eip;
	unsigned int eflags;
	unsigned int eax;
	unsigned int ecx;
	unsigned int edx;
	unsigned int ebx;
	unsigned int esp;
	unsigned int ebp;
	unsigned int esi;
	unsigned int edi;
	unsigned int es;
	unsigned int cs;
	unsigned int ss;
	unsigned int ds;
	unsigned int fs;
	unsigned int gs;
	unsigned int ldt;
	unsigned int io_map;
};
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

That certainly looks plausible as a TSS.

When you do LTR, you need to do LTR selector so you GDT may look like:

Null Segment - 0x00
Kernel Code - 0x08
Kernel Data - 0x10
User Code - 0x18
User Data - 0x20
TSS Descriptor - 0x28

In this case, you need to LTR 0x28. My code looks like this:

Code: Select all

load_task_register:
    push		ebp
    mov	ebp,	esp
    mov	eax,	[ebp+8]
    ltr         ax
    pop	ebp
ret
In this way, I can just call load_task_register(0x28) from my C code. This is probably overkill as I only ever call the function once! If you have a more dynamic GDT, you obviously need to supply the correct segment selector - but then, if your GDT is dynamic, you probably already have a function to do that. Note that a TSS descriptor must be in the GDT and not an LDT.

Adam
Pyrofan1
Member
Member
Posts: 234
Joined: Sun Apr 29, 2007 1:13 am

Post by Pyrofan1 »

okay, i got it now. thanks :)
Post Reply