summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornatrixaeria <upezu@student.kit.edu>2019-11-19 19:16:09 +0100
committernatrixaeria <upezu@student.kit.edu>2019-11-19 19:16:09 +0100
commit78ed9468fb817ffa225b8af3cfdd124c8e37d320 (patch)
treeeb1905b2874888ffd1793c005a33769384ac75a1
parent8609aa594e61e8789471cc8f540ee4787024509a (diff)
Fix apic register address and ordering
-rw-r--r--kernel/src/interrupts/apic.rs45
-rw-r--r--kernel/src/interrupts/idt.rs2
-rw-r--r--kernel/src/interrupts/mod.rs3
-rw-r--r--kernel/src/main.rs11
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<Apic> = 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);
}