例外狀況

AArch64 定義了包含 16 個項目的例外狀況向量表,適用於 4 種狀態的 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;

#[no_mangle]
extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) {
    error!("sync_exception_current");
    system_off::<Hvc>().unwrap();
}

#[no_mangle]
extern "C" fn irq_current(_elr: u64, _spsr: u64) {
    error!("irq_current");
    system_off::<Hvc>().unwrap();
}

#[no_mangle]
extern "C" fn fiq_current(_elr: u64, _spsr: u64) {
    error!("fiq_current");
    system_off::<Hvc>().unwrap();
}

#[no_mangle]
extern "C" fn serr_current(_elr: u64, _spsr: u64) {
    error!("serr_current");
    system_off::<Hvc>().unwrap();
}

#[no_mangle]
extern "C" fn sync_lower(_elr: u64, _spsr: u64) {
    error!("sync_lower");
    system_off::<Hvc>().unwrap();
}

#[no_mangle]
extern "C" fn irq_lower(_elr: u64, _spsr: u64) {
    error!("irq_lower");
    system_off::<Hvc>().unwrap();
}

#[no_mangle]
extern "C" fn fiq_lower(_elr: u64, _spsr: u64) {
    error!("fiq_lower");
    system_off::<Hvc>().unwrap();
}

#[no_mangle]
extern "C" fn serr_lower(_elr: u64, _spsr: u64) {
    error!("serr_lower");
    system_off::<Hvc>().unwrap();
}
  • EL 是指例外狀況層級,今天下午的所有範例都是在 EL1 執行。
  • 為求簡單,我們不會針對目前 EL 例外狀況區分 SP0 和 SPx,也不會針對較低 EL 例外狀況區分 AArch32 和 AArch64。
  • 在此範例中,我們只需記錄例外狀況並關機,因為我們並不預期會實際發生任何例外狀況。
  • 例外狀況處理常式和主執行環境,其實可以約略視為不同執行緒。SendSync 會控管可在它們之間分享的內容,就像執行緒一樣。舉例來說,如要在例外狀況處理常式與程式其餘部分之間分享某個值,而且是 Send (而非 Sync),我們就需要將該值包裝在 Mutex 等項目中並放入靜態項目。