All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/5] mc146818rtc: fix Windows VM clock faster
@ 2017-05-10  8:32 ` guangrong.xiao
  0 siblings, 0 replies; 22+ messages in thread
From: guangrong.xiao @ 2017-05-10  8:32 UTC (permalink / raw)
  To: pbonzini, mst, mtosatti; +Cc: qemu-devel, kvm, yunfangtai, Xiao Guangrong

From: Xiao Guangrong <xiaoguangrong@tencent.com>

Changelog in v3:
Thanks to Paolo's the elaborate review comments, this version
simplifies the logic of periodic_timer_update() significantly
that includes:
1) introduce rtc_periodic_clock_ticks() that takes both regA and
   regB into account and returns the period clock
2) count the clocks since last interrupt by always using current
   clock subtracts the clock when last interrupt happened
3) improve the assert() logic

Paolo, all you comments have been reflected in this version except
globally using s->period because in the current code, only x86 is
using s->period so that we should obey this rule to keep compatible
migration. I have added the comment to explain this suitable in the
code:

            /*
             * as the old QEMUs only used s->period for the case that
             * LOST_TICK_POLICY_SLEW is used, in order to keep the
             * compatible migration, we obey the rule as old QEMUs.
             */
            s->period = period;
If anything i missed, please let me know. :)

Changelog in v2:
Thanks to Paolo's review, the changes in this version are:
1) merge patch 2, 3, 4 together
2) use a nice way ((value ^ new_value) & BIT_MASK) to check if updating
   for periodic timer is needed
3) use a smarter way to calculate coalesced irqs and lost_clock
4) make sure only x86 can enable LOST_TICK_POLICY_SLEW
5) make the code depends on LOST_TICK_POLICY_SLEW rather than
   TARGET_I386

We noticed that the clock on some windows VMs, e.g, Window7 and window8
is really faster and the issue can be easily reproduced by staring the
VM with '-rtc base=localtime,clock=vm,driftfix=slew -no-hpet' and 
running attached code in the guest

The root cause is that the clock will be lost if the periodic period is
changed as currently code counts the next periodic time like this:
      next_irq_clock = (cur_clock & ~(period - 1)) + period;

consider the case if cur_clock = 0x11FF and period = 0x100, then the
next_irq_clock is 0x1200, however, there is only 1 clock left to trigger
the next irq. Unfortunately, Windows guests (at least Windows7) change
the period very frequently if it runs the attached code, so that the
lost clock is accumulated, the wall-time become faster and faster

The main idea to fix the issue is we use a accurate clock period to
calculate the next irq:
    next_irq_clock = cur_clock + period;

After that, it is really convenient to compensate clock if it is needed 

The code running in windows VM is attached:
// TimeInternalTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#pragma comment(lib, "winmm")
#include <stdio.h>
#include <windows.h>

#define SWITCH_PEROID  13

int _tmain(int argc, _TCHAR* argv[])
{
	if (argc != 2)
	{
		printf("parameter error!\n");
		printf("USAGE: *.exe time(ms)\n");
		printf("example: *.exe 40\n");
		return 0;
	}
	else
	{
		DWORD internal = atoi((char *)argv[1]);
		DWORD count = 0;

		while (1)
		{
			count++;
			timeBeginPeriod(1);
			DWORD start = timeGetTime();
			Sleep(internal);
			timeEndPeriod(1);
			if ((count % SWITCH_PEROID) == 0) {
				Sleep(1);
			}
		}
	}
	return 0;
}

Tai Yunfang (1):
  mc146818rtc: precisely count the clock for periodic timer

Xiao Guangrong (4):
  mc146818rtc: update periodic timer only if it is needed
  mc146818rtc: ensure LOST_TICK_POLICY_SLEW is only enabled on
    TARGET_I386
  mc146818rtc: drop unnecessary '#ifdef TARGET_I386'
  mc146818rtc: embrace all x86 specific code

 hw/timer/mc146818rtc.c | 212 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 149 insertions(+), 63 deletions(-)

-- 
2.9.3

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v3 0/5] mc146818rtc: fix Windows VM clock faster
@ 2017-05-10  8:32 ` guangrong.xiao
  0 siblings, 0 replies; 22+ messages in thread
From: guangrong.xiao @ 2017-05-10  8:32 UTC (permalink / raw)
  To: pbonzini, mst, mtosatti; +Cc: qemu-devel, kvm, yunfangtai, Xiao Guangrong

From: Xiao Guangrong <xiaoguangrong@tencent.com>

Changelog in v3:
Thanks to Paolo's the elaborate review comments, this version
simplifies the logic of periodic_timer_update() significantly
that includes:
1) introduce rtc_periodic_clock_ticks() that takes both regA and
   regB into account and returns the period clock
2) count the clocks since last interrupt by always using current
   clock subtracts the clock when last interrupt happened
3) improve the assert() logic

Paolo, all you comments have been reflected in this version except
globally using s->period because in the current code, only x86 is
using s->period so that we should obey this rule to keep compatible
migration. I have added the comment to explain this suitable in the
code:

            /*
             * as the old QEMUs only used s->period for the case that
             * LOST_TICK_POLICY_SLEW is used, in order to keep the
             * compatible migration, we obey the rule as old QEMUs.
             */
            s->period = period;
If anything i missed, please let me know. :)

Changelog in v2:
Thanks to Paolo's review, the changes in this version are:
1) merge patch 2, 3, 4 together
2) use a nice way ((value ^ new_value) & BIT_MASK) to check if updating
   for periodic timer is needed
3) use a smarter way to calculate coalesced irqs and lost_clock
4) make sure only x86 can enable LOST_TICK_POLICY_SLEW
5) make the code depends on LOST_TICK_POLICY_SLEW rather than
   TARGET_I386

We noticed that the clock on some windows VMs, e.g, Window7 and window8
is really faster and the issue can be easily reproduced by staring the
VM with '-rtc base=localtime,clock=vm,driftfix=slew -no-hpet' and 
running attached code in the guest

The root cause is that the clock will be lost if the periodic period is
changed as currently code counts the next periodic time like this:
      next_irq_clock = (cur_clock & ~(period - 1)) + period;

consider the case if cur_clock = 0x11FF and period = 0x100, then the
next_irq_clock is 0x1200, however, there is only 1 clock left to trigger
the next irq. Unfortunately, Windows guests (at least Windows7) change
the period very frequently if it runs the attached code, so that the
lost clock is accumulated, the wall-time become faster and faster

The main idea to fix the issue is we use a accurate clock period to
calculate the next irq:
    next_irq_clock = cur_clock + period;

After that, it is really convenient to compensate clock if it is needed 

The code running in windows VM is attached:
// TimeInternalTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#pragma comment(lib, "winmm")
#include <stdio.h>
#include <windows.h>

#define SWITCH_PEROID  13

int _tmain(int argc, _TCHAR* argv[])
{
	if (argc != 2)
	{
		printf("parameter error!\n");
		printf("USAGE: *.exe time(ms)\n");
		printf("example: *.exe 40\n");
		return 0;
	}
	else
	{
		DWORD internal = atoi((char *)argv[1]);
		DWORD count = 0;

		while (1)
		{
			count++;
			timeBeginPeriod(1);
			DWORD start = timeGetTime();
			Sleep(internal);
			timeEndPeriod(1);
			if ((count % SWITCH_PEROID) == 0) {
				Sleep(1);
			}
		}
	}
	return 0;
}

Tai Yunfang (1):
  mc146818rtc: precisely count the clock for periodic timer

Xiao Guangrong (4):
  mc146818rtc: update periodic timer only if it is needed
  mc146818rtc: ensure LOST_TICK_POLICY_SLEW is only enabled on
    TARGET_I386
  mc146818rtc: drop unnecessary '#ifdef TARGET_I386'
  mc146818rtc: embrace all x86 specific code

 hw/timer/mc146818rtc.c | 212 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 149 insertions(+), 63 deletions(-)

-- 
2.9.3

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH v3 1/5] mc146818rtc: update periodic timer only if it is needed
  2017-05-10  8:32 ` [Qemu-devel] " guangrong.xiao
@ 2017-05-10  8:32   ` guangrong.xiao
  -1 siblings, 0 replies; 22+ messages in thread
From: guangrong.xiao @ 2017-05-10  8:32 UTC (permalink / raw)
  To: pbonzini, mst, mtosatti; +Cc: qemu-devel, kvm, yunfangtai, Xiao Guangrong

From: Xiao Guangrong <xiaoguangrong@tencent.com>

Currently, the timer is updated whenever RegA or RegB is written
even if the periodic timer related configuration is not changed

This patch optimizes it slightly to make the update happen only
if its period or enable-status is changed, also later patches are
depend on this optimization

