Page 1 of 1

Getting around the TSS with software task-switching

Posted: Wed Apr 01, 2009 12:14 pm
by earlz
Ok, So I got my software task switching system perfect finally.. Now I have a problem though. Adding a stupid TSS so usermode can have interrupts... which, btw, is it possible to avoid the TSS altogether with usermode? Like, if a page-fault happened in usermode would that require the TSS? Cause I would be perfectly content using GPFs or the like instead of interrupts for syscalls... (infact, it seems more flexible to me)

Anyway though. My problem:

Code: Select all

int_template: ;compiled once but edited and used as a template
	pusha
	push ds
	push es
	push fs
	push gs
	mov ax, 0x08   ; Load the Kernel Data Segment descriptor! 
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov ss,ax
	mov ebx, esp   ; move the stack to temporary location
	mov eax,0
	mov al,byte [int_level]
	shl eax,12 ;align it to a page
	or eax,INT0_STACK_BASE
	inc byte [int_level]
	mov esp,eax
	push ebx ;push old stack value onto new stack 
	mov eax, int_catcher ;this stays constant
	call eax   ; A special call, preserves the 'eip' register
	;Get the return value
	pop esp ;throw away parameter
	mov esp,eax ;The int_catcher returns the stack!
	dec byte [int_level]
	;pop eax
	pop gs
	pop fs
	pop es
	pop ds
	popa
	add esp, 8     ; Cleans up the pushed error code and pushed ISR number
	iret           ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP!
end_template:
the INT0_STACK_BASE bit makes it so if an interrupt happens inside an interrupt, it will use a new stack.. I don't remember why, but reusing the old stack caused me some kind of problems before..

But on to my question.. how would I incorporate the TSS into this stub? The problem is the mov esp,eax. This is for my task-scheduler. It returns the programs stack address, so that all the variables can easily be popped off as if nothing happened.. If I had a TSS I would not be able to have this same functionality. I wouldn't be able to store the old stack address for the scheduler. How do I get around this problem?

Re: Getting around the TSS with software task-switching

Posted: Wed Apr 01, 2009 12:19 pm
by skyking
The problem is that the TSS contains the stack pointer for ring 0-2, so you need one for the ability to change ring.

Re: Getting around the TSS with software task-switching

Posted: Wed Apr 01, 2009 12:28 pm
by Combuster
Like, if a page-fault happened in usermode would that require the TSS?
Any jump, and only those jumps that go from a less privileged mode to a more privileged use the TSS. They replace ESP and SS with the values contained in there.

That means that once you enter userspace, you will need a valid TSS, or else any attempt to get out will cause a triple fault.

If you are careful, you have little to do with the actual stackpointer. When you enter the kernel (by system call for example), it sees that it goes from ring 3 to ring 0, and thus ESP and SS will be loaded with TSS.ESP0 and TSS.SS0, and you are at the top of a valid stack. If later an interrupt occurs, the processor will check the jump, and see it goes from ring 0 to ring 0, so it just pushes the current CS/EIP/FLAGS on the stack, but otherwise doesn't access the TSS.

That means that if you make sure that
a) Consecutive handlers can't overflow the stack (no large arrays, only EOI with interrupts disabled)
b) All handlers are safe to return to whatever state the processor was previously in (especially important for v8086 users!)
You don't need to worry about stack management in common use, and the only time you potentially need to change ESP manually is when switching between tasks.

Re: Getting around the TSS with software task-switching

Posted: Wed Apr 01, 2009 12:43 pm
by earlz
Combuster wrote:
That means that once you enter userspace, you will need a valid TSS, or else any attempt to get out will cause a triple fault.

If you are careful, you have little to do with the actual stackpointer. When you enter the kernel (by system call for example), it sees that it goes from ring 3 to ring 0, and thus ESP and SS will be loaded with TSS.ESP0 and TSS.SS0, and you are at the top of a valid stack. If later an interrupt occurs, the processor will check the jump, and see it goes from ring 0 to ring 0, so it just pushes the current CS/EIP/FLAGS on the stack, but otherwise doesn't access the TSS.
Ok, well JamesM needs to change his tutorial.. he makes it sound like IRQs can be enabled without a TSS in usermode.. lol.. (though it is a great tutorial!)

And that should really help.. so if I don't have any interrupts that enter anything but ring0, then I can set the ESP and SS to INT0_STACK_BASE?

What happens to the old ESP and SS though? like for my scheduler, it is crucial that I can get and set the stack address it will pop registers from... and if the TSS loads all context from the TSS on a ring3->ring0 switch, how do I obtain this information? must I read through the TSS to get this info cause that seems like it defeats the purpose of software task switching

Re: Getting around the TSS with software task-switching

Posted: Wed Apr 01, 2009 1:57 pm
by Combuster
You should seriously read the tutorial better. It says what you think it does not, and it answers each and every question you just posted.

Re: Getting around the TSS with software task-switching

Posted: Wed Apr 01, 2009 2:53 pm
by hailstorm
Earlz,

I think you don't fully understand the concept of task switching using only one TSS. In this case, the TSS is only used to make the transition to a higher privilege level. That means that if a ring 3 task gets interrupted, the cpu knows exactly where to push the registers that are saved during an interrupt, through the ss0-ss2 and esp0-esp2 entries in the TSS. If the RPL == CPL, only cs, eip and flags are pushed on the stack, since no transition to a higher privilege level takes place. But, if this transition is happening, the ss and esp register are pushed on the stack of the interrupt handling routine (or kernel, whatever), giving you access to the ss and esp register of the interrupted task. It is then up to you where you store your registers.

Hope this helps a bit. If not, I didn't understand you question at all... :mrgreen:

Greetz.

Re: Getting around the TSS with software task-switching

Posted: Wed Apr 01, 2009 3:41 pm
by earlz
Ok, I got it all fixed up now, even got software interrupts working!