aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/src')
-rw-r--r--arch/x86_64/src/boot/boot.s368
-rw-r--r--arch/x86_64/src/boot/boot32.S449
-rw-r--r--arch/x86_64/src/boot/crti.s13
-rw-r--r--arch/x86_64/src/boot/crtn.s9
-rw-r--r--arch/x86_64/src/boot/entry64.s60
-rw-r--r--arch/x86_64/src/boot/initialize_runtime.cpp26
-rw-r--r--arch/x86_64/src/context_switching/interrupt_descriptor_table/gate_descriptor.cpp24
-rw-r--r--arch/x86_64/src/context_switching/interrupt_descriptor_table/idt_flags.cpp17
-rw-r--r--arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp53
-rw-r--r--arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.cpp13
-rw-r--r--arch/x86_64/src/context_switching/interrupt_descriptor_table/ist_offset.cpp10
-rw-r--r--arch/x86_64/src/context_switching/interrupt_descriptor_table/segment_selector.cpp15
-rw-r--r--arch/x86_64/src/context_switching/main.cpp63
-rw-r--r--arch/x86_64/src/context_switching/segment_descriptor_table/access_byte.cpp17
-rw-r--r--arch/x86_64/src/context_switching/segment_descriptor_table/gdt_flags.cpp20
-rw-r--r--arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp109
-rw-r--r--arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table_pointer.cpp11
-rw-r--r--arch/x86_64/src/context_switching/segment_descriptor_table/segment_descriptor_base.cpp38
-rw-r--r--arch/x86_64/src/context_switching/segment_descriptor_table/segment_descriptor_extension.cpp24
-rw-r--r--arch/x86_64/src/context_switching/syscall/main.cpp35
-rw-r--r--arch/x86_64/src/context_switching/syscall/syscall_enable.cpp32
-rw-r--r--arch/x86_64/src/context_switching/syscall/syscall_handler.cpp118
-rw-r--r--arch/x86_64/src/exception_handling/abort.cpp15
-rw-r--r--arch/x86_64/src/exception_handling/assert.cpp15
-rw-r--r--arch/x86_64/src/exception_handling/panic.cpp22
-rw-r--r--arch/x86_64/src/exception_handling/pure_virtual.cpp6
-rw-r--r--arch/x86_64/src/interrupt_handling/generic_interrupt_handler.cpp13
-rw-r--r--arch/x86_64/src/kapi/cio.cpp20
-rw-r--r--arch/x86_64/src/kapi/cpu.cpp12
-rw-r--r--arch/x86_64/src/kapi/memory.cpp193
-rw-r--r--arch/x86_64/src/kernel/cpu/call.cpp9
-rw-r--r--arch/x86_64/src/kernel/cpu/control_register.cpp66
-rw-r--r--arch/x86_64/src/kernel/cpu/gdtr.cpp19
-rw-r--r--arch/x86_64/src/kernel/cpu/idtr.cpp18
-rw-r--r--arch/x86_64/src/kernel/cpu/if.cpp7
-rw-r--r--arch/x86_64/src/kernel/cpu/msr.cpp31
-rw-r--r--arch/x86_64/src/kernel/cpu/segment_register.cpp98
-rw-r--r--arch/x86_64/src/kernel/cpu/tlb.cpp16
-rw-r--r--arch/x86_64/src/kernel/cpu/tr.cpp16
-rw-r--r--arch/x86_64/src/kernel/main.cpp71
-rw-r--r--arch/x86_64/src/memory/allocator/area_frame_allocator.cpp85
-rw-r--r--arch/x86_64/src/memory/allocator/physical_frame.cpp24
-rw-r--r--arch/x86_64/src/memory/allocator/tiny_frame_allocator.cpp34
-rw-r--r--arch/x86_64/src/memory/heap/bump_allocator.cpp54
-rw-r--r--arch/x86_64/src/memory/heap/global_heap_allocator.cpp135
-rw-r--r--arch/x86_64/src/memory/heap/linked_list_allocator.cpp177
-rw-r--r--arch/x86_64/src/memory/heap/memory_block.cpp15
-rw-r--r--arch/x86_64/src/memory/heap/user_heap_allocator.cpp200
-rw-r--r--arch/x86_64/src/memory/kernel_mapper.cpp111
-rw-r--r--arch/x86_64/src/memory/main.cpp77
-rw-r--r--arch/x86_64/src/memory/mmu.cpp21
-rw-r--r--arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp13
-rw-r--r--arch/x86_64/src/memory/multiboot/reader.cpp131
-rw-r--r--arch/x86_64/src/memory/page_table.cpp82
-rw-r--r--arch/x86_64/src/memory/paging/active_page_table.cpp98
-rw-r--r--arch/x86_64/src/memory/paging/inactive_page_table.cpp20
-rw-r--r--arch/x86_64/src/memory/paging/page_entry.cpp63
-rw-r--r--arch/x86_64/src/memory/paging/page_table.cpp128
-rw-r--r--arch/x86_64/src/memory/paging/temporary_page.cpp29
-rw-r--r--arch/x86_64/src/memory/paging/virtual_page.cpp33
-rw-r--r--arch/x86_64/src/memory/paging_root.cpp19
-rw-r--r--arch/x86_64/src/memory/recursive_page_mapper.cpp119
-rw-r--r--arch/x86_64/src/memory/region_allocator.cpp92
-rw-r--r--arch/x86_64/src/memory/scoped_mapping.cpp69
-rw-r--r--arch/x86_64/src/stl/mutex.cpp16
-rw-r--r--arch/x86_64/src/user/main.cpp35
-rw-r--r--arch/x86_64/src/vga/text.cpp84
-rw-r--r--arch/x86_64/src/video/vga/text.cpp66
68 files changed, 1357 insertions, 2844 deletions
diff --git a/arch/x86_64/src/boot/boot.s b/arch/x86_64/src/boot/boot.s
deleted file mode 100644
index 7932045..0000000
--- a/arch/x86_64/src/boot/boot.s
+++ /dev/null
@@ -1,368 +0,0 @@
-.extern _end_physical
-.extern _init
-.extern kernel_main
-
-
-/**
- * Uninitialized data for the bootstrapping process.
- */
-.section .boot_bss, "aw", @nobits
-
-/**
- * Reserve some space for the Multiboot 2 information pointer.
- */
-.global multiboot_information_pointer
-multiboot_information_pointer: .skip 4
-
-/**
- * Align page maps to 4 KiB or the assembler code, will cause crashes when attempting to enable paging.
- */
-.align 4096
-
-/**
- * Reserve space for the page maps we are going to use during startup.
- *
- * Note: We are going to use large pages to make the initial mapping code
- * simpler.
- *
- * We need:
- * - A single PML 4 (since we will only use 4-level paging)
- * - 1 PML 3
- * - 1 PML 2
- */
-
-.global page_map_level_4
-page_map_level_4: .skip 512 * 8
-
-.global page_map_level_3
-page_map_level_3: .skip 512 * 8
-
-.global page_map_level_2
-page_map_level_2: .skip 512 * 8
-
-/**
- * Stack space for the bootstrapping process.
- *
- * Note: We are going to reserve 1 MiB for now. If/when the kernel requires
- * more space to run, it will have to relocate the stack.
- */
-.section .boot_stack, "aw", @nobits
-.align 16
-
-stack_bottom: .skip 1 << 20
-stack_top:
-
-/**
- * Constants for the bootstrapping process.
- */
-.section .boot_rodata, "a", @progbits
-
-/**
- * A valid Global Descriptor Table is still required in long mode. However, we
- * only need a single entry for the "code segment", so we will setup a single
- * segment table below.
- *
- * Bit 43: "E" in the access byte => mark the segment as executable.
- * Bit 44: "S" in the access byte => mark the segment as code or data.
- * Bit 47: "P" in the access byte => mark the segment as being present.
- * Bit 53: "L" in the flags byte => mark the segment as being for long mode
- */
-
-global_descriptor_table: .quad 0
-global_descriptor_table_code = . - global_descriptor_table
-.quad (1<<43) | (1<<44) | (1<<47) | (1<<53)
-
-/**
- * We also need a pointer that we can load into the GDTR.
- *
- * The pointer consists of a word describing the size of the table minus 1 and
- * the pointer to the actual table.
- */
-global_descriptor_table_pointer:
-.word . - global_descriptor_table - 1
-.quad global_descriptor_table
-
-/**
- * We are going to print some messages in case we panic during boot, so we are
- * going to store them here as well
- */
-.global message_prefix_panic
-message_prefix_panic:
-.string "TeachOS 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."
-mesage_long_mode_not_supported:
-.string "Long mode is not supported by this platform."
-
-/**
- * Mutable data for the bootstrapping process.
- */
-.section .boot_data, "aw", @progbits
-
-/**
- * We need a pointer to our current position in the VGA text buffer.
- */
-.global vga_buffer_pointer
-vga_buffer_pointer: .long 0xb8000
-
-/**
- * Code for the bootstrapping process.
- */
-.section .boot_text, "ax", @progbits
-.align 16
-.code32
-
-.global halt
-halt:
-1:
- hlt
- jmp 1b
-
-/**
- * Print a given panic message and then halt the machine.
- *
- * Parameters:
- * - [stack - 0] message: the message to print
- */
-_panic:
- push %ebp
- mov %esp, %ebp
-
- push message_prefix_panic
- push $0x4f
- call _print
- add $8, %esp
-
- push 8(%ebp)
- push 0x4f
- call _print
- add $8, %esp
-
- call halt
-
-/**
- * Print a message via the VGA buffer.
- *
- * Parameters:
- * - [stack - 4] message: the message to print
- * - [stack - 0] color: the color of the message
- */
-_print:
- push %ebp
- mov %esp, %ebp
-
- push %ebx
- push %esi
- mov 8(%ebp), %eax
- mov 12(%ebp), %ebx
- mov $0, %ecx
- mov (vga_buffer_pointer), %esi
-
-.Lprint_loop:
- mov (%ebx, %ecx), %dl
- test %dl, %dl
- je .Lupdate_vga_buffer_address
- mov %dl, (%esi, %ecx, 2)
- mov %al, 1(%esi, %ecx, 2)
- inc %ecx
- jmp .Lprint_loop
-
-.Lupdate_vga_buffer_address:
- shl $1, %ecx
- add %ecx, (vga_buffer_pointer)
-
-.Lprint_end:
- pop %esi
- pop %ebx
- mov %ebp, %esp
- pop %ebp
- ret
-
-/**
- * This is our entry point after being loaded by the bootloader.
- *
- * Having this in assembly makes it easier for us to keep things together.
- */
-.global _start
-_start:
- mov $stack_top, %esp
- mov %esp, %ebp
-
- call assert_loaded_by_multiboot2_loader
- call assert_cpuid_instruction_is_supported
- call assert_cpu_supports_long_mode
- call prepare_page_maps
- call enable_paging
- call enable_sse
-
- lgdt (global_descriptor_table_pointer)
- jmp $global_descriptor_table_code, $_transition_to_long_mode
-
- call halt
-
-/**
- * Assert that the CPU supports going into long mode.
- */
-assert_cpu_supports_long_mode:
- mov $0x80000000, %eax
- cpuid
- cmp $0x80000001, %eax
- jb .Llong_mode_assertion_failed
-
- mov $0x80000001, %eax
- cpuid
- test $(1 << 29), %edx
- jz .Llong_mode_assertion_failed
- ret
-.Llong_mode_assertion_failed:
- push $mesage_long_mode_not_supported
- call _panic
-
-/**
- * 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:
- 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
- je .Lcpuid_assertion_fail
- ret
-.Lcpuid_assertion_fail:
- push $message_cpuid_instruction_no_supported
- call _panic
-
-/**
- * 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:
- cmp $0x36d76289, %eax /* Check if we received the
- expected magic */
- jne .Lmultiboot2_assertion_fail /* Panic otherwise */
- mov %ebx, multiboot_information_pointer /* Store the MBI pointer */
- ret
-.Lmultiboot2_assertion_fail:
- push $message_not_loaded_by_multiboot2
- call _panic
-
-/**
- * Enable paging.
- *
- * Note: This routine expects for there to be a valid set of page maps already
- * set up for use.
- */
-enable_paging:
- mov $page_map_level_4, %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
-
- ret
-
-/**
- * Enable use of SSE instructions.
- */
-enable_sse:
- mov %cr0, %eax
- and $0xfffffffb, %eax
- or $0x00000002, %eax
- mov %eax, %cr0
-
- mov %cr4, %eax
- or $(3 << 9), %eax
- mov %eax, %cr4
-
- ret
-
-/**
- * Prepare the page maps.
- *
- * 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.
- */
-prepare_page_maps:
- /* Map the P4 table recursively */
- mov $page_map_level_4, %eax
- or $0b11, %eax /* Write present + writable flags into eax register */
- mov %eax, (page_map_level_4 + 511 * 8)
-
- /* Add an entry to the PML4, pointing to the PML3 */
- mov $page_map_level_3, %eax
- or $0x3, %eax
- mov %eax, (page_map_level_4 + ((0x0000000000100000 >> 39) & 0x1ff) * 8)
-
- /* Add an entry to the PML3, pointing to the PML2 */
- mov $page_map_level_2, %eax
- or $0x3, %eax
- mov %eax, (page_map_level_3 + ((0x0000000000100000 >> 30) & 0x1ff) * 8)
-
- xor %ecx, %ecx
-
- mov $_end_linear, %esi
- shr $21, %esi
- add $2, %esi
-
-.Lmap_pages:
- mov $(1 << 21), %eax
- mul %ecx
- or $((1 << 0) | (1 << 1) | (1 << 7)), %eax
- mov %eax, page_map_level_2(,%ecx,8)
-
- inc %ecx
- cmp %esi, %ecx
- jne .Lmap_pages
-
- ret
-
-.section .boot_text, "ax", @progbits
-.code64
-
-_transition_to_long_mode:
- xor %rax, %rax
- mov %rax, %ss
- mov %rax, %ds
- mov %rax, %es
- mov %rax, %fs
- mov %rax, %gs
-
- movl $0xb8000, (vga_buffer_pointer)
-
- call _init
-
- call kernel_main
- call halt
diff --git a/arch/x86_64/src/boot/boot32.S b/arch/x86_64/src/boot/boot32.S
new file mode 100644
index 0000000..79b3ec7
--- /dev/null
+++ b/arch/x86_64/src/boot/boot32.S
@@ -0,0 +1,449 @@
+#include "x86_64/boot/boot.hpp"
+
+/**
+ * @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_maps_start:
+page_map_level_4: .skip 512 * 8
+page_map_level_3_high: .skip 512 * 8
+page_map_level_3_low: .skip 512 * 8
+page_map_level_2: .skip 512 * 8
+page_maps_end = .
+page_maps_size = page_maps_end - page_maps_start
+
+/**
+ * @brief Storage for the bootstrap stack.
+ */
+.section .boot_stack, "aw", @nobits
+.align 16
+
+early_stack_bottom: .skip 1 << 8
+early_stack_top:
+early_stack_size = early_stack_top - early_stack_bottom
+
+/**
+ * @brief Constants for the bootstrapping process.
+ */
+.section .boot_rodata, "a", @progbits
+
+.global global_descriptor_table_data
+
+/**
+ * @brief A basic GDT for long mode.
+ */
+global_descriptor_table:
+global_descriptor_table_null = . - global_descriptor_table
+.quad 0
+global_descriptor_table_code = . - global_descriptor_table
+.quad GDT_READ_WRITE | GDT_EXECUTABLE | GDT_DESCRIPTOR_TYPE | GDT_PRESENT | GDT_LONG_MODE | (1 << 55)
+global_descriptor_table_data = . - global_descriptor_table
+.quad GDT_READ_WRITE | GDT_DESCRIPTOR_TYPE | GDT_PRESENT | (1 << 54) | (1 << 55)
+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 (early_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
+
+ push $HUGE_PAGES_TO_MAP
+ call _prepare_page_maps
+ add $4, %esp
+
+ call _enable_paging
+ call _enable_sse
+ call _reload_gdt
+
+ lea (_entry64 - 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.
+ */
+_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 th