diff mbox

[v2,6/8] KVM: Add reset/restore rtc_status support

Message ID 1363591479-4653-7-git-send-email-yang.z.zhang@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Zhang, Yang Z March 18, 2013, 7:24 a.m. UTC
From: Yang Zhang <yang.z.zhang@Intel.com>

reset/restore rtc_status when ioapic reset/restore.

Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com>
---
 arch/x86/kvm/lapic.c |    8 ++++++++
 arch/x86/kvm/lapic.h |    1 +
 virt/kvm/ioapic.c    |   33 +++++++++++++++++++++++++++++++++
 3 files changed, 42 insertions(+), 0 deletions(-)

Comments

Marcelo Tosatti March 19, 2013, 8:55 p.m. UTC | #1
On Mon, Mar 18, 2013 at 03:24:37PM +0800, Yang Zhang wrote:
> From: Yang Zhang <yang.z.zhang@Intel.com>
> 
> reset/restore rtc_status when ioapic reset/restore.
> 
> Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com>
> ---
>  arch/x86/kvm/lapic.c |    8 ++++++++
>  arch/x86/kvm/lapic.h |    1 +
>  virt/kvm/ioapic.c    |   33 +++++++++++++++++++++++++++++++++
>  3 files changed, 42 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
> index 6fb22e3..a223170 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)
>  	return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
>  }
>  
> +bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector)
> +{
> +	struct kvm_lapic *apic = vcpu->arch.apic;
> +
> +	return apic_test_vector(vector, apic->regs + APIC_ISR) ||
> +		apic_test_vector(vector, apic->regs + APIC_IRR);
> +}
> +

Should hook into kvm_lapic_reset and kvm_vcpu_ioctl_set_lapic to
generate updates.

>  static inline void apic_set_vector(int vec, void *bitmap)
>  {
>  	set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
> diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
> index 3a0f9d8..e2a03d1 100644
> --- a/arch/x86/kvm/lapic.h
> +++ b/arch/x86/kvm/lapic.h
> @@ -160,5 +160,6 @@ void kvm_calculate_eoi_exitmap(struct kvm_vcpu *vcpu,
>  
>  void kvm_get_dest_vcpu(struct kvm *kvm, struct kvm_lapic_irq *irq,
>  				unsigned long *vcpu_map);
> +bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector);
>  
>  #endif
> diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
> index 659511d..6266d1f 100644
> --- a/virt/kvm/ioapic.c
> +++ b/virt/kvm/ioapic.c
> @@ -88,6 +88,27 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
>  }
>  
>  #ifdef CONFIG_X86
> +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;
> +	int vector, i, need_eoi = 0, rtc_pin = 8;
> +
> +	vector = ioapic->redirtbl[rtc_pin].fields.vector;
> +	kvm_for_each_vcpu(i, vcpu, ioapic->kvm) {
> +		if (kvm_apic_pending_eoi(vcpu, vector)) {
> +			need_eoi++;
> +			set_bit(vcpu->vcpu_id, ioapic->rtc_status.vcpu_map);

Why set bit on vcpu_map here?


--
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
Marcelo Tosatti March 19, 2013, 9:01 p.m. UTC | #2
On Mon, Mar 18, 2013 at 03:24:37PM +0800, Yang Zhang wrote:
> From: Yang Zhang <yang.z.zhang@Intel.com>
> 
> reset/restore rtc_status when ioapic reset/restore.
> 
> Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com>
> ---
>  arch/x86/kvm/lapic.c |    8 ++++++++
>  arch/x86/kvm/lapic.h |    1 +
>  virt/kvm/ioapic.c    |   33 +++++++++++++++++++++++++++++++++
>  3 files changed, 42 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
> index 6fb22e3..a223170 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)
>  	return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
>  }
>  
> +bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector)
> +{
> +	struct kvm_lapic *apic = vcpu->arch.apic;
> +
> +	return apic_test_vector(vector, apic->regs + APIC_ISR) ||
> +		apic_test_vector(vector, apic->regs + APIC_IRR);
> +}
> +
>  static inline void apic_set_vector(int vec, void *bitmap)
>  {
>  	set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
> diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
> index 3a0f9d8..e2a03d1 100644
> --- a/arch/x86/kvm/lapic.h
> +++ b/arch/x86/kvm/lapic.h
> @@ -160,5 +160,6 @@ void kvm_calculate_eoi_exitmap(struct kvm_vcpu *vcpu,
>  
>  void kvm_get_dest_vcpu(struct kvm *kvm, struct kvm_lapic_irq *irq,
>  				unsigned long *vcpu_map);
> +bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector);
>  
>  #endif
> diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
> index 659511d..6266d1f 100644
> --- a/virt/kvm/ioapic.c
> +++ b/virt/kvm/ioapic.c
> @@ -88,6 +88,27 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
>  }
>  
>  #ifdef CONFIG_X86
> +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;
> +	int vector, i, need_eoi = 0, rtc_pin = 8;
> +
> +	vector = ioapic->redirtbl[rtc_pin].fields.vector;
> +	kvm_for_each_vcpu(i, vcpu, ioapic->kvm) {
> +		if (kvm_apic_pending_eoi(vcpu, vector)) {
> +			need_eoi++;
> +			set_bit(vcpu->vcpu_id, ioapic->rtc_status.vcpu_map);
> +		}
> +	}
> +	ioapic->rtc_status.need_eoi = need_eoi;
> +}
> +
>  static void rtc_irq_get_dest_vcpu(struct kvm_ioapic *ioapic, int irq)
>  {
>  	union kvm_ioapic_redirect_entry *entry = &ioapic->redirtbl[irq];
> @@ -111,6 +132,16 @@ static void rtc_irq_get_dest_vcpu(struct kvm_ioapic *ioapic, int irq)
>  
>  #else
>  
> +static void rtc_irq_reset(struct kvm_ioapic *ioapic)
> +{
> +	return;
> +}
> +
> +static void rtc_irq_restore(struct kvm_ioapic *ioapic)
> +{
> +	return;
> +}
> +
>  static void rtc_irq_get_dest_vcpu(struct kvm_ioapic *ioapic, int irq)
>  {
>  	return;
> @@ -462,6 +493,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);
>  }

