]> Zhao Yanbai Git Server - kernel.git/commitdiff
让AP支持中断
authoracevest <zhaoyanbai@126.com>
Mon, 5 Jan 2026 11:24:29 +0000 (19:24 +0800)
committeracevest <zhaoyanbai@126.com>
Mon, 5 Jan 2026 11:24:29 +0000 (19:24 +0800)
boot/ap_boot.S
boot/multiboot2_header.c
include/linkage.h
include/processor.h
kernel/ap.c
kernel/apic.c
kernel/entry.S
kernel/innerint.c
kernel/interrupts.S
kernel/system.c

index 1fc169fb77cb3a25f877f39fce3e2c40b1c11561..86260b3b8811063f29e3bad05f2a1321c1b1a79a 100644 (file)
@@ -133,23 +133,32 @@ ap_code32_real_entry:
 
 .align 32
 .global ap_code32_entry_address
-ap_code32_entry_address:    .long ap_code32_entry - ap_realmode_base # 在BSP复制代码后会动态调整
+ap_code32_entry_address:    .long ap_code32_entry # 在BSP复制代码后会动态调整
                             .word 0x0008, 0x0000
 
+# 下面的定义会一鱼两吃 [也会复制两份]:
+#   1. 在实模式式下用一次 [只不过BSP复制到1MB以下的内存会稍作调整]
+#   2. 在保护模式下用一次 [因为加载了最终的页目录就无法以一一映射的方式访问这段实模式内存]
 .align 32
+.global ap_gdtr
 .global ap_gdtr_base
 ap_gdtr:
     ap_gdtr_limit: .word ap_gdt_end-ap_gdt
-    ap_gdtr_base:  .long ap_gdt - ap_realmode_base # 在BSP复制代码后会动态调整
+    ap_gdtr_base:  .long ap_gdt # 在BSP复制代码后会动态调整
 
+
+# 此处定义8个GDT项, 参考ap.c里的AP_GDT_CNT
 .align 32
+.global ap_gdt
 ap_gdt:
-empty:     .long    0x00000000, 0x00000000
-code_desc: .long    0x0000FFFF, 0x00CF9B00
-data_desc: .long    0x0000FFFF, 0x00CF9300
-pad0:      .long    0x00000000, 0x00000000
-pad1:      .long    0x00000000, 0x00000000
-pad2:      .long    0x00000000, 0x00000000
+empty:      .long    0x00000000, 0x00000000
+ap_code:    .long    0x0000FFFF, 0x00CF9B00
+ap_data:    .long    0x0000FFFF, 0x00CF9300
+ap_tss:     .long    0x00000000, 0x00000000
+pad0:       .long    0x00000000, 0x00000000
+pad1:       .long    0x00000000, 0x00000000
+pad2:       .long    0x00000000, 0x00000000
+pad3:       .long    0x00000000, 0x00000000
 ap_gdt_end:
 
 ap_boot_end:
index cce1bff7adf587333ce723fff2642fe6a5d80c4b..c61bac2f73a7df07ee89b3330168ba779e9dc2b9 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <multiboot2.h>
+#include <linkage.h>
 
 // 启用FB这个功能,需要修改grub.cfg,添加如下内容
 // load_video
@@ -16,8 +17,6 @@
 // terminal_output gfxterm
 #define ENABLE_FB 0
 
-#define ALIGN8 __attribute__((aligned(8)))
-
 typedef struct ALIGN8 multiboot2_elf_header {
     ALIGN8 struct multiboot_header header;
 #if ENABLE_FB
index ef66a080c4bde0507947186a06558c57fa4b41bc..134d6a94dc831f49e3529d7619cbb64fc2972fb9 100644 (file)
@@ -30,3 +30,6 @@
 #endif
 
 #define __initdata __attribute__((__section__(".init.data")))
+
+#define ALIGN8 __attribute__((__aligned__(8)))
+#define ALIGN4 __attribute__((__aligned__(4)))
index 3180c1014de316a7e76f7028736ac4a554a8c2e3..1aefc19e9249590635d1ec13196e40b50efd5326 100644 (file)
@@ -60,7 +60,7 @@ typedef struct {
     unsigned char DB : 1;    // 0--16bits,1--32bits
     unsigned char G : 1;     // set to 1. We just need 4K size.
     unsigned char baseH;
-} Seg, *pSeg;
+} seg_t;
 
 //-------------------------------------------------------------------------
 // TSS State,LDT
