KTSS and KTSS64

There is, of course, nothing secret about the Task State Segment (TSS). It is perhaps as well, though, to have Microsoft’s representation handy and to take it as an opportunity to note some architectural detail.

Windows—even the sort that ran on DOS for long after Microsoft said—has never made much use of the processor’s built-in support for multi-tasking. As Intel itself put it, as long ago as the 386 DX Microprocessor Programmer’s Reference Manual,

Use of the multitasking mechanism is optional. In some applications, it may not be the best way to manage program execution.

Taking Intel’s option to “perform task switching in software” does not make the TSS redundant. Even when the TSS is not used to switch tasks, one TSS is still needed because the processor retains the notion of executing a current task and looks to the current TSS for certain properties of this task. This is true even for the amd64 architecture which tends to discard (or at least render trivial) 80386 features that programmers seem not to have wanted. Again from Intel, though now from the Intel 64 and IA-32 Architectures Software Developer’s Manual: “Although hardware task-switching is not supported in 64-bit mode, a 64-bit task state segment must exist.”

Hardware task-switching is not completely ignored by 32-bit Windows, but the use is minimal. One TSS for each processor serves all of that processor’s ordinary execution of Windows code. Switching through task gates is kept just to two difficult interrupts by the kernel: the Non-Maskable Interrupt (0x02) and the Double Fault (0x08). Each of these has its own TSS, which each has a dedicated GDT selector (0x0058 and 0x0050, respectively). The HAL in version 4.0 and higher adds to this for the Machine Check exception (0x12), using yet another dedicated GDT selector (0x00A0). The TSS for ordinary execution also has its own GDT selector (0x0028) but most access to it, notably for editing, is through an address that is kept in the KPCR (as the TSS member at offset 0x40).

Documentation Status

Perhaps because the KTSS and KTSS64 structures just model things that are anyway documented by Intel, Microsoft seems never to have got round to documenting them. Microsoft’s name for its representation of the 32-bit TSS is revealed in a C-language type definition in the NTDDK.H from as far back as the Device Driver Kit (DDK) for Windows NT 3.51, but the definition there is only of an opaque type and seems likely to have been provided only for neatness in the C-language definition of the KPCR which, of course, keeps a pointer to a KTSS. The first known publication of a C-language definition is in the NTOSP.H from an Enterprise edition of the Windows Driver Kit (WDK) for Windows 10.

Layout

In the tables that follow, names, types and offsets are reconstructed from type information in symbol files that Microsoft publishes for the kernel. As noted above, the 32-bit and 64-bit structures differ so much that the layouts are better presented separately.

32-Bit Windows (i386)

Symbol-file type information for the KTSS is first available for Windows 2003 SP3. What’s shown for earlier versions is something of a guess, being inferred by inspecting earlier versions for what use they make of the KTSS and either accounting for differences or assuming continuity For instance, since the kernel from version 3.10 allows only 0x206C bytes for each TSS, with the I/O permission bitmap beginning at offset 0x68, it is inferred that although version 3.10 cannot have the DirectionMap and IntDirectionMap that are known from symbol files for later versions, probably everything else that’s known for later versions persists without change.

Offset (x86) Definition Versions
0x00
USHORT Backlink;
all
0x02
USHORT Reserved0;
all
0x04
ULONG Esp0;
all
0x08
USHORT Ss0;
all
0x0A
USHORT Reserved1;
all
0x0C
ULONG NotUsed1 [4];
all
0x1C
ULONG CR3;
all
0x20
ULONG Eip;
all
0x24
ULONG NotUsed2 [9];
5.0 only
ULONG EFlags;
5.1 and higher
0x28
ULONG Eax;
5.1 and higher
0x2C
ULONG Ecx;
5.1 and higher
0x30
ULONG Edx;
5.1 and higher
0x34
ULONG Ebx;
5.1 and higher
0x38
ULONG Esp;
5.1 and higher
0x3C
ULONG Ebp;
5.1 and higher
0x40
ULONG Esi;
5.1 and higher
0x44
ULONG Edi;
5.1 and higher
0x48
USHORT Es;
all
0x4A
USHORT Reserved2;
all
0x4C
USHORT Cs;
all
0x4E
USHORT Reserved3;
all
0x50
USHORT Ss;
all
0x52
USHORT Reserved4;
all
0x54
USHORT Ds;
all
0x56
USHORT Reserved5;
all
0x58
USHORT Fs;
all
0x5A
USHORT Reserved6;
all
0x5C
USHORT Gs;
all
0x5E
USHORT Reserved7;
all
0x60
USHORT LDT;
all
0x62
USHORT Reserved8;
all
0x64
USHORT Flags;
all
0x66
USHORT IoMapBase;
all
0x68
KIIO_ACCESS_MAP IoMaps [1];
all
0x208C
UCHAR IntDirectionMap [0x20];
3.50 and higher

Among other things, the C-language definition in NTOSP.H shows that Microsoft has the convenience of a type definition, KINT_DIRECTION_MAP, for a 0x20-byte array that’s used as an interrupt direction map.

The KiIoAccessMap structure

Offset Definition Versions
0x00
UCHAR DirectionMap [0x20];
3.50 and higher
0x20
UCHAR IoMap [0x2004];
all

 

64-Bit Windows (amd64)

 

Offset (x86) Definition Versions
0x00
ULONG Reserved0;
 
0x04
ULONG64 Rsp0;
 
0x0C
ULONG64 Rsp1;
 
0x14
ULONG64 Rsp2;
 
0x1C
ULONG64 Ist [8];
 
0x5C
ULONG64 Reserved1;
 
0x64
USHORT Reserved2;
 
0x66
USHORT IoMapBase;