1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 19:27:44 +00:00

Kernel: Support starting up secondary processors on x86_64

This commit is contained in:
Hendiadyoin1 2021-06-30 14:24:37 +02:00 committed by Andreas Kling
parent 7a1a91d7f2
commit 90cd11fa8c
2 changed files with 47 additions and 33 deletions

View file

@ -354,6 +354,12 @@ apic_ap_start32:
movl (ap_cpu_init_cr3 - apic_ap_start)(%ebp), %eax movl (ap_cpu_init_cr3 - apic_ap_start)(%ebp), %eax
movl %eax, %cr3 movl %eax, %cr3
/* Enter Long-mode! ref(https://wiki.osdev.org/Setting_Up_Long_Mode)*/
mov $0xC0000080, %ecx /* Set the C-register to 0xC0000080, which is the EFER MSR.*/
rdmsr /* Read from the model-specific register.*/
or $(1 << 8), %eax /* Set the LM-bit which is the 9th bit (bit 8).*/
wrmsr /* Write to the model-specific register.*/
/* enable PAE + PSE */ /* enable PAE + PSE */
movl %cr4, %eax movl %cr4, %eax
orl $0x60, %eax orl $0x60, %eax
@ -364,39 +370,48 @@ apic_ap_start32:
orl $0x80000000, %eax orl $0x80000000, %eax
movl %eax, %cr0 movl %eax, %cr0
/* load a second temporary gdt that points above 3GB */ /* load the temporary 64-bit gdt from boot that points above 3GB */
lgdt (ap_cpu_gdtr_initial2 - apic_ap_start + 0xc0008000) lgdt gdt64ptr
/* jump above 3GB into our identity mapped area now */ /* jump above 3GB into our identity mapped area now */
ljmp $8, $(apic_ap_start32_2 - apic_ap_start + 0xc0008000) ljmpl $code64_sel, $(apic_ap_start64 - apic_ap_start + 0xc0008000)
apic_ap_start32_2: .code64
apic_ap_start64:
mov $0, %ax
mov %ax, %ss
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
/* flush the TLB */ /* flush the TLB */
movl %cr3, %eax movq %cr3, %rax
movl %eax, %cr3 movq %rax, %cr3
movl $0xc0008000, %ebp movl $0xc0008000, %ebp
/* now load the final gdt and idt from the identity mapped area */ /* now load the final gdt and idt from the identity mapped area */
movl (ap_cpu_gdtr - apic_ap_start)(%ebp), %eax movq (ap_cpu_gdtr - apic_ap_start)(%rbp), %rax
lgdt (%eax) lgdt (%rax)
movl (ap_cpu_idtr - apic_ap_start)(%ebp), %eax movq (ap_cpu_idtr - apic_ap_start)(%rbp), %rax
lidt (%eax) lidt (%rax)
/* set same cr0 and cr4 values as the BSP */ /* set same cr0 and cr4 values as the BSP */
movl (ap_cpu_init_cr0 - apic_ap_start)(%ebp), %eax movq (ap_cpu_init_cr0 - apic_ap_start)(%rbp), %rax
movl %eax, %cr0 movq %rax, %cr0
movl (ap_cpu_init_cr4 - apic_ap_start)(%ebp), %eax movq (ap_cpu_init_cr4 - apic_ap_start)(%rbp), %rax
movl %eax, %cr4 movq %rax, %cr4
/* push the Processor pointer this CPU is going to use */ /* push the Processor pointer this CPU is going to use */
movl (ap_cpu_init_processor_info_array - apic_ap_start)(%ebp), %eax movq (ap_cpu_init_processor_info_array - apic_ap_start)(%ebp), %rax
addl $0xc0000000, %eax movq $0xc0000000, %r8
movl 0(%eax, %esi, 4), %eax addq %r8, %rax
push %eax movq 0(%rax, %rsi, 4), %rax
push %rax
/* push the cpu id, 0 representing the bsp and call into c++ */ /* push the cpu id, 0 representing the bsp and call into c++ */
incl %esi incq %rsi
push %esi push %rsi
xor %ebp, %ebp xor %ebp, %ebp
cld cld
@ -404,8 +419,10 @@ apic_ap_start32_2:
/* We are in identity mapped P0x8000 and the BSP will unload this code /* We are in identity mapped P0x8000 and the BSP will unload this code
once all APs are initialized, so call init_ap but return to our once all APs are initialized, so call init_ap but return to our
infinite loop */ infinite loop */
push $loop movabs $loop, %rax
ljmp $8, $init_ap pushq %rax
movabs $init_ap, %rax
jmp *(%rax)
.align 4 .align 4
.global apic_ap_start_size .global apic_ap_start_size
@ -427,27 +444,24 @@ ap_cpu_gdt_end:
ap_cpu_gdtr_initial: ap_cpu_gdtr_initial:
.2byte ap_cpu_gdt_end - ap_cpu_gdt - 1 .2byte ap_cpu_gdt_end - ap_cpu_gdt - 1
.4byte (ap_cpu_gdt - apic_ap_start) + 0x8000 .4byte (ap_cpu_gdt - apic_ap_start) + 0x8000
ap_cpu_gdtr_initial2:
.2byte ap_cpu_gdt_end - ap_cpu_gdt - 1
.4byte (ap_cpu_gdt - apic_ap_start) + 0xc0008000
.global ap_cpu_gdtr .global ap_cpu_gdtr
ap_cpu_gdtr: ap_cpu_gdtr:
.4byte 0x0 /* will be set at runtime */ .8byte 0x0 /* will be set at runtime */
.global ap_cpu_idtr .global ap_cpu_idtr
ap_cpu_idtr: ap_cpu_idtr:
.4byte 0x0 /* will be set at runtime */ .8byte 0x0 /* will be set at runtime */
.global ap_cpu_init_cr0 .global ap_cpu_init_cr0
ap_cpu_init_cr0: ap_cpu_init_cr0:
.4byte 0x0 /* will be set at runtime */ .8byte 0x0 /* will be set at runtime */
.global ap_cpu_init_cr3 .global ap_cpu_init_cr3
ap_cpu_init_cr3: ap_cpu_init_cr3:
.4byte 0x0 /* will be set at runtime */ .8byte 0x0 /* will be set at runtime */
.global ap_cpu_init_cr4 .global ap_cpu_init_cr4
ap_cpu_init_cr4: ap_cpu_init_cr4:
.4byte 0x0 /* will be set at runtime */ .8byte 0x0 /* will be set at runtime */
.global ap_cpu_init_processor_info_array .global ap_cpu_init_processor_info_array
ap_cpu_init_processor_info_array: ap_cpu_init_processor_info_array:
.4byte 0x0 /* will be set at runtime */ .8byte 0x0 /* will be set at runtime */
.global ap_cpu_init_stacks .global ap_cpu_init_stacks
ap_cpu_init_stacks: ap_cpu_init_stacks:
/* array of allocated stack pointers */ /* array of allocated stack pointers */

