Skip to content

Commit

Permalink
Arch: Impl loading logic for idt
Browse files Browse the repository at this point in the history
  • Loading branch information
corigan01 committed Jan 8, 2025
1 parent 5aef433 commit f1dcbcc
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 16 deletions.
62 changes: 46 additions & 16 deletions crates/arch/src/idt64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use crate::{
registers::{cr2, Segment},
CpuPrivilege,
};
pub use arch_macro::interrupt;

#[derive(Clone, Copy, Debug)]
pub enum GateKind {
Expand All @@ -51,6 +52,26 @@ impl InterruptDescTable {
pub const fn attach_raw(&mut self, irq: u8, gate: GateDescriptor) {
self.0[irq as usize] = gate;
}

pub fn submit_table(&'static self) -> IdtPointer {
IdtPointer {
limit: 255,
offset: self.0.as_ptr() as u64,
}
}
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct IdtPointer {
limit: u16,
offset: u64,
}

impl IdtPointer {
pub unsafe fn load(self) {
unsafe { core::arch::asm!("lidt [{}]", in(reg) &self) }
}
}

#[make_hw(
Expand Down Expand Up @@ -223,7 +244,7 @@ pub enum InterruptFlags {
Irq(u8),
}

#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ExceptionKind {
Interrupt,
Fault,
Expand Down Expand Up @@ -264,7 +285,7 @@ impl InterruptFlags {
}
}

fn convert_from_interrupt(irq_id: u8, frame: &InterruptFrame, error: u64) -> Self {
fn convert_from_interrupt(irq_id: u8, error: u64) -> Self {
match irq_id {
0 => Self::DivisionError,
1 => Self::Debug,
Expand Down Expand Up @@ -328,14 +349,14 @@ impl InterruptInfo {
pub fn convert_from_ne(irq_id: u8, frame: InterruptFrame) -> Self {
Self {
frame,
flags: InterruptFlags::convert_from_interrupt(irq_id, &frame, 0),
flags: InterruptFlags::convert_from_interrupt(irq_id, 0),
}
}

pub fn convert_from_e(irq_id: u8, frame: InterruptFrame, error: u64) -> Self {
Self {
frame,
flags: InterruptFlags::convert_from_interrupt(irq_id, &frame, error),
flags: InterruptFlags::convert_from_interrupt(irq_id, error),
}
}
}
Expand All @@ -345,34 +366,43 @@ macro_rules! attach_irq {
($idt: ident, $irq: ident) => {{
for (irq_num, handler_ptr) in $irq::IRQ_FUNCTION_E_PTRS {
// FIXME: We need to allow the caller to define what these should be
let mut gate = GateDescriptor::zero();
let mut gate = ::arch::idt64::GateDescriptor::zero();
gate.set_offset(handler_ptr as u64);
gate.set_code_segment(Segment::new(1, CpuPrivilege::Ring0));
gate.set_privilege(CpuPrivilege::Ring0);
gate.set_gate_kind(GateKind::InterruptGate);
gate.set_code_segment(::arch::registers::Segment::new(
1,
::arch::CpuPrivilege::Ring0,
));
gate.set_privilege(::arch::CpuPrivilege::Ring0);
gate.set_gate_kind(::arch::idt64::GateKind::InterruptGate);
gate.set_present_flag(true);

$idt.attach_raw(irq_num, gate);
}

for (irq_num, handler_ptr) in $irq::IRQ_FUNCTION_NE_PTRS {
// FIXME: We need to allow the caller to define what these should be
let mut gate = GateDescriptor::zero();
let mut gate = ::arch::idt64::GateDescriptor::zero();
gate.set_offset(handler_ptr as u64);
gate.set_code_segment(Segment::new(1, CpuPrivilege::Ring0));
gate.set_privilege(CpuPrivilege::Ring0);
gate.set_gate_kind(GateKind::InterruptGate);
gate.set_code_segment(::arch::registers::Segment::new(
1,
::arch::CpuPrivilege::Ring0,
));
gate.set_privilege(::arch::CpuPrivilege::Ring0);
gate.set_gate_kind(::arch::idt64::GateKind::InterruptGate);
gate.set_present_flag(true);

$idt.attach_raw(irq_num, gate);
}

for (irq_num, handler_ptr) in $irq::IRQ_FUNCTION_RESERVED_PTRS {
let mut gate = GateDescriptor::zero();
let mut gate = ::arch::idt64::GateDescriptor::zero();
gate.set_offset(handler_ptr as u64);
gate.set_code_segment(Segment::new(1, CpuPrivilege::Ring0));
gate.set_privilege(CpuPrivilege::Ring0);
gate.set_gate_kind(GateKind::InterruptGate);
gate.set_code_segment(::arch::registers::Segment::new(
1,
::arch::CpuPrivilege::Ring0,
));
gate.set_privilege(::arch::CpuPrivilege::Ring0);
gate.set_gate_kind(::arch::idt64::GateKind::InterruptGate);
gate.set_present_flag(true);

$idt.attach_raw(irq_num, gate);
Expand Down
1 change: 1 addition & 0 deletions kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ lldebug = { workspace = true }
serial = { workspace = true }
util = {workspace = true}
mem = {workspace = true}
arch = {workspace = true}
19 changes: 19 additions & 0 deletions kernel/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,14 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
#![no_std]
#![no_main]
#![feature(sync_unsafe_cell)]
#![feature(abi_x86_interrupt)]

mod panic;

use arch::{
attach_irq,
idt64::{ExceptionKind, InterruptDescTable, InterruptInfo, interrupt},
};
use bootloader::KernelBootHeader;
use lldebug::{debug_ready, logln, make_debug};
use serial::{Serial, baud::SerialBaud};
Expand All @@ -45,11 +50,25 @@ extern "C" fn _start(kbh: u64) -> ! {
panic!("Main should not return");
}

#[interrupt(0..256)]
fn main_handler(args: InterruptInfo) {
logln!("Handler == {:#?}", args);

if args.flags.exception_kind() == ExceptionKind::Abort {
panic!("Interrupt -- {:?}", args.flags);
}
}

#[debug_ready]
fn main(kbh: &KernelBootHeader) {
logln!("Welcome to the Quantum Kernel!");
logln!(
"Free Memory : {}",
HumanBytes::from(kbh.phys_mem_map.bytes_of(mem::phys::PhysMemoryKind::Free))
);

let mut idt = InterruptDescTable::new();
attach_irq!(idt, main_handler);

logln!("Attached Interrupts!");
}

0 comments on commit f1dcbcc

Please sign in to comment.