summary refs log tree commit diff stats
path: root/hw/intc/apic.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-07-20 21:32:56 +0100
committerPeter Maydell <peter.maydell@linaro.org>2016-07-20 21:32:56 +0100
commite66b05e9ca471715388182613217503160ed7a4d (patch)
tree42d50d35e80d75e3d6494c1fef25b793c2afc6bd /hw/intc/apic.c
parent3b55fbdcb048bf82e82c29b555d0918b83fc40a5 (diff)
parent8fe6374e8e0c8dacb85e9e97897291541dd61be6 (diff)
downloadfocaccia-qemu-e66b05e9ca471715388182613217503160ed7a4d.tar.gz
focaccia-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;