@@ -381,6 +381,21 @@ ioapic_fix_level_trigger_unsupported(uint64_t *entry)
}
}
+static inline void
+ioapic_fix_smi_unsupported(uint64_t *entry)
+{
+ if ((*entry & IOAPIC_LVT_DELIV_MODE) ==
+ IOAPIC_DM_PMI << IOAPIC_LVT_DELIV_MODE_SHIFT) {
+ /*
+ * ignore a request for delivery mode of lowest SMI
+ */
+ warn_report_once("attempting to set delivery mode to SMI"
+ "which is not supported");
+ *entry &= ~IOAPIC_LVT_DELIV_MODE;
+ *entry |= IOAPIC_DM_FIXED << IOAPIC_LVT_DELIV_MODE_SHIFT;
+ }
+}
+
static void
ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val,
unsigned int size)
@@ -424,6 +439,9 @@ ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val,
if (s->level_trigger_unsupported) {
ioapic_fix_level_trigger_unsupported(&s->ioredtbl[index]);
}
+ if (s->smi_unsupported) {
+ ioapic_fix_smi_unsupported(&s->ioredtbl[index]);
+ }
ioapic_fix_edge_remote_irr(&s->ioredtbl[index]);
ioapic_service(s);
}
@@ -168,12 +168,32 @@ static void ioapic_common_set_level_trigger_unsupported(Object *obj, bool value,
s->level_trigger_unsupported = value;
}
+static bool ioapic_common_get_smi_unsupported(Object *obj, Error **errp)
+{
+ IOAPICCommonState *s = IOAPIC_COMMON(obj);
+ return s->smi_unsupported;
+}
+
+static void ioapic_common_set_smi_unsupported(Object *obj, bool value,
+ Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ IOAPICCommonState *s = IOAPIC_COMMON(obj);
+ /* only disabling before realize is allowed */
+ assert(!dev->realized);
+ assert(!s->smi_unsupported);
+ s->smi_unsupported = value;
+}
+
static void ioapic_common_init(Object *obj)
{
object_property_add_bool(obj, "level_trigger_unsupported",
ioapic_common_get_level_trigger_unsupported,
ioapic_common_set_level_trigger_unsupported);
+ object_property_add_bool(obj, "smi_unsupported",
+ ioapic_common_get_smi_unsupported,
+ ioapic_common_set_smi_unsupported);
}
static void ioapic_common_realize(DeviceState *dev, Error **errp)
@@ -104,6 +104,7 @@ struct IOAPICCommonState {
uint64_t ioredtbl[IOAPIC_NUM_PINS];
Notifier machine_done;
bool level_trigger_unsupported;
+ bool smi_unsupported;
uint8_t version;
uint64_t irq_count[IOAPIC_NUM_PINS];
int irq_level[IOAPIC_NUM_PINS];