Skip to content

Commit

Permalink
arm64: KVM: Inject a vSerror if detecting a bad GICV access at EL2
Browse files Browse the repository at this point in the history
If, when proxying a GICV access at EL2, we detect that the guest is
doing something silly, report an EL1 SError instead ofgnoring the
access.

Signed-off-by: Marc Zyngier <[email protected]>
Signed-off-by: Christoffer Dall <[email protected]>
  • Loading branch information
Marc Zyngier authored and chazy committed Sep 8, 2016
1 parent 21977a4 commit 3272f0d
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 9 deletions.
2 changes: 1 addition & 1 deletion arch/arm64/include/asm/kvm_hyp.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ typeof(orig) * __hyp_text fname(void) \

void __vgic_v2_save_state(struct kvm_vcpu *vcpu);
void __vgic_v2_restore_state(struct kvm_vcpu *vcpu);
bool __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);

void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
void __vgic_v3_restore_state(struct kvm_vcpu *vcpu);
Expand Down
18 changes: 15 additions & 3 deletions arch/arm64/kvm/hyp/switch.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,21 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
!kvm_vcpu_dabt_isextabt(vcpu) &&
!kvm_vcpu_dabt_iss1tw(vcpu);

if (valid && __vgic_v2_perform_cpuif_access(vcpu)) {
__skip_instr(vcpu);
goto again;
if (valid) {
int ret = __vgic_v2_perform_cpuif_access(vcpu);

if (ret == 1) {
__skip_instr(vcpu);
goto again;
}

if (ret == -1) {
/* Promote an illegal access to an SError */
__skip_instr(vcpu);
exit_code = ARM_EXCEPTION_EL1_SERROR;
}

/* 0 falls through to be handler out of EL2 */
}
}

Expand Down
21 changes: 16 additions & 5 deletions virt/kvm/arm/hyp/vgic-v2-sr.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,18 @@ void __hyp_text __vgic_v2_restore_state(struct kvm_vcpu *vcpu)
}

#ifdef CONFIG_ARM64
bool __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
/*
* __vgic_v2_perform_cpuif_access -- perform a GICV access on behalf of the
* guest.
*
* @vcpu: the offending vcpu
*
* Returns:
* 1: GICV access successfully performed
* 0: Not a GICV access
* -1: Illegal GICV access
*/
int __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
{
struct kvm *kvm = kern_hyp_va(vcpu->kvm);
struct vgic_dist *vgic = &kvm->arch.vgic;
Expand All @@ -185,15 +196,15 @@ bool __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
/* If not for GICV, move on */
if (fault_ipa < vgic->vgic_cpu_base ||
fault_ipa >= (vgic->vgic_cpu_base + KVM_VGIC_V2_CPU_SIZE))
return false;
return 0;

/* Reject anything but a 32bit access */
if (kvm_vcpu_dabt_get_as(vcpu) != sizeof(u32))
return false;
return -1;

/* Not aligned? Don't bother */
if (fault_ipa & 3)
return false;
return -1;

rd = kvm_vcpu_dabt_get_rd(vcpu);
addr = kern_hyp_va((kern_hyp_va(&kvm_vgic_global_state))->vcpu_base_va);
Expand All @@ -210,6 +221,6 @@ bool __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
sizeof(u32)));
}

return true;
return 1;
}
#endif

0 comments on commit 3272f0d

Please sign in to comment.