summaryrefslogtreecommitdiffstats
path: root/target
diff options
context:
space:
mode:
authorMarc Zyngier2019-11-26 14:55:36 +0100
committerPeter Maydell2019-11-26 14:55:36 +0100
commit7cf95aed53c8770a338617ef40d5f37d2c197853 (patch)
treeb746b3639c25316c75d370d1842829d9832cba97 /target
parenthw/arm: versal: Add the CRP as unimplemented (diff)
downloadqemu-7cf95aed53c8770a338617ef40d5f37d2c197853.tar.gz
qemu-7cf95aed53c8770a338617ef40d5f37d2c197853.tar.xz
qemu-7cf95aed53c8770a338617ef40d5f37d2c197853.zip
target/arm: Fix ISR_EL1 tracking when executing at EL2
The ARMv8 ARM states when executing at EL2, EL3 or Secure EL1, ISR_EL1 shows the pending status of the physical IRQ, FIQ, or SError interrupts. Unfortunately, QEMU's implementation only considers the HCR_EL2 bits, and ignores the current exception level. This means a hypervisor trying to look at its own interrupt state actually sees the guest state, which is unexpected and breaks KVM as of Linux 5.3. Instead, check for the running EL and return the physical bits if not running in a virtualized context. Fixes: 636540e9c40b Cc: qemu-stable@nongnu.org Reported-by: Quentin Perret <qperret@google.com> Signed-off-by: Marc Zyngier <maz@kernel.org> Message-id: 20191122135833.28953-1-maz@kernel.org Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r--target/arm/helper.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c
index a089fb5a69..027fffbff6 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -1934,8 +1934,11 @@ static uint64_t isr_read(CPUARMState *env, const ARMCPRegInfo *ri)
CPUState *cs = env_cpu(env);
uint64_t hcr_el2 = arm_hcr_el2_eff(env);
uint64_t ret = 0;
+ bool allow_virt = (arm_current_el(env) == 1 &&
+ (!arm_is_secure_below_el3(env) ||
+ (env->cp15.scr_el3 & SCR_EEL2)));
- if (hcr_el2 & HCR_IMO) {
+ if (allow_virt && (hcr_el2 & HCR_IMO)) {
if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) {
ret |= CPSR_I;
}
@@ -1945,7 +1948,7 @@ static uint64_t isr_read(CPUARMState *env, const ARMCPRegInfo *ri)
}
}
- if (hcr_el2 & HCR_FMO) {
+ if (allow_virt && (hcr_el2 & HCR_FMO)) {
if (cs->interrupt_request & CPU_INTERRUPT_VFIQ) {
ret |= CPSR_F;
}