aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src/boot/boot.s
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2025-07-22 20:48:11 +0000
committerFelix Morgner <felix.morgner@ost.ch>2025-07-22 20:51:52 +0000
commitce8683e63fc9ef59e1800927afb1753507a42ef6 (patch)
tree5bd32b1a291e81615695abe96bf093ad9a8e1692 /arch/x86_64/src/boot/boot.s
parenteb22cdcad4c27527a63a6e457e80c752f76821c6 (diff)
downloadteachos-ce8683e63fc9ef59e1800927afb1753507a42ef6.tar.xz
teachos-ce8683e63fc9ef59e1800927afb1753507a42ef6.zip
x86_64: extract constants from bootstrap code
Diffstat (limited to 'arch/x86_64/src/boot/boot.s')
-rw-r--r--arch/x86_64/src/boot/boot.s442
1 files changed, 0 insertions, 442 deletions
diff --git a/arch/x86_64/src/boot/boot.s b/arch/x86_64/src/boot/boot.s
deleted file mode 100644
index 7a46795..0000000
--- a/arch/x86_64/src/boot/boot.s
+++ /dev/null
@@ -1,442 +0,0 @@
-/**
- * @brief Uninitialized data for the bootstrapping process.
- */
-.section .boot_bss, "aw", @nobits
-
-/**
- * @brief Storage for the multiboot2 information pointer.
- */
-.global multiboot_information_pointer
-multiboot_information_pointer: .skip 8
-
-.align 4096
-
-page_map_level_4: .skip 512 * 8
-page_map_level_3: .skip 512 * 8
-page_map_level_2: .skip 512 * 8
-
-/**
- * @brief Storage for the bootstrap stack.
- */
-.section .boot_stack, "aw", @nobits
-.align 16
-
-stack_bottom: .skip 1 << 20
-stack_top:
-
-/**
- * @brief Constants for the bootstrapping process.
- */
-.section .boot_rodata, "a", @progbits
-
-/**
- * @brief A basic GDT for long mode.
- */
-global_descriptor_table:
-.set GDT_ACCESSED, 40
-.set GDT_READ_WRITE, 41
-.set GDT_EXECUTABLE, 43
-.set GDT_DESCRIPTOR_TYPE, 44
-.set GDT_PRESENT, 47
-.set GDT_LONG_MODE, 53
-global_descriptor_table_null = . - global_descriptor_table
-.quad 0
-global_descriptor_table_code = . - global_descriptor_table
-.quad (1 << GDT_ACCESSED) | (1 << GDT_READ_WRITE) | (1 << GDT_EXECUTABLE) | (1 << GDT_DESCRIPTOR_TYPE) | (1 << GDT_PRESENT) | (1 << GDT_LONG_MODE)
-global_descriptor_table_data = . - global_descriptor_table
-.quad (1 << GDT_ACCESSED) | (1 << GDT_READ_WRITE) | (1 << GDT_DESCRIPTOR_TYPE) | (1 << GDT_PRESENT)
-global_descriptor_table_end:
-
-message_prefix_panic: .string "Panic: "
-message_not_loaded_by_multiboot2: .string "The operating system was not loaded by a Multiboot 2 loader."
-message_cpuid_instruction_no_supported: .string "The 'cpuid' instruction is not supported on this platform."
-message_long_mode_not_supported: .string "Long mode is not supported by this platform."
-message_return_from_kernel_main: .string "Execution returned from kernel main."
-
-/**
- * @brief Initialized data for the bootstrapping process.
- */
-.section .boot_data, "aw", @progbits
-
-/**
- * @brief A pointer to the current position within the VGA text buffer.
- */
-.global vga_buffer_pointer
-vga_buffer_pointer: .quad 0xb8000
-
-/**
- * @brief Code for the bootstrapping process.
- */
-.section .boot_text, "ax", @progbits
-.align 16
-.code32
-
-.macro pie_base
- push %esi
- call 0f
- 0:
- pop %esi
-.endm
-
-.macro function_start
- push %ebp
- mov %esp, %ebp
-.endm
-
-.macro function_end
- leave
- ret
-.endm
-
-.macro pie_function_start
- function_start
- pie_base
-.endm
-
-.macro pie_function_end
- pop %esi
- function_end
-.endm
-
-/**
- * @brief Prepare the environment and start the kernel.
- *
- * This function performs all necessary checks to ensure the system was loaded
- * by the expected loader and supports all features required to run the kernel.
- * If successful, it prepares the system by setting up memory virtualization
- * and then start the kernel proper.
- *
- * @param %eax The Multiboot 2 magic marker.
- * @param %ebx The Multiboot 2 information pointer.
- * @return void This function does not return.
- */
-.global _start
-_start:
- call 0f
-0:
- pop %esi
-
- lea (stack_top - 0b)(%esi), %ecx
-
- mov %ecx, %esp
- mov %esp, %ebp
-
- call _assert_loaded_by_multiboot2_loader
- call _save_multiboot_information_pointer
-
- call _assert_cpuid_instruction_is_supported
- call _assert_cpu_supports_long_mode
-
- call _prepare_page_maps
- call _enable_paging
- call _enable_sse
- call _reload_gdt
-
- lea (_transition_to_long_mode - 0b)(%esi), %eax
- pushl $global_descriptor_table_code
- pushl %eax
- lret
-
-/**
- * @brief Halt the system.
- *
- * This function will instruct the CPU to halt. It will try to keep the CPU
- * halted, even if interrupts occur.
- *
- * @return This function never returns.
- */
-.global halt
-_halt:
- function_start
-
-1:
- hlt
- jmp 1b
-
- function_end
-
-/**
- * @brief Print a message via the VGA text buffer.
- *
- * @param ebp+12 The message to print.
- * @param ebp+8 The color to print the message in.
- */
-_print:
- pie_function_start
-
- push %edi
- push %ebx
-
- mov 8(%ebp), %al
- mov 12(%ebp), %edx
- mov $0, %ecx
- lea (vga_buffer_pointer - 0b)(%esi), %edi
- mov (%edi), %edi
-
-1:
- mov (%edx, %ecx), %bl
- test %bl, %bl
- je 2f
- mov %bl, (%edi, %ecx, 2)
- mov %al, 1(%edi, %ecx, 2)
- inc %ecx
- jmp 1b
-
-2:
- shl $1, %ecx
- add %ecx, %edi
- lea (vga_buffer_pointer - 0b)(%esi), %ecx
- mov %edi, (%ecx)
-
- pop %ebx
- pop %edi
-
- pie_function_end
-
-/**
- * @brief Print a given panic message and then halt the machine as if by calling ::halt()
- *
- * @param ebp+4 A message to print.
- * @return This function does not return.
- */
-_panic:
- pie_function_start
-
- lea (message_prefix_panic - 0b)(%esi), %eax
-
- push %eax
- push $0x4f
- call _print
-
- mov 16(%ebp), %eax
- mov %eax, 8(%ebp)
- call _print
- add $8, %esp
-
- call _halt
-
- pie_function_end
-
-/**
- * Assert that we were loaded by a Multiboot 2 compliant bootloader.
- *
- * This assertion will panic the system if the magic signature was not found.
- * If we were loaded my an appropriate bootloader, this function also saves
- * the provided MBI pointer to `multiboot_information_pointer`.
- */
-_assert_loaded_by_multiboot2_loader:
- pie_function_start
-
- .set MULTIBOOT2_MAGIC, 0x36d76289
- cmp $MULTIBOOT2_MAGIC, %eax
- je 1f
- lea (message_not_loaded_by_multiboot2 - 0b)(%esi), %eax
- push %eax
- call _panic
-1:
- pie_function_end
-
-/**
- * @brief Store the multiboot 2 information pointer in the global memory.
- *
- * @return void
- */
-_save_multiboot_information_pointer:
- pie_function_start
-
- lea (multiboot_information_pointer - 0b)(%esi), %eax
- mov %ebx, (%eax)
-
- pie_function_end
-
-/**
- * @brief Assert that the CPU supports the CPUID instruction.
- *
- * The primary way to check for support of the instruction is to flip the ID
- * bin in EFLAGS and then check if this changed was accepted. If so, the CPU
- * supports the CPUID instruction, otherwise it most-likely doesn't.
- */
-_assert_cpuid_instruction_is_supported:
- pie_function_start
-
- pushfl
- pop %eax
- mov %eax, %ecx
-
- xor $(1 << 21), %eax /* Flip the ID bit */
- push %eax /* Move the new bitset on the stack for loading */
- popfl /* Load the flags with ID set back into EFLAGS */
- pushfl /* Copy the flags back onto the stack */
- pop %eax /* Load the flags for further checking */
-
- push %ecx
- popfl
-
- cmp %ecx, %eax
- jne 1f
- lea (message_cpuid_instruction_no_supported - 0b)(%esi), %eax
- push %eax
- call _panic
-
-1:
- pie_function_end
-
-/**
- * @brief Assert that the CPU supports going into long mode.
- */
-_assert_cpu_supports_long_mode:
- pie_function_start
-
- mov $0x80000000, %eax
- cpuid
- cmp $0x80000001, %eax
- jb 1f
-
- mov $0x80000001, %eax
- cpuid
- test $(1 << 29), %edx
- jnz 2f
-1:
- lea (message_long_mode_not_supported - 0b)(%esi), %eax
- push %eax
- call _panic
-2:
- pie_function_end
-
-/**
- * @brief Prepare a recursive page map hierarchy
- *
- * We map all physical memory we were loaded in plus one additional page. The
- * mapping is done in terms of huge pages (2 MiB per page) to save on required
- * page map entries.
- *
- * @return void
- */
-_prepare_page_maps:
- pie_function_start
- push %ebx
-
- .set HUGE_PAGES_TO_MAP, 16
-
- /* Map the P4 table recursively */
- lea (page_map_level_4 - 0b)(%esi), %eax
- mov %eax, %ebx
- or $0b11, %ebx
- mov %ebx, (511 * 8)(%eax)
-
- /* Add an entry to the PML4, pointing to the PML3 */
- lea (page_map_level_3 - 0b)(%esi), %ebx
- or $0b11, %ebx
- mov %ebx, (((0x0000000000100000 >> 39) & 0x1ff) * 8)(%eax)
-
- /* Add an entry to the PML3, pointing to the PML2 */
- lea (page_map_level_3 - 0b)(%esi), %eax
- lea (page_map_level_2 - 0b)(%esi), %ebx
- or $0b11, %ebx
- mov %ebx, (((0x0000000000100000 >> 30) & 0x1ff) * 8)(%eax)
-
- /* Add entries for huge pages to the PML2 */
- push %edi
- lea (page_map_level_2 - 0b)(%esi), %ebx
- mov $HUGE_PAGES_TO_MAP, %edi
- xor %ecx, %ecx
-
-1:
- mov $(1 << 21), %eax
- mul %ecx
- or $0b10000011, %eax
- mov %eax, (%ebx, %ecx, 8)
-
- inc %ecx
- cmp %edi, %ecx
- jne 1b
-
- pop %edi
- pop %ebx
- pie_function_end
-
-/**
- * @p Enable memory virtualization via paging.
- *
- * Note: This routine expects for there to be a valid set of page maps already
- * set up for use.
- *
- * @return void
- */For
-_enable_paging:
- pie_function_start
-
- lea (page_map_level_4 - 0b)(%esi), %eax
- mov %eax, %cr3
-
- /* Enable Physical Address Extension */
- mov %cr4, %eax
- or $(1 << 5), %eax
- mov %eax, %cr4
-
- /* Enable long mode support */
- mov $0xC0000080, %ecx
- rdmsr
- or $(1 << 8), %eax
- wrmsr
-
- /* Enable paging */
- mov %cr0, %eax
- or $(1 << 31), %eax
- mov %eax, %cr0
-
- pie_function_end
-
-/**
- * @brief Enable use of SSE instructions.
- */
-_enable_sse:
- function_start
-
- mov %cr0, %eax
- and $0xfffffffb, %eax
- or $0x00000002, %eax
- mov %eax, %cr0
-
- mov %cr4, %eax
- or $(3 << 9), %eax
- mov %eax, %cr4
-
- function_end
-
-/**
- * @brief Prepare a new GTD and load make it active.
- *
- * @return void
- */
-_reload_gdt:
- pie_function_start
-
- sub $10, %esp
- lea (global_descriptor_table - 0b)(%esi), %eax
- movw $(global_descriptor_table_end - global_descriptor_table -1), (%esp)
- mov %eax, 2(%esp)
- movl $0, 6(%esp)
-
- lgdt (%esp)
- add $10, %esp
-
- pie_function_end
-
-.section .boot_text, "ax", @progbits
-.code64
-
-_transition_to_long_mode:
- mov $global_descriptor_table_data, %rax
- mov %rax, %ss
- mov %rax, %ds
- mov %rax, %es
- mov %rax, %fs
- mov %rax, %gs
-
- xor %rax, %rax
-
- call _init
-
- call main
- call _halt