patina_internal_cpu 23.3.0

CPU support.
Documentation
//! `AArch64` Interrupt module
//!
//! ## License
//!
//! Copyright (c) Microsoft Corporation.
//!
//! SPDX-License-Identifier: Apache-2.0
//!

use crate::log_registers;
use patina::pi::protocol::cpu_arch::EfiSystemContext;
use patina_stacktrace::{StackFrame, StackTrace, error::Error};

#[cfg(target_arch = "aarch64")]
pub mod gic_manager;
mod interrupt_manager;

#[allow(unused)]
pub use interrupt_manager::InterruptsAarch64;

pub type ExceptionContextAArch64 = patina::standard::efi::protocols::debug_support::SystemContextAArch64;

impl super::EfiSystemContextFactory for ExceptionContextAArch64 {
    fn create_efi_system_context(&mut self) -> EfiSystemContext {
        EfiSystemContext { system_context_aarch64: core::ptr::from_mut(self) }
    }
}

impl super::EfiExceptionInfoDump for ExceptionContextAArch64 {
    fn dump_stack_trace(&self) {
        let stack_frame = StackFrame { pc: self.elr, sp: self.sp, fp: self.fp };
        // SAFETY: Called during exception handling with CPU context registers.
        // The exception context is considered valid to dump at this time.
        match unsafe { StackTrace::dump_with(stack_frame) } {
            Ok(()) => (),
            Err(Error::ExceptionDirectoryNotFound { module }) => {
                let no_name = "<no module>";
                let image_name = module.unwrap_or(no_name);
                log::error!(
                    "StackTrace: `{image_name}` does not contain an exception directory. Trying fp/lr based stack trace instead."
                );
                // SAFETY: Called during exception handling with PC, SP, and FP
                // captured from the exception context. The frame pointer chain is
                // walked as a best effort fallback mainly to cater binaries
                // compiled with the GCC toolchain.
                if let Err(err) = unsafe { StackTrace::dump_with_fp_chain(stack_frame) } {
                    log::error!("StackTrace: {err}");
                }
            }
            Err(err) => {
                log::error!("StackTrace: {err}");
            }
        }
    }

    fn dump_system_context_registers(&self) {
        log::error!("Exception Registers:");
        log_registers!("ESR", self.esr, "ELR", self.elr, "SPSR", self.spsr, "FAR", self.far,);

        log::error!("");

        log::error!("General-Purpose Registers:");
        log_registers!(
            "x0", self.x0, "x1", self.x1, "x2", self.x2, "x3", self.x3, "x4", self.x4, "x5", self.x5, "x6", self.x6,
            "x7", self.x7, "x8", self.x8, "x9", self.x9, "x10", self.x10, "x11", self.x11, "x12", self.x12, "x13",
            self.x13, "x14", self.x14, "x15", self.x15, "x16", self.x16, "x17", self.x17, "x18", self.x18, "x19",
            self.x19, "x20", self.x20, "x21", self.x21, "x22", self.x22, "x23", self.x23, "x24", self.x24, "x25",
            self.x25, "x26", self.x26, "x27", self.x27, "x28", self.x28, "fp", self.fp, "lr", self.lr, "sp", self.sp
        );

        log::debug!("Full Context: {self:#X?}");
    }
}