diff options
-rw-r--r-- | src/apic/x2apic.rs | 18 | ||||
-rw-r--r-- | src/apic/xapic.rs | 74 |
2 files changed, 86 insertions, 6 deletions
diff --git a/src/apic/x2apic.rs b/src/apic/x2apic.rs index e38fe9f..ceb8aad 100644 --- a/src/apic/x2apic.rs +++ b/src/apic/x2apic.rs @@ -4,7 +4,8 @@ use bit_field::BitField; use super::{ApicControl, ApicId, Icr}; use crate::msr::{ rdmsr, wrmsr, IA32_APIC_BASE, IA32_TSC_DEADLINE, IA32_X2APIC_APICID, IA32_X2APIC_ESR, - IA32_X2APIC_LVT_LINT0, IA32_X2APIC_LVT_TIMER, IA32_X2APIC_SELF_IPI, IA32_X2APIC_VERSION, + IA32_X2APIC_LVT_LINT0, IA32_X2APIC_LVT_TIMER, IA32_X2APIC_SELF_IPI, IA32_X2APIC_SIVR, + IA32_X2APIC_VERSION, }; /// Represents an x2APIC driver instance. @@ -28,11 +29,16 @@ impl X2APIC { pub fn attach(&mut self) { // Enable unsafe { + // Enable x2APIC mode globally self.base = rdmsr(IA32_APIC_BASE); self.base.set_bit(10, true); // Enable x2APIC self.base.set_bit(11, true); // Enable xAPIC wrmsr(IA32_APIC_BASE, self.base); + // Enable this XAPIC (set bit 8, spurious IRQ vector 15) + let svr: u64 = 1 << 8 | 15; + wrmsr(IA32_X2APIC_SIVR, svr); + //TODO: let mut lint0 = rdmsr(IA32_X2APIC_LVT_LINT0); // TODO: Fix magic number let lint0 = 1 << 16 | (1 << 15) | (0b111 << 8) | 0x20; @@ -79,8 +85,14 @@ impl ApicControl for X2APIC { fn tsc_enable(&mut self, vector: u8) { unsafe { let mut lvt: u64 = rdmsr(IA32_X2APIC_LVT_TIMER); - lvt &= !(1 << 17); - lvt |= 1 << 18; + // Set vector + lvt &= !0xff; + lvt |= vector as u64; + // Unmask timer IRQ + lvt.set_bit(16, false); + // Enable TSC deadline mode + lvt.set_bit(17, false); + lvt.set_bit(18, false); wrmsr(IA32_X2APIC_LVT_TIMER, lvt); } } diff --git a/src/apic/xapic.rs b/src/apic/xapic.rs index 4b85580..51dc27f 100644 --- a/src/apic/xapic.rs +++ b/src/apic/xapic.rs @@ -3,6 +3,7 @@ //! Table 10-1 Local APIC Register Address Map //! the MMIO base values are found in this file. +use core::fmt; use core::intrinsics::{volatile_load, volatile_store}; use bit_field::BitField; @@ -192,7 +193,6 @@ enum ApicRegister { } /// State for the XAPIC driver. -#[derive(Debug)] pub struct XAPIC { /// Reference to the xAPCI region mmio_region: &'static mut [u32], @@ -200,6 +200,69 @@ pub struct XAPIC { base: u64, } +impl fmt::Debug for XAPIC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("XAPIC") + .field("XAPIC_ID", &self.read(ApicRegister::XAPIC_ID)) + .field("XAPIC_VERSION", &self.read(ApicRegister::XAPIC_VERSION)) + .field("XAPIC_TPR", &self.read(ApicRegister::XAPIC_TPR)) + .field("XAPIC_PPR", &self.read(ApicRegister::XAPIC_PPR)) + .field("XAPIC_EOI", &self.read(ApicRegister::XAPIC_EOI)) + .field("XAPIC_LDR", &self.read(ApicRegister::XAPIC_LDR)) + .field("XAPIC_SVR", &self.read(ApicRegister::XAPIC_SVR)) + .field("XAPIC_ISR0", &self.read(ApicRegister::XAPIC_ISR0)) + .field("XAPIC_ISR1", &self.read(ApicRegister::XAPIC_ISR1)) + .field("XAPIC_ISR2", &self.read(ApicRegister::XAPIC_ISR2)) + .field("XAPIC_ISR3", &self.read(ApicRegister::XAPIC_ISR3)) + .field("XAPIC_ISR4", &self.read(ApicRegister::XAPIC_ISR4)) + .field("XAPIC_ISR5", &self.read(ApicRegister::XAPIC_ISR5)) + .field("XAPIC_ISR6", &self.read(ApicRegister::XAPIC_ISR6)) + .field("XAPIC_ISR7", &self.read(ApicRegister::XAPIC_ISR7)) + .field("XAPIC_TMR0", &self.read(ApicRegister::XAPIC_TMR0)) + .field("XAPIC_TMR1", &self.read(ApicRegister::XAPIC_TMR1)) + .field("XAPIC_TMR2", &self.read(ApicRegister::XAPIC_TMR2)) + .field("XAPIC_TMR3", &self.read(ApicRegister::XAPIC_TMR3)) + .field("XAPIC_TMR4", &self.read(ApicRegister::XAPIC_TMR4)) + .field("XAPIC_TMR5", &self.read(ApicRegister::XAPIC_TMR5)) + .field("XAPIC_TMR6", &self.read(ApicRegister::XAPIC_TMR6)) + .field("XAPIC_TMR7", &self.read(ApicRegister::XAPIC_TMR7)) + .field("XAPIC_IRR0", &self.read(ApicRegister::XAPIC_IRR0)) + .field("XAPIC_IRR1", &self.read(ApicRegister::XAPIC_IRR1)) + .field("XAPIC_IRR2", &self.read(ApicRegister::XAPIC_IRR2)) + .field("XAPIC_IRR3", &self.read(ApicRegister::XAPIC_IRR3)) + .field("XAPIC_IRR4", &self.read(ApicRegister::XAPIC_IRR4)) + .field("XAPIC_IRR5", &self.read(ApicRegister::XAPIC_IRR5)) + .field("XAPIC_IRR6", &self.read(ApicRegister::XAPIC_IRR6)) + .field("XAPIC_IRR7", &self.read(ApicRegister::XAPIC_IRR7)) + .field("XAPIC_ESR", &self.read(ApicRegister::XAPIC_ESR)) + .field("XAPIC_LVT_CMCI", &self.read(ApicRegister::XAPIC_LVT_CMCI)) + .field("XAPIC_ICR0", &self.read(ApicRegister::XAPIC_ICR0)) + .field("XAPIC_ICR1", &self.read(ApicRegister::XAPIC_ICR1)) + .field("XAPIC_LVT_TIMER", &self.read(ApicRegister::XAPIC_LVT_TIMER)) + .field( + "XAPIC_LVT_THERMAL", + &self.read(ApicRegister::XAPIC_LVT_THERMAL), + ) + .field("XAPIC_LVT_PMI", &self.read(ApicRegister::XAPIC_LVT_PMI)) + .field("XAPIC_LVT_LINT0", &self.read(ApicRegister::XAPIC_LVT_LINT0)) + .field("XAPIC_LVT_LINT1", &self.read(ApicRegister::XAPIC_LVT_LINT1)) + .field("XAPIC_LVT_ERROR", &self.read(ApicRegister::XAPIC_LVT_ERROR)) + .field( + "XAPIC_TIMER_INIT_COUNT", + &self.read(ApicRegister::XAPIC_TIMER_INIT_COUNT), + ) + .field( + "XAPIC_TIMER_CURRENT_COUNT", + &self.read(ApicRegister::XAPIC_TIMER_CURRENT_COUNT), + ) + .field( + "XAPIC_TIMER_DIV_CONF", + &self.read(ApicRegister::XAPIC_TIMER_DIV_CONF), + ) + .finish() + } +} + impl XAPIC { /// Create a new xAPIC object for the local CPU. /// @@ -218,9 +281,14 @@ impl XAPIC { pub fn attach(&mut self) { // Enable unsafe { + // Enable xAPIC globally self.base = rdmsr(IA32_APIC_BASE); - self.base.set_bit(11, true); // Enable xAPIC + self.base.set_bit(11, true); wrmsr(IA32_APIC_BASE, self.base); + + // Enable this XAPIC (set bit 8, spurious IRQ vector 15) + let svr: u32 = 1 << 8 | 15; + self.write(ApicRegister::XAPIC_SVR, svr); } } @@ -274,7 +342,7 @@ impl ApicControl for XAPIC { let mut lvt: u32 = self.read(ApicRegister::XAPIC_LVT_TIMER); lvt &= !0xff; lvt |= vector as u32; - + lvt.set_bit(16, false); lvt.set_bit(17, false); lvt.set_bit(18, true); |