diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2017-06-09 14:49:49 +0300 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2017-06-15 11:45:04 +0300 |
commit | 40228ba57c8532d4977d684a363915402d85dbf9 (patch) | |
tree | f0d39703b30020857f34419b46e972090a5f46cc /virt | |
parent | 690a341577f9adf2c275ababe0dcefe91898bbf0 (diff) | |
download | linux-40228ba57c8532d4977d684a363915402d85dbf9.tar.xz |
KVM: arm64: vgic-v3: Add ICV_DIR_EL1 handler
Add a handler for writing the guest's view of the ICC_DIR_EL1
register, performing the deactivation of an interrupt if EOImode
is set ot 1.
Tested-by: Alexander Graf <agraf@suse.de>
Acked-by: David Daney <david.daney@cavium.com>
Reviewed-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/arm/hyp/vgic-v3-sr.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c index 08a5d76c82c7..2f2af03e8932 100644 --- a/virt/kvm/arm/hyp/vgic-v3-sr.c +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c @@ -652,6 +652,30 @@ static void __hyp_text __vgic_v3_bump_eoicount(void) write_gicreg(hcr, ICH_HCR_EL2); } +static void __hyp_text __vgic_v3_write_dir(struct kvm_vcpu *vcpu, + u32 vmcr, int rt) +{ + u32 vid = vcpu_get_reg(vcpu, rt); + u64 lr_val; + int lr; + + /* EOImode == 0, nothing to be done here */ + if (!(vmcr & ICH_VMCR_EOIM_MASK)) + return; + + /* No deactivate to be performed on an LPI */ + if (vid >= VGIC_MIN_LPI) + return; + + lr = __vgic_v3_find_active_lr(vcpu, vid, &lr_val); + if (lr == -1) { + __vgic_v3_bump_eoicount(); + return; + } + + __vgic_v3_clear_active_lr(lr, lr_val); +} + static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { u32 vid = vcpu_get_reg(vcpu, rt); @@ -946,6 +970,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu) else fn = __vgic_v3_write_bpr0; break; + case SYS_ICC_DIR_EL1: + fn = __vgic_v3_write_dir; + break; default: return 0; } |