Signed-off-by: Xiao Guangrong <xiaoguangrong@tencent.com>
---
 hw/timer/mc146818rtc.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 4165450..5cccb2a 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -391,6 +391,7 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
                               uint64_t data, unsigned size)
 {
     RTCState *s = opaque;
+    bool update_periodic_timer;
 
     if ((addr & 1) == 0) {
         s->cmos_index = data & 0x7f;
@@ -423,6 +424,8 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
             }
             break;
         case RTC_REG_A:
+            update_periodic_timer = (s->cmos_data[RTC_REG_A] ^ data) & 0x0f;
+
             if ((data & 0x60) == 0x60) {
                 if (rtc_running(s)) {
                     rtc_update_time(s);
@@ -445,10 +448,17 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
             /* UIP bit is read only */
             s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
                 (s->cmos_data[RTC_REG_A] & REG_A_UIP);
-            periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+
+            if (update_periodic_timer) {
+                periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+            }
+
             check_update_timer(s);
             break;
         case RTC_REG_B:
+            update_periodic_timer = (s->cmos_data[RTC_REG_B] ^ data)
+                                       & REG_B_PIE;
+
             if (data & REG_B_SET) {
                 /* update cmos to when the rtc was stopping */
                 if (rtc_running(s)) {
@@ -475,7 +485,11 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
                 qemu_irq_lower(s->irq);
             }
             s->cmos_data[RTC_REG_B] = data;
-            periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+
+            if (update_periodic_timer) {
+                periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+            }
+
             check_update_timer(s);
             break;
         case RTC_REG_C:
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v3 1/5] mc146818rtc: update periodic timer only if it is needed
@ 2017-05-10  8:32   ` guangrong.xiao
  0 siblings, 0 replies; 22+ messages in thread
From: guangrong.xiao @ 2017-05-10  8:32 UTC (permalink / raw)
  To: pbonzini, mst, mtosatti; +Cc: qemu-devel, kvm, yunfangtai, Xiao Guangrong

From: Xiao Guangrong <xiaoguangrong@tencent.com>

Currently, the timer is updated whenever RegA or RegB is written
even if the periodic timer related configuration is not changed

This patch optimizes it slightly to make the update happen only
if its period or enable-status is changed, also later patches are
depend on this optimization

Signed-off-by: Xiao Guangrong <xiaoguangrong@tencent.com>
---
 hw/timer/mc146818rtc.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 4165450..5cccb2a 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -391,6 +391,7 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
                               uint64_t data, unsigned size)
 {
     RTCState *s = opaque;
+    bool update_periodic_timer;
 
     if ((addr & 1) == 0) {
         s->cmos_index = data & 0x7f;
@@ -423,6 +424,8 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
             }
             break;
         case RTC_REG_A:
+            update_periodic_timer = (s->cmos_data[RTC_REG_A] ^ data) & 0x0f;
+
             if ((data & 0x60) == 0x60) {
                 if (rtc_running(s)) {
                     rtc_update_time(s);
@@ -445,10 +448,17 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
             /* UIP bit is read only */
             s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
                 (s->cmos_data[RTC_REG_A] & REG_A_UIP);
-            periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+
+            if (update_periodic_timer) {
+                periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+            }
+
             check_update_timer(s);
             break;
         case RTC_REG_B:
+            update_periodic_timer = (s->cmos_data[RTC_REG_B] ^ data)
+                                       & REG_B_PIE;
+
             if (data & REG_B_SET) {
                 /* update cmos to when the rtc was stopping */
                 if (rtc_running(s)) {
@@ -475,7 +485,11 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
                 qemu_irq_lower(s->irq);
             }
             s->cmos_data[RTC_REG_B] = data;
-            periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+
+            if (update_periodic_timer) {
+                periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+            }
+
             check_update_timer(s);
             break;
         case RTC_REG_C:
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v3 2/5] mc146818rtc: precisely count the clock for periodic timer
  2017-05-10  8:32 ` [Qemu-devel] " guangrong.xiao
@ 2017-05-10  8:32   ` guangrong.xiao
  -1 siblings, 0 replies; 22+ messages in thread
From: guangrong.xiao @ 2017-05-10  8:32 UTC (permalink / raw)
  To: pbonzini, mst, mtosatti; +Cc: qemu-devel, kvm, yunfangtai, Xiao Guangrong

From: Tai Yunfang <yunfangtai@tencent.com>

There are two issues in current code:
1) If the period is changed by re-configuring RegA, the coalesced
   irq will be scaled to reflect the new period, however, it
   calculates the new interrupt number like this:
    s->irq_coalesced = (s->irq_coalesced * s->period) / period;

   There are some clocks will be lost if they are not enough to
   be squeezed to a single new period that will cause the VM clock
   slower

   In order to fix the issue, we calculate the interrupt window
   based on the precise clock rather than period, then the clocks
   lost during period is scaled can be compensated properly

2) If periodic_timer_update() is called due to RegA reconfiguration,
   i.e, the period is updated, current time is not the start point
   for the next periodic timer, instead, which should start from the
   last interrupt, otherwise, the clock in VM will become slow

   This patch takes the clocks from last interrupt to current clock
   into account and compensates the clocks for the next interrupt,
   especially,if a complete interrupt was lost in this window, the
   time can be caught up by LOST_TICK_POLICY_SLEW

Signed-off-by: Tai Yunfang <yunfangtai@tencent.com>
Signed-off-by: Xiao Guangrong <xiaoguangrong@tencent.com>
---
 hw/timer/mc146818rtc.c | 126 ++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 103 insertions(+), 23 deletions(-)

diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 5cccb2a..dac6744 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -146,31 +146,106 @@ static void rtc_coalesced_timer(void *opaque)
 }
 #endif
 
-/* handle periodic timer */
-static void periodic_timer_update(RTCState *s, int64_t current_time)
+static uint32_t rtc_periodic_clock_ticks(RTCState *s)
 {
-    int period_code, period;
-    int64_t cur_clock, next_irq_clock;
+    int period_code;
+
+    if (!(s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
+        return 0;
+     }
 
     period_code = s->cmos_data[RTC_REG_A] & 0x0f;
-    if (period_code != 0
-        && (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
-        if (period_code <= 2)
-            period_code += 7;
-        /* period in 32 Khz cycles */
-        period = 1 << (period_code - 1);
-#ifdef TARGET_I386
-        if (period != s->period) {
-            s->irq_coalesced = (s->irq_coalesced * s->period) / period;
-            DPRINTF_C("cmos: coalesced irqs scaled to %d\n", s->irq_coalesced);
-        }
-        s->period = period;
-#endif
+    if (!period_code) {
+        return 0;
+    }
+
+    if (period_code <= 2) {
+        period_code += 7;
+    }
+
+    /* period in 32 Khz cycles */
+    return 1 << (period_code - 1);
+}
+
+/*
+ * handle periodic timer. @old_period indicates the periodic timer update
+ * is just due to period adjustment.
+ */
+static void
+periodic_timer_update(RTCState *s, int64_t current_time, uint32_t old_period)
+{
+    uint32_t period;
+    int64_t cur_clock, next_irq_clock, lost_clock = 0;
+
+    period = rtc_periodic_clock_ticks(s);
+
+    if (period) {
         /* compute 32 khz clock */
         cur_clock =
             muldiv64(current_time, RTC_CLOCK_RATE, NANOSECONDS_PER_SECOND);
 
-        next_irq_clock = (cur_clock & ~(period - 1)) + period;
+        /*
+        * if the periodic timer's update is due to period re-configuration,
+        * we should count the clock since last interrupt.
+        */
+        if (old_period) {
+            int64_t last_periodic_clock, next_periodic_clock;
+
+            next_periodic_clock = muldiv64(s->next_periodic_time,
+                                    RTC_CLOCK_RATE, NANOSECONDS_PER_SECOND);
+            last_periodic_clock = next_periodic_clock - old_period;
+            lost_clock = cur_clock - last_periodic_clock;
+            assert(lost_clock >= 0);
+        }
+
+#ifdef TARGET_I386
+        /*
+         * recalculate the coalesced irqs for two reasons:
+         *    a) the lost_clock is more that a period, i,e. the timer
+         *       interrupt has been lost, we should catch up the time.
+         *
+         *    b) the period may be reconfigured, under this case, when
+         *       switching from a shorter to a longer period, scale down
+         *       the missing ticks since we expect the OS handler to
+         *       treat the delayed ticks as longer. Any leftovers are
+         *       put back into lost_clock.
+         *       When switching to a shorter period, scale up the missing
+         *       ticks since we expect the OS handler to treat the delayed
+         *       ticks as shorter.
+         */
+        if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
+            uint32_t old_irq_coalesced = s->irq_coalesced;
+
+            /*
+             * as the old QEMUs only used s->period for the case that
+             * LOST_TICK_POLICY_SLEW is used, in order to keep the
+             * compatible migration, we obey the rule as old QEMUs.
+             */
+            s->period = period;
+
+            lost_clock += old_irq_coalesced * old_period;
+            s->irq_coalesced = lost_clock / s->period;
+            lost_clock %= s->period;
+            if (old_irq_coalesced != s->irq_coalesced ||
+               old_period != s->period) {
+                DPRINTF_C("cmos: coalesced irqs scaled from %d to %d, "
+                          "period scaled from %d to %d\n", old_irq_coalesced,
+                          s->irq_coalesced, old_period, s->period);
+                rtc_coalesced_timer_update(s);
+            }
+        } else
+#endif
+        {
+           /*
+             * no way to compensate the interrupt if LOST_TICK_POLICY_SLEW
+             * is not used, we should make the time progress anyway.
+             */
+            lost_clock = MIN(lost_clock, period);
+        }
+
+        assert(lost_clock >= 0 && lost_clock <= period);
+
+        next_irq_clock = cur_clock + period - lost_clock;
         s->next_periodic_time = muldiv64(next_irq_clock, NANOSECONDS_PER_SECOND,
                                          RTC_CLOCK_RATE) + 1;
         timer_mod(s->periodic_timer, s->next_periodic_time);
@@ -186,7 +261,7 @@ static void rtc_periodic_timer(void *opaque)
 {
     RTCState *s = opaque;
 
-    periodic_timer_update(s, s->next_periodic_time);
+    periodic_timer_update(s, s->next_periodic_time, 0);
     s->cmos_data[RTC_REG_C] |= REG_C_PF;
     if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
         s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
@@ -391,6 +466,7 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
                               uint64_t data, unsigned size)
 {
     RTCState *s = opaque;
+    uint32_t old_period;
     bool update_periodic_timer;
 
     if ((addr & 1) == 0) {
@@ -425,6 +501,7 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
             break;
         case RTC_REG_A:
             update_periodic_timer = (s->cmos_data[RTC_REG_A] ^ data) & 0x0f;
+            old_period = rtc_periodic_clock_ticks(s);
 
             if ((data & 0x60) == 0x60) {
                 if (rtc_running(s)) {
@@ -450,7 +527,8 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
                 (s->cmos_data[RTC_REG_A] & REG_A_UIP);
 
             if (update_periodic_timer) {
-                periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+                periodic_timer_update(s, qemu_clock_get_ns(rtc_clock),
+                                      old_period);
             }
 
             check_update_timer(s);
@@ -458,6 +536,7 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
         case RTC_REG_B:
             update_periodic_timer = (s->cmos_data[RTC_REG_B] ^ data)
                                        & REG_B_PIE;
+            old_period = rtc_periodic_clock_ticks(s);
 
             if (data & REG_B_SET) {
                 /* update cmos to when the rtc was stopping */
@@ -487,7 +566,8 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
             s->cmos_data[RTC_REG_B] = data;
 
             if (update_periodic_timer) {
-                periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+                periodic_timer_update(s, qemu_clock_get_ns(rtc_clock),
+                                      old_period);
             }
 
             check_update_timer(s);
@@ -757,7 +837,7 @@ static int rtc_post_load(void *opaque, int version_id)
         uint64_t now = qemu_clock_get_ns(rtc_clock);
         if (now < s->next_periodic_time ||
             now > (s->next_periodic_time + get_max_clock_jump())) {
-            periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+            periodic_timer_update(s, qemu_clock_get_ns(rtc_clock), 0);
         }
     }
 
@@ -822,7 +902,7 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data)
     int64_t now = *(int64_t *)data;
 
     rtc_set_date_from_host(ISA_DEVICE(s));
-    periodic_timer_update(s, now);
+    periodic_timer_update(s, now, 0);
     check_update_timer(s);
 #ifdef TARGET_I386
     if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v3 2/5] mc146818rtc: precisely count the clock for periodic timer
@ 2017-05-10  8:32   ` guangrong.xiao
  0 siblings, 0 replies; 22+ messages in thread
From: guangrong.xiao @ 2017-05-10  8:32 UTC (permalink / raw)
  To: pbonzini, mst, mtosatti; +Cc: qemu-devel, kvm, yunfangtai, Xiao Guangrong

From: Tai Yunfang <yunfangtai@tencent.com>

There are two issues in current code:
1) If the period is changed by re-configuring RegA, the coalesced
   irq will be scaled to reflect the new period, however, it
   calculates the new interrupt number like this:
    s->irq_coalesced = (s->irq_coalesced * s->period) / period;

   There are some clocks will be lost if they are not enough to
   be squeezed to a single new period that will cause the VM clock
   slower

   In order to fix the issue, we calculate the interrupt window
   based on the precise clock rather than period, then the clocks
   lost during period is scaled can be compensated properly

2) If periodic_timer_update() is called due to RegA reconfiguration,
   i.e, the period is updated, current time is not the start point
   for the next periodic timer, instead, which should start from the
   last interrupt, otherwise, the clock in VM will become slow

   This patch takes the clocks from last interrupt to current clock
   into account and compensates the clocks for the next interrupt,
   especially,if a complete interrupt was lost in this window, the
   time can be caught up by LOST_TICK_POLICY_SLEW

Signed-off-by: Tai Yunfang <yunfangtai@tencent.com>
Signed-off-by: Xiao Guangrong <xiaoguangrong@tencent.com>
---
 hw/timer/mc146818rtc.c | 126 ++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 103 insertions(+), 23 deletions(-)

diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 5cccb2a..dac6744 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -146,31 +146,106 @@ static void rtc_coalesced_timer(void *opaque)
 }
 #endif
 
