Bladeren bron

:new: AP处理器切换到64位模式

fslongjin 2 jaren geleden
bovenliggende
commit
5197253dde
7 gewijzigde bestanden met toevoegingen van 172 en 3 verwijderingen
  1. 6 2
      kernel/Makefile
  2. 1 0
      kernel/head.S
  3. 150 0
      kernel/smp/apu_boot.S
  4. 0 0
      kernel/smp/boot_apu.S
  5. 11 0
      kernel/smp/smp.c
  6. 3 0
      kernel/smp/smp.h
  7. 1 1
      run.sh

+ 6 - 2
kernel/Makefile

@@ -19,9 +19,9 @@ all: kernel
 	objcopy -I elf64-x86-64 -O elf64-x86-64 -R ".comment" -R ".eh_frame" kernel ../bin/kernel/kernel.elf
 #
 
-kernel: head.o entry.o main.o printk.o trap.o mm.o slab.o irq.o pic.o process.o syscall.o multiboot2.o cpu.o acpi.o ps2_keyboard.o ps2_mouse.o ata.o pci.o ahci.o smp.o
+kernel: head.o entry.o main.o printk.o trap.o mm.o slab.o irq.o pic.o process.o syscall.o multiboot2.o cpu.o acpi.o ps2_keyboard.o ps2_mouse.o ata.o pci.o ahci.o smp.o apu_boot.o
 	ld -b elf64-x86-64 -z muldefs -o kernel head.o exception/entry.o main.o common/printk.o exception/trap.o exception/irq.o mm/mm.o mm/slab.o process/process.o syscall/syscall.o driver/multiboot2/multiboot2.o \
-	common/cpu.o smp/smp.o 	\
+	common/cpu.o smp/smp.o smp/apu_boot.o	\
 	driver/acpi/acpi.o driver/interrupt/pic.o driver/keyboard/ps2_keyboard.o driver/mouse/ps2_mouse.o driver/disk/ata.o driver/pci/pci.o driver/disk/ahci/ahci.o \
 	-T link.lds
 
@@ -67,6 +67,10 @@ syscall.o: syscall/syscall.c
 smp.o: smp/smp.c 
 	gcc $(CFLAGS) -c smp/smp.c  -o smp/smp.o 
 
+apu_boot.o: smp/apu_boot.S
+	gcc -E smp/apu_boot.S > smp/apu_boot.s # 预处理
+	as $(ASFLAGS) -o smp/apu_boot.o smp/apu_boot.s
+
 cpu.o: common/cpu.c 
 	gcc $(CFLAGS) -c common/cpu.c -o common/cpu.o
 

+ 1 - 0
kernel/head.S

@@ -193,6 +193,7 @@ multiboot_header_end:
 // 临时页表 4KB/页
 .section .data
 .align 0x1000
+.global pml4
 pml4:
     .skip 0x1000
 pdpt:

+ 150 - 0
kernel/smp/apu_boot.S

