[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [BUG] panic: "IO-APIC + timer doesn't work" - several people have reproduced
On 17.03.2020 15:08, Jan Beulich wrote: >On 17.03.2020 15:08, Jan Beulich wrote: >> On 17.03.2020 14:48, Jason Andryuk wrote: >>> I got it to boot past "IO-APIC + timer doesn't work". I programmed >>> the HPET to provide a periodic timer in hpet_resume() on T0. When I >>> actually got it programmed properly, it worked to increment >>> pit0_ticks. I also made timer_interrupt() unconditionally >>> pit0_ticks++ though that may not matter. >> >> Hmm, at the first glance I would imply the system gets handed to Xen >> with a HPET state that we don't (and probably also shouldn't) expect. >> Could you provide HPET_CFG as well as all HPET_Tn_CFG and >> HPET_Tn_ROUTE values as hpet_resume() finds them before doing any >> adjustments to them? What are the components / parties involved in >> getting Xen loaded and started? > >Of course much depends on what exactly you mean you've done to >the HPET by saying "I programmed the HPET to provide ...". Below is the diff. It was messier and I tidied it up some. It's mainly the change to hpet_resume() to mimic Linux's legacy HPET setup on T0. It turns on HPET_CFG_LEGACY to ensure the timer interrupt is running. And it also includes the printing of the initial HPET config: HPET_CFG 00000001 HPET_T0_CFG 00008030 HPET_T0_ROUTE 0000016c HPET_T1_CFG 00008000 HPET_T1_ROUTE 00000000 HPET_T2_CFG 00008000 HPET_T2_ROUTE 00000000 HPET_T3_CFG 00008000 HPET_T3_ROUTE 00000000 HPET_T4_CFG 0000c000 HPET_T4_ROUTE 00000000 HPET_T5_CFG 0000c000 HPET_T5_ROUTE 00000000 HPET_T6_CFG 0000c000 HPET_T6_ROUTE 00000000 HPET_T7_CFG 0000c000 HPET_T7_ROUTE 00000000 Other changes are to try to prevent Xen from clobbering T0 as a periodic timer. I had some printks and didn't see Xen call any of them though. Regards, Jason diff --git a/xen/arch/x86/hpet.c b/xen/arch/x86/hpet.c index 86929b9ba1..f39aafda7d 100644 --- a/xen/arch/x86/hpet.c +++ b/xen/arch/x86/hpet.c @@ -585,16 +585,27 @@ void __init hpet_broadcast_init(void) pv_rtc_handler = handle_rtc_once; } + printk(XENLOG_INFO "%s cfg %d\n", __func__, cfg); hpet_write32(cfg, HPET_CFG); for ( i = 0; i < n; i++ ) { - if ( i == 0 && (cfg & HPET_CFG_LEGACY) ) + printk(XENLOG_INFO "hpet cfg %d legacy %d\n", i, cfg & HPET_CFG_LEGACY); + if ( i == 1 && (cfg & HPET_CFG_LEGACY) ) { /* set HPET T0 as oneshot */ - cfg = hpet_read32(HPET_Tn_CFG(0)); + cfg = hpet_read32(HPET_Tn_CFG(1)); cfg &= ~(HPET_TN_LEVEL | HPET_TN_PERIODIC); cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; + hpet_write32(cfg, HPET_Tn_CFG(1)); + } + + if ( i == 0 && (cfg & HPET_CFG_LEGACY) ) + { + /* set HPET T0 as periodic */ + cfg = hpet_read32(HPET_Tn_CFG(0)); + cfg |= (HPET_TN_LEVEL | HPET_TN_PERIODIC); + cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; hpet_write32(cfg, HPET_Tn_CFG(0)); } @@ -645,6 +656,7 @@ void hpet_broadcast_resume(void) n = 1; } + printk(XENLOG_INFO "%s cfg %d\n", __func__, cfg); hpet_write32(cfg, HPET_CFG); for ( i = 0; i < n; i++ ) @@ -652,6 +664,7 @@ void hpet_broadcast_resume(void) if ( hpet_events[i].msi.irq >= 0 ) __hpet_setup_msi_irq(irq_to_desc(hpet_events[i].msi.irq)); + if (i != 0) { /* set HPET Tn as oneshot */ cfg = hpet_read32(HPET_Tn_CFG(hpet_events[i].idx)); cfg &= ~(HPET_TN_LEVEL | HPET_TN_PERIODIC); @@ -659,6 +672,7 @@ void hpet_broadcast_resume(void) if ( !(hpet_events[i].flags & HPET_EVT_LEGACY) ) cfg |= HPET_TN_FSB; hpet_write32(cfg, HPET_Tn_CFG(hpet_events[i].idx)); + } hpet_events[i].next_event = STIME_MAX; } @@ -684,6 +698,7 @@ void hpet_disable_legacy_broadcast(void) /* Stop HPET legacy interrupts */ cfg = hpet_read32(HPET_CFG); cfg &= ~HPET_CFG_LEGACY; + printk(XENLOG_INFO "%s cfg %d\n", __func__, cfg); hpet_write32(cfg, HPET_CFG); spin_unlock_irqrestore(&hpet_events->lock, flags); @@ -759,6 +774,7 @@ int hpet_legacy_irq_tick(void) (hpet_events->flags & (HPET_EVT_DISABLE|HPET_EVT_LEGACY)) != HPET_EVT_LEGACY ) return 0; + hpet_events->event_handler(hpet_events); return 1; } @@ -804,6 +820,8 @@ u64 __init hpet_setup(void) return hpet_rate + (last * 2 > hpet_period); } +#include <asm/delay.h> + void hpet_resume(u32 *boot_cfg) { static u32 system_reset_latch; @@ -815,6 +833,7 @@ void hpet_resume(u32 *boot_cfg) system_reset_latch = system_reset_counter; cfg = hpet_read32(HPET_CFG); + printk(XENLOG_INFO "%s HPET_CFG %08x\n", __func__, cfg); if ( boot_cfg ) *boot_cfg = cfg; cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY); @@ -825,13 +844,18 @@ void hpet_resume(u32 *boot_cfg) cfg); cfg = 0; } + printk(XENLOG_INFO "%s cfg %d\n", __func__, cfg); hpet_write32(cfg, HPET_CFG); hpet_id = hpet_read32(HPET_ID); last = (hpet_id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT; for ( i = 0; i <= last; ++i ) { + u32 tmp; cfg = hpet_read32(HPET_Tn_CFG(i)); + printk(XENLOG_INFO "%s HPET_T%d_CFG %08x\n", __func__, i, cfg); + tmp = hpet_read32(HPET_Tn_ROUTE(i)); + printk(XENLOG_INFO "%s HPET_T%d_ROUTE %08x\n", __func__, i, tmp); if ( boot_cfg ) boot_cfg[i + 1] = cfg; cfg &= ~HPET_TN_ENABLE; @@ -842,11 +866,34 @@ void hpet_resume(u32 *boot_cfg) cfg & HPET_TN_RESERVED, i); cfg &= ~HPET_TN_RESERVED; } + if (i == 0) { + cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL | + HPET_TN_32BIT; + } hpet_write32(cfg, HPET_Tn_CFG(i)); + if (i == 0) { +#define NSEC_PER_SEC 1000000000L + uint64_t delta; + unsigned int now; + unsigned int cmp; + u64 hpet_rate = hpet_setup(); + uint32_t mult = div_sc((unsigned long)hpet_rate, + 1000000000ul, 32); + uint32_t shift = 32; + printk(XENLOG_INFO "hpet mult %d shift %d\n", mult, shift); + delta = ((uint64_t)(NSEC_PER_SEC / HZ)) * mult; + delta >>= shift; + now = hpet_read32(HPET_COUNTER); + cmp = now + (unsigned int)delta; + hpet_write32(cmp, HPET_Tn_CMP(i)); + udelay(1); + hpet_write32(delta, HPET_Tn_CMP(i)); + } } cfg = hpet_read32(HPET_CFG); - cfg |= HPET_CFG_ENABLE; + cfg |= HPET_CFG_ENABLE | HPET_CFG_LEGACY; + printk(XENLOG_INFO "%s cfg %d\n", __func__, cfg); hpet_write32(cfg, HPET_CFG); } @@ -862,6 +909,7 @@ void hpet_disable(void) return; } + printk(XENLOG_INFO "%s cfg %d\n", __func__, *hpet_boot_cfg); hpet_write32(*hpet_boot_cfg & ~HPET_CFG_ENABLE, HPET_CFG); id = hpet_read32(HPET_ID); @@ -869,5 +917,6 @@ void hpet_disable(void) hpet_write32(hpet_boot_cfg[i + 1], HPET_Tn_CFG(i)); if ( *hpet_boot_cfg & HPET_CFG_ENABLE ) + printk(XENLOG_INFO "%s cfg %d\n", __func__, *hpet_boot_cfg); hpet_write32(*hpet_boot_cfg, HPET_CFG); } _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |