The TSS holds ring-0 stack pointer and I/O map base for privilege switches on older multitasking models. Even on modern kernels, a minimal TSS is required so IST or ring transitions know which stack to use on interrupts from ring 3. For example, the x86 Linux per-CPU TSS mainly stores the ring-0 RSP for double-fault stacks.
Minimal fields
nasm
Loading…
TR register: Points to TSS selector in GDT (busy bit managed by CPU)
IST entries (64-bit TSS): Alternate stacks for critical exceptions
I/O bitmap offset: Set to TSS limit to disable port traps if unused
Hardware task switching is obsolete; software context switch replaces it
Busy bit rules
The CPU sets the TSS busy bit when loaded via LTR; do not manually edit it unless you know the double-fault implications. For minimal kernels, only ESP0 and SS0 fields matter; zero the rest. Place the TSS in memory that stays mapped after paging. The TR register holds the selector; verify it points to a system segment type 0x9 (available TSS) in the GDT.
Why for this exercise
You will pack a TSS GDT descriptor, compute exactly where the CPU lands on a ring-3-to-ring-0 interrupt (SS0:ESP0 minus the pushed frame), and evaluate the I/O permission bitmap. This exercise requires a valid ESP0 and SS0 for future ring-3 entry or interrupt stack switching.
Implement TSS descriptor packing, ring-3 to ring-0 stack switching, and I/O permission bitmap checks in C, driven by a command script on stdin.
Protocol (all numbers in hex):
desc <base> <limit>
Pack the 8-byte TSS system descriptor (access byte 0x89: present,
ring 0, 32-bit available TSS; same base/limit split as a code/data
descriptor) and print "TSSDESC=0x%016llX SEL=0x0028". The fixed
selector 0x0028 corresponds to GDT index 5.
switch <esp0> <ss0> <user_cs> <user_ss> <user_esp> <eip> <eflags>
Simulate a ring-3 interrupt: the CPU loads SS0:ESP0 from the TSS and
pushes the ring-3 SS, ESP, EFLAGS, CS, EIP frame (five dwords).
Print "ESP=0x%08llX SS=0x%04llX" for the loaded stack pointer
(esp0 - 20) and stack segment, then
"FRAME SS=0x%04llX ESP=0x%08llX EFLAGS=0x%08llX CS=0x%04llX EIP=0x%08llX"
for what lands on the new stack.
iomap <off> <base_port> <bm_lo> <bm_hi>
Configure the I/O permission bitmap: offset within the TSS, base
port, and two 64-bit bitmap words covering 128 ports. Print
"IOMAP=DISABLED ALL_PORTS_TRAPPED" when off >= the last desc limit
(bitmap out of range, every port denied), otherwise
"IOMAP=ENABLED BASE=0x%llX".
io <port>
Check one port against the bitmap: ports below base or 128 or more
above it, or any bit set in the bitmap words, print "TRAPPED";
clear bits print "PERMITTED". Print "UNCONFIGURED" if iomap has not
run, "TRAPPED" if the bitmap is disabled.
Process every command on stdin until EOF, printing one line per command.