@@ -0,0 +1,150 @@
+#include "../common/asm.h"
+
+
+.balign 0x1000  // 按照4k对齐
+
+.text
+.code16
+
+ENTRY(_apu_boot_start)
+_apu_boot_base = .
+    cli
+    wbinvd  // 将处理器缓存同步到内存中
+
+    mov %cs, %ax
+    mov %ax, %ds
+    mov %ax, %es
+    mov %ax, %ss
+    mov %ax, %fs
+    mov %ax, %gs
+
+    // 设置栈指针
+    movl $(_apu_boot_tmp_stack_end - _apu_boot_base), %esp
+    
+    // 计算ap处理器引导程序的基地址
+    mov %cs, %ax
+    movzx %ax, %esi
+    shll $4, %esi
+
+
+    // set gdt and 32bit/64bit code addr
+
+    leal (_apu_code32 - _apu_boot_base)(%esi), %eax
+    movl %eax, (_apu_code32_vector - _apu_boot_base)
+
+    leal (_apu_code64 - _apu_boot_base)(%esi), %eax
+    movl %eax, (_apu_code64_vector - _apu_boot_base)
+
+    leal (_apu_tmp_gdt - _apu_boot_base)(%esi), %eax
+    movl %eax, (_apu_tmp_gdt + 2 - _apu_boot_base)
+    
+// 从实模式切换到保护模式
+
+    lidtl _apu_tmp_idt - _apu_boot_base
+    lgdtl _apu_tmp_gdt - _apu_boot_base
+
+    // 操作cr0控制器,使能保护模式
+    smsw %ax
+    bts $0, %ax
+    lmsw %ax
+
+    // 转到保护模式
+    ljmpl *(_apu_code32_vector - _apu_boot_base)
+
+
+.code32
+.balign 4
+_apu_code32:
+    # 转到长模式
+
+    mov $0x10, %ax
+    mov %ax, %ds
+    mov %ax, %es
+    mov %ax, %ss
+    mov %ax, %fs
+    mov %ax, %gs
+
+    // 设置栈指针
+    leal (_apu_boot_tmp_stack_end - _apu_boot_base)(%esi), %eax
+    movl %eax, %esp
+
+    // open PAE
+    movl %cr4, %eax
+    bts $5, %eax
+    movl %eax, %cr4
+
+    // 设置页表
+
+    movl $pml4, %eax    // 复用bsp处理器初始化时的32位页表
+    movl %eax, %cr3
+
+    mov $0xC0000080, %ecx
+    rdmsr
+    or $(1<<8), %eax
+    wrmsr
+
+    // enable PE and paging 这里有问题
+
+    mov %cr0, %eax
+    or $(1<<31), %eax
+    mov %eax, %cr0
+
+    // 跳转到64位代码
+    ljmp *(_apu_code64_vector - _apu_boot_base)(%esi)
+
+
+.code64
+.balign 4
+_apu_code64:
+    movq $0x20, %rax
+    movq %rax, %ds
+    movq %rax, %es
+    movq %rax, %ss
+    movq %rax, %fs
+    movq %rax, %gs
+
+    //now enable SSE and the like
+    movq %cr0, %rax
+    and $0xFFFB, %ax		//clear coprocessor emulation CR0.EM
+    or $0x2, %ax			//set coprocessor monitoring  CR0.MP
+    movq %rax, %cr0
+    movq %cr4, %rax
+    or $(3 << 9), %ax		//set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
+    movq %rax, %cr4
+
+    hlt
+
+
+.balign 4
+_apu_tmp_idt:
+	.word	0
+	.word	0,0
+
+.balign 4
+_apu_tmp_gdt:
+    .short _apu_tmp_gdt_end - _apu_tmp_gdt -1
+    .long _apu_tmp_gdt - _apu_boot_base
+    .short 0
+    .quad	0x00cf9a000000ffff
+	.quad	0x00cf92000000ffff
+	.quad	0x0020980000000000
+	.quad	0x0000920000000000
+_apu_tmp_gdt_end:
+
+.balign 4
+_apu_code32_vector:
+	.long	_apu_code32 - _apu_boot_base
+	.word	0x08,0	
+
+.balign 4
+_apu_code64_vector:
+	.long	_apu_code64 - _apu_boot_base
+	.word	0x18,0	
+
+.balign 4
+_apu_boot_tmp_stack_start:
+	.org	0x400
+_apu_boot_tmp_stack_end:
+
+ENTRY(_apu_boot_end)
+

+ 0 - 0
kernel/smp/boot_apu.S


+ 11 - 0
kernel/smp/smp.c

@@ -17,4 +17,15 @@ void smp_init()
     {
         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);
     }
+
+    //*(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);
+
+    // 先init ipi, 然后连续发送两次start-up IPI
+    // x2APIC下,ICR寄存器地址为0x830
+    // xAPIC下则为0xfee00300(31-0) 0xfee00310 (63-32)
+    wrmsr(0x830, 0xc4500);  // init IPI
+    wrmsr(0x830, 0xc4620);  // start-up IPI
+    wrmsr(0x830, 0xc4620);  // start-up IPI
 }

+ 3 - 0
kernel/smp/smp.h

@@ -5,6 +5,9 @@
 #include "../driver/interrupt/apic/apic.h"
 
 #define MAX_SUPPORTED_PROCESSOR_NUM 1024    // 操作系统支持的最大处理器数量
+
+extern uchar _apu_boot_start[];
+extern uchar _apu_boot_end[];
 /**
  * @brief 初始化对称多核处理器
  *

+ 1 - 1
run.sh

@@ -93,7 +93,7 @@ if [ $flag_can_run -eq 1 ]; then
         bochs -q -f ${bochsrc} -rc ./tools/bochsinit
     else
         qemu-system-x86_64 -cdrom ${iso} -m 512M -smp 2,cores=2,threads=1,sockets=1 \
-        -monitor telnet::2333,server,nowait -serial stdio -s -S -cpu IvyBridge --enable-kvm \
+        -monitor stdio -s -S -cpu IvyBridge --enable-kvm \
         -drive id=disk,file=bin/disk.img,if=none \
         -device ahci,id=ahci \
         -device ide-hd,drive=disk,bus=ahci.0    \