>On 25/07/2017 11:29, peng.h...@zte.com.cn wrote: >>>On 25/07/2017 06:14, peng.h...@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, >> >> I don't think it can works.
>Have you tested it? >> REG_C_UF is totally cleared by periodic timer in original code. >> after periodic timer stoped, the REG_C_UF is never cleared. >Your patch cleared REG_C_UF, but you have not said why the actual >hardware would clear REG_C_UF (it wouldn't). >> rtc_update_timer has cleared REG_A_UIP,I think the patch does nothing. >> >> I reproduce the bug when many windows VMs reboot and it is about the >> method of windows kernel accessing rtc . >> >> so i don't know how to write the testcase. >First of all you have to describe the exact sequence of register >accesses that causes the problem. I can help you writing the testcase, >but your changes to the device model must reflect the actual behavior of >the hardware. when the problem happens , windows kernel is checking whether REG_A_UIP is changing after periodic timer has stopped. windows kernel access REG_A according to INB instrunction and it will spend several microseconds because of VM_EXIT. update timer has changed to a long expire time (as alarm timer)on the one hand. on the other hand 244 microseconds in one second is too short to hit the region. windows kernel may check REG_A_UIP when considering RTC something wrong. many windows VM reboot at the same time and rtc periodic timer may delay badly.. >Paolo