[翻译]Interrupt Descriptor Table–IDT

中断描述附表

中断描述附表是 x86 结构处理器用来实现中断向量表而使用的一种数据结构。处理器使用中断描述附表以便对运行过程中的中断与异常做出正确的响应。
下面所描述的中断描述附表主要应用于 x86 结构与 AMD64 结构,其他架构的处理器与此类似,但是细节上有些不同。
硬件中断、软件中断和异常(统称为中断)会触发对中断描述附表的使用。中断描述附表包含 256 个表项,其中前 32 个表项(0-31 or 0-1F)被处理器保留,用来处理运行过程中产生的异常。
 
实模式
在 8086 处理器下,中断描述附表位于内存的固定位置 0x0000 到 0x03FF,并且大小也是固定的:256个表项 * 4 byte = 1024 bytes = 1K。在 80286 及后来的处理器中,中断描述附表的大小与位置可以像其在保护模式下那样被改变,但是结构没有变化。一个实模式下的指针包含:16 位的段基址和 16 为的段内偏移。一个实模式的地址被扩展为 20 位(段基址左移 4 位然后加上段内偏移),中断处理句柄的地址被限制在可用内存最开始的 1M 空间内。最开始的 32 个表项被处理器保留,用来处理内部异常,但是如果使用可编程中断控制器,硬件中断的处理句柄可以位于其他任何表项。
在 x86 实模式下最常用的一个中断就是 BIOS 的 10 号中断,10 号中断主要用来处理在屏幕上画点或者设置屏幕分辨率等屏幕操作。
 
保护模式
在保护模式下,中断描述附表是一个由 8-byte 组成的数组(数组中一项占八个字节),这个数组在连续存储,并且通过中断向量进行索引。中断描述附表可能是中断们、陷阱门、任务门。中断或者陷阱门指针指向的可执行代码地址有段基址加段内偏移决定,其中段基址在全局描述附表或者局部描述附表中指定。中断门与陷阱门的主要区别是:中断门会禁止处理器处理其他硬件中断,特别适合服务于硬件中断。陷阱门并不会禁止硬件中断,主要用来处理软件中断与异常。最后,任务门会引起当前活动的任务状态段切换,这主要利用硬件的任务切换机制,从而可以高效的切换程序、线程或者进程。
在保护模式下,中断描述附表可能位于物理内存的任何地方。处理器有一个特殊的寄存器 IDTR,用来存储中断描述附表的起始地址与大小。当产生一个中断时,处理器会将中断号乘以8然后加到中断描述符表的基址上。然后验证产生的结果地址位于中断描述附表内部(利用表的起始地址与长度)。如果产生的地址没有位于中断描述符表的内部,将产生一个异常。如果产生的地址正确,存储在描述附表中的 8-byte 的描述符会被 CPU 加载并执行。
常用的中断描述附表的大小是 2K:256 个表项 * 8byte = 2048 byte = 2K。没有必要使用所有 256 个表项,但是最好从低地址到高地址逐个使用,并正确设置可以用长度(IDTR要使用)。0-31 个表项被 Intel 系列的处理器保留用来处理异常(保护错误、缺页异常等等)。虽然目前处理器只使用了 18 个表项,但是将来的处理器可能会使用剩下的表项(32 个中剩下的),因此为了避免引起兼容性问题,程序最好不要使用前 32 个表项。
 
硬件产生的异常列表
INT_NUM Short Description PM
0x00 Division by zero
0x01 Debugger
0x02 NMI
0x03 Breakpoint
0x04 Overflow
0x05 Bounds
0x06 Invalid Opcode
0x07 Coprocessor not available
0x08 Double fault
0x09 Coprocessor Segment Overrun (386 or earlier only)
0x0A Invalid Task State Segment
0x0B Segment not present
0x0C Stack Fault
0x0D General Protection
0x0E Page Fault
0x0F reserved
0x10 Math Fault
0x11 Alignment Check
0x12 Machine Check
0x13 SIMD Floating-Point Exception

钩子
 
有些 Windows 应用程序 hook 了对中断描述附表的调用。这主要用来在内核态下开发驱动程序时向中断描述附表中添加自己的处理代码。微软从来都没有官方声明支持这种用法,但是也没有利用代码禁止这种用法。在 64 位版本的 Windows 中,已经禁止了这种用法,如果尝试在内核态使用 hook,会引发一个系统错误。
 
