Task State Segment (TSS)

Task State Segment (TSS)

The Task State Segment (TSS) is a special data structure used in the x86 architecture to store information about a task. This includes the processor state, stack pointers for different privilege levels, the address of the page directory, and other important information required for task switching and handling interrupts in a protected mode operating system. It contains all the information the CPU needs to resume the execution of a previously interrupted task.

History

The concept of the TSS was introduced with the Intel 80286 processor. The 80286 was the first processor in the x86 family to support protected mode, a significant advancement over the earlier real mode, allowing for more robust memory management and protection features. The TSS and hardware task switching were integral parts of the protected mode enhancements.

Purpose of the TSS

  • Task Switching: It allows the CPU to switch between tasks quickly by saving the state of the current task and loading the state of the next task. This includes switching stack pointers, instruction pointers, and registers.
  • Hardware Context Switching: The TSS provides hardware support for context switching, enabling fast and efficient task transitions.
  • Protection and Privilege Management: It facilitates switching between tasks running at different privilege levels, enforcing protection and security within the operating system.

Structure of the TSS

The TSS is a special segment defined by the operating system and includes the following:

  1. General Registers: EAX, EBX, ECX, EDX, ESP, EBP, ESI, EDI.
  2. Segment Registers: ES, CS, SS, DS, FS, GS.
  3. Instruction Pointer (EIP): The address of the next instruction to be executed.
  4. EFLAGS Register: Contains the state of various flags that control CPU operations.
  5. Control Registers: CR3, which points to the page directory base register.
  6. LDT Segment Selector: Points to the Local Descriptor Table.
  7. I/O Map Base Address: Points to the I/O permission bit map.

The TSS also includes fields specific to the task such as the previous task link, a stack pointer (ESP) and segment selector (SS) for privilege levels 0, 1, and 2, and more.

The TSS structure in the x86 architecture is defined as follows:

struct tss_entry {
    uint32_t prev_tss;   // Previous TSS (if hardware task switching is used)
    uint32_t esp0;       // Stack pointer for ring 0
    uint32_t ss0;        // Stack segment for ring 0
    uint32_t esp1;       // Stack pointer for ring 1
    uint32_t ss1;        // Stack segment for ring 1
    uint32_t esp2;       // Stack pointer for ring 2
    uint32_t ss2;        // Stack segment for ring 2
    uint32_t cr3;        // Page directory base register
    uint32_t eip;        // Instruction pointer
    uint32_t eflags;     // Flags register
    uint32_t eax;        // General purpose registers
    uint32_t ecx;
    uint32_t edx;
    uint32_t ebx;
    uint32_t esp;        // Stack pointer
    uint32_t ebp;        // Base pointer
    uint32_t esi;        // Source index
    uint32_t edi;        // Destination index
    uint32_t es;         // Segment selectors
    uint32_t cs;
    uint32_t ss;
    uint32_t ds;
    uint32_t fs;
    uint32_t gs;
    uint32_t ldt;        // Local descriptor table selector
    uint16_t trap;       // Trap on task switch
    uint16_t iomap_base; // I/O map base address
} __attribute__((packed));
Fields of the TSS:
  • prev_tss: Link to the previous TSS (used for hardware task switching).
  • esp0, ss0: Stack pointer and stack segment for ring 0 (kernel mode).
  • esp1, ss1: Stack pointer and stack segment for ring 1.
  • esp2, ss2: Stack pointer and stack segment for ring 2.
  • cr3: Page directory base register, used for virtual memory management.
  • eip, eflags: Instruction pointer and flags register.
  • General Purpose Registers: eax, ecx, edx, ebx, esp, ebp, esi, edi.
  • Segment Selectors: es, cs, ss, ds, fs, gs.
  • ldt: Local descriptor table selector.
  • trap: Used to enable debugging on task switches.
  • iomap_base: I/O map base address for I/O port permissions.

Usage of the TSS

The TSS is used by the operating system's scheduler to manage multitasking. Here's a typical usage scenario:

  1. Task Initialization: The operating system initializes a TSS for each task and fills it with the appropriate values for the task's state.
  2. Loading the TSS: The operating system loads the TSS using the LTR (Load Task Register) instruction, which tells the CPU where to find the TSS for the current task.
  3. Task Switching: When a task switch is needed (e.g., due to a timer interrupt, I/O operation, or explicit request), the CPU saves the state of the current task in its TSS and loads the state of the next task from its TSS. This can be triggered by the JMP or CALL instruction to a task gate or through an interrupt or exception.

Example of Task Switching

  1. Current Task: The CPU is running Task A.
  2. Interrupt Occurs: A timer interrupt signals the need to switch to Task B.
  3. Save State: The CPU saves Task A's state (registers, stack pointer, instruction pointer) into Task A's TSS.
  4. Load New Task: The CPU loads Task B's state from Task B's TSS.
  5. Resume Execution: Task B resumes execution from the point where it was last interrupted.