continuing work on interrupts - PIC doesn't work, probably switching to APIC

This commit is contained in:
FantasyPvP
2024-11-19 01:03:59 +00:00
parent 4c157ab05e
commit a4b0662983
7 changed files with 118 additions and 43 deletions
+3 -2
View File
@@ -1,5 +1,5 @@
# Timeout in seconds that Limine will use before automatically booting. # Timeout in seconds that Limine will use before automatically booting.
timeout: 5 timeout: 1
# The entry name that will be displayed in the boot menu. # The entry name that will be displayed in the boot menu.
/GoofyAhhOS /GoofyAhhOS
@@ -7,4 +7,5 @@ timeout: 5
protocol: limine protocol: limine
# Path to the kernel to boot. boot():/ represents the partition on which limine.conf is located. # Path to the kernel to boot. boot():/ represents the partition on which limine.conf is located.
kernel_path: boot():/boot/kernel kernel_path: boot():/boot/kernel
+1
View File
@@ -9,6 +9,7 @@ spin = { version = "0.9.8", features = ["lazy"] }
bitflags = { version = "2.4.0", default-features = false } bitflags = { version = "2.4.0", default-features = false }
lazy_static = { version = "1.5.0", features = ["spin_no_std"] } lazy_static = { version = "1.5.0", features = ["spin_no_std"] }
x86_64 = { version = "0.15.1" } x86_64 = { version = "0.15.1" }
pic8259 = "0.11.0"
[features] [features]
default = [] default = []
+1 -1
View File
@@ -28,7 +28,7 @@ pub use sys::kernel::drivers::serial::{
}; };
pub fn init() { pub fn init() {
sys::kernel::cpu::interrupts::init(); sys::kernel::cpu::init();
} }
pub fn hcf() -> ! { pub fn hcf() -> ! {
+54
View File
@@ -0,0 +1,54 @@
use x86_64::{
instructions::tables::load_tss, registers::segmentation::{Segment, CS}, structures::{
gdt::{
Descriptor, GlobalDescriptorTable, SegmentSelector
},
tss::TaskStateSegment,
}, VirtAddr
};
use lazy_static::lazy_static;
use crate::println_log;
pub const DOUBLE_FAULT_IST_INDEX: u16 = 0;
lazy_static! {
static ref TSS: TaskStateSegment = {
let mut tss = TaskStateSegment::new();
tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX as usize] = {
const STACK_SIZE: usize = 4096 * 5;
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
let stack_end = stack_start + STACK_SIZE.try_into().unwrap();
stack_end
};
tss
};
}
lazy_static! {
static ref GDT: (GlobalDescriptorTable, Selectors) = {
let mut gdt = GlobalDescriptorTable::new();
let code_selector = gdt.append(Descriptor::kernel_code_segment());
let tss_selector = gdt.append(Descriptor::tss_segment(&TSS));
(gdt, Selectors { code_selector, tss_selector })
};
}
struct Selectors {
code_selector: SegmentSelector,
tss_selector: SegmentSelector
}
pub fn init() {
GDT.0.load();
println_log!("Loaded GDT...");
unsafe {
CS::set_reg(GDT.1.code_selector);
load_tss(GDT.1.tss_selector);
}
}
+32 -17
View File
@@ -4,15 +4,20 @@ use lazy_static::lazy_static;
use spin::lazy; use spin::lazy;
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
use crate::{println_log, serial_println}; use crate::{println_log, serial_println, sys::kernel::cpu::gdt};
use super::pics::ChainedPics; // use super::pics::ChainedPics;
use pic8259::ChainedPics;
pub const PIC_1_OFFSET: u8 = 32; pub const PIC_1_OFFSET: u8 = 32;
pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8; pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8;
pub static PICS: spin::Mutex<ChainedPics> = pub static PICS: spin::Mutex<ChainedPics> = spin::Mutex::new(
spin::Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) }); unsafe {
ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET)
}
);
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
#[repr(u8)] #[repr(u8)]
@@ -34,22 +39,35 @@ lazy_static! {
static ref IDT: InterruptDescriptorTable = { static ref IDT: InterruptDescriptorTable = {
let mut idt = InterruptDescriptorTable::new(); let mut idt = InterruptDescriptorTable::new();
idt.breakpoint.set_handler_fn(breakpoint_handler); idt.breakpoint.set_handler_fn(breakpoint_handler);
idt.double_fault.set_handler_fn(double_fault_handler);
idt[InterruptIndex::Timer.as_u8()].set_handler_fn(clock_handler); unsafe {
idt.double_fault.set_handler_fn(double_fault_handler)
.set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX);
}
idt[InterruptIndex::Timer.as_u8()].set_handler_fn(timer_interrupt_handler);
idt idt
}; };
} }
pub fn init() { pub fn init() {
IDT.load(); IDT.load();
println_log!("Loaded IDT...");
unsafe {
PICS.lock().initialize();
}
x86_64::instructions::interrupts::enable();
println_log!("Enabled interrupts...");
} }
extern "x86-interrupt" fn timer_interrupt_handler(stack_frame: InterruptStackFrame) {
serial_println!("clock");
println_log!("clock");
pub fn disable(func: impl Fn()) {
unsafe { unsafe {
asm!("cli", options(nomem, nostack, preserves_flags)); PICS.lock().notify_end_of_interrupt(InterruptIndex::Timer.as_u8());
func();
asm!("sti", options(nomem, nostack, preserves_flags));
} }
} }
@@ -63,11 +81,8 @@ extern "x86-interrupt" fn double_fault_handler(stack_frame: InterruptStackFrame,
panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame) panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame)
} }
extern "x86-interrupt" fn clock_handler(stack_frame: InterruptStackFrame) { pub fn disable(func: impl Fn()) {
println_log!("EXCEPTION: CLOCK\n{:#?}", stack_frame); x86_64::instructions::interrupts::disable();
serial_println!("EXCEPTION: CLOCK\n{:#?}", stack_frame); func();
x86_64::instructions::interrupts::enable();
unsafe {
PICS.lock().notify_end_of_interrupt(InterruptIndex::Timer.as_u8());
}
} }
+6 -1
View File
@@ -1,4 +1,9 @@
pub mod interrupts; pub mod interrupts;
pub mod gdt;
mod pics; mod pics;
pub use interrupts::*; pub fn init() {
gdt::init();
interrupts::init();
}
+21 -22
View File
@@ -127,7 +127,8 @@ if [ $is_test -eq 1 ]; then
serial_flags="-serial stdio" serial_flags="-serial stdio"
else else
test_flags="" test_flags=""
serial_flags="-serial tcp:127.0.0.1:1234,server,nowait" # serial_flags="-serial tcp:127.0.0.1:1234,server,nowait"
serial_flags="-serial stdio"
fi fi
# Run in QEMU # Run in QEMU
@@ -139,7 +140,25 @@ else
info "Running OS in QEMU..." info "Running OS in QEMU..."
fi fi
echo "test: " $is_test check_test_res() {
qemu_exit_code=$?
if [ $qemu_exit_code -eq 33 ]; then
# Success case (0x10 << 1) | 1 = 33
info "All tests passed"
exit 0
elif [ $qemu_exit_code -eq 35 ]; then
# Failure case (0x11 << 1) | 1 = 35
warning "Some tests failed"
exit 1
else
# Any other exit code is treated as a failure
warning "Some tests failed"
exit 1
fi
}
trap 'check_test_res "tests completed"' ERR
cd "$project_root" cd "$project_root"
qemu-system-x86_64 -M q35 \ qemu-system-x86_64 -M q35 \
@@ -152,23 +171,3 @@ qemu-system-x86_64 -M q35 \
${test_flags} \ ${test_flags} \
${debug_flags} \ ${debug_flags} \
${QEMU_FLAGS:-} ${QEMU_FLAGS:-}
# Get QEMU's exit code
qemu_exit_code=$?
# If this is a test run, translate QEMU exit codes to test exit codes
if [ $is_test -eq 1 ]; then
if [ $qemu_exit_code -eq 33 ]; then
# Success case (0x10 << 1) | 1 = 33
exit 0
elif [ $qemu_exit_code -eq 35 ]; then
# Failure case (0x11 << 1) | 1 = 35
exit 1
else
# Any other exit code is treated as a failure
exit 1
fi
else
# For non-test runs, pass through the exit code
exit $qemu_exit_code
fi