]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - virt/kvm/arm/vgic/vgic-v3.c
Merge tag 'platform-drivers-x86-v4.12-2' of git://git.infradead.org/linux-platform...
[karo-tx-linux.git] / virt / kvm / arm / vgic / vgic-v3.c
index 6fe3f003636a311d055581ee6a8133d0951fd3f2..030248e669f65acd5e0155fbbef189d96e7cf7e3 100644 (file)
@@ -159,15 +159,24 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
 void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 {
        struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
+       u32 model = vcpu->kvm->arch.vgic.vgic_model;
        u32 vmcr;
 
-       /*
-        * Ignore the FIQen bit, because GIC emulation always implies
-        * SRE=1 which means the vFIQEn bit is also RES1.
-        */
-       vmcr = ((vmcrp->ctlr >> ICC_CTLR_EL1_EOImode_SHIFT) <<
-                ICH_VMCR_EOIM_SHIFT) & ICH_VMCR_EOIM_MASK;
-       vmcr |= (vmcrp->ctlr << ICH_VMCR_CBPR_SHIFT) & ICH_VMCR_CBPR_MASK;
+       if (model == KVM_DEV_TYPE_ARM_VGIC_V2) {
+               vmcr = (vmcrp->ackctl << ICH_VMCR_ACK_CTL_SHIFT) &
+                       ICH_VMCR_ACK_CTL_MASK;
+               vmcr |= (vmcrp->fiqen << ICH_VMCR_FIQ_EN_SHIFT) &
+                       ICH_VMCR_FIQ_EN_MASK;
+       } else {
+               /*
+                * When emulating GICv3 on GICv3 with SRE=1 on the
+                * VFIQEn bit is RES1 and the VAckCtl bit is RES0.
+                */
+               vmcr = ICH_VMCR_FIQ_EN_MASK;
+       }
+
+       vmcr |= (vmcrp->cbpr << ICH_VMCR_CBPR_SHIFT) & ICH_VMCR_CBPR_MASK;
+       vmcr |= (vmcrp->eoim << ICH_VMCR_EOIM_SHIFT) & ICH_VMCR_EOIM_MASK;
        vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK;
        vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK;
        vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK;
@@ -180,17 +189,27 @@ void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 {
        struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
+       u32 model = vcpu->kvm->arch.vgic.vgic_model;
        u32 vmcr;
 
        vmcr = cpu_if->vgic_vmcr;
 
-       /*
-        * Ignore the FIQen bit, because GIC emulation always implies
-        * SRE=1 which means the vFIQEn bit is also RES1.
-        */
-       vmcrp->ctlr = ((vmcr >> ICH_VMCR_EOIM_SHIFT) <<
-                       ICC_CTLR_EL1_EOImode_SHIFT) & ICC_CTLR_EL1_EOImode_MASK;
-       vmcrp->ctlr |= (vmcr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT;
+       if (model == KVM_DEV_TYPE_ARM_VGIC_V2) {
+               vmcrp->ackctl = (vmcr & ICH_VMCR_ACK_CTL_MASK) >>
+                       ICH_VMCR_ACK_CTL_SHIFT;
+               vmcrp->fiqen = (vmcr & ICH_VMCR_FIQ_EN_MASK) >>
+                       ICH_VMCR_FIQ_EN_SHIFT;
+       } else {
+               /*
+                * When emulating GICv3 on GICv3 with SRE=1 on the
+                * VFIQEn bit is RES1 and the VAckCtl bit is RES0.
+                */
+               vmcrp->fiqen = 1;
+               vmcrp->ackctl = 0;
+       }
+
+       vmcrp->cbpr = (vmcr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT;
+       vmcrp->eoim = (vmcr & ICH_VMCR_EOIM_MASK) >> ICH_VMCR_EOIM_SHIFT;
        vmcrp->abpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
        vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
        vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;