ARMv8-R Hypervisor Trap to EL2 with Missing HSR.ISS Data During STRD Emulation

In ARMv8-R AEM FVP platforms running in hypervisor mode (EL2) with a 32-bit guest (AArch32), a specific issue arises when emulating an MMIO region accessed by a guest using the STRD (Store Doubleword) instruction. The guest attempts to access a memory region protected by the second-stage Memory Protection Unit (MPU), triggering a trap to EL2. While the Hypervisor Syndrome Register (HSR) correctly captures the Exception Class (HSR.EC) and the Hypervisor Data Fault Address Register (HDFAR) points to the correct address, the Instruction Syndrome (HSR.ISS) lacks sufficient information to decode and emulate the STRD instruction. Specifically, the ISV (Instruction Syndrome Valid) bit (HSR.ISS.ISV) is 0, rendering the ISS field effectively "empty." This behavior complicates the hypervisor’s ability to decode and emulate the instruction, raising questions about whether this is expected behavior, a hardware limitation, or a potential bug in the ARMv8-R AEM FVP model.

The STRD instruction in question is of the form STRD r4, [r3, r0], which attempts to store two 32-bit registers (r4 and r5) into a memory location calculated by adding the contents of r0 to the base address in r3. The address accessed (0xaf006128) is 64-bit aligned, ruling out alignment issues as the cause of the problem. The guest is attempting to access a GIC Distributor Router register, which is a common scenario in hypervisor-managed systems. However, the lack of ISS information prevents the hypervisor from accurately emulating the access, necessitating manual decoding of the instruction.

STRD Instruction and HSR.ISS Encoding Limitations in ARMv8-R

The root cause of this issue lies in the ARMv8-R architecture’s handling of the HSR.ISS field for Data Abort exceptions. According to the ARM Architecture Reference Manual (ARM ARM), the ISS field is only populated with valid information for specific instructions and under specific conditions. For Data Aborts, the ISV bit (HSR.ISS.ISV) is set to 1 only if the following conditions are met:

  1. The instruction generating the Data Abort is one of the following: LDR, LDA, LDRT, LDRSH, LDRSHT, LDRH, LDAH, LDRHT, LDRSB, LDRSBT, LDRB, LDAB, LDRBT, STR, STL, STRT, STRH, STLH, STRHT, STRB, STLB, or STRBT.
  2. The instruction is not performing register writeback.
  3. The instruction is not using the Program Counter (PC) as a source or destination register.

The STRD instruction, which stores two 32-bit registers to memory, is notably absent from this list. This omission means that when a Data Abort is triggered by an STRD instruction, the HSR.ISS field is not populated with valid information, and the ISV bit remains 0. This behavior is consistent with the ARMv8-R architecture specification and is not a bug in the ARMv8-R AEM FVP model. Instead, it reflects a deliberate design choice to limit the complexity of the ISS encoding for certain instructions.

The lack of ISS information for STRD instructions poses a challenge for hypervisors attempting to emulate MMIO accesses. Without the ISS field, the hypervisor must manually decode the faulting instruction to determine the source registers, destination address, and other relevant details. This process is more complex and error-prone than relying on the ISS field, which provides a structured and standardized way to decode exceptions.

Manual Instruction Decoding and Emulation Strategies for STRD in ARMv8-R

Given the limitations of the HSR.ISS field for STRD instructions, hypervisors must implement manual instruction decoding and emulation strategies to handle such cases. The following steps outline a systematic approach to resolving this issue:

  1. Instruction Fetch and Decoding: When a Data Abort exception occurs, the hypervisor must first fetch the faulting instruction from the guest’s memory. This can be done using the Exception Link Register (ELR_hyp), which holds the address of the faulting instruction. The hypervisor then decodes the instruction to determine its type, source registers, and addressing mode. For the STRD instruction STRD r4, [r3, r0], the hypervisor identifies r4 and r5 as the source registers and calculates the destination address by adding the contents of r0 to the base address in r3.

  2. Emulation of the STRD Instruction: Once the instruction is decoded, the hypervisor emulates the STRD operation. This involves reading the values from the source registers (r4 and r5) and writing them to the calculated destination address. Since the access is to an MMIO region, the hypervisor must ensure that the write operation is performed in a way that respects the semantics of the target device. For example, if the guest is accessing a GIC Distributor Router register, the hypervisor must translate the access into the appropriate sequence of writes to the virtualized GIC registers.

  3. Handling Alignment and Atomicity: The hypervisor must also ensure that the emulated access adheres to the alignment and atomicity requirements of the target architecture. In the case of STRD, the destination address must be 64-bit aligned. If the address is not aligned, the hypervisor must either generate an alignment fault or split the access into multiple operations. Additionally, the hypervisor must consider the atomicity of the access, especially when emulating 64-bit writes on a 32-bit system. In some cases, it may be necessary to use two 32-bit writes to emulate a single 64-bit write, as demonstrated in the Linux GICv3 driver code.

  4. Optimization and Performance Considerations: Manual instruction decoding and emulation can be computationally expensive, especially in systems with high trap rates. To mitigate this, hypervisors can implement optimizations such as instruction caching, where the results of previous decodings are stored and reused for subsequent traps. Additionally, hypervisors can leverage hardware features such as stage-2 translation tables and MPU configurations to minimize the frequency of traps and reduce the overhead of emulation.

  5. Fallback to 32-bit Accesses: In cases where 64-bit emulation is particularly challenging or inefficient, hypervisors can fall back to using 32-bit accesses. This approach is exemplified in the Linux GICv3 driver, which explicitly avoids using STRD/LDRD instructions for 64-bit MMIO accesses on 32-bit systems. Instead, the driver uses two 32-bit writes to emulate a 64-bit write, as shown in the following code snippet:

static inline void __gic_writeq_nonatomic(u64 val, volatile void __iomem *addr) {
    writel_relaxed((u32)val, addr);
    writel_relaxed((u32)(val >> 32), addr + 4);
}

This strategy simplifies the emulation process and ensures compatibility with systems that do not support atomic 64-bit accesses.

By following these steps, hypervisors can effectively handle the limitations of the HSR.ISS field for STRD instructions and provide robust emulation of MMIO accesses in ARMv8-R systems. While the lack of ISS information complicates the emulation process, careful design and optimization can mitigate the performance impact and ensure correct operation of the virtualized system.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *