aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kvm
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2016-01-13 14:02:51 -0500
committerMarc Zyngier <marc.zyngier@arm.com>2016-02-29 13:34:14 -0500
commit97e964371377ebf3958701b082597c2162e3df18 (patch)
treeebbded37b4a0bcacd16d38401aaa1c2486ac73c4 /arch/arm/kvm
parent9dddc2dfa5da95fa380635d400f80767077ef936 (diff)
ARM: KVM: Add populating of fault data structure
On guest exit, we must take care of populating our fault data structure so that the host code can handle it. This includes resolving the IPA for permission faults, which can result in restarting the guest. Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'arch/arm/kvm')
-rw-r--r--arch/arm/kvm/hyp/hyp.h4
-rw-r--r--arch/arm/kvm/hyp/switch.c54
2 files changed, 58 insertions, 0 deletions
diff --git a/arch/arm/kvm/hyp/hyp.h b/arch/arm/kvm/hyp/hyp.h
index ef582c9ad96d..8b1156b691ff 100644
--- a/arch/arm/kvm/hyp/hyp.h
+++ b/arch/arm/kvm/hyp/hyp.h
@@ -76,10 +76,14 @@
76#define IFSR __ACCESS_CP15(c5, 0, c0, 1) 76#define IFSR __ACCESS_CP15(c5, 0, c0, 1)
77#define ADFSR __ACCESS_CP15(c5, 0, c1, 0) 77#define ADFSR __ACCESS_CP15(c5, 0, c1, 0)
78#define AIFSR __ACCESS_CP15(c5, 0, c1, 1) 78#define AIFSR __ACCESS_CP15(c5, 0, c1, 1)
79#define HSR __ACCESS_CP15(c5, 4, c2, 0)
79#define DFAR __ACCESS_CP15(c6, 0, c0, 0) 80#define DFAR __ACCESS_CP15(c6, 0, c0, 0)
80#define IFAR __ACCESS_CP15(c6, 0, c0, 2) 81#define IFAR __ACCESS_CP15(c6, 0, c0, 2)
81#define HDFAR __ACCESS_CP15(c6, 4, c0, 0) 82#define HDFAR __ACCESS_CP15(c6, 4, c0, 0)
83#define HIFAR __ACCESS_CP15(c6, 4, c0, 2)
84#define HPFAR __ACCESS_CP15(c6, 4, c0, 4)
82#define ICIALLUIS __ACCESS_CP15(c7, 0, c1, 0) 85#define ICIALLUIS __ACCESS_CP15(c7, 0, c1, 0)
86#define ATS1CPR __ACCESS_CP15(c7, 0, c8, 0)
83#define TLBIALLIS __ACCESS_CP15(c8, 0, c3, 0) 87#define TLBIALLIS __ACCESS_CP15(c8, 0, c3, 0)
84#define TLBIALLNSNHIS __ACCESS_CP15(c8, 4, c3, 4) 88#define TLBIALLNSNHIS __ACCESS_CP15(c8, 4, c3, 4)
85#define PRRR __ACCESS_CP15(c10, 0, c2, 0) 89#define PRRR __ACCESS_CP15(c10, 0, c2, 0)
diff --git a/arch/arm/kvm/hyp/switch.c b/arch/arm/kvm/hyp/switch.c
index a1f3c1cf8f74..0dd0ba33b8a7 100644
--- a/arch/arm/kvm/hyp/switch.c
+++ b/arch/arm/kvm/hyp/switch.c
@@ -84,6 +84,56 @@ static void __hyp_text __vgic_restore_state(struct kvm_vcpu *vcpu)
84 __vgic_v2_restore_state(vcpu); 84 __vgic_v2_restore_state(vcpu);
85} 85}
86 86
87static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu)
88{
89 u32 hsr = read_sysreg(HSR);
90 u8 ec = hsr >> HSR_EC_SHIFT;
91 u32 hpfar, far;
92
93 vcpu->arch.fault.hsr = hsr;
94
95 if (ec == HSR_EC_IABT)
96 far = read_sysreg(HIFAR);
97 else if (ec == HSR_EC_DABT)
98 far = read_sysreg(HDFAR);
99 else
100 return true;
101
102 /*
103 * B3.13.5 Reporting exceptions taken to the Non-secure PL2 mode:
104 *
105 * Abort on the stage 2 translation for a memory access from a
106 * Non-secure PL1 or PL0 mode:
107 *
108 * For any Access flag fault or Translation fault, and also for any
109 * Permission fault on the stage 2 translation of a memory access
110 * made as part of a translation table walk for a stage 1 translation,
111 * the HPFAR holds the IPA that caused the fault. Otherwise, the HPFAR
112 * is UNKNOWN.
113 */
114 if (!(hsr & HSR_DABT_S1PTW) && (hsr & HSR_FSC_TYPE) == FSC_PERM) {
115 u64 par, tmp;
116
117 par = read_sysreg(PAR);
118 write_sysreg(far, ATS1CPR);
119 isb();
120
121 tmp = read_sysreg(PAR);
122 write_sysreg(par, PAR);
123
124 if (unlikely(tmp & 1))
125 return false; /* Translation failed, back to guest */
126
127 hpfar = ((tmp >> 12) & ((1UL << 28) - 1)) << 4;
128 } else {
129 hpfar = read_sysreg(HPFAR);
130 }
131
132 vcpu->arch.fault.hxfar = far;
133 vcpu->arch.fault.hpfar = hpfar;
134 return true;
135}
136
87static int __hyp_text __guest_run(struct kvm_vcpu *vcpu) 137static int __hyp_text __guest_run(struct kvm_vcpu *vcpu)
88{ 138{
89 struct kvm_cpu_context *host_ctxt; 139 struct kvm_cpu_context *host_ctxt;
@@ -111,9 +161,13 @@ static int __hyp_text __guest_run(struct kvm_vcpu *vcpu)
111 __banked_restore_state(guest_ctxt); 161 __banked_restore_state(guest_ctxt);
112 162
113 /* Jump in the fire! */ 163 /* Jump in the fire! */
164again:
114 exit_code = __guest_enter(vcpu, host_ctxt); 165 exit_code = __guest_enter(vcpu, host_ctxt);
115 /* And we're baaack! */ 166 /* And we're baaack! */
116 167
168 if (exit_code == ARM_EXCEPTION_HVC && !__populate_fault_info(vcpu))
169 goto again;
170
117 fp_enabled = __vfp_enabled(); 171 fp_enabled = __vfp_enabled();
118 172
119 __banked_save_state(guest_ctxt); 173 __banked_save_state(guest_ctxt);