KVM: x86: Rename timer function
[pandora-kernel.git] / arch / x86 / kvm / x86.c
index a465bd2..ce57cd8 100644 (file)
@@ -342,18 +342,12 @@ void kvm_inject_page_fault(struct kvm_vcpu *vcpu)
 
 void kvm_propagate_fault(struct kvm_vcpu *vcpu)
 {
-       u32 nested, error;
-
-       error   = vcpu->arch.fault.error_code;
-       nested  = error &  PFERR_NESTED_MASK;
-       error   = error & ~PFERR_NESTED_MASK;
-
-       vcpu->arch.fault.error_code = error;
-
-       if (mmu_is_nested(vcpu) && !nested)
+       if (mmu_is_nested(vcpu) && !vcpu->arch.fault.nested)
                vcpu->arch.nested_mmu.inject_page_fault(vcpu);
        else
                vcpu->arch.mmu.inject_page_fault(vcpu);
+
+       vcpu->arch.fault.nested = false;
 }
 
 void kvm_inject_nmi(struct kvm_vcpu *vcpu)
@@ -898,7 +892,7 @@ static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock)
 
        /*
         * The guest calculates current wall clock time by adding
-        * system time (updated by kvm_write_guest_time below) to the
+        * system time (updated by kvm_guest_time_update below) to the
         * wall clock specified here.  guest system time equals host
         * system time for us, thus we must fill in host boot time here.
         */
@@ -926,31 +920,35 @@ static uint32_t div_frac(uint32_t dividend, uint32_t divisor)
        return quotient;
 }
 
-static void kvm_set_time_scale(uint32_t tsc_khz, struct pvclock_vcpu_time_info *hv_clock)
+static void kvm_get_time_scale(uint32_t scaled_khz, uint32_t base_khz,
+                              s8 *pshift, u32 *pmultiplier)
 {
-       uint64_t nsecs = 1000000000LL;
+       uint64_t scaled64;
        int32_t  shift = 0;
        uint64_t tps64;
        uint32_t tps32;
 
-       tps64 = tsc_khz * 1000LL;
-       while (tps64 > nsecs*2) {
+       tps64 = base_khz * 1000LL;
+       scaled64 = scaled_khz * 1000LL;
+       while (tps64 > scaled64*2 || tps64 & 0xffffffff00000000UL) {
                tps64 >>= 1;
                shift--;
        }
 
        tps32 = (uint32_t)tps64;
-       while (tps32 <= (uint32_t)nsecs) {
-               tps32 <<= 1;
+       while (tps32 <= scaled64 || scaled64 & 0xffffffff00000000UL) {
+               if (scaled64 & 0xffffffff00000000UL || tps32 & 0x80000000)
+                       scaled64 >>= 1;
+               else
+                       tps32 <<= 1;
                shift++;
        }
 
-       hv_clock->tsc_shift = shift;
-       hv_clock->tsc_to_system_mul = div_frac(nsecs, tps32);
+       *pshift = shift;
+       *pmultiplier = div_frac(scaled64, tps32);
 
-       pr_debug("%s: tsc_khz %u, tsc_shift %d, tsc_mul %u\n",
-                __func__, tsc_khz, hv_clock->tsc_shift,
-                hv_clock->tsc_to_system_mul);
+       pr_debug("%s: base_khz %u => %u, shift %d, mul %u\n",
+                __func__, base_khz, scaled_khz, shift, *pmultiplier);
 }
 
 static inline u64 get_kernel_ns(void)
@@ -1034,7 +1032,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, u64 data)
 }
 EXPORT_SYMBOL_GPL(kvm_write_tsc);
 
-static int kvm_write_guest_time(struct kvm_vcpu *v)
+static int kvm_guest_time_update(struct kvm_vcpu *v)
 {
        unsigned long flags;
        struct kvm_vcpu_arch *vcpu = &v->arch;
@@ -1054,7 +1052,7 @@ static int kvm_write_guest_time(struct kvm_vcpu *v)
        local_irq_restore(flags);
 
        if (unlikely(this_tsc_khz == 0)) {
-               kvm_make_request(KVM_REQ_KVMCLOCK_UPDATE, v);
+               kvm_make_request(KVM_REQ_CLOCK_UPDATE, v);
                return 1;
        }
 
@@ -1090,7 +1088,9 @@ static int kvm_write_guest_time(struct kvm_vcpu *v)
        }
 
        if (unlikely(vcpu->hw_tsc_khz != this_tsc_khz)) {
-               kvm_set_time_scale(this_tsc_khz, &vcpu->hv_clock);
+               kvm_get_time_scale(NSEC_PER_SEC / 1000, this_tsc_khz,
+                                  &vcpu->hv_clock.tsc_shift,
+                                  &vcpu->hv_clock.tsc_to_system_mul);
                vcpu->hw_tsc_khz = this_tsc_khz;
        }
 
