> On 26/07/2017 03:28, peng.h...@zte.com.cn wrote:
> > > > > > 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. > A vmexit to the RTC timer should be around 10.000 clock cycles, which is > less than a microsecond. I use perf tools getting data(windows VM) IO Port Access Samples Samples% Time% Min Time Max Time Avg time 0x71: PIN 126 56.76% 32.62% 1us 2us 1.83us ( +- 0.62% ) 0x70: POUT 63 28.38% 51.56% 4us 15us 5.78us ( +- 3.12% ) But I'm not sure it is accurate. > > 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.. > Does Windows do this test when Hyper-V englightenments are enabled > (especially hv-relaxed)? yes ,I enable hv-relaxed.in my windows VM.But I'm not sure the interconnection between them. > It seems to be a Windows issue to me. I'm not sure adding hacks to the > device model is the right thing to do, especially because I don't > understand why your fix worked. 1. guest closes periodic timer,from then on rtc don't send interrupt anymore and no rtc handler can run to read RTC_REG_C(this read set RTC_REG_C = 0, clear REG_C_UF) 2. update timer expires, rtc_update_timer clears REG_A_UIP, and set REG_C_UF 3. because REG_C_UF is setted, check_update_timer sets update_timer's expire time to next_alarm_time, which is over ten hours 4. guest checks that REG_A_UIP changes from 0 to 1 in a infinte loop (we don't know why windows kernel does this) by read RTC_REG_A 5. update_in_progress called from cmos_ioport_read 6. beause update_timer is switched to alarm timer, which has a too big expire time to satisfes the fowllowing condition: if (qemu_clock_get_ns(rtc_clock) >= (next_update_time - UIP_HOLD_LENGTH)) { s->cmos_data[RTC_REG_A] |= REG_A_UIP return 1 } 7. update_in_progress's second condition don't satisfes: if ((guest_nsec % NANOSECONDS_PER_SECOND) >= (NANOSECONDS_PER_SECOND - UIP_HOLD_LENGTH)) { return 1 } because when many vms startup, inb instruction wastes much more time than normal situation and guest_nsec % NANOSECONDS_PER_SECOND is nearly < NANOSECONDS_PER_SECOND - UIP_HOLD_LENGTH always. 8. finally, REG_A_UIP is always cleared, REG_C_UF is always set, update_timer is always alarm timer, guest is always checking REG_A_UIP, and guest hung up.