Виключення
AArch64 визначає векторну таблицю винятків із 16 записами для 4 типів винятків (синхронний, IRQ, FIQ, SError) із 4 станів (поточний EL із SP0, поточний EL із SPx, нижчий EL із використанням AArch64, нижчий EL із застосуванням AArch32). Ми реалізуємо це в асемблері, щоб зберегти непостійні регістри в стеку перед викликом коду Rust:
use log::error; use smccc::psci::system_off; use smccc::Hvc; // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) { error!("sync_exception_current"); system_off::<Hvc>().unwrap(); } // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn irq_current(_elr: u64, _spsr: u64) { error!("irq_current"); system_off::<Hvc>().unwrap(); } // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn fiq_current(_elr: u64, _spsr: u64) { error!("fiq_current"); system_off::<Hvc>().unwrap(); } // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn serr_current(_elr: u64, _spsr: u64) { error!("serr_current"); system_off::<Hvc>().unwrap(); } // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn sync_lower(_elr: u64, _spsr: u64) { error!("sync_lower"); system_off::<Hvc>().unwrap(); } // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn irq_lower(_elr: u64, _spsr: u64) { error!("irq_lower"); system_off::<Hvc>().unwrap(); } // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn fiq_lower(_elr: u64, _spsr: u64) { error!("fiq_lower"); system_off::<Hvc>().unwrap(); } // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn serr_lower(_elr: u64, _spsr: u64) { error!("serr_lower"); system_off::<Hvc>().unwrap(); }
- EL - це рівень винятків; усі наші приклади сьогодні працюють на EL1.
- Для простоти ми не розрізняємо SP0 і SPx для поточних винятків EL або між AArch32 і AArch64 для нижчих винятків EL.
- У цьому прикладі ми просто реєструємо виняток і вимикаємо живлення, оскільки ми не очікуємо, що будь-що з цього станеться.
- Ми можемо розглядати обробники винятків і наш основний контекст виконання більш-менш як різні потоки.
Send
іSync
керуватимуть тим, чим ми можемо обмінюватися між ними, як і з потоками. Наприклад, якщо ми хочемо поділитися деяким значенням між обробниками винятків та рештою програми, і цеSend
, але неSync
, тоді нам потрібно буде загорнути його в щось на зразокMutex
і помістити у статику.