diff options
author | Dennis Kobert <dennis@kobert.dev> | 2019-11-20 03:47:08 +0100 |
---|---|---|
committer | Dennis Kobert <dennis@kobert.dev> | 2019-11-20 03:47:08 +0100 |
commit | 0cb231bd3de9bcd4c39064399211fbd2fbc6237e (patch) | |
tree | c3713274ae1057afdcd6ce1f9af1f96a03503e93 /kernel | |
parent | 78ed9468fb817ffa225b8af3cfdd124c8e37d320 (diff) |
Fix memory mapping for LAIC and setup it's paging
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/src/asm/boot.asm | 12 | ||||
-rw-r--r-- | kernel/src/interrupts/apic.rs | 131 | ||||
-rw-r--r-- | kernel/src/main.rs | 14 |
3 files changed, 85 insertions, 72 deletions
diff --git a/kernel/src/asm/boot.asm b/kernel/src/asm/boot.asm index 6449d66..87de35f 100644 --- a/kernel/src/asm/boot.asm +++ b/kernel/src/asm/boot.asm @@ -92,6 +92,16 @@ setup_page_tables: or eax, 0b11 ; present + writable mov [p3_table], eax + ; map third P3 entry to APIC P2 table + mov eax, apic_p2_table + or eax, 0b11 ; present + writable + mov [p3_table + 24], eax + + ; map apic memory space without caching + mov eax, 0xFEE00000 + 0b10000111 ; huge + no caching + writable + present + mov [apic_p2_table + 4024], eax + + ; map first page without caching mov eax, 0b10000111 ; huge + no caching + writable + present mov [p2_table], eax @@ -169,6 +179,8 @@ p3_table: resb 4096 p2_table: resb 4096 +apic_p2_table: + resb 4096 alignb 4096 * 512 ; align memory into huge memory page stack_bottom: diff --git a/kernel/src/interrupts/apic.rs b/kernel/src/interrupts/apic.rs index dc1177b..93fba8b 100644 --- a/kernel/src/interrupts/apic.rs +++ b/kernel/src/interrupts/apic.rs @@ -1,13 +1,13 @@ use x86_64::registers::model_specific::Msr; #[cfg(target_arch = "x86_64")] -const APIC_FLAG: u64 = 0x0800; -const APIC_BASE_MSR: u32 = 0x001b; +const APIC_FLAG: u64 = 0x0800; +const APIC_BASE_MSR: u32 = 0x001b; // APIC constant register values -const APIC_DISABLE: u32 = 0x0001_0000; -const APIC_NMI: u32 = 0x0000_0400; -const APIC_SW_ENABLE: u32 = 0x0000_0100; +const APIC_DISABLE: u32 = 0x0001_0000; +const APIC_NMI: u32 = 0x0000_0400; +const APIC_SW_ENABLE: u32 = 0x0000_0100; pub fn is_x2apic() -> bool { let info: u32; @@ -33,52 +33,52 @@ pub fn set_apic_base(v: u64) { pub struct InterruptCommand { low: u32, _rsv: [u32; 3], - high: u32 + high: u32, } #[repr(isize)] pub enum ApicRegister { - ApicId = 8, - ApicVer = 12, - TaskPriority = 32, - ArbitrationPriority = 36, - ProcessorPriority = 40, - EndOfInterrupt = 44, - LogicalDst = 52, - DstFmt = 56, - SpuriousInterruptVec = 60, - InService = 64, - TriggerMode = 96, - InterruptRequest = 128, - ErrorStatus = 160, - InterruptCommand = 192, - InterruptCommandHigh = 196, - LvtTimer = 200, - LvtThermalSensor = 204, - LvtPerformanceMonitor = 208, - LvtLint0 = 212, - LvtLint1 = 216, - LvtError = 220, - TimerInitialCount = 224, - TimerCurrentCount = 228, - TimerDivideConfig = 248, - ExtApicFeature = 256, - ExtApicControl = 260, - SpecificEndOfInterrupt = 264, - InterruptEnable = 288, - ExtInterruptLocalVectorTable = 320, + ApicId = 8, + ApicVer = 12, + TaskPriority = 32, + ArbitrationPriority = 36, + ProcessorPriority = 40, + EndOfInterrupt = 44, + LogicalDst = 52, + DstFmt = 56, + SpuriousInterruptVec = 60, + InService = 64, + TriggerMode = 96, + InterruptRequest = 128, + ErrorStatus = 160, + InterruptCommand = 192, + InterruptCommandHigh = 196, + LvtTimer = 200, + LvtThermalSensor = 204, + LvtPerformanceMonitor = 208, + LvtLint0 = 212, + LvtLint1 = 216, + LvtError = 220, + TimerInitialCount = 224, + TimerCurrentCount = 228, + TimerDivideConfig = 248, + ExtApicFeature = 256, + ExtApicControl = 260, + SpecificEndOfInterrupt = 264, + InterruptEnable = 288, + ExtInterruptLocalVectorTable = 320, } #[repr(u32)] pub enum TimerDivideConfig { - Div2 = 0, - Div4 = 1, - Div8 = 2, - Div16 = 3, - Div32 = 8, - Div64 = 9, - Div128 = 10, - NoDivide = 11, + Div2 = 0, + Div4 = 1, + Div8 = 2, + Div16 = 3, + Div32 = 8, + Div64 = 9, + Div128 = 10, + NoDivide = 11, } static mut LOCAL_APIC: Option<Apic> = None; @@ -98,15 +98,12 @@ pub struct Apic { impl Apic { pub fn new() -> Option<Self> { - if !is_apic() { return None; } + 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; apic.set(ApicRegister::LogicalDst, 0); @@ -116,7 +113,10 @@ impl Apic { 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::LvtError, + super::InterruptType::ApicError.as_u8().into(), + ); apic.set(ApicRegister::ErrorStatus, 0); unsafe { Msr::new(APIC_BASE_MSR).write(base_apic | APIC_FLAG) }; @@ -134,23 +134,25 @@ impl Apic { } fn from_base_apic(base_apic: u64) -> Self { - Self { regs: - ((base_apic >> 12) & 0xfffffffff) as *mut [u32; 1024] + Self { + regs: ((base_apic) & 0xfffffffff << 12) as *mut [u32; 1024], } } - pub 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 } + fn ptr_mut(&mut self) -> *mut u32 { + self.regs as *mut u32 + } pub fn get(&self, register: ApicRegister) -> u32 { - unsafe { ((self.ptr() as usize + (register as usize) * 4) as *const u32).read_volatile() } - //unsafe { self.ptr().offset(register as isize).read_volatile() } + unsafe { self.ptr().offset(register as isize).read_volatile() } } pub fn set(&mut self, register: ApicRegister, val: u32) { - 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) } + unsafe { self.ptr_mut().offset(register as isize).write_volatile(val) } } pub fn set_interrupt_command(&mut self, dst: u8, v: u8) { @@ -163,18 +165,23 @@ impl Apic { self.set(ApicRegister::EndOfInterrupt, 0); } - pub fn set_timer_interrupt_handler(&mut self, divide: TimerDivideConfig, intr: super::InterruptType) { + pub fn set_timer_interrupt_handler( + &mut self, + divide: TimerDivideConfig, + intr: super::InterruptType, + ) { self.set(ApicRegister::LvtTimer, intr.as_u8() as u32 | (1 << 17)); self.set(ApicRegister::TimerDivideConfig, divide as u32); - self.set(ApicRegister::TimerInitialCount, 2048); - self.set(ApicRegister::TimerCurrentCount, 2048) + self.set(ApicRegister::TimerInitialCount, 1 << 27); } pub fn get_timer_value(&self) -> u32 { self.get(ApicRegister::TimerCurrentCount) } - pub fn get_error_code(&self) -> u32 { + pub fn get_error_code(&mut self) -> u32 { + self.set(ApicRegister::ErrorStatus, 0); + // write contents of apic error register to memory self.get(ApicRegister::ErrorStatus) } diff --git a/kernel/src/main.rs b/kernel/src/main.rs index a0e1e56..c6c00c2 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -23,22 +23,16 @@ 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::Div16, 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); } |