## System Calls and Traps

See also system_calls

### Overview

Calls to the system must cross the user-kernel protection barrier. The barrier is hardware enforced. The i386 architecture has 4 levels of protection, ring 0 through 3. Nt uses ring 0 for the kernel and ring 3 for the user. The other rings are not used. Call gates are flow-of-control constructs vectoring through the IDT. According to the software people, IDT stands for Interrupt Dispatch Table (see Solomon's Inside Windows NT); according to the hardware people, it stands for Interrupt Descriptor Table. This table is pointed to by a hardware register in the I386 called the IDTR, the Interrupt Descriptor Table Register. Call gates include the interrupt, the trap, the task gate and the call gate. We are most interested here in the int 3 and int 2e traps. Traps differ from interrupts in that interrupts disable all interrupts on occurance, traps do not, hence leading to the situation of double-traps.

Are int 3 and int 2e traps or interrupts? Is a double trap an interrupt? Is it the same as a double fault?

### call gates

- far pointers are 48 bits, 16 bits segment pointer and 32 bits offset.
- a segment pointer points to a segment descriptor, a 64 bit structure in either the LDT or GDT
- the S bit in the segment descriptor identifies it as either a code/data segment descriptor, or a system descriptor,
- a system descriptor is identified in its type field as one of 16 different kinds, including a call gate.
- a call w. to a far pointer, where the segment pointer points to a call gate, invokes the call gate
- a call gate includes the segment and offset for the new CS and EIP, and so the offset given in the call instruction is ignored.

### traps

- interrupts and exceptions are referred to the IDT, Interrupt Descriptor Table, whose base is set by the IDTR, a register.
- there are 256 entries in the IDT, each a segment descriptor.
- The segement descriptors allowed in the IDT are limited to task-gate, interrupt-gate or trap-gate.
- exceptions are either faults, traps or aborts. a fault restarts at the faulting address. a trap restarts and the following address. an abort has no reliable restarting address.
- interrupts are either internal or external. the external interrupts are masked by EFLAGS.IF, the internal interrupts are not.
- Interrupts clear the IF flag. Exceptions leave the IF flag unchanged.

### Exhibits

- KDSESSION

### The Details

The Interrupt Descriptor Table should be seen in the context of two other tables, the Global Descriptor Table and the Local Descriptor, in that each is a vector of Descriptors. The descriptors of the IDT are Gate Descriptors. The GDT and LDT can also hold segment descriptors. The GDT is pointed to by the hardware register GDTR, and the LDT is pointed to by the hardware register LDTR. The gate descriptor format is:

1. 16 bits selector
2. 16 bit offset 15 ... 0
3. 16 bit offset contiuned 31 ..16
4. 16 bits of flags:
   1. P bit: 0 invalid/1 valid
   2. DPL (2 bits): descriptor privilege level
   3. one bit equal to 0
   4. Type (4 bits):
      - 4 = i286 Call Gate
      - 5 = i286/i486 Task Gate
      - 6 = i286 Interrupt Gate
      - 7 = i286 Trap Gate
      - C = i486 Call Gate
      - E = i486 Interrupt Gate
      - F = i486 Trap Gate
   5. Byte of "word count" - lowest 5 bits are depth of call stack, in case of a Call Gate only.

Given the little endianess of intel, here's a sample entry with interpretation:

      00084374 8014ee00

Flags are ee00, this is a valid, DPL level 3 (least privileged), i486 Interrupt Gate. The target offset is 0x8014,4374, using selection 8.

Intel protection lets data access down towards less privileged segements and gates upwards toward more privileged code. I do not know what the DPL level 3 indicates: for certain that anyone can vector through this trap. But now do levels change?

These are virtual addresses. The `!pcr` KD command will display the descriptor registers. Apparantly the IDT is located staticly in kernel memroy around 0x80036400, at least its been seen twice at that location.

The following exhibit shows a remote kernel debug setup, with the target halted by ^C.

### Author

Burton Rosenberg
11:28 AM 9/28/98

### Exhibits

- ### KD Session

      kd> !pcr
      PCR Processor 0 @ffdff000
              NtTib.ExceptionList: 8014f09c
                  NtTib.StackBase: 8014f380
                 NtTib.StackLimit: 8014c3f0
               NtTib.SubSystemTib: 00000000
                    NtTib.Version: 00000000
                NtTib.UserPointer: 00000000
                    NtTib.SelfTib: 00000000

                          SelfPcr: ffdff000
                             Prcb: ffdff120
                             Irql: 0000001c
                              IRR: 00000000
                              IDR: ffff22e8
                    InterruptMode: 00000000
                              IDT: 80036400
                              GDT: 80036000
                              TSS: 8001d000

                    CurrentThread: 8014c1b0
                       NextThread: 00000000
                       IdleThread: 8014c1b0

      *** Bad IOCTL request from an extension [1]

      kd> dd 0x80036400
      80036400  00083f64 80148e00 000840ac 80148e00
      80036410  005812de 00008500 00084374 8014ee00
      80036420  000844c8 8014ee00 00084604 80148e00
      80036430  0008475c 80148e00 00084c78 80148e00
      80036440  00501338 00008500 00084fb8 80148e00
      80036450  000850b8 80148e00 000851dc 80148e00
      80036460  000854cc 80148e00 000856cc 80148e00
      80036470  00086078 80148e00 000863e4 80148e00

      kd> u 0x080144374
      ntoskrnl!KiTrap03:
      80144374 6a00             push    0x0
      80144376 66c74424020000   mov     word ptr [esp+0x2],0x0
      8014437d 55               push    ebp
      8014437e 53               push    ebx
      8014437f 56               push    esi
      80144380 57               push    edi
      80144381 0fa0             push    fs
      80144383 bb30000000       mov     ebx,0x30
      kd>

- ### Interrupt Descriptor Table

  Either `!pcr` or the `r idtr` can be used to find the IDT's location. The format of the selectors (gates), when displayed as two double words, is:

      	[segment sel | offset 15..0 ] [ offset 31:16 | info ]

  where info is:

      	P:1 DPL:2 (00101 | 0D110 | 0D111) 0x00

  where P is 1 if Present, DPL is the Descriptor Privlege Level, D is 1 for a 32 bit gate, 0 for a 16 bit gate (?), and 110 signals an interupt gate, or 111 signals a trap gate, or 101 a task gate.

      kd> dd idtr
      80036400  00085034 80148e00 0008517c 80148e00
      80036410  005812de 00008500 00085444 8014ee00
      80036420  00085598 8014ee00 000856d4 80148e00
      80036430  0008582c 80148e00 00085d48 80148e00
      80036440  00501338 00008500 00086088 80148e00
      80036450  00086188 80148e00 000862ac 80148e00
      80036460  0008659c 80148e00 0008679c 80148e00
      80036470  00087194 80148e00 00087528 80148e00
      kd> dd
      80036480  00087628 80148e00 0008773c 80148e00
      80036490  00a07528 80148500 00087528 80148e00
      800364a0  00087528 80148e00 00087528 80148e00
      800364b0  00087528 80148e00 00087528 80148e00
      800364c0  00087528 80148e00 00087528 80148e00
      800364d0  00087528 80148e00 00087528 80148e00
      800364e0  00087528 80148e00 00087528 80148e00
      800364f0  00087528 80148e00 00087528 80148e00
      kd> dd
      80036500  00080000 00000000 00080000 00000000
      80036510  00080000 00000000 00080000 00000000
      80036520  00080000 00000000 00080000 00000000
      80036530  00080000 00000000 00080000 00000000
      80036540  00080000 00000000 00080000 00000000
      80036550  00084586 8014ee00 00084670 8014ee00
      80036560  00084780 8014ee00 0008533c 8014ee00
      80036570  00084100 8014ee00 00087528 80148e00
      kd> dd
      80036580  00084ffc 80018e00 00087b44 80678e00
      80036590  00083844 80148e00 0008384e 80148e00
      800365a0  00089dc4 805f8e00 00083862 80148e00
      800365b0  0008386c 80148e00 00083876 80148e00
      800365c0  00080a18 80018e00 0008388a 80148e00
      800365d0  00080ba4 80628e00 00080a84 806f8e00
      800365e0  00087dc4 80678e00 000838b2 80148e00
      800365f0  00081dc4 806e8e00 00081404 806f8e00