continuing work on interrupts - PIC doesn't work, probably switching to APIC
This commit is contained in:
+3
-2
@@ -1,5 +1,5 @@
|
||||
# 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.
|
||||
/GoofyAhhOS
|
||||
@@ -7,4 +7,5 @@ timeout: 5
|
||||
protocol: limine
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ spin = { version = "0.9.8", features = ["lazy"] }
|
||||
bitflags = { version = "2.4.0", default-features = false }
|
||||
lazy_static = { version = "1.5.0", features = ["spin_no_std"] }
|
||||
x86_64 = { version = "0.15.1" }
|
||||
pic8259 = "0.11.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ pub use sys::kernel::drivers::serial::{
|
||||
};
|
||||
|
||||
pub fn init() {
|
||||
sys::kernel::cpu::interrupts::init();
|
||||
sys::kernel::cpu::init();
|
||||
}
|
||||
|
||||
pub fn hcf() -> ! {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,15 +4,20 @@ use lazy_static::lazy_static;
|
||||
use spin::lazy;
|
||||
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_2_OFFSET: u8 = PIC_1_OFFSET + 8;
|
||||
|
||||
pub static PICS: spin::Mutex<ChainedPics> =
|
||||
spin::Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) });
|
||||
pub static PICS: spin::Mutex<ChainedPics> = spin::Mutex::new(
|
||||
unsafe {
|
||||
ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET)
|
||||
}
|
||||
);
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(u8)]
|
||||
@@ -34,22 +39,35 @@ lazy_static! {
|
||||
static ref IDT: InterruptDescriptorTable = {
|
||||
let mut idt = InterruptDescriptorTable::new();
|
||||
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
|
||||
};
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
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 {
|
||||
asm!("cli", options(nomem, nostack, preserves_flags));
|
||||
func();
|
||||
asm!("sti", options(nomem, nostack, preserves_flags));
|
||||
PICS.lock().notify_end_of_interrupt(InterruptIndex::Timer.as_u8());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,11 +81,8 @@ extern "x86-interrupt" fn double_fault_handler(stack_frame: InterruptStackFrame,
|
||||
panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame)
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn clock_handler(stack_frame: InterruptStackFrame) {
|
||||
println_log!("EXCEPTION: CLOCK\n{:#?}", stack_frame);
|
||||
serial_println!("EXCEPTION: CLOCK\n{:#?}", stack_frame);
|
||||
|
||||
unsafe {
|
||||
PICS.lock().notify_end_of_interrupt(InterruptIndex::Timer.as_u8());
|
||||
}
|
||||
pub fn disable(func: impl Fn()) {
|
||||
x86_64::instructions::interrupts::disable();
|
||||
func();
|
||||
x86_64::instructions::interrupts::enable();
|
||||
}
|
||||
@@ -1,4 +1,9 @@
|
||||
pub mod interrupts;
|
||||
pub mod gdt;
|
||||
|
||||
mod pics;
|
||||
|
||||
pub use interrupts::*;
|
||||
pub fn init() {
|
||||
gdt::init();
|
||||
interrupts::init();
|
||||
}
|
||||
+21
-22
@@ -127,7 +127,8 @@ if [ $is_test -eq 1 ]; then
|
||||
serial_flags="-serial stdio"
|
||||
else
|
||||
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
|
||||
|
||||
# Run in QEMU
|
||||
@@ -139,7 +140,25 @@ else
|
||||
info "Running OS in QEMU..."
|
||||
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"
|
||||
qemu-system-x86_64 -M q35 \
|
||||
@@ -152,23 +171,3 @@ qemu-system-x86_64 -M q35 \
|
||||
${test_flags} \
|
||||
${debug_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
|
||||
|
||||
Reference in New Issue
Block a user