@@ -1101,6 +1101,7 @@ static int kvm_write_guest_time(struct kvm_vcpu *v)
        vcpu->hv_clock.tsc_timestamp = tsc_timestamp;
        vcpu->hv_clock.system_time = kernel_ns + v->kvm->arch.kvmclock_offset;
        vcpu->last_kernel_ns = kernel_ns;
+       vcpu->last_guest_tsc = tsc_timestamp;
        vcpu->hv_clock.flags = 0;
 
        /*
@@ -1127,7 +1128,7 @@ static int kvm_request_guest_time_update(struct kvm_vcpu *v)
 
        if (!vcpu->time_page)
                return 0;
-       kvm_make_request(KVM_REQ_KVMCLOCK_UPDATE, v);
+       kvm_make_request(KVM_REQ_CLOCK_UPDATE, v);
        return 1;
 }
 
@@ -3016,18 +3017,18 @@ static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, struct kvm_irqchip *chip)
        r = 0;
        switch (chip->chip_id) {
        case KVM_IRQCHIP_PIC_MASTER:
-               raw_spin_lock(&pic_irqchip(kvm)->lock);
+               spin_lock(&pic_irqchip(kvm)->lock);
                memcpy(&pic_irqchip(kvm)->pics[0],
                        &chip->chip.pic,
                        sizeof(struct kvm_pic_state));
-               raw_spin_unlock(&pic_irqchip(kvm)->lock);
+               spin_unlock(&pic_irqchip(kvm)->lock);
                break;
        case KVM_IRQCHIP_PIC_SLAVE:
-               raw_spin_lock(&pic_irqchip(kvm)->lock);
+               spin_lock(&pic_irqchip(kvm)->lock);
                memcpy(&pic_irqchip(kvm)->pics[1],
                        &chip->chip.pic,
                        sizeof(struct kvm_pic_state));
-               raw_spin_unlock(&pic_irqchip(kvm)->lock);
+               spin_unlock(&pic_irqchip(kvm)->lock);
                break;
        case KVM_IRQCHIP_IOAPIC:
                r = kvm_set_ioapic(kvm, &chip->chip.ioapic);
@@ -3524,7 +3525,7 @@ static gpa_t translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access)
        access |= PFERR_USER_MASK;
        t_gpa  = vcpu->arch.mmu.gva_to_gpa(vcpu, gpa, access, &error);
        if (t_gpa == UNMAPPED_GVA)
-               vcpu->arch.fault.error_code |= PFERR_NESTED_MASK;
+               vcpu->arch.fault.nested = true;
 
        return t_gpa;
 }
@@ -4193,6 +4194,35 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
        memcpy(c->regs, vcpu->arch.regs, sizeof c->regs);
 }
 
+int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq)
+{
+       struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
+       int ret;
+
+       init_emulate_ctxt(vcpu);
+
+       vcpu->arch.emulate_ctxt.decode.op_bytes = 2;
+       vcpu->arch.emulate_ctxt.decode.ad_bytes = 2;
+       vcpu->arch.emulate_ctxt.decode.eip = vcpu->arch.emulate_ctxt.eip;
+       ret = emulate_int_real(&vcpu->arch.emulate_ctxt, &emulate_ops, irq);
+
+       if (ret != X86EMUL_CONTINUE)
+               return EMULATE_FAIL;
+
+       vcpu->arch.emulate_ctxt.eip = c->eip;
+       memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
+       kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip);
+       kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
+
+       if (irq == NMI_VECTOR)
+               vcpu->arch.nmi_pending = false;
+       else
+               vcpu->arch.interrupt.pending = false;
+
+       return EMULATE_DONE;
+}
+EXPORT_SYMBOL_GPL(kvm_inject_realmode_interrupt);
+
 static int handle_emulation_failure(struct kvm_vcpu *vcpu)
 {
        ++vcpu->stat.insn_emulation_fail;
@@ -5011,8 +5041,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
                        kvm_mmu_unload(vcpu);
                if (kvm_check_request(KVM_REQ_MIGRATE_TIMER, vcpu))
                        __kvm_migrate_timers(vcpu);
-               if (kvm_check_request(KVM_REQ_KVMCLOCK_UPDATE, vcpu)) {
-                       r = kvm_write_guest_time(vcpu);
+               if (kvm_check_request(KVM_REQ_CLOCK_UPDATE, vcpu)) {
+                       r = kvm_guest_time_update(vcpu);
                        if (unlikely(r))
                                goto out;
                }