aboutsummaryrefslogtreecommitdiff
path: root/hw/intc/apic_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/intc/apic_common.c')
-rw-r--r--hw/intc/apic_common.c52
1 files changed, 51 insertions, 1 deletions
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index 8d01c9c875..d78c885509 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -22,6 +22,7 @@
#include "qapi/error.h"
#include "qemu-common.h"
#include "cpu.h"
+#include "qapi/visitor.h"
#include "hw/i386/apic.h"
#include "hw/i386/apic_internal.h"
#include "trace.h"
@@ -39,6 +40,11 @@ void cpu_set_apic_base(DeviceState *dev, uint64_t val)
if (dev) {
APICCommonState *s = APIC_COMMON(dev);
APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
+ /* switching to x2APIC, reset possibly modified xAPIC ID */
+ if (!(s->apicbase & MSR_IA32_APICBASE_EXTD) &&
+ (val & MSR_IA32_APICBASE_EXTD)) {
+ s->id = s->initial_apic_id;
+ }
info->set_base(s, val);
}
}
@@ -242,6 +248,7 @@ static void apic_reset_common(DeviceState *dev)
bsp = s->apicbase & MSR_IA32_APICBASE_BSP;
s->apicbase = APIC_DEFAULT_ADDRESS | bsp | MSR_IA32_APICBASE_ENABLE;
+ s->id = s->initial_apic_id;
s->vapic_paddr = 0;
info->vapic_base_update(s);
@@ -428,7 +435,6 @@ static const VMStateDescription vmstate_apic_common = {
};
static Property apic_properties_common[] = {
- DEFINE_PROP_UINT8("id", APICCommonState, id, -1),
DEFINE_PROP_UINT8("version", APICCommonState, version, 0x14),
DEFINE_PROP_BIT("vapic", APICCommonState, vapic_control, VAPIC_ENABLE_BIT,
true),
@@ -437,6 +443,49 @@ static Property apic_properties_common[] = {
DEFINE_PROP_END_OF_LIST(),
};
+static void apic_common_get_id(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ APICCommonState *s = APIC_COMMON(obj);
+ int64_t value;
+
+ value = s->apicbase & MSR_IA32_APICBASE_EXTD ? s->initial_apic_id : s->id;
+ visit_type_int(v, name, &value, errp);
+}
+
+static void apic_common_set_id(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ APICCommonState *s = APIC_COMMON(obj);
+ DeviceState *dev = DEVICE(obj);
+ Error *local_err = NULL;
+ int64_t value;
+
+ if (dev->realized) {
+ qdev_prop_set_after_realize(dev, name, errp);
+ return;
+ }
+
+ visit_type_int(v, name, &value, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ s->initial_apic_id = value;
+ s->id = (uint8_t)value;
+}
+
+static void apic_common_initfn(Object *obj)
+{
+ APICCommonState *s = APIC_COMMON(obj);
+
+ s->id = s->initial_apic_id = -1;
+ object_property_add(obj, "id", "int",
+ apic_common_get_id,
+ apic_common_set_id, NULL, NULL, NULL);
+}
+
static void apic_common_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -456,6 +505,7 @@ static const TypeInfo apic_common_type = {
.name = TYPE_APIC_COMMON,
.parent = TYPE_DEVICE,
.instance_size = sizeof(APICCommonState),
+ .instance_init = apic_common_initfn,
.class_size = sizeof(APICCommonClass),
.class_init = apic_common_class_init,
.abstract = true,