[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 0/3] remove the periodic RTC update timer
From: |
Zhang, Yang Z |
Subject: |
[Qemu-devel] [PATCH 0/3] remove the periodic RTC update timer |
Date: |
Fri, 6 Jan 2012 07:37:17 +0000 |
Recently, I did some work for power optimization w/ KVM and I found
there was a periodic timer from qemu which stop the platform from staying deep
C state for a long period. After looking into the qemu code, there was a
periodic RTC update timer which is the culprit. In current RTC emulation logic,
it use a periodic timer(1 per second) to update RTC clock. Though 1 second is
long enough, when run more guests(for example 32, 64 ), you will see the
impaction is more than expected. In my case, I run 64 VMs and all of them are
idle. When enable the RTC update timer, the package C6 residency decreased
about 7% which means 2 watts in my case. So it would be better to stop the
periodic RTC update timer.
The following patch remove the periodic RTC update timer and use host
time with offset to calculate the RTC clock instead:
PATCH 1: use int64 when compare two time.
int32 only represent only 136 years when comparing two times based on
second. It would be better to use int64.
PATCH 2: use gettimeofday() instead of time().
Though the two functions both give the number of seconds since Epoch, I
found they will return different value on some rare occasion. For example, I
saw the getimeofday gives the number of seconds as A, but the time() function
still gives the (A-1). And this happen at the begin of every second. After
checking the implementation of the two functions in kernel, I found the time()
return the wall_time_sec directly and gettimeofday() will do a double check w/
TSC or HPET if available to get more accurate time. For example, if now is
99.999s, and an event happen which update wall_time_sec to 99s. After 0.001s,
userspace call gettimeofday() and time() at same time. For gettimeofday(), it
will read wall_time_sec and check w/ TSC. Then he will found now is 100s and
return 100s. But for time(), it return 99s directly even now is 100s.
In current QEMU, the timer logic is based on gettimeofday(), but the
qemu_get_timedate is using time() to get time. As mentioned before, this will
cause problems at some time.
For example:
The following code is to emulation a RTC alarm logic in the third patch:
static void rtc_alarm_interrupt(void *opaque)
{
qemu_get_timedate(&tm, s->offset);
/* check alarm */
if (((rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]) == tm.tm_sec) &&
rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]) == tm.tm_min) &&
rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]) == tm.tm_hour)
qemu_irq_raise(s->irq);
s->next_alarm_time += get_ticks_per_sec();
qemu_mod_timer(s->alarm_timer, s->next_alarm_time);
}
Suppose that now is 12:00:0, set an alarm at 12:00:10 and start a timer that
expired at 12:00:10. At the begin of 12:00:10, the timer(which base on
gettimeofday()) is fired and the callback function will call
qemu_get_timedate(based on time()) to get current time. As mentioned before,
the value returned by time() may slower than real time at the beginning of
every second. And the alarm will not be triggered. Then the guest will disable
the alarm and the alarm will have no chance to be fired.
PATCH 3: change the RTC update logic to use host time with offset to calculate
RTC clock.
There have no need to use two periodic timers to maintain an internal
timer for RTC clock update and alarm check. Instead, we calculate the real RTC
time by the host time with an offset. For alarm and updated-end interrupt, if
guest enabled it, then we setup a timer, or else, stop it.
best regards
yang
- [Qemu-devel] [PATCH 0/3] remove the periodic RTC update timer,
Zhang, Yang Z <=