target/arm: ISR_EL1 bits track virtual interrupts if IMO/FMO set

The A/I/F bits in ISR_EL1 should track the virtual interrupt
status, not the physical interrupt status, if the associated
HCR_EL2.AMO/IMO/FMO bit is set. Implement this, rather than
always showing the physical interrupt status.

We don't currently implement anything to do with external
aborts, so this applies only to the I and F bits (though it
ought to be possible for the outer guest to present a virtual
external abort to the inner guest, even if QEMU doesn't
emulate physical external aborts, so there is missing
functionality in this area).

Backports commit 636540e9c40bd0931ef3022cb953bb7dbecd74ed from qemu
This commit is contained in:
Peter Maydell 2018-11-10 09:20:56 -05:00 committed by Lioncash
parent f0c9e690fb
commit 0f0befc90a
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -1193,12 +1193,26 @@ static uint64_t isr_read(CPUARMState *env, const ARMCPRegInfo *ri)
CPUState *cs = ENV_GET_CPU(env);
uint64_t ret = 0;
if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
ret |= CPSR_I;
if (arm_hcr_el2_imo(env)) {
if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) {
ret |= CPSR_I;
}
} else {
if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
ret |= CPSR_I;
}
}
if (cs->interrupt_request & CPU_INTERRUPT_FIQ) {
ret |= CPSR_F;
if (arm_hcr_el2_fmo(env)) {
if (cs->interrupt_request & CPU_INTERRUPT_VFIQ) {
ret |= CPSR_F;
}
} else {
if (cs->interrupt_request & CPU_INTERRUPT_FIQ) {
ret |= CPSR_F;
}
}
/* External aborts are not possible in QEMU so A bit is always clear */
return ret;
}