summaryrefslogtreecommitdiffstats
path: root/hw/intc/apic.c
diff options
context:
space:
mode:
authorPeter Maydell2016-07-20 22:32:56 +0200
committerPeter Maydell2016-07-20 22:32:56 +0200
commite66b05e9ca471715388182613217503160ed7a4d (patch)
tree42d50d35e80d75e3d6494c1fef25b793c2afc6bd /hw/intc/apic.c
parentMerge remote-tracking branch 'remotes/cohuck/tags/s390x-20160720' into staging (diff)
parentpc: Make device_del CPU work for x86 CPUs (diff)
downloadqemu-e66b05e9ca471715388182613217503160ed7a4d.tar.gz
qemu-e66b05e9ca471715388182613217503160ed7a4d.tar.xz
qemu-e66b05e9ca471715388182613217503160ed7a4d.zip
Merge remote-tracking branch 'remotes/ehabkost/tags/x86-pull-request' into staging
x86 queue, 2016-07-20 # gpg: Signature made Wed 20 Jul 2016 16:07:38 BST # gpg: using RSA key 0x2807936F984DC5A6 # gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>" # Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF D1AA 2807 936F 984D C5A6 * remotes/ehabkost/tags/x86-pull-request: (28 commits) pc: Make device_del CPU work for x86 CPUs target-i386: Add x86_cpu_unrealizefn() apic: Use apic_id as apic's migration instance_id (kvm)apic: Add unrealize callbacks apic: kvm-apic: Fix crash due to access to freed memory region apic: Drop APICCommonState.idx and use APIC ID as index in local_apics[] apic: move MAX_APICS check to 'apic' class pc: Implement query-hotpluggable-cpus callback pc: cpu: Allow device_add to be used with x86 cpu pc: Enforce adding CPUs contiguously and removing them in opposite order pc: Forbid BSP removal pc: Register created initial and hotpluged CPUs in one place pc_cpu_plug() pc: Delay setting number of boot CPUs to machine_done time pc: Set APIC ID based on socket/core/thread ids if it's not been set yet target-i386: Fix apic object leak when CPU is deleted target-i386: cpu: Do not ignore error and fix apic parent target-i386: Add support for UMIP and RDPID CPUID bits target-i386: Add socket/core/thread properties to X86CPU target-i386: Replace custom apic-id setter/getter with static property pc: cpu: Consolidate apic-id validity checks in pc_cpu_pre_plug() ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/intc/apic.c')
-rw-r--r--hw/intc/apic.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index e1ab9354c6..45887d99c0 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -28,7 +28,9 @@
#include "trace.h"
#include "hw/i386/pc.h"
#include "hw/i386/apic-msidef.h"
+#include "qapi/error.h"
+#define MAX_APICS 255
#define MAX_APIC_WORDS 8
#define SYNC_FROM_VAPIC 0x1
@@ -419,7 +421,7 @@ static int apic_find_dest(uint8_t dest)
int i;
if (apic && apic->id == dest)
- return dest; /* shortcut in case apic->id == apic->idx */
+ return dest; /* shortcut in case apic->id == local_apics[dest]->id */
for (i = 0; i < MAX_APICS; i++) {
apic = local_apics[i];
@@ -502,14 +504,14 @@ static void apic_deliver(DeviceState *dev, uint8_t dest, uint8_t dest_mode,
break;
case 1:
memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask));
- apic_set_bit(deliver_bitmask, s->idx);
+ apic_set_bit(deliver_bitmask, s->id);
break;
case 2:
memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
break;
case 3:
memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
- apic_reset_bit(deliver_bitmask, s->idx);
+ apic_reset_bit(deliver_bitmask, s->id);
break;
}
@@ -870,20 +872,36 @@ static void apic_realize(DeviceState *dev, Error **errp)
{
APICCommonState *s = APIC_COMMON(dev);
+ if (s->id >= MAX_APICS) {
+ error_setg(errp, "%s initialization failed. APIC ID %d is invalid",
+ object_get_typename(OBJECT(dev)), s->id);
+ return;
+ }
+
memory_region_init_io(&s->io_memory, OBJECT(s), &apic_io_ops, s, "apic-msi",
APIC_SPACE_SIZE);
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, apic_timer, s);
- local_apics[s->idx] = s;
+ local_apics[s->id] = s;
msi_nonbroken = true;
}
+static void apic_unrealize(DeviceState *dev, Error **errp)
+{
+ APICCommonState *s = APIC_COMMON(dev);
+
+ timer_del(s->timer);
+ timer_free(s->timer);
+ local_apics[s->id] = NULL;
+}
+
static void apic_class_init(ObjectClass *klass, void *data)
{
APICCommonClass *k = APIC_COMMON_CLASS(klass);
k->realize = apic_realize;
+ k->unrealize = apic_unrealize;
k->set_base = apic_set_base;
k->set_tpr = apic_set_tpr;
k->get_tpr = apic_get_tpr;