aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.conan/profiles/x86_64-gcc26
-rw-r--r--.gitignore7
-rw-r--r--.vscode/extensions.json9
-rw-r--r--.vscode/settings.json10
-rw-r--r--cmake/Platforms/x86_64.cmake23
-rw-r--r--conanfile.py54
-rw-r--r--requirements.txt1
-rw-r--r--source/CMakeLists.txt11
-rw-r--r--source/boot/arch/x86_64/CMakeLists.txt8
-rw-r--r--source/boot/arch/x86_64/src/boot.s374
-rw-r--r--source/boot/arch/x86_64/src/crti.s13
-rw-r--r--source/boot/arch/x86_64/src/crtn.s9
-rw-r--r--source/boot/arch/x86_64/src/multiboot.s17
-rw-r--r--source/kernel/CMakeLists.txt33
-rw-r--r--source/kernel/arch/x86_64/kern.ld139
-rw-r--r--source/kernel/src/entry.cpp9
16 files changed, 742 insertions, 1 deletions
diff --git a/.conan/profiles/x86_64-gcc b/.conan/profiles/x86_64-gcc
new file mode 100644
index 0000000..1c29e8d
--- /dev/null
+++ b/.conan/profiles/x86_64-gcc
@@ -0,0 +1,26 @@
+target_host=x86_64-none-elf
+cc_compiler=gcc
+cxx_compiler=g++
+
+[env]
+CHOST=$target_host
+AR=$target_host-ar
+AS=$target_host-as
+CC=$target_host-$cc_compiler
+CXX=$target_host-$cxx_compiler
+LD=$target_host-$cxx_compiler
+OBJDUMP=$target_host-objdump
+RANLIB=$target_host-ranlib
+STRIP=$target_host-strip
+
+[settings]
+arch=x86_64
+build_type=Debug
+compiler=gcc
+compiler.version=13
+compiler.libcxx=libstdc++11
+compiler.cppstd=20
+os=baremetal
+
+[options]
+gcc:target_arch=x86_64
diff --git a/.gitignore b/.gitignore
index 1d17dae..f3818c5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,6 @@
-.venv
+/.venv
+/build
+
+# Conan Generated CMake presets
+CMakeUserPresets.json
+.gdb_history \ No newline at end of file
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..8122897
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,9 @@
+{
+ "recommendations": [
+ "basdp.language-gas-x86",
+ "ms-python.python",
+ "ms-vscode.cmake-tools",
+ "ms-vscode.cpptools",
+ "zixuanwang.linkerscript"
+ ]
+} \ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..51bcf93
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,10 @@
+{
+ "cmake.sourceDirectory": "/home/sophia/Projects/os/teachos/kernel/source",
+ "cmake.useCMakePresets": "always",
+
+ "C_Cpp.autoAddFileAssociations": false,
+ "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
+ // "[python]": {
+ // "editor.defaultFormatter": "ms-python.black-formatter"
+ // },
+} \ No newline at end of file
diff --git a/cmake/Platforms/x86_64.cmake b/cmake/Platforms/x86_64.cmake
new file mode 100644
index 0000000..9e727cf
--- /dev/null
+++ b/cmake/Platforms/x86_64.cmake
@@ -0,0 +1,23 @@
+execute_process(COMMAND "x86_64-none-elf-g++" "-print-file-name=crtbegin.o"
+ OUTPUT_VARIABLE CRT_BEGIN
+ ERROR_QUIET
+)
+string(STRIP "${CRT_BEGIN}" CRT_BEGIN)
+mark_as_advanced(CRT_BEGIN)
+
+string(REGEX REPLACE "/crtbegin.o" "" CMAKE_SYSROOT "${CRT_BEGIN}")
+mark_as_advanced(CMAKE_SYSROOT)
+
+set(CMAKE_CXX_FLAGS_INIT "-m64 -mno-red-zone -mcmodel=large")
+set(CMAKE_EXE_LINKER_FLAGS_INIT "-nostartfiles")
+set(CMAKE_CXX_LINK_EXECUTABLE
+ "<CMAKE_CXX_COMPILER> \
+ <FLAGS> \
+ <CMAKE_CXX_LINK_FLAGS> \
+ <LINK_FLAGS> \
+ ${CMAKE_SYSROOT}/crtbegin.o \
+ <OBJECTS> \
+ -o <TARGET> \
+ <LINK_LIBRARIES> \
+ ${CMAKE_SYSROOT}/crtend.o"
+)
diff --git a/conanfile.py b/conanfile.py
new file mode 100644
index 0000000..4712156
--- /dev/null
+++ b/conanfile.py
@@ -0,0 +1,54 @@
+from conan import ConanFile
+from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout
+from conan.tools.env import VirtualBuildEnv
+
+class KernelConan(ConanFile):
+ name = "kernel"
+ description = "The kernel of TeachOS"
+ version = "0.0.1"
+ package_type = "application"
+ homepage = "https://gitlab.ost.ch/teachos/kernel"
+
+ settings = [
+ "arch",
+ "build_type",
+ "compiler",
+ ]
+
+ tool_requires = [
+ "cmake/[~3.27]",
+ "gcc/13.2.0@teachos/stable",
+ ]
+
+ def build(self):
+ cmake = CMake(self)
+ cmake.configure()
+ cmake.build()
+
+ def generate(self):
+ build_environment = VirtualBuildEnv(self)
+ build_environment.generate()
+
+ dependencies = CMakeDeps(self)
+ dependencies.generate()
+
+ toolchain = CMakeToolchain(self)
+ toolchain.cache_variables["CMAKE_TRY_COMPILE_TARGET_TYPE"] = "STATIC_LIBRARY"
+ toolchain.variables["TEACHOS_DESCRIPTION"] = self.description
+ toolchain.variables["TEACHOS_HOMEPAGE_URL"] = self.homepage
+ toolchain.variables["TEACHOS_VERSION"] = self.version
+ toolchain.blocks["teachos_platform"] = PlatformIncludeBlock
+ toolchain.blocks["teachos_platform"].values["platform"] = self.settings.arch
+ toolchain.blocks.remove("cmake_flags_init")
+ toolchain.blocks.remove("arch_flags")
+ toolchain.generate()
+
+ def layout(self):
+ cmake_layout(self, src_folder="source")
+
+class PlatformIncludeBlock:
+ template = "include(\"../cmake/Platforms/{{platform}}.cmake\")"
+
+def context(self):
+ return { "platform": None }
+
diff --git a/requirements.txt b/requirements.txt
index 8dc8e73..4021434 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1 +1,2 @@
+black>=23
conan~=1.61
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
new file mode 100644
index 0000000..80b566e
--- /dev/null
+++ b/source/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION "3.27")
+
+project("kernel"
+ DESCRIPTION "${TEACHOS_DESCRIPTION}"
+ HOMEPAGE_URL "${TEACHOS_HOMEPAGE_URL}"
+ VERSION "${TEACHOS_VERSION}"
+ LANGUAGES ASM C CXX
+)
+
+add_subdirectory("boot/arch/${CMAKE_SYSTEM_PROCESSOR}")
+add_subdirectory("kernel")
diff --git a/source/boot/arch/x86_64/CMakeLists.txt b/source/boot/arch/x86_64/CMakeLists.txt
new file mode 100644
index 0000000..454f347
--- /dev/null
+++ b/source/boot/arch/x86_64/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_library("boot" STATIC
+ "src/boot.s"
+ "src/crti.s"
+ "src/crtn.s"
+ "src/multiboot.s"
+)
+
+add_library("teachos::boot" ALIAS "boot") \ No newline at end of file
diff --git a/source/boot/arch/x86_64/src/boot.s b/source/boot/arch/x86_64/src/boot.s
new file mode 100644
index 0000000..4781773
--- /dev/null
+++ b/source/boot/arch/x86_64/src/boot.s
@@ -0,0 +1,374 @@
+.extern _end_physical
+.extern _init
+.extern kernel_main
+
+
+/**
+ * Uninitialized data for the bootstrapping process.
+ */
+.section .boot_bss, "aw", @nobits
+.align 4096
+
+/**
+ * Reserve space for the page maps we are going to used 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)
+ * - 2 PML 3s (since we need to map high (-2GiB) and low (1+MiB) memory)
+ * - 2 PML 2s (since we need to map high (-2GiB) and low (1+MiB) memory)
+ */
+
+.global page_map_level_4
+page_map_level_4: .skip 512 * 8
+
+.global page_map_level_3_low
+page_map_level_3_low: .skip 512 * 8
+.global page_map_level_3_high
+page_map_level_3_high: .skip 512 * 8
+
+.global page_map_level_2_low
+page_map_level_2_low: .skip 512 * 8
+.global page_map_level_2_high
+page_map_level_2_high: .skip 512 * 8
+
+/**
+ * Reserve some space for the Multiboot 2 information pointer.
+ */
+.global multiboot_information_pointer
+multiboot_information_pointer: .skip 4
+
+/**
+ * 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
+ */
+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.
+ */
+vga_buffer_pointer: .long 0xb8000
+
+/**
+ * Code for the bootstrapping process.
+ */
+.section .boot_text, "ax", @progbits
+.align 16
+.code32
+
+/**
+ * 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
+
+ hlt
+
+/**
+ * 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
+
+ hlt
+
+/**
+ * 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. Note that we also map memory both in the low and high
+ * virtual address ranges, giving us two ways of accessing it. We need to do
+ * this, because the bootstrapping code lives in low memory, while the rest of
+ * the kernel will reside on the high end.
+ */
+prepare_page_maps:
+ /* Add an entry to the PML4, pointing to the low PML3 */
+ mov $page_map_level_3_low, %eax
+ or $0x3, %eax
+ mov %eax, (page_map_level_4 + ((0x0000000000100000 >> 39) & 0x1ff) * 8)
+
+ /* Add an entry to the PML4, pointing to the high PML3 */
+ mov $page_map_level_3_high, %eax
+ or $0x3, %eax
+ mov %eax, (page_map_level_4 + ((0xffffffff80100000 >> 39) & 0x1ff) * 8)
+
+ /* Add an entry to the low PML3, pointing to the low PML2 */
+ mov $page_map_level_2_low, %eax
+ or $0x3, %eax
+ mov %eax, (page_map_level_3_low + ((0x0000000000100000 >> 30) & 0x1ff) * 8)
+
+ /* Add an entry to the high PML3, pointing to the high PML2 */
+ mov $page_map_level_2_high, %eax
+ or $0x3, %eax
+ mov %eax, (page_map_level_3_high + ((0xffffffff80100000 >> 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_low(,%ecx,8)
+ mov %eax, page_map_level_2_high(,%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
+
+ /* Clear the screen */
+ mov $0x0f200f200f200f20, %rax
+ mov $0x0b8000, %rdi
+ mov $500, %rcx
+ rep stosq
+
+ call _init
+
+ mov multiboot_information_pointer, %rdi
+ call kernel_main
+ hlt
diff --git a/source/boot/arch/x86_64/src/crti.s b/source/boot/arch/x86_64/src/crti.s
new file mode 100644
index 0000000..26878fe
--- /dev/null
+++ b/source/boot/arch/x86_64/src/crti.s
@@ -0,0 +1,13 @@
+.code64
+
+.section .init
+.global _init
+_init:
+ push %rbp
+ movq %rsp, %rbp
+
+.section .fini
+.global _fini
+_fini:
+ push %rbp
+ movq %rsp, %rbp
diff --git a/source/boot/arch/x86_64/src/crtn.s b/source/boot/arch/x86_64/src/crtn.s
new file mode 100644
index 0000000..06fb7ce
--- /dev/null
+++ b/source/boot/arch/x86_64/src/crtn.s
@@ -0,0 +1,9 @@
+.code64
+
+.section .init
+ popq %rbp
+ ret
+
+.section .fini
+ popq %rbp
+ ret
diff --git a/source/boot/arch/x86_64/src/multiboot.s b/source/boot/arch/x86_64/src/multiboot.s
new file mode 100644
index 0000000..207a639
--- /dev/null
+++ b/source/boot/arch/x86_64/src/multiboot.s
@@ -0,0 +1,17 @@
+.section .boot_mbh, "a"
+.align 64
+
+multiboot_header_start:
+.Lmagic:
+ .long 0xe85250d6
+.Larch:
+ .long 0
+.Llength:
+ .long multiboot_header_end - multiboot_header_start
+.Lchecksum:
+ .long 0x100000000 - (0xe85250d6 + 0 + (multiboot_header_end - multiboot_header_start))
+.Lend:
+ .int 0
+ .int 0
+ .long 8
+multiboot_header_end:
diff --git a/source/kernel/CMakeLists.txt b/source/kernel/CMakeLists.txt
new file mode 100644
index 0000000..c8e0c4a
--- /dev/null
+++ b/source/kernel/CMakeLists.txt
@@ -0,0 +1,33 @@
+set(TEACHOS_KERNEL_LINKER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/arch/${CMAKE_SYSTEM_PROCESSOR}/kern.ld")
+mark_as_advanced(TEACHOS_KERNEL_LINKER_SCRIPT)
+
+add_executable("kernel"
+ "src/entry.cpp"
+)
+
+target_compile_features("kernel" PRIVATE
+ "cxx_std_20"
+)
+
+target_compile_options("kernel" PRIVATE
+ "$<$<CXX_COMPILER_ID:GNU>:-Wall>"
+ "$<$<CXX_COMPILER_ID:GNU>:-Wextra>"
+ "$<$<CXX_COMPILER_ID:GNU>:-Werror>"
+ "$<$<CXX_COMPILER_ID:GNU>:-pedantic-errors>"
+)
+
+target_link_options("kernel" PRIVATE
+ "-T${TEACHOS_KERNEL_LINKER_SCRIPT}"
+)
+
+target_link_libraries("kernel" PRIVATE
+ "-Wl,--whole-archive"
+ "teachos::boot"
+ "-Wl,--no-whole-archive"
+)
+
+set_target_properties("kernel" PROPERTIES
+ CXX_EXTENSIONS OFF
+ CXX_STANDARD_REQUIRED YES
+ LINK_DEPENDS "${TEACHOS_KERNEL_LINKER_SCRIPT}"
+)
diff --git a/source/kernel/arch/x86_64/kern.ld b/source/kernel/arch/x86_64/kern.ld
new file mode 100644
index 0000000..4e44cfa
--- /dev/null
+++ b/source/kernel/arch/x86_64/kern.ld
@@ -0,0 +1,139 @@
+ENTRY(_start)
+
+/*****************************************************************************
+ * Virtual and linear start addresses of the TeachOS kernel
+ *****************************************************************************/
+TEACHOS_HIGH = -2048M;
+TEACHOS_LOW = 1M;
+
+PHDRS {
+ boot_rodata PT_LOAD FLAGS(4);
+ boot_text PT_LOAD FLAGS(5);
+ boot_data PT_LOAD FLAGS(6);
+
+ text PT_LOAD FLAGS(5);
+ data PT_LOAD FLAGS(6);
+ rodata PT_LOAD FLAGS(4);
+}
+
+SECTIONS
+{
+ /***************************************************************************
+ * Load the bootstrap code into low memory. We need to be accessible in
+ * 32-Bit mode, so we want to live down low, but we need to leave the 1MiB
+ * hole open since some BIOS functionality resides below it.
+ ***************************************************************************/
+ . = TEACHOS_LOW;
+
+ /***************************************************************************
+ * We want to be able to be able to access all memory (linear and virtual)
+ * during bootstrapping and operation. To achieve this, we define some
+ * symbols at the beginning.
+ ***************************************************************************/
+ _start_linear = .;
+ _start_virtual = . + TEACHOS_HIGH;
+
+ /***************************************************************************
+ * The bootstrapping infratructure goes first. We first place the read-only
+ * data, followed by our code, initialized mutable data, and finally our
+ * uninitialized mutable data.
+ ***************************************************************************/
+ .boot_rodata :
+ {
+ KEEP(*(.boot_mbh))
+ *(.boot_rodata)
+ } :boot_rodata
+
+ .boot_text :
+ {
+ *(.boot_text)
+ } :boot_text
+
+ .boot_data :
+ {
+ *(.boot_data)
+ } :boot_data
+
+ .boot_bss :
+ {
+ *(.boot_bss)
+ *(.boot_stack)
+ }
+
+ /***************************************************************************
+ * Now it is time to load the 64-bit kernel code. We virtually load it into
+ * the upper 2GiB, while adjusting the linear load address appropriately. We
+ * also make sure to align the loaded data onto a page boundary.
+ ***************************************************************************/
+ . = ALIGN(4K);
+ . += TEACHOS_HIGH;
+
+ .init ALIGN(4K) : AT(ADDR (.init) - TEACHOS_HIGH)
+ {
+ /*
+ * Make sure that the crt code is wrapped around the compiler generated
+ * initialization code.
+ */
+ KEEP(*:crti.s.obj(.init))
+ KEEP(*(EXCLUDE_FILE (*crti.s.obj crtn.s.obj) .init))
+ KEEP(*:crtn.s.obj(.init))
+ } :text
+
+ .fini ALIGN(4K) : AT(ADDR (.fini) - TEACHOS_HIGH)
+ {
+ /*
+ * Make sure that the crt code is wrapped around the compiler generated
+ * finalizer code.
+ */
+ KEEP(*:crti.s.obj(.fini))
+ KEEP(*(EXCLUDE_FILE (*crti.s.obj crtn.s.obj).fini))
+ KEEP(*:crtn.s.obj(.fini))
+ }
+
+ .text ALIGN(4K) : AT(ADDR (.text) - TEACHOS_HIGH)
+ {
+ *(.text*)
+ }
+
+ .rodata ALIGN(4K) : AT (ADDR (.rodata) - TEACHOS_HIGH)
+ {
+ *(.rodata)
+ *(.rodata.*)
+ } :rodata
+
+ .ctors ALIGN(4K) : AT (ADDR (.ctors) - TEACHOS_HIGH)
+ {
+ KEEP(*crtbegin.o(.ctors))
+ KEEP(*(EXCLUDE_FILE (*crtend.o) .ctors))
+ KEEP(*(SORT(.ctors.*)))
+ KEEP(*crtend.o(.ctors))
+ } :data
+
+ .dtors ALIGN(4K) : AT (ADDR (.dtors) - TEACHOS_HIGH)
+ {
+ KEEP(*crtbegin.o(.dtors))
+ KEEP(*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP(*(SORT(.dtors.*)))
+ KEEP(*crtend.o(.dtors))
+ }
+
+ .data ALIGN(4K) : AT (ADDR (.data) - TEACHOS_HIGH)
+ {
+ *(.data)
+ }
+
+ .bss ALIGN(4K) : AT (ADDR (.bss) - TEACHOS_HIGH)
+ {
+ *(COMMON)
+ *(.bss*)
+ }
+
+ /***************************************************************************
+ * In accordance with the symbol definitions at the start, we generate some
+ * symbols to mark the end of our loaded image.
+ ***************************************************************************/
+ _end_virtual = ADDR(.bss) + SIZEOF(.bss);
+ _end_linear = _end_virtual - TEACHOS_HIGH;
+
+ /DISCARD/ : { *(.comment) }
+}
diff --git a/source/kernel/src/entry.cpp b/source/kernel/src/entry.cpp
new file mode 100644
index 0000000..0daf227
--- /dev/null
+++ b/source/kernel/src/entry.cpp
@@ -0,0 +1,9 @@
+namespace teachos
+{
+ extern "C" auto kernel_main() -> void
+ {
+ while(true) {
+ asm volatile ("nop");
+ }
+ }
+}