-/* handle periodic timer */
-static void periodic_timer_update(RTCState *s, int64_t current_time)
+static uint32_t rtc_periodic_clock_ticks(RTCState *s)
 {
-    int period_code, period;
-    int64_t cur_clock, next_irq_clock;
+    int period_code;
+
+    if (!(s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
+        return 0;
+     }
 
     period_code = s->cmos_data[RTC_REG_A] & 0x0f;
-    if (period_code != 0
-        && (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
-        if (period_code <= 2)
-            period_code += 7;
-        /* period in 32 Khz cycles */
-        period = 1 << (period_code - 1);
-#ifdef TARGET_I386
-        if (period != s->period) {
-            s->irq_coalesced = (s->irq_coalesced * s->period) / period;
-            DPRINTF_C("cmos: coalesced irqs scaled to %d\n", s->irq_coalesced);
-        }
-        s->period = period;
-#endif
+    if (!period_code) {
+        return 0;
+    }
+
+    if (period_code <= 2) {
+        period_code += 7;
+    }
+
+    /* period in 32 Khz cycles */
+    return 1 << (period_code - 1);
+}
+
+/*
+ * handle periodic timer. @old_period indicates the periodic timer update
+ * is just due to period adjustment.
+ */
+static void
+periodic_timer_update(RTCState *s, int64_t current_time, uint32_t old_period)
+{
+    uint32_t period;
+    int64_t cur_clock, next_irq_clock, lost_clock = 0;
+
+    period = rtc_periodic_clock_ticks(s);
+
+    if (period) {
         /* compute 32 khz clock */
         cur_clock =
             muldiv64(current_time, RTC_CLOCK_RATE, NANOSECONDS_PER_SECOND);
 
-        next_irq_clock = (cur_clock & ~(period - 1)) + period;
+        /*
+        * if the periodic timer's update is due to period re-configuration,
+        * we should count the clock since last interrupt.
+        */
+        if (old_period) {
+            int64_t last_periodic_clock, next_periodic_clock;
+
+            next_periodic_clock = muldiv64(s->next_periodic_time,
+                                    RTC_CLOCK_RATE, NANOSECONDS_PER_SECOND);
+            last_periodic_clock = next_periodic_clock - old_period;
+            lost_clock = cur_clock - last_periodic_clock;
+            assert(lost_clock >= 0);
+        }
+
+#ifdef TARGET_I386
+        /*
+         * recalculate the coalesced irqs for two reasons:
+         *    a) the lost_clock is more that a period, i,e. the timer
+         *       interrupt has been lost, we should catch up the time.
+         *
+         *    b) the period may be reconfigured, under this case, when
+         *       switching from a shorter to a longer period, scale down
+         *       the missing ticks since we expect the OS handler to
+         *       treat the delayed ticks as longer. Any leftovers are
+         *       put back into lost_clock.
+         *       When switching to a shorter period, scale up the missing
+         *       ticks since we expect the OS handler to treat the delayed
+         *       ticks as shorter.
+         */
+        if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
+            uint32_t old_irq_coalesced = s->irq_coalesced;
+
+            /*
+             * as the old QEMUs only used s->period for the case that
+             * LOST_TICK_POLICY_SLEW is used, in order to keep the
+             * compatible migration, we obey the rule as old QEMUs.
+             */
+            s->period = period;
+
+            lost_clock += old_irq_coalesced * old_period;
+            s->irq_coalesced = lost_clock / s->period;
+            lost_clock %= s->period;
+            if (old_irq_coalesced != s->irq_coalesced ||
+               old_period != s->period) {
+                DPRINTF_C("cmos: coalesced irqs scaled from %d to %d, "
+                          "period scaled from %d to %d\n", old_irq_coalesced,
+                          s->irq_coalesced, old_period, s->period);
+                rtc_coalesced_timer_update(s);
+            }
+        } else
+#endif
+        {
+           /*
+             * no way to compensate the interrupt if LOST_TICK_POLICY_SLEW
+             * is not used, we should make the time progress anyway.
+             */
+            lost_clock = MIN(lost_clock, period);
+        }
+
+        assert(lost_clock >= 0 && lost_clock <= period);
+
+        next_irq_clock = cur_clock + period - lost_clock;
         s->next_periodic_time = muldiv64(next_irq_clock, NANOSECONDS_PER_SECOND,
                                          RTC_CLOCK_RATE) + 1;
         timer_mod(s->periodic_timer, s->next_periodic_time);
@@ -186,7 +261,7 @@ static void rtc_periodic_timer(void *opaque)
 {
     RTCState *s = opaque;
 
-    periodic_timer_update(s, s->next_periodic_time);
+    periodic_timer_update(s, s->next_periodic_time, 0);
     s->cmos_data[RTC_REG_C] |= REG_C_PF;
     if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
         s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
@@ -391,6 +466,7 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
                               uint64_t data, unsigned size)
 {
     RTCState *s = opaque;
+    uint32_t old_period;
     bool update_periodic_timer;
 
     if ((addr & 1) == 0) {
@@ -425,6 +501,7 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
             break;
         case RTC_REG_A:
             update_periodic_timer = (s->cmos_data[RTC_REG_A] ^ data) & 0x0f;
+            old_period = rtc_periodic_clock_ticks(s);
 
             if ((data & 0x60) == 0x60) {
                 if (rtc_running(s)) {
@@ -450,7 +527,8 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
                 (s->cmos_data[RTC_REG_A] & REG_A_UIP);
 
             if (update_periodic_timer) {
-                periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+                periodic_timer_update(s, qemu_clock_get_ns(rtc_clock),
+                                      old_period);
             }
 
             check_update_timer(s);
@@ -458,6 +536,7 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
         case RTC_REG_B:
             update_periodic_timer = (s->cmos_data[RTC_REG_B] ^ data)
                                        & REG_B_PIE;
+            old_period = rtc_periodic_clock_ticks(s);
 
             if (data & REG_B_SET) {
                 /* update cmos to when the rtc was stopping */
@@ -487,7 +566,8 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
             s->cmos_data[RTC_REG_B] = data;
 
             if (update_periodic_timer) {
-                periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+                periodic_timer_update(s, qemu_clock_get_ns(rtc_clock),
+                                      old_period);
             }
 
             check_update_timer(s);
@@ -757,7 +837,7 @@ static int rtc_post_load(void *opaque, int version_id)
         uint64_t now = qemu_clock_get_ns(rtc_clock);
         if (now < s->next_periodic_time ||
             now > (s->next_periodic_time + get_max_clock_jump())) {
-            periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+            periodic_timer_update(s, qemu_clock_get_ns(rtc_clock), 0);
         }
     }
 
@@ -822,7 +902,7 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data)
     int64_t now = *(int64_t *)data;
 
     rtc_set_date_from_host(ISA_DEVICE(s));
-    periodic_timer_update(s, now);
+    periodic_timer_update(s, now, 0);
     check_update_timer(s);
 #ifdef TARGET_I386
     if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v3 3/5] mc146818rtc: ensure LOST_TICK_POLICY_SLEW is only enabled on TARGET_I386
  2017-05-10  8:32 ` [Qemu-devel] " guangrong.xiao
@ 2017-05-10  8:32   ` guangrong.xiao
  -1 siblings, 0 replies; 22+ messages in thread
From: guangrong.xiao @ 2017-05-10  8:32 UTC (permalink / raw)
  To: pbonzini, mst, mtosatti; +Cc: qemu-devel, kvm, yunfangtai, Xiao Guangrong

From: Xiao Guangrong <xiaoguangrong@tencent.com>

Any tick policy specified on other platforms rather on TARGET_I386
will fall back to LOST_TICK_POLICY_DISCARD silently, this patch makes
sure only TARGET_I386 can enable LOST_TICK_POLICY_SLEW

After that, we can enable LOST_TICK_POLICY_SLEW in the common code
which need not use '#ifdef TARGET_I386' to make these code be x86
specific anymore

Signed-off-by: Xiao Guangrong <xiaoguangrong@tencent.com>
---
 hw/timer/mc146818rtc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index dac6744..9810bd5 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -980,19 +980,19 @@ static void rtc_realizefn(DeviceState *dev, Error **errp)
 
     rtc_set_date_from_host(isadev);
 
-#ifdef TARGET_I386
     switch (s->lost_tick_policy) {
+#ifdef TARGET_I386
     case LOST_TICK_POLICY_SLEW:
         s->coalesced_timer =
             timer_new_ns(rtc_clock, rtc_coalesced_timer, s);
         break;
+#endif
     case LOST_TICK_POLICY_DISCARD:
         break;
     default:
         error_setg(errp, "Invalid lost tick policy.");
         return;
     }
-#endif
 
     s->periodic_timer = timer_new_ns(rtc_clock, rtc_periodic_timer, s);
     s->update_timer = timer_new_ns(rtc_clock, rtc_update_timer, s);
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v3 3/5] mc146818rtc: ensure LOST_TICK_POLICY_SLEW is only enabled on TARGET_I386
@ 2017-05-10  8:32   ` guangrong.xiao
  0 siblings, 0 replies; 22+ messages in thread
From: guangrong.xiao @ 2017-05-10  8:32 UTC (permalink / raw)
  To: pbonzini, mst, mtosatti; +Cc: qemu-devel, kvm, yunfangtai, Xiao Guangrong

From: Xiao Guangrong <xiaoguangrong@tencent.com>

Any tick policy specified on other platforms rather on TARGET_I386
will fall back to LOST_TICK_POLICY_DISCARD silently, this patch makes
sure only TARGET_I386 can enable LOST_TICK_POLICY_SLEW

After that, we can enable LOST_TICK_POLICY_SLEW in the common code
which need not use '#ifdef TARGET_I386' to make these code be x86
specific anymore

Signed-off-by: Xiao Guangrong <xiaoguangrong@tencent.com>
---
 hw/timer/mc146818rtc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index dac6744..9810bd5 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -980,19 +980,19 @@ static void rtc_realizefn(DeviceState *dev, Error **errp)
 
     rtc_set_date_from_host(isadev);
 
-#ifdef TARGET_I386
     switch (s->lost_tick_policy) {
+#ifdef TARGET_I386
     case LOST_TICK_POLICY_SLEW:
         s->coalesced_timer =
             timer_new_ns(rtc_clock, rtc_coalesced_timer, s);
         break;
+#endif
     case LOST_TICK_POLICY_DISCARD:
         break;
     default:
         error_setg(errp, "Invalid lost tick policy.");
         return;
     }
-#endif
 
     s->periodic_timer = timer_new_ns(rtc_clock, rtc_periodic_timer, s);
     s->update_timer = timer_new_ns(rtc_clock, rtc_update_timer, s);
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v3 4/5] mc146818rtc: drop unnecessary '#ifdef TARGET_I386'
  2017-05-10  8:32 ` [Qemu-devel] " guangrong.xiao
@ 2017-05-10  8:32   ` guangrong.xiao
  -1 siblings, 0 replies; 22+ messages in thread
From: guangrong.xiao @ 2017-05-10  8:32 UTC (permalink / raw)
  To: pbonzini, mst, mtosatti; +Cc: qemu-devel, kvm, yunfangtai, Xiao Guangrong

From: Xiao Guangrong <xiaoguangrong@tencent.com>

If the code purely depends on LOST_TICK_POLICY_SLEW, we can simply
drop '#ifdef TARGET_I386' as only x86 can enable this tick policy

Signed-off-by: Xiao Guangrong <xiaoguangrong@tencent.com>
---
 hw/timer/mc146818rtc.c | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 9810bd5..104a26d 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -112,7 +112,6 @@ static uint64_t get_guest_rtc_ns(RTCState *s)
         guest_clock - s->last_update + s->offset;
 }
 
-#ifdef TARGET_I386
 static void rtc_coalesced_timer_update(RTCState *s)
 {
     if (s->irq_coalesced == 0) {
@@ -126,6 +125,7 @@ static void rtc_coalesced_timer_update(RTCState *s)
     }
 }
 
+#ifdef TARGET_I386
 static void rtc_coalesced_timer(void *opaque)
 {
     RTCState *s = opaque;
@@ -198,7 +198,6 @@ periodic_timer_update(RTCState *s, int64_t current_time, uint32_t old_period)
             assert(lost_clock >= 0);
         }
 
-#ifdef TARGET_I386
         /*
          * recalculate the coalesced irqs for two reasons:
          *    a) the lost_clock is more that a period, i,e. the timer
@@ -233,9 +232,7 @@ periodic_timer_update(RTCState *s, int64_t current_time, uint32_t old_period)
                           s->irq_coalesced, old_period, s->period);
                 rtc_coalesced_timer_update(s);
             }
-        } else
-#endif
-        {
+        } else {
            /*
              * no way to compensate the interrupt if LOST_TICK_POLICY_SLEW
              * is not used, we should make the time progress anyway.
@@ -250,9 +247,7 @@ periodic_timer_update(RTCState *s, int64_t current_time, uint32_t old_period)
                                          RTC_CLOCK_RATE) + 1;
         timer_mod(s->periodic_timer, s->next_periodic_time);
     } else {
-#ifdef TARGET_I386
         s->irq_coalesced = 0;
-#endif
         timer_del(s->periodic_timer);
     }
 }
@@ -841,13 +836,11 @@ static int rtc_post_load(void *opaque, int version_id)
         }
     }
 
-#ifdef TARGET_I386
     if (version_id >= 2) {
         if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
             rtc_coalesced_timer_update(s);
         }
     }
-#endif
     return 0;
 }
 
@@ -904,11 +897,10 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data)
     rtc_set_date_from_host(ISA_DEVICE(s));
     periodic_timer_update(s, now, 0);
     check_update_timer(s);
-#ifdef TARGET_I386
+
     if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
         rtc_coalesced_timer_update(s);
     }
-#endif
 }
 
 /* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
@@ -929,12 +921,10 @@ static void rtc_reset(void *opaque)
 
     qemu_irq_lower(s->irq);
 
-#ifdef TARGET_I386
     if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
         s->irq_coalesced = 0;
         s->irq_reinject_on_ack_count = 0;		
     }
-#endif
 }
 
 static const MemoryRegionOps cmos_ops = {
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v3 4/5] mc146818rtc: drop unnecessary '#ifdef TARGET_I386'
@ 2017-05-10  8:32   ` guangrong.xiao
  0 siblings, 0 replies; 22+ messages in thread
From: guangrong.xiao @ 2017-05-10  8:32 UTC (permalink / raw)
  To: pbonzini, mst, mtosatti; +Cc: qemu-devel, kvm, yunfangtai, Xiao Guangrong

From: Xiao Guangrong <xiaoguangrong@tencent.com>

If the code purely depends on LOST_TICK_POLICY_SLEW, we can simply
drop '#ifdef TARGET_I386' as only x86 can enable this tick policy

Signed-off-by: Xiao Guangrong <xiaoguangrong@tencent.com>
---
 hw/timer/mc146818rtc.c | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 9810bd5..104a26d 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -112,7 +112,6 @@ static uint64_t get_guest_rtc_ns(RTCState *s)
         guest_clock - s->last_update + s->offset;
 }
 
-#ifdef TARGET_I386
 static void rtc_coalesced_timer_update(RTCState *s)
 {
     if (s->irq_coalesced == 0) {
@@ -126,6 +125,7 @@ static void rtc_coalesced_timer_update(RTCState *s)
     }
 }
 
+#ifdef TARGET_I386
 static void rtc_coalesced_timer(void *opaque)
 {
     RTCState *s = opaque;
@@ -198,7 +198,6 @@ periodic_timer_update(RTCState *s, int64_t current_time, uint32_t old_period)
             assert(lost_clock >= 0);
         }
 
-#ifdef TARGET_I386
         /*
          * recalculate the coalesced irqs for two reasons:
          *    a) the lost_clock is more that a period, i,e. the timer
@@ -233,9 +232,7 @@ periodic_timer_update(RTCState *s, int64_t current_time, uint32_t old_period)
                           s->irq_coalesced, old_period, s->period);
                 rtc_coalesced_timer_update(s);
             }
-        } else
-#endif
-        {
+        } else {
            /*
              * no way to compensate the interrupt if LOST_TICK_POLICY_SLEW
              * is not used, we should make the time progress anyway.
@@ -250,9 +247,7 @@ periodic_timer_update(RTCState *s, int64_t current_time, uint32_t old_period)
                                          RTC_CLOCK_RATE) + 1;
         timer_mod(s->periodic_timer, s->next_periodic_time);
     } else {
-#ifdef TARGET_I386
         s->irq_coalesced = 0;
-#endif
         timer_del(s->periodic_timer);
     }
 }
@@ -841,13 +836,11 @@ static int rtc_post_load(void *opaque, int version_id)
         }
     }
 
-#ifdef TARGET_I386
     if (version_id >= 2) {
         if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
             rtc_coalesced_timer_update(s);
         }
     }
-#endif
     return 0;
 }
 
@@ -904,11 +897,10 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data)
     rtc_set_date_from_host(ISA_DEVICE(s));
     periodic_timer_update(s, now, 0);
     check_update_timer(s);
-#ifdef TARGET_I386
+
     if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
         rtc_coalesced_timer_update(s);
     }
-#endif
 }
 
 /* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
@@ -929,12 +921,10 @@ static void rtc_reset(void *opaque)
 
     qemu_irq_lower(s->irq);
 
-#ifdef TARGET_I386
     if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
         s->irq_coalesced = 0;
         s->irq_reinject_on_ack_count = 0;		
     }
-#endif
 }
 
 static const MemoryRegionOps cmos_ops = {
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v3 5/5] mc146818rtc: embrace all x86 specific code
  2017-05-10  8:32 ` [Qemu-devel] " guangrong.xiao
@ 2017-05-10  8:32   ` guangrong.xiao
  -1 siblings, 0 replies; 22+ messages in thread
From: guangrong.xiao @ 2017-05-10  8:32 UTC (permalink / raw)
  To: pbonzini, mst, mtosatti; +Cc: qemu-devel, kvm, yunfangtai, Xiao Guangrong

From: Xiao Guangrong <xiaoguangrong@tencent.com>

Introduce a function, rtc_policy_slew_deliver_irq(), which delivers
irq if LOST_TICK_POLICY_SLEW is used, as which is only supported on
x86, other platforms call it will trigger a assert

After that, we can move the x86 specific code to the common place

Signed-off-by: Xiao Guangrong <xiaoguangrong@tencent.com>
---
 hw/timer/mc146818rtc.c | 60 ++++++++++++++++++++++++++------------------------
 1 file changed, 31 insertions(+), 29 deletions(-)

diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 104a26d..6d0a610 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -125,17 +125,34 @@ static void rtc_coalesced_timer_update(RTCState *s)
     }
 }
 
+static QLIST_HEAD(, RTCState) rtc_devices =
+    QLIST_HEAD_INITIALIZER(rtc_devices);
+
 #ifdef TARGET_I386
+void qmp_rtc_reset_reinjection(Error **errp)
+{
+    RTCState *s;
+
+    QLIST_FOREACH(s, &rtc_devices, link) {
+        s->irq_coalesced = 0;
+    }
+}
+
+static bool rtc_policy_slew_deliver_irq(RTCState *s)
+{
+    apic_reset_irq_delivered();
+    qemu_irq_raise(s->irq);
+    return apic_get_irq_delivered();
+}
+
 static void rtc_coalesced_timer(void *opaque)
 {
     RTCState *s = opaque;
 
     if (s->irq_coalesced != 0) {
-        apic_reset_irq_delivered();
         s->cmos_data[RTC_REG_C] |= 0xc0;
         DPRINTF_C("cmos: injecting from timer\n");
-        qemu_irq_raise(s->irq);
-        if (apic_get_irq_delivered()) {
+        if (rtc_policy_slew_deliver_irq(s)) {
             s->irq_coalesced--;
             DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
                       s->irq_coalesced);
@@ -144,6 +161,12 @@ static void rtc_coalesced_timer(void *opaque)
 
     rtc_coalesced_timer_update(s);
 }
+#else
+static bool rtc_policy_slew_deliver_irq(RTCState *s)
+{
+    assert(0);
+    return false;
+}
 #endif
 
 static uint32_t rtc_periodic_clock_ticks(RTCState *s)
@@ -260,21 +283,17 @@ static void rtc_periodic_timer(void *opaque)
     s->cmos_data[RTC_REG_C] |= REG_C_PF;
     if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
         s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
-#ifdef TARGET_I386
         if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
             if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
-                s->irq_reinject_on_ack_count = 0;		
-            apic_reset_irq_delivered();
-            qemu_irq_raise(s->irq);
-            if (!apic_get_irq_delivered()) {
+                s->irq_reinject_on_ack_count = 0;
+            if (!rtc_policy_slew_deliver_irq(s)) {
                 s->irq_coalesced++;
                 rtc_coalesced_timer_update(s);
                 DPRINTF_C("cmos: coalesced irqs increased to %d\n",
                           s->irq_coalesced);
             }
         } else
-#endif
-        qemu_irq_raise(s->irq);
+            qemu_irq_raise(s->irq);
     }
 }
 
@@ -618,20 +637,6 @@ static void rtc_get_time(RTCState *s, struct tm *tm)
         rtc_from_bcd(s, s->cmos_data[RTC_CENTURY]) * 100 - 1900;
 }
 
-static QLIST_HEAD(, RTCState) rtc_devices =
-    QLIST_HEAD_INITIALIZER(rtc_devices);
-
-#ifdef TARGET_I386
-void qmp_rtc_reset_reinjection(Error **errp)
-{
-    RTCState *s;
-
-    QLIST_FOREACH(s, &rtc_devices, link) {
-        s->irq_coalesced = 0;
-    }
-}
-#endif
-
 static void rtc_set_time(RTCState *s)
 {
     struct tm tm;
@@ -751,22 +756,19 @@ static uint64_t cmos_ioport_read(void *opaque, hwaddr addr,
             if (ret & (REG_C_UF | REG_C_AF)) {
                 check_update_timer(s);
             }
-#ifdef TARGET_I386
+
             if(s->irq_coalesced &&
                     (s->cmos_data[RTC_REG_B] & REG_B_PIE) &&
                     s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) {
                 s->irq_reinject_on_ack_count++;
                 s->cmos_data[RTC_REG_C] |= REG_C_IRQF | REG_C_PF;
-                apic_reset_irq_delivered();
                 DPRINTF_C("cmos: injecting on ack\n");
-                qemu_irq_raise(s->irq);
-                if (apic_get_irq_delivered()) {
+                if (rtc_policy_slew_deliver_irq(s)) {
                     s->irq_coalesced--;
                     DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
                               s->irq_coalesced);
                 }
             }
-#endif
             break;
         default:
             ret = s->cmos_data[s->cmos_index];
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v3 5/5] mc146818rtc: embrace all x86 specific code
@ 2017-05-10  8:32   ` guangrong.xiao
  0 siblings, 0 replies; 22+ messages in thread
From: guangrong.xiao @ 2017-05-10  8:32 UTC (permalink / raw)
  To: pbonzini, mst, mtosatti; +Cc: qemu-devel, kvm, yunfangtai, Xiao Guangrong

From: Xiao Guangrong <xiaoguangrong@tencent.com>

Introduce a function, rtc_policy_slew_deliver_irq(), which delivers
irq if LOST_TICK_POLICY_SLEW is used, as which is only supported on
x86, other platforms call it will trigger a assert

After that, we can move the x86 specific code to the common place

Signed-off-by: Xiao Guangrong <xiaoguangrong@tencent.com>
---
 hw/timer/mc146818rtc.c | 60 ++++++++++++++++++++++++++------------------------
 1 file changed, 31 insertions(+), 29 deletions(-)

diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 104a26d..6d0a610 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -125,17 +125,34 @@ static void rtc_coalesced_timer_update(RTCState *s)
     }
 }
 
+static QLIST_HEAD(, RTCState) rtc_devices =
+    QLIST_HEAD_INITIALIZER(rtc_devices);
+
 #ifdef TARGET_I386
+void qmp_rtc_reset_reinjection(Error **errp)
+{
+    RTCState *s;
+
+    QLIST_FOREACH(s, &rtc_devices, link) {
+        s->irq_coalesced = 0;
+    }
+}
+
+static bool rtc_policy_slew_deliver_irq(RTCState *s)
+{
+    apic_reset_irq_delivered();
+    qemu_irq_raise(s->irq);
+    return apic_get_irq_delivered();
+}
+
 static void rtc_coalesced_timer(void *opaque)
 {
     RTCState *s = opaque;
 
     if (s->irq_coalesced != 0) {
-        apic_reset_irq_delivered();
         s->cmos_data[RTC_REG_C] |= 0xc0;
         DPRINTF_C("cmos: injecting from timer\n");
-        qemu_irq_raise(s->irq);
-        if (apic_get_irq_delivered()) {
+        if (rtc_policy_slew_deliver_irq(s)) {
             s->irq_coalesced--;
             DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
                       s->irq_coalesced);
@@ -144,6 +161,12 @@ static void rtc_coalesced_timer(void *opaque)
 
     rtc_coalesced_timer_update(s);
 }
+#else
+static bool rtc_policy_slew_deliver_irq(RTCState *s)
+{
+    assert(0);
+    return false;
+}
 #endif
 
 static uint32_t rtc_periodic_clock_ticks(RTCState *s)
@@ -260,21 +283,17 @@ static void rtc_periodic_timer(void *opaque)
     s->cmos_data[RTC_REG_C] |= REG_C_PF;
     if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
         s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
-#ifdef TARGET_I386
         if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
             if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
-                s->irq_reinject_on_ack_count = 0;		
-            apic_reset_irq_delivered();
-            qemu_irq_raise(s->irq);
-            if (!apic_get_irq_delivered()) {
+                s->irq_reinject_on_ack_count = 0;
+            if (!rtc_policy_slew_deliver_irq(s)) {
                 s->irq_coalesced++;
                 rtc_coalesced_timer_update(s);
                 DPRINTF_C("cmos: coalesced irqs increased to %d\n",
                           s->irq_coalesced);
             }
         } else
-#endif
-        qemu_irq_raise(s->irq);
+            qemu_irq_raise(s->irq);
     }
 }
 
@@ -618,20 +637,6 @@ static void rtc_get_time(RTCState *s, struct tm *tm)
         rtc_from_bcd(s, s->cmos_data[RTC_CENTURY]) * 100 - 1900;
 }
 
-static QLIST_HEAD(, RTCState) rtc_devices =
-    QLIST_HEAD_INITIALIZER(rtc_devices);
-
-#ifdef TARGET_I386
-void qmp_rtc_reset_reinjection(Error **errp)
-{
-    RTCState *s;
-
-    QLIST_FOREACH(s, &rtc_devices, link) {
-        s->irq_coalesced = 0;
-    }
-}
-#endif
-
 static void rtc_set_time(RTCState *s)
 {
     struct tm tm;
@@ -751,22 +756,19 @@ static uint64_t cmos_ioport_read(void *opaque, hwaddr addr,
             if (ret & (REG_C_UF | REG_C_AF)) {
                 check_update_timer(s);
             }
-#ifdef TARGET_I386
+
             if(s->irq_coalesced &&
                     (s->cmos_data[RTC_REG_B] & REG_B_PIE) &&
                     s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) {
                 s->irq_reinject_on_ack_count++;
                 s->cmos_data[RTC_REG_C] |= REG_C_IRQF | REG_C_PF;
-                apic_reset_irq_delivered();
                 DPRINTF_C("cmos: injecting on ack\n");
-                qemu_irq_raise(s->irq);
-                if (apic_get_irq_delivered()) {
+                if (rtc_policy_slew_deliver_irq(s)) {
                     s->irq_coalesced--;
                     DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
                               s->irq_coalesced);
                 }
             }
-#endif
             break;
         default:
             ret = s->cmos_data[s->cmos_index];
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH v3 0/5] mc146818rtc: fix Windows VM clock faster
  2017-05-10  8:32 ` [Qemu-devel] " guangrong.xiao
@ 2017-05-10  9:53   ` Paolo Bonzini
  -1 siblings, 0 replies; 22+ messages in thread
From: Paolo Bonzini @ 2017-05-10  9:53 UTC (permalink / raw)
  To: guangrong.xiao, mst, mtosatti; +Cc: qemu-devel, kvm, yunfangtai, Xiao Guangrong



On 10/05/2017 10:32, guangrong.xiao@gmail.com wrote:
> From: Xiao Guangrong <xiaoguangrong@tencent.com>
> 
> Changelog in v3:
> Thanks to Paolo's the elaborate review comments, this version
> simplifies the logic of periodic_timer_update() significantly
> that includes:
> 1) introduce rtc_periodic_clock_ticks() that takes both regA and
>    regB into account and returns the period clock
> 2) count the clocks since last interrupt by always using current
>    clock subtracts the clock when last interrupt happened
> 3) improve the assert() logic
> 
> Paolo, all you comments have been reflected in this version except
> globally using s->period because in the current code, only x86 is
> using s->period so that we should obey this rule to keep compatible
> migration. I have added the comment to explain this suitable in the
> code:
> 
>             /*
>              * as the old QEMUs only used s->period for the case that
>              * LOST_TICK_POLICY_SLEW is used, in order to keep the
>              * compatible migration, we obey the rule as old QEMUs.
>              */
>             s->period = period;
> If anything i missed, please let me know. :)

Looks great.  Thanks for following up quickly on the reviews.

Paolo

> Changelog in v2:
> Thanks to Paolo's review, the changes in this version are:
> 1) merge patch 2, 3, 4 together
> 2) use a nice way ((value ^ new_value) & BIT_MASK) to check if updating
>    for periodic timer is needed
> 3) use a smarter way to calculate coalesced irqs and lost_clock
> 4) make sure only x86 can enable LOST_TICK_POLICY_SLEW
> 5) make the code depends on LOST_TICK_POLICY_SLEW rather than
>    TARGET_I386
> 
> We noticed that the clock on some windows VMs, e.g, Window7 and window8
> is really faster and the issue can be easily reproduced by staring the
> VM with '-rtc base=localtime,clock=vm,driftfix=slew -no-hpet' and 
> running attached code in the guest
> 
> The root cause is that the clock will be lost if the periodic period is
> changed as currently code counts the next periodic time like this:
>       next_irq_clock = (cur_clock & ~(period - 1)) + period;
> 
> consider the case if cur_clock = 0x11FF and period = 0x100, then the
> next_irq_clock is 0x1200, however, there is only 1 clock left to trigger
> the next irq. Unfortunately, Windows guests (at least Windows7) change
> the period very frequently if it runs the attached code, so that the
> lost clock is accumulated, the wall-time become faster and faster
> 
> The main idea to fix the issue is we use a accurate clock period to
> calculate the next irq:
>     next_irq_clock = cur_clock + period;
> 
> After that, it is really convenient to compensate clock if it is needed 
> 
> The code running in windows VM is attached:
> // TimeInternalTest.cpp : Defines the entry point for the console application.
> //
> 
> #include "stdafx.h"
> #pragma comment(lib, "winmm")
> #include <stdio.h>
> #include <windows.h>
> 
> #define SWITCH_PEROID  13
> 
> int _tmain(int argc, _TCHAR* argv[])
> {
> 	if (argc != 2)
> 	{
> 		printf("parameter error!\n");
> 		printf("USAGE: *.exe time(ms)\n");
> 		printf("example: *.exe 40\n");
> 		return 0;
> 	}
> 	else
> 	{
> 		DWORD internal = atoi((char *)argv[1]);
> 		DWORD count = 0;
> 
> 		while (1)
> 		{
> 			count++;
> 			timeBeginPeriod(1);
> 			DWORD start = timeGetTime();
> 			Sleep(internal);
> 			timeEndPeriod(1);
> 			if ((count % SWITCH_PEROID) == 0) {
> 				Sleep(1);
> 			}
> 		}
> 	}
> 	return 0;
> }
> 
> Tai Yunfang (1):
>   mc146818rtc: precisely count the clock for periodic timer
> 
> Xiao Guangrong (4):
>   mc146818rtc: update periodic timer only if it is needed
>   mc146818rtc: ensure LOST_TICK_POLICY_SLEW is only enabled on
>     TARGET_I386
>   mc146818rtc: drop unnecessary '#ifdef TARGET_I386'
>   mc146818rtc: embrace all x86 specific code
> 
>  hw/timer/mc146818rtc.c | 212 ++++++++++++++++++++++++++++++++++---------------
>  1 file changed, 149 insertions(+), 63 deletions(-)
> 

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v3 0/5] mc146818rtc: fix Windows VM clock faster
@ 2017-05-10  9:53   ` Paolo Bonzini
  0 siblings, 0 replies; 22+ messages in thread
From: Paolo Bonzini @ 2017-05-10  9:53 UTC (permalink / raw)
  To: guangrong.xiao, mst, mtosatti; +Cc: qemu-devel, kvm, yunfangtai, Xiao Guangrong



On 10/05/2017 10:32, guangrong.xiao@gmail.com wrote:
> From: Xiao Guangrong <xiaoguangrong@tencent.com>
> 
> Changelog in v3:
> Thanks to Paolo's the elaborate review comments, this version
> simplifies the logic of periodic_timer_update() significantly
> that includes:
> 1) introduce rtc_periodic_clock_ticks() that takes both regA and
>    regB into account and returns the period clock
> 2) count the clocks since last interrupt by always using current
>    clock subtracts the clock when last interrupt happened
> 3) improve the assert() logic
> 
> Paolo, all you comments have been reflected in this version except
> globally using s->period because in the current code, only x86 is
> using s->period so that we should obey this rule to keep compatible
> migration. I have added the comment to explain this suitable in the
> code:
> 
>             /*
>              * as the old QEMUs only used s->period for the case that
>              * LOST_TICK_POLICY_SLEW is used, in order to keep the
>              * compatible migration, we obey the rule as old QEMUs.
>              */
>             s->period = period;
> If anything i missed, please let me know. :)

Looks great.  Thanks for following up quickly on the reviews.

Paolo

> Changelog in v2:
> Thanks to Paolo's review, the changes in this version are:
> 1) merge patch 2, 3, 4 together
> 2) use a nice way ((value ^ new_value) & BIT_MASK) to check if updating
>    for periodic timer is needed
> 3) use a smarter way to calculate coalesced irqs and lost_clock
> 4) make sure only x86 can enable LOST_TICK_POLICY_SLEW
> 5) make the code depends on LOST_TICK_POLICY_SLEW rather than
>    TARGET_I386
> 
> We noticed that the clock on some windows VMs, e.g, Window7 and window8
> is really faster and the issue can be easily reproduced by staring the
> VM with '-rtc base=localtime,clock=vm,driftfix=slew -no-hpet' and 
> running attached code in the guest
> 
> The root cause is that the clock will be lost if the periodic period is
> changed as currently code counts the next periodic time like this:
>       next_irq_clock = (cur_clock & ~(period - 1)) + period;
> 
> consider the case if cur_clock = 0x11FF and period = 0x100, then the
> next_irq_clock is 0x1200, however, there is only 1 clock left to trigger
> the next irq. Unfortunately, Windows guests (at least Windows7) change
> the period very frequently if it runs the attached code, so that the
> lost clock is accumulated, the wall-time become faster and faster
> 
> The main idea to fix the issue is we use a accurate clock period to
> calculate the next irq:
>     next_irq_clock = cur_clock + period;
> 
> After that, it is really convenient to compensate clock if it is needed 
> 
> The code running in windows VM is attached:
> // TimeInternalTest.cpp : Defines the entry point for the console application.
> //
> 
> #include "stdafx.h"
> #pragma comment(lib, "winmm")
> #include <stdio.h>
> #include <windows.h>
> 
> #define SWITCH_PEROID  13
> 
> int _tmain(int argc, _TCHAR* argv[])
> {
> 	if (argc != 2)
> 	{
> 		printf("parameter error!\n");
> 		printf("USAGE: *.exe time(ms)\n");
> 		printf("example: *.exe 40\n");
> 		return 0;
> 	}
> 	else
> 	{
> 		DWORD internal = atoi((char *)argv[1]);
> 		DWORD count = 0;
> 
> 		while (1)
> 		{
> 			count++;
> 			timeBeginPeriod(1);
> 			DWORD start = timeGetTime();
> 			Sleep(internal);
> 			timeEndPeriod(1);
> 			if ((count % SWITCH_PEROID) == 0) {
> 				Sleep(1);
> 			}
> 		}
> 	}
> 	return 0;
> }
> 
> Tai Yunfang (1):
>   mc146818rtc: precisely count the clock for periodic timer
> 
> Xiao Guangrong (4):
>   mc146818rtc: update periodic timer only if it is needed
>   mc146818rtc: ensure LOST_TICK_POLICY_SLEW is only enabled on
>     TARGET_I386
>   mc146818rtc: drop unnecessary '#ifdef TARGET_I386'
>   mc146818rtc: embrace all x86 specific code
> 
>  hw/timer/mc146818rtc.c | 212 ++++++++++++++++++++++++++++++++++---------------
>  1 file changed, 149 insertions(+), 63 deletions(-)
> 

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v3 0/5] mc146818rtc: fix Windows VM clock faster
  2017-05-10  8:32 ` [Qemu-devel] " guangrong.xiao
                   ` (6 preceding siblings ...)
  (?)
@ 2017-05-10 10:04 ` no-reply
  -1 siblings, 0 replies; 22+ messages in thread
