TSS - Waaal/BobaOS GitHub Wiki

Task State Segment

A TSS is a struct that lives in memory. It holds information about the kernel stack.

TSS in protected mode (32bit)

In protected mode TSS is responsible for holding information such as the kernel stack pointer and segment. It also holds the General purpose registers, Segment Selectors, Instruction pointer, EFLAGS register and the Cr3. Important for us are the Kernel stack pointer (ESP0) and the kernel stack segment (SS0).

Whenever a system call in ring3 occurs, the CPU takes the ESP0 and SS0 values from the TSS and populates its stack registers with it. So basically it holds the kernel stack and when we are in ring3 and perform a interrupt and we change our ring level to 0 we know where the kernel stack is.

But important if, if we are currently working on a interrupt for a process and the process time ends and we change to a different process and this process also performs a interrupt we land in the same stack. To solve this problem each process has its own kernel stack. The TSS ESP0 values just needs to be swapped when we change process.

Important: The TSS is only needed in interrupts where a priviledge level change occure. So If we are in ring 0 and a interrupt occurs the TSS is not used and is not filled by the CPU.

TSS structure protected mode

4 Bytes Offset
SSP 0x68
IOPB (2byte (high)) 0x64
LDTR (2byte) 0x60
GS (2byte) 0x5C
FS (2byte) 0x58
DS (2byte) 0x54
SS (2byte) 0x50
CS (2byte) 0x4C
ES (2byte) 0x48
EDI 0x44
ESI 0x40
EBP 0x3C
ESP 0x38
EBX 0x34
EDX 0x30
ECX 0x2C
EAX 0x28
EFLAGS 0x24
EIP 0x20
CR3 0x1C
SS2 (2byte) 0x18
ESP2 0x14
SS1 (2byte) 0x10
ESP1 0x0C
SS0 (2byte) 0x08
ESP0 0x04
LINK (2byte) 0x00

LINK: The segment selector for the TSS of the previous task

SS0, SS1, SS2: Segment selectors to load stack for priviledge level change from ring 0 - 2

ESP0, ESP1, ESP2: Stack pointer load stack when priviledge level change from ring 0 - 2

IOPB: I/O Map Base address field for I/O port permission map

SSP: Shadow stack pointer

TSS in long mode (64bit)

TSS more info

The TSS is also needed for multitasking. Because each CPU core has its own TSS in a multitasking scenario.

TSS in a GDT

The TSS needs to have a entry in the gdt. The TSS entry is special, because the base and limit needs to be set to the start and size of the TSS.

Base = TSS start address.

Limit = TSS Length.

The Access Bytes look like this: 1110 1001 Special about this is that the bit 4 (Descriptor Type) is set to 0 which means this is a system segment and not a code or data segment.

Load the TSS

The tss needs to be loaded with the ltr instruction. The ltr instruction taks as argument the TSS GDT entry.

    mov ax, 0x28 	;0x28 = 00000000 00101000 = RPL = 0; TL = 0; Selected Index = 5 (At which index is the TSS entry in the GDT);
    ltr ax

Implementation

⚠️ **GitHub.com Fallback** ⚠️