Gleb Natapov wrote:
>> +
>> +static int exception_class(int vector)
>> +{
>> +    if (vector == 14)
>> +            return EXCPT_PF;
>> +    else if (vector == 0 || (vector >= 10 && vector <= 13)) +               
>> return
>> EXCPT_CONTRIBUTORY; +        else
>> +            return EXCPT_BENIGN;
>> +}
>> +
> This makes double fault (8) benign exception. Surely not what you
> want. 

double fault fall into neither of above class per SDM. But it should be 
checked earlier than generating DB fault. See new updated.
>> +    /* to check exception */
>> +    prev_nr = vcpu->arch.exception.nr;
>> +    class2 = exception_class(nr);
>> +    class1 = exception_class(prev_nr);
>> +    if ((class1 == EXCPT_CONTRIBUTORY && class2 == EXCPT_CONTRIBUTORY)
>> +            || (class1 == EXCPT_PF && class2 != EXCPT_BENIGN)) {
>> +            /* generate double fault per SDM Table 5-5 */
>> +            printk(KERN_DEBUG "kvm: double fault 0x%x on 0x%x\n",
>> +                    prev_nr, nr); +         vcpu->arch.exception.pending = 
>> true;
>> +            vcpu->arch.exception.has_error_code = 1;
>> +            vcpu->arch.exception.nr = DF_VECTOR;
>> +            vcpu->arch.exception.error_code = 0;
>> +            if (prev_nr == DF_VECTOR) {
>> +                    /* triple fault -> shutdown */
>> +                    set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests); +       
>>         }
>> +    } else
>> +            printk(KERN_ERR "Exception 0x%x on 0x%x happens serially\n",
>> +                    prev_nr, nr); +}
> When two exceptions happens serially is is better to replace pending
> exception with a new one. This way the first exception (that is lost)
> will be regenerated when instruction will be re-executed.

Do you want it to be covered for now? For exception, it is easy but for IRQ, it 
needs to be pushed back.

Thx, eddie



    Move Double-Fault generation logic out of page fault
    exception generating function to cover more generic case.
    
    Signed-off-by: Eddie Dong <[email protected]>

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index ab1fdac..d0e75a2 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -162,12 +162,60 @@ void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data)
 }
 EXPORT_SYMBOL_GPL(kvm_set_apic_base);
 
+#define EXCPT_BENIGN           0
+#define EXCPT_CONTRIBUTORY     1
+#define EXCPT_PF               2
+
+static int exception_class(int vector)
+{
+       if (vector == 14)
+               return EXCPT_PF;
+       else if (vector == 0 || (vector >= 10 && vector <= 13))
+               return EXCPT_CONTRIBUTORY;
+       else
+               return EXCPT_BENIGN;
+}
+
+static void kvm_multiple_exception(struct kvm_vcpu *vcpu,
+               unsigned nr, bool has_error, u32 error_code)
+{
+       u32 prev_nr;
+       int class1, class2;
+
+       if (!vcpu->arch.exception.pending) {
+               vcpu->arch.exception.pending = true;
+               vcpu->arch.exception.has_error_code = has_error;
+               vcpu->arch.exception.nr = nr;
+               vcpu->arch.exception.error_code = error_code;
+               return;
+       }
+
+       /* to check exception */
+       prev_nr = vcpu->arch.exception.nr;
+       if (prev_nr == DF_VECTOR) {
+               /* triple fault -> shutdown */
+               set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests);
+               return;
+       }
+       class1 = exception_class(prev_nr);
+       class2 = exception_class(nr);
+       if ((class1 == EXCPT_CONTRIBUTORY && class2 == EXCPT_CONTRIBUTORY)
+               || (class1 == EXCPT_PF && class2 != EXCPT_BENIGN)) {
+               /* generate double fault per SDM Table 5-5 */
+               printk(KERN_DEBUG "kvm: double fault 0x%x on 0x%x\n",
+                       prev_nr, nr);
+               vcpu->arch.exception.pending = true;
+               vcpu->arch.exception.has_error_code = true;
+               vcpu->arch.exception.nr = DF_VECTOR;
+               vcpu->arch.exception.error_code = 0;
+       } else
+               printk(KERN_ERR "Exception 0x%x on 0x%x happens serially\n",
+                       prev_nr, nr);
+}
+
 void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr)
 {
-       WARN_ON(vcpu->arch.exception.pending);
-       vcpu->arch.exception.pending = true;
-       vcpu->arch.exception.has_error_code = false;
-       vcpu->arch.exception.nr = nr;
+       kvm_multiple_exception(vcpu, nr, false, 0);
 }
 EXPORT_SYMBOL_GPL(kvm_queue_exception);
 
@@ -176,18 +224,6 @@ void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned 
long addr,
 {
        ++vcpu->stat.pf_guest;
 
-       if (vcpu->arch.exception.pending) {
-               if (vcpu->arch.exception.nr == PF_VECTOR) {
-                       printk(KERN_DEBUG "kvm: inject_page_fault:"
-                                       " double fault 0x%lx\n", addr);
-                       vcpu->arch.exception.nr = DF_VECTOR;
-                       vcpu->arch.exception.error_code = 0;
-               } else if (vcpu->arch.exception.nr == DF_VECTOR) {
-                       /* triple fault -> shutdown */
-                       set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests);
-               }
-               return;
-       }
        vcpu->arch.cr2 = addr;
        kvm_queue_exception_e(vcpu, PF_VECTOR, error_code);
 }
@@ -200,11 +236,7 @@ EXPORT_SYMBOL_GPL(kvm_inject_nmi);
 
 void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code)
 {
-       WARN_ON(vcpu->arch.exception.pending);
-       vcpu->arch.exception.pending = true;
-       vcpu->arch.exception.has_error_code = true;
-       vcpu->arch.exception.nr = nr;
-       vcpu->arch.exception.error_code = error_code;
+       kvm_multiple_exception(vcpu, nr, true, error_code);
 }
 EXPORT_SYMBOL_GPL(kvm_queue_exception_e);
 

Attachment: irq2.patch
Description: irq2.patch

Reply via email to