Use physical addresses in boot segments

This commit is contained in:
Ruihan Li
2024-12-07 23:50:52 +08:00
committed by Tate, Hongliang Tian
parent a3ae1aa28a
commit 18d5eb1f02
4 changed files with 52 additions and 56 deletions

View File

@ -30,11 +30,11 @@ PHDRS
# segment to prevent this from happening. # segment to prevent this from happening.
header PT_LOAD FLAGS(4); # R__ header PT_LOAD FLAGS(4); # R__
# Boot segments. # Boot segments. Addresses are physical.
bsp_boot PT_LOAD FLAGS(7); # RWE bsp_boot PT_LOAD FLAGS(7); # RWE
ap_boot PT_LOAD FLAGS(7); # RWE ap_boot PT_LOAD FLAGS(7); # RWE
# Normal segments. # Normal segments. Addresses are virtual.
text PT_LOAD FLAGS(5); # R_E text PT_LOAD FLAGS(5); # R_E
rodata PT_LOAD FLAGS(4); # R__ rodata PT_LOAD FLAGS(4); # R__
data PT_LOAD FLAGS(6); # RW_ data PT_LOAD FLAGS(6); # RW_
@ -57,22 +57,21 @@ SECTIONS
} : header } : header
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# These are 2 boot sections that need specific physical addresses. But they # # These are 2 boot sections that need specific physical addresses. #
# should use virtual symbols. #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
. = BSP_BOOT_LMA + KERNEL_VMA; . = BSP_BOOT_LMA;
.bsp_boot : AT(BSP_BOOT_LMA) { .bsp_boot : AT(BSP_BOOT_LMA) {
KEEP(*(.bsp_boot .bsp_boot.*)) KEEP(*(.bsp_boot .bsp_boot.*))
. = ALIGN(4096); . = ALIGN(4096);
} : bsp_boot } : bsp_boot
. = AP_EXEC_MA + KERNEL_VMA; . = AP_EXEC_MA;
.ap_boot : AT(BSP_BOOT_LMA + SIZEOF(.bsp_boot)) { .ap_boot : AT(BSP_BOOT_LMA + SIZEOF(.bsp_boot)) {
__ap_boot_start = . - AP_EXEC_MA + BSP_BOOT_LMA + SIZEOF(.bsp_boot); __ap_boot_start = BSP_BOOT_LMA + SIZEOF(.bsp_boot) + KERNEL_VMA;
KEEP(*(.ap_boot .ap_boot.*)) KEEP(*(.ap_boot .ap_boot.*))
__ap_boot_end = . - AP_EXEC_MA + BSP_BOOT_LMA + SIZEOF(.bsp_boot); __ap_boot_end = __ap_boot_start + (. - AP_EXEC_MA);
. = ALIGN(4096); . = ALIGN(4096);
} : ap_boot } : ap_boot

View File

