Chapter 06:Interrupt === :::info 作業系統本質上就是中斷驅動的大型軟體,如果沒有中斷,程式只會從頭運行到尾端,也不可能實現排程器,更別說是多工處理了。本節從最底層的 x86 硬體技術:IDT 開始介紹,接著是統一處理 external interrupt 的 8259A,最後是 internal interrupt 中最著名的 system call。 &emsp; 1. IDT &emsp; 2. 8259A &emsp; 3. System Call ::: >[time=Wed, Oct 15, 2025 3:19 AM] --- https://youtu.be/JUkbPCG6-_E <iframe width="560" height="315" src="https://www.youtube.com/embed/JUkbPCG6-_E?si=q_Z01qPVfcqxSODQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> ![截圖 2025-10-20 下午5.20.09](https://hackmd.io/_uploads/HkbxkKQRgl.png) # IDT (Interrupt Descriptor Table) >Reference: >[OSDev wiki](https://wiki.osdev.org/Interrupt_Descriptor_Table) >[Intel 80386 Reference Programmer's Manual](https://pdos.csail.mit.edu/6.828/2005/readings/i386/s09_05.htm) >[!Note] Interrupt Gate Descriptor >![截圖 2025-10-17 晚上7.44.17](https://hackmd.io/_uploads/rkNN3oyCgx.png) >![截圖 2025-10-19 下午4.41.42](https://hackmd.io/_uploads/HJmuVQGAel.png) >[!Note] LIDT >![截圖 2025-10-18 晚上11.37.00](https://hackmd.io/_uploads/BypN4NZ0gg.png) >![v2-ac423456ae69f2a3af14db8a4d8ba38f_1440w](https://hackmd.io/_uploads/HJSJWr-Alx.jpg) >[!Note] Interrupt 發生後 stack 的變化 (CPU 自動完成) >![截圖 2025-10-17 晚上8.10.28](https://hackmd.io/_uploads/HktvM2yCxe.png) >![截圖 2025-10-17 晚上8.10.52](https://hackmd.io/_uploads/S1gufhJ0xl.png) >[!Note] Interrupt Vectors >The x86 architecture defines 256 possible interrupt vectors (0-255). >* 0x00 - 0x1F: for processor exceptions and non-maskable interrupts (NMIs). >![截圖 2025-10-17 晚上8.47.58](https://hackmd.io/_uploads/ry5XjnkCxl.png) >Reference: [OSDev wiki](https://wiki.osdev.org/Exceptions) >* 0x20 - 0x2F: assigned to maskable hardware interrupts (IRQs) by the PIC/APIC. >🔹主 8259A (Master PIC): 接收 IRQ0–IRQ7,重新對映至中斷向量 0x20–0x27 >🔹 從 8259A (Slave PIC): 接收 IRQ8–IRQ15,重新對映至中斷向量 0x28–0x2F >![截圖 2025-10-19 凌晨1.46.48](https://hackmd.io/_uploads/H1RsfLZAxx.png) >* 0x30 - 0xFF: used for software interrupts or additional hardware interrupts. >[!Note] inline assembly ```c= asm ("assembler template" : output operands : input operands : clobbered registers/memory); ``` >Reference: [OSDev wiki](https://wiki.osdev.org/Inline_Assembly) | Constraint | 對應暫存器 | 範例 | 說明 | | ---------- | ------------- | ------------ | ----------------- | | `"a"` | `eax` / `rax` | `"a"(value)` | 使用累加器寄存器 | | `"b"` | `ebx` / `rbx` | `"b"(value)` | 使用 base 寄存器 | | `"c"` | `ecx` / `rcx` | `"c"(value)` | 使用計數暫存器 | | `"d"` | `edx` / `rdx` | `"d"(value)` | 使用資料寄存器 | | `"S"` | `esi` / `rsi` | `"S"(src)` | Source index | | `"D"` | `edi` / `rdi` | `"D"(dest)` | Destination index | | `"r"` | 任意可用暫存器 | `"r"(value)` | compiler 自動選寄存器 | | `"m"` | 記憶體操作數 | `"m"(var)` | 指向變數的記憶體位置 | | `"i"` | 立即數常量 | `"i"(value)` | 用於固定常數 | ```c= int a = 2, b = 3, result; asm volatile ( "addl %2, %1\n\t" // 將 %2 加到 %1 "movl %1, %0" // 將結果放入 %0 : "=r"(result) // %0 : "r"(a), "r"(b) // %1, %2 ); ``` >[!Note] page fault >When the CPU fires a page-not-present exception the ==CR2== register is populated with the linear address that caused the exception. >Reference: [OSDev wiki](https://wiki.osdev.org/Paging#Page_Faults) ## Source Code https://github.com/srhuang/a-os/commit/e09eaebbbe16ac1d0ae1961631c762cc4cd1de37 ## Compile ``` make all ``` ## Put on hard disk ``` sh gen.sh ``` ## Checkpoint ![截圖 2025-10-19 晚上10.31.44](https://hackmd.io/_uploads/HJE3LufAxl.png) ![截圖 2025-10-19 凌晨1.10.52](https://hackmd.io/_uploads/ByrN5S-0gl.png) ![截圖 2025-10-19 凌晨1.11.13](https://hackmd.io/_uploads/S1iBcSW0ge.png) test page fault ![截圖 2025-10-19 晚上10.49.19](https://hackmd.io/_uploads/ry9q9dzCgl.png) test divide zero ![截圖 2025-10-19 晚上10.50.38](https://hackmd.io/_uploads/rJWyouMRgx.png) # 8259A (External Interrupt) ![截圖 2025-10-19 下午5.17.25](https://hackmd.io/_uploads/HyB637MRxl.png) >Reference: [8259A data sheet](https://pdos.csail.mit.edu/6.828/2010/readings/hardware/8259A.pdf) * INT: 發送訊號通知 CPU。 * INTA: interrupt acknowledge,接收來自 CPU ACK 訊號。 | 暫存器名稱 | 簡述 | | ------------------------------------ | ------------------------------- | | **IRR** (Interrupt Request Register) | 儲存尚未被 CPU 處理的中斷請求。 | | **ISR** (In-Service Register) | 儲存目前正在被 CPU 處理的中斷。 | | **IMR** (Interrupt Mask Register) | 指定哪些 IRQ 被遮罩 (mask)。 | | **PR** (Priority Resolver) | 找出優先權高的中斷。 | >[!Note] End of Interrupt >![99509fac-a86e-48c8-be3c-ccd4879a598f](https://hackmd.io/_uploads/SJPr9mM0lg.png) >![截圖 2025-10-19 下午5.08.17](https://hackmd.io/_uploads/BkMi9QGCxe.png) >![截圖 2025-10-19 下午5.09.06](https://hackmd.io/_uploads/rJkA97GRgl.png) >[!Note] Cascade 8259A ![upload_73e6cceec9ae7fb9fda0eef5c8131f9b](https://hackmd.io/_uploads/SkjJr7f0xg.jpg) >[!Note] 8259A Programming: Initialization Command Words (ICW) >![截圖 2025-10-19 下午5.19.50](https://hackmd.io/_uploads/H14IpXzReg.png) >![截圖 2025-10-19 下午5.20.32](https://hackmd.io/_uploads/H1COpmGAle.png) | 名稱 | 功能說明 | | -------- | ------------------------------------- | | **ICW1** | 基本啟動設定(邊緣觸發 / 電平觸發、是否有 ICW4、是否有從 PIC) | | **ICW2** | 中斷向量號碼的起始位置(中斷偏移量) | | **ICW3** | 主從連線關係設定(主 PIC 哪條 IRQ 連從 PIC) | | **ICW4** | 進階控制(8086/8088 模式、自動 EOI、緩衝、特殊全巢狀模式) | >[!Caution] 寫入 ICW 有嚴格的規定,必須依序設定 ICW1, ICW2, ICW3, ICW4。 >[!Note] 8259A Programming: Operation Command Word (OCW) >![截圖 2025-10-19 下午5.35.01](https://hackmd.io/_uploads/B1ekbNzCll.png) >![截圖 2025-10-19 下午5.35.44](https://hackmd.io/_uploads/HyAZZEMAgg.png) | 名稱 | 全名 | 主要用途 | | -------- | ------------------------ | ------------------------ | | **OCW1** | Operation Command Word 1 | 控制每條 IRQ 是否允許 (Mask) | | **OCW2** | Operation Command Word 2 | 控制中斷結束 (EOI)、優先權旋轉 | | **OCW3** | Operation Command Word 3 | 查詢寄存器 (IRR / ISR)、設定輪詢模式 | >[!Caution] 我們採用固定優先權,IRQ number 越低,優先權越高。 ![upload_106057987cd2cdd51bb4f70ce96c2672](https://hackmd.io/_uploads/Sk-fSmGAex.png) ![截圖 2025-10-19 下午4.47.46](https://hackmd.io/_uploads/BkbABXMRgg.png) >Reference: [Bochs' map of I/O ports to functions](https://bochs.sourceforge.io/techspec/PORTS.LST) >[!Caution] I/O port 0x20 如何辨識 registers >ICW1: [4:3]=b'10 >OCW2: [4:3]=b'00 >OCW3: [4:3]=b'01 >ICW2, ICW3, ICW4, OCW1: 依據寫入流程。 >[!Note] Port Operations >![截圖 2025-10-20 晚上8.31.14](https://hackmd.io/_uploads/HJG0soQRgx.png) >![截圖 2025-10-20 晚上8.36.51](https://hackmd.io/_uploads/r1lWTjQRex.png) >![截圖 2025-10-20 晚上8.40.14](https://hackmd.io/_uploads/Hk5T6sQAxg.png) >Reference: [x86 Instruction Set Reference](https://c9x.me/x86/) >[!Note] Interrupt Flag >![截圖 2025-10-19 晚上10.10.24](https://hackmd.io/_uploads/rJPdZ_zAlx.png) >![截圖 2025-10-19 晚上10.11.01](https://hackmd.io/_uploads/Hya9Z_fCxg.png) >![upload_1ad1cb15dbe0b9946a577cd963214de5](https://hackmd.io/_uploads/SkOAbOGRgg.png) ## Source Code https://github.com/srhuang/a-os/commit/3f8c917f5646f5a6c369c2d1181f5e1492b381db ## Compile ``` make all ``` ## Put on hard disk ``` sh gen.sh ``` ## Checkpoint ![截圖 2025-10-19 晚上11.01.41](https://hackmd.io/_uploads/rkOuTOM0lx.png) unmask system timer ![截圖 2025-10-19 晚上10.54.46](https://hackmd.io/_uploads/rkLk2_MRex.png) ![截圖 2025-10-19 晚上10.54.05](https://hackmd.io/_uploads/HkWnj_f0el.png) # System Call (Internal Interrupt) ![截圖 2025-10-20 凌晨1.24.20](https://hackmd.io/_uploads/BJ-1JsGRxl.png) ## Source Code https://github.com/srhuang/a-os/commit/aa556b986a5a160f0d48a8de2f9856c1a0f9b7df >[!Warning] Bug fix >https://github.com/srhuang/a-os/commit/786e9091f5b5f088e881406400983b8ef0b1e978 ## Compile ``` make all ``` ## Put on hard disk ``` sh gen.sh ``` ## Checkpoint ![截圖 2025-10-20 凌晨1.13.40](https://hackmd.io/_uploads/SkHdnqz0xg.png)