2011年9月15日 星期四

Interrupt 中斷

Interrupt
可分為兩種
1. Synchronous: 由內部驅動, 例如system call, divide by zero, 此類又叫做exception
2. Asynchronous: caused by external , 例如device I/O, time ticks

x86 interrupt可分為index 0-255
0-31: processor interrupt, or exception
ex: 14 for page fault
32-255: 由軟體控制
32-47: device interrupt (IRQ) in JOS
int 0x80 for system call interrupt
ex: 
IRQ=0, INT=32, Timer interrupt
IRQ=1, INT=33, Keyboard interrupt


Interrupt Procedure
當interrupt發生時, 控制權轉移至kernel的interrupt handler, CPU register儲存到kernel stack (TSS), 然後執行interrupt handler. 執行完後resume program (iret instruction)
HW要如何知道執行甚麼?
A. interrupt descriptor table (IDT) 在開機時必需設定好, 當interrupt發生時查此table然後執行
idtr: register pointing to the IDT, similar to gdtr, ldtr
entry 0 代表interrupt 0

Hardware Handling of Interrupts (4.2.4)
步驟如下
CS and EIP contain logical address of next instruction to be executed. 在執行之前會檢查是否發生interrupt, if yes, do the following:
1. determine the vector i (0 < i < 255)
2. 從IDT (idtr) 中讀出第i個entry, entry中包含了segment selector and offset
3. 從segment selector中去找GDT, 拿到base address. This descriptor specifies the base address of the segment that includes the interrupt or exception handler.
4,5,6. Makes sure the interrupt was issued by an authorized source. (就一些檢查, 先跳過)
7. Saves the contents of eflags , cs, and eip in the stack.
8. If the exception carries a hardware error code, it saves it on the stack.
9. 跳至interrupt handler:
Loads cs and eip, respectively, with the Segment Selector and the Offset fields of the Gate Descriptor stored in the i th entry of the IDT. These values define the logical address of the first instruction of the interrupt or exception handler.

Interrupt Descriptor
the fields in the interrupt descriptor includes:
1. code segment selector
2. segment offset
3. PrivilegeLevel(ring)
4. Present bit–disable unused interrupts
5. gate type

IRQ sharing (from chapter 4.6.1)
IRQ可以被多個devices共用:
The interrupt handler executes several interrupt service routines (ISRs). Each ISR is a function related to a single device sharing the IRQ line. Because it is not possible to know in advance which particular device issued the IRQ, each ISR is executed to verify whether its device needs attention; if so, the ISR performs all the operations that need to be executed when the device raises an interrupt.

Disable Interrupt
1. cli disable interrupt and sti enable it
2. clear the bit 9 of EFLAGS (IF flag)
Before touching a shared data structure (or grabbing a lock), an interrupt handler should disable I/O interrupts
當interrupt handler要拿一個lock時, 必須要disable interrupt. 如果拿到lock, 然後被另一個handler preempt, then deadlock.
“Interrupt handlers need to synchronize, both with locks (multi-processor) and by disabling interrupts (same CPU)” - ref2

Gate Type
在IDT裡面有兩種gate type
1. Interrupt: 必須要disable all other interrupt
2. Exception: 不必


TSS (Task Stack Segment)
The Task State Segment is a special structure on x86-based computers which holds information about a task. It is used by the operating system kernel for task management.  (from wiki)
TSS用來儲存關於task的資料, 例如
1. processor register state (當要做context switching時存下現狀)
2. I/O port permission ,...
暫存器TR(task register)儲存segment selector指向GDT, 內有valid TSS.
- Linux使用one TSS per CPU, and modify TSS fields when context switching

Protection
Interrupt提供一個界面讓user space可以進入kernel space, x86 processor必須提供保護kernel的機制已避免user space application bug造成kernel crashes. 兩種方法如下:
from ref3:
  1. The Interrupt Descriptor Table. The processor ensures that interrupts and exceptions can only cause the kernel to be entered at a few specific, well-defined entry-points determined by the kernel itself, and not by the code running when the interrupt or exception is taken.
    The x86 allows up to 256 different interrupt or exception entry points into the kernel, each with a different interrupt vector. A vector is a number between 0 and 255. An interrupt's vector is determined by the source of the interrupt: different devices, error conditions, and application requests to the kernel generate interrupts with different vectors. The CPU uses the vector as an index into the processor's interrupt descriptor table (IDT), which the kernel sets up in kernel-private memory, much like the GDT. From the appropriate entry in this table the processor loads:
    • the value to load into the instruction pointer (EIP) register, pointing to the kernel code designated to handle that type of exception.
    • the value to load into the code segment (CS) register, which includes in bits 0-1 the privilege level at which the exception handler is to run. (In JOS, all exceptions are handled in kernel mode, privilege level 0.)

  2. The Task State Segment. The processor needs a place to save the old processor state before the interrupt or exception occurred, such as the original values of EIP and CS before the processor invoked the exception handler, so that the exception handler can later restore that old state and resume the interrupted code from where it left off. But this save area for the old processor state must in turn be protected from unprivileged user-mode code; otherwise buggy or malicious user code could compromise the kernel.
    For this reason, when an x86 processor takes an interrupt or trap that causes a privilege level change from user to kernel mode, it also switches to a stack in the kernel's memory. A structure called the task state segment (TSS) specifies the segment selector and address where this stack lives. The processor pushes (on this new stack) SS, ESP, EFLAGS, CS, EIP, and an optional error code. Then it loads the CS and EIP from the interrupt descriptor, and sets the ESP and SS to refer to the new stack.
    Although the TSS is large and can potentially serve a variety of purposes, JOS only uses it to define the kernel stack that the processor should switch to when it transfers from user to kernel mode. Since "kernel mode" in JOS is privilege level 0 on the x86, the processor uses the ESP0 and SS0 fields of the TSS to define the kernel stack when entering kernel mode. JOS doesn't use any other TSS fields.
Interrupt Procedure in x86
1. Interrupt gate跟call gate的作用機制很像
2. IDT entry裡面有selector跟offset, selector指向GDT, 從GDT拿到base address.
3. 最後利用CALL CS:IP, CS=base, IP=offset去職行

from ref4.




Reference:
1. Understanding the Linux kernel
2. CSE506 course slide
3. CSE506 lab3, JOS lab3
4. 80386 Programmer's Reference Manual: http://www.cs.stonybrook.edu/~porter/courses/cse506/f11/ref/i386/c09.htm

沒有留言:

張貼留言