redox/arch/x86_64/src/interrupt/mod.rs
Jeremy Soller 149b0297a4 Smp (#23)
* Fire up multiple processors

* Use IPIs to wake up secondary processors

* Much better exception information

* Modifications to show more information on fault

* WIP: Use real libstd

* Add TLS (not complete)

* Add random function, export getpid, cleanup

* Do not spin APs until new context

* Update rust

* Update rust

* Use rd/wrfsbase

* Implement TLS

* Implement compiler builtins and update rust

* Update rust

* Back to Redox libstd

* Update rust
2016-10-31 10:49:00 -06:00

86 lines
2.3 KiB
Rust

//! Interrupt instructions
use core::mem;
use paging::{ActivePageTable, VirtualAddress};
pub mod exception;
pub mod ipi;
pub mod irq;
pub mod syscall;
/// Clear interrupts
#[inline(always)]
pub unsafe fn disable() {
asm!("cli" : : : : "intel", "volatile");
}
/// Set interrupts
#[inline(always)]
pub unsafe fn enable() {
asm!("sti" : : : : "intel", "volatile");
}
/// Set interrupts and halt
/// This will atomically wait for the next interrupt
/// Performing enable followed by halt is not guaranteed to be atomic, use this instead!
#[inline(always)]
pub unsafe fn enable_and_halt() {
asm!("sti
hlt"
: : : : "intel", "volatile");
}
/// Set interrupts and nop
/// This will enable interrupts and allow the IF flag to be processed
/// Simply enabling interrupts does not gurantee that they will trigger, use this instead!
#[inline(always)]
pub unsafe fn enable_and_nop() {
asm!("sti
nop"
: : : : "intel", "volatile");
}
/// Halt instruction
#[inline(always)]
pub unsafe fn halt() {
asm!("hlt" : : : : "intel", "volatile");
}
/// Pause instruction
/// Safe because it is similar to a NOP, and has no memory effects
#[inline(always)]
pub fn pause() {
unsafe { asm!("pause" : : : : "intel", "volatile"); }
}
/// Get a stack trace
//TODO: Check for stack being mapped before dereferencing
#[inline(never)]
pub unsafe fn stack_trace() {
let mut rbp: usize;
asm!("" : "={rbp}"(rbp) : : : "intel", "volatile");
println!("TRACE: {:>016X}", rbp);
//Maximum 64 frames
let active_table = ActivePageTable::new();
for _frame in 0..64 {
if let Some(rip_rbp) = rbp.checked_add(mem::size_of::<usize>()) {
if active_table.translate(VirtualAddress::new(rbp)).is_some() && active_table.translate(VirtualAddress::new(rip_rbp)).is_some() {
let rip = *(rip_rbp as *const usize);
if rip == 0 {
println!(" {:>016X}: EMPTY RETURN", rbp);
break;
}
println!(" {:>016X}: {:>016X}", rbp, rip);
rbp = *(rbp as *const usize);
} else {
println!(" {:>016X}: GUARD PAGE", rbp);
break;
}
} else {
println!(" {:>016X}: RBP OVERFLOW", rbp);
}
}
}