From: no-reply @ 2017-05-10 10:04 UTC (permalink / raw)
  To: guangrong.xiao
  Cc: famz, pbonzini, mst, mtosatti, xiaoguangrong, yunfangtai,
	qemu-devel, kvm

Hi,

This series seems to have some coding style problems. See output below for
more information:

Message-id: 20170510083259.3900-1-xiaoguangrong@tencent.com
Type: series
Subject: [Qemu-devel] [PATCH v3 0/5] mc146818rtc: fix Windows VM clock faster

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
    echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
    if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
        failed=1
        echo
    fi
    n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]         patchew/20170510092333.8890-1-famz@redhat.com -> patchew/20170510092333.8890-1-famz@redhat.com
 * [new tag]         patchew/20170510092903.23649-1-marcel@redhat.com -> patchew/20170510092903.23649-1-marcel@redhat.com
Switched to a new branch 'test'
e739ce9 mc146818rtc: embrace all x86 specific code
1aa2c5e mc146818rtc: drop unnecessary '#ifdef TARGET_I386'
0ab5312 mc146818rtc: ensure LOST_TICK_POLICY_SLEW is only enabled on TARGET_I386
f90b3ba mc146818rtc: precisely count the clock for periodic timer
95f013c mc146818rtc: update periodic timer only if it is needed

