summaryrefslogtreecommitdiff
path: root/Kernel/Arch/x86/i386
diff options
context:
space:
mode:
authorGunnar Beutner <gbeutner@serenityos.org>2021-07-05 00:55:09 +0200
committerAndreas Kling <kling@serenityos.org>2021-07-05 12:28:45 +0200
commit040fe0054b303d25fd094643070bf30b6d55bf50 (patch)
treefb8e107221e765096b24a0fce741c8cc548ab14a /Kernel/Arch/x86/i386
parentce6658acc130a83f6a4468a8ec547f403ac7d042 (diff)
downloadserenity-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.S179
-rw-r--r--Kernel/Arch/x86/i386/Boot/boot.S407
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, .