diff options
Diffstat (limited to 'arch/x86/kvm/lapic.c')
-rw-r--r-- | arch/x86/kvm/lapic.c | 167 |
1 files changed, 135 insertions, 32 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 57dcbd4308fa..54abb40199d6 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -68,6 +68,9 @@ | |||
68 | #define VEC_POS(v) ((v) & (32 - 1)) | 68 | #define VEC_POS(v) ((v) & (32 - 1)) |
69 | #define REG_POS(v) (((v) >> 5) << 4) | 69 | #define REG_POS(v) (((v) >> 5) << 4) |
70 | 70 | ||
71 | static unsigned int min_timer_period_us = 500; | ||
72 | module_param(min_timer_period_us, uint, S_IRUGO | S_IWUSR); | ||
73 | |||
71 | static inline u32 apic_get_reg(struct kvm_lapic *apic, int reg_off) | 74 | static inline u32 apic_get_reg(struct kvm_lapic *apic, int reg_off) |
72 | { | 75 | { |
73 | return *((u32 *) (apic->regs + reg_off)); | 76 | return *((u32 *) (apic->regs + reg_off)); |
@@ -135,9 +138,23 @@ static inline int apic_lvt_vector(struct kvm_lapic *apic, int lvt_type) | |||
135 | return apic_get_reg(apic, lvt_type) & APIC_VECTOR_MASK; | 138 | return apic_get_reg(apic, lvt_type) & APIC_VECTOR_MASK; |
136 | } | 139 | } |
137 | 140 | ||
141 | static inline int apic_lvtt_oneshot(struct kvm_lapic *apic) | ||
142 | { | ||
143 | return ((apic_get_reg(apic, APIC_LVTT) & | ||
144 | apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_ONESHOT); | ||
145 | } | ||
146 | |||
138 | static inline int apic_lvtt_period(struct kvm_lapic *apic) | 147 | static inline int apic_lvtt_period(struct kvm_lapic *apic) |
139 | { | 148 | { |
140 | return apic_get_reg(apic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC; | 149 | return ((apic_get_reg(apic, APIC_LVTT) & |
150 | apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_PERIODIC); | ||
151 | } | ||
152 | |||
153 | static inline int apic_lvtt_tscdeadline(struct kvm_lapic *apic) | ||
154 | { | ||
155 | return ((apic_get_reg(apic, APIC_LVTT) & | ||
156 | apic->lapic_timer.timer_mode_mask) == | ||
157 | APIC_LVT_TIMER_TSCDEADLINE); | ||
141 | } | 158 | } |
142 | 159 | ||
143 | static inline int apic_lvt_nmi_mode(u32 lvt_val) | 160 | static inline int apic_lvt_nmi_mode(u32 lvt_val) |
@@ -166,7 +183,7 @@ static inline int apic_x2apic_mode(struct kvm_lapic *apic) | |||
166 | } | 183 | } |
167 | 184 | ||
168 | static unsigned int apic_lvt_mask[APIC_LVT_NUM] = { | 185 | static unsigned int apic_lvt_mask[APIC_LVT_NUM] = { |
169 | LVT_MASK | APIC_LVT_TIMER_PERIODIC, /* LVTT */ | 186 | LVT_MASK , /* part LVTT mask, timer mode mask added at runtime */ |
170 | LVT_MASK | APIC_MODE_MASK, /* LVTTHMR */ | 187 | LVT_MASK | APIC_MODE_MASK, /* LVTTHMR */ |
171 | LVT_MASK | APIC_MODE_MASK, /* LVTPC */ | 188 | LVT_MASK | APIC_MODE_MASK, /* LVTPC */ |
172 | LINT_MASK, LINT_MASK, /* LVT0-1 */ | 189 | LINT_MASK, LINT_MASK, /* LVT0-1 */ |
@@ -316,8 +333,8 @@ int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda) | |||
316 | result = 1; | 333 | result = 1; |
317 | break; | 334 | break; |
318 | default: | 335 | default: |
319 | printk(KERN_WARNING "Bad DFR vcpu %d: %08x\n", | 336 | apic_debug("Bad DFR vcpu %d: %08x\n", |
320 | apic->vcpu->vcpu_id, apic_get_reg(apic, APIC_DFR)); | 337 | apic->vcpu->vcpu_id, apic_get_reg(apic, APIC_DFR)); |
321 | break; | 338 | break; |
322 | } | 339 | } |
323 | 340 | ||
@@ -354,8 +371,8 @@ int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, | |||
354 | result = (target != source); | 371 | result = (target != source); |
355 | break; | 372 | break; |
356 | default: | 373 | default: |
357 | printk(KERN_WARNING "Bad dest shorthand value %x\n", | 374 | apic_debug("kvm: apic: Bad dest shorthand value %x\n", |
358 | short_hand); | 375 | short_hand); |
359 | break; | 376 | break; |
360 | } | 377 | } |
361 | 378 | ||
@@ -401,11 +418,11 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, | |||
401 | break; | 418 | break; |
402 | 419 | ||
403 | case APIC_DM_REMRD: | 420 | case APIC_DM_REMRD: |
404 | printk(KERN_DEBUG "Ignoring delivery mode 3\n"); | 421 | apic_debug("Ignoring delivery mode 3\n"); |
405 | break; | 422 | break; |
406 | 423 | ||
407 | case APIC_DM_SMI: | 424 | case APIC_DM_SMI: |
408 | printk(KERN_DEBUG "Ignoring guest SMI\n"); | 425 | apic_debug("Ignoring guest SMI\n"); |
409 | break; | 426 | break; |
410 | 427 | ||
411 | case APIC_DM_NMI: | 428 | case APIC_DM_NMI: |
@@ -565,11 +582,13 @@ static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset) | |||
565 | val = kvm_apic_id(apic) << 24; | 582 | val = kvm_apic_id(apic) << 24; |
566 | break; | 583 | break; |
567 | case APIC_ARBPRI: | 584 | case APIC_ARBPRI: |
568 | printk(KERN_WARNING "Access APIC ARBPRI register " | 585 | apic_debug("Access APIC ARBPRI register which is for P6\n"); |
569 | "which is for P6\n"); | ||
570 | break; | 586 | break; |
571 | 587 | ||
572 | case APIC_TMCCT: /* Timer CCR */ | 588 | case APIC_TMCCT: /* Timer CCR */ |
589 | if (apic_lvtt_tscdeadline(apic)) | ||
590 | return 0; | ||
591 | |||
573 | val = apic_get_tmcct(apic); | 592 | val = apic_get_tmcct(apic); |
574 | break; | 593 | break; |
575 | 594 | ||
@@ -664,29 +683,40 @@ static void update_divide_count(struct kvm_lapic *apic) | |||
664 | 683 | ||
665 | static void start_apic_timer(struct kvm_lapic *apic) | 684 | static void start_apic_timer(struct kvm_lapic *apic) |
666 | { | 685 | { |
667 | ktime_t now = apic->lapic_timer.timer.base->get_time(); | 686 | ktime_t now; |
668 | |||
669 | apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT) * | ||
670 | APIC_BUS_CYCLE_NS * apic->divide_count; | ||
671 | atomic_set(&apic->lapic_timer.pending, 0); | 687 | atomic_set(&apic->lapic_timer.pending, 0); |
672 | 688 | ||
673 | if (!apic->lapic_timer.period) | 689 | if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic)) { |
674 | return; | 690 | /* lapic timer in oneshot or peroidic mode */ |
675 | /* | 691 | now = apic->lapic_timer.timer.base->get_time(); |
676 | * Do not allow the guest to program periodic timers with small | 692 | apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT) |
677 | * interval, since the hrtimers are not throttled by the host | 693 | * APIC_BUS_CYCLE_NS * apic->divide_count; |
678 | * scheduler. | 694 | |
679 | */ | 695 | if (!apic->lapic_timer.period) |
680 | if (apic_lvtt_period(apic)) { | 696 | return; |
681 | if (apic->lapic_timer.period < NSEC_PER_MSEC/2) | 697 | /* |
682 | apic->lapic_timer.period = NSEC_PER_MSEC/2; | 698 | * Do not allow the guest to program periodic timers with small |
683 | } | 699 | * interval, since the hrtimers are not throttled by the host |
700 | * scheduler. | ||
701 | */ | ||
702 | if (apic_lvtt_period(apic)) { | ||
703 | s64 min_period = min_timer_period_us * 1000LL; | ||
704 | |||
705 | if (apic->lapic_timer.period < min_period) { | ||
706 | pr_info_ratelimited( | ||
707 | "kvm: vcpu %i: requested %lld ns " | ||
708 | "lapic timer period limited to %lld ns\n", | ||
709 | apic->vcpu->vcpu_id, | ||
710 | apic->lapic_timer.period, min_period); | ||
711 | apic->lapic_timer.period = min_period; | ||
712 | } | ||
713 | } | ||
684 | 714 | ||
685 | hrtimer_start(&apic->lapic_timer.timer, | 715 | hrtimer_start(&apic->lapic_timer.timer, |
686 | ktime_add_ns(now, apic->lapic_timer.period), | 716 | ktime_add_ns(now, apic->lapic_timer.period), |
687 | HRTIMER_MODE_ABS); | 717 | HRTIMER_MODE_ABS); |
688 | 718 | ||
689 | apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016" | 719 | apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016" |
690 | PRIx64 ", " | 720 | PRIx64 ", " |
691 | "timer initial count 0x%x, period %lldns, " | 721 | "timer initial count 0x%x, period %lldns, " |
692 | "expire @ 0x%016" PRIx64 ".\n", __func__, | 722 | "expire @ 0x%016" PRIx64 ".\n", __func__, |
@@ -695,6 +725,30 @@ static void start_apic_timer(struct kvm_lapic *apic) | |||
695 | apic->lapic_timer.period, | 725 | apic->lapic_timer.period, |
696 | ktime_to_ns(ktime_add_ns(now, | 726 | ktime_to_ns(ktime_add_ns(now, |
697 | apic->lapic_timer.period))); | 727 | apic->lapic_timer.period))); |
728 | } else if (apic_lvtt_tscdeadline(apic)) { | ||
729 | /* lapic timer in tsc deadline mode */ | ||
730 | u64 guest_tsc, tscdeadline = apic->lapic_timer.tscdeadline; | ||
731 | u64 ns = 0; | ||
732 | struct kvm_vcpu *vcpu = apic->vcpu; | ||
733 | unsigned long this_tsc_khz = vcpu_tsc_khz(vcpu); | ||
734 | unsigned long flags; | ||
735 | |||
736 | if (unlikely(!tscdeadline || !this_tsc_khz)) | ||
737 | return; | ||
738 | |||
739 | local_irq_save(flags); | ||
740 | |||
741 | now = apic->lapic_timer.timer.base->get_time(); | ||
742 | guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu); | ||
743 | if (likely(tscdeadline > guest_tsc)) { | ||
744 | ns = (tscdeadline - guest_tsc) * 1000000ULL; | ||
745 | do_div(ns, this_tsc_khz); | ||
746 | } | ||
747 | hrtimer_start(&apic->lapic_timer.timer, | ||
748 | ktime_add_ns(now, ns), HRTIMER_MODE_ABS); | ||
749 | |||
750 | local_irq_restore(flags); | ||
751 | } | ||
698 | } | 752 | } |
699 | 753 | ||
700 | static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val) | 754 | static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val) |
@@ -782,7 +836,6 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) | |||
782 | 836 | ||
783 | case APIC_LVT0: | 837 | case APIC_LVT0: |
784 | apic_manage_nmi_watchdog(apic, val); | 838 | apic_manage_nmi_watchdog(apic, val); |
785 | case APIC_LVTT: | ||
786 | case APIC_LVTTHMR: | 839 | case APIC_LVTTHMR: |
787 | case APIC_LVTPC: | 840 | case APIC_LVTPC: |
788 | case APIC_LVT1: | 841 | case APIC_LVT1: |
@@ -796,7 +849,22 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) | |||
796 | 849 | ||
797 | break; | 850 | break; |
798 | 851 | ||
852 | case APIC_LVTT: | ||
853 | if ((apic_get_reg(apic, APIC_LVTT) & | ||
854 | apic->lapic_timer.timer_mode_mask) != | ||
855 | (val & apic->lapic_timer.timer_mode_mask)) | ||
856 | hrtimer_cancel(&apic->lapic_timer.timer); | ||
857 | |||
858 | if (!apic_sw_enabled(apic)) | ||
859 | val |= APIC_LVT_MASKED; | ||
860 | val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask); | ||
861 | apic_set_reg(apic, APIC_LVTT, val); | ||
862 | break; | ||
863 | |||
799 | case APIC_TMICT: | 864 | case APIC_TMICT: |
865 | if (apic_lvtt_tscdeadline(apic)) | ||
866 | break; | ||
867 | |||
800 | hrtimer_cancel(&apic->lapic_timer.timer); | 868 | hrtimer_cancel(&apic->lapic_timer.timer); |
801 | apic_set_reg(apic, APIC_TMICT, val); | 869 | apic_set_reg(apic, APIC_TMICT, val); |
802 | start_apic_timer(apic); | 870 | start_apic_timer(apic); |
@@ -804,14 +872,14 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) | |||
804 | 872 | ||
805 | case APIC_TDCR: | 873 | case APIC_TDCR: |
806 | if (val & 4) | 874 | if (val & 4) |
807 | printk(KERN_ERR "KVM_WRITE:TDCR %x\n", val); | 875 | apic_debug("KVM_WRITE:TDCR %x\n", val); |
808 | apic_set_reg(apic, APIC_TDCR, val); | 876 | apic_set_reg(apic, APIC_TDCR, val); |
809 | update_divide_count(apic); | 877 | update_divide_count(apic); |
810 | break; | 878 | break; |
811 | 879 | ||
812 | case APIC_ESR: | 880 | case APIC_ESR: |
813 | if (apic_x2apic_mode(apic) && val != 0) { | 881 | if (apic_x2apic_mode(apic) && val != 0) { |
814 | printk(KERN_ERR "KVM_WRITE:ESR not zero %x\n", val); | 882 | apic_debug("KVM_WRITE:ESR not zero %x\n", val); |
815 | ret = 1; | 883 | ret = 1; |
816 | } | 884 | } |
817 | break; | 885 | break; |
@@ -864,6 +932,15 @@ static int apic_mmio_write(struct kvm_io_device *this, | |||
864 | return 0; | 932 | return 0; |
865 | } | 933 | } |
866 | 934 | ||
935 | void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu) | ||
936 | { | ||
937 | struct kvm_lapic *apic = vcpu->arch.apic; | ||
938 | |||
939 | if (apic) | ||
940 | apic_reg_write(vcpu->arch.apic, APIC_EOI, 0); | ||
941 | } | ||
942 | EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi); | ||
943 | |||
867 | void kvm_free_lapic(struct kvm_vcpu *vcpu) | 944 | void kvm_free_lapic(struct kvm_vcpu *vcpu) |
868 | { | 945 | { |
869 | if (!vcpu->arch.apic) | 946 | if (!vcpu->arch.apic) |
@@ -883,6 +960,32 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu) | |||
883 | *---------------------------------------------------------------------- | 960 | *---------------------------------------------------------------------- |
884 | */ | 961 | */ |
885 | 962 | ||
963 | u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu) | ||
964 | { | ||
965 | struct kvm_lapic *apic = vcpu->arch.apic; | ||
966 | if (!apic) | ||
967 | return 0; | ||
968 | |||
969 | if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic)) | ||
970 | return 0; | ||
971 | |||
972 | return apic->lapic_timer.tscdeadline; | ||
973 | } | ||
974 | |||
975 | void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data) | ||
976 | { | ||
977 | struct kvm_lapic *apic = vcpu->arch.apic; | ||
978 | if (!apic) | ||
979 | return; | ||
980 | |||
981 | if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic)) | ||
982 | return; | ||
983 | |||
984 | hrtimer_cancel(&apic->lapic_timer.timer); | ||
985 | apic->lapic_timer.tscdeadline = data; | ||
986 | start_apic_timer(apic); | ||
987 | } | ||
988 | |||
886 | void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8) | 989 | void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8) |
887 | { | 990 | { |
888 | struct kvm_lapic *apic = vcpu->arch.apic; | 991 | struct kvm_lapic *apic = vcpu->arch.apic; |