From: acevest Date: Thu, 8 Jan 2026 07:58:21 +0000 (+0800) Subject: 用新的方法切换ap的内核栈 X-Git-Url: http://repos.zhaoyanbai.com/Mou_128.png?a=commitdiff_plain;h=d5e53a7c69a2df718cffb9dde01ef5b4eb8089ab;p=kernel.git 用新的方法切换ap的内核栈 --- diff --git a/boot/ap_boot.S b/boot/ap_boot.S index 86260b3..1542298 100644 --- a/boot/ap_boot.S +++ b/boot/ap_boot.S @@ -121,6 +121,11 @@ ap_code32_real_entry: subl $kernel_virtual_addr_start, %eax # 算出物理地址 movl %eax, %cr3 + # 加载AP的内核栈顶到esp + .extern ap_get_kernel_esp + call ap_get_kernel_esp + movl %eax, %esp + # 进入内核ap代码 .extern ap_kernel_entry leal ap_kernel_entry, %eax diff --git a/include/system.h b/include/system.h index d5c5ef1..4c5dc1c 100644 --- a/include/system.h +++ b/include/system.h @@ -158,6 +158,9 @@ typedef struct system { dev_t root_dev; + // + uint32_t ap_cpuid; + // 按理这些信息应该按CPU存储,简化实现 lapic_t* lapic; paddr_t lapic_addr; @@ -172,9 +175,9 @@ typedef struct system { u32 debug; u32 delay; -} System, *pSystem; +} system_t; -extern System system; +extern system_t system; void system_delay(); diff --git a/kernel/ap.c b/kernel/ap.c index fd05c06..8985482 100644 --- a/kernel/ap.c +++ b/kernel/ap.c @@ -52,11 +52,13 @@ static inline void set_ap_idt_gate(u32 vec, u32 handler, u8 type, u8 DPL) { set_ap_idt_gate(vect, (u32)handler, type, DPL); \ } while (0) -void ap_kernel_entry() { +uint32_t ap_get_kernel_esp() { // 虽然ap_pre_pgd只做了一下跳板页目录看起来很可惜 // 不过可以把它拿来个AP的栈用 - asm("mov %0, %%esp" : : "r"(pa2va(&ap_pre_pgd) + PAGE_SIZE - 128)); + return (uint32_t)pa2va(&ap_pre_pgd) + PAGE_SIZE; +} +void ap_kernel_entry() { // 进入内核空间后要加载原来已经在内核空间的ap_gdt // 之前加载的被复制到1MB以下的ap_gdt需要废弃,因为它已经在内核地址空间之外了 // 虽然他们是同一个ap_gdt @@ -124,6 +126,9 @@ void ap_kernel_entry() { write_msr(MSR_IA32_APIC_BASE, apic_base); } + system.ap_cpuid = lapic->get_lapic_id(); + printk("AP CPU id: %d\n", system.ap_cpuid); + uint32_t lapic_svr = lapic->read(LAPIC_SVR); lapic_svr |= (1 << 8); // 启用LAPIC lapic_svr &= ~(1 << 12); // 禁用EOI广播 @@ -163,3 +168,7 @@ void do_ap_no_irq_handler() { *p = *p == ' ' ? 'K' : ' '; system.lapic->write(LAPIC_EOI, 0); } + +bool ap_ready() { + return system.ap_cpuid != 0; +} diff --git a/kernel/apic.c b/kernel/apic.c index 5600206..c4aa8ac 100644 --- a/kernel/apic.c +++ b/kernel/apic.c @@ -624,6 +624,13 @@ void init_apic() { paddr_t ap_code_addr = 0x1000; prepare_ap_code(ap_code_addr); wakeup_ap(ap_code_addr); + + printk("wait AP ready..."); + extern bool ap_ready(); + while (!ap_ready()) { + asm("pause"); + } + printk("AP ready\n"); } // ## 中断路由路径配置矩阵 diff --git a/kernel/system.c b/kernel/system.c index a37f32e..2afd1ee 100644 --- a/kernel/system.c +++ b/kernel/system.c @@ -27,7 +27,7 @@ #include #include -System system; +system_t system; tss_t tss; desc_t ALIGN8 idt[NIDT];