From 76b7e7b93cce0564f137cfe608bd7d6e986380c2 Mon Sep 17 00:00:00 2001 From: shibedrill Date: Wed, 28 May 2025 01:38:19 -0400 Subject: [PATCH] saving before I sleep --- Cargo.lock | 39 +++++++++++++++++++++++-------- Cargo.toml | 4 ++-- README.md | 44 ++++++++++++++++++----------------- src/kernel/arch/x86_64/gdt.rs | 35 +++++++++++----------------- src/kernel/boot/mod.rs | 20 ++++------------ src/kernel/boot/modules.rs | 13 +++++++++-- src/kernel/boot/params.rs | 2 +- src/kernel/device/acpi.rs | 6 +++++ src/kernel/device/mod.rs | 13 ++--------- src/kernel/interrupt/mod.rs | 3 +++ src/kernel/main.rs | 26 +++++++++++++++++---- src/kernel/memory.rs | 19 +++++++++++++++ src/kernel/util.rs | 3 +++ 13 files changed, 138 insertions(+), 89 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ac43214..d60f3b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,16 +106,23 @@ dependencies = [ "enumflags2", "fdt", "flagset", + "intbits", "lazy_static", "limine", "lzma-rs", "once_cell", - "raw-cpuid", "spin 0.10.0", "talc", + "tar-no-std", "x86_64", ] +[[package]] +name = "intbits" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5170c2c8ecda29c1bccb9d95ccbe107bc75fa084dc0c9c6087e719f9d46330e5" + [[package]] name = "lazy_static" version = "1.5.0" @@ -166,6 +173,15 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.21.3" @@ -200,15 +216,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "raw-cpuid" -version = "11.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" -dependencies = [ - "bitflags", -] - [[package]] name = "rustversion" version = "1.0.20" @@ -256,6 +263,18 @@ dependencies = [ "lock_api", ] +[[package]] +name = "tar-no-std" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15574aa79d3c04a12f3cb53ff976d5571e53b9d8e0bdbe4021df0a06473dd1c9" +dependencies = [ + "bitflags", + "log", + "memchr", + "num-traits", +] + [[package]] name = "unicode-ident" version = "1.0.18" diff --git a/Cargo.toml b/Cargo.toml index eeb4bda..8c7ee02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,14 +8,14 @@ acpi = "5.1.0" enumflags2 = "0.7.11" fdt = { git = "https://github.com/repnop/fdt", version = "0.2.0-alpha1" } flagset = "0.4.7" +intbits = "0.2.0" lazy_static = { version = "1.5.0", default-features = false, features = ["spin_no_std"] } limine = "0.4.0" lzma-rs = { git = "https://github.com/glaeqen/lzma-no-std-rs/", version = "0.2.0", default-features = false } once_cell = { version = "1.20.3", default-features = false, features = ["alloc", "critical-section"] } -raw-cpuid = "11.5.0" spin = "0.10.0" talc = "4.4.2" -x86_64 = "0.15.2" +tar-no-std = "0.3.4" [target.'cfg(target_arch = "x86_64")'.dependencies] x86_64 = "0.15.2" diff --git a/README.md b/README.md index 9b85b5e..331fc91 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Gila is a Rust microkernel OS, inspired by the Xinu embedded OS, as well as Linu ### Complete -- Builds for multiple architectures +- Builds for AArch64, RISCV64, x86_64, and LoongArch64 - Valid Limine kernel - Boots on `x86_64` - Kernel command line parameters @@ -17,25 +17,34 @@ Gila is a Rust microkernel OS, inspired by the Xinu embedded OS, as well as Linu ### In-Progress -- Multi-architecture feature support - Display console - Serial console +- Device discovery & APIs +- Power management +- Paging ### Future/Desired -- Code execution +- Userspace binaries/processes +- Interprocess communication +- Driver server interface - Interrupts and timers - Context switching - Process scheduling -- Shell and CLI - System calls (multi-convention?) -- Multi-user support and access control +- Capability access control - Simultaneous multiprocessing support -- ACPI, USB, PCI(e), SATA -- Filesystem support (FAT32) -- Application sandboxing/permissions control -- Graphical desktop environment -- Networking support +- Hypervisor functionality + +### Additional Future Features (Userspace) + +- Device drivers +- Filesystem drivers +- Shell +- Standard system API +- Rust and C stdlib port +- Display/windowing +- Application sandboxing ## Licensing @@ -64,7 +73,7 @@ Licensed under the GNU Public License v3. See [LICENSE](LICENSE) for details. ## Building and running -Building a bootable kernel is easy. All you need to do is run `cargo build --bin kernel`, and a valid, bootable Limine executable will be generated. However, it cannot be booted without installing it in a bootable Limine filesystem, and it cannot do anything useful without an initramfs containing system servers such as the init server and +Building a bootable kernel is easy. All you need to do is run `cargo build --bin kernel`, and a valid, bootable Limine executable will be generated. However, it cannot be booted without installing it in a bootable Limine filesystem, and it cannot do anything useful without an initramfs containing system servers, such as the init server and device drivers. This project uses [cargo-make](https://github.com/sagiegurari/cargo-make) to handle building ISOs and managing files not associated with Cargo. You need to install it before you can build an ISO automatically. To do so, you can run `cargo install cargo-make`. In addition, you will also need: @@ -76,20 +85,13 @@ This project uses [cargo-make](https://github.com/sagiegurari/cargo-make) to han Then run `cargo make` to invoke the [Makefile.toml](Makefile.toml). -- `cargo make prepare`: Installs needed Rust toolchain. - `cargo make clean_all`: Cleans all built binaries, libraries, initramfs files, and ISOs. -- `cargo make clean_iso`: Clean only files involved in building the ISO. -- `cargo make clean_initramfs`: Clean only files involved in building the initramfs. -- `cargo make clean_kernel`: Clean only kernel binaries and libraries. - `cargo make lib`: Builds `libgila`, the library that the kernel and user code are linked against. - `cargo make kernel`: Builds the kernel ELF file. -- `cargo make bins`: Builds all binaries included in the system. - `cargo make initramfs`: Build the init archive. - `cargo make iso`: Builds the bootable ISO with Limine installed. - `cargo make run`: Builds the ISO and boots it in QEMU. - `cargo make debug`: Launch the kernel in QEMU with debugging enabled, and start and connect GDB. -- `cargo make debug_run`: Launch the kernel in QEMU for debugging. -- `cargo make debug_view`: Attach to a running QEMU process to debug. You do not need to clean any files after making changes. The `lib`, `kernel`, and `iso` tasks will automatically be rerun if their input files change. @@ -108,9 +110,9 @@ Kernel parameters are passed as part of the `cmdline` through [limine.conf](limi List of current extant kernel parameters: -- `-loglevel`: Can be a number or string corresponding to a log level. Only one value supported. Current options are `Disabled`, `Trace`, `Info`, `Warning`, `Error`, and `Critical`. -- `-logdev`: A sequence of one or more values representing devices to log to. Current options are `display` and `serial`. -- `-initramfs`: A valid path to a module to serve as the initramfs (containing the init binary). Only one value supported. +- `-loglevel`: Can be a number or string corresponding to a log level. Only one value supported. Current options are `Disabled`, `Trace`, `Info`, `Warning`, `Error`, and `Critical`. This parameter is case insensitive. +- `-logdev`: A sequence of one or more values representing devices to log to. Current options are `display` and `serial`. This parameter is case insensitive. +- `-initramfs`: A valid path to a module to serve as the initramfs (containing the init binary). Only one value supported. This parameter is case sensitive. The default behavior for each parameter, when not supplied, is: diff --git a/src/kernel/arch/x86_64/gdt.rs b/src/kernel/arch/x86_64/gdt.rs index 68d034a..af82180 100644 --- a/src/kernel/arch/x86_64/gdt.rs +++ b/src/kernel/arch/x86_64/gdt.rs @@ -1,25 +1,18 @@ -use x86_64::structures::gdt::{Descriptor, GlobalDescriptorTable}; +// Copyright (c) 2025 shibedrill +// SPDX-License-Identifier: GPL-3.0-or-later -use lazy_static::lazy_static; +use core::arch::asm; +use core::ptr::addr_of_mut; -use crate::log::{LOGGER, LogLevel}; -use crate::{critical_section, format, log_trace}; +use intbits::Bits; -lazy_static! { - pub static ref GDT: GlobalDescriptorTable = { - let mut gdt = GlobalDescriptorTable::new(); - gdt.append(Descriptor::kernel_code_segment()); - gdt - }; -} - -#[allow(dead_code)] -pub fn setup_gdt() { - critical_section!({ - GDT.load(); - log_trace!( - "GDT: Setting up global descriptor table at 0x{:x}", - core::ptr::addr_of!(GDT) as usize - ); - }); +pub unsafe fn gdt() -> (u8, u64) { + let mut addr: u128 = 0; + unsafe { + asm! { + "sgdt [rax]", + in("rax") addr_of_mut!(addr), + } + } + (addr.bits(0..=15) as u8, addr.bits(16..=79) as u64) } diff --git a/src/kernel/boot/mod.rs b/src/kernel/boot/mod.rs index f56f9a3..b35be62 100644 --- a/src/kernel/boot/mod.rs +++ b/src/kernel/boot/mod.rs @@ -9,6 +9,7 @@ use limine::{BaseRevision, request::*}; #[used] #[unsafe(link_section = ".requests_start_marker")] static _START_MARKER: RequestsStartMarker = RequestsStartMarker::new(); + #[used] #[unsafe(link_section = ".requests_end_marker")] static _END_MARKER: RequestsEndMarker = RequestsEndMarker::new(); @@ -16,28 +17,15 @@ static _END_MARKER: RequestsEndMarker = RequestsEndMarker::new(); #[used] #[unsafe(link_section = ".requests")] pub static BASE_REVISION: BaseRevision = limine::BaseRevision::new(); + #[used] #[unsafe(link_section = ".requests")] pub static MP_REQUEST: MpRequest = limine::request::MpRequest::new(); -#[used] -#[unsafe(link_section = ".requests")] -pub static FILE_REQUEST: ExecutableFileRequest = limine::request::ExecutableFileRequest::new(); -#[used] -#[unsafe(link_section = ".requests")] -pub static RSDP_REQUEST: RsdpRequest = limine::request::RsdpRequest::new(); -#[used] -#[unsafe(link_section = ".requests")] -pub static MODULE_REQUEST: ModuleRequest = limine::request::ModuleRequest::new(); -#[used] -#[unsafe(link_section = ".requests")] -pub static ADDRESS_REQUEST: ExecutableAddressRequest = - limine::request::ExecutableAddressRequest::new(); + #[used] #[unsafe(link_section = ".requests")] pub static FRAMEBUFFER_REQUEST: FramebufferRequest = limine::request::FramebufferRequest::new(); -#[used] -#[unsafe(link_section = ".requests")] -pub static MEMMAP_REQUEST: MemoryMapRequest = limine::request::MemoryMapRequest::new(); + #[used] #[unsafe(link_section = ".requests")] pub static DTB_REQUEST: DeviceTreeBlobRequest = limine::request::DeviceTreeBlobRequest::new(); diff --git a/src/kernel/boot/modules.rs b/src/kernel/boot/modules.rs index 62dc876..acd42b9 100644 --- a/src/kernel/boot/modules.rs +++ b/src/kernel/boot/modules.rs @@ -2,9 +2,18 @@ // SPDX-License-Identifier: GPL-3.0-or-later use lazy_static::lazy_static; -use limine::response::ModuleResponse; +use limine::{ + request::{ExecutableFileRequest, ModuleRequest}, + response::ModuleResponse, +}; -use crate::boot::MODULE_REQUEST; +#[used] +#[unsafe(link_section = ".requests")] +pub static FILE_REQUEST: ExecutableFileRequest = limine::request::ExecutableFileRequest::new(); + +#[used] +#[unsafe(link_section = ".requests")] +pub static MODULE_REQUEST: ModuleRequest = limine::request::ModuleRequest::new(); lazy_static! { pub static ref MODULE_RESPONSE: &'static ModuleResponse = MODULE_REQUEST diff --git a/src/kernel/boot/params.rs b/src/kernel/boot/params.rs index dab3e0d..54d5f20 100644 --- a/src/kernel/boot/params.rs +++ b/src/kernel/boot/params.rs @@ -1,7 +1,7 @@ // Copyright (c) 2025 shibedrill // SPDX-License-Identifier: GPL-3.0-or-later -use crate::boot::FILE_REQUEST; +use crate::boot::modules::FILE_REQUEST; use crate::memory::alloc; use alloc::string::String; use alloc::vec::Vec; diff --git a/src/kernel/device/acpi.rs b/src/kernel/device/acpi.rs index f12f131..79f95ee 100644 --- a/src/kernel/device/acpi.rs +++ b/src/kernel/device/acpi.rs @@ -2,3 +2,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later // TODO: Implement per-arch memory handlers for ACPI memory map regions + +use limine::request::RsdpRequest; + +#[used] +#[unsafe(link_section = ".requests")] +pub static RSDP_REQUEST: RsdpRequest = limine::request::RsdpRequest::new(); diff --git a/src/kernel/device/mod.rs b/src/kernel/device/mod.rs index 5d9847e..fc8f47f 100644 --- a/src/kernel/device/mod.rs +++ b/src/kernel/device/mod.rs @@ -6,21 +6,12 @@ mod acpi; use fdt::*; use lazy_static::lazy_static; use limine::response::{DeviceTreeBlobResponse, RsdpResponse}; -use raw_cpuid::native_cpuid::CpuIdReaderNative; -use raw_cpuid::*; -use crate::boot::{DTB_REQUEST, RSDP_REQUEST}; +use crate::boot::DTB_REQUEST; +use crate::device::acpi::RSDP_REQUEST; use crate::log::{LOGGER, LogLevel}; use crate::{format, log_info, log_trace, log_warning}; -pub fn log_cpuid() { - let cpuid: CpuId = CpuId::with_cpuid_reader(CpuIdReaderNative); - log_trace!( - "Device: CPU vendor: {}", - cpuid.get_processor_brand_string().unwrap().as_str() - ) -} - lazy_static! { pub static ref DTB: Option<&'static DeviceTreeBlobResponse> = match DTB_REQUEST.get_response() { Some(resp) => { diff --git a/src/kernel/interrupt/mod.rs b/src/kernel/interrupt/mod.rs index a0c44b6..407267d 100644 --- a/src/kernel/interrupt/mod.rs +++ b/src/kernel/interrupt/mod.rs @@ -1,3 +1,6 @@ +// Copyright (c) 2025 shibedrill +// SPDX-License-Identifier: GPL-3.0-or-later + pub fn double_fault(info: &str) -> ! { panic!("Double fault: {}", info); } diff --git a/src/kernel/main.rs b/src/kernel/main.rs index 036d0f9..910c709 100644 --- a/src/kernel/main.rs +++ b/src/kernel/main.rs @@ -19,17 +19,21 @@ mod process; #[macro_use] mod util; +use core::arch::asm; + +use arch::x86_64::gdt::gdt; #[cfg(target_arch = "x86_64")] use arch::x86_64::serial::Serialport; use arch::asm::*; use boot::{modules::*, params, *}; use constants::*; -use device::*; use log::*; +use memory::{MEMMAP_REQUEST, HHDM_RESPONSE}; use memory::alloc::{format, string::*, vec}; use params::*; +use intbits::{self, Bits}; use limine::file::File; use limine::memory_map::EntryType; #[allow(unused_imports)] @@ -195,8 +199,7 @@ unsafe extern "C" fn main() -> ! { panic!("Memory map contains no entries"); } - //#[cfg(target_arch = "x86_64")] - //gdt::setup_gdt(); + log_info!("HHDM offset: 0x{:x}", HHDM_RESPONSE.offset()); #[cfg(target_arch = "x86_64")] { @@ -208,10 +211,23 @@ unsafe extern "C" fn main() -> ! { "Boot: Paging enable: {}", unsafe { cr0() & (0b1 << 31) } == 1 ); + let pd_addr = { + let cr3: u64; + unsafe { + asm! { + "mov {}, cr3", + out(reg) cr3, + } + } + log_trace!("Boot: cr3 value: 0b{:b}", cr3); + cr3.bits(12..=31) + }; + log_trace!("Boot: Physical address of page directory: 0x{:x}", pd_addr); + log_trace!("Boot: Virtual address of page directory: 0x{:x}", pd_addr + HHDM_RESPONSE.offset()); + log_trace!("Boot: GDT: 0x{:x} bytes @ 0x{:x}", unsafe { gdt().0 }, unsafe { gdt().1} ); + log_trace!("Boot: GDT: 0x{:x}", unsafe { *((gdt().1 + 0x0) as *const u64) }) } - log_cpuid(); - panic!("Bailing"); #[allow(unreachable_code)] diff --git a/src/kernel/memory.rs b/src/kernel/memory.rs index 8d98d81..c32df88 100644 --- a/src/kernel/memory.rs +++ b/src/kernel/memory.rs @@ -4,12 +4,31 @@ #![allow(unused_imports)] use enumflags2::*; +use lazy_static::lazy_static; +use limine::{request::{ExecutableAddressRequest, HhdmRequest, MemoryMapRequest}, response::HhdmResponse}; use core::alloc::{Allocator, Layout}; use talc::*; pub extern crate alloc; +#[used] +#[unsafe(link_section = ".requests")] +pub static ADDRESS_REQUEST: ExecutableAddressRequest = + limine::request::ExecutableAddressRequest::new(); + +#[used] +#[unsafe(link_section = ".requests")] +pub static MEMMAP_REQUEST: MemoryMapRequest = limine::request::MemoryMapRequest::new(); + +#[used] +#[unsafe(link_section = ".requests")] +pub static HHDM_REQUEST: HhdmRequest = limine::request::HhdmRequest::new(); + +lazy_static! { + pub static ref HHDM_RESPONSE: &'static HhdmResponse = HHDM_REQUEST.get_response().expect("Did not get HHDM response from bootloader"); +} + static mut ARENA: [u8; 10000] = [0; 10000]; #[global_allocator] diff --git a/src/kernel/util.rs b/src/kernel/util.rs index 774552b..5e0c156 100644 --- a/src/kernel/util.rs +++ b/src/kernel/util.rs @@ -1,3 +1,6 @@ +// Copyright (c) 2025 shibedrill +// SPDX-License-Identifier: GPL-3.0-or-later + #[macro_export] macro_rules! critical_section { ($b:block) => {