hw/intc/apic: move checks to realize()
apic_common_set_id() dereferences s->cpu to check for x2APIC support when the APIC ID is >= 255. On a standalone APIC object that has not been attached to a CPU, s->cpu is NULL, causing a segfault. To solve this, move validation during realize(). Fixes: b5ee0468e9d2 ("apic: add support for x2APIC mode") Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Marc-André Lureau committed
Apr 25, 2026 at 01:00 UTC
2bb73a332ccb9a506b3f775fbb9881811178ec62
2 files changed
+14
-15
hw/intc/apic_common.c
+13
-10
@@ -257,6 +257,19 @@ static void apic_common_realize(DeviceState *dev, Error **errp)
257
static DeviceState *vapic;
258
uint32_t instance_id = s->initial_apic_id;
259
260
+ if (!s->cpu) {
261
+ error_setg(errp, "APIC is not attached to a CPU");
262
+ return;
263
+ }
264
+
265
+ if (s->initial_apic_id >= 255 &&
266
+ !cpu_has_x2apic_feature(&s->cpu->env)) {
267
+ error_setg(errp, "APIC ID %d requires x2APIC feature in CPU",
268
+ s->initial_apic_id);
269
+ error_append_hint(errp, "Try x2apic=on in -cpu.\n");
270
+ return;
271
+ }
272
+
273
/* Normally initial APIC ID should be no more than hundreds */
274
assert(instance_id != VMSTATE_INSTANCE_ID_ANY);
275
@@ -410,7 +423,6 @@ static void apic_common_set_id(Object *obj, Visitor *v, const char *name,
423
APICCommonState *s = APIC_COMMON(obj);
424
DeviceState *dev = DEVICE(obj);
425
uint32_t value;
413
- Error *local_err = NULL;
426
427
if (dev->realized) {
428
qdev_prop_set_after_realize(dev, name, errp);
@@ -421,15 +433,6 @@ static void apic_common_set_id(Object *obj, Visitor *v, const char *name,
433
return;
434
}
435
424
- if (value >= 255 && !cpu_has_x2apic_feature(&s->cpu->env)) {
425
- error_setg(&local_err,
426
- "APIC ID %d requires x2APIC feature in CPU",
427
- value);
428
- error_append_hint(&local_err, "Try x2apic=on in -cpu.\n");
429
- error_propagate(errp, local_err);
430
- return;
431
- }
432
-
436
s->initial_apic_id = value;
437
s->id = (uint8_t)value;
438
}
target/i386/cpu-apic.c
+1
-5
@@ -56,11 +56,7 @@ void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
56
cpu->apic_state->cpu = cpu;
57
cpu->apic_state->apicbase = APIC_DEFAULT_ADDRESS | MSR_IA32_APICBASE_ENABLE;
58
59
- /*
60
- * apic_common_set_id needs to check if the CPU has x2APIC
61
- * feature in case APIC ID >= 255, so we need to set cpu->apic_state->cpu
62
- * before setting APIC ID
63
- */
59
+ /* cpu must be set before realize, which validates the APIC ID */
60
qdev_prop_set_uint32(DEVICE(cpu->apic_state), "id", cpu->apic_id);
61
}
62