Page 1 of 1
handling exceptions with taskgates
Posted: Sun Oct 17, 2004 12:45 pm
by aladdin
I read in intel manual that using taskgates is more interestiong than intgates since the task context is automatically saved while calling exceptions
so I did a simple test with GPF exception, and it seems to work, but I have a little problem :
when the exception is called for the first time, everything is ok, but when it is called again, it doesn't work
I thing this is due to the fact that EIP is saved to its tss, so how can I do to make EIP re-point to the beginning of my GPF handler code ?
Re:handling exceptions with taskgates
Posted: Mon Oct 18, 2004 2:40 am
by Pype.Clicker
Beware that task gates are not always interresting, especially for interrupts (due to extra context switch overhead plus the fact that they'll generally be handled in a different address space than the faulting code). Any context information will have to be looked up in the outgoing TSS:
Code: Select all
epi_ptr=&((struct TSS*)(BaseAddress(currTSS()->backLink))->eip);
Re:handling exceptions with taskgates
Posted: Mon Oct 18, 2004 6:33 am
by Brendan
Hi,
aladdin wrote:
I read in intel manual that using taskgates is more interestiong than intgates since the task context is automatically saved while calling exceptions
so I did a simple test with GPF exception, and it seems to work, but I have a little problem :
when the exception is called for the first time, everything is ok, but when it is called again, it doesn't work
I thing this is due to the fact that EIP is saved to its tss, so how can I do to make EIP re-point to the beginning of my GPF handler code ?
Because the interrupt handler is running as a seperate task, you have to do something like:
Code: Select all
exception_handler:
/* code to handle exception goes here */
jmp next_thread:0
jmp exception_handler
It looks really strange because the CPU will return from "jmp next_thread:0" on the next exception (almost like the jump is a call). Typically the "jmp next_thread:0" would be done by your scheduler, which looks more sensible:
Code: Select all
exception_handler:
/* code to handle exception goes here */
call find_another_task_to_run_and_switch_to_it
jmp exception_handler
While task gates do have plenty of overhead, they are also the ONLY way you can reliably handle some exceptions (e.g. double fault). In this case the overhead is irrelevant, as double faults shouldn't be generated often...
Cheers,
Brendan
Re:handling exceptions with taskgates
Posted: Mon Oct 18, 2004 7:59 am
by Pype.Clicker
hmm ... that 'jmp task' thingy looks messy to me.
The interrupt handler called by a taskgate should be terminated using "IRETD", which will detect the fact we're in a nested task (NT bit, iirc) and perform the task return, clear the 'Busy' bit in the handler's descriptor, so that the handler can be called again.
If you attempt to do something like "jump to next task", you'll clear the handler too, but you also leave the caller (faulty) task busy, so any attempt to return to it will be going wrong ...
Re:handling exceptions with taskgates
Posted: Mon Oct 18, 2004 8:45 am
by Brendan
Hi,
Pype.Clicker wrote:
The interrupt handler called by a taskgate should be terminated using "IRETD", which will detect the fact we're in a nested task (NT bit, iirc) and perform the task return, clear the 'Busy' bit in the handler's descriptor, so that the handler can be called again.
You're right - for exception handlers that return to the task that was interrupted (and IRQ handlers) it should be:
Code: Select all
exception_handler:
/* code to handle exception goes here */
iretd
jmp exception_handler
Which actually looks worse!
To jump to a different task (ie. not the one that was interrupted) you have to clear the interrupt task's busy bit in it's TSS segment descriptor (unless you never want to run the interrupted task again).
Code: Select all
exception_handler:
/* code to handle exception goes here */
clear_interrupted_task_busy_bit();
jmp new_task:0
jmp exception_handler
Sorry about my mistake - I used hardware task switching for a kernel about 8 years ago where the only task gate was used for the double fault handler. The double fault handler terminated the interrupted task (and didn't care about returning to it).
Cheers,
Brendan
Re:handling exceptions with taskgates
Posted: Mon Oct 18, 2004 11:18 am
by Pype.Clicker
no! no "jmp exception handler" stuff is required. The TSS isn't modified by a return, so if the handler task isn't switched off, its TSS will still hold the handler state for the next run ...
Re:handling exceptions with taskgates
Posted: Mon Oct 18, 2004 11:57 am
by Brendan
Hi,
Pype.Clicker wrote:
no! no "jmp exception handler" stuff is required. The TSS isn't modified by a return, so if the handler task isn't switched off, its TSS will still hold the handler state for the next run ...
It does look wrong, but call/retf, <int>/iret and jmp are all closely related. The only differences are the busy bit and the NT flag.
For e.g.:
Code: Select all
exception_handler:
/* initialize anything here */
.next_exception:
/* code to handle exception goes here */
iretd
jmp .next_exception
See "Section 6.3 Task Switching" of Intel's "IA-32 Intel Architecture Software Developer?s Manual Volume 3: System Programming Guide", where the steps involved for all types of task switch are detailed (with any differences between task switch types noted), and the paragraph which immediately follows the list of steps:
"The state of the currently executing task is always saved when a successful task switch occurs. If the task is resumed, execution starts with the instruction pointed to by the saved EIP value, and the registers are restored to the values they held when the task was suspended."
Cheers,
Brendan
Re:handling exceptions with taskgates
Posted: Tue Oct 19, 2004 3:28 am
by Pype.Clicker
hmm ... yup, now i remember ...
Well, the 'trick' pioneers (like Tran/Renaissance) have used was to load TR with a "dummy" or "trash" TSS right before the IRET. That way, the 'handler' TSS was kept clean and the handler context wasn't altered in any way (so it's not required to re-load any register at the handler's prologue).
Code: Select all
handler:
...
mov ax,[handler_tss+backlink]
mov [trash_tss+backlink],ax
ltr TRASH_TSS_SELECTOR
iretd
Re:handling exceptions with taskgates
Posted: Mon Jan 31, 2005 4:53 am
by Vianney Rancurel
Have a look in LSE/OS since it uses taskgates for task switching. You're right, it is much cleaner using this.
Re:handling exceptions with taskgates
Posted: Mon Jan 31, 2005 6:32 pm
by mystran
My humble opinion is that task-gates are absolutely useless, and TSS in general is only useful for specifying the kernel stack location. YMMV.
Re:handling exceptions with taskgates
Posted: Tue Feb 01, 2005 3:33 am
by Pype.Clicker
there is at least one exception that *requires* task gates: the stack fault. Double fault will also benefit of a task gate as it gives a "fresher" state.
Note that depending on your framework, you may never see a stack fault, but if you do (e.g. have appliable limits on a kernel stack segment), you'll have no choice but using a task gate.