=== OUTPUT BEGIN ===
Checking PATCH 1/5: mc146818rtc: update periodic timer only if it is needed...
Checking PATCH 2/5: mc146818rtc: precisely count the clock for periodic timer...
ERROR: braces {} are necessary for all arms of this statement
#130: FILE: hw/timer/mc146818rtc.c:216:
+        if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
[...]
+        } else
[...]

total: 1 errors, 0 warnings, 187 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 3/5: mc146818rtc: ensure LOST_TICK_POLICY_SLEW is only enabled on TARGET_I386...
Checking PATCH 4/5: mc146818rtc: drop unnecessary '#ifdef TARGET_I386'...
Checking PATCH 5/5: mc146818rtc: embrace all x86 specific code...
=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v3 4/5] mc146818rtc: drop unnecessary '#ifdef TARGET_I386'
  2017-05-10  8:32   ` [Qemu-devel] " guangrong.xiao
  (?)
@ 2017-05-13 22:12   ` Philippe Mathieu-Daudé
  -1 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-05-13 22:12 UTC (permalink / raw)
  To: guangrong.xiao, pbonzini, mst, mtosatti
  Cc: Xiao Guangrong, yunfangtai, qemu-devel, kvm

On 05/10/2017 05:32 AM, guangrong.xiao@gmail.com wrote:
> From: Xiao Guangrong <xiaoguangrong@tencent.com>
>
> If the code purely depends on LOST_TICK_POLICY_SLEW, we can simply
> drop '#ifdef TARGET_I386' as only x86 can enable this tick policy
>
> Signed-off-by: Xiao Guangrong <xiaoguangrong@tencent.com>

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>  hw/timer/mc146818rtc.c | 16 +++-------------
>  1 file changed, 3 insertions(+), 13 deletions(-)
>
> diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
> index 9810bd5..104a26d 100644
> --- a/hw/timer/mc146818rtc.c
> +++ b/hw/timer/mc146818rtc.c
> @@ -112,7 +112,6 @@ static uint64_t get_guest_rtc_ns(RTCState *s)
>          guest_clock - s->last_update + s->offset;
>  }
>
> -#ifdef TARGET_I386
>  static void rtc_coalesced_timer_update(RTCState *s)
>  {
>      if (s->irq_coalesced == 0) {
> @@ -126,6 +125,7 @@ static void rtc_coalesced_timer_update(RTCState *s)
>      }
>  }
>
> +#ifdef TARGET_I386
>  static void rtc_coalesced_timer(void *opaque)
>  {
>      RTCState *s = opaque;
> @@ -198,7 +198,6 @@ periodic_timer_update(RTCState *s, int64_t current_time, uint32_t old_period)
>              assert(lost_clock >= 0);
>          }
>
> -#ifdef TARGET_I386
>          /*
>           * recalculate the coalesced irqs for two reasons:
>           *    a) the lost_clock is more that a period, i,e. the timer
> @@ -233,9 +232,7 @@ periodic_timer_update(RTCState *s, int64_t current_time, uint32_t old_period)
>                            s->irq_coalesced, old_period, s->period);
>                  rtc_coalesced_timer_update(s);
>              }
> -        } else
> -#endif
> -        {
> +        } else {
>             /*
>               * no way to compensate the interrupt if LOST_TICK_POLICY_SLEW
>               * is not used, we should make the time progress anyway.
> @@ -250,9 +247,7 @@ periodic_timer_update(RTCState *s, int64_t current_time, uint32_t old_period)
>                                           RTC_CLOCK_RATE) + 1;
>          timer_mod(s->periodic_timer, s->next_periodic_time);
>      } else {
> -#ifdef TARGET_I386
>          s->irq_coalesced = 0;
> -#endif
>          timer_del(s->periodic_timer);
>      }
>  }
> @@ -841,13 +836,11 @@ static int rtc_post_load(void *opaque, int version_id)
>          }
>      }
>
> -#ifdef TARGET_I386
>      if (version_id >= 2) {
>          if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
>              rtc_coalesced_timer_update(s);
>          }
>      }
> -#endif
>      return 0;
>  }
>
> @@ -904,11 +897,10 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data)
>      rtc_set_date_from_host(ISA_DEVICE(s));
>      periodic_timer_update(s, now, 0);
>      check_update_timer(s);
> -#ifdef TARGET_I386
> +
>      if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
>          rtc_coalesced_timer_update(s);
>      }
> -#endif
>  }
>
>  /* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
> @@ -929,12 +921,10 @@ static void rtc_reset(void *opaque)
>
>      qemu_irq_lower(s->irq);
>
> -#ifdef TARGET_I386
>      if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
>          s->irq_coalesced = 0;
>          s->irq_reinject_on_ack_count = 0;		
>      }
> -#endif
>  }
>
>  static const MemoryRegionOps cmos_ops = {
>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v3 3/5] mc146818rtc: ensure LOST_TICK_POLICY_SLEW is only enabled on TARGET_I386
  2017-05-10  8:32   ` [Qemu-devel] " guangrong.xiao
  (?)
@ 2017-05-13 22:13   ` Philippe Mathieu-Daudé
  -1 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-05-13 22:13 UTC (permalink / raw)
  To: guangrong.xiao, pbonzini, mst, mtosatti
  Cc: Xiao Guangrong, yunfangtai, qemu-devel, kvm

On 05/10/2017 05:32 AM, guangrong.xiao@gmail.com wrote:
> From: Xiao Guangrong <xiaoguangrong@tencent.com>
>
> Any tick policy specified on other platforms rather on TARGET_I386
> will fall back to LOST_TICK_POLICY_DISCARD silently, this patch makes
> sure only TARGET_I386 can enable LOST_TICK_POLICY_SLEW
>
> After that, we can enable LOST_TICK_POLICY_SLEW in the common code
> which need not use '#ifdef TARGET_I386' to make these code be x86
> specific anymore
>
> Signed-off-by: Xiao Guangrong <xiaoguangrong@tencent.com>

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>  hw/timer/mc146818rtc.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
> index dac6744..9810bd5 100644
> --- a/hw/timer/mc146818rtc.c
> +++ b/hw/timer/mc146818rtc.c
> @@ -980,19 +980,19 @@ static void rtc_realizefn(DeviceState *dev, Error **errp)
>
>      rtc_set_date_from_host(isadev);
>
> -#ifdef TARGET_I386
>      switch (s->lost_tick_policy) {
> +#ifdef TARGET_I386
>      case LOST_TICK_POLICY_SLEW:
>          s->coalesced_timer =
>              timer_new_ns(rtc_clock, rtc_coalesced_timer, s);
>          break;
> +#endif
>      case LOST_TICK_POLICY_DISCARD:
>          break;
>      default:
>          error_setg(errp, "Invalid lost tick policy.");
>          return;
>      }
> -#endif
>
>      s->periodic_timer = timer_new_ns(rtc_clock, rtc_periodic_timer, s);
>      s->update_timer = timer_new_ns(rtc_clock, rtc_update_timer, s);
>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v3 0/5] mc146818rtc: fix Windows VM clock faster
  2017-05-10  9:53   ` [Qemu-devel] " Paolo Bonzini
@ 2017-05-18  2:26     ` Xiao Guangrong
  -1 siblings, 0 replies; 22+ messages in thread
From: Xiao Guangrong @ 2017-05-18  2:26 UTC (permalink / raw)
  To: Paolo Bonzini, mst, mtosatti; +Cc: qemu-devel, kvm, yunfangtai, Xiao Guangrong



On 05/10/2017 05:53 PM, Paolo Bonzini wrote:
> 
> 
> On 10/05/2017 10:32, guangrong.xiao@gmail.com wrote:
>> From: Xiao Guangrong <xiaoguangrong@tencent.com>
>>
>> Changelog in v3:
>> Thanks to Paolo's the elaborate review comments, this version
>> simplifies the logic of periodic_timer_update() significantly
>> that includes:
>> 1) introduce rtc_periodic_clock_ticks() that takes both regA and
>>     regB into account and returns the period clock
>> 2) count the clocks since last interrupt by always using current
>>     clock subtracts the clock when last interrupt happened
>> 3) improve the assert() logic
>>
>> Paolo, all you comments have been reflected in this version except
>> globally using s->period because in the current code, only x86 is
>> using s->period so that we should obey this rule to keep compatible
>> migration. I have added the comment to explain this suitable in the
>> code:
>>
>>              /*
>>               * as the old QEMUs only used s->period for the case that
>>               * LOST_TICK_POLICY_SLEW is used, in order to keep the
>>               * compatible migration, we obey the rule as old QEMUs.
>>               */
>>              s->period = period;
>> If anything i missed, please let me know. :)
> 
> Looks great.  Thanks for following up quickly on the reviews.
> 