View file

@ -88,7 +88,7 @@ static void setup_serial_debug();
// boot.S expects these functions to exactly have the following signatures. // boot.S expects these functions to exactly have the following signatures.
// We declare them here to ensure their signatures don't accidentally change. // We declare them here to ensure their signatures don't accidentally change.
extern "C" void init_finished(u32 cpu) __attribute__((used)); extern "C" void init_finished(u32 cpu) __attribute__((used));
extern "C" [[noreturn]] void init_ap(u32 cpu, Processor* processor_info); extern "C" [[noreturn]] void init_ap(FlatPtr cpu, Processor* processor_info);
extern "C" [[noreturn]] void init(); extern "C" [[noreturn]] void init();
READONLY_AFTER_INIT VirtualConsole* tty0; READONLY_AFTER_INIT VirtualConsole* tty0;
@ -194,7 +194,7 @@ extern "C" [[noreturn]] UNMAP_AFTER_INIT void init()
// //
// The purpose of init_ap() is to initialize APs for multi-tasking. // The purpose of init_ap() is to initialize APs for multi-tasking.
// //
extern "C" [[noreturn]] UNMAP_AFTER_INIT void init_ap(u32 cpu, Processor* processor_info) extern "C" [[noreturn]] UNMAP_AFTER_INIT void init_ap(FlatPtr cpu, Processor* processor_info)
{ {
processor_info->early_initialize(cpu); processor_info->early_initialize(cpu);