From: acevest Date: Mon, 5 Jan 2026 11:24:29 +0000 (+0800) Subject: 让AP支持中断 X-Git-Url: http://repos.zhaoyanbai.com/?a=commitdiff_plain;h=756e95554c10679e7ecd1f27a8efa793638eb5d0;p=kernel.git 让AP支持中断 --- diff --git a/boot/ap_boot.S b/boot/ap_boot.S index 1fc169f..86260b3 100644 --- a/boot/ap_boot.S +++ b/boot/ap_boot.S @@ -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: diff --git a/boot/multiboot2_header.c b/boot/multiboot2_header.c index cce1bff..c61bac2 100644 --- a/boot/multiboot2_header.c +++ b/boot/multiboot2_header.c @@ -8,6 +8,7 @@ */ #include +#include // 启用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 diff --git a/include/linkage.h b/include/linkage.h index ef66a08..134d6a9 100644 --- a/include/linkage.h +++ b/include/linkage.h @@ -30,3 +30,6 @@ #endif #define __initdata __attribute__((__section__(".init.data"))) + +#define ALIGN8 __attribute__((__aligned__(8))) +#define ALIGN4 __attribute__((__aligned__(4))) diff --git a/include/processor.h b/include/processor.h index 3180c10..1aefc19 100644 --- a/include/processor.h +++ b/include/processor.h @@ -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 diff --git a/kernel/ap.c b/kernel/ap.c index 5b9a3a0..be45a56 100644 --- a/kernel/ap.c +++ b/kernel/ap.c @@ -8,14 +8,106 @@ */ #include +#include +#include +#include +#include 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' : ' '; +} diff --git a/kernel/apic.c b/kernel/apic.c index 0c92c8e..e30c6c1 100644 --- a/kernel/apic.c +++ b/kernel/apic.c @@ -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 #include #include +#include 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)); }