aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEddie Dong <eddie.dong@intel.com>2009-11-19 10:54:07 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2010-03-01 10:35:38 -0500
commit3fd28fce765632d0fe46b31f63c0e7a7ec6c6b79 (patch)
tree0f73abea5061ce2d0c9a7fe744ac0cf4e882d687
parent30ff056c42c665b9ea535d8515890857ae382540 (diff)
KVM: x86: make double/triple fault promotion generic to all exceptions
Move Double-Fault generation logic out of page fault exception generating function to cover more generic case. Signed-off-by: Eddie Dong <eddie.dong@intel.com> Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r--arch/x86/kvm/x86.c89
1 files changed, 61 insertions, 28 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index a1e1bc9d412d..8d860e0301a0 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -257,12 +257,68 @@ void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data)
257} 257}
258EXPORT_SYMBOL_GPL(kvm_set_apic_base); 258EXPORT_SYMBOL_GPL(kvm_set_apic_base);
259 259
260#define EXCPT_BENIGN 0
261#define EXCPT_CONTRIBUTORY 1
262#define EXCPT_PF 2
263
264static int exception_class(int vector)
265{
266 switch (vector) {
267 case PF_VECTOR:
268 return EXCPT_PF;
269 case DE_VECTOR:
270 case TS_VECTOR:
271 case NP_VECTOR:
272 case SS_VECTOR:
273 case GP_VECTOR:
274 return EXCPT_CONTRIBUTORY;
275 default:
276 break;
277 }
278 return EXCPT_BENIGN;
279}
280
281static void kvm_multiple_exception(struct kvm_vcpu *vcpu,
282 unsigned nr, bool has_error, u32 error_code)
283{
284 u32 prev_nr;
285 int class1, class2;
286
287 if (!vcpu->arch.exception.pending) {
288 queue:
289 vcpu->arch.exception.pending = true;
290 vcpu->arch.exception.has_error_code = has_error;
291 vcpu->arch.exception.nr = nr;
292 vcpu->arch.exception.error_code = error_code;
293 return;
294 }
295
296 /* to check exception */
297 prev_nr = vcpu->arch.exception.nr;
298 if (prev_nr == DF_VECTOR) {
299 /* triple fault -> shutdown */
300 set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests);
301 return;
302 }
303 class1 = exception_class(prev_nr);
304 class2 = exception_class(nr);
305 if ((class1 == EXCPT_CONTRIBUTORY && class2 == EXCPT_CONTRIBUTORY)
306 || (class1 == EXCPT_PF && class2 != EXCPT_BENIGN)) {
307 /* generate double fault per SDM Table 5-5 */
308 vcpu->arch.exception.pending = true;
309 vcpu->arch.exception.has_error_code = true;
310 vcpu->arch.exception.nr = DF_VECTOR;
311 vcpu->arch.exception.error_code = 0;
312 } else
313 /* replace previous exception with a new one in a hope
314 that instruction re-execution will regenerate lost
315 exception */
316 goto queue;
317}
318
260void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr) 319void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr)
261{ 320{
262 WARN_ON(vcpu->arch.exception.pending); 321 kvm_multiple_exception(vcpu, nr, false, 0);
263 vcpu->arch.exception.pending = true;
264 vcpu->arch.exception.has_error_code = false;
265 vcpu->arch.exception.nr = nr;
266} 322}
267EXPORT_SYMBOL_GPL(kvm_queue_exception); 323EXPORT_SYMBOL_GPL(kvm_queue_exception);
268 324
@@ -270,25 +326,6 @@ void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long addr,
270 u32 error_code) 326 u32 error_code)
271{ 327{
272 ++vcpu->stat.pf_guest; 328 ++vcpu->stat.pf_guest;
273
274 if (vcpu->arch.exception.pending) {
275 switch(vcpu->arch.exception.nr) {
276 case DF_VECTOR:
277 /* triple fault -> shutdown */
278 set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests);
279 return;
280 case PF_VECTOR:
281 vcpu->arch.exception.nr = DF_VECTOR;
282 vcpu->arch.exception.error_code = 0;
283 return;
284 default:
285 /* replace previous exception with a new one in a hope
286 that instruction re-execution will regenerate lost
287 exception */
288 vcpu->arch.exception.pending = false;
289 break;
290 }
291 }
292 vcpu->arch.cr2 = addr; 329 vcpu->arch.cr2 = addr;
293 kvm_queue_exception_e(vcpu, PF_VECTOR, error_code); 330 kvm_queue_exception_e(vcpu, PF_VECTOR, error_code);
294} 331}
@@ -301,11 +338,7 @@ EXPORT_SYMBOL_GPL(kvm_inject_nmi);
301 338
302void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code) 339void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code)
303{ 340{
304 WARN_ON(vcpu->arch.exception.pending); 341 kvm_multiple_exception(vcpu, nr, true, error_code);
305 vcpu->arch.exception.pending = true;
306 vcpu->arch.exception.has_error_code = true;
307 vcpu->arch.exception.nr = nr;
308 vcpu->arch.exception.error_code = error_code;
309} 342}
310EXPORT_SYMBOL_GPL(kvm_queue_exception_e); 343EXPORT_SYMBOL_GPL(kvm_queue_exception_e);
311 344