Hi,
Could any one told me what's the difference between the Source of task switch initiation:
CALL instruction
IRET instruction
JMP instruction
Task gate in IDT
I am very confused about these.
About Task Switch and TSS
Re: About Task Switch and TSS
Hi,
IRET instruction: Expects current task's "busy bit" to be set and clears it (similar to RETF). Sets destination task's "busy bit".
JMP instruction: Clear's previous task's "busy bit" and sets destination task's busy bit.
Task gate in IDT: Says which "TSS descriptor" (in the GDT) to use for the task switch
Of course I don't actually use any of this. It's better/faster/easier to use software task switching for switching between processes/threads; and (at least for micro-kernels) easier to make sure exception handlers don't crash (and avoid the need to bother with double fault exception handlers completely).
Also note that because tasks are not re-entrant (any attempt to switch to a task that has its "busy bit" set results in a general protection fault); it's extremely difficult to use hardware task switching in a multi-CPU scenario. For a simple example, if you have a task gate for the double fault exception handler, then you'll need a different TSS (and different "TSS descriptor") for each CPU, just in case 2 or more CPUs happens to trigger a double fault at the same time (otherwise, the first CPU to use that task sets the task's "busy bit" and the second CPU gets a general protection fault while attempting to start the double fault handler, which results in a triple fault/reset).
Cheers,
Brendan
CALL instruction: Leaves previous task's "busy bit" set, and also sets destination task's "busy bit". I think it also sets the destination task's "back link" field (as a way of remembering which task to "RETF" to) but can't quite remember.watermirror wrote:Could any one told me what's the difference between the Source of task switch initiation:
IRET instruction: Expects current task's "busy bit" to be set and clears it (similar to RETF). Sets destination task's "busy bit".
JMP instruction: Clear's previous task's "busy bit" and sets destination task's busy bit.
Task gate in IDT: Says which "TSS descriptor" (in the GDT) to use for the task switch
The difference between different types of task switching is mostly how it effects the "busy bit" for both tasks. In general, for hardware task switching between processes/threads you should never need to use anything except "JMP". For using hardware task switching to ensure that exception handlers are started with a secure state (e.g. possibly for double fault and NMI, even if the OS uses software task switching) there's no choice - you have to have a TSS somewhere, a "TSS descriptor" in the GDT that says where the TSS is, plus a "task gate" in the IDT so the CPU knows its not a normal interrupt/trap gate.watermirror wrote:I am very confused about these.
Of course I don't actually use any of this. It's better/faster/easier to use software task switching for switching between processes/threads; and (at least for micro-kernels) easier to make sure exception handlers don't crash (and avoid the need to bother with double fault exception handlers completely).
Also note that because tasks are not re-entrant (any attempt to switch to a task that has its "busy bit" set results in a general protection fault); it's extremely difficult to use hardware task switching in a multi-CPU scenario. For a simple example, if you have a task gate for the double fault exception handler, then you'll need a different TSS (and different "TSS descriptor") for each CPU, just in case 2 or more CPUs happens to trigger a double fault at the same time (otherwise, the first CPU to use that task sets the task's "busy bit" and the second CPU gets a general protection fault while attempting to start the double fault handler, which results in a triple fault/reset).
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: About Task Switch and TSS
Figured I would just ask this here since we are on the topic.
If I were to use a task gate for something that always needs to have a known good stack (like IST mechanism in long mode) like NMI, the old cs/eip/ss/esp is not pushed onto the stack obtained from the new TSS if it's using the task gate mechanism correct?
If I wanted that, I would need to use the back-link selector (assuming int got us here) and read it out manually correct?
If I were to use a task gate for something that always needs to have a known good stack (like IST mechanism in long mode) like NMI, the old cs/eip/ss/esp is not pushed onto the stack obtained from the new TSS if it's using the task gate mechanism correct?
If I wanted that, I would need to use the back-link selector (assuming int got us here) and read it out manually correct?
Re: About Task Switch and TSS
Hi,
Of course (due to interactions between NMI and SMI/SMM) there's no way to prevent a second NMI from interrupting while you're handling a previous NMI, and hardware tasks aren't re-entrant, so it's extremely difficult to use a task gate for NMI 100% safely (even for single-CPU).
Cheers,
Brendan
Correct. The only thing the CPU pushes on the stack is the exception's error code (but only if the exception has one - NMI doesn't).devsau wrote:If I were to use a task gate for something that always needs to have a known good stack (like IST mechanism in long mode) like NMI, the old cs/eip/ss/esp is not pushed onto the stack obtained from the new TSS if it's using the task gate mechanism correct?
Yes - use your NMI handler task's backlink to find the previous task's TSS descriptor in the GDT, then use that to find the previous task's TSS.devsau wrote:If I wanted that, I would need to use the back-link selector (assuming int got us here) and read it out manually correct?
Of course (due to interactions between NMI and SMI/SMM) there's no way to prevent a second NMI from interrupting while you're handling a previous NMI, and hardware tasks aren't re-entrant, so it's extremely difficult to use a task gate for NMI 100% safely (even for single-CPU).
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: About Task Switch and TSS
Brendan wrote:Hi,
Correct. The only thing the CPU pushes on the stack is the exception's error code (but only if the exception has one - NMI doesn't).devsau wrote:If I were to use a task gate for something that always needs to have a known good stack (like IST mechanism in long mode) like NMI, the old cs/eip/ss/esp is not pushed onto the stack obtained from the new TSS if it's using the task gate mechanism correct?
Yes - use your NMI handler task's backlink to find the previous task's TSS descriptor in the GDT, then use that to find the previous task's TSS.devsau wrote:If I wanted that, I would need to use the back-link selector (assuming int got us here) and read it out manually correct?
Of course (due to interactions between NMI and SMI/SMM) there's no way to prevent a second NMI from interrupting while you're handling a previous NMI, and hardware tasks aren't re-entrant, so it's extremely difficult to use a task gate for NMI 100% safely (even for single-CPU).
Cheers,
Brendan
thank you again.