Should also zero the counter if the OS resets the IOAPIC (think reboot
via triple-fault with unacked RTC interrupt in ISR/IRR).

--
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
Zhang, Yang Z March 20, 2013, 2:42 a.m. UTC | #3
Marcelo Tosatti wrote on 2013-03-20:
> On Mon, Mar 18, 2013 at 03:24:37PM +0800, Yang Zhang wrote:
>> From: Yang Zhang <yang.z.zhang@Intel.com>
>> 
>> reset/restore rtc_status when ioapic reset/restore.
>> 
>> Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com>
>> ---
>>  arch/x86/kvm/lapic.c |    8 ++++++++
>>  arch/x86/kvm/lapic.h |    1 +
>>  virt/kvm/ioapic.c    |   33 +++++++++++++++++++++++++++++++++
>>  3 files changed, 42 insertions(+), 0 deletions(-)
>> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
>> index 6fb22e3..a223170 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)
>>  	return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
>>  }
>> +bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector)
>> +{
>> +	struct kvm_lapic *apic = vcpu->arch.apic;
>> +
>> +	return apic_test_vector(vector, apic->regs + APIC_ISR) ||
>> +		apic_test_vector(vector, apic->regs + APIC_IRR);
>> +}
>> +
> 
> Should hook into kvm_lapic_reset and kvm_vcpu_ioctl_set_lapic to
> generate updates.
rtc_irq_restore will be called after lapic is restored. What's the problem if we no hook into the two function?

