void kvmppc_vcpu_block(struct kvm_vcpu *vcpu) { u64 now; unsigned long dec_nsec; now = get_tb(); if (now >= vcpu->arch.dec_expires && !kvmppc_core_pending_dec(vcpu)) kvmppc_core_queue_dec(vcpu); if (vcpu->arch.pending_exceptions) return; if (vcpu->arch.dec_expires != ~(u64)0) { dec_nsec = (vcpu->arch.dec_expires - now) * NSEC_PER_SEC / tb_ticks_per_sec; hrtimer_start(&vcpu->arch.dec_timer, ktime_set(0, dec_nsec), HRTIMER_MODE_REL); } kvmppc_vcpu_blocked(vcpu); kvm_vcpu_block(vcpu); vcpu->stat.halt_wakeup++; if (vcpu->arch.dec_expires != ~(u64)0) hrtimer_try_to_cancel(&vcpu->arch.dec_timer); kvmppc_vcpu_unblocked(vcpu); }
static void update_timer_ints(struct kvm_vcpu *vcpu) { if ((vcpu->arch.tcr & TCR_DIE) && (vcpu->arch.tsr & TSR_DIS)) kvmppc_core_queue_dec(vcpu); else kvmppc_core_dequeue_dec(vcpu); }
void kvmppc_emulate_dec(struct kvm_vcpu *vcpu) { unsigned long dec_nsec; pr_debug("mtDEC: %x\n", vcpu->arch.dec); #ifdef CONFIG_PPC_BOOK3S /* mtdec lowers the interrupt line when positive. */ kvmppc_core_dequeue_dec(vcpu); /* POWER4+ triggers a dec interrupt if the value is < 0 */ if (vcpu->arch.dec & 0x80000000) { hrtimer_try_to_cancel(&vcpu->arch.dec_timer); kvmppc_core_queue_dec(vcpu); return; } #endif if (kvmppc_dec_enabled(vcpu)) { /* The decrementer ticks at the same rate as the timebase, so * that's how we convert the guest DEC value to the number of * host ticks. */ hrtimer_try_to_cancel(&vcpu->arch.dec_timer); dec_nsec = vcpu->arch.dec; dec_nsec *= 1000; dec_nsec /= tb_ticks_per_usec; hrtimer_start(&vcpu->arch.dec_timer, ktime_set(0, dec_nsec), HRTIMER_MODE_REL); vcpu->arch.dec_jiffies = get_tb(); } else { hrtimer_try_to_cancel(&vcpu->arch.dec_timer); } }
static void kvmppc_decrementer_func(unsigned long data) { struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data; kvmppc_core_queue_dec(vcpu); if (waitqueue_active(&vcpu->wq)) { wake_up_interruptible(&vcpu->wq); vcpu->stat.halt_wakeup++; } }
void kvmppc_emulate_dec(struct kvm_vcpu *vcpu) { unsigned long dec_nsec; unsigned long long dec_time; pr_debug("mtDEC: %x\n", vcpu->arch.dec); hrtimer_try_to_cancel(&vcpu->arch.dec_timer); #ifdef CONFIG_PPC_BOOK3S /* mtdec lowers the interrupt line when positive. */ kvmppc_core_dequeue_dec(vcpu); /* POWER4+ triggers a dec interrupt if the value is < 0 */ if (vcpu->arch.dec & 0x80000000) { kvmppc_core_queue_dec(vcpu); return; } #endif #ifdef CONFIG_BOOKE /* On BOOKE, DEC = 0 is as good as decrementer not enabled */ if (vcpu->arch.dec == 0) return; #endif /* * The decrementer ticks at the same rate as the timebase, so * that's how we convert the guest DEC value to the number of * host ticks. */ dec_time = vcpu->arch.dec; /* * Guest timebase ticks at the same frequency as host decrementer. * So use the host decrementer calculations for decrementer emulation. */ dec_time = dec_time << decrementer_clockevent.shift; do_div(dec_time, decrementer_clockevent.mult); dec_nsec = do_div(dec_time, NSEC_PER_SEC); hrtimer_start(&vcpu->arch.dec_timer, ktime_set(dec_time, dec_nsec), HRTIMER_MODE_REL); vcpu->arch.dec_jiffies = get_tb(); }