From: acevest Date: Sun, 4 Jan 2026 11:11:18 +0000 (+0800) Subject: AP启动进入保护模式 X-Git-Url: http://repos.zhaoyanbai.com/Mou_128.png?a=commitdiff_plain;h=1fea26ab0cc439757c26afcda14bb59e35c34294;p=kernel.git AP启动进入保护模式 --- diff --git a/boot/ap_boot.S b/boot/ap_boot.S new file mode 100644 index 0000000..538fce8 --- /dev/null +++ b/boot/ap_boot.S @@ -0,0 +1,86 @@ +/* + * ------------------------------------------------------------------------ + * File Name: ap_boot.S + * Author: Zhao Yanbai + * 2026-01-04 08:18:07 Sunday CST + * Description: none + * ------------------------------------------------------------------------ + */ + +.code16 +#.text +#.section .ap_boot, "ax", @progbits +.global ap_boot_bgn +.global ap_boot_end +.align 0x1000 +ap_boot_bgn: +ap_realmode_base: +ap_real_mode_entry: + cli + + wbinvd # 将CPU缓存写回主内存并使缓存失效 + + xorl %ebx, %ebx + + movw %cs, %bx + movw %bx, %ds + movw %bx, %es + movw %bx, %ss + + # 算出ap_realmode_base的线性地址 + shl $4, %ebx + + movl %ebx, %esp + addl $0x1000, %esp + + # 算出gdt的线性地址 + leal (ap_gdt - ap_realmode_base)(%ebx), %eax + # 把这个地址填入gdtr的base位置 + movl %eax, (ap_gdtr_base - ap_realmode_base) + + + # 算出ap_code32_entry的线性地址 + leal (ap_code32_entry - ap_realmode_base)(%ebx), %eax + # 把这个地址填入ap_code32_entry_address + mov %eax, (ap_code32_entry_address - ap_realmode_base) + + + lgdt ap_gdtr - ap_realmode_base + + # enable PE + movl %cr0,%eax + orl $0x00000001,%eax + movl %eax,%cr0 + + # 清空指令流水线 + jmp .flush +.flush: + + # ljmpl 的前后两个l都很重要 + ljmpl *(ap_code32_entry_address - ap_realmode_base) + + +.code32 +.align 32 +ap_code32_entry: + cli + nop + nop + hlt + + +.align 32 +ap_code32_entry_address: .long 0x00000000 # 等待动态写入 + .word 0x0008, 0x0000 + +.align 32 +ap_gdt: +empty: .long 0x00000000, 0x00000000 +code_desc: .long 0x0000FFFF, 0x00CF9B00 +data_desc: .long 0x0000FFFF, 0x00CF9300 +ap_gdt_end: +ap_gdtr: + ap_gdtr_limit: .word ap_gdt_end-ap_gdt + ap_gdtr_base: .long 0 # 等待动态写入 + +ap_boot_end: diff --git a/boot/multiboot.S b/boot/multiboot.S index 9545d59..4f850bc 100644 --- a/boot/multiboot.S +++ b/boot/multiboot.S @@ -107,7 +107,7 @@ p_label_far_ptr: .align 32 boot_gdt: -empty: .long 0x00000000, 0x00000000 +empty: .long 0x00000000, 0x00000000 code_desc: .long 0x0000FFFF, 0x00CF9B00 data_desc: .long 0x0000FFFF, 0x00CF9300 boot_gdt_end: diff --git a/kernel/apic.c b/kernel/apic.c index eecd233..3643db0 100644 --- a/kernel/apic.c +++ b/kernel/apic.c @@ -362,12 +362,20 @@ void ioapic_init() { void prepare_ap_code(paddr_t paddr) { // 注意: 最开始时AP是运行在实模式 paddr += KERNEL_VADDR_BASE; - *(volatile uint8_t*)(paddr + 0) = 0x90; - *(volatile uint8_t*)(paddr + 1) = 0x90; - *(volatile uint8_t*)(paddr + 2) = 0x90; - *(volatile uint8_t*)(paddr + 3) = 0xEA; // jmp - *(volatile uint16_t*)(paddr + 4) = 0x0000; // offset: 0000 - *(volatile uint16_t*)(paddr + 6) = 0x0100; // cs:0100 + // *(volatile uint8_t*)(paddr + 0) = 0x90; + // *(volatile uint8_t*)(paddr + 1) = 0x90; + // *(volatile uint8_t*)(paddr + 2) = 0x90; + // *(volatile uint8_t*)(paddr + 3) = 0xEA; // jmp + // *(volatile uint16_t*)(paddr + 4) = 0x0000; // offset: 0000 + // *(volatile uint16_t*)(paddr + 6) = 0x0100; // cs:0100 + + extern char ap_boot_bgn; + extern char ap_boot_end; + uint32_t bytes = &ap_boot_end - &ap_boot_bgn; + // memcpy((void*)paddr, &ap_boot_bgn, bytes); + for(int i=0; iwrite64(LAPIC_ICR, startup_ipi); printk("STARTUP[1] IPI %016x\n", startup_ipi); +#endif printk("wakeup ap\n"); }