162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * 8253/8254 interval timer emulation 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (c) 2003-2004 Fabrice Bellard 562306a36Sopenharmony_ci * Copyright (c) 2006 Intel Corporation 662306a36Sopenharmony_ci * Copyright (c) 2007 Keir Fraser, XenSource Inc 762306a36Sopenharmony_ci * Copyright (c) 2008 Intel Corporation 862306a36Sopenharmony_ci * Copyright 2009 Red Hat, Inc. and/or its affiliates. 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 1162306a36Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal 1262306a36Sopenharmony_ci * in the Software without restriction, including without limitation the rights 1362306a36Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1462306a36Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is 1562306a36Sopenharmony_ci * furnished to do so, subject to the following conditions: 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 1862306a36Sopenharmony_ci * all copies or substantial portions of the Software. 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2162306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2262306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2362306a36Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2462306a36Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2562306a36Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 2662306a36Sopenharmony_ci * THE SOFTWARE. 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * Authors: 2962306a36Sopenharmony_ci * Sheng Yang <sheng.yang@intel.com> 3062306a36Sopenharmony_ci * Based on QEMU and Xen. 3162306a36Sopenharmony_ci */ 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#include <linux/kvm_host.h> 3662306a36Sopenharmony_ci#include <linux/slab.h> 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#include "ioapic.h" 3962306a36Sopenharmony_ci#include "irq.h" 4062306a36Sopenharmony_ci#include "i8254.h" 4162306a36Sopenharmony_ci#include "x86.h" 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#ifndef CONFIG_X86_64 4462306a36Sopenharmony_ci#define mod_64(x, y) ((x) - (y) * div64_u64(x, y)) 4562306a36Sopenharmony_ci#else 4662306a36Sopenharmony_ci#define mod_64(x, y) ((x) % (y)) 4762306a36Sopenharmony_ci#endif 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define RW_STATE_LSB 1 5062306a36Sopenharmony_ci#define RW_STATE_MSB 2 5162306a36Sopenharmony_ci#define RW_STATE_WORD0 3 5262306a36Sopenharmony_ci#define RW_STATE_WORD1 4 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic void pit_set_gate(struct kvm_pit *pit, int channel, u32 val) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci struct kvm_kpit_channel_state *c = &pit->pit_state.channels[channel]; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci switch (c->mode) { 5962306a36Sopenharmony_ci default: 6062306a36Sopenharmony_ci case 0: 6162306a36Sopenharmony_ci case 4: 6262306a36Sopenharmony_ci /* XXX: just disable/enable counting */ 6362306a36Sopenharmony_ci break; 6462306a36Sopenharmony_ci case 1: 6562306a36Sopenharmony_ci case 2: 6662306a36Sopenharmony_ci case 3: 6762306a36Sopenharmony_ci case 5: 6862306a36Sopenharmony_ci /* Restart counting on rising edge. */ 6962306a36Sopenharmony_ci if (c->gate < val) 7062306a36Sopenharmony_ci c->count_load_time = ktime_get(); 7162306a36Sopenharmony_ci break; 7262306a36Sopenharmony_ci } 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci c->gate = val; 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic int pit_get_gate(struct kvm_pit *pit, int channel) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci return pit->pit_state.channels[channel].gate; 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic s64 __kpit_elapsed(struct kvm_pit *pit) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci s64 elapsed; 8562306a36Sopenharmony_ci ktime_t remaining; 8662306a36Sopenharmony_ci struct kvm_kpit_state *ps = &pit->pit_state; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci if (!ps->period) 8962306a36Sopenharmony_ci return 0; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci /* 9262306a36Sopenharmony_ci * The Counter does not stop when it reaches zero. In 9362306a36Sopenharmony_ci * Modes 0, 1, 4, and 5 the Counter ``wraps around'' to 9462306a36Sopenharmony_ci * the highest count, either FFFF hex for binary counting 9562306a36Sopenharmony_ci * or 9999 for BCD counting, and continues counting. 9662306a36Sopenharmony_ci * Modes 2 and 3 are periodic; the Counter reloads 9762306a36Sopenharmony_ci * itself with the initial count and continues counting 9862306a36Sopenharmony_ci * from there. 9962306a36Sopenharmony_ci */ 10062306a36Sopenharmony_ci remaining = hrtimer_get_remaining(&ps->timer); 10162306a36Sopenharmony_ci elapsed = ps->period - ktime_to_ns(remaining); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci return elapsed; 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic s64 kpit_elapsed(struct kvm_pit *pit, struct kvm_kpit_channel_state *c, 10762306a36Sopenharmony_ci int channel) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci if (channel == 0) 11062306a36Sopenharmony_ci return __kpit_elapsed(pit); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci return ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time)); 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic int pit_get_count(struct kvm_pit *pit, int channel) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci struct kvm_kpit_channel_state *c = &pit->pit_state.channels[channel]; 11862306a36Sopenharmony_ci s64 d, t; 11962306a36Sopenharmony_ci int counter; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci t = kpit_elapsed(pit, c, channel); 12262306a36Sopenharmony_ci d = mul_u64_u32_div(t, KVM_PIT_FREQ, NSEC_PER_SEC); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci switch (c->mode) { 12562306a36Sopenharmony_ci case 0: 12662306a36Sopenharmony_ci case 1: 12762306a36Sopenharmony_ci case 4: 12862306a36Sopenharmony_ci case 5: 12962306a36Sopenharmony_ci counter = (c->count - d) & 0xffff; 13062306a36Sopenharmony_ci break; 13162306a36Sopenharmony_ci case 3: 13262306a36Sopenharmony_ci /* XXX: may be incorrect for odd counts */ 13362306a36Sopenharmony_ci counter = c->count - (mod_64((2 * d), c->count)); 13462306a36Sopenharmony_ci break; 13562306a36Sopenharmony_ci default: 13662306a36Sopenharmony_ci counter = c->count - mod_64(d, c->count); 13762306a36Sopenharmony_ci break; 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci return counter; 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic int pit_get_out(struct kvm_pit *pit, int channel) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci struct kvm_kpit_channel_state *c = &pit->pit_state.channels[channel]; 14562306a36Sopenharmony_ci s64 d, t; 14662306a36Sopenharmony_ci int out; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci t = kpit_elapsed(pit, c, channel); 14962306a36Sopenharmony_ci d = mul_u64_u32_div(t, KVM_PIT_FREQ, NSEC_PER_SEC); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci switch (c->mode) { 15262306a36Sopenharmony_ci default: 15362306a36Sopenharmony_ci case 0: 15462306a36Sopenharmony_ci out = (d >= c->count); 15562306a36Sopenharmony_ci break; 15662306a36Sopenharmony_ci case 1: 15762306a36Sopenharmony_ci out = (d < c->count); 15862306a36Sopenharmony_ci break; 15962306a36Sopenharmony_ci case 2: 16062306a36Sopenharmony_ci out = ((mod_64(d, c->count) == 0) && (d != 0)); 16162306a36Sopenharmony_ci break; 16262306a36Sopenharmony_ci case 3: 16362306a36Sopenharmony_ci out = (mod_64(d, c->count) < ((c->count + 1) >> 1)); 16462306a36Sopenharmony_ci break; 16562306a36Sopenharmony_ci case 4: 16662306a36Sopenharmony_ci case 5: 16762306a36Sopenharmony_ci out = (d == c->count); 16862306a36Sopenharmony_ci break; 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci return out; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic void pit_latch_count(struct kvm_pit *pit, int channel) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci struct kvm_kpit_channel_state *c = &pit->pit_state.channels[channel]; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci if (!c->count_latched) { 17962306a36Sopenharmony_ci c->latched_count = pit_get_count(pit, channel); 18062306a36Sopenharmony_ci c->count_latched = c->rw_mode; 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistatic void pit_latch_status(struct kvm_pit *pit, int channel) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci struct kvm_kpit_channel_state *c = &pit->pit_state.channels[channel]; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci if (!c->status_latched) { 18962306a36Sopenharmony_ci /* TODO: Return NULL COUNT (bit 6). */ 19062306a36Sopenharmony_ci c->status = ((pit_get_out(pit, channel) << 7) | 19162306a36Sopenharmony_ci (c->rw_mode << 4) | 19262306a36Sopenharmony_ci (c->mode << 1) | 19362306a36Sopenharmony_ci c->bcd); 19462306a36Sopenharmony_ci c->status_latched = 1; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cistatic inline struct kvm_pit *pit_state_to_pit(struct kvm_kpit_state *ps) 19962306a36Sopenharmony_ci{ 20062306a36Sopenharmony_ci return container_of(ps, struct kvm_pit, pit_state); 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_cistatic void kvm_pit_ack_irq(struct kvm_irq_ack_notifier *kian) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci struct kvm_kpit_state *ps = container_of(kian, struct kvm_kpit_state, 20662306a36Sopenharmony_ci irq_ack_notifier); 20762306a36Sopenharmony_ci struct kvm_pit *pit = pit_state_to_pit(ps); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci atomic_set(&ps->irq_ack, 1); 21062306a36Sopenharmony_ci /* irq_ack should be set before pending is read. Order accesses with 21162306a36Sopenharmony_ci * inc(pending) in pit_timer_fn and xchg(irq_ack, 0) in pit_do_work. 21262306a36Sopenharmony_ci */ 21362306a36Sopenharmony_ci smp_mb(); 21462306a36Sopenharmony_ci if (atomic_dec_if_positive(&ps->pending) > 0) 21562306a36Sopenharmony_ci kthread_queue_work(pit->worker, &pit->expired); 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_civoid __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu) 21962306a36Sopenharmony_ci{ 22062306a36Sopenharmony_ci struct kvm_pit *pit = vcpu->kvm->arch.vpit; 22162306a36Sopenharmony_ci struct hrtimer *timer; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci /* Somewhat arbitrarily make vcpu0 the owner of the PIT. */ 22462306a36Sopenharmony_ci if (vcpu->vcpu_id || !pit) 22562306a36Sopenharmony_ci return; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci timer = &pit->pit_state.timer; 22862306a36Sopenharmony_ci mutex_lock(&pit->pit_state.lock); 22962306a36Sopenharmony_ci if (hrtimer_cancel(timer)) 23062306a36Sopenharmony_ci hrtimer_start_expires(timer, HRTIMER_MODE_ABS); 23162306a36Sopenharmony_ci mutex_unlock(&pit->pit_state.lock); 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistatic void destroy_pit_timer(struct kvm_pit *pit) 23562306a36Sopenharmony_ci{ 23662306a36Sopenharmony_ci hrtimer_cancel(&pit->pit_state.timer); 23762306a36Sopenharmony_ci kthread_flush_work(&pit->expired); 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_cistatic void pit_do_work(struct kthread_work *work) 24162306a36Sopenharmony_ci{ 24262306a36Sopenharmony_ci struct kvm_pit *pit = container_of(work, struct kvm_pit, expired); 24362306a36Sopenharmony_ci struct kvm *kvm = pit->kvm; 24462306a36Sopenharmony_ci struct kvm_vcpu *vcpu; 24562306a36Sopenharmony_ci unsigned long i; 24662306a36Sopenharmony_ci struct kvm_kpit_state *ps = &pit->pit_state; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci if (atomic_read(&ps->reinject) && !atomic_xchg(&ps->irq_ack, 0)) 24962306a36Sopenharmony_ci return; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci kvm_set_irq(kvm, pit->irq_source_id, 0, 1, false); 25262306a36Sopenharmony_ci kvm_set_irq(kvm, pit->irq_source_id, 0, 0, false); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* 25562306a36Sopenharmony_ci * Provides NMI watchdog support via Virtual Wire mode. 25662306a36Sopenharmony_ci * The route is: PIT -> LVT0 in NMI mode. 25762306a36Sopenharmony_ci * 25862306a36Sopenharmony_ci * Note: Our Virtual Wire implementation does not follow 25962306a36Sopenharmony_ci * the MP specification. We propagate a PIT interrupt to all 26062306a36Sopenharmony_ci * VCPUs and only when LVT0 is in NMI mode. The interrupt can 26162306a36Sopenharmony_ci * also be simultaneously delivered through PIC and IOAPIC. 26262306a36Sopenharmony_ci */ 26362306a36Sopenharmony_ci if (atomic_read(&kvm->arch.vapics_in_nmi_mode) > 0) 26462306a36Sopenharmony_ci kvm_for_each_vcpu(i, vcpu, kvm) 26562306a36Sopenharmony_ci kvm_apic_nmi_wd_deliver(vcpu); 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_cistatic enum hrtimer_restart pit_timer_fn(struct hrtimer *data) 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci struct kvm_kpit_state *ps = container_of(data, struct kvm_kpit_state, timer); 27162306a36Sopenharmony_ci struct kvm_pit *pt = pit_state_to_pit(ps); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci if (atomic_read(&ps->reinject)) 27462306a36Sopenharmony_ci atomic_inc(&ps->pending); 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci kthread_queue_work(pt->worker, &pt->expired); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if (ps->is_periodic) { 27962306a36Sopenharmony_ci hrtimer_add_expires_ns(&ps->timer, ps->period); 28062306a36Sopenharmony_ci return HRTIMER_RESTART; 28162306a36Sopenharmony_ci } else 28262306a36Sopenharmony_ci return HRTIMER_NORESTART; 28362306a36Sopenharmony_ci} 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_cistatic inline void kvm_pit_reset_reinject(struct kvm_pit *pit) 28662306a36Sopenharmony_ci{ 28762306a36Sopenharmony_ci atomic_set(&pit->pit_state.pending, 0); 28862306a36Sopenharmony_ci atomic_set(&pit->pit_state.irq_ack, 1); 28962306a36Sopenharmony_ci} 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_civoid kvm_pit_set_reinject(struct kvm_pit *pit, bool reinject) 29262306a36Sopenharmony_ci{ 29362306a36Sopenharmony_ci struct kvm_kpit_state *ps = &pit->pit_state; 29462306a36Sopenharmony_ci struct kvm *kvm = pit->kvm; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci if (atomic_read(&ps->reinject) == reinject) 29762306a36Sopenharmony_ci return; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci /* 30062306a36Sopenharmony_ci * AMD SVM AVIC accelerates EOI write and does not trap. 30162306a36Sopenharmony_ci * This cause in-kernel PIT re-inject mode to fail 30262306a36Sopenharmony_ci * since it checks ps->irq_ack before kvm_set_irq() 30362306a36Sopenharmony_ci * and relies on the ack notifier to timely queue 30462306a36Sopenharmony_ci * the pt->worker work iterm and reinject the missed tick. 30562306a36Sopenharmony_ci * So, deactivate APICv when PIT is in reinject mode. 30662306a36Sopenharmony_ci */ 30762306a36Sopenharmony_ci if (reinject) { 30862306a36Sopenharmony_ci kvm_set_apicv_inhibit(kvm, APICV_INHIBIT_REASON_PIT_REINJ); 30962306a36Sopenharmony_ci /* The initial state is preserved while ps->reinject == 0. */ 31062306a36Sopenharmony_ci kvm_pit_reset_reinject(pit); 31162306a36Sopenharmony_ci kvm_register_irq_ack_notifier(kvm, &ps->irq_ack_notifier); 31262306a36Sopenharmony_ci kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier); 31362306a36Sopenharmony_ci } else { 31462306a36Sopenharmony_ci kvm_clear_apicv_inhibit(kvm, APICV_INHIBIT_REASON_PIT_REINJ); 31562306a36Sopenharmony_ci kvm_unregister_irq_ack_notifier(kvm, &ps->irq_ack_notifier); 31662306a36Sopenharmony_ci kvm_unregister_irq_mask_notifier(kvm, 0, &pit->mask_notifier); 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci atomic_set(&ps->reinject, reinject); 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic void create_pit_timer(struct kvm_pit *pit, u32 val, int is_period) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci struct kvm_kpit_state *ps = &pit->pit_state; 32562306a36Sopenharmony_ci struct kvm *kvm = pit->kvm; 32662306a36Sopenharmony_ci s64 interval; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci if (!ioapic_in_kernel(kvm) || 32962306a36Sopenharmony_ci ps->flags & KVM_PIT_FLAGS_HPET_LEGACY) 33062306a36Sopenharmony_ci return; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci interval = mul_u64_u32_div(val, NSEC_PER_SEC, KVM_PIT_FREQ); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci pr_debug("create pit timer, interval is %llu nsec\n", interval); 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci /* TODO The new value only affected after the retriggered */ 33762306a36Sopenharmony_ci hrtimer_cancel(&ps->timer); 33862306a36Sopenharmony_ci kthread_flush_work(&pit->expired); 33962306a36Sopenharmony_ci ps->period = interval; 34062306a36Sopenharmony_ci ps->is_periodic = is_period; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci kvm_pit_reset_reinject(pit); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci /* 34562306a36Sopenharmony_ci * Do not allow the guest to program periodic timers with small 34662306a36Sopenharmony_ci * interval, since the hrtimers are not throttled by the host 34762306a36Sopenharmony_ci * scheduler. 34862306a36Sopenharmony_ci */ 34962306a36Sopenharmony_ci if (ps->is_periodic) { 35062306a36Sopenharmony_ci s64 min_period = min_timer_period_us * 1000LL; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci if (ps->period < min_period) { 35362306a36Sopenharmony_ci pr_info_ratelimited( 35462306a36Sopenharmony_ci "requested %lld ns " 35562306a36Sopenharmony_ci "i8254 timer period limited to %lld ns\n", 35662306a36Sopenharmony_ci ps->period, min_period); 35762306a36Sopenharmony_ci ps->period = min_period; 35862306a36Sopenharmony_ci } 35962306a36Sopenharmony_ci } 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci hrtimer_start(&ps->timer, ktime_add_ns(ktime_get(), interval), 36262306a36Sopenharmony_ci HRTIMER_MODE_ABS); 36362306a36Sopenharmony_ci} 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_cistatic void pit_load_count(struct kvm_pit *pit, int channel, u32 val) 36662306a36Sopenharmony_ci{ 36762306a36Sopenharmony_ci struct kvm_kpit_state *ps = &pit->pit_state; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci pr_debug("load_count val is %u, channel is %d\n", val, channel); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci /* 37262306a36Sopenharmony_ci * The largest possible initial count is 0; this is equivalent 37362306a36Sopenharmony_ci * to 216 for binary counting and 104 for BCD counting. 37462306a36Sopenharmony_ci */ 37562306a36Sopenharmony_ci if (val == 0) 37662306a36Sopenharmony_ci val = 0x10000; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci ps->channels[channel].count = val; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci if (channel != 0) { 38162306a36Sopenharmony_ci ps->channels[channel].count_load_time = ktime_get(); 38262306a36Sopenharmony_ci return; 38362306a36Sopenharmony_ci } 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci /* Two types of timer 38662306a36Sopenharmony_ci * mode 1 is one shot, mode 2 is period, otherwise del timer */ 38762306a36Sopenharmony_ci switch (ps->channels[0].mode) { 38862306a36Sopenharmony_ci case 0: 38962306a36Sopenharmony_ci case 1: 39062306a36Sopenharmony_ci /* FIXME: enhance mode 4 precision */ 39162306a36Sopenharmony_ci case 4: 39262306a36Sopenharmony_ci create_pit_timer(pit, val, 0); 39362306a36Sopenharmony_ci break; 39462306a36Sopenharmony_ci case 2: 39562306a36Sopenharmony_ci case 3: 39662306a36Sopenharmony_ci create_pit_timer(pit, val, 1); 39762306a36Sopenharmony_ci break; 39862306a36Sopenharmony_ci default: 39962306a36Sopenharmony_ci destroy_pit_timer(pit); 40062306a36Sopenharmony_ci } 40162306a36Sopenharmony_ci} 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_civoid kvm_pit_load_count(struct kvm_pit *pit, int channel, u32 val, 40462306a36Sopenharmony_ci int hpet_legacy_start) 40562306a36Sopenharmony_ci{ 40662306a36Sopenharmony_ci u8 saved_mode; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci WARN_ON_ONCE(!mutex_is_locked(&pit->pit_state.lock)); 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci if (hpet_legacy_start) { 41162306a36Sopenharmony_ci /* save existing mode for later reenablement */ 41262306a36Sopenharmony_ci WARN_ON(channel != 0); 41362306a36Sopenharmony_ci saved_mode = pit->pit_state.channels[0].mode; 41462306a36Sopenharmony_ci pit->pit_state.channels[0].mode = 0xff; /* disable timer */ 41562306a36Sopenharmony_ci pit_load_count(pit, channel, val); 41662306a36Sopenharmony_ci pit->pit_state.channels[0].mode = saved_mode; 41762306a36Sopenharmony_ci } else { 41862306a36Sopenharmony_ci pit_load_count(pit, channel, val); 41962306a36Sopenharmony_ci } 42062306a36Sopenharmony_ci} 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_cistatic inline struct kvm_pit *dev_to_pit(struct kvm_io_device *dev) 42362306a36Sopenharmony_ci{ 42462306a36Sopenharmony_ci return container_of(dev, struct kvm_pit, dev); 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_cistatic inline struct kvm_pit *speaker_to_pit(struct kvm_io_device *dev) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci return container_of(dev, struct kvm_pit, speaker_dev); 43062306a36Sopenharmony_ci} 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_cistatic inline int pit_in_range(gpa_t addr) 43362306a36Sopenharmony_ci{ 43462306a36Sopenharmony_ci return ((addr >= KVM_PIT_BASE_ADDRESS) && 43562306a36Sopenharmony_ci (addr < KVM_PIT_BASE_ADDRESS + KVM_PIT_MEM_LENGTH)); 43662306a36Sopenharmony_ci} 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_cistatic int pit_ioport_write(struct kvm_vcpu *vcpu, 43962306a36Sopenharmony_ci struct kvm_io_device *this, 44062306a36Sopenharmony_ci gpa_t addr, int len, const void *data) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci struct kvm_pit *pit = dev_to_pit(this); 44362306a36Sopenharmony_ci struct kvm_kpit_state *pit_state = &pit->pit_state; 44462306a36Sopenharmony_ci int channel, access; 44562306a36Sopenharmony_ci struct kvm_kpit_channel_state *s; 44662306a36Sopenharmony_ci u32 val = *(u32 *) data; 44762306a36Sopenharmony_ci if (!pit_in_range(addr)) 44862306a36Sopenharmony_ci return -EOPNOTSUPP; 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci val &= 0xff; 45162306a36Sopenharmony_ci addr &= KVM_PIT_CHANNEL_MASK; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci mutex_lock(&pit_state->lock); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci if (val != 0) 45662306a36Sopenharmony_ci pr_debug("write addr is 0x%x, len is %d, val is 0x%x\n", 45762306a36Sopenharmony_ci (unsigned int)addr, len, val); 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci if (addr == 3) { 46062306a36Sopenharmony_ci channel = val >> 6; 46162306a36Sopenharmony_ci if (channel == 3) { 46262306a36Sopenharmony_ci /* Read-Back Command. */ 46362306a36Sopenharmony_ci for (channel = 0; channel < 3; channel++) { 46462306a36Sopenharmony_ci if (val & (2 << channel)) { 46562306a36Sopenharmony_ci if (!(val & 0x20)) 46662306a36Sopenharmony_ci pit_latch_count(pit, channel); 46762306a36Sopenharmony_ci if (!(val & 0x10)) 46862306a36Sopenharmony_ci pit_latch_status(pit, channel); 46962306a36Sopenharmony_ci } 47062306a36Sopenharmony_ci } 47162306a36Sopenharmony_ci } else { 47262306a36Sopenharmony_ci /* Select Counter <channel>. */ 47362306a36Sopenharmony_ci s = &pit_state->channels[channel]; 47462306a36Sopenharmony_ci access = (val >> 4) & KVM_PIT_CHANNEL_MASK; 47562306a36Sopenharmony_ci if (access == 0) { 47662306a36Sopenharmony_ci pit_latch_count(pit, channel); 47762306a36Sopenharmony_ci } else { 47862306a36Sopenharmony_ci s->rw_mode = access; 47962306a36Sopenharmony_ci s->read_state = access; 48062306a36Sopenharmony_ci s->write_state = access; 48162306a36Sopenharmony_ci s->mode = (val >> 1) & 7; 48262306a36Sopenharmony_ci if (s->mode > 5) 48362306a36Sopenharmony_ci s->mode -= 4; 48462306a36Sopenharmony_ci s->bcd = val & 1; 48562306a36Sopenharmony_ci } 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci } else { 48862306a36Sopenharmony_ci /* Write Count. */ 48962306a36Sopenharmony_ci s = &pit_state->channels[addr]; 49062306a36Sopenharmony_ci switch (s->write_state) { 49162306a36Sopenharmony_ci default: 49262306a36Sopenharmony_ci case RW_STATE_LSB: 49362306a36Sopenharmony_ci pit_load_count(pit, addr, val); 49462306a36Sopenharmony_ci break; 49562306a36Sopenharmony_ci case RW_STATE_MSB: 49662306a36Sopenharmony_ci pit_load_count(pit, addr, val << 8); 49762306a36Sopenharmony_ci break; 49862306a36Sopenharmony_ci case RW_STATE_WORD0: 49962306a36Sopenharmony_ci s->write_latch = val; 50062306a36Sopenharmony_ci s->write_state = RW_STATE_WORD1; 50162306a36Sopenharmony_ci break; 50262306a36Sopenharmony_ci case RW_STATE_WORD1: 50362306a36Sopenharmony_ci pit_load_count(pit, addr, s->write_latch | (val << 8)); 50462306a36Sopenharmony_ci s->write_state = RW_STATE_WORD0; 50562306a36Sopenharmony_ci break; 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci } 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci mutex_unlock(&pit_state->lock); 51062306a36Sopenharmony_ci return 0; 51162306a36Sopenharmony_ci} 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_cistatic int pit_ioport_read(struct kvm_vcpu *vcpu, 51462306a36Sopenharmony_ci struct kvm_io_device *this, 51562306a36Sopenharmony_ci gpa_t addr, int len, void *data) 51662306a36Sopenharmony_ci{ 51762306a36Sopenharmony_ci struct kvm_pit *pit = dev_to_pit(this); 51862306a36Sopenharmony_ci struct kvm_kpit_state *pit_state = &pit->pit_state; 51962306a36Sopenharmony_ci int ret, count; 52062306a36Sopenharmony_ci struct kvm_kpit_channel_state *s; 52162306a36Sopenharmony_ci if (!pit_in_range(addr)) 52262306a36Sopenharmony_ci return -EOPNOTSUPP; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci addr &= KVM_PIT_CHANNEL_MASK; 52562306a36Sopenharmony_ci if (addr == 3) 52662306a36Sopenharmony_ci return 0; 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci s = &pit_state->channels[addr]; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci mutex_lock(&pit_state->lock); 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci if (s->status_latched) { 53362306a36Sopenharmony_ci s->status_latched = 0; 53462306a36Sopenharmony_ci ret = s->status; 53562306a36Sopenharmony_ci } else if (s->count_latched) { 53662306a36Sopenharmony_ci switch (s->count_latched) { 53762306a36Sopenharmony_ci default: 53862306a36Sopenharmony_ci case RW_STATE_LSB: 53962306a36Sopenharmony_ci ret = s->latched_count & 0xff; 54062306a36Sopenharmony_ci s->count_latched = 0; 54162306a36Sopenharmony_ci break; 54262306a36Sopenharmony_ci case RW_STATE_MSB: 54362306a36Sopenharmony_ci ret = s->latched_count >> 8; 54462306a36Sopenharmony_ci s->count_latched = 0; 54562306a36Sopenharmony_ci break; 54662306a36Sopenharmony_ci case RW_STATE_WORD0: 54762306a36Sopenharmony_ci ret = s->latched_count & 0xff; 54862306a36Sopenharmony_ci s->count_latched = RW_STATE_MSB; 54962306a36Sopenharmony_ci break; 55062306a36Sopenharmony_ci } 55162306a36Sopenharmony_ci } else { 55262306a36Sopenharmony_ci switch (s->read_state) { 55362306a36Sopenharmony_ci default: 55462306a36Sopenharmony_ci case RW_STATE_LSB: 55562306a36Sopenharmony_ci count = pit_get_count(pit, addr); 55662306a36Sopenharmony_ci ret = count & 0xff; 55762306a36Sopenharmony_ci break; 55862306a36Sopenharmony_ci case RW_STATE_MSB: 55962306a36Sopenharmony_ci count = pit_get_count(pit, addr); 56062306a36Sopenharmony_ci ret = (count >> 8) & 0xff; 56162306a36Sopenharmony_ci break; 56262306a36Sopenharmony_ci case RW_STATE_WORD0: 56362306a36Sopenharmony_ci count = pit_get_count(pit, addr); 56462306a36Sopenharmony_ci ret = count & 0xff; 56562306a36Sopenharmony_ci s->read_state = RW_STATE_WORD1; 56662306a36Sopenharmony_ci break; 56762306a36Sopenharmony_ci case RW_STATE_WORD1: 56862306a36Sopenharmony_ci count = pit_get_count(pit, addr); 56962306a36Sopenharmony_ci ret = (count >> 8) & 0xff; 57062306a36Sopenharmony_ci s->read_state = RW_STATE_WORD0; 57162306a36Sopenharmony_ci break; 57262306a36Sopenharmony_ci } 57362306a36Sopenharmony_ci } 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci if (len > sizeof(ret)) 57662306a36Sopenharmony_ci len = sizeof(ret); 57762306a36Sopenharmony_ci memcpy(data, (char *)&ret, len); 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci mutex_unlock(&pit_state->lock); 58062306a36Sopenharmony_ci return 0; 58162306a36Sopenharmony_ci} 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_cistatic int speaker_ioport_write(struct kvm_vcpu *vcpu, 58462306a36Sopenharmony_ci struct kvm_io_device *this, 58562306a36Sopenharmony_ci gpa_t addr, int len, const void *data) 58662306a36Sopenharmony_ci{ 58762306a36Sopenharmony_ci struct kvm_pit *pit = speaker_to_pit(this); 58862306a36Sopenharmony_ci struct kvm_kpit_state *pit_state = &pit->pit_state; 58962306a36Sopenharmony_ci u32 val = *(u32 *) data; 59062306a36Sopenharmony_ci if (addr != KVM_SPEAKER_BASE_ADDRESS) 59162306a36Sopenharmony_ci return -EOPNOTSUPP; 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci mutex_lock(&pit_state->lock); 59462306a36Sopenharmony_ci if (val & (1 << 1)) 59562306a36Sopenharmony_ci pit_state->flags |= KVM_PIT_FLAGS_SPEAKER_DATA_ON; 59662306a36Sopenharmony_ci else 59762306a36Sopenharmony_ci pit_state->flags &= ~KVM_PIT_FLAGS_SPEAKER_DATA_ON; 59862306a36Sopenharmony_ci pit_set_gate(pit, 2, val & 1); 59962306a36Sopenharmony_ci mutex_unlock(&pit_state->lock); 60062306a36Sopenharmony_ci return 0; 60162306a36Sopenharmony_ci} 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_cistatic int speaker_ioport_read(struct kvm_vcpu *vcpu, 60462306a36Sopenharmony_ci struct kvm_io_device *this, 60562306a36Sopenharmony_ci gpa_t addr, int len, void *data) 60662306a36Sopenharmony_ci{ 60762306a36Sopenharmony_ci struct kvm_pit *pit = speaker_to_pit(this); 60862306a36Sopenharmony_ci struct kvm_kpit_state *pit_state = &pit->pit_state; 60962306a36Sopenharmony_ci unsigned int refresh_clock; 61062306a36Sopenharmony_ci int ret; 61162306a36Sopenharmony_ci if (addr != KVM_SPEAKER_BASE_ADDRESS) 61262306a36Sopenharmony_ci return -EOPNOTSUPP; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci /* Refresh clock toggles at about 15us. We approximate as 2^14ns. */ 61562306a36Sopenharmony_ci refresh_clock = ((unsigned int)ktime_to_ns(ktime_get()) >> 14) & 1; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci mutex_lock(&pit_state->lock); 61862306a36Sopenharmony_ci ret = (!!(pit_state->flags & KVM_PIT_FLAGS_SPEAKER_DATA_ON) << 1) | 61962306a36Sopenharmony_ci pit_get_gate(pit, 2) | (pit_get_out(pit, 2) << 5) | 62062306a36Sopenharmony_ci (refresh_clock << 4); 62162306a36Sopenharmony_ci if (len > sizeof(ret)) 62262306a36Sopenharmony_ci len = sizeof(ret); 62362306a36Sopenharmony_ci memcpy(data, (char *)&ret, len); 62462306a36Sopenharmony_ci mutex_unlock(&pit_state->lock); 62562306a36Sopenharmony_ci return 0; 62662306a36Sopenharmony_ci} 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_cistatic void kvm_pit_reset(struct kvm_pit *pit) 62962306a36Sopenharmony_ci{ 63062306a36Sopenharmony_ci int i; 63162306a36Sopenharmony_ci struct kvm_kpit_channel_state *c; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci pit->pit_state.flags = 0; 63462306a36Sopenharmony_ci for (i = 0; i < 3; i++) { 63562306a36Sopenharmony_ci c = &pit->pit_state.channels[i]; 63662306a36Sopenharmony_ci c->mode = 0xff; 63762306a36Sopenharmony_ci c->gate = (i != 2); 63862306a36Sopenharmony_ci pit_load_count(pit, i, 0); 63962306a36Sopenharmony_ci } 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci kvm_pit_reset_reinject(pit); 64262306a36Sopenharmony_ci} 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_cistatic void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, bool mask) 64562306a36Sopenharmony_ci{ 64662306a36Sopenharmony_ci struct kvm_pit *pit = container_of(kimn, struct kvm_pit, mask_notifier); 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci if (!mask) 64962306a36Sopenharmony_ci kvm_pit_reset_reinject(pit); 65062306a36Sopenharmony_ci} 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_cistatic const struct kvm_io_device_ops pit_dev_ops = { 65362306a36Sopenharmony_ci .read = pit_ioport_read, 65462306a36Sopenharmony_ci .write = pit_ioport_write, 65562306a36Sopenharmony_ci}; 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_cistatic const struct kvm_io_device_ops speaker_dev_ops = { 65862306a36Sopenharmony_ci .read = speaker_ioport_read, 65962306a36Sopenharmony_ci .write = speaker_ioport_write, 66062306a36Sopenharmony_ci}; 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_cistruct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags) 66362306a36Sopenharmony_ci{ 66462306a36Sopenharmony_ci struct kvm_pit *pit; 66562306a36Sopenharmony_ci struct kvm_kpit_state *pit_state; 66662306a36Sopenharmony_ci struct pid *pid; 66762306a36Sopenharmony_ci pid_t pid_nr; 66862306a36Sopenharmony_ci int ret; 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci pit = kzalloc(sizeof(struct kvm_pit), GFP_KERNEL_ACCOUNT); 67162306a36Sopenharmony_ci if (!pit) 67262306a36Sopenharmony_ci return NULL; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci pit->irq_source_id = kvm_request_irq_source_id(kvm); 67562306a36Sopenharmony_ci if (pit->irq_source_id < 0) 67662306a36Sopenharmony_ci goto fail_request; 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci mutex_init(&pit->pit_state.lock); 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci pid = get_pid(task_tgid(current)); 68162306a36Sopenharmony_ci pid_nr = pid_vnr(pid); 68262306a36Sopenharmony_ci put_pid(pid); 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci pit->worker = kthread_create_worker(0, "kvm-pit/%d", pid_nr); 68562306a36Sopenharmony_ci if (IS_ERR(pit->worker)) 68662306a36Sopenharmony_ci goto fail_kthread; 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci kthread_init_work(&pit->expired, pit_do_work); 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci pit->kvm = kvm; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci pit_state = &pit->pit_state; 69362306a36Sopenharmony_ci hrtimer_init(&pit_state->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); 69462306a36Sopenharmony_ci pit_state->timer.function = pit_timer_fn; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci pit_state->irq_ack_notifier.gsi = 0; 69762306a36Sopenharmony_ci pit_state->irq_ack_notifier.irq_acked = kvm_pit_ack_irq; 69862306a36Sopenharmony_ci pit->mask_notifier.func = pit_mask_notifer; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci kvm_pit_reset(pit); 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci kvm_pit_set_reinject(pit, true); 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci mutex_lock(&kvm->slots_lock); 70562306a36Sopenharmony_ci kvm_iodevice_init(&pit->dev, &pit_dev_ops); 70662306a36Sopenharmony_ci ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, KVM_PIT_BASE_ADDRESS, 70762306a36Sopenharmony_ci KVM_PIT_MEM_LENGTH, &pit->dev); 70862306a36Sopenharmony_ci if (ret < 0) 70962306a36Sopenharmony_ci goto fail_register_pit; 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci if (flags & KVM_PIT_SPEAKER_DUMMY) { 71262306a36Sopenharmony_ci kvm_iodevice_init(&pit->speaker_dev, &speaker_dev_ops); 71362306a36Sopenharmony_ci ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, 71462306a36Sopenharmony_ci KVM_SPEAKER_BASE_ADDRESS, 4, 71562306a36Sopenharmony_ci &pit->speaker_dev); 71662306a36Sopenharmony_ci if (ret < 0) 71762306a36Sopenharmony_ci goto fail_register_speaker; 71862306a36Sopenharmony_ci } 71962306a36Sopenharmony_ci mutex_unlock(&kvm->slots_lock); 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci return pit; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_cifail_register_speaker: 72462306a36Sopenharmony_ci kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &pit->dev); 72562306a36Sopenharmony_cifail_register_pit: 72662306a36Sopenharmony_ci mutex_unlock(&kvm->slots_lock); 72762306a36Sopenharmony_ci kvm_pit_set_reinject(pit, false); 72862306a36Sopenharmony_ci kthread_destroy_worker(pit->worker); 72962306a36Sopenharmony_cifail_kthread: 73062306a36Sopenharmony_ci kvm_free_irq_source_id(kvm, pit->irq_source_id); 73162306a36Sopenharmony_cifail_request: 73262306a36Sopenharmony_ci kfree(pit); 73362306a36Sopenharmony_ci return NULL; 73462306a36Sopenharmony_ci} 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_civoid kvm_free_pit(struct kvm *kvm) 73762306a36Sopenharmony_ci{ 73862306a36Sopenharmony_ci struct kvm_pit *pit = kvm->arch.vpit; 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci if (pit) { 74162306a36Sopenharmony_ci mutex_lock(&kvm->slots_lock); 74262306a36Sopenharmony_ci kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &pit->dev); 74362306a36Sopenharmony_ci kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &pit->speaker_dev); 74462306a36Sopenharmony_ci mutex_unlock(&kvm->slots_lock); 74562306a36Sopenharmony_ci kvm_pit_set_reinject(pit, false); 74662306a36Sopenharmony_ci hrtimer_cancel(&pit->pit_state.timer); 74762306a36Sopenharmony_ci kthread_destroy_worker(pit->worker); 74862306a36Sopenharmony_ci kvm_free_irq_source_id(kvm, pit->irq_source_id); 74962306a36Sopenharmony_ci kfree(pit); 75062306a36Sopenharmony_ci } 75162306a36Sopenharmony_ci} 752