diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2016-09-06 16:02:00 +0300 |
---|---|---|
committer | Christoffer Dall <christoffer.dall@linaro.org> | 2016-09-08 13:53:00 +0300 |
commit | 44636f976f5bb92631f0dd5fd26547d64c2c6a80 (patch) | |
tree | a23a01759d0f2a237ee119c5747080cd82c5fe4d /arch/arm64/kvm | |
parent | 7b17145ec7de9267e24038c0621c9ed47853ae4f (diff) | |
download | linux-44636f976f5bb92631f0dd5fd26547d64c2c6a80.tar.xz |
arm64: KVM: Preserve pending vSError in world switch
The HCR_EL2.VSE bit is used to signal an SError to a guest, and has
the peculiar feature of getting cleared when the guest has taken
the abort (this is the only bit that behaves as such in this register).
This means that if we signal such an abort, we must leave it
in the guest context until it disappears from HCR_EL2, and at which
point it must be cleared from the context. This is achieved by
reading back from HCR_EL2 until the guest takes the fault.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'arch/arm64/kvm')
-rw-r--r-- | arch/arm64/kvm/hyp/switch.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index b3a66c50d12b..8246de27ace1 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -110,6 +110,15 @@ static hyp_alternate_select(__deactivate_traps_arch, static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu) { + /* + * If we pended a virtual abort, preserve it until it gets + * cleared. See D1.14.3 (Virtual Interrupts) for details, but + * the crucial bit is "On taking a vSError interrupt, + * HCR_EL2.VSE is cleared to 0." + */ + if (vcpu->arch.hcr_el2 & HCR_VSE) + vcpu->arch.hcr_el2 = read_sysreg(hcr_el2); + __deactivate_traps_arch()(); write_sysreg(0, hstr_el2); write_sysreg(read_sysreg(mdcr_el2) & MDCR_EL2_HPMN_MASK, mdcr_el2); |