From 78ed9468fb817ffa225b8af3cfdd124c8e37d320 Mon Sep 17 00:00:00 2001 From: natrixaeria Date: Tue, 19 Nov 2019 19:16:09 +0100 Subject: Fix apic register address and ordering --- kernel/src/interrupts/apic.rs | 45 +++++++++++++++++++++++++++++++++---------- kernel/src/interrupts/idt.rs | 2 +- kernel/src/interrupts/mod.rs | 3 ++- kernel/src/main.rs | 11 ++++++++++- 4 files changed, 48 insertions(+), 13 deletions(-) diff --git a/kernel/src/interrupts/apic.rs b/kernel/src/interrupts/apic.rs index 3d42ba9..dc1177b 100644 --- a/kernel/src/interrupts/apic.rs +++ b/kernel/src/interrupts/apic.rs @@ -84,7 +84,8 @@ pub enum TimerDivideConfig { static mut LOCAL_APIC: Option = None; pub unsafe fn set_local_apic(apic: Apic) -> &'static mut Apic { - LOCAL_APIC.get_or_insert(apic) + LOCAL_APIC = Some(apic); + LOCAL_APIC.as_mut().unwrap() } pub unsafe fn get_local_apic() -> Option<&'static mut Apic> { @@ -100,18 +101,27 @@ impl Apic { if !is_apic() { return None; } Self::disable_pic(); let mut base_apic = unsafe { Msr::new(APIC_BASE_MSR).read() }; + //panic!("msr{:x}", base_apic); + unsafe { Msr::new(APIC_BASE_MSR).write(base_apic) }; let mut apic = Self::from_base_apic(base_apic); + //panic!("msr{:08x}", apic.regs as usize); - let spurious = apic.get(ApicRegister::SpuriousInterruptVec) | 0x1ff; + // let spurious = apic.get(ApicRegister::SpuriousInterruptVec) | 0x1ff; - unsafe { Msr::new(APIC_BASE_MSR).write(base_apic | APIC_FLAG) }; - - apic.set(ApicRegister::SpuriousInterruptVec, spurious); + apic.set(ApicRegister::LogicalDst, 0); apic.set(ApicRegister::TaskPriority, 0); + apic.set(ApicRegister::LvtTimer, APIC_DISABLE); apic.set(ApicRegister::LvtPerformanceMonitor, APIC_NMI); apic.set(ApicRegister::LvtLint0, APIC_DISABLE); apic.set(ApicRegister::LvtLint1, APIC_DISABLE); + apic.set(ApicRegister::DstFmt, 0x0FFFFFFF); + apic.set(ApicRegister::LvtError, super::InterruptType::ApicError.as_u8().into()); + apic.set(ApicRegister::ErrorStatus, 0); + + unsafe { Msr::new(APIC_BASE_MSR).write(base_apic | APIC_FLAG) }; + + apic.set(ApicRegister::SpuriousInterruptVec, 0x1ff); Some(apic) } @@ -129,16 +139,18 @@ impl Apic { } } - fn ptr(&self) -> *const u32 { self.regs as *const u32 } + pub fn ptr(&self) -> *const u32 { self.regs as *const u32 } fn ptr_mut(&mut self) -> *mut u32 { self.regs as *mut u32 } pub fn get(&self, register: ApicRegister) -> u32 { - unsafe { self.ptr().offset(register as isize).read_volatile() } + unsafe { ((self.ptr() as usize + (register as usize) * 4) as *const u32).read_volatile() } + //unsafe { self.ptr().offset(register as isize).read_volatile() } } pub fn set(&mut self, register: ApicRegister, val: u32) { - unsafe { self.ptr_mut().offset(register as isize).write_volatile(val) } + unsafe { ((self.ptr() as usize + (register as usize) * 4) as *mut u32).write_volatile(val) } + //unsafe { self.ptr_mut().offset(register as isize).write_volatile(val) } } pub fn set_interrupt_command(&mut self, dst: u8, v: u8) { @@ -152,8 +164,21 @@ impl Apic { } pub fn set_timer_interrupt_handler(&mut self, divide: TimerDivideConfig, intr: super::InterruptType) { - self.set(ApicRegister::LvtTimer, intr.as_u8().into()); + self.set(ApicRegister::LvtTimer, intr.as_u8() as u32 | (1 << 17)); self.set(ApicRegister::TimerDivideConfig, divide as u32); - self.set(ApicRegister::TimerInitialCount, 0xFFFFFFFF) + self.set(ApicRegister::TimerInitialCount, 2048); + self.set(ApicRegister::TimerCurrentCount, 2048) + } + + pub fn get_timer_value(&self) -> u32 { + self.get(ApicRegister::TimerCurrentCount) + } + + pub fn get_error_code(&self) -> u32 { + self.get(ApicRegister::ErrorStatus) + } + + pub fn get_id(&self) -> u32 { + self.get(ApicRegister::ApicId) } } diff --git a/kernel/src/interrupts/idt.rs b/kernel/src/interrupts/idt.rs index 3eb9724..e41f957 100644 --- a/kernel/src/interrupts/idt.rs +++ b/kernel/src/interrupts/idt.rs @@ -5,7 +5,7 @@ use x86_64::structures::idt::InterruptDescriptorTable; lazy_static! { static ref IDT: InterruptDescriptorTable = { let mut idt = InterruptDescriptorTable::new(); - for i in 32..255 { + for i in 32..256 { idt[i].set_handler_fn(dummy_handler); } diff --git a/kernel/src/interrupts/mod.rs b/kernel/src/interrupts/mod.rs index 27993ec..6a92c3f 100644 --- a/kernel/src/interrupts/mod.rs +++ b/kernel/src/interrupts/mod.rs @@ -31,7 +31,8 @@ pub enum InterruptType { Virtualization, Security, Timer = INT_OFFSET, - Keyboard = INT_OFFSET + 1, + Keyboard, + ApicError, None = 255, } diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 2116838..a0e1e56 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -23,13 +23,22 @@ extern "C" fn _start() -> ! { let apic = interrupts::apic::Apic::new().expect("no APIC support"); let mut apic = unsafe { interrupts::apic::set_local_apic(apic) }; - apic.set_timer_interrupt_handler(interrupts::apic::TimerDivideConfig::Div32, interrupts::InterruptType::Timer); + apic.set_timer_interrupt_handler(interrupts::apic::TimerDivideConfig::Div16, interrupts::InterruptType::Timer); x86_64::instructions::interrupts::enable(); let mut stdout = OStream::new(); stdout.print(b"apic initialisation complete\n"); + loop { + stdout.set_col(0); + use core::fmt::Write; + //let n = apic.get_timer_value(); + let n = apic.get_error_code(); + write!(&mut stdout, "timer: {} ", n); + //write!(&mut stdout, "timer: {:08x} ", apic.ptr() as usize); + } + if cfg!(test) { qemu::exit_qemu(qemu::QemuExitCode::Success); } -- cgit v1.2.3