Paolo, if it is okay to you, could you please consider to merge this
patchset? ;)

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v3 0/5] mc146818rtc: fix Windows VM clock faster
@ 2017-05-18  2:26     ` Xiao Guangrong
  0 siblings, 0 replies; 22+ messages in thread
From: Xiao Guangrong @ 2017-05-18  2:26 UTC (permalink / raw)
  To: Paolo Bonzini, mst, mtosatti; +Cc: qemu-devel, kvm, yunfangtai, Xiao Guangrong



On 05/10/2017 05:53 PM, Paolo Bonzini wrote:
> 
> 
> On 10/05/2017 10:32, guangrong.xiao@gmail.com wrote:
>> From: Xiao Guangrong <xiaoguangrong@tencent.com>
>>
>> Changelog in v3:
>> Thanks to Paolo's the elaborate review comments, this version
>> simplifies the logic of periodic_timer_update() significantly
>> that includes:
>> 1) introduce rtc_periodic_clock_ticks() that takes both regA and
>>     regB into account and returns the period clock
>> 2) count the clocks since last interrupt by always using current
>>     clock subtracts the clock when last interrupt happened
>> 3) improve the assert() logic
>>
>> Paolo, all you comments have been reflected in this version except
>> globally using s->period because in the current code, only x86 is
>> using s->period so that we should obey this rule to keep compatible
>> migration. I have added the comment to explain this suitable in the
>> code:
>>
>>              /*
>>               * as the old QEMUs only used s->period for the case that
>>               * LOST_TICK_POLICY_SLEW is used, in order to keep the
>>               * compatible migration, we obey the rule as old QEMUs.
>>               */
>>              s->period = period;
>> If anything i missed, please let me know. :)
> 
> Looks great.  Thanks for following up quickly on the reviews.
> 

Paolo, if it is okay to you, could you please consider to merge this
patchset? ;)

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v3 0/5] mc146818rtc: fix Windows VM clock faster
  2017-05-18  2:26     ` [Qemu-devel] " Xiao Guangrong
  (?)
