diff options
author | Arnd Bergmann <arnd@arndb.de> | 2009-06-12 03:53:47 -0400 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2009-06-12 05:32:58 -0400 |
commit | 5b02ee3d219f9e01b6e9146e25613822cfc2e5ce (patch) | |
tree | 7ce9126738c3cf4b37d67170d0e4b34818c057a9 /arch/x86/kvm/lapic.c | |
parent | 26a28fa4fea5b8c65713aa50c124f76a88c7924d (diff) | |
parent | 8ebf975608aaebd7feb33d77f07ba21a6380e086 (diff) |
asm-generic: merge branch 'master' of torvalds/linux-2.6
Fixes a merge conflict against the x86 tree caused by a fix to
atomic.h which I renamed to atomic_long.h.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/x86/kvm/lapic.c')
-rw-r--r-- | arch/x86/kvm/lapic.c | 251 |
1 files changed, 86 insertions, 165 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index f0b67f2cdd69..ae99d83f81a3 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -196,20 +196,15 @@ int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu) | |||
196 | } | 196 | } |
197 | EXPORT_SYMBOL_GPL(kvm_lapic_find_highest_irr); | 197 | EXPORT_SYMBOL_GPL(kvm_lapic_find_highest_irr); |
198 | 198 | ||
199 | int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig) | 199 | static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, |
200 | int vector, int level, int trig_mode); | ||
201 | |||
202 | int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq) | ||
200 | { | 203 | { |
201 | struct kvm_lapic *apic = vcpu->arch.apic; | 204 | struct kvm_lapic *apic = vcpu->arch.apic; |
202 | 205 | ||
203 | if (!apic_test_and_set_irr(vec, apic)) { | 206 | return __apic_accept_irq(apic, irq->delivery_mode, irq->vector, |
204 | /* a new pending irq is set in IRR */ | 207 | irq->level, irq->trig_mode); |
205 | if (trig) | ||
206 | apic_set_vector(vec, apic->regs + APIC_TMR); | ||
207 | else | ||
208 | apic_clear_vector(vec, apic->regs + APIC_TMR); | ||
209 | kvm_vcpu_kick(apic->vcpu); | ||
210 | return 1; | ||
211 | } | ||
212 | return 0; | ||
213 | } | 208 | } |
214 | 209 | ||
215 | static inline int apic_find_highest_isr(struct kvm_lapic *apic) | 210 | static inline int apic_find_highest_isr(struct kvm_lapic *apic) |
@@ -250,7 +245,7 @@ static void apic_set_tpr(struct kvm_lapic *apic, u32 tpr) | |||
250 | 245 | ||
251 | int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest) | 246 | int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest) |
252 | { | 247 | { |
253 | return kvm_apic_id(apic) == dest; | 248 | return dest == 0xff || kvm_apic_id(apic) == dest; |
254 | } | 249 | } |
255 | 250 | ||
256 | int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda) | 251 | int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda) |
@@ -279,37 +274,34 @@ int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda) | |||
279 | return result; | 274 | return result; |
280 | } | 275 | } |
281 | 276 | ||
282 | static int apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, | 277 | int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, |
283 | int short_hand, int dest, int dest_mode) | 278 | int short_hand, int dest, int dest_mode) |
284 | { | 279 | { |
285 | int result = 0; | 280 | int result = 0; |
286 | struct kvm_lapic *target = vcpu->arch.apic; | 281 | struct kvm_lapic *target = vcpu->arch.apic; |
287 | 282 | ||
288 | apic_debug("target %p, source %p, dest 0x%x, " | 283 | apic_debug("target %p, source %p, dest 0x%x, " |
289 | "dest_mode 0x%x, short_hand 0x%x", | 284 | "dest_mode 0x%x, short_hand 0x%x\n", |
290 | target, source, dest, dest_mode, short_hand); | 285 | target, source, dest, dest_mode, short_hand); |
291 | 286 | ||
292 | ASSERT(!target); | 287 | ASSERT(!target); |
293 | switch (short_hand) { | 288 | switch (short_hand) { |
294 | case APIC_DEST_NOSHORT: | 289 | case APIC_DEST_NOSHORT: |
295 | if (dest_mode == 0) { | 290 | if (dest_mode == 0) |
296 | /* Physical mode. */ | 291 | /* Physical mode. */ |
297 | if ((dest == 0xFF) || (dest == kvm_apic_id(target))) | 292 | result = kvm_apic_match_physical_addr(target, dest); |
298 | result = 1; | 293 | else |
299 | } else | ||
300 | /* Logical mode. */ | 294 | /* Logical mode. */ |
301 | result = kvm_apic_match_logical_addr(target, dest); | 295 | result = kvm_apic_match_logical_addr(target, dest); |
302 | break; | 296 | break; |
303 | case APIC_DEST_SELF: | 297 | case APIC_DEST_SELF: |
304 | if (target == source) | 298 | result = (target == source); |
305 | result = 1; | ||
306 | break; | 299 | break; |
307 | case APIC_DEST_ALLINC: | 300 | case APIC_DEST_ALLINC: |
308 | result = 1; | 301 | result = 1; |
309 | break; | 302 | break; |
310 | case APIC_DEST_ALLBUT: | 303 | case APIC_DEST_ALLBUT: |
311 | if (target != source) | 304 | result = (target != source); |
312 | result = 1; | ||
313 | break; | 305 | break; |
314 | default: | 306 | default: |
315 | printk(KERN_WARNING "Bad dest shorthand value %x\n", | 307 | printk(KERN_WARNING "Bad dest shorthand value %x\n", |
@@ -327,20 +319,22 @@ static int apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, | |||
327 | static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, | 319 | static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, |
328 | int vector, int level, int trig_mode) | 320 | int vector, int level, int trig_mode) |
329 | { | 321 | { |
330 | int orig_irr, result = 0; | 322 | int result = 0; |
331 | struct kvm_vcpu *vcpu = apic->vcpu; | 323 | struct kvm_vcpu *vcpu = apic->vcpu; |
332 | 324 | ||
333 | switch (delivery_mode) { | 325 | switch (delivery_mode) { |
334 | case APIC_DM_FIXED: | ||
335 | case APIC_DM_LOWEST: | 326 | case APIC_DM_LOWEST: |
327 | vcpu->arch.apic_arb_prio++; | ||
328 | case APIC_DM_FIXED: | ||
336 | /* FIXME add logic for vcpu on reset */ | 329 | /* FIXME add logic for vcpu on reset */ |
337 | if (unlikely(!apic_enabled(apic))) | 330 | if (unlikely(!apic_enabled(apic))) |
338 | break; | 331 | break; |
339 | 332 | ||
340 | orig_irr = apic_test_and_set_irr(vector, apic); | 333 | result = !apic_test_and_set_irr(vector, apic); |
341 | if (orig_irr && trig_mode) { | 334 | if (!result) { |
342 | apic_debug("level trig mode repeatedly for vector %d", | 335 | if (trig_mode) |
343 | vector); | 336 | apic_debug("level trig mode repeatedly for " |
337 | "vector %d", vector); | ||
344 | break; | 338 | break; |
345 | } | 339 | } |
346 | 340 | ||
@@ -349,10 +343,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, | |||
349 | apic_set_vector(vector, apic->regs + APIC_TMR); | 343 | apic_set_vector(vector, apic->regs + APIC_TMR); |
350 | } else | 344 | } else |
351 | apic_clear_vector(vector, apic->regs + APIC_TMR); | 345 | apic_clear_vector(vector, apic->regs + APIC_TMR); |
352 | |||
353 | kvm_vcpu_kick(vcpu); | 346 | kvm_vcpu_kick(vcpu); |
354 | |||
355 | result = (orig_irr == 0); | ||
356 | break; | 347 | break; |
357 | 348 | ||
358 | case APIC_DM_REMRD: | 349 | case APIC_DM_REMRD: |
@@ -364,12 +355,14 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, | |||
364 | break; | 355 | break; |
365 | 356 | ||
366 | case APIC_DM_NMI: | 357 | case APIC_DM_NMI: |
358 | result = 1; | ||
367 | kvm_inject_nmi(vcpu); | 359 | kvm_inject_nmi(vcpu); |
368 | kvm_vcpu_kick(vcpu); | 360 | kvm_vcpu_kick(vcpu); |
369 | break; | 361 | break; |
370 | 362 | ||
371 | case APIC_DM_INIT: | 363 | case APIC_DM_INIT: |
372 | if (level) { | 364 | if (level) { |
365 | result = 1; | ||
373 | if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE) | 366 | if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE) |
374 | printk(KERN_DEBUG | 367 | printk(KERN_DEBUG |
375 | "INIT on a runnable vcpu %d\n", | 368 | "INIT on a runnable vcpu %d\n", |
@@ -386,6 +379,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, | |||
386 | apic_debug("SIPI to vcpu %d vector 0x%02x\n", | 379 | apic_debug("SIPI to vcpu %d vector 0x%02x\n", |
387 | vcpu->vcpu_id, vector); | 380 | vcpu->vcpu_id, vector); |
388 | if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) { | 381 | if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) { |
382 | result = 1; | ||
389 | vcpu->arch.sipi_vector = vector; | 383 | vcpu->arch.sipi_vector = vector; |
390 | vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED; | 384 | vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED; |
391 | kvm_vcpu_kick(vcpu); | 385 | kvm_vcpu_kick(vcpu); |
@@ -408,43 +402,9 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, | |||
408 | return result; | 402 | return result; |
409 | } | 403 | } |
410 | 404 | ||
411 | static struct kvm_lapic *kvm_apic_round_robin(struct kvm *kvm, u8 vector, | 405 | int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2) |
412 | unsigned long bitmap) | ||
413 | { | ||
414 | int last; | ||
415 | int next; | ||
416 | struct kvm_lapic *apic = NULL; | ||
417 | |||
418 | last = kvm->arch.round_robin_prev_vcpu; | ||
419 | next = last; | ||
420 | |||
421 | do { | ||
422 | if (++next == KVM_MAX_VCPUS) | ||
423 | next = 0; | ||
424 | if (kvm->vcpus[next] == NULL || !test_bit(next, &bitmap)) | ||
425 | continue; | ||
426 | apic = kvm->vcpus[next]->arch.apic; | ||
427 | if (apic && apic_enabled(apic)) | ||
428 | break; | ||
429 | apic = NULL; | ||
430 | } while (next != last); | ||
431 | kvm->arch.round_robin_prev_vcpu = next; | ||
432 | |||
433 | if (!apic) | ||
434 | printk(KERN_DEBUG "vcpu not ready for apic_round_robin\n"); | ||
435 | |||
436 | return apic; | ||
437 | } | ||
438 | |||
439 | struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector, | ||
440 | unsigned long bitmap) | ||
441 | { | 406 | { |
442 | struct kvm_lapic *apic; | 407 | return vcpu1->arch.apic_arb_prio - vcpu2->arch.apic_arb_prio; |
443 | |||
444 | apic = kvm_apic_round_robin(kvm, vector, bitmap); | ||
445 | if (apic) | ||
446 | return apic->vcpu; | ||
447 | return NULL; | ||
448 | } | 408 | } |
449 | 409 | ||
450 | static void apic_set_eoi(struct kvm_lapic *apic) | 410 | static void apic_set_eoi(struct kvm_lapic *apic) |
@@ -472,47 +432,24 @@ static void apic_send_ipi(struct kvm_lapic *apic) | |||
472 | { | 432 | { |
473 | u32 icr_low = apic_get_reg(apic, APIC_ICR); | 433 | u32 icr_low = apic_get_reg(apic, APIC_ICR); |
474 | u32 icr_high = apic_get_reg(apic, APIC_ICR2); | 434 | u32 icr_high = apic_get_reg(apic, APIC_ICR2); |
435 | struct kvm_lapic_irq irq; | ||
475 | 436 | ||
476 | unsigned int dest = GET_APIC_DEST_FIELD(icr_high); | 437 | irq.vector = icr_low & APIC_VECTOR_MASK; |
477 | unsigned int short_hand = icr_low & APIC_SHORT_MASK; | 438 | irq.delivery_mode = icr_low & APIC_MODE_MASK; |
478 | unsigned int trig_mode = icr_low & APIC_INT_LEVELTRIG; | 439 | irq.dest_mode = icr_low & APIC_DEST_MASK; |
479 | unsigned int level = icr_low & APIC_INT_ASSERT; | 440 | irq.level = icr_low & APIC_INT_ASSERT; |
480 | unsigned int dest_mode = icr_low & APIC_DEST_MASK; | 441 | irq.trig_mode = icr_low & APIC_INT_LEVELTRIG; |
481 | unsigned int delivery_mode = icr_low & APIC_MODE_MASK; | 442 | irq.shorthand = icr_low & APIC_SHORT_MASK; |
482 | unsigned int vector = icr_low & APIC_VECTOR_MASK; | 443 | irq.dest_id = GET_APIC_DEST_FIELD(icr_high); |
483 | |||
484 | struct kvm_vcpu *target; | ||
485 | struct kvm_vcpu *vcpu; | ||
486 | unsigned long lpr_map = 0; | ||
487 | int i; | ||
488 | 444 | ||
489 | apic_debug("icr_high 0x%x, icr_low 0x%x, " | 445 | apic_debug("icr_high 0x%x, icr_low 0x%x, " |
490 | "short_hand 0x%x, dest 0x%x, trig_mode 0x%x, level 0x%x, " | 446 | "short_hand 0x%x, dest 0x%x, trig_mode 0x%x, level 0x%x, " |
491 | "dest_mode 0x%x, delivery_mode 0x%x, vector 0x%x\n", | 447 | "dest_mode 0x%x, delivery_mode 0x%x, vector 0x%x\n", |
492 | icr_high, icr_low, short_hand, dest, | 448 | icr_high, icr_low, irq.shorthand, irq.dest_id, |
493 | trig_mode, level, dest_mode, delivery_mode, vector); | 449 | irq.trig_mode, irq.level, irq.dest_mode, irq.delivery_mode, |
494 | 450 | irq.vector); | |
495 | for (i = 0; i < KVM_MAX_VCPUS; i++) { | ||
496 | vcpu = apic->vcpu->kvm->vcpus[i]; | ||
497 | if (!vcpu) | ||
498 | continue; | ||
499 | |||
500 | if (vcpu->arch.apic && | ||
501 | apic_match_dest(vcpu, apic, short_hand, dest, dest_mode)) { | ||
502 | if (delivery_mode == APIC_DM_LOWEST) | ||
503 | set_bit(vcpu->vcpu_id, &lpr_map); | ||
504 | else | ||
505 | __apic_accept_irq(vcpu->arch.apic, delivery_mode, | ||
506 | vector, level, trig_mode); | ||
507 | } | ||
508 | } | ||
509 | 451 | ||
510 | if (delivery_mode == APIC_DM_LOWEST) { | 452 | kvm_irq_delivery_to_apic(apic->vcpu->kvm, apic, &irq); |
511 | target = kvm_get_lowest_prio_vcpu(vcpu->kvm, vector, lpr_map); | ||
512 | if (target != NULL) | ||
513 | __apic_accept_irq(target->arch.apic, delivery_mode, | ||
514 | vector, level, trig_mode); | ||
515 | } | ||
516 | } | 453 | } |
517 | 454 | ||
518 | static u32 apic_get_tmcct(struct kvm_lapic *apic) | 455 | static u32 apic_get_tmcct(struct kvm_lapic *apic) |
@@ -527,12 +464,13 @@ static u32 apic_get_tmcct(struct kvm_lapic *apic) | |||
527 | if (apic_get_reg(apic, APIC_TMICT) == 0) | 464 | if (apic_get_reg(apic, APIC_TMICT) == 0) |
528 | return 0; | 465 | return 0; |
529 | 466 | ||
530 | remaining = hrtimer_expires_remaining(&apic->timer.dev); | 467 | remaining = hrtimer_expires_remaining(&apic->lapic_timer.timer); |
531 | if (ktime_to_ns(remaining) < 0) | 468 | if (ktime_to_ns(remaining) < 0) |
532 | remaining = ktime_set(0, 0); | 469 | remaining = ktime_set(0, 0); |
533 | 470 | ||
534 | ns = mod_64(ktime_to_ns(remaining), apic->timer.period); | 471 | ns = mod_64(ktime_to_ns(remaining), apic->lapic_timer.period); |
535 | tmcct = div64_u64(ns, (APIC_BUS_CYCLE_NS * apic->timer.divide_count)); | 472 | tmcct = div64_u64(ns, |
473 | (APIC_BUS_CYCLE_NS * apic->divide_count)); | ||
536 | 474 | ||
537 | return tmcct; | 475 | return tmcct; |
538 | } | 476 | } |
@@ -619,25 +557,25 @@ static void update_divide_count(struct kvm_lapic *apic) | |||
619 | tdcr = apic_get_reg(apic, APIC_TDCR); | 557 | tdcr = apic_get_reg(apic, APIC_TDCR); |
620 | tmp1 = tdcr & 0xf; | 558 | tmp1 = tdcr & 0xf; |
621 | tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1; | 559 | tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1; |
622 | apic->timer.divide_count = 0x1 << (tmp2 & 0x7); | 560 | apic->divide_count = 0x1 << (tmp2 & 0x7); |
623 | 561 | ||
624 | apic_debug("timer divide count is 0x%x\n", | 562 | apic_debug("timer divide count is 0x%x\n", |
625 | apic->timer.divide_count); | 563 | apic->divide_count); |
626 | } | 564 | } |
627 | 565 | ||
628 | static void start_apic_timer(struct kvm_lapic *apic) | 566 | static void start_apic_timer(struct kvm_lapic *apic) |
629 | { | 567 | { |
630 | ktime_t now = apic->timer.dev.base->get_time(); | 568 | ktime_t now = apic->lapic_timer.timer.base->get_time(); |
631 | 569 | ||
632 | apic->timer.period = apic_get_reg(apic, APIC_TMICT) * | 570 | apic->lapic_timer.period = apic_get_reg(apic, APIC_TMICT) * |
633 | APIC_BUS_CYCLE_NS * apic->timer.divide_count; | 571 | APIC_BUS_CYCLE_NS * apic->divide_count; |
634 | atomic_set(&apic->timer.pending, 0); | 572 | atomic_set(&apic->lapic_timer.pending, 0); |
635 | 573 | ||
636 | if (!apic->timer.period) | 574 | if (!apic->lapic_timer.period) |
637 | return; | 575 | return; |
638 | 576 | ||
639 | hrtimer_start(&apic->timer.dev, | 577 | hrtimer_start(&apic->lapic_timer.timer, |
640 | ktime_add_ns(now, apic->timer.period), | 578 | ktime_add_ns(now, apic->lapic_timer.period), |
641 | HRTIMER_MODE_ABS); | 579 | HRTIMER_MODE_ABS); |
642 | 580 | ||
643 | apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016" | 581 | apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016" |
@@ -646,9 +584,9 @@ static void start_apic_timer(struct kvm_lapic *apic) | |||
646 | "expire @ 0x%016" PRIx64 ".\n", __func__, | 584 | "expire @ 0x%016" PRIx64 ".\n", __func__, |
647 | APIC_BUS_CYCLE_NS, ktime_to_ns(now), | 585 | APIC_BUS_CYCLE_NS, ktime_to_ns(now), |
648 | apic_get_reg(apic, APIC_TMICT), | 586 | apic_get_reg(apic, APIC_TMICT), |
649 | apic->timer.period, | 587 | apic->lapic_timer.period, |
650 | ktime_to_ns(ktime_add_ns(now, | 588 | ktime_to_ns(ktime_add_ns(now, |
651 | apic->timer.period))); | 589 | apic->lapic_timer.period))); |
652 | } | 590 | } |
653 | 591 | ||
654 | static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val) | 592 | static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val) |
@@ -730,7 +668,7 @@ static void apic_mmio_write(struct kvm_io_device *this, | |||
730 | apic_set_reg(apic, APIC_LVTT + 0x10 * i, | 668 | apic_set_reg(apic, APIC_LVTT + 0x10 * i, |
731 | lvt_val | APIC_LVT_MASKED); | 669 | lvt_val | APIC_LVT_MASKED); |
732 | } | 670 | } |
733 | atomic_set(&apic->timer.pending, 0); | 671 | atomic_set(&apic->lapic_timer.pending, 0); |
734 | 672 | ||
735 | } | 673 | } |
736 | break; | 674 | break; |
@@ -762,7 +700,7 @@ static void apic_mmio_write(struct kvm_io_device *this, | |||
762 | break; | 700 | break; |
763 | 701 | ||
764 | case APIC_TMICT: | 702 | case APIC_TMICT: |
765 | hrtimer_cancel(&apic->timer.dev); | 703 | hrtimer_cancel(&apic->lapic_timer.timer); |
766 | apic_set_reg(apic, APIC_TMICT, val); | 704 | apic_set_reg(apic, APIC_TMICT, val); |
767 | start_apic_timer(apic); | 705 | start_apic_timer(apic); |
768 | return; | 706 | return; |
@@ -802,7 +740,7 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu) | |||
802 | if (!vcpu->arch.apic) | 740 | if (!vcpu->arch.apic) |
803 | return; | 741 | return; |
804 | 742 | ||
805 | hrtimer_cancel(&vcpu->arch.apic->timer.dev); | 743 | hrtimer_cancel(&vcpu->arch.apic->lapic_timer.timer); |
806 | 744 | ||
807 | if (vcpu->arch.apic->regs_page) | 745 | if (vcpu->arch.apic->regs_page) |
808 | __free_page(vcpu->arch.apic->regs_page); | 746 | __free_page(vcpu->arch.apic->regs_page); |
@@ -880,7 +818,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu) | |||
880 | ASSERT(apic != NULL); | 818 | ASSERT(apic != NULL); |
881 | 819 | ||
882 | /* Stop the timer in case it's a reset to an active apic */ | 820 | /* Stop the timer in case it's a reset to an active apic */ |
883 | hrtimer_cancel(&apic->timer.dev); | 821 | hrtimer_cancel(&apic->lapic_timer.timer); |
884 | 822 | ||
885 | apic_set_reg(apic, APIC_ID, vcpu->vcpu_id << 24); | 823 | apic_set_reg(apic, APIC_ID, vcpu->vcpu_id << 24); |
886 | apic_set_reg(apic, APIC_LVR, APIC_VERSION); | 824 | apic_set_reg(apic, APIC_LVR, APIC_VERSION); |
@@ -905,11 +843,13 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu) | |||
905 | apic_set_reg(apic, APIC_TMR + 0x10 * i, 0); | 843 | apic_set_reg(apic, APIC_TMR + 0x10 * i, 0); |
906 | } | 844 | } |
907 | update_divide_count(apic); | 845 | update_divide_count(apic); |
908 | atomic_set(&apic->timer.pending, 0); | 846 | atomic_set(&apic->lapic_timer.pending, 0); |
909 | if (vcpu->vcpu_id == 0) | 847 | if (vcpu->vcpu_id == 0) |
910 | vcpu->arch.apic_base |= MSR_IA32_APICBASE_BSP; | 848 | vcpu->arch.apic_base |= MSR_IA32_APICBASE_BSP; |
911 | apic_update_ppr(apic); | 849 | apic_update_ppr(apic); |
912 | 850 | ||
851 | vcpu->arch.apic_arb_prio = 0; | ||
852 | |||
913 | apic_debug(KERN_INFO "%s: vcpu=%p, id=%d, base_msr=" | 853 | apic_debug(KERN_INFO "%s: vcpu=%p, id=%d, base_msr=" |
914 | "0x%016" PRIx64 ", base_address=0x%0lx.\n", __func__, | 854 | "0x%016" PRIx64 ", base_address=0x%0lx.\n", __func__, |
915 | vcpu, kvm_apic_id(apic), | 855 | vcpu, kvm_apic_id(apic), |
@@ -917,16 +857,14 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu) | |||
917 | } | 857 | } |
918 | EXPORT_SYMBOL_GPL(kvm_lapic_reset); | 858 | EXPORT_SYMBOL_GPL(kvm_lapic_reset); |
919 | 859 | ||
920 | int kvm_lapic_enabled(struct kvm_vcpu *vcpu) | 860 | bool kvm_apic_present(struct kvm_vcpu *vcpu) |
921 | { | 861 | { |
922 | struct kvm_lapic *apic = vcpu->arch.apic; | 862 | return vcpu->arch.apic && apic_hw_enabled(vcpu->arch.apic); |
923 | int ret = 0; | 863 | } |
924 | |||
925 | if (!apic) | ||
926 | return 0; | ||
927 | ret = apic_enabled(apic); | ||
928 | 864 | ||
929 | return ret; | 865 | int kvm_lapic_enabled(struct kvm_vcpu *vcpu) |
866 | { | ||
867 | return kvm_apic_present(vcpu) && apic_sw_enabled(vcpu->arch.apic); | ||
930 | } | 868 | } |
931 | EXPORT_SYMBOL_GPL(kvm_lapic_enabled); | 869 | EXPORT_SYMBOL_GPL(kvm_lapic_enabled); |
932 | 870 | ||
@@ -936,22 +874,11 @@ EXPORT_SYMBOL_GPL(kvm_lapic_enabled); | |||
936 | *---------------------------------------------------------------------- | 874 | *---------------------------------------------------------------------- |
937 | */ | 875 | */ |
938 | 876 | ||
939 | /* TODO: make sure __apic_timer_fn runs in current pCPU */ | 877 | static bool lapic_is_periodic(struct kvm_timer *ktimer) |
940 | static int __apic_timer_fn(struct kvm_lapic *apic) | ||
941 | { | 878 | { |
942 | int result = 0; | 879 | struct kvm_lapic *apic = container_of(ktimer, struct kvm_lapic, |
943 | wait_queue_head_t *q = &apic->vcpu->wq; | 880 | lapic_timer); |
944 | 881 | return apic_lvtt_period(apic); | |
945 | if(!atomic_inc_and_test(&apic->timer.pending)) | ||
946 | set_bit(KVM_REQ_PENDING_TIMER, &apic->vcpu->requests); | ||
947 | if (waitqueue_active(q)) | ||
948 | wake_up_interruptible(q); | ||
949 | |||
950 | if (apic_lvtt_period(apic)) { | ||
951 | result = 1; | ||
952 | hrtimer_add_expires_ns(&apic->timer.dev, apic->timer.period); | ||
953 | } | ||
954 | return result; | ||
955 | } | 882 | } |
956 | 883 | ||
957 | int apic_has_pending_timer(struct kvm_vcpu *vcpu) | 884 | int apic_has_pending_timer(struct kvm_vcpu *vcpu) |
@@ -959,7 +886,7 @@ int apic_has_pending_timer(struct kvm_vcpu *vcpu) | |||
959 | struct kvm_lapic *lapic = vcpu->arch.apic; | 886 | struct kvm_lapic *lapic = vcpu->arch.apic; |
960 | 887 | ||
961 | if (lapic && apic_enabled(lapic) && apic_lvt_enabled(lapic, APIC_LVTT)) | 888 | if (lapic && apic_enabled(lapic) && apic_lvt_enabled(lapic, APIC_LVTT)) |
962 | return atomic_read(&lapic->timer.pending); | 889 | return atomic_read(&lapic->lapic_timer.pending); |
963 | 890 | ||
964 | return 0; | 891 | return 0; |
965 | } | 892 | } |
@@ -986,20 +913,9 @@ void kvm_apic_nmi_wd_deliver(struct kvm_vcpu *vcpu) | |||
986 | kvm_apic_local_deliver(apic, APIC_LVT0); | 913 | kvm_apic_local_deliver(apic, APIC_LVT0); |
987 | } | 914 | } |
988 | 915 | ||
989 | static enum hrtimer_restart apic_timer_fn(struct hrtimer *data) | 916 | static struct kvm_timer_ops lapic_timer_ops = { |
990 | { | 917 | .is_periodic = lapic_is_periodic, |
991 | struct kvm_lapic *apic; | 918 | }; |
992 | int restart_timer = 0; | ||
993 | |||
994 | apic = container_of(data, struct kvm_lapic, timer.dev); | ||
995 | |||
996 | restart_timer = __apic_timer_fn(apic); | ||
997 | |||
998 | if (restart_timer) | ||
999 | return HRTIMER_RESTART; | ||
1000 | else | ||
1001 | return HRTIMER_NORESTART; | ||
1002 | } | ||
1003 | 919 | ||
1004 | int kvm_create_lapic(struct kvm_vcpu *vcpu) | 920 | int kvm_create_lapic(struct kvm_vcpu *vcpu) |
1005 | { | 921 | { |
@@ -1024,8 +940,13 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu) | |||
1024 | memset(apic->regs, 0, PAGE_SIZE); | 940 | memset(apic->regs, 0, PAGE_SIZE); |
1025 | apic->vcpu = vcpu; | 941 | apic->vcpu = vcpu; |
1026 | 942 | ||
1027 | hrtimer_init(&apic->timer.dev, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | 943 | hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC, |
1028 | apic->timer.dev.function = apic_timer_fn; | 944 | HRTIMER_MODE_ABS); |
945 | apic->lapic_timer.timer.function = kvm_timer_fn; | ||
946 | apic->lapic_timer.t_ops = &lapic_timer_ops; | ||
947 | apic->lapic_timer.kvm = vcpu->kvm; | ||
948 | apic->lapic_timer.vcpu_id = vcpu->vcpu_id; | ||
949 | |||
1029 | apic->base_address = APIC_DEFAULT_PHYS_BASE; | 950 | apic->base_address = APIC_DEFAULT_PHYS_BASE; |
1030 | vcpu->arch.apic_base = APIC_DEFAULT_PHYS_BASE; | 951 | vcpu->arch.apic_base = APIC_DEFAULT_PHYS_BASE; |
1031 | 952 | ||
@@ -1078,9 +999,9 @@ void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu) | |||
1078 | { | 999 | { |
1079 | struct kvm_lapic *apic = vcpu->arch.apic; | 1000 | struct kvm_lapic *apic = vcpu->arch.apic; |
1080 | 1001 | ||
1081 | if (apic && atomic_read(&apic->timer.pending) > 0) { | 1002 | if (apic && atomic_read(&apic->lapic_timer.pending) > 0) { |
1082 | if (kvm_apic_local_deliver(apic, APIC_LVTT)) | 1003 | if (kvm_apic_local_deliver(apic, APIC_LVTT)) |
1083 | atomic_dec(&apic->timer.pending); | 1004 | atomic_dec(&apic->lapic_timer.pending); |
1084 | } | 1005 | } |
1085 | } | 1006 | } |
1086 | 1007 | ||
@@ -1106,7 +1027,7 @@ void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu) | |||
1106 | MSR_IA32_APICBASE_BASE; | 1027 | MSR_IA32_APICBASE_BASE; |
1107 | apic_set_reg(apic, APIC_LVR, APIC_VERSION); | 1028 | apic_set_reg(apic, APIC_LVR, APIC_VERSION); |
1108 | apic_update_ppr(apic); | 1029 | apic_update_ppr(apic); |
1109 | hrtimer_cancel(&apic->timer.dev); | 1030 | hrtimer_cancel(&apic->lapic_timer.timer); |
1110 | update_divide_count(apic); | 1031 | update_divide_count(apic); |
1111 | start_apic_timer(apic); | 1032 | start_apic_timer(apic); |
1112 | } | 1033 | } |
@@ -1119,7 +1040,7 @@ void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu) | |||
1119 | if (!apic) | 1040 | if (!apic) |
1120 | return; | 1041 | return; |
1121 | 1042 | ||
1122 | timer = &apic->timer.dev; | 1043 | timer = &apic->lapic_timer.timer; |
1123 | if (hrtimer_cancel(timer)) | 1044 | if (hrtimer_cancel(timer)) |
1124 | hrtimer_start_expires(timer, HRTIMER_MODE_ABS); | 1045 | hrtimer_start_expires(timer, HRTIMER_MODE_ABS); |
1125 | } | 1046 | } |