@@ -81,19 +81,19 @@ typedef struct {
 
     unsigned short eaddrH;
 
-} Gate, *pGate;
+} gate_t;
 
 // just used for type...
 typedef union {
-    Seg seg;
-    Gate gate;
-} Desc, *pDesc;
+    seg_t seg;
+    gate_t gate;
+} desc_t;
 
-#define NGDT 256
+#define NGDT 16
 #define NIDT 256
-#define NLDT 5
-extern Desc idt[NIDT];
-extern Desc gdt[NGDT];
+
+extern desc_t idt[NIDT];
+extern desc_t gdt[NGDT];
 
 //-------------------------------------------------------------------------
 // Define Gate Types...
@@ -102,13 +102,13 @@ extern Desc gdt[NGDT];
 #define TRAP_GATE 0x0F  // Keep  'IF' bit.
 #define TSS_DESC 0x09
 
-static inline void _init_desc(pDesc desc) {
-    memset((char*)desc, 0, sizeof(Desc));
+static inline void _init_desc(desc_t* desc) {
+    memset((void*)desc, 0, sizeof(desc_t));
 }
 
-static inline Desc _create_seg(u8 type, u8 DPL) {
-    Desc d;
-    pSeg p = &d.seg;
+static inline desc_t _create_seg(u8 type, u8 DPL) {
+    desc_t d;
+    seg_t* p = &d.seg;
 
     _init_desc(&d);
     p->limitL = 0xFFFF;
@@ -123,9 +123,9 @@ static inline Desc _create_seg(u8 type, u8 DPL) {
     return d;
 }
 
-static inline Desc _create_gate(u32 handler, u8 type, u8 DPL) {
-    Desc d;
-    pGate p = &d.gate;
+static inline desc_t _create_gate(u32 handler, u8 type, u8 DPL) {
+    desc_t d;
+    gate_t* p = &d.gate;
 
     _init_desc(&d);
 
@@ -175,9 +175,9 @@ typedef struct tss {
     u16 gs, _gs;
     u16 ldt, _ldt;
     u16 T : 1, _T : 15, iomap_base;
-} TSS_t;
+} tss_t;
 
-extern TSS_t tss;
+extern tss_t tss;
 
 // CR0 含有控制处理器操作模式和状态的系统控制标志
 #define CR0_PE (1 << 0)   // R/W Protection Enabled
index 5b9a3a0dba7d26dcc537036f1220acda1c2b4fd9..be45a56f5cfa67c0adc13181f08813444ba382d6 100644 (file)
  */
 
 #include <page.h>
+#include <types.h>
+#include <system.h>
+#include <processor.h>
+#include <linkage.h>
 
 extern pde_t* ap_pre_pgd;
 
+#define AP_GDT_CNT 8
+#define AP_IDT_CNT 256
+
+desc_t ALIGN8 ap_idt[AP_IDT_CNT];
+uint8_t ALIGN8 ap_idtr[6];
+
+#define AP_CS_SELECTOR 0x08
+#define AP_DS_SELECTOR 0x10
+
+static inline desc_t _create_ap_gate(u32 handler, u8 type, u8 DPL) {
+    desc_t d;
+    gate_t* p = &d.gate;
+
+    _init_desc(&d);
+
+    p->eaddrL = 0xFFFF & handler;
+    p->eaddrH = 0xFFFF & (handler >> 16);
+    p->selector = AP_CS_SELECTOR;
+    p->type = type;
+    p->P = 0x1;
+    p->DPL = DPL;
+
+    return d;
+}
+
+static inline void set_ap_idt_gate(u32 vec, u32 handler, u8 type, u8 DPL) {
+    ap_idt[vec] = _create_ap_gate(handler, type, DPL);
+}
+
+#define set_ap_sys_int(vect, type, DPL, handler)        \
+    do {                                                \
+        void handler();                                 \
+        set_ap_idt_gate(vect, (u32)handler, type, DPL); \
+    } while (0)
+
 void ap_kernel_entry() {
     // 虽然ap_pre_pgd只做了一下跳板页目录看起来很可惜
     // 不过可以把它拿来个AP的栈用
     asm("mov %0, %%esp" : : "r"(pa2va(&ap_pre_pgd) + PAGE_SIZE));
+
+    // 进入内核空间后要加载原来已经在内核空间的ap_gdt
+    // 之前加载的被复制到1MB以下的ap_gdt需要废弃,因为它已经在内核地址空间之外了
+    // 虽然他们是同一个ap_gdt
+    extern char ap_gdtr;
+    asm("lgdt ap_gdtr");
+
+    // tss
+    // AP 暂时不服务用户特权级 所以暂时用不到tss
+
+    //
+    set_ap_sys_int(0x00, TRAP_GATE, PRIVILEGE_KRNL, APDivideError);
+    set_ap_sys_int(0x01, TRAP_GATE, PRIVILEGE_KRNL, APDebug);
+    set_ap_sys_int(0x02, INTR_GATE, PRIVILEGE_KRNL, APNMI);
+    set_ap_sys_int(0x03, TRAP_GATE, PRIVILEGE_USER, APBreakPoint);
+    set_ap_sys_int(0x04, TRAP_GATE, PRIVILEGE_USER, APOverFlow);
+    set_ap_sys_int(0x05, TRAP_GATE, PRIVILEGE_USER, APBoundsCheck);
+    set_ap_sys_int(0x06, TRAP_GATE, PRIVILEGE_KRNL, APInvalidOpcode);
+    set_ap_sys_int(0x07, TRAP_GATE, PRIVILEGE_KRNL, APDeviceNotAvailable);
+    set_ap_sys_int(0x08, TRAP_GATE, PRIVILEGE_KRNL, APDoubleFault);
+    set_ap_sys_int(0x09, TRAP_GATE, PRIVILEGE_KRNL, APCoprocSegOverRun);
+    set_ap_sys_int(0x0A, TRAP_GATE, PRIVILEGE_KRNL, APInvalidTss);
+    set_ap_sys_int(0x0B, TRAP_GATE, PRIVILEGE_KRNL, APSegNotPresent);
+    set_ap_sys_int(0x0C, TRAP_GATE, PRIVILEGE_KRNL, APStackFault);
+    set_ap_sys_int(0x0D, TRAP_GATE, PRIVILEGE_KRNL, APGeneralProtection);
+    set_ap_sys_int(0x0E, TRAP_GATE, PRIVILEGE_KRNL, APPageFault);
+    set_ap_sys_int(0x10, TRAP_GATE, PRIVILEGE_KRNL, APCoprocError);
+
+    // idt gates
+    for (int i = 0x11; i < 0x20; i++) {
+        set_ap_sys_int(i, INTR_GATE, PRIVILEGE_KRNL, ap_no_irq_handler);
+    }
+
+    // irq gates
+    for (int i = 0x20; i < 256; i++) {
+        set_ap_sys_int(i, INTR_GATE, PRIVILEGE_KRNL, ap_no_irq_handler);
+    }
+
+    // 加载 ap_idtr
+    *((unsigned short*)ap_idtr) = AP_IDT_CNT * sizeof(gate_t);
+    *((unsigned long*)(ap_idtr + 2)) = (unsigned long)ap_idt;
+    asm volatile("lidt ap_idtr");
+
+    asm("int $0x28");
+
     while (1) {
         asm("nop;");
+        asm("int $0x28");
     }
 }
+
+void do_ap_no_irq_handler() {
+    // do nothing
+    // printk("AP no irq handler\n");
+    uint8_t* p = (uint8_t*)0xC00B8000;
+    *p = *p == ' ' ? 'K' : ' ';
+}
index 0c92c8ebb28216b5ab0d1dba35dd377b7e01f0d9..e30c6c1470e5ba8c4d1236f79758dc53ca96e622 100644 (file)
@@ -373,7 +373,7 @@ void prepare_ap_code(paddr_t paddr) {
     extern char ap_boot_end;
     uint32_t bytes = &ap_boot_end - &ap_boot_bgn;
 
-    for(int i=0; i<bytes; i++) {
+    for (int i = 0; i < bytes; i++) {
         ((uint8_t*)paddr)[i] = ((uint8_t*)&ap_boot_bgn)[i];
     }
 
@@ -381,14 +381,16 @@ void prepare_ap_code(paddr_t paddr) {
     extern uint8_t ap_code32_entry_address;
     extern uint8_t ap_gdtr_base;
 
-    uint32_t *dst = 0;
+    uint32_tdst = 0;
 
     //
-    dst = (uint32_t *)(paddr + (uint32_t)(&ap_code32_entry_address) - (uint32_t)(&ap_boot_bgn));
+    dst = (uint32_t*)(paddr + (uint32_t)(&ap_code32_entry_address) - (uint32_t)(&ap_boot_bgn));
+    (*dst) -= (uint32_t)(&ap_boot_bgn);
     (*dst) += (paddr - KERNEL_VADDR_BASE);
 
     //
-    dst = (uint32_t *)(paddr + (uint32_t)(&ap_gdtr_base) - (uint32_t)(&ap_boot_bgn));
+    dst = (uint32_t*)(paddr + (uint32_t)(&ap_gdtr_base) - (uint32_t)(&ap_boot_bgn));
+    (*dst) -= (uint32_t)(&ap_boot_bgn);
     (*dst) += (paddr - KERNEL_VADDR_BASE);
 }
 
index 333035926045c117e73dbeccbf0c6cffe66bc946..853c41eecacafa04c51eeed1143c28f8f810250b 100644 (file)
@@ -46,7 +46,7 @@
  */
 #define NOERRCODE(name)     \
     EC_ENTRY(name)          \
-    pushl    $0;             \
+    pushl    $0;            \
     EC_CALLDO(name)
 
 #define ERRORCODE(name)     \
@@ -70,3 +70,24 @@ ERRORCODE    (StackFault)
 ERRORCODE    (GeneralProtection)
 ERRORCODE    (_page_fault)
 NOERRCODE    (CoprocError)
+
+
+
+
+
+NOERRCODE    (APDivideError)
+NOERRCODE    (APDebug)
+NOERRCODE    (APNMI)
+NOERRCODE    (APBreakPoint)
+NOERRCODE    (APOverFlow)
+NOERRCODE    (APBoundsCheck)
+NOERRCODE    (APInvalidOpcode)
+NOERRCODE    (APDeviceNotAvailable)
+NOERRCODE    (APDoubleFault)
+NOERRCODE    (APCoprocSegOverRun)
+ERRORCODE    (APInvalidTss)
+ERRORCODE    (APSegNotPresent)
+ERRORCODE    (APStackFault)
+ERRORCODE    (APGeneralProtection)
+ERRORCODE    (APPageFault)
+NOERRCODE    (APCoprocError)
index c3c22d00613534c56baf0a20d216b941bf438a38..e09df5689a1e52081722d8a21604dd2564e52235 100644 (file)
@@ -109,3 +109,62 @@ US RW  P - Description
 void doCoprocError(pt_regs_t regs) {
     DIE_MSG();
 }
+
+// TODO 把printk换掉
+#define AP_DIE_MSG()                                                                                     \
+    do {                                                                                                 \
+        printk("AP Unsupport Now...[%s]\n", __FUNCTION__);                                               \
+        printk("EFLAGS:%08x CS:%02x EIP:%08x ERRCODE:%x", regs.eflags, regs.cs, regs.eip, regs.errcode); \
+        asm("cli;hlt;");                                                                                 \
+    } while (0);
+
+void doAPDivideError(pt_regs_t regs) {
+    AP_DIE_MSG();
+}
+void doAPDebug(pt_regs_t regs) {
+    AP_DIE_MSG();
+}
+void doAPNMI(pt_regs_t regs) {
+    AP_DIE_MSG();
+}
+void doAPBreakPoint(pt_regs_t regs) {
+    AP_DIE_MSG();
+}
+void doAPOverFlow(pt_regs_t regs) {
+    AP_DIE_MSG();
+}
+void doAPBoundsCheck(pt_regs_t regs) {
+    AP_DIE_MSG();
+}
+void doAPInvalidOpcode(pt_regs_t regs) {
+    AP_DIE_MSG();
+}
+void doAPDeviceNotAvailable(pt_regs_t regs) {
+    AP_DIE_MSG();
+}
+void doAPDoubleFault(pt_regs_t regs) {
+    AP_DIE_MSG();
+}
+void doAPCoprocSegOverRun(pt_regs_t regs) {
+    AP_DIE_MSG();
+}
+void doAPInvalidTss(pt_regs_t regs) {
+    AP_DIE_MSG();
+}
+void doAPSegNotPresent(pt_regs_t regs) {
+    AP_DIE_MSG();
+}
+void doAPStackFault(pt_regs_t regs) {
+    AP_DIE_MSG();
+}
+void doAPGeneralProtection(pt_regs_t regs) {
+    AP_DIE_MSG();
+}
+
+void doAPPageFault(pt_regs_t regs) {
+    AP_DIE_MSG();
+}
+
+void doAPCoprocError(pt_regs_t regs) {
+    AP_DIE_MSG();
+}
index 8bc701b2eacf95b7d675303e20a440b74e619dc5..7a7db3a07ce6579d65629ecd257c5ff57d66a446 100644 (file)
@@ -105,3 +105,14 @@ _boot_clk_irq_handler:
 _boot_kbd_irq_handler:
     push $0x01;
     jmp _boot_irq_handler
+
+
+
+.global ap_no_irq_handler
+ap_no_irq_handler:
+    SAVE_REGS
+
+    call    do_ap_no_irq_handler
+
+    RESTORE_REGS
+    iret
index 447d482f48671ee3c58949be2141b7c39788fb86..112480e689e419ef16de0a798202ff450ae49ef9 100644 (file)
 #include <string.h>
 #include <syscall.h>
 #include <system.h>
+#include <linkage.h>
 
 System system;
-TSS_t tss;
-Desc idt[NIDT] __attribute__((__aligned__(8)));
-Desc gdt[NGDT] __attribute__((__aligned__(8)));
-char gdtr[6] __attribute__((__aligned__(4)));
-char idtr[6] __attribute__((__aligned__(4)));
+tss_t tss;
 
-extern char _gdtr[6];
-extern char _idtr[6];
+desc_t ALIGN8 idt[NIDT];
+desc_t ALIGN8 gdt[NGDT];
+
+char ALIGN4 gdtr[6];
+char ALIGN4 idtr[6];
 
 volatile int reenter = -1;
 
 void setup_gdt() {
-    pDesc pdesc;
+    desc_t* pdesc;
     // change to new gdt.
     asm volatile("sgdt gdtr");
 
     // 复制旧的GDT
     memcpy(gdt, (void*)pa2va(*((uint32_t*)(gdtr + 2))), *((uint16_t*)(gdtr + 0)));
-    *((unsigned short*)gdtr) = NGDT * sizeof(Desc);
+    *((unsigned short*)gdtr) = NGDT * sizeof(desc_t);
     *((unsigned long*)(gdtr + 2)) = (unsigned long)gdt;
 
     asm volatile("lgdt gdtr");
 
-    memcpy(gdt + INDEX_UCODE, gdt + INDEX_KCODE, sizeof(Desc));
-    memcpy(gdt + INDEX_UDATA, gdt + INDEX_KDATA, sizeof(Desc));
+    memcpy(gdt + INDEX_UCODE, gdt + INDEX_KCODE, sizeof(desc_t));
+    memcpy(gdt + INDEX_UDATA, gdt + INDEX_KDATA, sizeof(desc_t));
     pdesc = gdt + INDEX_UCODE;
     pdesc->seg.DPL = 3;
     pdesc = gdt + INDEX_UDATA;
@@ -62,7 +62,7 @@ void setup_gdt() {
 // 通过中断门进入中断服务程序CPU会自动将中断关闭,也就是将EFLAGS的IF位清0
 // 通过陷阱门进入服务程序时则维持IF标志位不变
 void setup_idt() {
-    *((unsigned short*)idtr) = NIDT * sizeof(Gate);
+    *((unsigned short*)idtr) = NIDT * sizeof(gate_t);
     *((unsigned long*)(idtr + 2)) = (unsigned long)idt;
     asm volatile("lidt idtr");
 }
@@ -174,8 +174,8 @@ void setup_boot_irqs() {
 }
 
 void set_tss_gate(u32 vec, u32 addr, u32 limit) {
-    pSeg p = (pSeg)(gdt + vec);
-    _init_desc((pDesc)p);
+    seg_t* p = (seg_t*)(gdt + vec);
+    _init_desc((desc_t*)p);
     p->limitL = 0xFFFF & limit;
     p->limitH = 0x0F & (limit >> 16);
     p->baseL = 0xFFFF & addr;
@@ -190,8 +190,8 @@ void set_tss_gate(u32 vec, u32 addr, u32 limit) {
 }
 
 void set_tss() {
-    TSS_t* p = &tss;
-    memset((void*)p, sizeof(TSS_t), 0);
+    tss_t* p = &tss;
+    memset((void*)p, 0, sizeof(tss_t));
     p->esp0 = 0;  // delay to init root_task
     p->ss0 = SELECTOR_KRNL_DS;
     p->ss = SELECTOR_KRNL_DS;
@@ -201,11 +201,11 @@ void set_tss() {
     p->ds = SELECTOR_KRNL_DS;
     p->cs = SELECTOR_KRNL_CS;
     p->eflags = 0x1200;
-    p->iomap_base = sizeof(TSS_t);
+    p->iomap_base = sizeof(tss_t);
 
-    // tss的iomap_base=sizeof(TSS_t) > TSS_GATE.LIMIT - 1
+    // tss的iomap_base=sizeof(tss_t) > TSS_GATE.LIMIT - 1
     // 因此表示没有I/O位图
-    set_tss_gate(INDEX_TSS, (u32)p, sizeof(TSS_t));
+    set_tss_gate(INDEX_TSS, (u32)p, sizeof(tss_t));
 
     asm("ltr %%ax" ::"a"((INDEX_TSS << 3) + 3));
 }