@ 2017-05-18  7:52     ` Paolo Bonzini
  2017-05-18 13:38       ` Xiao Guangrong
  -1 siblings, 1 reply; 22+ messages in thread
From: Paolo Bonzini @ 2017-05-18  7:52 UTC (permalink / raw)
  To: Xiao Guangrong; +Cc: mst, mtosatti, Xiao Guangrong, yunfangtai, qemu-devel, kvm


> > Looks great.  Thanks for following up quickly on the reviews.
> 
> Paolo, if it is okay to you, could you please consider to merge this
> patchset? ;)

Yes, I've already queued it, but I don't have many patches so I am
delaying the pull request a bit (until at least I have time to test
vhost-user-scsi...).

In the meanwhile, it would be great if you prepared a qtest for the
problem of too many interrupts when the periodic timer is reprogrammed
continuously.

Thanks,

Paolo

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v3 0/5] mc146818rtc: fix Windows VM clock faster
  2017-05-18  7:52     ` Paolo Bonzini
@ 2017-05-18 13:38       ` Xiao Guangrong
  2017-05-18 13:51         ` Paolo Bonzini
  0 siblings, 1 reply; 22+ messages in thread
From: Xiao Guangrong @ 2017-05-18 13:38 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: mst, mtosatti, Xiao Guangrong, yunfangtai, qemu-devel, kvm



On 05/18/2017 03:52 PM, Paolo Bonzini wrote:
> 
>>> Looks great.  Thanks for following up quickly on the reviews.
>>
>> Paolo, if it is okay to you, could you please consider to merge this
>> patchset? ;)
> 
> Yes, I've already queued it, but I don't have many patches so I am
> delaying the pull request a bit (until at least I have time to test
> vhost-user-scsi...).
> 

Very glad to know it. I should check your git tree before raise this
kind of request next time. :)

> In the meanwhile, it would be great if you prepared a qtest for the
> problem of too many interrupts when the periodic timer is reprogrammed
> continuously.
> 

Sure, will do it, thanks for your suggestion.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v3 0/5] mc146818rtc: fix Windows VM clock faster
  2017-05-18 13:38       ` Xiao Guangrong
