From b3c92486b31a2c5a38bcc2a04c5ed424c1e6a690 Mon Sep 17 00:00:00 2001 From: August Date: Sun, 5 Apr 2026 12:16:08 -0400 Subject: [PATCH] Experiments with GDT --- Makefile.toml | 43 ++--------------------------------- configs/init.toml | 6 +++++ configs/server_config.toml | 13 ----------- docs/API.md | 28 +++++++++++++++++++++++ kernel/src/arch/x86_64/gdt.rs | 5 ++-- kernel/src/main.rs | 18 +++++++++++++-- 6 files changed, 55 insertions(+), 58 deletions(-) create mode 100644 configs/init.toml delete mode 100644 configs/server_config.toml create mode 100644 docs/API.md diff --git a/Makefile.toml b/Makefile.toml index 553521b..0594723 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -30,8 +30,6 @@ default_to_workspace = false LIMINEDIR = "/usr/share/limine" # Compile target TARGET = "x86_64-unknown-none" -# Binaries included in the OS initramfs -BINS = [] [env.development] PROFILE = "dev" @@ -61,7 +59,7 @@ alias = "run" [tasks.clean_all] -run_task = { name = ["clean_kernel", "clean_initramfs", "clean_iso"] } +run_task = { name = ["clean_kernel", "clean_iso"] } [tasks.clean_kernel] command = "cargo" @@ -74,10 +72,6 @@ script = "rustup install nightly; rustup target add ${TARGET}" command = "rm" args = ["-rf", "build/iso", "build/gila.iso"] -[tasks.clean_initramfs] -command = "rm" -args = ["-rf", "build/initramfs", "build/initramfs.tar.lzma"] - [tasks.lib] condition = { files_modified = { input = ["libgila/src/**/*.rs"], output = ["${ARTIFACTDIR}/libgila.rlib"] }, fail_message = "(inputs unchanged)" } dependencies = [] @@ -94,34 +88,6 @@ dependencies = ["lib"] command = "cargo" args = ["build", "--profile", "${PROFILE}", "-p", "kernel"] -[tasks.bins] -dependencies = [] - - - - - -[tasks.initramfs] -condition = { files_modified = { input = [ - # This will not depend on *every* binary we build. - # If we mount a disk later in boot we can store other binaries there. - "configs/server_config.toml" -], output = ["build/${ARCH}/initramfs.tar.lzma"] }, fail_message = "(inputs unchanged)" } -dependencies = ["bins"] -script = ''' - mkdir -p build/initramfs/system/bin - mkdir -p build/initramfs/system/cfg - mkdir -p build/${ARCH} - - for bin in $(echo ${BINS} | tr ";" " ") - do - cp ${ARTIFACTDIR}/$bin build/initramfs/system/bin/ - done - cp configs/server_config.toml build/initramfs/system/cfg/ - - tar -c --lzma -f build/${ARCH}/initramfs.tar.lzma build/initramfs -''' - [tasks.iso] condition = { files_modified = { input = [ "${ARTIFACTDIR}/kernel", @@ -131,7 +97,7 @@ condition = { files_modified = { input = [ "${LIMINEDIR}/limine-uefi-cd.bin", "${LIMINEDIR}/${LIMINEBIN}" ], output = ["build/gila.iso"] }, fail_message = "(inputs unchanged)" } -dependencies = ["kernel", "initramfs"] +dependencies = ["kernel"] script = ''' mkdir -p build/iso/boot/limine mkdir -p build/iso/EFI/BOOT @@ -142,14 +108,9 @@ script = ''' cp -f ${LIMINEDIR}/limine-bios-cd.bin build/iso/boot/limine/ cp -f ${LIMINEDIR}/limine-uefi-cd.bin build/iso/boot/limine/ cp -f ${LIMINEDIR}/${LIMINEBIN} build/iso/EFI/BOOT - cp -f build/${ARCH}/initramfs.tar.lzma build/iso/boot/${ARCH} cp -f ${ARTIFACTDIR}/kernel build/iso/boot/${ARCH}/gila - mkdir -p build/iso/system/bin - mkdir -p build/iso/system/tmp - mkdir -p build/iso/system/cfg - xorriso -as mkisofs \ -b boot/limine/limine-bios-cd.bin \ -no-emul-boot \ diff --git a/configs/init.toml b/configs/init.toml new file mode 100644 index 0000000..2d8ad7d --- /dev/null +++ b/configs/init.toml @@ -0,0 +1,6 @@ +[deployment] +libgila_version = "0.1.0" +arch = "x86_64" +# Optional +name = "example" +version = "0.1.0" \ No newline at end of file diff --git a/configs/server_config.toml b/configs/server_config.toml deleted file mode 100644 index e3d3315..0000000 --- a/configs/server_config.toml +++ /dev/null @@ -1,13 +0,0 @@ -# The configuration file detailing which system servers -# are responsible for what responsibilities. - -# This configuration file details several tables. Each table -# is a category of server the OS will launch to provide -# userspace functionality. Each key in the table is a specific -# functionality. - -[filesystems] - -[devices] - -[services] \ No newline at end of file diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 0000000..0b2b3f3 --- /dev/null +++ b/docs/API.md @@ -0,0 +1,28 @@ +# Application Programming Interface + +## Overview + +The Gila microkernel has a very limited API surface, but several components +developed alongside it expose additional functionality- such as `libgila` and +Userboot, which are treated as extensions of the kernel. + +## The libgila Library + +The `libgila` library is shared between the kernel and any binaries built for +it, serving to abstract the syscall API and any structures or protocols that +pass the kernel-mode boundary. It provides the official kernel API, and its +version number is incremented independent of the kernel's. + +## Userboot + +Userboot is an early-boot program which is launched as the first unprivileged +process by Gila. The kernel will pass several pieces of data to it, such as the +addresses of device tree blobs, framebuffers, and ACPI tables. These addresses +will not necessarily be mapped to memory. What the kernel *will* map is the +page range containing the initramfs, which Userboot is responsible for +decompressing and parsing. If the initramfs's structure & manifest file do not +match the specification denoted here, Userboot will fail to complete the boot +process. + +## Initramfs Structure + diff --git a/kernel/src/arch/x86_64/gdt.rs b/kernel/src/arch/x86_64/gdt.rs index 158b67a..4441748 100644 --- a/kernel/src/arch/x86_64/gdt.rs +++ b/kernel/src/arch/x86_64/gdt.rs @@ -42,7 +42,8 @@ pub fn read_gdt() -> GlobalDescriptorTable { // x86 gdtr: Lower 2 8-bit bytes (lower 16 bits) is the size of the GDT, // in 8-bit bytes, minus one. // Bits 16 through 79 are the virtual address of the GDT. - let (limit, addr) = (addr.bits(0..=15) as usize + 1, addr.bits(16..=79) as u64); - let gdt_raw: &[u64] = unsafe { core::slice::from_raw_parts(addr as *const u64, limit / 8) }; + let limit = addr.bits(0..=15) as usize + 1; + let base = addr.bits(16..=79) as u64; + let gdt_raw: &[u64] = unsafe { core::slice::from_raw_parts(base as *const u64, (limit / 8) - 1) }; GlobalDescriptorTable::from_raw_entries(gdt_raw) } diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 89ac535..fb6b456 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -16,6 +16,8 @@ mod panic; mod process; mod util; +use core::{arch::asm, ptr::addr_of}; + use arch::x86_64::interrupts::IDT; use arch::x86_64::serial::SerialPort; use boot::{BASE_REVISION, params, *}; @@ -28,7 +30,10 @@ use lazy_static::lazy_static; use limine::firmware_type::FirmwareType; use spin::mutex::Mutex; -use crate::{arch::x86_64::cpuid::{CPUID, virt_supported}, memory::HHDM_RESPONSE}; +use crate::{ + arch::x86_64::{cpuid::{CPUID, virt_supported}, gdt::GdtEntryRead}, + memory::HHDM_RESPONSE, +}; lazy_static! { pub static ref SERIAL_3F8: Mutex = Mutex::new( @@ -153,9 +158,18 @@ unsafe extern "C" fn main() -> ! { let l4_start = x86_64::registers::control::Cr3::read().0.start_address(); log_info!("Physical address of current L4 table: 0x{:x}", l4_start); - log_info!("Virtual address of current L4 table: 0x{:x}", l4_start.as_u64() + HHDM_RESPONSE.offset()); + log_info!( + "Virtual address of current L4 table: 0x{:x}", + l4_start.as_u64() + HHDM_RESPONSE.offset() + ); //iter_table(4, &PML4); + let gdt = crate::arch::x86_64::gdt::read_gdt(); + log_info!("GDT length: {}", gdt.limit() + 1); + for entry in gdt.entries() { + log_info!("GDT entry: Flags 0b{:b}, Access 0b{:b}", entry.flags(), entry.access()); + } + panic!("Finished boot, but cannot start init because processes not implemented!"); }