* [Qemu-devel] [PATCH V3] rtc: fix a infinite loop in windows vm startup
@ 2017-07-24 18:35 Peng Hao
2017-07-24 11:53 ` Paolo Bonzini
2017-07-24 11:54 ` Eric Blake
0 siblings, 2 replies; 5+ messages in thread
From: Peng Hao @ 2017-07-24 18:35 UTC (permalink / raw)
To: mst, pbonzini; +Cc: qemu-devel, Peng Hao, Liu Yi
When a windows vm starts, periodic timer of rtc will stop several times.
windows kernel will check whether REG_A_UIP is changed. REG_C's interrupt
flags will not be cleared when periodic timer stops and the update timer
will switch to alarm timer. So the expiration time of alarm timer is very
long and REG_A_UIP will not vary.At last windows kernel will repeat to
check REG_A_UIP all the time.
Signed-off-by: Peng Hao <peng.hao2@zte.com.cn>
Signed-off-by: Liu Yi <liu.yi24@zte.com.cn>
---
hw/timer/mc146818rtc.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 1b8d3d7..aa55fae 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -457,6 +457,8 @@ static void rtc_update_timer(void *opaque)
if ((new_irqs & s->cmos_data[RTC_REG_B]) != 0) {
s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
qemu_irq_raise(s->irq);
+ } else if ((s->cmos_data[RTC_REG_B] & REG_B_UIE) == 0) {
+ s->cmos_data[RTC_REG_C] &= ~REG_C_UF;
}
check_update_timer(s);
}
@@ -559,7 +561,7 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
qemu_irq_raise(s->irq);
} else {
- s->cmos_data[RTC_REG_C] &= ~REG_C_IRQF;
+ s->cmos_data[RTC_REG_C] &= ~(REG_C_UF | REG_C_IRQF);
qemu_irq_lower(s->irq);
}
s->cmos_data[RTC_REG_B] = data;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [Qemu-devel] [PATCH V3] rtc: fix a infinite loop in windows vm startup
2017-07-24 18:35 [Qemu-devel] [PATCH V3] rtc: fix a infinite loop in windows vm startup Peng Hao
@ 2017-07-24 11:53 ` Paolo Bonzini
2017-07-24 11:54 ` Eric Blake
1 sibling, 0 replies; 5+ messages in thread
From: Paolo Bonzini @ 2017-07-24 11:53 UTC (permalink / raw)
To: Peng Hao, mst; +Cc: qemu-devel, Liu Yi
On 24/07/2017 20:35, Peng Hao wrote:
> When a windows vm starts, periodic timer of rtc will stop several times.
> windows kernel will check whether REG_A_UIP is changed. REG_C's interrupt
> flags will not be cleared when periodic timer stops and the update timer
> will switch to alarm timer. So the expiration time of alarm timer is very
> long and REG_A_UIP will not vary.At last windows kernel will repeat to
> check REG_A_UIP all the time.
This should not happen. REG_A_UIP is set and cleared in register A
every second, like this:
case RTC_REG_A:
if (update_in_progress(s)) {
s->cmos_data[s->cmos_index] |= REG_A_UIP;
} else {
s->cmos_data[s->cmos_index] &= ~REG_A_UIP;
}
ret = s->cmos_data[s->cmos_index];
break;
where update_in_progress does:
guest_nsec = get_guest_rtc_ns(s);
/* UIP bit will be set at last 244us of every second. */
if ((guest_nsec % NANOSECONDS_PER_SECOND) >=
(NANOSECONDS_PER_SECOND - UIP_HOLD_LENGTH)) {
return 1;
}
return 0;
This is done even if the timer is not pending.
How can the bug be reproduced?
Paolo
> Signed-off-by: Peng Hao <peng.hao2@zte.com.cn>
> Signed-off-by: Liu Yi <liu.yi24@zte.com.cn>
> ---
> hw/timer/mc146818rtc.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
> index 1b8d3d7..aa55fae 100644
> --- a/hw/timer/mc146818rtc.c
> +++ b/hw/timer/mc146818rtc.c
> @@ -457,6 +457,8 @@ static void rtc_update_timer(void *opaque)
> if ((new_irqs & s->cmos_data[RTC_REG_B]) != 0) {
> s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
> qemu_irq_raise(s->irq);
> + } else if ((s->cmos_data[RTC_REG_B] & REG_B_UIE) == 0) {
> + s->cmos_data[RTC_REG_C] &= ~REG_C_UF;
> }
> check_update_timer(s);
> }
> @@ -559,7 +561,7 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
> s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
> qemu_irq_raise(s->irq);
> } else {
> - s->cmos_data[RTC_REG_C] &= ~REG_C_IRQF;
> + s->cmos_data[RTC_REG_C] &= ~(REG_C_UF | REG_C_IRQF);
> qemu_irq_lower(s->irq);
> }
> s->cmos_data[RTC_REG_B] = data;
>
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [Qemu-devel] [PATCH V3] rtc: fix a infinite loop in windows vm startup
2017-07-24 18:35 [Qemu-devel] [PATCH V3] rtc: fix a infinite loop in windows vm startup Peng Hao
2017-07-24 11:53 ` Paolo Bonzini
@ 2017-07-24 11:54 ` Eric Blake
1 sibling, 0 replies; 5+ messages in thread
From: Eric Blake @ 2017-07-24 11:54 UTC (permalink / raw)
To: Peng Hao, mst, pbonzini; +Cc: Liu Yi, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 830 bytes --]
On 07/24/2017 01:35 PM, Peng Hao wrote:
> When a windows vm starts, periodic timer of rtc will stop several times.
> windows kernel will check whether REG_A_UIP is changed. REG_C's interrupt
> flags will not be cleared when periodic timer stops and the update timer
> will switch to alarm timer. So the expiration time of alarm timer is very
> long and REG_A_UIP will not vary.At last windows kernel will repeat to
> check REG_A_UIP all the time.
>
> Signed-off-by: Peng Hao <peng.hao2@zte.com.cn>
> Signed-off-by: Liu Yi <liu.yi24@zte.com.cn>
> ---
When posting a v3, it's useful to tell us (after the --- separator) what
changed from v2, to help us focus on why a v3 was needed.
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH V3] rtc: fix a infinite loop in windows vm startup
@ 2017-07-25 4:14 peng.hao2
2017-07-25 7:17 ` Paolo Bonzini
0 siblings, 1 reply; 5+ messages in thread
From: peng.hao2 @ 2017-07-25 4:14 UTC (permalink / raw)
To: pbonzini; +Cc: mst, qemu-devel, liu.yi24
>On 24/07/2017 20:35, Peng Hao wrote:
>> When a windows vm starts, periodic timer of rtc will stop several times.
>> windows kernel will check whether REG_A_UIP is changed. REG_C's interrupt
>> flags will not be cleared when periodic timer stops and the update timer
>> will switch to alarm timer. So the expiration time of alarm timer is very
>> long and REG_A_UIP will not vary.At last windows kernel will repeat to
>> check REG_A_UIP all the time.
>This should not happen. REG_A_UIP is set and cleared in register A
>every second, like this:
> case RTC_REG_A:
> if (update_in_progress(s)) {
> s->cmos_data[s->cmos_index] |= REG_A_UIP
> } else {
> s->cmos_data[s->cmos_index] &= ~REG_A_UIP
> }
> ret = s->cmos_data[s->cmos_index]
> break
when periodic timer stop, update timer is set to a long expire time (as alarm timer).
So update_in_progress always return 1 and REG_A_UIP is never cleared.
>where update_in_progress does:
> guest_nsec = get_guest_rtc_ns(s)
> /* UIP bit will be set at last 244us of every second. */
> if ((guest_nsec % NANOSECONDS_PER_SECOND) >=
> (NANOSECONDS_PER_SECOND - UIP_HOLD_LENGTH)) {
> return 1
> }
> return 0
>This is done even if the timer is not pending.
>How can the bug be reproduced?
many windows VMs reboot at the same time.some VM's vcpu thread go to a infinite loop
at the starting stage.
>Paolo
> Signed-off-by: Peng Hao <peng.hao2@zte.com.cn>
> Signed-off-by: Liu Yi <liu.yi24@zte.com.cn>
> ---
> hw/timer/mc146818rtc.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
> index 1b8d3d7..aa55fae 100644
> --- a/hw/timer/mc146818rtc.c
> +++ b/hw/timer/mc146818rtc.c
> @@ -457,6 +457,8 @@ static void rtc_update_timer(void *opaque)
> if ((new_irqs & s->cmos_data[RTC_REG_B]) != 0) {
> s->cmos_data[RTC_REG_C] |= REG_C_IRQF
> qemu_irq_raise(s->irq)
> + } else if ((s->cmos_data[RTC_REG_B] & REG_B_UIE) == 0) {
> + s->cmos_data[RTC_REG_C] &= ~REG_C_UF
> }
> check_update_timer(s)
> }
> @@ -559,7 +561,7 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
> s->cmos_data[RTC_REG_C] |= REG_C_IRQF
> qemu_irq_raise(s->irq)
> } else {
> - s->cmos_data[RTC_REG_C] &= ~REG_C_IRQF
> + s->cmos_data[RTC_REG_C] &= ~(REG_C_UF | REG_C_IRQF)
> qemu_irq_lower(s->irq)
> }
> s->cmos_data[RTC_REG_B] = data
>
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [Qemu-devel] [PATCH V3] rtc: fix a infinite loop in windows vm startup
2017-07-25 4:14 peng.hao2
@ 2017-07-25 7:17 ` Paolo Bonzini
0 siblings, 0 replies; 5+ messages in thread
From: Paolo Bonzini @ 2017-07-25 7:17 UTC (permalink / raw)
To: peng.hao2; +Cc: liu.yi24, qemu-devel, mst
On 25/07/2017 06:14, peng.hao2@zte.com.cn wrote:
>> On 24/07/2017 20:35, Peng Hao wrote:
>
>
>
>
>
>>> When a windows vm starts, periodic timer of rtc will stop several times.
>>> windows kernel will check whether REG_A_UIP is changed. REG_C's interrupt
>>> flags will not be cleared when periodic timer stops and the update timer
>>> will switch to alarm timer. So the expiration time of alarm timer is very
>>> long and REG_A_UIP will not vary.At last windows kernel will repeat to
>>> check REG_A_UIP all the time.
>
>> This should not happen. REG_A_UIP is set and cleared in register A
>> every second, like this:
>> case RTC_REG_A:
>
>> if (update_in_progress(s)) {
>> s->cmos_data[s->cmos_index] |= REG_A_UIP
>> } else {
>> s->cmos_data[s->cmos_index] &= ~REG_A_UIP
>> }
>> ret = s->cmos_data[s->cmos_index]
>> break
>
>
>
> when periodic timer stop, update timer is set to a long expire time (as alarm timer).
I think I see the bug now:
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 1b8d3d7d4c..6184b4378e 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -321,9 +321,11 @@ static void check_update_timer(RTCState *s)
s->next_alarm_time = next_update_time +
(next_alarm_sec - 1) * NANOSECONDS_PER_SECOND;
- if (s->cmos_data[RTC_REG_C] & REG_C_UF) {
- /* UF is set, but AF is clear. Program the timer to target
- * the alarm time. */
+ if ((s->cmos_data[RTC_REG_C] & REG_C_UF) &&
+ !(s->cmos_data[RTC_REG_A] & REG_A_UIP)) {
+ /* If UIP was latched, we need to clear it at the next update.
+ * Otherwise, if UF is set we only need to program the timer to
+ * target the alarm time. */
next_update_time = s->next_alarm_time;
}
if (next_update_time != timer_expire_time_ns(s->update_timer)) {
but I would like to have a testcase for it in tests/rtc-test.c.
Can you check if the above works and try writing a testcase (that fails
without the patch and succeeds with it)?
Thanks,
Paolo
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2017-07-25 7:17 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-07-24 18:35 [Qemu-devel] [PATCH V3] rtc: fix a infinite loop in windows vm startup Peng Hao
2017-07-24 11:53 ` Paolo Bonzini
2017-07-24 11:54 ` Eric Blake
-- strict thread matches above, loose matches on Subject: below --
2017-07-25 4:14 peng.hao2
2017-07-25 7:17 ` Paolo Bonzini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).