Loading arch/arm/include/asm/kvm_emulate.h +21 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <linux/kvm_host.h> #include <asm/kvm_asm.h> #include <asm/kvm_mmio.h> #include <asm/kvm_arm.h> unsigned long *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num); unsigned long *vcpu_spsr(struct kvm_vcpu *vcpu); Loading Loading @@ -69,4 +70,24 @@ static inline bool kvm_vcpu_reg_is_pc(struct kvm_vcpu *vcpu, int reg) return reg == 15; } static inline u32 kvm_vcpu_get_hsr(struct kvm_vcpu *vcpu) { return vcpu->arch.fault.hsr; } static inline unsigned long kvm_vcpu_get_hfar(struct kvm_vcpu *vcpu) { return vcpu->arch.fault.hxfar; } static inline phys_addr_t kvm_vcpu_get_fault_ipa(struct kvm_vcpu *vcpu) { return ((phys_addr_t)vcpu->arch.fault.hpfar & HPFAR_MASK) << 8; } static inline unsigned long kvm_vcpu_get_hyp_pc(struct kvm_vcpu *vcpu) { return vcpu->arch.fault.hyp_pc; } #endif /* __ARM_KVM_EMULATE_H__ */ arch/arm/include/asm/kvm_host.h +8 −6 Original line number Diff line number Diff line Loading @@ -80,6 +80,13 @@ struct kvm_mmu_memory_cache { void *objects[KVM_NR_MEM_OBJS]; }; struct kvm_vcpu_fault_info { u32 hsr; /* Hyp Syndrome Register */ u32 hxfar; /* Hyp Data/Inst. Fault Address Register */ u32 hpfar; /* Hyp IPA Fault Address Register */ u32 hyp_pc; /* PC when exception was taken from Hyp mode */ }; struct kvm_vcpu_arch { struct kvm_regs regs; Loading @@ -93,9 +100,7 @@ struct kvm_vcpu_arch { u32 midr; /* Exception Information */ u32 hsr; /* Hyp Syndrome Register */ u32 hxfar; /* Hyp Data/Inst Fault Address Register */ u32 hpfar; /* Hyp IPA Fault Address Register */ struct kvm_vcpu_fault_info fault; /* Floating point registers (VFP and Advanced SIMD/NEON) */ struct vfp_hard_struct vfp_guest; Loading @@ -122,9 +127,6 @@ struct kvm_vcpu_arch { /* Interrupt related fields */ u32 irq_lines; /* IRQ and FIQ levels */ /* Hyp exception information */ u32 hyp_pc; /* PC when exception was taken from Hyp mode */ /* Cache some mmu pages needed inside spinlock regions */ struct kvm_mmu_memory_cache mmu_page_cache; Loading arch/arm/kernel/asm-offsets.c +4 −4 Original line number Diff line number Diff line Loading @@ -165,10 +165,10 @@ int main(void) DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_pc)); DEFINE(VCPU_CPSR, offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_cpsr)); DEFINE(VCPU_IRQ_LINES, offsetof(struct kvm_vcpu, arch.irq_lines)); DEFINE(VCPU_HSR, offsetof(struct kvm_vcpu, arch.hsr)); DEFINE(VCPU_HxFAR, offsetof(struct kvm_vcpu, arch.hxfar)); DEFINE(VCPU_HPFAR, offsetof(struct kvm_vcpu, arch.hpfar)); DEFINE(VCPU_HYP_PC, offsetof(struct kvm_vcpu, arch.hyp_pc)); DEFINE(VCPU_HSR, offsetof(struct kvm_vcpu, arch.fault.hsr)); DEFINE(VCPU_HxFAR, offsetof(struct kvm_vcpu, arch.fault.hxfar)); DEFINE(VCPU_HPFAR, offsetof(struct kvm_vcpu, arch.fault.hpfar)); DEFINE(VCPU_HYP_PC, offsetof(struct kvm_vcpu, arch.fault.hyp_pc)); #ifdef CONFIG_KVM_ARM_VGIC DEFINE(VCPU_VGIC_CPU, offsetof(struct kvm_vcpu, arch.vgic_cpu)); DEFINE(VGIC_CPU_HCR, offsetof(struct vgic_cpu, vgic_hcr)); Loading arch/arm/kvm/arm.c +14 −14 Original line number Diff line number Diff line Loading @@ -492,7 +492,7 @@ static int handle_svc_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run) static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) { trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0), vcpu->arch.hsr & HSR_HVC_IMM_MASK); kvm_vcpu_get_hsr(vcpu) & HSR_HVC_IMM_MASK); if (kvm_psci_call(vcpu)) return 1; Loading @@ -513,16 +513,16 @@ static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) static int handle_pabt_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run) { /* The hypervisor should never cause aborts */ kvm_err("Prefetch Abort taken from Hyp mode at %#08x (HSR: %#08x)\n", vcpu->arch.hxfar, vcpu->arch.hsr); kvm_err("Prefetch Abort taken from Hyp mode at %#08lx (HSR: %#08x)\n", kvm_vcpu_get_hfar(vcpu), kvm_vcpu_get_hsr(vcpu)); return -EFAULT; } static int handle_dabt_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run) { /* This is either an error in the ws. code or an external abort */ kvm_err("Data Abort taken from Hyp mode at %#08x (HSR: %#08x)\n", vcpu->arch.hxfar, vcpu->arch.hsr); kvm_err("Data Abort taken from Hyp mode at %#08lx (HSR: %#08x)\n", kvm_vcpu_get_hfar(vcpu), kvm_vcpu_get_hsr(vcpu)); return -EFAULT; } Loading Loading @@ -559,17 +559,17 @@ static bool kvm_condition_valid(struct kvm_vcpu *vcpu) * catch undefined instructions, and then we won't get past * the arm_exit_handlers test anyway. */ BUG_ON(((vcpu->arch.hsr & HSR_EC) >> HSR_EC_SHIFT) == 0); BUG_ON(((kvm_vcpu_get_hsr(vcpu) & HSR_EC) >> HSR_EC_SHIFT) == 0); /* Top two bits non-zero? Unconditional. */ if (vcpu->arch.hsr >> 30) if (kvm_vcpu_get_hsr(vcpu) >> 30) return true; cpsr = *vcpu_cpsr(vcpu); /* Is condition field valid? */ if ((vcpu->arch.hsr & HSR_CV) >> HSR_CV_SHIFT) cond = (vcpu->arch.hsr & HSR_COND) >> HSR_COND_SHIFT; if ((kvm_vcpu_get_hsr(vcpu) & HSR_CV) >> HSR_CV_SHIFT) cond = (kvm_vcpu_get_hsr(vcpu) & HSR_COND) >> HSR_COND_SHIFT; else { /* This can happen in Thumb mode: examine IT state. */ unsigned long it; Loading Loading @@ -602,20 +602,20 @@ static int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, case ARM_EXCEPTION_IRQ: return 1; case ARM_EXCEPTION_UNDEFINED: kvm_err("Undefined exception in Hyp mode at: %#08x\n", vcpu->arch.hyp_pc); kvm_err("Undefined exception in Hyp mode at: %#08lx\n", kvm_vcpu_get_hyp_pc(vcpu)); BUG(); panic("KVM: Hypervisor undefined exception!\n"); case ARM_EXCEPTION_DATA_ABORT: case ARM_EXCEPTION_PREF_ABORT: case ARM_EXCEPTION_HVC: hsr_ec = (vcpu->arch.hsr & HSR_EC) >> HSR_EC_SHIFT; hsr_ec = (kvm_vcpu_get_hsr(vcpu) & HSR_EC) >> HSR_EC_SHIFT; if (hsr_ec >= ARRAY_SIZE(arm_exit_handlers) || !arm_exit_handlers[hsr_ec]) { kvm_err("Unkown exception class: %#08lx, " "hsr: %#08x\n", hsr_ec, (unsigned int)vcpu->arch.hsr); (unsigned int)kvm_vcpu_get_hsr(vcpu)); BUG(); } Loading @@ -624,7 +624,7 @@ static int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, * that fail their condition code check" */ if (!kvm_condition_valid(vcpu)) { bool is_wide = vcpu->arch.hsr & HSR_IL; bool is_wide = kvm_vcpu_get_hsr(vcpu) & HSR_IL; kvm_skip_instr(vcpu, is_wide); return 1; } Loading arch/arm/kvm/coproc.c +12 −12 Original line number Diff line number Diff line Loading @@ -293,7 +293,7 @@ static int emulate_cp15(struct kvm_vcpu *vcpu, if (likely(r->access(vcpu, params, r))) { /* Skip instruction, since it was emulated */ kvm_skip_instr(vcpu, (vcpu->arch.hsr >> 25) & 1); kvm_skip_instr(vcpu, (kvm_vcpu_get_hsr(vcpu) >> 25) & 1); return 1; } /* If access function fails, it should complain. */ Loading @@ -315,14 +315,14 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) { struct coproc_params params; params.CRm = (vcpu->arch.hsr >> 1) & 0xf; params.Rt1 = (vcpu->arch.hsr >> 5) & 0xf; params.is_write = ((vcpu->arch.hsr & 1) == 0); params.CRm = (kvm_vcpu_get_hsr(vcpu) >> 1) & 0xf; params.Rt1 = (kvm_vcpu_get_hsr(vcpu) >> 5) & 0xf; params.is_write = ((kvm_vcpu_get_hsr(vcpu) & 1) == 0); params.is_64bit = true; params.Op1 = (vcpu->arch.hsr >> 16) & 0xf; params.Op1 = (kvm_vcpu_get_hsr(vcpu) >> 16) & 0xf; params.Op2 = 0; params.Rt2 = (vcpu->arch.hsr >> 10) & 0xf; params.Rt2 = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf; params.CRn = 0; return emulate_cp15(vcpu, ¶ms); Loading @@ -347,14 +347,14 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) { struct coproc_params params; params.CRm = (vcpu->arch.hsr >> 1) & 0xf; params.Rt1 = (vcpu->arch.hsr >> 5) & 0xf; params.is_write = ((vcpu->arch.hsr & 1) == 0); params.CRm = (kvm_vcpu_get_hsr(vcpu) >> 1) & 0xf; params.Rt1 = (kvm_vcpu_get_hsr(vcpu) >> 5) & 0xf; params.is_write = ((kvm_vcpu_get_hsr(vcpu) & 1) == 0); params.is_64bit = false; params.CRn = (vcpu->arch.hsr >> 10) & 0xf; params.Op1 = (vcpu->arch.hsr >> 14) & 0x7; params.Op2 = (vcpu->arch.hsr >> 17) & 0x7; params.CRn = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf; params.Op1 = (kvm_vcpu_get_hsr(vcpu) >> 14) & 0x7; params.Op2 = (kvm_vcpu_get_hsr(vcpu) >> 17) & 0x7; params.Rt2 = 0; return emulate_cp15(vcpu, ¶ms); Loading Loading
arch/arm/include/asm/kvm_emulate.h +21 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <linux/kvm_host.h> #include <asm/kvm_asm.h> #include <asm/kvm_mmio.h> #include <asm/kvm_arm.h> unsigned long *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num); unsigned long *vcpu_spsr(struct kvm_vcpu *vcpu); Loading Loading @@ -69,4 +70,24 @@ static inline bool kvm_vcpu_reg_is_pc(struct kvm_vcpu *vcpu, int reg) return reg == 15; } static inline u32 kvm_vcpu_get_hsr(struct kvm_vcpu *vcpu) { return vcpu->arch.fault.hsr; } static inline unsigned long kvm_vcpu_get_hfar(struct kvm_vcpu *vcpu) { return vcpu->arch.fault.hxfar; } static inline phys_addr_t kvm_vcpu_get_fault_ipa(struct kvm_vcpu *vcpu) { return ((phys_addr_t)vcpu->arch.fault.hpfar & HPFAR_MASK) << 8; } static inline unsigned long kvm_vcpu_get_hyp_pc(struct kvm_vcpu *vcpu) { return vcpu->arch.fault.hyp_pc; } #endif /* __ARM_KVM_EMULATE_H__ */
arch/arm/include/asm/kvm_host.h +8 −6 Original line number Diff line number Diff line Loading @@ -80,6 +80,13 @@ struct kvm_mmu_memory_cache { void *objects[KVM_NR_MEM_OBJS]; }; struct kvm_vcpu_fault_info { u32 hsr; /* Hyp Syndrome Register */ u32 hxfar; /* Hyp Data/Inst. Fault Address Register */ u32 hpfar; /* Hyp IPA Fault Address Register */ u32 hyp_pc; /* PC when exception was taken from Hyp mode */ }; struct kvm_vcpu_arch { struct kvm_regs regs; Loading @@ -93,9 +100,7 @@ struct kvm_vcpu_arch { u32 midr; /* Exception Information */ u32 hsr; /* Hyp Syndrome Register */ u32 hxfar; /* Hyp Data/Inst Fault Address Register */ u32 hpfar; /* Hyp IPA Fault Address Register */ struct kvm_vcpu_fault_info fault; /* Floating point registers (VFP and Advanced SIMD/NEON) */ struct vfp_hard_struct vfp_guest; Loading @@ -122,9 +127,6 @@ struct kvm_vcpu_arch { /* Interrupt related fields */ u32 irq_lines; /* IRQ and FIQ levels */ /* Hyp exception information */ u32 hyp_pc; /* PC when exception was taken from Hyp mode */ /* Cache some mmu pages needed inside spinlock regions */ struct kvm_mmu_memory_cache mmu_page_cache; Loading
arch/arm/kernel/asm-offsets.c +4 −4 Original line number Diff line number Diff line Loading @@ -165,10 +165,10 @@ int main(void) DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_pc)); DEFINE(VCPU_CPSR, offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_cpsr)); DEFINE(VCPU_IRQ_LINES, offsetof(struct kvm_vcpu, arch.irq_lines)); DEFINE(VCPU_HSR, offsetof(struct kvm_vcpu, arch.hsr)); DEFINE(VCPU_HxFAR, offsetof(struct kvm_vcpu, arch.hxfar)); DEFINE(VCPU_HPFAR, offsetof(struct kvm_vcpu, arch.hpfar)); DEFINE(VCPU_HYP_PC, offsetof(struct kvm_vcpu, arch.hyp_pc)); DEFINE(VCPU_HSR, offsetof(struct kvm_vcpu, arch.fault.hsr)); DEFINE(VCPU_HxFAR, offsetof(struct kvm_vcpu, arch.fault.hxfar)); DEFINE(VCPU_HPFAR, offsetof(struct kvm_vcpu, arch.fault.hpfar)); DEFINE(VCPU_HYP_PC, offsetof(struct kvm_vcpu, arch.fault.hyp_pc)); #ifdef CONFIG_KVM_ARM_VGIC DEFINE(VCPU_VGIC_CPU, offsetof(struct kvm_vcpu, arch.vgic_cpu)); DEFINE(VGIC_CPU_HCR, offsetof(struct vgic_cpu, vgic_hcr)); Loading
arch/arm/kvm/arm.c +14 −14 Original line number Diff line number Diff line Loading @@ -492,7 +492,7 @@ static int handle_svc_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run) static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) { trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0), vcpu->arch.hsr & HSR_HVC_IMM_MASK); kvm_vcpu_get_hsr(vcpu) & HSR_HVC_IMM_MASK); if (kvm_psci_call(vcpu)) return 1; Loading @@ -513,16 +513,16 @@ static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) static int handle_pabt_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run) { /* The hypervisor should never cause aborts */ kvm_err("Prefetch Abort taken from Hyp mode at %#08x (HSR: %#08x)\n", vcpu->arch.hxfar, vcpu->arch.hsr); kvm_err("Prefetch Abort taken from Hyp mode at %#08lx (HSR: %#08x)\n", kvm_vcpu_get_hfar(vcpu), kvm_vcpu_get_hsr(vcpu)); return -EFAULT; } static int handle_dabt_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run) { /* This is either an error in the ws. code or an external abort */ kvm_err("Data Abort taken from Hyp mode at %#08x (HSR: %#08x)\n", vcpu->arch.hxfar, vcpu->arch.hsr); kvm_err("Data Abort taken from Hyp mode at %#08lx (HSR: %#08x)\n", kvm_vcpu_get_hfar(vcpu), kvm_vcpu_get_hsr(vcpu)); return -EFAULT; } Loading Loading @@ -559,17 +559,17 @@ static bool kvm_condition_valid(struct kvm_vcpu *vcpu) * catch undefined instructions, and then we won't get past * the arm_exit_handlers test anyway. */ BUG_ON(((vcpu->arch.hsr & HSR_EC) >> HSR_EC_SHIFT) == 0); BUG_ON(((kvm_vcpu_get_hsr(vcpu) & HSR_EC) >> HSR_EC_SHIFT) == 0); /* Top two bits non-zero? Unconditional. */ if (vcpu->arch.hsr >> 30) if (kvm_vcpu_get_hsr(vcpu) >> 30) return true; cpsr = *vcpu_cpsr(vcpu); /* Is condition field valid? */ if ((vcpu->arch.hsr & HSR_CV) >> HSR_CV_SHIFT) cond = (vcpu->arch.hsr & HSR_COND) >> HSR_COND_SHIFT; if ((kvm_vcpu_get_hsr(vcpu) & HSR_CV) >> HSR_CV_SHIFT) cond = (kvm_vcpu_get_hsr(vcpu) & HSR_COND) >> HSR_COND_SHIFT; else { /* This can happen in Thumb mode: examine IT state. */ unsigned long it; Loading Loading @@ -602,20 +602,20 @@ static int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, case ARM_EXCEPTION_IRQ: return 1; case ARM_EXCEPTION_UNDEFINED: kvm_err("Undefined exception in Hyp mode at: %#08x\n", vcpu->arch.hyp_pc); kvm_err("Undefined exception in Hyp mode at: %#08lx\n", kvm_vcpu_get_hyp_pc(vcpu)); BUG(); panic("KVM: Hypervisor undefined exception!\n"); case ARM_EXCEPTION_DATA_ABORT: case ARM_EXCEPTION_PREF_ABORT: case ARM_EXCEPTION_HVC: hsr_ec = (vcpu->arch.hsr & HSR_EC) >> HSR_EC_SHIFT; hsr_ec = (kvm_vcpu_get_hsr(vcpu) & HSR_EC) >> HSR_EC_SHIFT; if (hsr_ec >= ARRAY_SIZE(arm_exit_handlers) || !arm_exit_handlers[hsr_ec]) { kvm_err("Unkown exception class: %#08lx, " "hsr: %#08x\n", hsr_ec, (unsigned int)vcpu->arch.hsr); (unsigned int)kvm_vcpu_get_hsr(vcpu)); BUG(); } Loading @@ -624,7 +624,7 @@ static int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, * that fail their condition code check" */ if (!kvm_condition_valid(vcpu)) { bool is_wide = vcpu->arch.hsr & HSR_IL; bool is_wide = kvm_vcpu_get_hsr(vcpu) & HSR_IL; kvm_skip_instr(vcpu, is_wide); return 1; } Loading
arch/arm/kvm/coproc.c +12 −12 Original line number Diff line number Diff line Loading @@ -293,7 +293,7 @@ static int emulate_cp15(struct kvm_vcpu *vcpu, if (likely(r->access(vcpu, params, r))) { /* Skip instruction, since it was emulated */ kvm_skip_instr(vcpu, (vcpu->arch.hsr >> 25) & 1); kvm_skip_instr(vcpu, (kvm_vcpu_get_hsr(vcpu) >> 25) & 1); return 1; } /* If access function fails, it should complain. */ Loading @@ -315,14 +315,14 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) { struct coproc_params params; params.CRm = (vcpu->arch.hsr >> 1) & 0xf; params.Rt1 = (vcpu->arch.hsr >> 5) & 0xf; params.is_write = ((vcpu->arch.hsr & 1) == 0); params.CRm = (kvm_vcpu_get_hsr(vcpu) >> 1) & 0xf; params.Rt1 = (kvm_vcpu_get_hsr(vcpu) >> 5) & 0xf; params.is_write = ((kvm_vcpu_get_hsr(vcpu) & 1) == 0); params.is_64bit = true; params.Op1 = (vcpu->arch.hsr >> 16) & 0xf; params.Op1 = (kvm_vcpu_get_hsr(vcpu) >> 16) & 0xf; params.Op2 = 0; params.Rt2 = (vcpu->arch.hsr >> 10) & 0xf; params.Rt2 = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf; params.CRn = 0; return emulate_cp15(vcpu, ¶ms); Loading @@ -347,14 +347,14 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) { struct coproc_params params; params.CRm = (vcpu->arch.hsr >> 1) & 0xf; params.Rt1 = (vcpu->arch.hsr >> 5) & 0xf; params.is_write = ((vcpu->arch.hsr & 1) == 0); params.CRm = (kvm_vcpu_get_hsr(vcpu) >> 1) & 0xf; params.Rt1 = (kvm_vcpu_get_hsr(vcpu) >> 5) & 0xf; params.is_write = ((kvm_vcpu_get_hsr(vcpu) & 1) == 0); params.is_64bit = false; params.CRn = (vcpu->arch.hsr >> 10) & 0xf; params.Op1 = (vcpu->arch.hsr >> 14) & 0x7; params.Op2 = (vcpu->arch.hsr >> 17) & 0x7; params.CRn = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf; params.Op1 = (kvm_vcpu_get_hsr(vcpu) >> 14) & 0x7; params.Op2 = (kvm_vcpu_get_hsr(vcpu) >> 17) & 0x7; params.Rt2 = 0; return emulate_cp15(vcpu, ¶ms); Loading