diff options
Diffstat (limited to 'arch/x86/kvm/i8254.c')
-rw-r--r-- | arch/x86/kvm/i8254.c | 109 |
1 files changed, 60 insertions, 49 deletions
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c index c13bb92d3157..4d6f0d293ee2 100644 --- a/arch/x86/kvm/i8254.c +++ b/arch/x86/kvm/i8254.c | |||
@@ -98,6 +98,37 @@ static int pit_get_gate(struct kvm *kvm, int channel) | |||
98 | return kvm->arch.vpit->pit_state.channels[channel].gate; | 98 | return kvm->arch.vpit->pit_state.channels[channel].gate; |
99 | } | 99 | } |
100 | 100 | ||
101 | static s64 __kpit_elapsed(struct kvm *kvm) | ||
102 | { | ||
103 | s64 elapsed; | ||
104 | ktime_t remaining; | ||
105 | struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state; | ||
106 | |||
107 | /* | ||
108 | * The Counter does not stop when it reaches zero. In | ||
109 | * Modes 0, 1, 4, and 5 the Counter ``wraps around'' to | ||
110 | * the highest count, either FFFF hex for binary counting | ||
111 | * or 9999 for BCD counting, and continues counting. | ||
112 | * Modes 2 and 3 are periodic; the Counter reloads | ||
113 | * itself with the initial count and continues counting | ||
114 | * from there. | ||
115 | */ | ||
116 | remaining = hrtimer_expires_remaining(&ps->pit_timer.timer); | ||
117 | elapsed = ps->pit_timer.period - ktime_to_ns(remaining); | ||
118 | elapsed = mod_64(elapsed, ps->pit_timer.period); | ||
119 | |||
120 | return elapsed; | ||
121 | } | ||
122 | |||
123 | static s64 kpit_elapsed(struct kvm *kvm, struct kvm_kpit_channel_state *c, | ||
124 | int channel) | ||
125 | { | ||
126 | if (channel == 0) | ||
127 | return __kpit_elapsed(kvm); | ||
128 | |||
129 | return ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time)); | ||
130 | } | ||
131 | |||
101 | static int pit_get_count(struct kvm *kvm, int channel) | 132 | static int pit_get_count(struct kvm *kvm, int channel) |
102 | { | 133 | { |
103 | struct kvm_kpit_channel_state *c = | 134 | struct kvm_kpit_channel_state *c = |
@@ -107,7 +138,7 @@ static int pit_get_count(struct kvm *kvm, int channel) | |||
107 | 138 | ||
108 | WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock)); | 139 | WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock)); |
109 | 140 | ||
110 | t = ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time)); | 141 | t = kpit_elapsed(kvm, c, channel); |
111 | d = muldiv64(t, KVM_PIT_FREQ, NSEC_PER_SEC); | 142 | d = muldiv64(t, KVM_PIT_FREQ, NSEC_PER_SEC); |
112 | 143 | ||
113 | switch (c->mode) { | 144 | switch (c->mode) { |
@@ -137,7 +168,7 @@ static int pit_get_out(struct kvm *kvm, int channel) | |||
137 | 168 | ||
138 | WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock)); | 169 | WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock)); |
139 | 170 | ||
140 | t = ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time)); | 171 | t = kpit_elapsed(kvm, c, channel); |
141 | d = muldiv64(t, KVM_PIT_FREQ, NSEC_PER_SEC); | 172 | d = muldiv64(t, KVM_PIT_FREQ, NSEC_PER_SEC); |
142 | 173 | ||
143 | switch (c->mode) { | 174 | switch (c->mode) { |
@@ -193,28 +224,6 @@ static void pit_latch_status(struct kvm *kvm, int channel) | |||
193 | } | 224 | } |
194 | } | 225 | } |
195 | 226 | ||
196 | static int __pit_timer_fn(struct kvm_kpit_state *ps) | ||
197 | { | ||
198 | struct kvm_vcpu *vcpu0 = ps->pit->kvm->vcpus[0]; | ||
199 | struct kvm_kpit_timer *pt = &ps->pit_timer; | ||
200 | |||
201 | if (!atomic_inc_and_test(&pt->pending)) | ||
202 | set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests); | ||
203 | |||
204 | if (!pt->reinject) | ||
205 | atomic_set(&pt->pending, 1); | ||
206 | |||
207 | if (vcpu0 && waitqueue_active(&vcpu0->wq)) | ||
208 | wake_up_interruptible(&vcpu0->wq); | ||
209 | |||
210 | hrtimer_add_expires_ns(&pt->timer, pt->period); | ||
211 | pt->scheduled = hrtimer_get_expires_ns(&pt->timer); | ||
212 | if (pt->period) | ||
213 | ps->channels[0].count_load_time = ktime_get(); | ||
214 | |||
215 | return (pt->period == 0 ? 0 : 1); | ||
216 | } | ||
217 | |||
218 | int pit_has_pending_timer(struct kvm_vcpu *vcpu) | 227 | int pit_has_pending_timer(struct kvm_vcpu *vcpu) |
219 | { | 228 | { |
220 | struct kvm_pit *pit = vcpu->kvm->arch.vpit; | 229 | struct kvm_pit *pit = vcpu->kvm->arch.vpit; |
@@ -235,21 +244,6 @@ static void kvm_pit_ack_irq(struct kvm_irq_ack_notifier *kian) | |||
235 | spin_unlock(&ps->inject_lock); | 244 | spin_unlock(&ps->inject_lock); |
236 | } | 245 | } |
237 | 246 | ||
238 | static enum hrtimer_restart pit_timer_fn(struct hrtimer *data) | ||
239 | { | ||
240 | struct kvm_kpit_state *ps; | ||
241 | int restart_timer = 0; | ||
242 | |||
243 | ps = container_of(data, struct kvm_kpit_state, pit_timer.timer); | ||
244 | |||
245 | restart_timer = __pit_timer_fn(ps); | ||
246 | |||
247 | if (restart_timer) | ||
248 | return HRTIMER_RESTART; | ||
249 | else | ||
250 | return HRTIMER_NORESTART; | ||
251 | } | ||
252 | |||
253 | void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu) | 247 | void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu) |
254 | { | 248 | { |
255 | struct kvm_pit *pit = vcpu->kvm->arch.vpit; | 249 | struct kvm_pit *pit = vcpu->kvm->arch.vpit; |
@@ -263,15 +257,26 @@ void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu) | |||
263 | hrtimer_start_expires(timer, HRTIMER_MODE_ABS); | 257 | hrtimer_start_expires(timer, HRTIMER_MODE_ABS); |
264 | } | 258 | } |
265 | 259 | ||
266 | static void destroy_pit_timer(struct kvm_kpit_timer *pt) | 260 | static void destroy_pit_timer(struct kvm_timer *pt) |
267 | { | 261 | { |
268 | pr_debug("pit: execute del timer!\n"); | 262 | pr_debug("pit: execute del timer!\n"); |
269 | hrtimer_cancel(&pt->timer); | 263 | hrtimer_cancel(&pt->timer); |
270 | } | 264 | } |
271 | 265 | ||
266 | static bool kpit_is_periodic(struct kvm_timer *ktimer) | ||
267 | { | ||
268 | struct kvm_kpit_state *ps = container_of(ktimer, struct kvm_kpit_state, | ||
269 | pit_timer); | ||
270 | return ps->is_periodic; | ||
271 | } | ||
272 | |||
273 | static struct kvm_timer_ops kpit_ops = { | ||
274 | .is_periodic = kpit_is_periodic, | ||
275 | }; | ||
276 | |||
272 | static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period) | 277 | static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period) |
273 | { | 278 | { |
274 | struct kvm_kpit_timer *pt = &ps->pit_timer; | 279 | struct kvm_timer *pt = &ps->pit_timer; |
275 | s64 interval; | 280 | s64 interval; |
276 | 281 | ||
277 | interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ); | 282 | interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ); |
@@ -280,8 +285,14 @@ static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period) | |||
280 | 285 | ||
281 | /* TODO The new value only affected after the retriggered */ | 286 | /* TODO The new value only affected after the retriggered */ |
282 | hrtimer_cancel(&pt->timer); | 287 | hrtimer_cancel(&pt->timer); |
283 | pt->period = (is_period == 0) ? 0 : interval; | 288 | pt->period = interval; |
284 | pt->timer.function = pit_timer_fn; | 289 | ps->is_periodic = is_period; |
290 | |||
291 | pt->timer.function = kvm_timer_fn; | ||
292 | pt->t_ops = &kpit_ops; | ||
293 | pt->kvm = ps->pit->kvm; | ||
294 | pt->vcpu_id = 0; | ||
295 | |||
285 | atomic_set(&pt->pending, 0); | 296 | atomic_set(&pt->pending, 0); |
286 | ps->irq_ack = 1; | 297 | ps->irq_ack = 1; |
287 | 298 | ||
@@ -298,23 +309,23 @@ static void pit_load_count(struct kvm *kvm, int channel, u32 val) | |||
298 | pr_debug("pit: load_count val is %d, channel is %d\n", val, channel); | 309 | pr_debug("pit: load_count val is %d, channel is %d\n", val, channel); |
299 | 310 | ||
300 | /* | 311 | /* |
301 | * Though spec said the state of 8254 is undefined after power-up, | 312 | * The largest possible initial count is 0; this is equivalent |
302 | * seems some tricky OS like Windows XP depends on IRQ0 interrupt | 313 | * to 216 for binary counting and 104 for BCD counting. |
303 | * when booting up. | ||
304 | * So here setting initialize rate for it, and not a specific number | ||
305 | */ | 314 | */ |
306 | if (val == 0) | 315 | if (val == 0) |
307 | val = 0x10000; | 316 | val = 0x10000; |
308 | 317 | ||
309 | ps->channels[channel].count_load_time = ktime_get(); | ||
310 | ps->channels[channel].count = val; | 318 | ps->channels[channel].count = val; |
311 | 319 | ||
312 | if (channel != 0) | 320 | if (channel != 0) { |
321 | ps->channels[channel].count_load_time = ktime_get(); | ||
313 | return; | 322 | return; |
323 | } | ||
314 | 324 | ||
315 | /* Two types of timer | 325 | /* Two types of timer |
316 | * mode 1 is one shot, mode 2 is period, otherwise del timer */ | 326 | * mode 1 is one shot, mode 2 is period, otherwise del timer */ |
317 | switch (ps->channels[0].mode) { | 327 | switch (ps->channels[0].mode) { |
328 | case 0: | ||
318 | case 1: | 329 | case 1: |
319 | /* FIXME: enhance mode 4 precision */ | 330 | /* FIXME: enhance mode 4 precision */ |
320 | case 4: | 331 | case 4: |