Skip to content

Commit bf8feb3

Browse files
Marc Zyngierchazy
authored andcommitted
arm64: KVM: vgic-v2: Add GICV access from HYP
Now that we have the necessary infrastructure to handle MMIO accesses in HYP, perform the GICV access on behalf of the guest. This requires checking that the access is strictly 32bit, properly aligned, and falls within the expected range. When all condition are satisfied, we perform the access and tell the rest of the HYP code that the instruction has been correctly emulated. Reviewed-by: Christoffer Dall <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Signed-off-by: Christoffer Dall <[email protected]>
1 parent fb5ee36 commit bf8feb3

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

include/kvm/arm_vgic.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ struct vgic_global {
5050
/* Physical address of vgic virtual cpu interface */
5151
phys_addr_t vcpu_base;
5252

53+
/* GICV mapping */
54+
void __iomem *vcpu_base_va;
55+
5356
/* virtual control interface mapping */
5457
void __iomem *vctrl_base;
5558

virt/kvm/arm/hyp/vgic-v2-sr.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/irqchip/arm-gic.h>
2020
#include <linux/kvm_host.h>
2121

22+
#include <asm/kvm_emulate.h>
2223
#include <asm/kvm_hyp.h>
2324

2425
static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
@@ -171,6 +172,44 @@ void __hyp_text __vgic_v2_restore_state(struct kvm_vcpu *vcpu)
171172
#ifdef CONFIG_ARM64
172173
bool __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
173174
{
175+
struct kvm *kvm = kern_hyp_va(vcpu->kvm);
176+
struct vgic_dist *vgic = &kvm->arch.vgic;
177+
phys_addr_t fault_ipa;
178+
void __iomem *addr;
179+
int rd;
180+
181+
/* Build the full address */
182+
fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
183+
fault_ipa |= kvm_vcpu_get_hfar(vcpu) & GENMASK(11, 0);
184+
185+
/* If not for GICV, move on */
186+
if (fault_ipa < vgic->vgic_cpu_base ||
187+
fault_ipa >= (vgic->vgic_cpu_base + KVM_VGIC_V2_CPU_SIZE))
174188
return false;
189+
190+
/* Reject anything but a 32bit access */
191+
if (kvm_vcpu_dabt_get_as(vcpu) != sizeof(u32))
192+
return false;
193+
194+
/* Not aligned? Don't bother */
195+
if (fault_ipa & 3)
196+
return false;
197+
198+
rd = kvm_vcpu_dabt_get_rd(vcpu);
199+
addr = kern_hyp_va((kern_hyp_va(&kvm_vgic_global_state))->vcpu_base_va);
200+
addr += fault_ipa - vgic->vgic_cpu_base;
201+
202+
if (kvm_vcpu_dabt_iswrite(vcpu)) {
203+
u32 data = vcpu_data_guest_to_host(vcpu,
204+
vcpu_get_reg(vcpu, rd),
205+
sizeof(u32));
206+
writel_relaxed(data, addr);
207+
} else {
208+
u32 data = readl_relaxed(addr);
209+
vcpu_set_reg(vcpu, rd, vcpu_data_host_to_guest(vcpu, data,
210+
sizeof(u32)));
211+
}
212+
213+
return true;
175214
}
176215
#endif

0 commit comments

Comments
 (0)