异常

AArch64 定义了一个包含 16 个条目的异常矢量表,适用于处理 4 种状态(当前 EL 使用 SP0,当前 EL 使用 SPx,较低 EL 使用 AArch64,较低 EL 使用 AArch32)下的 4 种异常(同步、IRQ、FIQ、SError)。可以通过汇编方式实现这一操作,以便在调用 Rust 代码之前将易失性寄存器保存到堆栈:

  1. use log::error;
  2. use smccc::psci::system_off;
  3. use smccc::Hvc;
  4. #[no_mangle]
  5. extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) {
  6. error!("sync_exception_current");
  7. system_off::<Hvc>().unwrap();
  8. }
  9. #[no_mangle]
  10. extern "C" fn irq_current(_elr: u64, _spsr: u64) {
  11. error!("irq_current");
  12. system_off::<Hvc>().unwrap();
  13. }
  14. #[no_mangle]
  15. extern "C" fn fiq_current(_elr: u64, _spsr: u64) {
  16. error!("fiq_current");
  17. system_off::<Hvc>().unwrap();
  18. }
  19. #[no_mangle]
  20. extern "C" fn serr_current(_elr: u64, _spsr: u64) {
  21. error!("serr_current");
  22. system_off::<Hvc>().unwrap();
  23. }
  24. #[no_mangle]
  25. extern "C" fn sync_lower(_elr: u64, _spsr: u64) {
  26. error!("sync_lower");
  27. system_off::<Hvc>().unwrap();
  28. }
  29. #[no_mangle]
  30. extern "C" fn irq_lower(_elr: u64, _spsr: u64) {
  31. error!("irq_lower");
  32. system_off::<Hvc>().unwrap();
  33. }
  34. #[no_mangle]
  35. extern "C" fn fiq_lower(_elr: u64, _spsr: u64) {
  36. error!("fiq_lower");
  37. system_off::<Hvc>().unwrap();
  38. }
  39. #[no_mangle]
  40. extern "C" fn serr_lower(_elr: u64, _spsr: u64) {
  41. error!("serr_lower");
  42. system_off::<Hvc>().unwrap();
  43. }
  • EL 指异常级别;我们今天下午的所有示例都在 EL1 级别下运行。
  • 为简单起见,我们没有区分当前 EL 异常中的 SP0 和 SPx,也没有区分较低 EL 异常中的 AArch32 和 AArch64。
  • 在本示例中,只需记录异常并进行关机操作,因为预计不会发生任何此类异常。
  • 我们可以将异常处理程序和主执行上下文视为不同的线程。通过 Send 和 Sync 控制它们之间可以共享的内容,就像使用线程进行共享一样。例如,如果想在异常处理程序和程序的其余部分之间共享某个值,并且使用 Send 而非 Sync,则需要将该值封装在诸如 Mutex 之类的内容中,并放入静态变量。