From cc714be94e75de9b8d0462869d2ba968cfe23fb8 Mon Sep 17 00:00:00 2001 From: Erin Date: Thu, 8 Dec 2022 20:15:10 +0100 Subject: [PATCH] Moved away from PIC to APIC. --- Cargo.lock | 39 ++++++++++++++---- kernel/Cargo.toml | 2 +- .../src/arch/x86_64/{idt.rs => interrupts.rs} | 40 +++++++++++++------ kernel/src/arch/x86_64/memory.rs | 3 ++ kernel/src/arch/x86_64/mod.rs | 4 +- kernel/src/lib.rs | 2 +- 6 files changed, 67 insertions(+), 23 deletions(-) rename kernel/src/arch/x86_64/{idt.rs => interrupts.rs} (51%) diff --git a/Cargo.lock b/Cargo.lock index c9f9698cc..810c4a109 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -122,6 +122,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b645c5c09a7d4035949cfce1a915785aaad6f17800c35fda8a8c311c491f284" + [[package]] name = "bit_field" version = "0.10.1" @@ -369,11 +375,11 @@ dependencies = [ "limine", "linked_list_allocator", "log", - "pic8259", "slab", "spin", "uart_16550", "versioning", + "x2apic", "x86_64", ] @@ -497,13 +503,10 @@ dependencies = [ ] [[package]] -name = "pic8259" -version = "0.10.2" +name = "paste" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ec21f514e2e16e94649f1d041ca4a7069b512c037ac156360652a775e6229d" -dependencies = [ - "x86_64", -] +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] name = "pin-project-lite" @@ -596,6 +599,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "raw-cpuid" +version = "10.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6823ea29436221176fe662da99998ad3b4db2c7f31e7b6f5fe43adccd6320bb" +dependencies = [ + "bitflags", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -995,6 +1007,19 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +[[package]] +name = "x2apic" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b6a3e030cfc71d614954e1de6dcb09e40bf1437f620c27b4526f978bee912e" +dependencies = [ + "bit", + "bitflags", + "paste", + "raw-cpuid", + "x86_64", +] + [[package]] name = "x86_64" version = "0.14.10" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 830ba1543..00afab0f3 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -17,6 +17,6 @@ features = ["alloc"] [target.'cfg(target_arch = "x86_64")'.dependencies] limine = "0.1" -pic8259 = "0.10" uart_16550 = "0.2" x86_64 = "0.14" +x2apic = "0.4" diff --git a/kernel/src/arch/x86_64/idt.rs b/kernel/src/arch/x86_64/interrupts.rs similarity index 51% rename from kernel/src/arch/x86_64/idt.rs rename to kernel/src/arch/x86_64/interrupts.rs index 6eeb358fe..ee7c2d274 100644 --- a/kernel/src/arch/x86_64/idt.rs +++ b/kernel/src/arch/x86_64/interrupts.rs @@ -1,25 +1,36 @@ -use pic8259::ChainedPics; use spin::{Lazy, Mutex}; +use x2apic::lapic::{LocalApic, LocalApicBuilder}; use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode}; -pub const PIC_1_OFFSET: u8 = 32; -pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8; - -static PICS: Mutex = - Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) }); - pub unsafe fn init() { log::info!("Initialising IDT"); IDT.load(); - PICS.lock().initialize(); + Lazy::force(&LAPIC); x86_64::instructions::interrupts::enable(); } #[repr(u8)] enum Interrupt { - Timer = PIC_1_OFFSET, + Timer = 32, + ApicErr = u8::MAX - 1, + Spurious = u8::MAX, } +static LAPIC: Lazy> = Lazy::new(|| { + let mut lapic = LocalApicBuilder::new() + .timer_vector(Interrupt::Timer as usize) + .error_vector(Interrupt::ApicErr as usize) + .spurious_vector(Interrupt::Spurious as usize) + .set_xapic_base( + unsafe { x2apic::lapic::xapic_base() } + + super::memory::HHDM_OFFSET.load(core::sync::atomic::Ordering::Relaxed), + ) + .build() + .expect("failed to setup Local APIC"); + unsafe { lapic.enable() }; + Mutex::new(lapic) +}); + static IDT: Lazy = Lazy::new(|| { let mut idt = InterruptDescriptorTable::new(); unsafe { @@ -44,9 +55,14 @@ extern "x86-interrupt" fn page_fault( } extern "x86-interrupt" fn timer(_: InterruptStackFrame) { - unsafe { eoi(Interrupt::Timer as u8) }; + panic!("make timer not double fault"); + unsafe { LAPIC.lock().end_of_interrupt() }; } -unsafe fn eoi(i: u8) { - PICS.lock().notify_end_of_interrupt(i); +extern "x86-interrupt" fn apic_err(_: InterruptStackFrame) { + panic!("Internal APIC error"); +} + +extern "x86-interrupt" fn spurious(_: InterruptStackFrame) { + unsafe { LAPIC.lock().end_of_interrupt() }; } diff --git a/kernel/src/arch/x86_64/memory.rs b/kernel/src/arch/x86_64/memory.rs index f33e76170..c85c189f4 100644 --- a/kernel/src/arch/x86_64/memory.rs +++ b/kernel/src/arch/x86_64/memory.rs @@ -1,3 +1,4 @@ +use core::sync::atomic::AtomicU64; use limine::{LimineMemmapEntry, LimineMemoryMapEntryType}; use spin::{Mutex, Once}; use x86_64::{ @@ -7,10 +8,12 @@ use x86_64::{ pub static PAGE_TABLE: Once> = Once::new(); pub static FRAME_ALLOC: Once> = Once::new(); +pub static HHDM_OFFSET: AtomicU64 = AtomicU64::new(0); /// Initialise page table pub unsafe fn init_pt(phys_base: VirtAddr) { log::info!("Retrieving page table"); + HHDM_OFFSET.store(phys_base.as_u64(), core::sync::atomic::Ordering::Relaxed); PAGE_TABLE.call_once(|| { Mutex::new(OffsetPageTable::new( &mut *((phys_base diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index 921aa25ec..b5a6cce2c 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -5,7 +5,7 @@ use x86_64::VirtAddr; mod allocator; mod gdt; -mod idt; +mod interrupts; mod memory; static SERIAL_CONSOLE: Mutex = Mutex::new(unsafe { SerialPort::new(0x3f8) }); @@ -37,7 +37,7 @@ unsafe extern "C" fn _kernel_start() -> ! { allocator::init_alloc().expect("tried to initialise allocator"); gdt::init(); - idt::init(); + interrupts::init(); crate::kmain::kmain() } diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index e83f6333b..cb20735a5 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -34,7 +34,7 @@ fn panic(info: &core::panic::PanicInfo) -> ! { if let Some(loc) = info.location() { let _ = crate::arch::serial_fmt(format_args!( - "Location: {} : {} / {}\r\n", + "Location: {}: {}, {}\r\n", loc.file(), loc.line(), loc.column()