===========================================================================================================
中断描述附表是 i386 处理器架构的特有结构。它是实模式下的中断向量表(IVT)在保护模式下的对应结构,目的使处理器可以定位中断服务例程(Interrupt Service Routines-ISR)。中断描述附表在数据结构上类似于全局描述附表。中断描述附表一般被称作门,包括:中断门、任务门和陷阱门。
 
位置与大小
中断描述附表的位置(包含起始地址与大小)被存放在 CPU 的 IDTR 寄存器中,可以通过汇编指令 LIDT 与 SIDT 来设置或读取。
IDTR
Name Bit Description
0 0..2 These bits are ignored by the CPU and should be 0.
Limit 0..15 Defines the length of the IDT in bytes (minimum value is 100h, a value of 1000h means 200 interrupts).
Base 16..47 This 32 bits are the physical address where the IDT starts (INT 0)

 

这个结构与全局描述附表类似,除了:
* 中断描述附表使用了第一个表项,而全局描述符表没有使用。
* 中断描述附表有 256 个表项,每个对应一个中断。
* 中断描述附表可以少于 256 个表项,或者多余 256 个表项。多余的表项被忽略。当产生没有索引的中断(不过是硬件中断还是软件中断)或者异常时, CPU 会产生一个保护错误,报告访问了中断描述附表中不存在的表项。因此,至少应该保证中断描述附表中有足够的表项,保证保护错可以捕获并处理。
 
结构

中断描述附表中多个表项,每个表项的实际大小为 8-byte,结构如下:

struct IDTDescr{
   uint16 offset_1; // offset bits 0..15
   uint16 selector; // a code segment selector in GDT or LDT
   uint8 zero;      // unused, set to 0
   uint8 type_attr; // type and attributes, see below
   uint16 offset_2; // offset bits 16..31
};

偏移量是一个 32 位的值,被分成了两个部分。选择子是一个 16 位的值,必须是全局描述附表中的一个合法选择子。

type_attr 信息如下:

  7                           0
+---+---+---+---+---+---+---+---+
| P | Priv  | S |    GateType   |
+---+---+---+---+---+---+---+---+

 

位信息如下:

中断描述符表项, 中断门

