KVM: SVM: Exit to userspace if write to cr8 and not using in-kernel apic
[deliverable/linux.git] / drivers / kvm / svm.c
index 87072c647f286207c45e047630a06a91ec8cd3be..442ca818c5a9f562983a28254dbd1bab351712f8 100644 (file)
@@ -207,30 +207,6 @@ static bool svm_exception_injected(struct kvm_vcpu *vcpu)
        return !(svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID);
 }
 
-static void svm_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code)
-{
-       struct vcpu_svm *svm = to_svm(vcpu);
-
-       svm->vmcb->control.event_inj =          SVM_EVTINJ_VALID |
-                                               SVM_EVTINJ_VALID_ERR |
-                                               SVM_EVTINJ_TYPE_EXEPT |
-                                               GP_VECTOR;
-       svm->vmcb->control.event_inj_err = error_code;
-}
-
-static void inject_ud(struct kvm_vcpu *vcpu)
-{
-       to_svm(vcpu)->vmcb->control.event_inj = SVM_EVTINJ_VALID |
-                                               SVM_EVTINJ_TYPE_EXEPT |
-                                               UD_VECTOR;
-}
-
-static int is_page_fault(uint32_t info)
-{
-       info &= SVM_EVTINJ_VEC_MASK | SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
-       return info == (PF_VECTOR | SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_EXEPT);
-}
-
 static int is_external_interrupt(u32 info)
 {
        info &= SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
@@ -473,11 +449,13 @@ static void init_vmcb(struct vmcb *vmcb)
 
        control->intercept_cr_read =    INTERCEPT_CR0_MASK |
                                        INTERCEPT_CR3_MASK |
-                                       INTERCEPT_CR4_MASK;
+                                       INTERCEPT_CR4_MASK |
+                                       INTERCEPT_CR8_MASK;
 
        control->intercept_cr_write =   INTERCEPT_CR0_MASK |
                                        INTERCEPT_CR3_MASK |
-                                       INTERCEPT_CR4_MASK;
+                                       INTERCEPT_CR4_MASK |
+                                       INTERCEPT_CR8_MASK;
 
        control->intercept_dr_read =    INTERCEPT_DR0_MASK |
                                        INTERCEPT_DR1_MASK |
@@ -965,8 +943,7 @@ static int ud_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
 
        er = emulate_instruction(&svm->vcpu, kvm_run, 0, 0, 0);
        if (er != EMULATE_DONE)
-               inject_ud(&svm->vcpu);
-
+               kvm_queue_exception(&svm->vcpu, UD_VECTOR);
        return 1;
 }
 
@@ -1044,7 +1021,7 @@ static int vmmcall_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
 static int invalid_op_interception(struct vcpu_svm *svm,
                                   struct kvm_run *kvm_run)
 {
-       inject_ud(&svm->vcpu);
+       kvm_queue_exception(&svm->vcpu, UD_VECTOR);
        return 1;
 }
 
@@ -1071,6 +1048,15 @@ static int emulate_on_interception(struct vcpu_svm *svm,
        return 1;
 }
 
+static int cr8_write_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
+{
+       emulate_instruction(&svm->vcpu, NULL, 0, 0, 0);
+       if (irqchip_in_kernel(svm->vcpu.kvm))
+               return 1;
+       kvm_run->exit_reason = KVM_EXIT_SET_TPR;
+       return 0;
+}
+
 static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
@@ -1121,7 +1107,7 @@ static int rdmsr_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
        u64 data;
 
        if (svm_get_msr(&svm->vcpu, ecx, &data))
-               svm_inject_gp(&svm->vcpu, 0);
+               kvm_inject_gp(&svm->vcpu, 0);
        else {
                svm->vmcb->save.rax = data & 0xffffffff;
                svm->vcpu.regs[VCPU_REGS_RDX] = data >> 32;
@@ -1182,7 +1168,7 @@ static int wrmsr_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
                | ((u64)(svm->vcpu.regs[VCPU_REGS_RDX] & -1u) << 32);
        svm->next_rip = svm->vmcb->save.rip + 2;
        if (svm_set_msr(&svm->vcpu, ecx, data))
-               svm_inject_gp(&svm->vcpu, 0);
+               kvm_inject_gp(&svm->vcpu, 0);
        else
                skip_emulated_instruction(&svm->vcpu);
        return 1;
@@ -1220,10 +1206,12 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm,
        [SVM_EXIT_READ_CR0]                     = emulate_on_interception,
        [SVM_EXIT_READ_CR3]                     = emulate_on_interception,
        [SVM_EXIT_READ_CR4]                     = emulate_on_interception,
+       [SVM_EXIT_READ_CR8]                     = emulate_on_interception,
        /* for now: */
        [SVM_EXIT_WRITE_CR0]                    = emulate_on_interception,
        [SVM_EXIT_WRITE_CR3]                    = emulate_on_interception,
        [SVM_EXIT_WRITE_CR4]                    = emulate_on_interception,
+       [SVM_EXIT_WRITE_CR8]                    = cr8_write_interception,
        [SVM_EXIT_READ_DR0]                     = emulate_on_interception,
        [SVM_EXIT_READ_DR1]                     = emulate_on_interception,
        [SVM_EXIT_READ_DR2]                     = emulate_on_interception,
@@ -1624,34 +1612,6 @@ static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root)
        }
 }
 
-static void svm_inject_page_fault(struct kvm_vcpu *vcpu,
-                                 unsigned long  addr,
-                                 uint32_t err_code)
-{
-       struct vcpu_svm *svm = to_svm(vcpu);
-       uint32_t exit_int_info = svm->vmcb->control.exit_int_info;
-
-       ++vcpu->stat.pf_guest;
-
-       if (is_page_fault(exit_int_info)) {
-
-               svm->vmcb->control.event_inj_err = 0;
-               svm->vmcb->control.event_inj =  SVM_EVTINJ_VALID |
-                                               SVM_EVTINJ_VALID_ERR |
-                                               SVM_EVTINJ_TYPE_EXEPT |
-                                               DF_VECTOR;
-               return;
-       }
-       vcpu->cr2 = addr;
-       svm->vmcb->save.cr2 = addr;
-       svm->vmcb->control.event_inj =  SVM_EVTINJ_VALID |
-                                       SVM_EVTINJ_VALID_ERR |
-                                       SVM_EVTINJ_TYPE_EXEPT |
-                                       PF_VECTOR;
-       svm->vmcb->control.event_inj_err = err_code;
-}
-
-
 static int is_disabled(void)
 {
        u64 vm_cr;
@@ -1721,9 +1681,6 @@ static struct kvm_x86_ops svm_x86_ops = {
        .set_rflags = svm_set_rflags,
 
        .tlb_flush = svm_flush_tlb,
-       .inject_page_fault = svm_inject_page_fault,
-
-       .inject_gp = svm_inject_gp,
 
        .run = svm_vcpu_run,
        .handle_exit = handle_exit,
This page took 0.027974 seconds and 5 git commands to generate.