@ -6,8 +6,6 @@
.extern boot_page_table_start .extern boot_page_table_start
.extern ap_early_entry .extern ap_early_entry
KERNEL_VMA = 0xffffffff80000000
.section ".ap_boot", "awx" .section ".ap_boot", "awx"
.align 4096 .align 4096
.code16 .code16
@ -23,13 +21,13 @@ ap_real_mode_boot:
xor ax, ax // clear ax xor ax, ax // clear ax
mov ds, ax // clear ds mov ds, ax // clear ds
lgdt [ap_gdtr - KERNEL_VMA] // load gdt lgdt [ap_gdtr] // load gdt
mov eax, cr0 mov eax, cr0
or eax, 1 or eax, 1
mov cr0, eax // enable protected mode mov cr0, eax // enable protected mode
ljmp 0x8, offset ap_protect_entry - KERNEL_VMA ljmp 0x8, offset ap_protect_entry
// 32-bit AP GDT. // 32-bit AP GDT.
.align 16 .align 16
@ -44,7 +42,7 @@ ap_gdt_end:
.align 16 .align 16
ap_gdtr: ap_gdtr:
.word ap_gdt_end - ap_gdt - 1 .word ap_gdt_end - ap_gdt - 1
.quad ap_gdt - KERNEL_VMA .quad ap_gdt
.align 4 .align 4
.code32 .code32
@ -95,7 +93,7 @@ ap_protect:
// Now we try getting into long mode. // Now we try getting into long mode.
// Use the 64-bit GDT. // Use the 64-bit GDT.
lgdt [boot_gdtr - KERNEL_VMA] lgdt [boot_gdtr]
// Enable PAE and PGE. // Enable PAE and PGE.
mov eax, cr4 mov eax, cr4
@ -105,7 +103,7 @@ ap_protect:
// Set the page table. The application processors use // Set the page table. The application processors use
// the same page table as the bootstrap processor's // the same page table as the bootstrap processor's
// boot phase page table. // boot phase page table.
lea eax, [boot_page_table_start - KERNEL_VMA] lea eax, [boot_page_table_start]
mov cr3, eax mov cr3, eax
// Enable long mode. // Enable long mode.
@ -119,10 +117,9 @@ ap_protect:
or eax, 1 << 31 or eax, 1 << 31
mov cr0, eax mov cr0, eax
ljmp 0x8, offset ap_long_mode_in_low_address - KERNEL_VMA ljmp 0x8, offset ap_long_mode_in_low_address
.code64 .code64
ap_long_mode_in_low_address: ap_long_mode_in_low_address:
mov ax, 0 mov ax, 0
mov ds, ax mov ds, ax
@ -132,18 +129,19 @@ ap_long_mode_in_low_address:
mov gs, ax mov gs, ax
// Update RIP to use the virtual address. // Update RIP to use the virtual address.
mov rbx, KERNEL_VMA mov rax, offset ap_long_mode
lea rax, [ap_long_mode - KERNEL_VMA]
or rax, rbx
jmp rax jmp rax
// This is a pointer to be filled by the BSP when boot stacks // This is a pointer to be filled by the BSP when boot stacks
// of all APs are allocated and initialized. // of all APs are allocated and initialized.
.data
.global __ap_boot_stack_array_pointer .global __ap_boot_stack_array_pointer
.align 8 .align 8
__ap_boot_stack_array_pointer: __ap_boot_stack_array_pointer:
.skip 8 .skip 8
.text
.code64
ap_long_mode: ap_long_mode:
// The local APIC ID is in the RDI. // The local APIC ID is in the RDI.
mov rax, rdi mov rax, rdi
@ -158,4 +156,5 @@ ap_long_mode:
mov rax, offset ap_early_entry mov rax, offset ap_early_entry
call rax call rax
hlt .extern halt # bsp_boot.S
jmp halt

View File

