|
[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 |