Compare commits

...

3 Commits

Author SHA1 Message Date
f9fd19b6d0
fixing GPFs
All checks were successful
Continuous Integration / Check (push) Successful in 43s
Continuous Integration / Clippy (push) Successful in 41s
2026-07-05 15:01:51 +00:00
108ddb7cf9
modularity 2026-07-05 14:03:18 +00:00
c9f1f6466d
Remove garbage files 2026-07-05 13:42:25 +00:00
9 changed files with 78 additions and 28094 deletions

28013
1

File diff suppressed because it is too large Load Diff

BIN
a.out

Binary file not shown.

View File

@ -15,6 +15,7 @@ compile_error!(
pub mod x86_64; pub mod x86_64;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub use x86_64::asm; pub use x86_64::asm;
pub use x86_64::startup;
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
pub mod aarch64; pub mod aarch64;

View File

@ -54,7 +54,6 @@ pub struct Selectors {
pub sel_kernel_stack: SegmentSelector, pub sel_kernel_stack: SegmentSelector,
pub sel_user_code: SegmentSelector, pub sel_user_code: SegmentSelector,
pub sel_user_stack: SegmentSelector, pub sel_user_stack: SegmentSelector,
#[allow(unused)]
pub sel_tss: SegmentSelector, pub sel_tss: SegmentSelector,
pub gdt: GlobalDescriptorTable<48>, pub gdt: GlobalDescriptorTable<48>,
} }
@ -79,7 +78,7 @@ lazy_static! {
// DO NOT REORDER // DO NOT REORDER
let sel_tss = gdt.append( let sel_tss = gdt.append(
Descriptor::tss_segment(&TSS).set_flags(DescriptorFlags::from_bits_retain(0b1010)) Descriptor::tss_segment(&TSS).set_flags(DescriptorFlags::from_bits_retain(0b1010))
//.set_access(0b10001011), // This would set the TSS to Busy, but it causes a GPF. .set_access(0b10001011), // This would set the TSS to Busy, but it causes a GPF.
); );
Selectors { Selectors {
sel_kernel_code: sel_k_cs, sel_kernel_code: sel_k_cs,

View File

@ -23,9 +23,9 @@ lazy_static! {
// code. The x86_interrupt ABI is always breaking, and this // code. The x86_interrupt ABI is always breaking, and this
// approach will fall apart once multiarch support is re-added. // approach will fall apart once multiarch support is re-added.
unsafe { unsafe {
idt.double_fault.set_handler_fn(double_fault).set_code_selector(SELECTORS.sel_kernel_code).set_privilege_level(x86_64::PrivilegeLevel::Ring0); 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).set_privilege_level(x86_64::PrivilegeLevel::Ring0); 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).set_privilege_level(x86_64::PrivilegeLevel::Ring0); idt.general_protection_fault.set_handler_fn(gen_prot_fault).set_code_selector(SELECTORS.sel_kernel_code);
} }
idt idt
}; };
@ -35,6 +35,7 @@ lazy_static! {
#[allow(dead_code)] #[allow(dead_code)]
extern "x86-interrupt" fn double_fault(info: InterruptStackFrame, _: u64) -> ! { extern "x86-interrupt" fn double_fault(info: InterruptStackFrame, _: u64) -> ! {
crate::interrupt::double_fault(format!("{info:#?}")); crate::interrupt::double_fault(format!("{info:#?}"));
unsafe { info.iretq() }
} }
#[allow(dead_code)] #[allow(dead_code)]
@ -68,11 +69,13 @@ extern "x86-interrupt" fn page_fault(info: InterruptStackFrame, errcode: PageFau
} }
#[allow(dead_code)] #[allow(dead_code)]
extern "x86-interrupt" fn gen_prot_fault(info: InterruptStackFrame, _: u64) { extern "x86-interrupt" fn gen_prot_fault(info: InterruptStackFrame, error: u64) {
crate::interrupt::gen_prot_fault(format!( crate::interrupt::gen_prot_fault(format!(
"RIP 0x{:x}, CS {} ({:?})", "RIP 0x{:x}, CS {} ({:?}), error: 0x{:x}",
info.instruction_pointer, info.instruction_pointer,
info.code_segment.index(), info.code_segment.index(),
info.code_segment.rpl() info.code_segment.rpl(),
error
)); ));
unsafe { info.iretq() }
} }

