--- a/xen/arch/x86/hvm/rtc.c +++ b/xen/arch/x86/hvm/rtc.c @@ -50,6 +50,23 @@ static void rtc_set_time(RTCState *s); static inline int from_bcd(RTCState *s, int a); static inline int convert_hour(RTCState *s, int hour); +#include //temp +#define LOGIDX_MASK 0xf//temp +static struct {//temp + s_time_t time; + void*caller; +} log[LOGIDX_MASK + 1]; +static unsigned logidx;//temp +static void pt_off(int line) {//temp + unsigned i, idx = logidx; + printk("pt off #%d @%"PRIx64"\n", line, NOW()); + for(i = idx; i <= idx + LOGIDX_MASK; ++i) { + if(!log[i & LOGIDX_MASK].caller) continue; + printk("pt irq @%"PRIx64, log[i & LOGIDX_MASK].time); + print_symbol(" (%s)\n", (unsigned long)log[i & LOGIDX_MASK].caller); + } +} + static void rtc_update_irq(RTCState *s) { struct domain *d = vrtc_domain(s); @@ -68,6 +85,7 @@ static void rtc_update_irq(RTCState *s) hvm_isa_irq_deassert(d, RTC_IRQ); if ( irqf ) +log[logidx & LOGIDX_MASK].time = NOW(), log[logidx++ & LOGIDX_MASK].caller = __builtin_return_address(0),//temp hvm_isa_irq_assert(d, RTC_IRQ); } @@ -81,12 +99,14 @@ void rtc_periodic_interrupt(void *opaque s->hw.cmos_data[RTC_REG_C] |= RTC_PF; rtc_update_irq(s); } - else if ( ++(s->pt_dead_ticks) >= 10 ) + else if ( ++(s->pt_dead_ticks) >= 250 ) { /* VM is ignoring its RTC; no point in running the timer */ +pt_off(__LINE__);//temp destroy_periodic_time(&s->pt); s->pt_code = 0; } +else if(s->pt_code) rtc_update_irq(s);//todo? spin_unlock(&s->lock); } @@ -114,6 +134,7 @@ static void rtc_timer_update(RTCState *s { if ( period_code != s->pt_code ) { +printk("pt on: %d @%"PRIx64"\n", period_code, NOW());//temp s->pt_code = period_code; period = 1 << (period_code - 1); /* period in 32 Khz cycles */ period = DIV_ROUND(period * 1000000000ULL, 32768); /* in ns */ @@ -125,6 +146,7 @@ static void rtc_timer_update(RTCState *s } /* fall through */ default: +pt_off(__LINE__);//temp destroy_periodic_time(&s->pt); s->pt_code = 0; break; @@ -451,6 +473,9 @@ static int rtc_ioport_write(void *opaque rtc_timer_update(s); break; case RTC_REG_B: +printk("B=%02x [A:%02x B:%02x C:%02x pt:%d/%d] @%"PRIx64"\n",//temp + data, s->hw.cmos_data[RTC_REG_A], orig, s->hw.cmos_data[RTC_REG_C],//temp + s->pt_code, s->pt_dead_ticks, NOW());//temp if ( data & RTC_SET ) { /* set mode: reset UIP mode */ @@ -474,6 +499,7 @@ static int rtc_ioport_write(void *opaque */ rtc_update_irq(s); s->hw.cmos_data[RTC_REG_B] = data; +if((data & RTC_PIE) && !(orig & RTC_PIE)) rtc_timer_update(s);//todo? if ( (data ^ orig) & RTC_SET ) check_update_timer(s); if ( (data ^ orig) & (RTC_24H | RTC_DM_BINARY | RTC_SET) ) @@ -629,6 +655,7 @@ static uint32_t rtc_ioport_read(RTCState case RTC_REG_C: ret = s->hw.cmos_data[s->hw.cmos_index]; s->hw.cmos_data[RTC_REG_C] = 0x00; +printk("C=%02x pt=%d/%d @%"PRIx64"\n", ret, s->pt_code, s->pt_dead_ticks, NOW());//temp rtc_update_irq(s); check_update_timer(s); alarm_timer_update(s); @@ -730,6 +757,8 @@ void rtc_reset(struct domain *d) destroy_periodic_time(&s->pt); s->pt_code = 0; s->pt.source = PTSRC_isa; +s->hw.cmos_data[RTC_REG_B] &= ~(RTC_PIE|RTC_AIE|RTC_UIE);//todo? +s->hw.cmos_data[RTC_REG_C] = 0;//todo? } void rtc_init(struct domain *d)