Fix CS in IDT
All checks were successful
Continuous Integration / Check (push) Successful in 46s
Continuous Integration / Clippy (push) Successful in 43s

This commit is contained in:
August 2026-07-03 05:24:35 +00:00
parent ffdad93fed
commit 6882af0390
Signed by: shibedrill
SSH Key Fingerprint: SHA256:M0m3JW1s38BgO2t0fG146Yxd9OJ2IOqkvCAsuRHQ6Pw
9 changed files with 28040 additions and 66 deletions

28013
1 Normal file

File diff suppressed because it is too large Load Diff

View File

@ -160,7 +160,7 @@ args = ["-display", "none", "-drive", "file=build/gila.iso,format=raw,index=0,me
[tasks.debug_run]
dependencies = ["iso"]
command = "${QEMUCOMMAND}"
args = ["-s", "-S", "-display", "none", "-drive", "file=build/gila.iso,format=raw,index=0,media=disk", "-no-reboot", "-no-shutdown", "-serial", "stdio", "-d", "int"]
args = ["-s", "-S", "-display", "none", "-drive", "file=build/gila.iso,format=raw,index=0,media=disk", "-no-reboot", "-serial", "stdio", "-d", "int"]
[tasks.debug_view]
dependencies = ["iso"]

BIN
a.out Executable file

Binary file not shown.

View File

@ -8,6 +8,7 @@ pub fn nop() {
::x86_64::instructions::nop();
}
#[allow(unused)]
pub fn long_mode() -> bool {
let mut output: u32;
unsafe {
@ -29,6 +30,7 @@ pub fn ltr(selector: u16) {
}
}
#[allow(unused)]
pub fn str() -> u16 {
let result: u16;
unsafe {

View File

@ -59,9 +59,8 @@ pub struct Selectors {
pub gdt: GlobalDescriptorTable<48>,
}
pub const TSS: TaskStateSegment = TaskStateSegment::new();
lazy_static! {
pub static ref TSS: TaskStateSegment = TaskStateSegment::new();
#[derive(Debug)]
pub static ref SELECTORS: Selectors = {
let mut gdt = GlobalDescriptorTable::empty();
@ -79,7 +78,8 @@ 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)),
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.
);
Selectors {
sel_kernel_code: sel_k_cs,
@ -134,6 +134,7 @@ pub fn read_gdt() -> GlobalDescriptorTable {
GlobalDescriptorTable::from_raw_entries(gdt_raw)
}
#[allow(unused)]
pub fn dump_gdt() {
let gdt = crate::arch::x86_64::gdt::read_gdt();
log_info!("GDT length: {}", gdt.limit() + 1);

View File

@ -1,12 +1,14 @@
// Copyright (c) 2025 shibedrill
// SPDX-License-Identifier: MIT
use crate::arch::x86_64::gdt::SELECTORS;
use crate::{LOGGER, format, log_info, log_trace};
use crate::{LogLevel, log_error};
use lazy_static::lazy_static;
use x86_64::PhysAddr;
use x86_64::structures::idt::*;
#[allow(unused)]
pub fn get_lapic_addr() -> PhysAddr {
let apic_base = x86_64::registers::model_specific::ApicBase::read();
let addr: PhysAddr = apic_base.0.start_address();
@ -20,9 +22,11 @@ lazy_static! {
// 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.
idt.double_fault.set_handler_fn(double_fault);
idt.page_fault.set_handler_fn(page_fault);
idt.general_protection_fault.set_handler_fn(gen_prot_fault);
unsafe {
idt.double_fault.set_handler_fn(double_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).set_privilege_level(x86_64::PrivilegeLevel::Ring0);
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
};
}

View File

@ -1,7 +1,7 @@
// Copyright (c) 2025 shibedrill
// SPDX-License-Identifier: MIT
use crate::{SERIAL_3F8, log::*};
use crate::log::*;
use crate::{format, log_error, memory::alloc::string::String};
pub fn double_fault(info: String) -> ! {
@ -13,6 +13,5 @@ pub fn page_fault_fatal(addr: usize, info: String) -> ! {
}
pub fn gen_prot_fault(info: String) {
SERIAL_3F8.lock().log_writeln("Ohhhhh shit double fault");
log_error!("General protection fault: {}", info);
}

View File

@ -31,26 +31,18 @@ use limine::firmware::{
FIRMWARE_TYPE_EFI32, FIRMWARE_TYPE_EFI64, FIRMWARE_TYPE_SBI, FIRMWARE_TYPE_X86BIOS,
};
use spin::mutex::Mutex;
use x86_64::{
VirtAddr,
registers::rflags::RFlags,
structures::{
idt::InterruptStackFrameValue,
paging::{PageTableFlags, page_table::PageTableEntry},
},
};
use x86_64::{VirtAddr, registers::rflags::RFlags, structures::idt::InterruptStackFrameValue};
use crate::{
arch::{
asm::{self, ltr, str},
asm::ltr,
x86_64::{
cpuid::{CPUID, virt_supported},
gdt::{SELECTORS, dump_gdt},
interrupts::get_lapic_addr,
gdt::SELECTORS,
},
},
boot::modules::MODULE_RESPONSE,
memory::paging::{self, active_root_table, map_page, phys_to_virt},
memory::paging::active_root_table,
};
lazy_static! {
@ -95,19 +87,11 @@ unsafe extern "C" fn main() -> ! {
// Initialize all statics so the bootloader memory can be reclaimed
memory::init_statics();
log_info!(
"Long mode: {}",
if asm::long_mode() {
"enabled"
} else {
"disabled"
}
);
// Ensure IDT exists
IDT.load();
log_info!("IDT loaded!");
SELECTORS.gdt.load();
log_info!("GDT loaded!");
IDT.load();
log_info!("IDT loaded!");
log_info!(
"Kernel cmdline: {}",
@ -205,23 +189,12 @@ unsafe extern "C" fn main() -> ! {
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();
}
//let loglevel = LOGGER.lock().level;
//if loglevel <= LogLevel::Trace {
// paging::walk_tables();
//}
}
dump_gdt();
let lapic = get_lapic_addr();
let mapping = {
let mut m = PageTableEntry::new();
m.set_addr(lapic, PageTableFlags::PRESENT);
m
};
let res = map_page(phys_to_virt(lapic), mapping);
log_info!("Map status: {:?}", res);
if let Some(modules_list) = *MODULE_RESPONSE
&& modules_list.modules()[0].path().ends_with("/userboot.bin")
{
@ -232,23 +205,6 @@ unsafe extern "C" fn main() -> ! {
let start_addr = VirtAddr::from_ptr(usermode_fn as *const fn());
log_info!("Start address: 0x{:x}", start_addr);
// This does not work :/
/*unsafe {
InterruptStackFrameValue::new(
start_addr,
GDT_SELECTOR_USER_CODE,
RFlags::empty(),
phys_to_virt(PhysAddr::new(0x1000)),
GDT_SELECTOR_USER_DATA,
)
.iretq()
};*/
log_trace!("Segment offsets:");
log_trace!("GDT_SELECTOR_USER_CODE: {}", SELECTORS.sel_user_code.0);
log_trace!("GDT_SELECTOR_USER_DATA: {}", SELECTORS.sel_user_stack.0);
log_trace!("GDT_SELECTOR_KERNEL_CODE: {}", SELECTORS.sel_kernel_code.0);
log_trace!("GDT_SELECTOR_KERNEL_DATA: {}", SELECTORS.sel_kernel_stack.0);
log_trace!("GDT_SELECTOR_TSS: {}", SELECTORS.sel_tss.0);
x86_64::registers::model_specific::Star::write(
SELECTORS.sel_user_code,
SELECTORS.sel_user_stack,
@ -256,9 +212,7 @@ unsafe extern "C" fn main() -> ! {
SELECTORS.sel_kernel_stack,
)
.expect("fuck");
log_trace!("STR before loading new TSS: {}", str());
ltr(SELECTORS.sel_tss.0);
log_trace!("STR after loading new TSS: {}", str());
ltr(SELECTORS.sel_tss.index());
unsafe {
InterruptStackFrameValue::new(
VirtAddr::from_ptr(usermode_fn as *const fn()),

View File

@ -115,6 +115,7 @@ pub unsafe fn active_root_table() -> (&'static mut PageTable, usize) {
)
}
#[allow(unused)]
pub fn walk_tables() {
iter_table(
match control::Cr4::read().contains(Cr4Flags::L5_PAGING) {