diff options
author | Gunnar Beutner <gbeutner@serenityos.org> | 2021-07-05 00:55:09 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-07-05 12:28:45 +0200 |
commit | 040fe0054b303d25fd094643070bf30b6d55bf50 (patch) | |
tree | fb8e107221e765096b24a0fce741c8cc548ab14a /Kernel/Arch/x86/i386 | |
parent | ce6658acc130a83f6a4468a8ec547f403ac7d042 (diff) | |
download | serenity-040fe0054b303d25fd094643070bf30b6d55bf50.zip |
Kernel: Merge the x86 and x86_64 boot code into a single file
They're mostly the same apart from some x86_64-specific parts.
Diffstat (limited to 'Kernel/Arch/x86/i386')
-rw-r--r-- | Kernel/Arch/x86/i386/Boot/ap_setup.S | 179 | ||||
-rw-r--r-- | Kernel/Arch/x86/i386/Boot/boot.S | 407 |
2 files changed, 179 insertions, 407 deletions
diff --git a/Kernel/Arch/x86/i386/Boot/ap_setup.S b/Kernel/Arch/x86/i386/Boot/ap_setup.S new file mode 100644 index 0000000000..253df086cb --- /dev/null +++ b/Kernel/Arch/x86/i386/Boot/ap_setup.S @@ -0,0 +1,179 @@ +.set KERNEL_VIRTUAL_BASE, 0xc0000000 + +.extern init_ap +.type init_ap, @function + +/* + The apic_ap_start function will be loaded to P0x00008000 where the APIC + will boot the AP from in real mode. This code also contains space for + special variables that *must* remain here. When initializing the APIC, + the code here gets copied to P0x00008000, the variables in here get + populated and then the the boot of the APs will be triggered. Having + the variables here allows us to access them from real mode. Also, the + code here avoids the need for relocation entries. + + Basically, the variables between apic_ap_start and end_apic_ap_start + *MUST* remain here and cannot be moved into a .bss or any other location. +*/ +.global apic_ap_start +.type apic_ap_start, @function +apic_ap_start: +.code16 + cli + jmp $0x800, $(1f - apic_ap_start) /* avoid relocation entries */ +1: + mov %cs, %ax + mov %ax, %ds + + xor %ax, %ax + mov %ax, %sp + + /* load the first temporary gdt */ + lgdt (ap_cpu_gdtr_initial - apic_ap_start) + + /* enable PM */ + movl %cr0, %eax + orl $1, %eax + movl %eax, %cr0 + + ljmpl $8, $(apic_ap_start32 - apic_ap_start + 0x8000) +apic_ap_start32: +.code32 + mov $0x10, %ax + mov %ax, %ss + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + + movl $0x8000, %ebp + + /* generate a unique ap cpu id (0 means 1st ap, not bsp!) */ + xorl %eax, %eax + incl %eax + lock; xaddl %eax, (ap_cpu_id - apic_ap_start)(%ebp) /* avoid relocation entries */ + movl %eax, %esi + + /* find our allocated stack based on the generated id */ + movl (ap_cpu_init_stacks - apic_ap_start)(%ebp, %eax, 4), %esp + + /* check if we support NX and enable it if we do */ + movl $0x80000001, %eax + cpuid + testl $0x100000, %edx + je (1f - apic_ap_start + 0x8000) + /* turn on IA32_EFER.NXE */ + movl $0xc0000080, %ecx + rdmsr + orl $0x800, %eax + wrmsr +1: + + /* load the bsp's cr3 value */ + movl (ap_cpu_init_cr3 - apic_ap_start)(%ebp), %eax + movl %eax, %cr3 + + /* enable PAE + PSE */ + movl %cr4, %eax + orl $0x60, %eax + movl %eax, %cr4 + + /* enable PG */ + movl %cr0, %eax + orl $0x80000000, %eax + movl %eax, %cr0 + + /* load a second temporary gdt that points above 3GB */ + lgdt (ap_cpu_gdtr_initial2 - apic_ap_start + 0xc0008000) + + /* jump above 3GB into our identity mapped area now */ + ljmp $8, $(apic_ap_start32_2 - apic_ap_start + 0xc0008000) +apic_ap_start32_2: + /* flush the TLB */ + movl %cr3, %eax + movl %eax, %cr3 + + movl $0xc0008000, %ebp + + /* now load the final gdt and idt from the identity mapped area */ + movl (ap_cpu_gdtr - apic_ap_start)(%ebp), %eax + lgdt (%eax) + movl (ap_cpu_idtr - apic_ap_start)(%ebp), %eax + lidt (%eax) + + /* set same cr0 and cr4 values as the BSP */ + movl (ap_cpu_init_cr0 - apic_ap_start)(%ebp), %eax + movl %eax, %cr0 + movl (ap_cpu_init_cr4 - apic_ap_start)(%ebp), %eax + movl %eax, %cr4 + + /* push the Processor pointer this CPU is going to use */ + movl (ap_cpu_init_processor_info_array - apic_ap_start)(%ebp), %eax + addl $KERNEL_VIRTUAL_BASE, %eax + movl 0(%eax, %esi, 4), %eax + push %eax + + /* push the cpu id, 0 representing the bsp and call into c++ */ + incl %esi + push %esi + + xor %ebp, %ebp + cld + + /* 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 + infinite loop */ + push $loop + ljmp $8, $init_ap + +loop: + hlt + jmp loop + +.align 4 +.global apic_ap_start_size +apic_ap_start_size: + .2byte end_apic_ap_start - apic_ap_start +.align 4 +ap_cpu_id: + .4byte 0x0 +ap_cpu_gdt: + /* null */ + .8byte 0x0 + /* code */ + .4byte 0x0000FFFF + .4byte 0x00cf9a00 + /* data */ + .4byte 0x0000FFFF + .4byte 0x00cf9200 +ap_cpu_gdt_end: +ap_cpu_gdtr_initial: + .2byte ap_cpu_gdt_end - ap_cpu_gdt - 1 + .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 +ap_cpu_gdtr: + .4byte 0x0 /* will be set at runtime */ +.global ap_cpu_idtr +ap_cpu_idtr: + .4byte 0x0 /* will be set at runtime */ +.global ap_cpu_init_cr0 +ap_cpu_init_cr0: + .4byte 0x0 /* will be set at runtime */ +.global ap_cpu_init_cr3 +ap_cpu_init_cr3: + .4byte 0x0 /* will be set at runtime */ +.global ap_cpu_init_cr4 +ap_cpu_init_cr4: + .4byte 0x0 /* will be set at runtime */ +.global ap_cpu_init_processor_info_array +ap_cpu_init_processor_info_array: + .4byte 0x0 /* will be set at runtime */ +.global ap_cpu_init_stacks +ap_cpu_init_stacks: + /* array of allocated stack pointers */ + /* NOTE: ap_cpu_init_stacks must be the last variable before + end_apic_ap_start! */ +.set end_apic_ap_start, . diff --git a/Kernel/Arch/x86/i386/Boot/boot.S b/Kernel/Arch/x86/i386/Boot/boot.S deleted file mode 100644 index 06215c6087..0000000000 --- a/Kernel/Arch/x86/i386/Boot/boot.S +++ /dev/null @@ -1,407 +0,0 @@ -.set KERNEL_VIRTUAL_BASE, 0xc0000000 - -.section .stack, "aw", @nobits -stack_bottom: -.skip 32768 -stack_top: - -.global kernel_cmdline -kernel_cmdline: -.skip 4096 - -.section .page_tables, "aw", @nobits -.align 4096 -.global boot_pdpt -boot_pdpt: -.skip 4096 -.global boot_pd0 -boot_pd0: -.skip 4096 -.global boot_pd3 -boot_pd3: -.skip 4096 -.global boot_pd0_pt0 -boot_pd0_pt0: -.skip 4096 * 4 -.global boot_pd3_pts -boot_pd3_pts: -.skip 4096 * 16 -.global boot_pd3_pt1023 -boot_pd3_pt1023: -.skip 4096 - -.section .boot_text, "ax" - -.global start -.type start, @function - -.extern init -.type init, @function - -.extern multiboot_info_ptr -.type multiboot_info_ptr, @object - -/* - construct the following (32-bit PAE) page table layout: - -pdpt - - 0: boot_pd0 (0-1GB) - 1: n/a (1-2GB) - 2: n/a (2-3GB) - 3: boot_pd3 (3-4GB) - -boot_pd0 : 512 pde's - - 0: boot_pd0_pt0 (0-2MB) (id 512 4KB pages) - -boot_pd3 : 512 pde's - - 0: boot_pd3_pts[0] (3072-3074MB) (pseudo 512 4KB pages) - 1: boot_pd3_pts[1] (3074-3076MB) (pseudo 512 4KB pages) - 2: boot_pd3_pts[2] (3076-3078MB) (pseudo 512 4KB pages) - 3: boot_pd3_pts[3] (3078-3080MB) (pseudo 512 4KB pages) - 4: boot_pd3_pts[4] (3080-3082MB) (pseudo 512 4KB pages) - 5: boot_pd3_pts[5] (3082-3084MB) (pseudo 512 4KB pages) - 6: boot_pd3_pts[6] (3084-3086MB) (pseudo 512 4KB pages) - 7: boot_pd3_pts[7] (3086-3088MB) (pseudo 512 4KB pages) - - 8: boot_pd3_pts[8] (3088-3090MB) (pseudo 512 4KB pages) - 9: boot_pd3_pts[9] (3090-3076MB) (pseudo 512 4KB pages) - 10: boot_pd3_pts[10] (3092-3094MB) (pseudo 512 4KB pages) - 11: boot_pd3_pts[11] (3094-3096MB) (pseudo 512 4KB pages) - 12: boot_pd3_pts[12] (3096-3098MB) (pseudo 512 4KB pages) - 13: boot_pd3_pts[13] (3098-3100MB) (pseudo 512 4KB pages) - 14: boot_pd3_pts[14] (3100-3102MB) (pseudo 512 4KB pages) - 15: boot_pd3_pts[15] (3102-3104MB) (pseudo 512 4KB pages) - - 16: boot_pd3_pt1023 (4094-4096MB) (for page table mappings) - -the 9 page tables each contain 512 pte's that map individual 4KB pages - -*/ - -start: - cli - cld - - /* We don't know where the bootloader might have put the command line. - * It might be at an inconvenient location that we're not about to map, - * so let's just copy it to a convenient location while we have the whole - * memory space identity-mapped anyway. :^) - */ - - movl %ebx, %esi - addl $16, %esi - movl (%esi), %esi - movl $1024, %ecx - movl $(kernel_cmdline - KERNEL_VIRTUAL_BASE), %edi - rep movsl - - /* clear pdpt */ - movl $(boot_pdpt - KERNEL_VIRTUAL_BASE), %edi - movl $1024, %ecx - xorl %eax, %eax - rep stosl - - /* set up pdpt[0] and pdpt[3] */ - movl $(boot_pdpt - KERNEL_VIRTUAL_BASE), %edi - movl $((boot_pd0 - KERNEL_VIRTUAL_BASE) + 1), 0(%edi) - movl $((boot_pd3 - KERNEL_VIRTUAL_BASE) + 1), 24(%edi) - - /* clear pd0 */ - movl $(boot_pd0 - KERNEL_VIRTUAL_BASE), %edi - movl $1024, %ecx - xorl %eax, %eax - rep stosl - - /* clear pd3 */ - movl $(boot_pd3 - KERNEL_VIRTUAL_BASE), %edi - movl $1024, %ecx - xorl %eax, %eax - rep stosl - - /* clear pd0's pt's */ - movl $(boot_pd0_pt0 - KERNEL_VIRTUAL_BASE), %edi - movl $(1024 * 4), %ecx - xorl %eax, %eax - rep stosl - - /* clear pd3's pt's */ - movl $(boot_pd3_pts - KERNEL_VIRTUAL_BASE), %edi - movl $(1024 * 17), %ecx - xorl %eax, %eax - rep stosl - - /* add boot_pd0_pt0 to boot_pd0 */ - movl $(boot_pd0 - KERNEL_VIRTUAL_BASE), %edi - movl $(boot_pd0_pt0 - KERNEL_VIRTUAL_BASE), %eax - movl %eax, 0(%edi) - /* R/W + Present */ - orl $0x3, 0(%edi) - - /* add boot_pd3_pts to boot_pd3 */ - movl $16, %ecx - movl $(boot_pd3 - KERNEL_VIRTUAL_BASE), %edi - movl $(boot_pd3_pts - KERNEL_VIRTUAL_BASE), %eax - -1: - movl %eax, 0(%edi) - /* R/W + Present */ - orl $0x3, 0(%edi) - addl $8, %edi - addl $4096, %eax - loop 1b - - /* identity map the 0 to 2MB range */ - movl $512, %ecx - movl $(boot_pd0_pt0 - KERNEL_VIRTUAL_BASE), %edi - xorl %eax, %eax - -1: - movl %eax, 0(%edi) - /* R/W + Present */ - orl $0x3, 0(%edi) - addl $8, %edi - addl $4096, %eax - loop 1b - - /* pseudo identity map the 3072-3102MB range */ - movl $(512 * 16), %ecx - movl $(boot_pd3_pts - KERNEL_VIRTUAL_BASE), %edi - xorl %eax, %eax - -1: - movl %eax, 0(%edi) - /* R/W + Present */ - orl $0x3, 0(%edi) - addl $8, %edi - addl $4096, %eax - loop 1b - - /* create an empty page table for the top 2MB at the 4GB mark */ - movl $(boot_pd3 - KERNEL_VIRTUAL_BASE), %edi - movl $(boot_pd3_pt1023 - KERNEL_VIRTUAL_BASE), 4088(%edi) - orl $0x3, 4088(%edi) - movl $0, 4092(%edi) - - /* point CR3 to PDPT */ - movl $(boot_pdpt - KERNEL_VIRTUAL_BASE), %eax - movl %eax, %cr3 - - /* enable PAE + PSE */ - movl %cr4, %eax - orl $0x60, %eax - movl %eax, %cr4 - - /* enable PG */ - movl %cr0, %eax - orl $0x80000000, %eax - movl %eax, %cr0 - - /* set up stack */ - mov $stack_top, %esp - and $-16, %esp - - /* jmp to an address above the 3GB mark */ - movl $1f,%eax - jmp *%eax -1: - movl %cr3, %eax - movl %eax, %cr3 - - /* unmap the 0-1MB range, which isn't used after jmp-ing up here */ - movl $256, %ecx - movl $(boot_pd0_pt0 - KERNEL_VIRTUAL_BASE), %edi - xorl %eax, %eax - -1: - movl %eax, 0(%edi) - addl $8, %edi - loop 1b - - /* jump into C++ land */ - addl $KERNEL_VIRTUAL_BASE, %ebx - movl %ebx, multiboot_info_ptr - - call init - add $4, %esp - - cli -loop: - hlt - jmp loop - -.extern init_ap -.type init_ap, @function - -/* - The apic_ap_start function will be loaded to P0x00008000 where the APIC - will boot the AP from in real mode. This code also contains space for - special variables that *must* remain here. When initializing the APIC, - the code here gets copied to P0x00008000, the variables in here get - populated and then the the boot of the APs will be triggered. Having - the variables here allows us to access them from real mode. Also, the - code here avoids the need for relocation entries. - - Basically, the variables between apic_ap_start and end_apic_ap_start - *MUST* remain here and cannot be moved into a .bss or any other location. -*/ -.global apic_ap_start -.type apic_ap_start, @function -apic_ap_start: -.code16 - cli - jmp $0x800, $(1f - apic_ap_start) /* avoid relocation entries */ -1: - mov %cs, %ax - mov %ax, %ds - - xor %ax, %ax - mov %ax, %sp - - /* load the first temporary gdt */ - lgdt (ap_cpu_gdtr_initial - apic_ap_start) - - /* enable PM */ - movl %cr0, %eax - orl $1, %eax - movl %eax, %cr0 - - ljmpl $8, $(apic_ap_start32 - apic_ap_start + 0x8000) -apic_ap_start32: -.code32 - mov $0x10, %ax - mov %ax, %ss - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - - movl $0x8000, %ebp - - /* generate a unique ap cpu id (0 means 1st ap, not bsp!) */ - xorl %eax, %eax - incl %eax - lock; xaddl %eax, (ap_cpu_id - apic_ap_start)(%ebp) /* avoid relocation entries */ - movl %eax, %esi - - /* find our allocated stack based on the generated id */ - movl (ap_cpu_init_stacks - apic_ap_start)(%ebp, %eax, 4), %esp - - /* check if we support NX and enable it if we do */ - movl $0x80000001, %eax - cpuid - testl $0x100000, %edx - je (1f - apic_ap_start + 0x8000) - /* turn on IA32_EFER.NXE */ - movl $0xc0000080, %ecx - rdmsr - orl $0x800, %eax - wrmsr -1: - - /* load the bsp's cr3 value */ - movl (ap_cpu_init_cr3 - apic_ap_start)(%ebp), %eax - movl %eax, %cr3 - - /* enable PAE + PSE */ - movl %cr4, %eax - orl $0x60, %eax - movl %eax, %cr4 - - /* enable PG */ - movl %cr0, %eax - orl $0x80000000, %eax - movl %eax, %cr0 - - /* load a second temporary gdt that points above 3GB */ - lgdt (ap_cpu_gdtr_initial2 - apic_ap_start + 0xc0008000) - - /* jump above 3GB into our identity mapped area now */ - ljmp $8, $(apic_ap_start32_2 - apic_ap_start + 0xc0008000) -apic_ap_start32_2: - /* flush the TLB */ - movl %cr3, %eax - movl %eax, %cr3 - - movl $0xc0008000, %ebp - - /* now load the final gdt and idt from the identity mapped area */ - movl (ap_cpu_gdtr - apic_ap_start)(%ebp), %eax - lgdt (%eax) - movl (ap_cpu_idtr - apic_ap_start)(%ebp), %eax - lidt (%eax) - - /* set same cr0 and cr4 values as the BSP */ - movl (ap_cpu_init_cr0 - apic_ap_start)(%ebp), %eax - movl %eax, %cr0 - movl (ap_cpu_init_cr4 - apic_ap_start)(%ebp), %eax - movl %eax, %cr4 - - /* push the Processor pointer this CPU is going to use */ - movl (ap_cpu_init_processor_info_array - apic_ap_start)(%ebp), %eax - addl $KERNEL_VIRTUAL_BASE, %eax - movl 0(%eax, %esi, 4), %eax - push %eax - - /* push the cpu id, 0 representing the bsp and call into c++ */ - incl %esi - push %esi - - xor %ebp, %ebp - cld - - /* 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 - infinite loop */ - push $loop - ljmp $8, $init_ap - -.align 4 -.global apic_ap_start_size -apic_ap_start_size: - .2byte end_apic_ap_start - apic_ap_start -.align 4 -ap_cpu_id: - .4byte 0x0 -ap_cpu_gdt: - /* null */ - .8byte 0x0 - /* code */ - .4byte 0x0000FFFF - .4byte 0x00cf9a00 - /* data */ - .4byte 0x0000FFFF - .4byte 0x00cf9200 -ap_cpu_gdt_end: -ap_cpu_gdtr_initial: - .2byte ap_cpu_gdt_end - ap_cpu_gdt - 1 - .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 -ap_cpu_gdtr: - .4byte 0x0 /* will be set at runtime */ -.global ap_cpu_idtr -ap_cpu_idtr: - .4byte 0x0 /* will be set at runtime */ -.global ap_cpu_init_cr0 -ap_cpu_init_cr0: - .4byte 0x0 /* will be set at runtime */ -.global ap_cpu_init_cr3 -ap_cpu_init_cr3: - .4byte 0x0 /* will be set at runtime */ -.global ap_cpu_init_cr4 -ap_cpu_init_cr4: - .4byte 0x0 /* will be set at runtime */ -.global ap_cpu_init_processor_info_array -ap_cpu_init_processor_info_array: - .4byte 0x0 /* will be set at runtime */ -.global ap_cpu_init_stacks -ap_cpu_init_stacks: - /* array of allocated stack pointers */ - /* NOTE: ap_cpu_init_stacks must be the last variable before - end_apic_ap_start! */ -.set end_apic_ap_start, . |