From b7df2805ed92afcba05610cc2471a8bab68739f4 Mon Sep 17 00:00:00 2001 From: fslongjin Date: Wed, 6 Apr 2022 15:11:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AD=98=E5=9C=A8bug=EF=BC=8Capu=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=90=8E=E8=A7=A6=E5=8F=91=E5=BC=82=E5=B8=B8=E4=BC=9A?= =?UTF-8?q?Reset?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/Makefile | 2 +- kernel/driver/interrupt/apic/apic.c | 21 ++--- kernel/exception/irq.c | 13 +-- kernel/exception/trap.c | 136 ++++++++++++++++------------ kernel/head.S | 13 ++- kernel/main.c | 6 +- kernel/smp/apu_boot.S | 42 ++++++--- kernel/smp/smp.c | 80 +++++++++++++++- 8 files changed, 214 insertions(+), 99 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index 34061161..1536887c 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -7,7 +7,7 @@ DIR_LIB=lib lib_patterns := *.a LIB_FILES := $(foreach DIR,$(DIR_LIB),$(addprefix $(DIR)/,$(lib_patterns))) -CFLAGS := -mcmodel=large -fno-builtin -m64 -g +CFLAGS := -mcmodel=large -fno-builtin -m64 -g -O0 # 控制操作系统使用的中断控制器 _INTR_8259A_ _INTR_APIC_ PIC := _INTR_APIC_ diff --git a/kernel/driver/interrupt/apic/apic.c b/kernel/driver/interrupt/apic/apic.c index 9a089e3f..145bbd91 100644 --- a/kernel/driver/interrupt/apic/apic.c +++ b/kernel/driver/interrupt/apic/apic.c @@ -390,18 +390,17 @@ void apic_local_apic_init() void apic_init() { - - // 初始化主芯片 - io_out8(0x20, 0x11); // 初始化主芯片的icw1 - io_out8(0x21, 0x20); // 设置主芯片的中断向量号为0x20(0x20-0x27) - io_out8(0x21, 0x04); // 设置int2端口级联从芯片 - io_out8(0x21, 0x01); // 设置为AEOI模式、FNM、无缓冲 + // 初始化主芯片 + io_out8(0x20, 0x11); // 初始化主芯片的icw1 + io_out8(0x21, 0x20); // 设置主芯片的中断向量号为0x20(0x20-0x27) + io_out8(0x21, 0x04); // 设置int2端口级联从芯片 + io_out8(0x21, 0x01); // 设置为AEOI模式、FNM、无缓冲 - // 初始化从芯片 - io_out8(0xa0, 0x11); - io_out8(0xa1, 0x28); // 设置从芯片的中断向量号为0x28(0x28-0x2f) - io_out8(0xa1, 0x02); // 设置从芯片连接到主芯片的int2 - io_out8(0xa1, 0x01); + // 初始化从芯片 + io_out8(0xa0, 0x11); + io_out8(0xa1, 0x28); // 设置从芯片的中断向量号为0x28(0x28-0x2f) + io_out8(0xa1, 0x02); // 设置从芯片连接到主芯片的int2 + io_out8(0xa1, 0x01); // 屏蔽类8259A芯片 io_mfence(); io_out8(0xa1, 0xff); diff --git a/kernel/exception/irq.c b/kernel/exception/irq.c index 003c981a..05c99222 100644 --- a/kernel/exception/irq.c +++ b/kernel/exception/irq.c @@ -49,12 +49,13 @@ #define Build_IRQ(number) \ void IRQ_NAME(number); \ __asm__(SYMBOL_NAME_STR(IRQ) #number "interrupt: \n\t" \ - "pushq $0x00 \n\t" SAVE_ALL_REGS \ - "movq %rsp, %rdi\n\t" \ - "leaq ret_from_intr(%rip), %rax\n\t" \ + "pushq $0x00 \n\t" \ + SAVE_ALL_REGS \ + "movq %rsp, %rdi \n\t" \ + "leaq ret_from_intr(%rip), %rax \n\t" \ "pushq %rax \n\t" \ - "movq $" #number ", %rsi \n\t" \ - "jmp do_IRQ\n\t"); + "movq $"#number", %rsi \n\t" \ + "jmp do_IRQ \n\t"); // 构造中断入口 Build_IRQ(0x20); @@ -168,8 +169,8 @@ void irq_init() #if _INTR_8259A_ init_8259A(); #else - memset(interrupt_desc, 0, sizeof(irq_desc_t) * IRQ_NUM); apic_init(); + memset(interrupt_desc, 0, sizeof(irq_desc_t) * IRQ_NUM); #endif } diff --git a/kernel/exception/trap.c b/kernel/exception/trap.c index b2ad0a6b..bf68be8c 100644 --- a/kernel/exception/trap.c +++ b/kernel/exception/trap.c @@ -1,10 +1,36 @@ #include "trap.h" #include "gate.h" #include "../process/ptrace.h" -#include"../common/kprint.h" +#include "../common/kprint.h" void sys_vector_init() { + set_trap_gate(0, 1, ÷_error); + set_trap_gate(1, 1, &debug); + set_intr_gate(2, 1, &nmi); + set_system_trap_gate(3, 1, &int3); + set_system_trap_gate(4, 1, &overflow); + set_system_trap_gate(5, 1, &bounds); + set_trap_gate(6, 1, &undefined_opcode); + set_trap_gate(7, 1, &dev_not_avaliable); + set_trap_gate(8, 1, &double_fault); + set_trap_gate(9, 1, &coprocessor_segment_overrun); + set_trap_gate(10, 1, &invalid_TSS); + set_trap_gate(11, 1, &segment_not_exists); + set_trap_gate(12, 1, &stack_segment_fault); + set_trap_gate(13, 1, &general_protection); + set_trap_gate(14, 1, &page_fault); + // 中断号15由Intel保留,不能使用 + set_trap_gate(16, 1, &x87_FPU_error); + set_trap_gate(17, 1, &alignment_check); + set_trap_gate(18, 1, &machine_check); + set_trap_gate(19, 1, &SIMD_exception); + set_trap_gate(20, 1, &virtualization_exception); + // 中断号21-31由Intel保留,不能使用 + + // 32-255为用户自定义中断内部 + + /* set_trap_gate(0, 1, divide_error); set_trap_gate(1, 1, debug); set_intr_gate(2, 1, nmi); @@ -26,15 +52,13 @@ void sys_vector_init() set_trap_gate(18, 1, machine_check); set_trap_gate(19, 1, SIMD_exception); set_trap_gate(20, 1, virtualization_exception); - // 中断号21-31由Intel保留,不能使用 - - // 32-255为用户自定义中断内部 + */ } // 0 #DE 除法错误 -void do_divide_error(struct pt_regs * regs, unsigned long error_code) +void do_divide_error(struct pt_regs *regs, unsigned long error_code) { - + kerror("do_divide_error(0),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); while (1) @@ -42,9 +66,8 @@ void do_divide_error(struct pt_regs * regs, unsigned long error_code) } // 1 #DB 调试异常 -void do_debug(struct pt_regs * regs, unsigned long error_code) +void do_debug(struct pt_regs *regs, unsigned long error_code) { - printk("[ "); printk_color(RED, BLACK, "ERROR / TRAP"); printk(" ] do_debug(1),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); @@ -54,9 +77,9 @@ void do_debug(struct pt_regs * regs, unsigned long error_code) } // 2 不可屏蔽中断 -void do_nmi(struct pt_regs * regs, unsigned long error_code) +void do_nmi(struct pt_regs *regs, unsigned long error_code) { - + printk("[ "); printk_color(BLUE, BLACK, "INT"); printk(" ] do_nmi(2),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); @@ -66,9 +89,9 @@ void do_nmi(struct pt_regs * regs, unsigned long error_code) } // 3 #BP 断点异常 -void do_int3(struct pt_regs * regs, unsigned long error_code) +void do_int3(struct pt_regs *regs, unsigned long error_code) { - + printk("[ "); printk_color(YELLOW, BLACK, "TRAP"); printk(" ] do_int3(3),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); @@ -78,9 +101,9 @@ void do_int3(struct pt_regs * regs, unsigned long error_code) } // 4 #OF 溢出异常 -void do_overflow(struct pt_regs * regs, unsigned long error_code) +void do_overflow(struct pt_regs *regs, unsigned long error_code) { - + printk("[ "); printk_color(YELLOW, BLACK, "TRAP"); printk(" ] do_overflow(4),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); @@ -90,9 +113,9 @@ void do_overflow(struct pt_regs * regs, unsigned long error_code) } // 5 #BR 越界异常 -void do_bounds(struct pt_regs * regs, unsigned long error_code) +void do_bounds(struct pt_regs *regs, unsigned long error_code) { - + kerror("do_bounds(5),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); while (1) @@ -100,9 +123,9 @@ void do_bounds(struct pt_regs * regs, unsigned long error_code) } // 6 #UD 无效/未定义的机器码 -void do_undefined_opcode(struct pt_regs * regs, unsigned long error_code) +void do_undefined_opcode(struct pt_regs *regs, unsigned long error_code) { - + kerror("do_undefined_opcode(6),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx", error_code, regs->rsp, regs->rip); while (1) @@ -110,9 +133,9 @@ void do_undefined_opcode(struct pt_regs * regs, unsigned long error_code) } // 7 #NM 设备异常(FPU不存在) -void do_dev_not_avaliable(struct pt_regs * regs, unsigned long error_code) +void do_dev_not_avaliable(struct pt_regs *regs, unsigned long error_code) { - + kerror("do_dev_not_avaliable(7),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); while (1) @@ -120,9 +143,9 @@ void do_dev_not_avaliable(struct pt_regs * regs, unsigned long error_code) } // 8 #DF 双重错误 -void do_double_fault(struct pt_regs * regs, unsigned long error_code) +void do_double_fault(struct pt_regs *regs, unsigned long error_code) { - + printk("[ "); printk_color(RED, BLACK, "Terminate"); printk(" ] do_double_fault(8),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); @@ -132,9 +155,9 @@ void do_double_fault(struct pt_regs * regs, unsigned long error_code) } // 9 协处理器越界(保留) -void do_coprocessor_segment_overrun(struct pt_regs * regs, unsigned long error_code) +void do_coprocessor_segment_overrun(struct pt_regs *regs, unsigned long error_code) { - + kerror("do_coprocessor_segment_overrun(9),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); while (1) @@ -142,9 +165,9 @@ void do_coprocessor_segment_overrun(struct pt_regs * regs, unsigned long error_c } // 10 #TS 无效的TSS段 -void do_invalid_TSS(struct pt_regs * regs, unsigned long error_code) +void do_invalid_TSS(struct pt_regs *regs, unsigned long error_code) { - + printk("["); printk_color(RED, BLACK, "ERROR"); printk("] do_invalid_TSS(10),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); @@ -173,9 +196,9 @@ void do_invalid_TSS(struct pt_regs * regs, unsigned long error_code) } // 11 #NP 段不存在 -void do_segment_not_exists(struct pt_regs * regs, unsigned long error_code) +void do_segment_not_exists(struct pt_regs *regs, unsigned long error_code) { - + kerror("do_segment_not_exists(11),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); while (1) @@ -183,9 +206,9 @@ void do_segment_not_exists(struct pt_regs * regs, unsigned long error_code) } // 12 #SS SS段错误 -void do_stack_segment_fault(struct pt_regs * regs, unsigned long error_code) +void do_stack_segment_fault(struct pt_regs *regs, unsigned long error_code) { - + kerror("do_stack_segment_fault(12),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); while (1) @@ -193,31 +216,31 @@ void do_stack_segment_fault(struct pt_regs * regs, unsigned long error_code) } // 13 #GP 通用保护性异常 -void do_general_protection(struct pt_regs * regs, unsigned long error_code) +void do_general_protection(struct pt_regs *regs, unsigned long error_code) { - + kerror("do_general_protection(13),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); - if(error_code & 0x01) - printk_color(RED,BLACK,"The exception occurred during delivery of an event external to the program,such as an interrupt or an earlier exception.\n"); + if (error_code & 0x01) + printk_color(RED, BLACK, "The exception occurred during delivery of an event external to the program,such as an interrupt or an earlier exception.\n"); - if(error_code & 0x02) - printk_color(RED,BLACK,"Refers to a gate descriptor in the IDT;\n"); - else - printk_color(RED,BLACK,"Refers to a descriptor in the GDT or the current LDT;\n"); + if (error_code & 0x02) + printk_color(RED, BLACK, "Refers to a gate descriptor in the IDT;\n"); + else + printk_color(RED, BLACK, "Refers to a descriptor in the GDT or the current LDT;\n"); - if((error_code & 0x02) == 0) - if(error_code & 0x04) - printk_color(RED,BLACK,"Refers to a segment or gate descriptor in the LDT;\n"); - else - printk_color(RED,BLACK,"Refers to a descriptor in the current GDT;\n"); + if ((error_code & 0x02) == 0) + if (error_code & 0x04) + printk_color(RED, BLACK, "Refers to a segment or gate descriptor in the LDT;\n"); + else + printk_color(RED, BLACK, "Refers to a descriptor in the current GDT;\n"); - printk_color(RED,BLACK,"Segment Selector Index:%#010x\n",error_code & 0xfff8); + printk_color(RED, BLACK, "Segment Selector Index:%#010x\n", error_code & 0xfff8); while (1) ; } // 14 #PF 页故障 -void do_page_fault(struct pt_regs * regs, unsigned long error_code) +void do_page_fault(struct pt_regs *regs, unsigned long error_code) { unsigned long cr2 = 0; // 先保存cr2寄存器的值,避免由于再次触发页故障而丢失值 @@ -225,7 +248,6 @@ void do_page_fault(struct pt_regs * regs, unsigned long error_code) __asm__ __volatile__("movq %%cr2, %0" : "=r"(cr2)::"memory"); - kerror("do_page_fault(14),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\tCR2:%#18lx\n", error_code, regs->rsp, regs->rip, cr2); printk_color(YELLOW, BLACK, "Information:\n"); @@ -255,9 +277,9 @@ void do_page_fault(struct pt_regs * regs, unsigned long error_code) // 15 Intel保留,请勿使用 // 16 #MF x87FPU错误 -void do_x87_FPU_error(struct pt_regs * regs, unsigned long error_code) +void do_x87_FPU_error(struct pt_regs *regs, unsigned long error_code) { - + kerror("do_x87_FPU_error(16),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); while (1) @@ -265,9 +287,9 @@ void do_x87_FPU_error(struct pt_regs * regs, unsigned long error_code) } // 17 #AC 对齐检测 -void do_alignment_check(struct pt_regs * regs, unsigned long error_code) +void do_alignment_check(struct pt_regs *regs, unsigned long error_code) { - + kerror("do_alignment_check(17),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); while (1) @@ -275,9 +297,9 @@ void do_alignment_check(struct pt_regs * regs, unsigned long error_code) } // 18 #MC 机器检测 -void do_machine_check(struct pt_regs * regs, unsigned long error_code) +void do_machine_check(struct pt_regs *regs, unsigned long error_code) { - + kerror("do_machine_check(18),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); while (1) @@ -285,9 +307,9 @@ void do_machine_check(struct pt_regs * regs, unsigned long error_code) } // 19 #XM SIMD浮点异常 -void do_SIMD_exception(struct pt_regs * regs, unsigned long error_code) +void do_SIMD_exception(struct pt_regs *regs, unsigned long error_code) { - + kerror("do_SIMD_exception(19),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); while (1) @@ -295,10 +317,10 @@ void do_SIMD_exception(struct pt_regs * regs, unsigned long error_code) } // 20 #VE 虚拟化异常 -void do_virtualization_exception(struct pt_regs * regs, unsigned long error_code) +void do_virtualization_exception(struct pt_regs *regs, unsigned long error_code) { - - kerror("do_virtualization_exception(20),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); + + kerror("do_virtualization_exception(20),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip); while (1) ; diff --git a/kernel/head.S b/kernel/head.S index 0c0dbdf7..62b1b0bf 100644 --- a/kernel/head.S +++ b/kernel/head.S @@ -297,6 +297,8 @@ _start: add $8, %eax loop .fill_pt +.global enter_head_from_ap_boot +enter_head_from_ap_boot: // 填写 CR3 mov $pml4, %eax mov %eax, %cr3 @@ -349,8 +351,14 @@ ENTRY(_start64) mov %ax, %ss mov %ax, %gs - movq $0x7e00, %rsp - + movq _stack_start(%rip), %rsp + + // 分支,判断是否为apu + movq $0x1b, %rcx // 根据IA32_APIC_BASE.BSP[8]标志位判断处理器是否为apu + rdmsr + bt $8, %rax + jnc load_cr3 + // 2. 设置临时页表 // 最高级 mov $__PML4E, %eax @@ -366,6 +374,7 @@ ENTRY(_start64) // ==== 加载CR3寄存器 +load_cr3: movq $__PML4E, %rax //设置页目录基地址 movq %rax, %cr3 diff --git a/kernel/main.c b/kernel/main.c index 329c22ea..e5f3693a 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -149,7 +149,7 @@ void system_initialize() load_TR(10); // 加载TR寄存器 ul tss_item_addr = 0x7c00; - set_TSS64((ul)TSS64_Table, _stack_start, _stack_start, tss_item_addr, tss_item_addr, + set_TSS64((ul)&TSS64_Table, _stack_start, _stack_start, _stack_start, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr); cpu_core_info[0].stack_start = _stack_start; @@ -165,8 +165,10 @@ void system_initialize() // 初始化中断模块 irq_init(); + kdebug("23232"); smp_init(); - + kdebug("12121221212"); + //smp_ap_start(); hlt(); // 先初始化系统调用模块 syscall_init(); diff --git a/kernel/smp/apu_boot.S b/kernel/smp/apu_boot.S index 7652ce55..feda92e1 100644 --- a/kernel/smp/apu_boot.S +++ b/kernel/smp/apu_boot.S @@ -1,7 +1,7 @@ #include "../common/asm.h" -.balign 0x1000 // 按照4k对齐 +.align 0x1000 // 按照4k对齐 .text .code16 @@ -53,7 +53,7 @@ _apu_boot_base = . .code32 -.balign 4 +.align 0x1000 _apu_code32: # 转到长模式 @@ -63,11 +63,22 @@ _apu_code32: mov %ax, %ss mov %ax, %fs mov %ax, %gs + + // 1. 允许 PAE + mov %cr4, %eax + or $(1<<5), %eax + mov %eax, %cr4 + movl $enter_head_from_ap_boot, %eax + jmpl *%eax + hlt // 设置栈指针 leal (_apu_boot_tmp_stack_end - _apu_boot_base)(%esi), %eax movl %eax, %esp + + + // open PAE movl %cr4, %eax bts $5, %eax @@ -77,16 +88,17 @@ _apu_code32: movl $pml4, %eax // 复用bsp处理器初始化时的32位页表 movl %eax, %cr3 + + movl $0xC0000080, %ecx + rdmsr - mov $0xC0000080, %ecx - rdmsr - or $(1<<8), %eax - wrmsr - - // enable PE and paging 这里有问题 + bts $8, %eax + wrmsr + // enable PE and paging mov %cr0, %eax or $(1<<31), %eax + or $(1<<0), %eax mov %eax, %cr0 // 跳转到64位代码 @@ -94,7 +106,7 @@ _apu_code32: .code64 -.balign 4 +.align 0x1000 _apu_code64: movq $0x20, %rax movq %rax, %ds @@ -119,12 +131,12 @@ _apu_code64: hlt -.balign 4 +.align 0x1000 _apu_tmp_idt: .word 0 .word 0,0 -.balign 4 +.align 0x1000 _apu_tmp_gdt: .short _apu_tmp_gdt_end - _apu_tmp_gdt -1 .long _apu_tmp_gdt - _apu_boot_base @@ -135,19 +147,19 @@ _apu_tmp_gdt: .quad 0x0000920000000000 _apu_tmp_gdt_end: -.balign 4 +.align 0x1000 _apu_code32_vector: .long _apu_code32 - _apu_boot_base .word 0x08,0 -.balign 4 +.align 0x1000 _apu_code64_vector: .long _apu_code64 - _apu_boot_base .word 0x18,0 -.balign 4 +.align 0x1000 _apu_boot_tmp_stack_start: - .org 0x400 +// .org 0x400 _apu_boot_tmp_stack_end: ENTRY(_apu_boot_end) diff --git a/kernel/smp/smp.c b/kernel/smp/smp.c index 5937a260..50237f28 100644 --- a/kernel/smp/smp.c +++ b/kernel/smp/smp.c @@ -23,8 +23,8 @@ void smp_init() //*(uchar *)0x20000 = 0xf4; // 在内存的0x20000处写入HLT指令(AP处理器会执行物理地址0x20000的代码) // 将引导程序复制到物理地址0x20000处 memcpy((unsigned char *)0x20000, _apu_boot_start, (unsigned long)&_apu_boot_end - (unsigned long)&_apu_boot_start); - wrmsr(0x830, 0xc4500); // init IPI + // wrmsr(0x830, 0xc4500); // init IPI struct INT_CMD_REG icr_entry; icr_entry.dest_mode = DEST_PHYSICAL; icr_entry.deliver_status = IDLE; @@ -37,6 +37,14 @@ void smp_init() for (int i = 1; i < total_processor_num; ++i) // i从1开始,不初始化bsp { current_starting_cpu = i; + + icr_entry.vector = 0x00; + icr_entry.deliver_mode = ICR_INIT; + icr_entry.dest_shorthand = ICR_ALL_EXCLUDE_Self; + icr_entry.destination.x2apic_destination = current_starting_cpu; + + wrmsr(0x830, *(unsigned long *)&icr_entry); // INIT IPI + kdebug("[core %d] acpi processor UID=%d, APIC ID=%d, flags=%#010lx", i, proc_local_apic_structs[i]->ACPI_Processor_UID, proc_local_apic_structs[i]->ACPI_ID, proc_local_apic_structs[i]->flags); // 为每个AP处理器分配栈空间、tss空间 cpu_core_info[i].stack_start = (uint64_t)kmalloc(STACK_SIZE, 0) + STACK_SIZE; @@ -45,7 +53,8 @@ void smp_init() set_tss_descriptor(10 + (i * 2), (void *)(cpu_core_info[i].tss_vaddr)); set_TSS64(cpu_core_info[i].tss_vaddr, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start); kdebug("GDT Table %#018lx, \t %#018lx", GDT_Table[10 + i * 2], GDT_Table[10 + i * 2 + 1]); - + kdebug("(cpu_core_info[i].tss_vaddr)=%#018lx", (cpu_core_info[i].tss_vaddr)); + kdebug("(cpu_core_info[i].stack_start)=%#018lx", (cpu_core_info[i].stack_start)); icr_entry.vector = 0x20; icr_entry.deliver_mode = ICR_Start_up; icr_entry.dest_shorthand = ICR_No_Shorthand; @@ -57,7 +66,10 @@ void smp_init() wrmsr(0x830, *(ul *)&icr_entry); // start-up IPI wrmsr(0x830, *(ul *)&icr_entry); // start-up IPI + + } + hlt(); } /** @@ -66,11 +78,69 @@ void smp_init() */ void smp_ap_start() { + // 切换栈基地址 + // uint64_t stack_start = (uint64_t)kmalloc(STACK_SIZE, 0) + STACK_SIZE; + __asm__ __volatile__("movq %0, %%rbp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start) + : "memory"); + __asm__ __volatile__("movq %0, %%rsp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start) + : "memory"); ksuccess("AP core successfully started!"); kdebug("current=%d", current_starting_cpu); - load_TR(10 + current_starting_cpu * 2); apic_init_ap_core_local_apic(); - int a =1/0; // 在这儿会出现异常,cs fs gs ss寄存器会被改变 - + + // apic_init_ap_core_local_apic(); + /* + kinfo("Initializing AP-core's local apic..."); + uint eax, edx; + // 启用xAPIC 和x2APIC + __asm__ __volatile__("movq $0x1b, %%rcx \n\t" // 读取IA32_APIC_BASE寄存器 + "rdmsr \n\t" + "bts $10, %%rax \n\t" + "bts $11, %%rax \n\t" + "wrmsr \n\t" + "movq $0x1b, %%rcx \n\t" + "rdmsr \n\t" + : "=a"(eax), "=d"(edx)::"memory"); + + // kdebug("After enable xAPIC and x2APIC: edx=%#010x, eax=%#010x", edx, eax); + + // 检测是否成功启用xAPIC和x2APIC + if (eax & 0xc00) + kinfo("xAPIC & x2APIC enabled!"); + // 设置SVR寄存器,开启local APIC、禁止EOI广播 + + // enable SVR[8] + __asm__ __volatile__("movq $0x80f, %%rcx \n\t" + "rdmsr \n\t" + "bts $8, %%rax \n\t" + // "bts $12, %%rax\n\t" + "wrmsr \n\t" + "movq $0x80f, %%rcx \n\t" + "rdmsr \n\t" + : "=a"(eax), "=d"(edx) + : + : "memory"); + + if (eax & 0x100) + printk_color(RED, YELLOW, "SVR[8] enabled\n"); + if (edx & 0x1000) + printk_color(RED, YELLOW, "SVR[12] enabled\n"); + + // get local APIC ID + __asm__ __volatile__("movq $0x802, %%rcx \n\t" + "rdmsr \n\t" + : "=a"(eax), "=d"(edx) + : + : "memory"); + + printk_color(RED, YELLOW, "x2APIC ID:%#010x\n", eax); + */ + load_TR(10 + current_starting_cpu * 2); + sti(); + kdebug("IDT_addr = %#018lx", &IDT_Table); + sti(); + //int a = 1 / 0; // 在这儿会出现异常,cs fs gs ss寄存器会被改变 + kdebug("IDT_addr = %#018lx", &IDT_Table); + hlt(); hlt(); } \ No newline at end of file