From 088a7e3fc8be81ee978da5e654a64cd9eda6a011 Mon Sep 17 00:00:00 2001 From: August Date: Mon, 6 Jul 2026 00:20:39 +0000 Subject: [PATCH] need to push this shit before I murder someone --- src/kernel/arch/x86_64/gdt.rs | 16 +++++- src/kernel/arch/x86_64/interrupts.rs | 55 ++++++++++++++---- src/kernel/arch/x86_64/startup.rs | 23 +++++--- src/kernel/main.rs | 83 ++-------------------------- 4 files changed, 78 insertions(+), 99 deletions(-) diff --git a/src/kernel/arch/x86_64/gdt.rs b/src/kernel/arch/x86_64/gdt.rs index cb65e64..57cfd5b 100644 --- a/src/kernel/arch/x86_64/gdt.rs +++ b/src/kernel/arch/x86_64/gdt.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: MIT use core::arch::asm; -use core::ptr::addr_of_mut; +use core::ptr::{addr_of, addr_of_mut}; use intbits::Bits; use lazy_static::lazy_static; @@ -77,7 +77,19 @@ lazy_static! { let sel_u_cs = gdt.append(Descriptor::user_code_segment()); // DO NOT REORDER let sel_tss = gdt.append( - Descriptor::tss_segment(&TSS).set_flags(DescriptorFlags::from_bits_retain(0b1010)) + { + let tss_addr = addr_of!(TSS) as u128; + let tss_size = size_of_val(&TSS) as u128; + let mut tss_descriptor: u128 = 0; + tss_descriptor.set_bits(0..=15, tss_size.bits(0..=15)); // Limit bits 0..=15 + tss_descriptor.set_bits(48..=51, tss_size.bits(16..=19)); // Limit bits 16..=19 + tss_descriptor.set_bits(16..=39, tss_addr.bits(0..=24)); // Base bits 0..=24 + tss_descriptor.set_bits(56..=95, tss_addr.bits(25..=63)); // Base bits 25..=63 + tss_descriptor.set_bits(40..=47, 0b10110001); + tss_descriptor.set_bits(52..=55, 0b1010); + log_info!("TSS descriptor (calculated manually): 0x{:032x}", tss_descriptor); + Descriptor::SystemSegment(tss_descriptor.bits(64..=127) as u64, tss_descriptor.bits(0..=63) as u64) + } ); Selectors { sel_kernel_code: sel_k_cs, diff --git a/src/kernel/arch/x86_64/interrupts.rs b/src/kernel/arch/x86_64/interrupts.rs index e7bfd87..e270c29 100644 --- a/src/kernel/arch/x86_64/interrupts.rs +++ b/src/kernel/arch/x86_64/interrupts.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: MIT use crate::arch::x86_64::gdt::SELECTORS; -use crate::{LOGGER, format, log_info, log_trace}; +use crate::{LOGGER, SERIAL_3F8, format, log_info, log_trace}; use crate::{LogLevel, log_error}; use lazy_static::lazy_static; use x86_64::PhysAddr; @@ -19,18 +19,47 @@ pub fn get_lapic_addr() -> PhysAddr { lazy_static! { pub static ref IDT: InterruptDescriptorTable = { let mut idt = InterruptDescriptorTable::new(); - // TODO: Rewrite using our own x86 interrupt wrapper - // code. The x86_interrupt ABI is always breaking, and this - // approach will fall apart once multiarch support is re-added. unsafe { - idt.double_fault.set_handler_fn(double_fault).set_code_selector(SELECTORS.sel_kernel_code); - idt.page_fault.set_handler_fn(page_fault).set_code_selector(SELECTORS.sel_kernel_code); - idt.general_protection_fault.set_handler_fn(gen_prot_fault).set_code_selector(SELECTORS.sel_kernel_code); + idt.double_fault + .set_handler_fn(double_fault) + .set_code_selector(SELECTORS.sel_kernel_code) + .set_privilege_level(x86_64::PrivilegeLevel::Ring3) + .set_present(true); + idt.page_fault + .set_handler_fn(page_fault) + .set_code_selector(SELECTORS.sel_kernel_code) + .set_privilege_level(x86_64::PrivilegeLevel::Ring3) + .set_present(true); + idt.general_protection_fault + .set_handler_fn(gen_prot_fault) + .set_code_selector(SELECTORS.sel_kernel_code) + .set_privilege_level(x86_64::PrivilegeLevel::Ring3) + .set_present(true); + idt.divide_error + .set_handler_fn(div_zero) + .set_code_selector(SELECTORS.sel_kernel_code) + .set_privilege_level(x86_64::PrivilegeLevel::Ring3) + .set_present(true); + idt.breakpoint + .set_handler_fn(debug) + .set_code_selector(SELECTORS.sel_kernel_code) + .set_privilege_level(x86_64::PrivilegeLevel::Ring3) + .set_present(true); } idt }; } +extern "x86-interrupt" fn div_zero(info: InterruptStackFrame) { + log_error!("Divide by zero error: 0x{:x}, {:?}", info.instruction_pointer, info.code_segment.rpl()); + unsafe { info.iretq() } +} + +extern "x86-interrupt" fn debug(info: InterruptStackFrame) { + log_error!("Debug"); + unsafe { info.iretq() } +} + // Must do this to avoid unused function warning #[allow(dead_code)] extern "x86-interrupt" fn double_fault(info: InterruptStackFrame, _: u64) -> ! { @@ -40,10 +69,11 @@ extern "x86-interrupt" fn double_fault(info: InterruptStackFrame, _: u64) -> ! { #[allow(dead_code)] extern "x86-interrupt" fn page_fault(info: InterruptStackFrame, errcode: PageFaultErrorCode) { - let addr = x86_64::registers::control::Cr2::read(); + SERIAL_3F8.lock().log_writeln("Page fault, baby!"); + let page_fault_addr = x86_64::registers::control::Cr2::read(); log_trace!( "Fault: Page fault with {}, error code 0b{:b}", - match addr { + match page_fault_addr { Ok(addr_inner) => format!("address 0x{:x}", addr_inner), Err(_) => "invalid virtual address".into(), }, @@ -60,7 +90,10 @@ extern "x86-interrupt" fn page_fault(info: InterruptStackFrame, errcode: PageFau | errcode.contains(PageFaultErrorCode::MALFORMED_TABLE) { let info_formatted = format!("{info:#?}"); - crate::interrupt::page_fault_fatal(addr.unwrap().as_u64() as usize, info_formatted) + crate::interrupt::page_fault_fatal( + page_fault_addr.unwrap().as_u64() as usize, + info_formatted, + ) } else { log_error!("Page Fault, trying to recover..."); todo!("Page fault handler (kernel mode)") @@ -71,7 +104,7 @@ extern "x86-interrupt" fn page_fault(info: InterruptStackFrame, errcode: PageFau #[allow(dead_code)] extern "x86-interrupt" fn gen_prot_fault(info: InterruptStackFrame, error: u64) { crate::interrupt::gen_prot_fault(format!( - "RIP 0x{:x}, CS {} ({:?}), error: 0x{:x}", + "RIP 0x{:x}, CS {} (RPL {:?}), error: 0x{:x}", info.instruction_pointer, info.code_segment.index(), info.code_segment.rpl(), diff --git a/src/kernel/arch/x86_64/startup.rs b/src/kernel/arch/x86_64/startup.rs index 6d1aa20..e951a08 100644 --- a/src/kernel/arch/x86_64/startup.rs +++ b/src/kernel/arch/x86_64/startup.rs @@ -1,20 +1,22 @@ -use x86_64::{VirtAddr, registers::rflags::RFlags, structures::idt::InterruptStackFrameValue}; +use x86_64::{VirtAddr, registers::{rflags::RFlags, segmentation::Segment}, structures::idt::InterruptStackFrameValue}; use crate::{ arch::{ - asm::ltr, x86_64::{ - gdt::SELECTORS, interrupts::IDT, - }, - }, log::{LOGGER, LogLevel}, log_info, memory::alloc::format, + asm::ltr, + x86_64::{gdt::SELECTORS, interrupts::IDT}, + }, + log::{LOGGER, LogLevel}, + log_info, + memory::alloc::format, }; pub fn init() -> Result<(), ()> { - // Ensure GDT exists - SELECTORS.gdt.load(); - log_info!("GDT loaded!"); // Load IDT IDT.load(); log_info!("IDT loaded!"); + // Ensure GDT exists + SELECTORS.gdt.load(); + log_info!("GDT loaded!"); x86_64::registers::model_specific::Star::write( SELECTORS.sel_user_code, SELECTORS.sel_user_stack, @@ -22,12 +24,17 @@ pub fn init() -> Result<(), ()> { SELECTORS.sel_kernel_stack, ) .expect("Segment order in GDT is bad"); + unsafe { + x86_64::registers::segmentation::CS::set_reg(SELECTORS.sel_kernel_code); + x86_64::registers::segmentation::SS::set_reg(SELECTORS.sel_kernel_stack); + } //ltr(SELECTORS.sel_tss.index()) // THIS WILL CAUSE A GPF, YOU STUPID WHORE ltr(SELECTORS.sel_tss.0); Ok(()) } pub fn jump_to_usermode(sp: VirtAddr, ip: VirtAddr) -> ! { + log_info!("Jumping to usermode..."); unsafe { InterruptStackFrameValue::new( ip, diff --git a/src/kernel/main.rs b/src/kernel/main.rs index a36b0d4..e7c8b42 100644 --- a/src/kernel/main.rs +++ b/src/kernel/main.rs @@ -16,27 +16,18 @@ mod panic; mod process; mod util; -use core::ptr::addr_of; - use arch::x86_64::serial::SerialPort; -use boot::{BASE_REVISION, params, *}; +use boot::{BASE_REVISION, params}; use constants::*; use log::*; use memory::alloc::{boxed::Box, format, vec}; use params::*; use lazy_static::lazy_static; -use limine::firmware::{ - FIRMWARE_TYPE_EFI32, FIRMWARE_TYPE_EFI64, FIRMWARE_TYPE_SBI, FIRMWARE_TYPE_X86BIOS, -}; use spin::mutex::Mutex; use x86_64::VirtAddr; -use crate::{ - arch::x86_64::cpuid::{CPUID, virt_supported}, - boot::modules::MODULE_RESPONSE, - memory::paging::active_root_table, -}; +use crate::{arch::x86_64::gdt::SELECTORS, boot::modules::MODULE_RESPONSE}; lazy_static! { pub static ref SERIAL_3F8: Mutex = Mutex::new( @@ -100,78 +91,13 @@ unsafe extern "C" fn main() -> ! { .log_writeln("\tWelcome to the Gila microkernel!\n"); log_info!("Booting gila version {}", kernel_version_string()); - match boot::FIRMWARE_TYPE_REQUEST.response() { - Some(resp) => log_info!( - "Firmware type: {}", - match resp.firmware_type { - FIRMWARE_TYPE_SBI => "SBI", - FIRMWARE_TYPE_EFI32 => "UEFI (32-bit)", - FIRMWARE_TYPE_EFI64 => "UEFI (64-bit)", - FIRMWARE_TYPE_X86BIOS => "x86 BIOS", - _ => "Unknown", - } - ), - None => log_warning!("Firmware type: No response"), - } - log_info!("Trans rights!"); - if let Some(framebuffer_response) = FRAMEBUFFER_REQUEST.response() { - let fb = framebuffer_response.framebuffers_rev1().unwrap()[0]; - log_info!("Framebuffer response received"); - for mode in fb.modes() { - log_trace!( - "Mode: {}x{}, {} bits per pixel", - mode.width, - mode.height, - mode.bpp - ); - } - } else { - log_info!("Framebuffer response absent, graphics disabled",); - } - - let smp_response = MP_REQUEST.response(); - match smp_response { - None => log_info!("Multiprocessing response not received"), - Some(resp) => { - log_info!("Multiprocessing response received"); - log_info!("{} CPUs found", resp.cpus().len()); - } - } - - let rsdp_response = RSDP_REQUEST.response(); - match rsdp_response { - None => log_info!("RDSP response not received"), - Some(resp) => { - log_info!("RSDP response received"); - log_trace!("RSDP address: 0x{:x}", resp.address as usize) - } - } - boot::modules::log_modules(); - memory::log_memory(); memory::log_address(); - if let Some(string) = CPUID.get_processor_brand_string() { - log_info!("CPU brand string: {}", string.as_str()); - } - if let Some(string) = CPUID.get_vendor_info() { - log_info!("CPU vendor: {}", string.as_str()); - } - if let Some(string) = CPUID.get_hypervisor_info() { - log_info!("Hypervisor: {:?}", string.identify()); - } - log_info!("Virtualization provider: {:?}", virt_supported()); - - let root_ptable_info = unsafe { active_root_table() }; - log_info!( - "Root page table is Level {} at 0x{:x}", - root_ptable_info.1, - addr_of!(*root_ptable_info.0) as usize - ); - + log_info!("TSS descriptor: 0x{:08x} {:08x}", SELECTORS.gdt.entries()[SELECTORS.sel_tss.index() as usize + 1].raw(), SELECTORS.gdt.entries()[SELECTORS.sel_tss.index() as usize].raw()); if let Some(modules_list) = *MODULE_RESPONSE && modules_list.modules()[0].path().ends_with("/userboot.bin") { @@ -180,7 +106,8 @@ unsafe extern "C" fn main() -> ! { // TODO: remap userboot as user pages let start_addr = VirtAddr::from_ptr(ub.data() as *const [u8]); - arch::startup::jump_to_usermode(VirtAddr::new(0xfffffff800000000), start_addr) + log_trace!("Userboot start address: 0x{:x}", start_addr); + arch::startup::jump_to_usermode(VirtAddr::new(0xffffffff80000000), start_addr) } else { panic!("Userboot not found, cannot boot!"); }