@samitouri / QOSamiQemu / commits / 2bb73a332c

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