Name Bit Full Name Description
Offset 48..63 Offset 16..31 Higher part of the offset.
P 47 Present can be set to 0 for unused interrupts or for Paging.
DPL 45,46 Descriptor Privilege Level Gate call protection. Specifies which privilege Level the calling Descriptor minimum should have. So hardware and CPU interrupts can be protected from beeing called out of userspace.
S 44 Storage Segment = 0 for interrupt gates.
Typ 40..43 Gate Type 0..3 Possible IDT gate types :
0b0101 0x5 5 80386 32 bit Task gate
0b0110 0x6 6 80286 16-bit interrupt gate
0b0111 0x7 7 80286 16-bit trap gate
0b1110 0xE 14 80386 32-bit interrupt gate
0b1111 0xF 15 80386 32-bit trap gate
0 32..39 Unused 0..7 Have to be 0.
Selector 16..31 Selector 0..15 Selector of the interrupt function (to make sense - the kernel's selector). The selector's descriptor's DPL field has to be 0.
Offset 0..15 Offset 0..15 Lower part of the interrupt function's offset address (also known as pointer).

I386 中断门

中断门用来指定中断服务程序。在保护模式下,当你写汇编指令 INT 50 时,CPU 在中断描述附表中查找第 50 个表项(位于 50 * 8 byte)。然后,中断门的段选择子与偏移量被加载。通过段选择子与偏移量可以调用中断服务程序。当遇到中断服务程序中的 IRET 指令时,CPU 返回原来的地址继续执行。当运行在 32 位模式下,而选择子是 16 位,在执行完中断服务程序后,CPU 会继续在 16 位保护模式下运行。如果想在执行完中断服务后仍然运行在 32 位模式,需要执行 032 IRET 指令,否则 CPU 无法知道是否返回 32 位模式(在栈中读取 32 位地址作为返回地址,而不是 16 位)。


type_attr Type
0b1110=0xE 32-bit interrupt gate
0b0110=0x6 16-bit interrupt gate

Here are some pre-cooked type_attr values people are likely to use (assuming DPL=0):

  • 32-bit Interrupt gate: 0x8E ( P=1, DPL=00b, S=0, type=1110b => type_attr=1000_1110b=0x8E)
 

I386 陷阱门


当属于陷阱门或者中断门的中断或者异常产生时,CPU 会在栈(EFLAGS,CS, IP)中存放放回信息,因此中断处理程序可以通过 IRET 指令返回。然后会执行对应门选择子的 segment:offset。对于某些异常,错误码也会压入栈中,需要在执行 IRET 前,将其 POP 出来。陷阱与异常相似,他们的描述子相同,只是类型不同。不同之处是:对于中断门,中断会禁用其他描述符表项直到 IRET 返回时。


type_attr Type
0b1111=0xf 32-bit trap gate
0b0110=0x7 16-bit trap gate


Here are some pre-cooked type_attr values people are likely to use (assuming DPL=0):

  • 32-bit Trap gate: 0x8F ( P=1, DPL=00b, S=0, type=1111b => type_attr=1000_1111b=0x8F)

Thus, Trap and Interrupt gate descriptors hold the following data (other than type_attr):

  • 16-bit selector of a code segment in GDT or LDT
  • 32-bit offset into that segment - address of the handler, where execution will be transferred
 

I386 任务门

在任务门情况下,描述符的偏移量部分没有使用,应该设置为 0。

当类型是任务门的中断或者异常发生时,任务会发生切换。


"A task gate in the IDT references a TSS descriptor in the GDT. A switch to the handler task is handled in the same manner as an ordinary task switch. (..) The link back to the interrupted task is stored in the previous task link field of the handler task's TSS. If an exception caused an error code to be generated, this error code is copied to the stack of the new task."

—Intel manual (vol.3 p.5-19)

"*NOTE* Because IA-32 tasks are not re-entrant, an interrupt-handler task must disable interrupts between the time it completes handling the interrupt and the time it executes the IRET instruction. This action prevents another interrupt from occurring while the interrupt task's TSS is still marked busy, which would cause a general-protection (#GP) exception."

—Intel manual


Choosing type_attr values: (See

type_attr Type
0b0101=0x5 task gate

For DPL=0, type_attr=0x85=0b0101

因此, TSS 选择子是在任务门下唯一需要的描述符。

Advantages over using trap/interrupt  gates:

  • The entire context of the interrupted task is saved automatically (no need to worry about registers)
  • The handler can be isolated from other tasks in a separate address space in LDT.
  • "A new tss permits the handler to use a new privilege level 0 stack when handling the exception or interrupt. If an exception or interrupt occurs when the current privilege level 0 stack is corrupted, accessing the handler through a task gate can prevent a system crash by providing the handler with a new privilege level 0 stack" --Intel manual

Disadvantage:

  • Saving the entire task context into TSS is slower than using a trap/interrupt gate (where the handler can save only what it needs).
    • Is it that much faster if the handler does PUSHAD or pushes registers one by one?
    • Does it make a difference, considering a non-dummy, non-trivial handler?

 

设置与存储

中断描述附表使用 LIDT 汇编指令来设置。操作数是中断描述附表的地址:


Byte: +---------------+---------------+ 0 | Size | +---------------+---------------+ +---------------+---------------+---------------+---------------+ 2 | Offset | +---------------+---------------+---------------+---------------+

偏移量是中断描述附表自己的虚拟地址。大小字段是描述附表的大小减一。这个结构可以通过 SIDT 指令,被再次存放到内存中。

IDT in IA-32e Mode (64-bit IDT)

 

When in long or compatibility mode (once the EFER.LME flag has been set) the IDT's structure changes slightly. The IDTR structure's (used by LIDT and SITD) base field changes to 64-bits to allow the IDT to reside anywhere in memory, and each entry in the IDT grows by 64-bits. The first dword is the high bits of the address, while the second is zero.

IDTR
Offset Size Description
0 2 Limit - Maximum addressable byte in table
2 8 Offset - Linear (paged) base address of IDT
IDT Descriptor
Offset Size Description
0 2 Offset low bits (0..15)
2 2 Selector (Code segment selector)
4 1 Zero
5 1 Type and Attributes (same as before)
6 2 Offset middle bits (16..31)
8 4 Offset high bits (32..63)
12 4 Zero

posted @ 2010-11-24 21:25  Proteas  阅读(481)  评论(0编辑  收藏  举报