>>  static inline void apic_set_vector(int vec, void *bitmap)
>>  {
>>  	set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
>> diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index
>> 3a0f9d8..e2a03d1 100644 --- a/arch/x86/kvm/lapic.h +++
>> b/arch/x86/kvm/lapic.h @@ -160,5 +160,6 @@ void
>> kvm_calculate_eoi_exitmap(struct kvm_vcpu *vcpu,
>> 
>>  void kvm_get_dest_vcpu(struct kvm *kvm, struct kvm_lapic_irq *irq,
>>  				unsigned long *vcpu_map);
>> +bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector);
>> 
>>  #endif
>> diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
>> index 659511d..6266d1f 100644
>> --- a/virt/kvm/ioapic.c
>> +++ b/virt/kvm/ioapic.c
>> @@ -88,6 +88,27 @@ static unsigned long ioapic_read_indirect(struct
> kvm_ioapic *ioapic,
>>  }
>>  
>>  #ifdef CONFIG_X86
>> +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;
>> +	int vector, i, need_eoi = 0, rtc_pin = 8;
>> +
>> +	vector = ioapic->redirtbl[rtc_pin].fields.vector;
>> +	kvm_for_each_vcpu(i, vcpu, ioapic->kvm) {
>> +		if (kvm_apic_pending_eoi(vcpu, vector)) {
>> +			need_eoi++;
>> +			set_bit(vcpu->vcpu_id, ioapic->rtc_status.vcpu_map);
> 
> Why set bit on vcpu_map here?
We will set need_eoi here. And if target vcpu is not in vcpu_map, then it will not update need_eoi on EOI.

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
Zhang, Yang Z March 20, 2013, 2:44 a.m. UTC | #4
Marcelo Tosatti wrote on 2013-03-20:
> On Mon, Mar 18, 2013 at 03:24:37PM +0800, Yang Zhang wrote:
>> From: Yang Zhang <yang.z.zhang@Intel.com>
>> 
>> reset/restore rtc_status when ioapic reset/restore.
>> 
>> Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com>
>> ---
>>  arch/x86/kvm/lapic.c |    8 ++++++++
>>  arch/x86/kvm/lapic.h |    1 +
>>  virt/kvm/ioapic.c    |   33 +++++++++++++++++++++++++++++++++
>>  3 files changed, 42 insertions(+), 0 deletions(-)
>> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
>> index 6fb22e3..a223170 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)
>>  	return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
>>  }
>> +bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector)
>> +{
>> +	struct kvm_lapic *apic = vcpu->arch.apic;
>> +
>> +	return apic_test_vector(vector, apic->regs + APIC_ISR) ||
>> +		apic_test_vector(vector, apic->regs + APIC_IRR);
>> +}
>> +
>>  static inline void apic_set_vector(int vec, void *bitmap)
>>  {
>>  	set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
>> diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index
>> 3a0f9d8..e2a03d1 100644 --- a/arch/x86/kvm/lapic.h +++
>> b/arch/x86/kvm/lapic.h @@ -160,5 +160,6 @@ void
>> kvm_calculate_eoi_exitmap(struct kvm_vcpu *vcpu,
>> 
>>  void kvm_get_dest_vcpu(struct kvm *kvm, struct kvm_lapic_irq *irq,
>>  				unsigned long *vcpu_map);
>> +bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector);
>> 
>>  #endif
>> diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
>> index 659511d..6266d1f 100644
>> --- a/virt/kvm/ioapic.c
>> +++ b/virt/kvm/ioapic.c
>> @@ -88,6 +88,27 @@ static unsigned long ioapic_read_indirect(struct
> kvm_ioapic *ioapic,
>>  }
>>  
>>  #ifdef CONFIG_X86
>> +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;
>> +	int vector, i, need_eoi = 0, rtc_pin = 8;
>> +
>> +	vector = ioapic->redirtbl[rtc_pin].fields.vector;
>> +	kvm_for_each_vcpu(i, vcpu, ioapic->kvm) {
>> +		if (kvm_apic_pending_eoi(vcpu, vector)) {
>> +			need_eoi++;
>> +			set_bit(vcpu->vcpu_id, ioapic->rtc_status.vcpu_map);
>> +		}
>> +	}
>> +	ioapic->rtc_status.need_eoi = need_eoi;
>> +}
>> +
>>  static void rtc_irq_get_dest_vcpu(struct kvm_ioapic *ioapic, int irq)
>>  {
>>  	union kvm_ioapic_redirect_entry *entry = &ioapic->redirtbl[irq];
>> @@ -111,6 +132,16 @@ static void rtc_irq_get_dest_vcpu(struct
>> kvm_ioapic *ioapic, int irq)
>> 
>>  #else
>> +static void rtc_irq_reset(struct kvm_ioapic *ioapic)
>> +{
>> +	return;
>> +}
>> +
>> +static void rtc_irq_restore(struct kvm_ioapic *ioapic)
>> +{
>> +	return;
>> +}
>> +
>>  static void rtc_irq_get_dest_vcpu(struct kvm_ioapic *ioapic, int irq)
>>  { 	return; @@ -462,6 +493,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); }
> 
> Should also zero the counter if the OS resets the IOAPIC (think reboot
> via triple-fault with unacked RTC interrupt in ISR/IRR).
rtc_irq_reset() already did it.

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
Zhang, Yang Z March 20, 2013, 11:43 a.m. UTC | #5
I have send out the latest patch(v4). Please give comments for the latest one, because some issues you point out may not exist on latest patch. If it still exits. please point out it again.