@ -31,7 +31,7 @@ __linux32_boot:
cld cld
// Set the kernel call stack. // Set the kernel call stack.
mov esp, offset boot_stack_top - KERNEL_VMA mov esp, offset boot_stack_top
push 0 // upper 32-bits push 0 // upper 32-bits
push esi // boot_params ptr push esi // boot_params ptr
@ -47,7 +47,7 @@ __linux32_boot:
.global __linux64_boot_tag .global __linux64_boot_tag
__linux64_boot_tag: __linux64_boot_tag:
// Set the kernel call stack. // Set the kernel call stack.
lea rsp, [boot_stack_top - KERNEL_VMA] lea rsp, [boot_stack_top]
push rsi // boot_params ptr from the loader push rsi // boot_params ptr from the loader
push ENTRYTYPE_LINUX_64 push ENTRYTYPE_LINUX_64
@ -62,7 +62,7 @@ __multiboot_boot:
cld cld
// Set the kernel call stack. // Set the kernel call stack.
mov esp, offset boot_stack_top - KERNEL_VMA mov esp, offset boot_stack_top
push 0 // Upper 32-bits. push 0 // Upper 32-bits.
push eax // multiboot magic ptr push eax // multiboot magic ptr
@ -87,11 +87,11 @@ initial_boot_setup:
// Prepare for far return. We use a far return as a fence after setting GDT. // Prepare for far return. We use a far return as a fence after setting GDT.
mov eax, 24 mov eax, 24
push eax push eax
lea edx, [protected_mode - KERNEL_VMA] lea edx, [protected_mode]
push edx push edx
// Switch to our own temporary GDT. // Switch to our own temporary GDT.
lgdt [boot_gdtr - KERNEL_VMA] lgdt [boot_gdtr]
retf retf
protected_mode: protected_mode:
@ -105,8 +105,8 @@ protected_mode:
page_table_setup: page_table_setup:
// Zero out the page table. // Zero out the page table.
mov al, 0x00 mov al, 0x00
lea edi, [boot_page_table_start - KERNEL_VMA] lea edi, [boot_page_table_start]
lea ecx, [boot_page_table_end - KERNEL_VMA] lea ecx, [boot_page_table_end]
sub ecx, edi sub ecx, edi
cld cld
rep stosb rep stosb
@ -121,8 +121,8 @@ PTE_GLOBAL = (1 << 8)
// 0x00000000_40000000 ~ 0x00000000_7fffffff // 0x00000000_40000000 ~ 0x00000000_7fffffff
// 0x00000000_80000000 ~ 0x00000000_bfffffff // 0x00000000_80000000 ~ 0x00000000_bfffffff
// 0x00000000_c0000000 ~ 0x00000000_ffffffff // 0x00000000_c0000000 ~ 0x00000000_ffffffff
lea edi, [boot_pml4 - KERNEL_VMA] lea edi, [boot_pml4]
lea eax, [boot_pdpt - KERNEL_VMA + (PTE_PRESENT | PTE_WRITE)] lea eax, [boot_pdpt + (PTE_PRESENT | PTE_WRITE)]
mov dword ptr [edi], eax mov dword ptr [edi], eax
mov dword ptr [edi + 4], 0 mov dword ptr [edi + 4], 0
@ -131,56 +131,56 @@ PTE_GLOBAL = (1 << 8)
// 0xffff8000_80000000 ~ 0xffff8000_bfffffff // 0xffff8000_80000000 ~ 0xffff8000_bfffffff
// 0xffff8000_c0000000 ~ 0xffff8000_ffffffff // 0xffff8000_c0000000 ~ 0xffff8000_ffffffff
// 0xffff8008_00000000 ~ 0xffff8008_3fffffff // 0xffff8008_00000000 ~ 0xffff8008_3fffffff
lea edi, [boot_pml4 - KERNEL_VMA + 0x100 * 8] lea edi, [boot_pml4 + 0x100 * 8]
lea eax, [boot_pdpt - KERNEL_VMA + (PTE_PRESENT | PTE_WRITE)] lea eax, [boot_pdpt + (PTE_PRESENT | PTE_WRITE)]
mov dword ptr [edi], eax mov dword ptr [edi], eax
mov dword ptr [edi + 4], 0 mov dword ptr [edi + 4], 0
// PML4: 0xffffffff_80000000 ~ 0xffffffff_bfffffff // PML4: 0xffffffff_80000000 ~ 0xffffffff_bfffffff
// 0xffffffff_c0000000 ~ 0xffffffff_ffffffff // 0xffffffff_c0000000 ~ 0xffffffff_ffffffff
lea edi, [boot_pml4 - KERNEL_VMA + 0x1ff * 8] lea edi, [boot_pml4 + 0x1ff * 8]
lea eax, [boot_pdpt - KERNEL_VMA + (PTE_PRESENT | PTE_WRITE)] lea eax, [boot_pdpt + (PTE_PRESENT | PTE_WRITE)]
mov dword ptr [edi], eax mov dword ptr [edi], eax
mov dword ptr [edi + 4], 0 mov dword ptr [edi + 4], 0
// PDPT: 0x00000000_00000000 ~ 0x00000000_3fffffff // PDPT: 0x00000000_00000000 ~ 0x00000000_3fffffff
lea edi, [boot_pdpt - KERNEL_VMA] lea edi, [boot_pdpt]
lea eax, [boot_pd_0g_1g - KERNEL_VMA + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)] lea eax, [boot_pd_0g_1g + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)]
mov dword ptr [edi], eax mov dword ptr [edi], eax
mov dword ptr [edi + 4], 0 mov dword ptr [edi + 4], 0
// PDPT: 0x00000000_40000000 ~ 0x00000000_7fffffff // PDPT: 0x00000000_40000000 ~ 0x00000000_7fffffff
lea edi, [boot_pdpt - KERNEL_VMA + 0x1 * 8] lea edi, [boot_pdpt + 0x1 * 8]
lea eax, [boot_pd_1g_2g - KERNEL_VMA + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)] lea eax, [boot_pd_1g_2g + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)]
mov dword ptr [edi], eax mov dword ptr [edi], eax
mov dword ptr [edi + 4], 0 mov dword ptr [edi + 4], 0
// PDPT: 0x00000000_80000000 ~ 0x00000000_bfffffff // PDPT: 0x00000000_80000000 ~ 0x00000000_bfffffff
lea edi, [boot_pdpt - KERNEL_VMA + 0x2 * 8] lea edi, [boot_pdpt + 0x2 * 8]
lea eax, [boot_pd_2g_3g - KERNEL_VMA + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)] lea eax, [boot_pd_2g_3g + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)]
mov dword ptr [edi], eax mov dword ptr [edi], eax
mov dword ptr [edi + 4], 0 mov dword ptr [edi + 4], 0
// PDPT: 0x00000000_c0000000 ~ 0x00000000_ffffffff // PDPT: 0x00000000_c0000000 ~ 0x00000000_ffffffff
lea edi, [boot_pdpt - KERNEL_VMA + 0x3 * 8] lea edi, [boot_pdpt + 0x3 * 8]
lea eax, [boot_pd_3g_4g - KERNEL_VMA + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)] lea eax, [boot_pd_3g_4g + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)]
mov dword ptr [edi], eax mov dword ptr [edi], eax
mov dword ptr [edi + 4], 0 mov dword ptr [edi + 4], 0
// PDPT: 0xffffffff_80000000 ~ 0xffffffff_bfffffff // PDPT: 0xffffffff_80000000 ~ 0xffffffff_bfffffff
lea edi, [boot_pdpt - KERNEL_VMA + 0x1fe * 8] lea edi, [boot_pdpt + 0x1fe * 8]
lea eax, [boot_pd_0g_1g - KERNEL_VMA + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)] lea eax, [boot_pd_0g_1g + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)]
mov dword ptr [edi], eax mov dword ptr [edi], eax
mov dword ptr [edi + 4], 0 mov dword ptr [edi + 4], 0
// PDPT: 0xffffffff_c0000000 ~ 0xffffffff_ffffffff // PDPT: 0xffffffff_c0000000 ~ 0xffffffff_ffffffff
lea edi, [boot_pdpt - KERNEL_VMA + 0x1ff * 8] lea edi, [boot_pdpt + 0x1ff * 8]
lea eax, [boot_pd_1g_2g - KERNEL_VMA + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)] lea eax, [boot_pd_1g_2g + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)]
mov dword ptr [edi], eax mov dword ptr [edi], eax
mov dword ptr [edi + 4], 0 mov dword ptr [edi + 4], 0
// Page Directory: map to low 1 GiB * 4 space // Page Directory: map to low 1 GiB * 4 space
lea edi, [boot_pd - KERNEL_VMA] lea edi, [boot_pd]
mov eax, PTE_PRESENT | PTE_WRITE | PTE_GLOBAL | PTE_HUGE mov eax, PTE_PRESENT | PTE_WRITE | PTE_GLOBAL | PTE_HUGE
mov ecx, 512 * 4 // (of entries in PD) * (number of PD) mov ecx, 512 * 4 // (of entries in PD) * (number of PD)
write_pd_entry: write_pd_entry:
@ -199,7 +199,7 @@ enable_long_mode:
mov cr4, eax mov cr4, eax
// Set the page table address. // Set the page table address.
lea eax, [boot_pml4 - KERNEL_VMA] lea eax, [boot_pml4]
mov cr3, eax mov cr3, eax
// Enable long mode. // Enable long mode.
@ -211,7 +211,7 @@ enable_long_mode:
// Prepare for far return. // Prepare for far return.
mov eax, 8 mov eax, 8
push eax push eax
lea edx, [long_mode_in_low_address - KERNEL_VMA] lea edx, [long_mode_in_low_address]
push edx push edx
// Enable paging. // Enable paging.
@ -227,7 +227,7 @@ enable_long_mode:
.global boot_gdtr .global boot_gdtr
boot_gdtr: boot_gdtr:
.word gdt_end - gdt - 1 .word gdt_end - gdt - 1
.quad gdt - KERNEL_VMA .quad gdt
.align 16 .align 16
gdt: gdt:
@ -274,13 +274,12 @@ long_mode_in_low_address:
// Update RSP/RIP to use the virtual address. // Update RSP/RIP to use the virtual address.
mov rbx, KERNEL_VMA mov rbx, KERNEL_VMA
or rsp, rbx or rsp, rbx
lea rax, [long_mode - KERNEL_VMA] mov rax, offset long_mode
or rax, rbx
jmp rax jmp rax
// From here, we're in the .text section: we no longer use physical address. // From here, we're in the .text section: we no longer use physical address.
.code64
.text .text
.code64
long_mode: long_mode:
// Clear .bss section. // Clear .bss section.
mov al, 0x00 mov al, 0x00

View File

@ -10,7 +10,6 @@ MB2_MAGIC = 0xE85250D6
MB2_ARCHITECTURE = 0 // 32-bit (protected) mode of i386 MB2_ARCHITECTURE = 0 // 32-bit (protected) mode of i386
MB2_HEADERLEN = header_end - header_start MB2_HEADERLEN = header_end - header_start
MB2_CHECKSUM = -(MB2_MAGIC + MB2_ARCHITECTURE + MB2_HEADERLEN) MB2_CHECKSUM = -(MB2_MAGIC + MB2_ARCHITECTURE + MB2_HEADERLEN)
KERNEL_VMA = 0xffffffff80000000
header_start: header_start:
.align 8 .align 8
@ -26,7 +25,7 @@ entry_address_tag_start:
.short 1 // Optional .short 1 // Optional
.long entry_address_tag_end - entry_address_tag_start .long entry_address_tag_end - entry_address_tag_start
.extern __multiboot_boot .extern __multiboot_boot
.long __multiboot_boot - KERNEL_VMA // entry_addr .long __multiboot_boot // entry_addr
entry_address_tag_end: entry_address_tag_end:
// Tag: information request // Tag: information request