View File

@ -8,3 +8,4 @@ pub mod gdt;
pub mod intel_virt; pub mod intel_virt;
pub mod interrupts; pub mod interrupts;
pub mod serial; pub mod serial;
pub mod startup;

View File

@ -0,0 +1,46 @@
use x86_64::{VirtAddr, registers::rflags::RFlags, structures::idt::InterruptStackFrameValue};
use crate::{
arch::{
asm::ltr,
x86_64::{
gdt::{SELECTORS, dump_gdt},
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!");
x86_64::registers::model_specific::Star::write(
SELECTORS.sel_user_code,
SELECTORS.sel_user_stack,
SELECTORS.sel_kernel_code,
SELECTORS.sel_kernel_stack,
)
.expect("Segment order in GDT is bad");
dump_gdt();
ltr(SELECTORS.sel_tss.index());
Ok(())
}
pub fn jump_to_usermode(sp: VirtAddr, ip: VirtAddr) -> ! {
unsafe {
InterruptStackFrameValue::new(
ip,
SELECTORS.sel_user_code,
RFlags::INTERRUPT_FLAG,
sp,
SELECTORS.sel_user_stack,
)
.iretq();
}
}

View File

@ -4,8 +4,8 @@
use crate::log::*; use crate::log::*;
use crate::{format, log_error, memory::alloc::string::String}; use crate::{format, log_error, memory::alloc::string::String};
pub fn double_fault(info: String) -> ! { pub fn double_fault(info: String) {
panic!("Double fault: {}", info); log_error!("Double fault: {}", info);
} }
pub fn page_fault_fatal(addr: usize, info: String) -> ! { pub fn page_fault_fatal(addr: usize, info: String) -> ! {

View File

@ -18,7 +18,6 @@ mod util;
use core::ptr::addr_of; use core::ptr::addr_of;
use arch::x86_64::interrupts::IDT;
use arch::x86_64::serial::SerialPort; use arch::x86_64::serial::SerialPort;
use boot::{BASE_REVISION, params, *}; use boot::{BASE_REVISION, params, *};
use constants::*; use constants::*;
@ -31,16 +30,10 @@ use limine::firmware::{
FIRMWARE_TYPE_EFI32, FIRMWARE_TYPE_EFI64, FIRMWARE_TYPE_SBI, FIRMWARE_TYPE_X86BIOS, FIRMWARE_TYPE_EFI32, FIRMWARE_TYPE_EFI64, FIRMWARE_TYPE_SBI, FIRMWARE_TYPE_X86BIOS,
}; };
use spin::mutex::Mutex; use spin::mutex::Mutex;
use x86_64::{VirtAddr, registers::rflags::RFlags, structures::idt::InterruptStackFrameValue}; use x86_64::VirtAddr;
use crate::{ use crate::{
arch::{ arch::x86_64::cpuid::{CPUID, virt_supported},
asm::ltr,
x86_64::{
cpuid::{CPUID, virt_supported},
gdt::SELECTORS,
},
},
boot::modules::MODULE_RESPONSE, boot::modules::MODULE_RESPONSE,
memory::paging::active_root_table, memory::paging::active_root_table,
}; };
@ -79,31 +72,22 @@ unsafe extern "C" fn main() -> ! {
LOGGER.lock().add_device(Box::new(serial_logger)); LOGGER.lock().add_device(Box::new(serial_logger));
} }
log_trace!("Configured kernel logging devices"); log_trace!("Configured kernel logging devices");
let log_level = LOGGER.lock().level;
log_info!("Log level: {:?}", log_level);
} }
// END OF CRITICAL AREA // END OF CRITICAL AREA
// Fallible code can be placed below this comment // Fallible code can be placed below this comment
let _ = arch::startup::init();
// Initialize all statics so the bootloader memory can be reclaimed // Initialize all statics so the bootloader memory can be reclaimed
memory::init_statics(); memory::init_statics();
// Ensure IDT exists
SELECTORS.gdt.load();
log_info!("GDT loaded!");
IDT.load();
log_info!("IDT loaded!");
log_info!( log_info!(
"Kernel cmdline: {}", "Boot cmdline: {} {}",
EXECUTABLE_FILE_RESPONSE.executable_file().path(),
EXECUTABLE_FILE_RESPONSE.executable_file().cmdline() EXECUTABLE_FILE_RESPONSE.executable_file().cmdline()
); );
log_info!(
"Kernel file path: {}",
EXECUTABLE_FILE_RESPONSE.executable_file().path()
);
let log_level = log::LOGGER.lock().level;
log_info!("Log level: {:?}", log_level);
// Branding // Branding
for line in ASCII_LOGO { for line in ASCII_LOGO {
@ -181,60 +165,23 @@ unsafe extern "C" fn main() -> ! {
} }
log_info!("Virtualization provider: {:?}", virt_supported()); log_info!("Virtualization provider: {:?}", virt_supported());
{ let root_ptable_info = unsafe { active_root_table() };
let root_ptable_info = unsafe { active_root_table() }; log_info!(
log_info!( "Root page table is Level {} at 0x{:x}",
"Root page table is Level {} at 0x{:x}", root_ptable_info.1,
root_ptable_info.1, addr_of!(*root_ptable_info.0) as usize
addr_of!(*root_ptable_info.0) as usize );
);
// This is an expensive function. Only run it if we're actually logging the results.
//let loglevel = LOGGER.lock().level;
//if loglevel <= LogLevel::Trace {
// paging::walk_tables();
//}
}
if let Some(modules_list) = *MODULE_RESPONSE if let Some(modules_list) = *MODULE_RESPONSE
&& modules_list.modules()[0].path().ends_with("/userboot.bin") && modules_list.modules()[0].path().ends_with("/userboot.bin")
{ {
let ub = modules_list.modules()[0]; let ub = modules_list.modules()[0];
log_info!("Found userboot: {} {}", ub.path(), ub.cmdline()); log_info!("Found userboot: {} {}", ub.path(), ub.cmdline());
// TODO: remap userboot as user pages
//let start_addr = VirtAddr::from_ptr(ub.data() as *const [u8]); let start_addr = VirtAddr::from_ptr(ub.data() as *const [u8]);
let start_addr = VirtAddr::from_ptr(usermode_fn as *const fn()); arch::startup::jump_to_usermode(VirtAddr::new(0xfffffff800000000), start_addr)
log_info!("Start address: 0x{:x}", start_addr); } else {
panic!("Userboot not found, cannot boot!");
x86_64::registers::model_specific::Star::write(
SELECTORS.sel_user_code,
SELECTORS.sel_user_stack,
SELECTORS.sel_kernel_code,
SELECTORS.sel_kernel_stack,
)
.expect("fuck");
ltr(SELECTORS.sel_tss.index());
unsafe {
InterruptStackFrameValue::new(
VirtAddr::from_ptr(usermode_fn as *const fn()),
SELECTORS.sel_user_code,
RFlags::INTERRUPT_FLAG,
VirtAddr::new(0xffffffff80000000),
SELECTORS.sel_user_stack,
)
.iretq();
}
}
// TODO:
// - Map APIC
// - Create an interrupt stack frame, push it to stack, and iret to userboot
panic!("Finished boot, but cannot start init because processes not implemented!");
}
fn usermode_fn() -> ! {
log_info!("In usermode!");
loop {
arch::asm::nop();
} }
} }