qemu-devel
[Top][All Lists]
Advanced

[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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]