need to push this shit before I murder someone

This commit is contained in:
August 2026-07-06 00:20:39 +00:00
parent 749a0d6bec
commit 088a7e3fc8
Signed by: shibedrill
SSH Key Fingerprint: SHA256:M0m3JW1s38BgO2t0fG146Yxd9OJ2IOqkvCAsuRHQ6Pw
4 changed files with 78 additions and 99 deletions

View File

@ -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,

View File

@ -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(),

View File

@ -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,
asm::ltr,
x86_64::{gdt::SELECTORS, interrupts::IDT},
},
}, log::{LOGGER, LogLevel}, log_info, memory::alloc::format,
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,

View File

@ -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<SerialPort> = 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!");
}