0001
0002
0003
0004
0005
0006
0007 #include <hyp/adjust_pc.h>
0008
0009 #include <linux/compiler.h>
0010 #include <linux/irqchip/arm-gic.h>
0011 #include <linux/kvm_host.h>
0012 #include <linux/swab.h>
0013
0014 #include <asm/kvm_emulate.h>
0015 #include <asm/kvm_hyp.h>
0016 #include <asm/kvm_mmu.h>
0017
0018 static bool __is_be(struct kvm_vcpu *vcpu)
0019 {
0020 if (vcpu_mode_is_32bit(vcpu))
0021 return !!(read_sysreg_el2(SYS_SPSR) & PSR_AA32_E_BIT);
0022
0023 return !!(read_sysreg(SCTLR_EL1) & SCTLR_ELx_EE);
0024 }
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
0038 {
0039 struct kvm *kvm = kern_hyp_va(vcpu->kvm);
0040 struct vgic_dist *vgic = &kvm->arch.vgic;
0041 phys_addr_t fault_ipa;
0042 void __iomem *addr;
0043 int rd;
0044
0045
0046 fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
0047 fault_ipa |= kvm_vcpu_get_hfar(vcpu) & GENMASK(11, 0);
0048
0049
0050 if (fault_ipa < vgic->vgic_cpu_base ||
0051 fault_ipa >= (vgic->vgic_cpu_base + KVM_VGIC_V2_CPU_SIZE))
0052 return 0;
0053
0054
0055 if (kvm_vcpu_dabt_get_as(vcpu) != sizeof(u32)) {
0056 __kvm_skip_instr(vcpu);
0057 return -1;
0058 }
0059
0060
0061 if (fault_ipa & 3) {
0062 __kvm_skip_instr(vcpu);
0063 return -1;
0064 }
0065
0066 rd = kvm_vcpu_dabt_get_rd(vcpu);
0067 addr = kvm_vgic_global_state.vcpu_hyp_va;
0068 addr += fault_ipa - vgic->vgic_cpu_base;
0069
0070 if (kvm_vcpu_dabt_iswrite(vcpu)) {
0071 u32 data = vcpu_get_reg(vcpu, rd);
0072 if (__is_be(vcpu)) {
0073
0074 data = __kvm_swab32(data);
0075 }
0076 writel_relaxed(data, addr);
0077 } else {
0078 u32 data = readl_relaxed(addr);
0079 if (__is_be(vcpu)) {
0080
0081 data = __kvm_swab32(data);
0082 }
0083 vcpu_set_reg(vcpu, rd, data);
0084 }
0085
0086 __kvm_skip_instr(vcpu);
0087
0088 return 1;
0089 }