Exception Analysis and Utilities
Relevant source files
This document covers the exception analysis and parsing utilities provided by the exception_utils.rs module. These utilities form a critical layer between the low-level assembly exception vectors and high-level exception handlers, providing functions to extract and interpret information from AArch64 exception syndrome registers, perform address translations, and manage register context during exception handling.
For information about the assembly exception vectors that capture exceptions, see Assembly Exception Vectors. For details about high-level exception dispatch and handling logic, see High-Level Exception Handling.
Exception Syndrome Register Analysis
The exception analysis system provides a comprehensive interface for reading and interpreting the Exception Syndrome Register (ESR_EL2), which contains detailed information about the cause and nature of exceptions that occur during guest execution.
Exception Syndrome Register Reading Functions
flowchart TD
subgraph subGraph1["Exception Classification"]
EC["Exception Class (EC)"]
ISS["Instruction Specific Syndrome (ISS)"]
IL["Instruction Length (IL)"]
end
subgraph subGraph0["Core Reading Functions"]
exception_esr["exception_esr()"]
exception_class["exception_class()"]
exception_class_value["exception_class_value()"]
exception_iss["exception_iss()"]
end
ESR_EL2["ESR_EL2 Hardware Register"]
DataAbort["Data Abort Analysis"]
SystemReg["System Register Analysis"]
HVC["HVC Call Analysis"]
EC --> DataAbort
EC --> HVC
EC --> SystemReg
ESR_EL2 --> exception_class
ESR_EL2 --> exception_class_value
ESR_EL2 --> exception_esr
ESR_EL2 --> exception_iss
ISS --> DataAbort
ISS --> SystemReg
exception_class --> EC
exception_esr --> IL
exception_iss --> ISS
The system provides several core functions for accessing different fields of the ESR_EL2 register:
exception_esr()src/exception_utils.rs(L12 - L14) returns the complete ESR_EL2 register valueexception_class()src/exception_utils.rs(L21 - L23) extracts the Exception Class field as an enum valueexception_class_value()src/exception_utils.rs(L30 - L32) extracts the Exception Class as a raw numeric valueexception_iss()src/exception_utils.rs(L170 - L172) extracts the Instruction Specific Syndrome field
Sources: src/exception_utils.rs(L7 - L32) src/exception_utils.rs(L165 - L172)
Instruction Analysis
The system provides utilities for analyzing instruction-related information from exceptions:
| Function | Purpose | Return Value |
|---|---|---|
| exception_instruction_length() | Determines if instruction is 16-bit or 32-bit | 0 for 16-bit, 1 for 32-bit |
| exception_next_instruction_step() | Calculates step size for instruction pointer advancement | 2 for 16-bit, 4 for 32-bit |
Sources: src/exception_utils.rs(L144 - L163)
Fault Address Translation System
The fault address translation system handles the complex process of converting virtual fault addresses to physical addresses using the ARM Address Translation (AT) instructions and register coordination.
Address Translation Flow
flowchart TD
subgraph subGraph2["Final Address Calculation"]
Page_Offset["FAR & 0xfff"]
Page_Number["HPFAR << 8"]
Final_GPA["GuestPhysAddr"]
end
subgraph subGraph1["Translation Process"]
arm_at["arm_at!(s1e1r, far)"]
translate_far_to_hpfar["translate_far_to_hpfar()"]
par_to_far["par_to_far() helper"]
exception_hpfar["exception_hpfar()"]
end
subgraph subGraph0["Translation Decision Logic"]
S1PTW_Check["Check ESR_ELx_S1PTW bit"]
Permission_Check["exception_data_abort_is_permission_fault()"]
Translation_Needed["Translation Needed?"]
end
FAR_EL2["FAR_EL2: Fault Address Register"]
HPFAR_EL2["HPFAR_EL2: Hypervisor Physical Fault Address Register"]
PAR_EL1["PAR_EL1: Physical Address Register"]
FAR_EL2 --> Page_Offset
FAR_EL2 --> S1PTW_Check
PAR_EL1 --> par_to_far
Page_Number --> Final_GPA
Page_Offset --> Final_GPA
Permission_Check --> Translation_Needed
S1PTW_Check --> Permission_Check
Translation_Needed --> exception_hpfar
Translation_Needed --> translate_far_to_hpfar
arm_at --> PAR_EL1
exception_hpfar --> Page_Number
par_to_far --> Page_Number
translate_far_to_hpfar --> arm_at
The exception_fault_addr() function src/exception_utils.rs(L133 - L142) implements a sophisticated address translation algorithm that:
- Reads the FAR_EL2 register to get the virtual fault address
- Determines whether address translation is needed based on the S1PTW bit and fault type
- Either performs address translation using
translate_far_to_hpfar()or directly reads HPFAR_EL2 - Combines the page offset from FAR_EL2 with the page number from HPFAR_EL2
The translate_far_to_hpfar() function src/exception_utils.rs(L92 - L113) uses the ARM Address Translation instruction to convert a virtual address to physical, handling the PAR_EL1 register state and error conditions.
Sources: src/exception_utils.rs(L34 - L142)
Data Abort Exception Analysis
The system provides comprehensive analysis capabilities for data abort exceptions, which are among the most common exceptions in virtualization scenarios involving MMIO operations.
Data Abort Analysis Functions
flowchart TD
subgraph subGraph1["Access Pattern Analysis"]
exception_data_abort_access_is_write["exception_data_abort_access_is_write()"]
exception_data_abort_access_width["exception_data_abort_access_width()"]
exception_data_abort_access_reg["exception_data_abort_access_reg()"]
exception_data_abort_access_reg_width["exception_data_abort_access_reg_width()"]
exception_data_abort_access_is_sign_ext["exception_data_abort_access_is_sign_ext()"]
end
subgraph subGraph0["Data Abort Classification"]
exception_data_abort_is_permission_fault["exception_data_abort_is_permission_fault()"]
exception_data_abort_is_translate_fault["exception_data_abort_is_translate_fault()"]
exception_data_abort_handleable["exception_data_abort_handleable()"]
end
ESR_ISS["ESR_EL2.ISS Field"]
ESR_ISS --> exception_data_abort_access_is_sign_ext
ESR_ISS --> exception_data_abort_access_is_write
ESR_ISS --> exception_data_abort_access_reg
ESR_ISS --> exception_data_abort_access_reg_width
ESR_ISS --> exception_data_abort_access_width
ESR_ISS --> exception_data_abort_handleable
ESR_ISS --> exception_data_abort_is_permission_fault
ESR_ISS --> exception_data_abort_is_translate_fault
The data abort analysis functions extract specific information from the ISS field of ESR_EL2:
| Function | Bit Fields | Purpose |
|---|---|---|
| exception_data_abort_is_permission_fault() | ISS[5:0] & 0xF0 == 12 | Identifies permission faults vs translation faults |
| exception_data_abort_is_translate_fault() | ISS[5:0] & 0xF0 == 4 | Identifies translation faults |
| exception_data_abort_access_is_write() | ISS[6] | Determines read vs write access |
| exception_data_abort_access_width() | ISS[23:22] | Access width (1, 2, 4, or 8 bytes) |
| exception_data_abort_access_reg() | ISS[20:16] | Register index (0-31) |
| exception_data_abort_handleable() | ISS[24] | !ISS[10] | Determines if abort can be handled |
Sources: src/exception_utils.rs(L197 - L255)
System Register Access Analysis
The system provides specialized parsing for system register access exceptions, which occur when guests attempt to access system registers that require hypervisor intervention.
System Register Parsing Functions
flowchart TD
subgraph subGraph1["Parsing Functions"]
exception_sysreg_direction_write["exception_sysreg_direction_write()"]
exception_sysreg_gpr["exception_sysreg_gpr()"]
exception_sysreg_addr["exception_sysreg_addr()"]
end
subgraph subGraph0["System Register ISS Format"]
ISS_Field["ESR_EL2.ISS[24:0]"]
Op0["Op0[21:20]"]
Op2["Op2[19:17]"]
Op1["Op1[16:14]"]
CRn["CRn[13:10]"]
CRm["CRm[4:1]"]
Direction["Direction[0]"]
RT["RT[9:5]"]
end
CRm --> exception_sysreg_addr
CRn --> exception_sysreg_addr
Direction --> exception_sysreg_direction_write
ISS_Field --> CRm
ISS_Field --> CRn
ISS_Field --> Direction
ISS_Field --> Op0
ISS_Field --> Op1
ISS_Field --> Op2
ISS_Field --> RT
Op0 --> exception_sysreg_addr
Op1 --> exception_sysreg_addr
Op2 --> exception_sysreg_addr
RT --> exception_sysreg_gpr
The system register analysis functions provide:
exception_sysreg_direction_write()src/exception_utils.rs(L175 - L178) determines if the access is a write (true) or read (false)exception_sysreg_gpr()src/exception_utils.rs(L181 - L186) extracts the general-purpose register index (RT field)exception_sysreg_addr()src/exception_utils.rs(L192 - L195) constructs the system register address from encoding fields
The exception_sysreg_addr() function implements the ARMv8 system register encoding format, combining Op0, Op1, Op2, CRn, and CRm fields into a unique register identifier.
Sources: src/exception_utils.rs(L174 - L195)
Register Context Management Macros
The system provides assembly macros for managing host register context during exception handling, ensuring proper preservation and restoration of callee-saved registers.
Context Switching Macros
flowchart TD
subgraph subGraph1["Exception Flow Integration"]
VM_Entry["VM Entry from Aarch64VCpu::run()"]
VM_Exit["VM Exit to Exception Handler"]
Return_to_Host["Return to Aarch64VCpu::run()"]
end
subgraph subGraph0["Host Context Management"]
Host_Registers["Host Callee-Saved Registersx19-x30"]
Stack_Frame["Stack Frame12 * 8 bytes"]
save_regs_to_stack["save_regs_to_stack!"]
restore_regs_from_stack["restore_regs_from_stack!"]
end
Exception_Processing["Exception Processing"]
Exception_Processing --> restore_regs_from_stack
Host_Registers --> Return_to_Host
Host_Registers --> Stack_Frame
Stack_Frame --> Host_Registers
VM_Entry --> save_regs_to_stack
VM_Exit --> Exception_Processing
restore_regs_from_stack --> Stack_Frame
save_regs_to_stack --> Host_Registers
The register context management system consists of two complementary macros:
save_regs_to_stack! src/exception_utils.rs(L278 - L289) :
- Allocates 96 bytes (12 * 8) on the stack
- Saves registers x19-x30 using
stp(store pair) instructions - Used during VM entry to preserve host state
restore_regs_from_stack! src/exception_utils.rs(L300 - L311) :
- Restores registers x19-x30 using
ldp(load pair) instructions - Deallocates the 96-byte stack frame
- Used during VM exit to restore host state
These macros ensure that the host's callee-saved registers are properly preserved across guest execution, maintaining the calling convention for the Aarch64VCpu::run() function.
Sources: src/exception_utils.rs(L267 - L311)
Integration with Exception Handling Pipeline
The exception utilities integrate seamlessly with the broader exception handling system, providing the analytical foundation for exception dispatch and handling decisions.
Utility Function Usage Pattern
flowchart TD
subgraph subGraph2["Exception Handlers"]
handle_data_abort["handle_data_abort()"]
handle_system_register["handle_system_register()"]
handle_psci_call["handle_psci_call()"]
end
subgraph subGraph1["Exception Type Specific Analysis"]
Data_Abort["Data Abort Functions"]
System_Register["System Register Functions"]
HVC_Analysis["HVC Call Analysis"]
end
subgraph subGraph0["Exception Analysis Phase"]
exception_esr["exception_esr()"]
exception_class["exception_class()"]
exception_fault_addr["exception_fault_addr()"]
end
Exception_Vector["Assembly Exception Vector"]
Exception_Context["Exception Context Capture"]
Data_Abort --> exception_fault_addr
Data_Abort --> handle_data_abort
Exception_Context --> exception_esr
Exception_Vector --> Exception_Context
HVC_Analysis --> handle_psci_call
System_Register --> handle_system_register
exception_class --> Data_Abort
exception_class --> HVC_Analysis
exception_class --> System_Register
exception_esr --> exception_class
The utilities serve as the foundational layer that enables higher-level exception handlers to make informed decisions about how to process different types of exceptions, providing both classification and detailed analysis capabilities.
Sources: src/exception_utils.rs(L1 - L311)