The 80286 Task State Segment and Task Switching
Call gate descriptors are used for system calls
Interrupt gate descriptors are essentially a new interrupt vector table
Task state descriptors are used to save task state during task switching
Tasks
An example of a task is a process. An example of task switching is process switching.
A task consists of the following:
- One or more segments of executable task code
- One or more segments of data used by the task
- The stacks used by the task when executing at each privilege level
- The task’s LDT, which forms the task’s private local address space
- A Task State Segment (TSS)
Format of the Task State Segment
When a task is suspended, the CPU stores certain information about the task in the Task State Segment. When a previously suspended task is resumed, the CPU reads this information from the task’s TSS, restores the task to the state it was in when it was suspended, and then continues execution. The information stored in the TSS is defined by the CPU and is read and written by the CPU during task switching; it is not a data structure defined by the programmer.
A Task State Segment (TSS) consists of two parts:
-
Dynamic fields — the processor sets the values of these fields on every task switch:
1.1 General-purpose registers (EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI).
1.2 Segment registers (ES, CS, SS, DS, FS, GS)
1.3 Status register (EFLAGS)
1.4 Instruction pointer (EIP)
1.5 The selector of the previously executing task’s TSS segment (only updated when returning). -
Static fields — the processor reads these but never modifies them. These fields include:
2.1 The task’s LDT selector
2.2 _Page Directory Base Register (PDBR) (read-only when paging is enabled — the 80286 currently under discussion does not have this; it appears starting with the 80386)
2.3 Inner-stack pointers for privilege levels 0–2, one stack pointer per privilege level. Privilege level 3 does not need one, for two reasons: (1) when the current privilege level is 3, the stack pointer is stored in SS:SP; (2) when the current privilege level is not 3, the privilege level 3 stack pointer is copied into the current code’s stack.
2.4 The T-bit, which indicates whether the processor should raise a debug exception during a task switch.
2.5 The I/O map base address, describing which I/O ports (the kind accessed by IN/OUT instructions) the current task has permission to access.
Task Switching
A task switch performs the following steps:
-
Check that the current task is allowed to switch to the specified task. The data access rules are used to check the JMP or CALL instruction. The DPL field of the TSS descriptor or task gate must be less than or equal to the maximum of the CPL and the gate selector’s RPL field. Interrupts, exceptions, and IRET can switch to any task, regardless of the DPL of the target TSS descriptor or task gate.
-
Check that the target TSS descriptor exists and has a valid limit. By this point, all errors are considered to have occurred in the context of the outgoing task that initiated the task switch. Errors can be handled and the operation restarted, and are transparent to the application program.
-
Save the state of the current task. The processor uses the cached, invisible portion of the task register to locate the base address of the current task. The processor copies the register values into the current task’s TSS (EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, ES, CS, SS, DS, FS, GS, and the flags register EFLAGS). The EIP field is set to point to the instruction following the one that caused the task switch.
-
Load the new task’s selector into the task register, and mark the new task’s TSS descriptor as busy. Set the TS (task switched) bit in the MSW. The selector is obtained either from the instruction’s operand or from a task gate.
-
Load the new task’s state from its TSS and resume its execution. The registers loaded are the LDT register, the flags register (EFLAGS), the general-purpose registers EIP, EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, and the segment registers ES, CS, SS, DS, FS, and GS. Also PDBR (CR3). All errors detected here will occur in the context of the new task. To an exception handler, it appears as if the first instruction of the new task has not yet executed.
Note that, in any case, the old task’s state is always saved. If the task is re-executed, it will execute the instruction after the one that caused the task switch. When the task runs, all register values are restored.
Every task switch sets the TS (task switched) bit of the MSW (machine status word). The TS flag is important for systems with a coprocessor. The TS bit indicates that the coprocessor’s state may no longer match the current task’s state. Chapter 11 discusses the TS bit further.
Exception handlers that handle task-switch exceptions (those caused by cases 4 through 16 in Table 7-1) should be careful when performing the operation that loads the selector that caused the exception. Such an operation may trigger a second exception, unless the exception handler first inspects the selector and fixes the underlying problem.
The privilege level of the task about to execute is neither affected by nor constrained by the task that initiated the switch. Because each task has a separate address space and a different TSS, and because privilege-level rules can be used to prevent illegal TSS access, no privilege-level rules are needed to constrain the CPL across tasks. The new task executes at the privilege level specified by the RPL field of the CS selector, where CS is loaded from the TSS.
Direct and Indirect Task Switching
There are several ways to switch tasks:
- Direct switching: the current task executes a JMP or CALL, and the operand specifies a TSS descriptor.
- Indirect switching: the current task executes a JMP or CALL, and the operand specifies a task gate.
- An interrupt vector or exception vector in the IDT causes a switch to a new task.
- The current task executes an IRET instruction, with the NT flag set.
Setting aside interrupt-related mechanisms, there are two ways to switch tasks: direct (through the Task State Segment) and indirect (through a task gate, which in turn points to a Task State Segment).
The flow diagram for switching tasks through the Task State Segment is shown below:

The flow diagram for switching tasks through a task gate is shown below:

A task gate descriptor provides an indirect, protected way to access a TSS.
Format of the Task Gate Descriptor and Task State Segment Descriptor
A Task State Segment (TSS) is described by a Task State Segment descriptor (TSS descriptor). The structure of the TSS descriptor is as follows:

The format of a task gate descriptor is as follows:

Comments