Message ID | 1363334700-24507-6-git-send-email-yang.z.zhang@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Fri, Mar 15, 2013 at 04:05:00PM +0800, Yang Zhang wrote: > From: Yang Zhang <yang.z.zhang@Intel.com> > > Current interrupt coalescing logci which only used by RTC has conflict > with Posted Interrupt. > This patch introduces a new mechinism to use eoi to track interrupt: > When delivering an interrupt to vcpu, the need_eoi set to number of > vcpu that received the interrupt. And decrease it when each vcpu writing > eoi. No subsequent RTC interrupt can deliver to vcpu until all vcpus > write eoi. > > Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com> > --- > arch/x86/kvm/lapic.c | 2 +- > arch/x86/kvm/lapic.h | 1 + > virt/kvm/ioapic.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 107 insertions(+), 1 deletions(-) > > diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c > index ad97f1f..bf2d208 100644 > --- a/arch/x86/kvm/lapic.c > +++ b/arch/x86/kvm/lapic.c > @@ -89,7 +89,7 @@ static inline int apic_test_and_clear_vector(int vec, void *bitmap) > return test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); > } > > -static inline int apic_test_vector(int vec, void *bitmap) > +int apic_test_vector(int vec, void *bitmap) > { > return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); > } That's too low level to call from IOAPIC. Put kvm_apic_pending_eoi() here instead. > diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h > index 3a0f9d8..02da8b8 100644 > --- a/arch/x86/kvm/lapic.h > +++ b/arch/x86/kvm/lapic.h > @@ -84,6 +84,7 @@ static inline bool kvm_hv_vapic_assist_page_enabled(struct kvm_vcpu *vcpu) > > int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data); > void kvm_lapic_init(void); > +int apic_test_vector(int vec, void *bitmap); > > static inline u32 kvm_apic_get_reg(struct kvm_lapic *apic, int reg_off) > { > diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c > index 2c6235c..46cb8ed 100644 > --- a/virt/kvm/ioapic.c > +++ b/virt/kvm/ioapic.c > @@ -103,12 +103,110 @@ static void rtc_register_notifier(struct kvm_ioapic *ioapic) > kvm_register_irq_ack_notifier(ioapic->kvm, > &ioapic->rtc_status.irq_ack_notifier); > } > + > +static void rtc_irq_reset(struct kvm_ioapic *ioapic) > +{ > + ioapic->rtc_status.need_eoi = 0; > + bitmap_zero(ioapic->rtc_status.vcpu_map, KVM_MAX_VCPUS); > +} > + > +static void rtc_irq_restore(struct kvm_ioapic *ioapic) > +{ > + struct kvm_vcpu *vcpu; > + struct kvm_lapic *apic; > + int vector, i, need_eoi = 0, rtc_pin = 8; > + > + vector = ioapic->redirtbl[rtc_pin].fields.vector; > + kvm_for_each_vcpu(i, vcpu, ioapic->kvm) { > + apic = vcpu->arch.apic; > + if (apic_test_vector(vector, apic->regs + APIC_ISR) || > + apic_test_vector(vector, apic->regs + APIC_IRR)) { > + need_eoi++; > + set_bit(vcpu->vcpu_id, ioapic->rtc_status.vcpu_map); > + } > + } > + ioapic->rtc_status.need_eoi = need_eoi; > +} > + > +static void rtc_irq_update(struct kvm_ioapic *ioapic, > + struct kvm_lapic_irq *irqe, int irq) > +{ > + int weight; > + > + if (irq != 8) > + return; > + > + rtc_irq_reset(ioapic); > + > + kvm_get_dest_vcpu(ioapic->kvm, irqe, ioapic->rtc_status.vcpu_map); > + if (likely(!bitmap_empty(ioapic->rtc_status.vcpu_map, KVM_MAX_VCPUS))) { > + if (irqe->delivery_mode == APIC_DM_LOWEST) > + ioapic->rtc_status.need_eoi = 1; > + else { > + weight = bitmap_weight(ioapic->rtc_status.vcpu_map, > + sizeof(ioapic->rtc_status.vcpu_map)); > + ioapic->rtc_status.need_eoi = weight; > + } > + } > +} > + > +static void rtc_irq_ack_eoi(struct kvm_vcpu *vcpu, > + struct rtc_status *rtc_status, int irq) > +{ > + if (irq != 8) > + return; > + > + if (test_and_clear_bit(vcpu->vcpu_id, rtc_status->vcpu_map)) { > + if (!(--rtc_status->need_eoi)) WARN_ON(need_eoi < 0)? > + /* Clear irr to accept subsequent RTC interrupt */ > + vcpu->kvm->arch.vioapic->irr &= ~(1 << 8); This is not needed if you do not set irr if irq is coalesced. > + } > +} > + > +static bool rtc_irq_check(struct kvm_ioapic *ioapic, int irq) > +{ > + if (irq != 8) > + return false; > + > + if (ioapic->rtc_status.need_eoi > 0) > + return true; /* coalesced */ > + > + return false; > +} > + > #else > > static void rtc_register_notifier(struct kvm_ioapic *ioapic) > { > return; > } > + > +static void rtc_irq_reset(struct kvm_ioapic *ioapic) > +{ > + return; > +} > + > +static void rtc_irq_restore(struct kvm_ioapic *ioapic) > +{ > + return; > +} > + > +static void rtc_irq_update(struct kvm_ioapic *ioapic, > + struct kvm_lapic_irq *irqe, int irq) > +{ > + return; > +} > + > +static void rtc_irq_ack_eoi(struct kvm_vcpu *vcpu, > + struct rtc_status *rtc_status, int irq) > +{ > + return; > +} > + > +static bool rtc_irq_check(struct kvm_ioapic *ioapic, int irq) > +{ > + return false; > +} > #endif > > static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) > @@ -119,6 +217,8 @@ static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) > pent = &ioapic->redirtbl[idx]; > > if (!pent->fields.mask) { > + if (rtc_irq_check(ioapic, idx)) > + return 0; /* coalesced */ > injected = ioapic_deliver(ioapic, idx); > if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG) > pent->fields.remote_irr = 1; > @@ -241,6 +341,8 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) > irqe.level = 1; > irqe.shorthand = 0; > > + rtc_irq_update(ioapic, &irqe, irq); > + Do it once when GSI is configured. > return kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe); > } > > @@ -299,6 +401,7 @@ static void __kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu, > if (ent->fields.vector != vector) > continue; > > + rtc_irq_ack_eoi(vcpu, &ioapic->rtc_status, i); > /* > * We are dropping lock while calling ack notifiers because ack > * notifier callbacks for assigned devices call into IOAPIC > @@ -452,6 +555,7 @@ void kvm_ioapic_reset(struct kvm_ioapic *ioapic) > ioapic->ioregsel = 0; > ioapic->irr = 0; > ioapic->id = 0; > + rtc_irq_reset(ioapic); > update_handled_vectors(ioapic); > } > > @@ -519,6 +623,7 @@ int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state) > spin_lock(&ioapic->lock); > memcpy(ioapic, state, sizeof(struct kvm_ioapic_state)); > update_handled_vectors(ioapic); > + rtc_irq_restore(ioapic); > kvm_ioapic_make_eoibitmap_request(kvm); > spin_unlock(&ioapic->lock); > return 0; > -- > 1.7.1 -- Gleb. -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Gleb Natapov wrote on 2013-03-17: > On Fri, Mar 15, 2013 at 04:05:00PM +0800, Yang Zhang wrote: >> From: Yang Zhang <yang.z.zhang@Intel.com> >> >> Current interrupt coalescing logci which only used by RTC has conflict >> with Posted Interrupt. >> This patch introduces a new mechinism to use eoi to track interrupt: >> When delivering an interrupt to vcpu, the need_eoi set to number of >> vcpu that received the interrupt. And decrease it when each vcpu writing >> eoi. No subsequent RTC interrupt can deliver to vcpu until all vcpus >> write eoi. >> >> Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com> >> --- >> arch/x86/kvm/lapic.c | 2 +- arch/x86/kvm/lapic.h | 1 + >> virt/kvm/ioapic.c | 105 >> ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, >> 107 insertions(+), 1 deletions(-) >> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c >> index ad97f1f..bf2d208 100644 >> --- a/arch/x86/kvm/lapic.c >> +++ b/arch/x86/kvm/lapic.c >> @@ -89,7 +89,7 @@ static inline int apic_test_and_clear_vector(int vec, void > *bitmap) >> return test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); >> } >> -static inline int apic_test_vector(int vec, void *bitmap) >> +int apic_test_vector(int vec, void *bitmap) >> { >> return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); >> } > That's too low level to call from IOAPIC. Put kvm_apic_pending_eoi() > here instead. > >> diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index >> 3a0f9d8..02da8b8 100644 --- a/arch/x86/kvm/lapic.h +++ >> b/arch/x86/kvm/lapic.h @@ -84,6 +84,7 @@ static inline bool >> kvm_hv_vapic_assist_page_enabled(struct kvm_vcpu *vcpu) >> >> int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data); >> void kvm_lapic_init(void); >> +int apic_test_vector(int vec, void *bitmap); >> >> static inline u32 kvm_apic_get_reg(struct kvm_lapic *apic, int reg_off) >> { >> diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c >> index 2c6235c..46cb8ed 100644 >> --- a/virt/kvm/ioapic.c >> +++ b/virt/kvm/ioapic.c >> @@ -103,12 +103,110 @@ static void rtc_register_notifier(struct kvm_ioapic > *ioapic) >> kvm_register_irq_ack_notifier(ioapic->kvm, >> &ioapic->rtc_status.irq_ack_notifier); >> } >> + +static void rtc_irq_reset(struct kvm_ioapic *ioapic) +{ >> + ioapic->rtc_status.need_eoi = 0; >> + bitmap_zero(ioapic->rtc_status.vcpu_map, KVM_MAX_VCPUS); +} + +static >> void rtc_irq_restore(struct kvm_ioapic *ioapic) +{ + struct kvm_vcpu >> *vcpu; + struct kvm_lapic *apic; + int vector, i, need_eoi = 0, rtc_pin >> = 8; + + vector = ioapic->redirtbl[rtc_pin].fields.vector; >> + kvm_for_each_vcpu(i, vcpu, ioapic->kvm) { + apic = vcpu->arch.apic; >> + if (apic_test_vector(vector, apic->regs + APIC_ISR) || + >> apic_test_vector(vector, apic->regs + APIC_IRR)) { + need_eoi++; >> + set_bit(vcpu->vcpu_id, ioapic->rtc_status.vcpu_map); + } + } >> + ioapic->rtc_status.need_eoi = need_eoi; +} + +static void >> rtc_irq_update(struct kvm_ioapic *ioapic, + struct kvm_lapic_irq >> *irqe, int irq) +{ + int weight; + + if (irq != 8) + return; + >> + rtc_irq_reset(ioapic); + + kvm_get_dest_vcpu(ioapic->kvm, irqe, >> ioapic->rtc_status.vcpu_map); + if >> (likely(!bitmap_empty(ioapic->rtc_status.vcpu_map, KVM_MAX_VCPUS))) { >> + if (irqe->delivery_mode == APIC_DM_LOWEST) >> + ioapic->rtc_status.need_eoi = 1; + else { + weight = >> bitmap_weight(ioapic->rtc_status.vcpu_map, >> + sizeof(ioapic->rtc_status.vcpu_map)); >> + ioapic->rtc_status.need_eoi = weight; + } + } +} + +static void >> rtc_irq_ack_eoi(struct kvm_vcpu *vcpu, + struct rtc_status >> *rtc_status, int irq) +{ + if (irq != 8) + return; + + if >> (test_and_clear_bit(vcpu->vcpu_id, rtc_status->vcpu_map)) { + if >> (!(--rtc_status->need_eoi)) > WARN_ON(need_eoi < 0)? > >> + /* Clear irr to accept subsequent RTC interrupt */ >> + vcpu->kvm->arch.vioapic->irr &= ~(1 << 8); > This is not needed if you do not set irr if irq is coalesced. > >> + } >> +} >> + >> +static bool rtc_irq_check(struct kvm_ioapic *ioapic, int irq) >> +{ >> + if (irq != 8) >> + return false; >> + >> + if (ioapic->rtc_status.need_eoi > 0) >> + return true; /* coalesced */ >> + >> + return false; >> +} >> + >> #else >> >> static void rtc_register_notifier(struct kvm_ioapic *ioapic) >> { >> return; >> } >> + >> +static void rtc_irq_reset(struct kvm_ioapic *ioapic) >> +{ >> + return; >> +} >> + >> +static void rtc_irq_restore(struct kvm_ioapic *ioapic) >> +{ >> + return; >> +} >> + >> +static void rtc_irq_update(struct kvm_ioapic *ioapic, >> + struct kvm_lapic_irq *irqe, int irq) >> +{ >> + return; >> +} >> + >> +static void rtc_irq_ack_eoi(struct kvm_vcpu *vcpu, >> + struct rtc_status *rtc_status, int irq) >> +{ >> + return; >> +} >> + >> +static bool rtc_irq_check(struct kvm_ioapic *ioapic, int irq) >> +{ >> + return false; >> +} >> #endif >> >> static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) >> @@ -119,6 +217,8 @@ static int ioapic_service(struct kvm_ioapic *ioapic, > unsigned int idx) >> pent = &ioapic->redirtbl[idx]; >> >> if (!pent->fields.mask) { >> + if (rtc_irq_check(ioapic, idx)) >> + return 0; /* coalesced */ >> injected = ioapic_deliver(ioapic, idx); >> if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG) >> pent->fields.remote_irr = 1; >> @@ -241,6 +341,8 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int > irq) >> irqe.level = 1; >> irqe.shorthand = 0; >> + rtc_irq_update(ioapic, &irqe, irq); >> + > Do it once when GSI is configured. This function will set need_eoi to number of CPU received RTC interrupt. When GSI is configured, there is no real interrupt generated and if set need_eoi, no EOI will decrease it. >> return kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe); >> } >> @@ -299,6 +401,7 @@ static void __kvm_ioapic_update_eoi(struct kvm_vcpu > *vcpu, >> if (ent->fields.vector != vector) >> continue; >> + rtc_irq_ack_eoi(vcpu, &ioapic->rtc_status, i); >> /* * We are dropping lock while calling ack notifiers because ack >> * notifier callbacks for assigned devices call into IOAPIC @@ >> -452,6 +555,7 @@ void kvm_ioapic_reset(struct kvm_ioapic *ioapic) >> ioapic->ioregsel = 0; ioapic->irr = 0; ioapic->id = 0; >> + rtc_irq_reset(ioapic); update_handled_vectors(ioapic); } >> @@ -519,6 +623,7 @@ int kvm_set_ioapic(struct kvm *kvm, struct > kvm_ioapic_state *state) >> spin_lock(&ioapic->lock); memcpy(ioapic, state, sizeof(struct >> kvm_ioapic_state)); update_handled_vectors(ioapic); >> + rtc_irq_restore(ioapic); kvm_ioapic_make_eoibitmap_request(kvm); >> spin_unlock(&ioapic->lock); return 0; >> -- >> 1.7.1 > > -- > Gleb. > -- > To unsubscribe from this list: send the line "unsubscribe kvm" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html Best regards, Yang -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Sun, Mar 17, 2013 at 01:09:09PM +0000, Zhang, Yang Z wrote: > >> @@ -241,6 +341,8 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int > > irq) > >> irqe.level = 1; > >> irqe.shorthand = 0; > >> + rtc_irq_update(ioapic, &irqe, irq); > >> + > > Do it once when GSI is configured. > This function will set need_eoi to number of CPU received RTC interrupt. When GSI is configured, there is no real interrupt generated and if set need_eoi, no EOI will decrease it. > You made this function do two unrelated things: recalculate vcpu map and track need_info. Former should be done during GSI configuration, later here. -- Gleb. -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index ad97f1f..bf2d208 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -89,7 +89,7 @@ static inline int apic_test_and_clear_vector(int vec, void *bitmap) return test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); } -static inline int apic_test_vector(int vec, void *bitmap) +int apic_test_vector(int vec, void *bitmap) { return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); } diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index 3a0f9d8..02da8b8 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -84,6 +84,7 @@ static inline bool kvm_hv_vapic_assist_page_enabled(struct kvm_vcpu *vcpu) int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data); void kvm_lapic_init(void); +int apic_test_vector(int vec, void *bitmap); static inline u32 kvm_apic_get_reg(struct kvm_lapic *apic, int reg_off) { diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 2c6235c..46cb8ed 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c @@ -103,12 +103,110 @@ static void rtc_register_notifier(struct kvm_ioapic *ioapic) kvm_register_irq_ack_notifier(ioapic->kvm, &ioapic->rtc_status.irq_ack_notifier); } + +static void rtc_irq_reset(struct kvm_ioapic *ioapic) +{ + ioapic->rtc_status.need_eoi = 0; + bitmap_zero(ioapic->rtc_status.vcpu_map, KVM_MAX_VCPUS); +} + +static void rtc_irq_restore(struct kvm_ioapic *ioapic) +{ + struct kvm_vcpu *vcpu; + struct kvm_lapic *apic; + int vector, i, need_eoi = 0, rtc_pin = 8; + + vector = ioapic->redirtbl[rtc_pin].fields.vector; + kvm_for_each_vcpu(i, vcpu, ioapic->kvm) { + apic = vcpu->arch.apic; + if (apic_test_vector(vector, apic->regs + APIC_ISR) || + apic_test_vector(vector, apic->regs + APIC_IRR)) { + need_eoi++; + set_bit(vcpu->vcpu_id, ioapic->rtc_status.vcpu_map); + } + } + ioapic->rtc_status.need_eoi = need_eoi; +} + +static void rtc_irq_update(struct kvm_ioapic *ioapic, + struct kvm_lapic_irq *irqe, int irq) +{ + int weight; + + if (irq != 8) + return; + + rtc_irq_reset(ioapic); + + kvm_get_dest_vcpu(ioapic->kvm, irqe, ioapic->rtc_status.vcpu_map); + if (likely(!bitmap_empty(ioapic->rtc_status.vcpu_map, KVM_MAX_VCPUS))) { + if (irqe->delivery_mode == APIC_DM_LOWEST) + ioapic->rtc_status.need_eoi = 1; + else { + weight = bitmap_weight(ioapic->rtc_status.vcpu_map, + sizeof(ioapic->rtc_status.vcpu_map)); + ioapic->rtc_status.need_eoi = weight; + } + } +} + +static void rtc_irq_ack_eoi(struct kvm_vcpu *vcpu, + struct rtc_status *rtc_status, int irq) +{ + if (irq != 8) + return; + + if (test_and_clear_bit(vcpu->vcpu_id, rtc_status->vcpu_map)) { + if (!(--rtc_status->need_eoi)) + /* Clear irr to accept subsequent RTC interrupt */ + vcpu->kvm->arch.vioapic->irr &= ~(1 << 8); + } +} + +static bool rtc_irq_check(struct kvm_ioapic *ioapic, int irq) +{ + if (irq != 8) + return false; + + if (ioapic->rtc_status.need_eoi > 0) + return true; /* coalesced */ + + return false; +} + #else static void rtc_register_notifier(struct kvm_ioapic *ioapic) { return; } + +static void rtc_irq_reset(struct kvm_ioapic *ioapic) +{ + return; +} + +static void rtc_irq_restore(struct kvm_ioapic *ioapic) +{ + return; +} + +static void rtc_irq_update(struct kvm_ioapic *ioapic, + struct kvm_lapic_irq *irqe, int irq) +{ + return; +} + +static void rtc_irq_ack_eoi(struct kvm_vcpu *vcpu, + struct rtc_status *rtc_status, int irq) +{ + return; +} + +static bool rtc_irq_check(struct kvm_ioapic *ioapic, int irq) +{ + return false; +} #endif static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) @@ -119,6 +217,8 @@ static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) pent = &ioapic->redirtbl[idx]; if (!pent->fields.mask) { + if (rtc_irq_check(ioapic, idx)) + return 0; /* coalesced */ injected = ioapic_deliver(ioapic, idx); if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG) pent->fields.remote_irr = 1; @@ -241,6 +341,8 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) irqe.level = 1; irqe.shorthand = 0; + rtc_irq_update(ioapic, &irqe, irq); + return kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe); } @@ -299,6 +401,7 @@ static void __kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu, if (ent->fields.vector != vector) continue; + rtc_irq_ack_eoi(vcpu, &ioapic->rtc_status, i); /* * We are dropping lock while calling ack notifiers because ack * notifier callbacks for assigned devices call into IOAPIC @@ -452,6 +555,7 @@ void kvm_ioapic_reset(struct kvm_ioapic *ioapic) ioapic->ioregsel = 0; ioapic->irr = 0; ioapic->id = 0; + rtc_irq_reset(ioapic); update_handled_vectors(ioapic); } @@ -519,6 +623,7 @@ int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state) spin_lock(&ioapic->lock); memcpy(ioapic, state, sizeof(struct kvm_ioapic_state)); update_handled_vectors(ioapic); + rtc_irq_restore(ioapic); kvm_ioapic_make_eoibitmap_request(kvm); spin_unlock(&ioapic->lock); return 0;