diff options
author | Yang Zhang <yang.z.zhang@Intel.com> | 2013-04-11 07:21:38 -0400 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2013-04-15 22:20:34 -0400 |
commit | 106069193ce501ea68649037bde7ea50ed492948 (patch) | |
tree | 3dea2fb1878a3c8a116b88258f1324591433aa84 | |
parent | b4f2225c07dd4d8eef7aa7f5b36a3b72c3cbbe5b (diff) |
KVM: Add reset/restore rtc_status support
restore rtc_status from migration or save/restore
Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com>
Reviewed-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r-- | arch/x86/kvm/lapic.c | 9 | ||||
-rw-r--r-- | arch/x86/kvm/lapic.h | 2 | ||||
-rw-r--r-- | virt/kvm/ioapic.c | 58 | ||||
-rw-r--r-- | virt/kvm/ioapic.h | 1 |
4 files changed, 70 insertions, 0 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 0b734025fc87..67962188c775 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -94,6 +94,14 @@ static inline int apic_test_vector(int vec, void *bitmap) | |||
94 | return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); | 94 | return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); |
95 | } | 95 | } |
96 | 96 | ||
97 | bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector) | ||
98 | { | ||
99 | struct kvm_lapic *apic = vcpu->arch.apic; | ||
100 | |||
101 | return apic_test_vector(vector, apic->regs + APIC_ISR) || | ||
102 | apic_test_vector(vector, apic->regs + APIC_IRR); | ||
103 | } | ||
104 | |||
97 | static inline void apic_set_vector(int vec, void *bitmap) | 105 | static inline void apic_set_vector(int vec, void *bitmap) |
98 | { | 106 | { |
99 | set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); | 107 | set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); |
@@ -1618,6 +1626,7 @@ void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu, | |||
1618 | apic->highest_isr_cache = -1; | 1626 | apic->highest_isr_cache = -1; |
1619 | kvm_x86_ops->hwapic_isr_update(vcpu->kvm, apic_find_highest_isr(apic)); | 1627 | kvm_x86_ops->hwapic_isr_update(vcpu->kvm, apic_find_highest_isr(apic)); |
1620 | kvm_make_request(KVM_REQ_EVENT, vcpu); | 1628 | kvm_make_request(KVM_REQ_EVENT, vcpu); |
1629 | kvm_rtc_eoi_tracking_restore_one(vcpu); | ||
1621 | } | 1630 | } |
1622 | 1631 | ||
1623 | void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu) | 1632 | void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu) |
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index 3e5a43160cb7..16304b1a8cba 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h | |||
@@ -166,4 +166,6 @@ static inline bool kvm_apic_has_events(struct kvm_vcpu *vcpu) | |||
166 | return vcpu->arch.apic->pending_events; | 166 | return vcpu->arch.apic->pending_events; |
167 | } | 167 | } |
168 | 168 | ||
169 | bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector); | ||
170 | |||
169 | #endif | 171 | #endif |
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 27ae8dd64e29..9d76baa78e89 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c | |||
@@ -90,6 +90,62 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic, | |||
90 | return result; | 90 | return result; |
91 | } | 91 | } |
92 | 92 | ||
93 | static void rtc_irq_eoi_tracking_reset(struct kvm_ioapic *ioapic) | ||
94 | { | ||
95 | ioapic->rtc_status.pending_eoi = 0; | ||
96 | bitmap_zero(ioapic->rtc_status.dest_map, KVM_MAX_VCPUS); | ||
97 | } | ||
98 | |||
99 | static void __rtc_irq_eoi_tracking_restore_one(struct kvm_vcpu *vcpu) | ||
100 | { | ||
101 | bool new_val, old_val; | ||
102 | struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic; | ||
103 | union kvm_ioapic_redirect_entry *e; | ||
104 | |||
105 | e = &ioapic->redirtbl[RTC_GSI]; | ||
106 | if (!kvm_apic_match_dest(vcpu, NULL, 0, e->fields.dest_id, | ||
107 | e->fields.dest_mode)) | ||
108 | return; | ||
109 | |||
110 | new_val = kvm_apic_pending_eoi(vcpu, e->fields.vector); | ||
111 | old_val = test_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map); | ||
112 | |||
113 | if (new_val == old_val) | ||
114 | return; | ||
115 | |||
116 | if (new_val) { | ||
117 | __set_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map); | ||
118 | ioapic->rtc_status.pending_eoi++; | ||
119 | } else { | ||
120 | __clear_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map); | ||
121 | ioapic->rtc_status.pending_eoi--; | ||
122 | } | ||
123 | |||
124 | WARN_ON(ioapic->rtc_status.pending_eoi < 0); | ||
125 | } | ||
126 | |||
127 | void kvm_rtc_eoi_tracking_restore_one(struct kvm_vcpu *vcpu) | ||
128 | { | ||
129 | struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic; | ||
130 | |||
131 | spin_lock(&ioapic->lock); | ||
132 | __rtc_irq_eoi_tracking_restore_one(vcpu); | ||
133 | spin_unlock(&ioapic->lock); | ||
134 | } | ||
135 | |||
136 | static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic) | ||
137 | { | ||
138 | struct kvm_vcpu *vcpu; | ||
139 | int i; | ||
140 | |||
141 | if (RTC_GSI >= IOAPIC_NUM_PINS) | ||
142 | return; | ||
143 | |||
144 | rtc_irq_eoi_tracking_reset(ioapic); | ||
145 | kvm_for_each_vcpu(i, vcpu, ioapic->kvm) | ||
146 | __rtc_irq_eoi_tracking_restore_one(vcpu); | ||
147 | } | ||
148 | |||
93 | static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) | 149 | static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) |
94 | { | 150 | { |
95 | union kvm_ioapic_redirect_entry *pent; | 151 | union kvm_ioapic_redirect_entry *pent; |
@@ -428,6 +484,7 @@ void kvm_ioapic_reset(struct kvm_ioapic *ioapic) | |||
428 | ioapic->ioregsel = 0; | 484 | ioapic->ioregsel = 0; |
429 | ioapic->irr = 0; | 485 | ioapic->irr = 0; |
430 | ioapic->id = 0; | 486 | ioapic->id = 0; |
487 | rtc_irq_eoi_tracking_reset(ioapic); | ||
431 | update_handled_vectors(ioapic); | 488 | update_handled_vectors(ioapic); |
432 | } | 489 | } |
433 | 490 | ||
@@ -494,6 +551,7 @@ int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state) | |||
494 | memcpy(ioapic, state, sizeof(struct kvm_ioapic_state)); | 551 | memcpy(ioapic, state, sizeof(struct kvm_ioapic_state)); |
495 | update_handled_vectors(ioapic); | 552 | update_handled_vectors(ioapic); |
496 | kvm_ioapic_make_eoibitmap_request(kvm); | 553 | kvm_ioapic_make_eoibitmap_request(kvm); |
554 | kvm_rtc_eoi_tracking_restore_all(ioapic); | ||
497 | spin_unlock(&ioapic->lock); | 555 | spin_unlock(&ioapic->lock); |
498 | return 0; | 556 | return 0; |
499 | } | 557 | } |
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h index 761e5b57099e..313fc4ea61d9 100644 --- a/virt/kvm/ioapic.h +++ b/virt/kvm/ioapic.h | |||
@@ -79,6 +79,7 @@ static inline struct kvm_ioapic *ioapic_irqchip(struct kvm *kvm) | |||
79 | return kvm->arch.vioapic; | 79 | return kvm->arch.vioapic; |
80 | } | 80 | } |
81 | 81 | ||
82 | void kvm_rtc_eoi_tracking_restore_one(struct kvm_vcpu *vcpu); | ||
82 | int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, | 83 | int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, |
83 | int short_hand, int dest, int dest_mode); | 84 | int short_hand, int dest, int dest_mode); |
84 | int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2); | 85 | int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2); |