@ 2017-05-18 13:51         ` Paolo Bonzini
  0 siblings, 0 replies; 22+ messages in thread
From: Paolo Bonzini @ 2017-05-18 13:51 UTC (permalink / raw)
  To: Xiao Guangrong; +Cc: mst, mtosatti, Xiao Guangrong, yunfangtai, qemu-devel, kvm



On 18/05/2017 15:38, Xiao Guangrong wrote:
>>>
>>
>> Yes, I've already queued it, but I don't have many patches so I am
>> delaying the pull request a bit (until at least I have time to test
>> vhost-user-scsi...).
>>
> 
> Very glad to know it. I should check your git tree before raise this
> kind of request next time. :)

Well, I don't have a public staging git tree. :)

Paolo

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2017-05-18 13:52 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-10  8:32 [PATCH v3 0/5] mc146818rtc: fix Windows VM clock faster guangrong.xiao
2017-05-10  8:32 ` [Qemu-devel] " guangrong.xiao
2017-05-10  8:32 ` [PATCH v3 1/5] mc146818rtc: update periodic timer only if it is needed guangrong.xiao
2017-05-10  8:32   ` [Qemu-devel] " guangrong.xiao
2017-05-10  8:32 ` [PATCH v3 2/5] mc146818rtc: precisely count the clock for periodic timer guangrong.xiao
2017-05-10  8:32   ` [Qemu-devel] " guangrong.xiao
2017-05-10  8:32 ` [PATCH v3 3/5] mc146818rtc: ensure LOST_TICK_POLICY_SLEW is only enabled on TARGET_I386 guangrong.xiao
2017-05-10  8:32   ` [Qemu-devel] " guangrong.xiao
2017-05-13 22:13   ` Philippe Mathieu-Daudé
2017-05-10  8:32 ` [PATCH v3 4/5] mc146818rtc: drop unnecessary '#ifdef TARGET_I386' guangrong.xiao
2017-05-10  8:32   ` [Qemu-devel] " guangrong.xiao
2017-05-13 22:12   ` Philippe Mathieu-Daudé
2017-05-10  8:32 ` [PATCH v3 5/5] mc146818rtc: embrace all x86 specific code guangrong.xiao
2017-05-10  8:32   ` [Qemu-devel] " guangrong.xiao
2017-05-10  9:53 ` [PATCH v3 0/5] mc146818rtc: fix Windows VM clock faster Paolo Bonzini
2017-05-10  9:53   ` [Qemu-devel] " Paolo Bonzini
2017-05-18  2:26   ` Xiao Guangrong
2017-05-18  2:26     ` [Qemu-devel] " Xiao Guangrong
2017-05-18  7:52     ` Paolo Bonzini
2017-05-18 13:38       ` Xiao Guangrong
2017-05-18 13:51         ` Paolo Bonzini
2017-05-10 10:04 ` no-reply

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.