Zhang, Yang Z wrote on 2013-03-20:
> Marcelo Tosatti wrote on 2013-03-20:
>> On Mon, Mar 18, 2013 at 03:24:37PM +0800, Yang Zhang wrote:
>>> From: Yang Zhang <yang.z.zhang@Intel.com>
>>> 
>>> reset/restore rtc_status when ioapic reset/restore.
>>> 
>>> Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com>
>>> ---
>>>  arch/x86/kvm/lapic.c |    8 ++++++++
>>>  arch/x86/kvm/lapic.h |    1 +
>>>  virt/kvm/ioapic.c    |   33 +++++++++++++++++++++++++++++++++
>>>  3 files changed, 42 insertions(+), 0 deletions(-)
>>> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
>>> index 6fb22e3..a223170 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)
>>>  	return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
>>>  }
>>> +bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector)
>>> +{
>>> +	struct kvm_lapic *apic = vcpu->arch.apic;
>>> +
>>> +	return apic_test_vector(vector, apic->regs + APIC_ISR) ||
>>> +		apic_test_vector(vector, apic->regs + APIC_IRR);
>>> +}
>>> +
>> 
>> Should hook into kvm_lapic_reset and kvm_vcpu_ioctl_set_lapic to
>> generate updates.
> rtc_irq_restore will be called after lapic is restored. What's the problem if we no
> hook into the two function?
> 
>>>  static inline void apic_set_vector(int vec, void *bitmap)
>>>  {
>>>  	set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
>>> diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index
>>> 3a0f9d8..e2a03d1 100644 --- a/arch/x86/kvm/lapic.h +++
>>> b/arch/x86/kvm/lapic.h @@ -160,5 +160,6 @@ void
>>> kvm_calculate_eoi_exitmap(struct kvm_vcpu *vcpu,
>>> 
>>>  void kvm_get_dest_vcpu(struct kvm *kvm, struct kvm_lapic_irq *irq,
>>>  				unsigned long *vcpu_map);
>>> +bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector);
>>> 
>>>  #endif
>>> diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
>>> index 659511d..6266d1f 100644
>>> --- a/virt/kvm/ioapic.c
>>> +++ b/virt/kvm/ioapic.c
>>> @@ -88,6 +88,27 @@ static unsigned long ioapic_read_indirect(struct
>> kvm_ioapic *ioapic,
>>>  }
>>>  
>>>  #ifdef CONFIG_X86
>>> +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;
>>> +	int vector, i, need_eoi = 0, rtc_pin = 8;
>>> +
>>> +	vector = ioapic->redirtbl[rtc_pin].fields.vector;
>>> +	kvm_for_each_vcpu(i, vcpu, ioapic->kvm) {
>>> +		if (kvm_apic_pending_eoi(vcpu, vector)) {
>>> +			need_eoi++;
>>> +			set_bit(vcpu->vcpu_id, ioapic->rtc_status.vcpu_map);
>> 
>> Why set bit on vcpu_map here?
> We will set need_eoi here. And if target vcpu is not in vcpu_map, then it will not
> update need_eoi on EOI.
> 
> Best regards,
> Yang


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
diff mbox

Patch

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 6fb22e3..a223170 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)
 	return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
 }
 
+bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	return apic_test_vector(vector, apic->regs + APIC_ISR) ||
+		apic_test_vector(vector, apic->regs + APIC_IRR);
+}
+
 static inline void apic_set_vector(int vec, void *bitmap)
 {
 	set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 3a0f9d8..e2a03d1 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -160,5 +160,6 @@  void kvm_calculate_eoi_exitmap(struct kvm_vcpu *vcpu,
 
 void kvm_get_dest_vcpu(struct kvm *kvm, struct kvm_lapic_irq *irq,
 				unsigned long *vcpu_map);
+bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector);
 
 #endif
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index 659511d..6266d1f 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -88,6 +88,27 @@  static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
 }
 
 #ifdef CONFIG_X86
+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;
+	int vector, i, need_eoi = 0, rtc_pin = 8;
+
+	vector = ioapic->redirtbl[rtc_pin].fields.vector;
+	kvm_for_each_vcpu(i, vcpu, ioapic->kvm) {
+		if (kvm_apic_pending_eoi(vcpu, vector)) {
+			need_eoi++;
+			set_bit(vcpu->vcpu_id, ioapic->rtc_status.vcpu_map);
+		}
+	}
+	ioapic->rtc_status.need_eoi = need_eoi;
+}
+
 static void rtc_irq_get_dest_vcpu(struct kvm_ioapic *ioapic, int irq)
 {
 	union kvm_ioapic_redirect_entry *entry = &ioapic->redirtbl[irq];
@@ -111,6 +132,16 @@  static void rtc_irq_get_dest_vcpu(struct kvm_ioapic *ioapic, int irq)
 
 #else
 
+static void rtc_irq_reset(struct kvm_ioapic *ioapic)
+{
+	return;
+}
+
+static void rtc_irq_restore(struct kvm_ioapic *ioapic)
+{
+	return;
+}
+
 static void rtc_irq_get_dest_vcpu(struct kvm_ioapic *ioapic, int irq)
 {
 	return;
@@ -462,6 +493,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);
 }
 
@@ -527,6 +559,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_scan_ioapic_entry(kvm);
 	spin_unlock(&ioapic->lock);
 	return 0;