From 7a47fbaea825bcd7b1d82c8f9e542e63fcc440ec Mon Sep 17 00:00:00 2001 From: Mathieu Strypsteen Date: Mon, 11 Nov 2024 09:06:58 +0100 Subject: [PATCH] Only log to serial in a VM --- Cargo.lock | 10 ++++++++++ kernel/src/main.rs | 5 +++-- lib/kernel-common/src/loader_struct.rs | 1 + lib/kernel-common/src/log.rs | 12 ++++++++++-- loader/Cargo.toml | 1 + loader/src/loader_struct.rs | 3 ++- loader/src/main.rs | 12 ++++++++++-- qemu.sh | 2 +- 8 files changed, 38 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 624c242..d5badba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -204,6 +204,7 @@ dependencies = [ "elf", "kernel-common", "log", + "raw-cpuid", "static-alloc", "uefi", ] @@ -300,6 +301,15 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "raw-cpuid" +version = "11.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0" +dependencies = [ + "bitflags", +] + [[package]] name = "regex" version = "1.11.1" diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 1b759f8..bf6a885 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -38,6 +38,7 @@ static LOADER_STRUCT: Mutex = Mutex::new(LoaderStruct { phys_heap_start: 0, rsdp_address: 0, available_memory: [LoaderStructMemoryRegion { initial_page: 0, page_count: 0 }; 1024], + vm: 0, }); global_asm!(include_str!("cpu/boot.s"), options(att_syntax)); @@ -47,13 +48,13 @@ extern "C" fn early_main(temp_loader_struct: *const LoaderStruct) -> ! { unsafe { ALLOC.lock().init(KERNEL_HEAP_START as usize, KERNEL_HEAP_INITIAL_SIZE); } - init_logger(); - info!("Starting kernel..."); let mut loader_struct = LOADER_STRUCT.lock(); unsafe { temp_loader_struct.copy_to(&mut *loader_struct, 1); } assert_eq!(loader_struct.magic, LOADER_STRUCT_MAGIC); + init_logger(loader_struct.vm != 0); + info!("Starting kernel..."); setup_gdt(); setup_idt(); setup_paging(&loader_struct, loader_struct.phys_kernel_start, loader_struct.phys_heap_start); diff --git a/lib/kernel-common/src/loader_struct.rs b/lib/kernel-common/src/loader_struct.rs index 65ae4fd..258449f 100644 --- a/lib/kernel-common/src/loader_struct.rs +++ b/lib/kernel-common/src/loader_struct.rs @@ -12,6 +12,7 @@ pub struct LoaderStruct { pub phys_heap_start: u64, pub rsdp_address: u64, pub available_memory: [LoaderStructMemoryRegion; 1024], + pub vm: u8, } pub const LOADER_STRUCT_MAGIC: u64 = 0x123456789abcdef0; diff --git a/lib/kernel-common/src/log.rs b/lib/kernel-common/src/log.rs index 9e10c59..eaf9df2 100644 --- a/lib/kernel-common/src/log.rs +++ b/lib/kernel-common/src/log.rs @@ -1,4 +1,7 @@ -use core::fmt::{Result, Write}; +use core::{ + fmt::{Result, Write}, + sync::atomic::{AtomicBool, Ordering}, +}; use log::{LevelFilter, Log, Metadata}; @@ -8,9 +11,13 @@ struct SerialWriter; pub struct SerialLogger; static LOGGER: SerialLogger = SerialLogger {}; +static SERIAL_ENABLED: AtomicBool = AtomicBool::new(false); impl Write for SerialWriter { fn write_str(&mut self, s: &str) -> Result { + if !SERIAL_ENABLED.load(Ordering::SeqCst) { + return Ok(()); + } for byte in s.bytes() { unsafe { outb(0x3f8, byte); @@ -30,7 +37,8 @@ impl Log for SerialLogger { fn flush(&self) {} } -pub fn init_logger() { +pub fn init_logger(serial_enabled: bool) { + SERIAL_ENABLED.store(serial_enabled, Ordering::SeqCst); log::set_logger(&LOGGER).unwrap(); log::set_max_level(LevelFilter::Trace); } diff --git a/loader/Cargo.toml b/loader/Cargo.toml index 3f1b031..733e6ac 100644 --- a/loader/Cargo.toml +++ b/loader/Cargo.toml @@ -8,5 +8,6 @@ license = "Unlicense" elf = {version = "0.7.4", default-features = false} kernel-common = {path = "../lib/kernel-common"} log = "0.4.22" +raw-cpuid = "11.2.0" static-alloc = "0.2.5" uefi = "0.33.0" diff --git a/loader/src/loader_struct.rs b/loader/src/loader_struct.rs index b984a12..d6796db 100644 --- a/loader/src/loader_struct.rs +++ b/loader/src/loader_struct.rs @@ -4,13 +4,14 @@ use uefi::{ mem::memory_map::{MemoryMap, MemoryMapOwned}, }; -pub fn generate_loader_struct(memory_map: &MemoryMapOwned, phys_start: u64, heap_start: u64, rsdp_address: u64) -> LoaderStruct { +pub fn generate_loader_struct(memory_map: &MemoryMapOwned, phys_start: u64, heap_start: u64, rsdp_address: u64, vm: bool) -> LoaderStruct { let mut loader_struct = LoaderStruct { magic: LOADER_STRUCT_MAGIC, phys_kernel_start: phys_start, phys_heap_start: heap_start, rsdp_address, available_memory: [LoaderStructMemoryRegion { initial_page: 0, page_count: 0 }; 1024], + vm: vm as u8, }; let mut next_entry = 0; for i in memory_map.entries() { diff --git a/loader/src/main.rs b/loader/src/main.rs index ee74e6f..1e90936 100644 --- a/loader/src/main.rs +++ b/loader/src/main.rs @@ -20,6 +20,7 @@ use kernel_common::{ use loader_struct::generate_loader_struct; use log::{error, info}; use paging::setup_paging; +use raw_cpuid::CpuId; use static_alloc::Bump; use uefi::{ boot::{allocate_pages, exit_boot_services}, @@ -40,9 +41,16 @@ const KERNEL: &[u8] = include_bytes!("../../target/x86_64-unknown-none/release/k #[entry] fn main() -> Status { - init_logger(); + let cpuid = CpuId::new(); + let features = cpuid.get_feature_info().unwrap(); + init_logger(features.has_hypervisor()); info!("Starting bootloader..."); uefi::helpers::init().unwrap(); + assert!(features.has_rdrand()); + let extended_features = cpuid.get_extended_feature_info().unwrap(); + assert!(extended_features.has_smap()); + assert!(extended_features.has_smep()); + assert!(cpuid.get_extended_processor_and_feature_identifiers().unwrap().has_syscall_sysret()); let (kernel_start, kernel_entry) = load_kernel(KERNEL); let heap_start = allocate_pages(AllocateType::AnyPages, MemoryType::LOADER_DATA, KERNEL_HEAP_INITIAL_SIZE / 0x1000).unwrap().as_ptr() as u64; let rsdp = AtomicU64::new(0); @@ -58,7 +66,7 @@ fn main() -> Status { let memory_map = unsafe { exit_boot_services(MemoryType::LOADER_DATA) }; let pml4 = setup_paging(&memory_map, heap_start); map_kernel(KERNEL, pml4, kernel_start); - let loader_struct = generate_loader_struct(&memory_map, kernel_start, heap_start, rsdp.load(Ordering::SeqCst)); + let loader_struct = generate_loader_struct(&memory_map, kernel_start, heap_start, rsdp.load(Ordering::SeqCst), features.has_hypervisor()); info!("Jumping to kernel..."); unsafe { (mem::transmute::<_, extern "C" fn(&LoaderStruct) -> !>(kernel_entry))(&loader_struct); diff --git a/qemu.sh b/qemu.sh index 7137458..b287118 100755 --- a/qemu.sh +++ b/qemu.sh @@ -2,4 +2,4 @@ # shellcheck disable=SC2068 set -euo pipefail ./build.sh -qemu-system-x86_64 -M q35 -accel kvm -cpu qemu64,+rdrand -m 256M -L /usr/share/OVMF -bios OVMF_CODE.fd -drive file=img/os.img,format=raw $@ +qemu-system-x86_64 -M q35 -accel kvm -cpu qemu64,rdrand,smap,smep -m 256M -L /usr/share/OVMF -bios OVMF_CODE.fd -drive file=img/os.img,format=raw $@