aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/hvm/vioapic.c
diff options
context:
space:
mode:
authorSteven Hand <steven@xensource.com>2006-10-20 11:43:14 +0100
committerSteven Hand <steven@xensource.com>2006-10-20 11:43:14 +0100
commit94220a3f202fb12cfb4289b8ac5df7b2b2308113 (patch)
treebcdb3fdcde3cd36f0072d6f762f2931de30fb2b5 /xen/arch/x86/hvm/vioapic.c
parent28100f12bc1ccad55ef19521f2dd325fe012bcbe (diff)
downloadxen-94220a3f202fb12cfb4289b8ac5df7b2b2308113.tar.gz
xen-94220a3f202fb12cfb4289b8ac5df7b2b2308113.tar.bz2
xen-94220a3f202fb12cfb4289b8ac5df7b2b2308113.zip
Workaround for bigsmp APIC mode SMP linux guests - we cannot correctly deal
with timer interrupts being delivered to VCPUs other than 0, so spit a warning and then subsequently ignore the target. This fixes the recent issues Intel reported when booting SMP FC5 and FC6 kernels. Needs a better fix at some point. Signed-off-by: Steven Hand <steven@xensource.com>
Diffstat (limited to 'xen/arch/x86/hvm/vioapic.c')
-rw-r--r--xen/arch/x86/hvm/vioapic.c51
1 files changed, 34 insertions, 17 deletions
diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c
index daa812a6f3..e608b24fbf 100644
--- a/xen/arch/x86/hvm/vioapic.c
+++ b/xen/arch/x86/hvm/vioapic.c
@@ -42,6 +42,9 @@
/* HACK: Route IRQ0 only to VCPU0 to prevent time jumps. */
#define IRQ0_SPECIAL_ROUTING 1
+#ifdef IRQ0_SPECIAL_ROUTING
+static int redir_warning_done = 0;
+#endif
#if defined(__ia64__)
#define opt_hvm_debug_level opt_vmx_debug_level
@@ -155,6 +158,7 @@ static void hvm_vioapic_update_imr(struct hvm_vioapic *s, int index)
clear_bit(index, &s->imr);
}
+
static void hvm_vioapic_write_indirect(struct hvm_vioapic *s,
unsigned long addr,
unsigned long length,
@@ -179,21 +183,35 @@ static void hvm_vioapic_write_indirect(struct hvm_vioapic *s,
{
uint32_t redir_index = 0;
+ redir_index = (s->ioregsel - 0x10) >> 1;
+
HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "hvm_vioapic_write_indirect "
"change redir index %x val %lx\n",
redir_index, val);
- redir_index = (s->ioregsel - 0x10) >> 1;
-
if (redir_index >= 0 && redir_index < IOAPIC_NUM_PINS) {
uint64_t redir_content;
redir_content = s->redirtbl[redir_index].value;
- if (s->ioregsel & 0x1)
+ if (s->ioregsel & 0x1) {
+#ifdef IRQ0_SPECIAL_ROUTING
+ if ( !redir_warning_done && (redir_index == 0) &&
+ ((val >> 24) != 0) ) {
+ /*
+ * Cannot yet handle delivering PIT interrupts to
+ * any VCPU != 0. Needs proper fixing, but for now
+ * simply spit a warning that we're going to ignore
+ * the target in practice & always deliver to VCPU 0
+ */
+ printk("IO-APIC: PIT (IRQ0) redirect to VCPU %lx "
+ "will be ignored.\n", val >> 24);
+ redir_warning_done = 1;
+ }
+#endif
redir_content = (((uint64_t)val & 0xffffffff) << 32) |
(redir_content & 0xffffffff);
- else
+ } else
redir_content = ((redir_content >> 32) << 32) |
(val & 0xffffffff);
s->redirtbl[redir_index].value = redir_content;
@@ -409,6 +427,8 @@ static void ioapic_deliver(hvm_vioapic_t *s, int irqno)
uint8_t vector = s->redirtbl[irqno].RedirForm.vector;
uint8_t trig_mode = s->redirtbl[irqno].RedirForm.trigmod;
uint32_t deliver_bitmask;
+ struct vlapic *target;
+
HVM_DBG_LOG(DBG_LEVEL_IOAPIC,
"dest %x dest_mode %x delivery_mode %x vector %x trig_mode %x\n",
@@ -427,9 +447,8 @@ static void ioapic_deliver(hvm_vioapic_t *s, int irqno)
switch (delivery_mode) {
case dest_LowestPrio:
{
- struct vlapic* target;
-
#ifdef IRQ0_SPECIAL_ROUTING
+ /* Force round-robin to pick VCPU 0 */
if (irqno == 0)
target = s->lapic_info[0];
else
@@ -450,19 +469,17 @@ static void ioapic_deliver(hvm_vioapic_t *s, int irqno)
{
uint8_t bit;
for (bit = 0; bit < s->lapic_count; bit++) {
- if (deliver_bitmask & (1 << bit)) {
+ if ( !(deliver_bitmask & (1 << bit)) )
+ continue;
#ifdef IRQ0_SPECIAL_ROUTING
- if ( (irqno == 0) && (bit !=0) )
- {
- printk("PIT irq to bit %x\n", bit);
- domain_crash_synchronous();
- }
+ /* Do not deliver timer interrupts to VCPU != 0 */
+ if ( (irqno == 0) && (bit !=0 ) )
+ target = s->lapic_info[0];
+ else
#endif
- if (s->lapic_info[bit]) {
- ioapic_inj_irq(s, s->lapic_info[bit],
- vector, trig_mode, delivery_mode);
- }
- }
+ target = s->lapic_info[bit];
+ if (target)
+ ioapic_inj_irq(s, target, vector, trig_mode, delivery_mode);
}
break;
}