Running an hypervisor in Armv8-R AEM FVP platform, hypervisor mode, aarch32. While trap and emulating an MMIO region where the supervisor mode guest emits an STRD instruction (targetting a region protected by the 2nd stage MPU), HSR.ISS comes up "empty". That is, despite ELR_hyp, HDFAR and HSR.EC being correct, HSR.ISS.ISV is 0. Therefore, I don't have sufficient information to decode and emulate the access. I guess it would be possible to decode the instruction "by hand", but I don't understand why this is happening. Can you imagine any reason why this information is not there? Should I expect this in real hardware? Could this possibly be some kind of bug or issue with the model?
From Arm ARM, ISS encoding for exception from a Data Abort. For ISV, bit [24]
This bit is 0 for all faults except Data Aborts generated by stage 2 address translations for which all the following apply to the instruction that generated the Data Abort exception:
• The instruction is an LDR, LDA, LDRT, LDRSH, LDRSHT, LDRH, LDAH, LDRHT, LDRSB, LDRSBT, LDRB, LDAB, LDRBT, STR, STL, STRT, STRH, STLH, STRHT,STRB, STLB, or STRBT instruction.• The instruction is not performing register writeback.• The instruction is not using the PC as a source or destination register
It seems STRD/LDRD are not in the instructions list that can generate valid syndrome.
It seems you are right. I assumed it would apply also to ldrd/strd given that EC.SAS field has a enconding for doubleword accesses on aarch32.
Thank you for helping me figure this out!
Just for completeness... I should have checked this before, but Linux gicv3 driver files for 32-bit arm have the explicit answer to this question in this exact case (ie access to gicd.irouter register):
/* * Even in 32bit systems that use LPAE, there is no guarantee that the I/O * interface provides true 64bit atomic accesses, so using strd/ldrd doesn't * make much sense. * Moreover, 64bit I/O emulation is extremely difficult to implement on * AArch32, since the syndrome register doesn't provide any information for * them. * Consequently, the following IO helpers use 32bit accesses. */ static inline void __gic_writeq_nonatomic(u64 val, volatile void __iomem *addr) { writel_relaxed((u32)val, addr); writel_relaxed((u32)(val >> 32), addr + 4); }
The GIC function's comment is very clear. Two traps are more simpler than decode invalid dataabort and emulate 64-bit IO.
Glad to be of help!