summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2013-05-02 10:57:01 -0500
committerAnthony Liguori <aliguori@us.ibm.com>2013-05-02 10:57:01 -0500
commit8ca27ce2e1150486ea2db4116a03706b28294f16 (patch)
tree39a42b9ba7a4b1fc8db8c098fd24b08f39fee6ed /hw
parent0db4c324a8c6f2b1b8a118146f9b0fc8c4210719 (diff)
parente7bdf659c16e1cefd61f53648503d8c060668d6b (diff)
downloadqemu-8ca27ce2e1150486ea2db4116a03706b28294f16.tar.gz
Merge remote-tracking branch 'afaerber/qom-cpu' into staging
# By Igor Mammedov (21) and others # Via Andreas Färber * afaerber/qom-cpu: (29 commits) Drop redundant resume_all_vcpus() from main() cpus: Fix pausing TCG CPUs while in vCPU thread target-i386: Replace cpuid_*features fields with a feature word array target-i386: Break CPUID feature definition lines target-i386/kvm.c: Code formatting changes target-i386: Group together level, xlevel, xlevel2 fields pc: Implement QEMUMachine::hot_add_cpu hook QMP: Add cpu-add command Add hot_add_cpu hook to QEMUMachine target-i386: Move APIC to ICC bus target-i386: Attach ICC bus to CPU on its creation target-i386: Introduce ICC bus/device/bridge cpu: Move cpu_write_elfXX_note() functions to CPUState kvmvapic: Make dependency on sysbus.h explicit target-i386: Replace MSI_SPACE_SIZE with APIC_SPACE_SIZE target-i386: Do not allow to set apic-id once CPU is realized target-i386: Introduce apic-id CPU property target-i386: Introduce feat2prop() for CPU properties acpi_piix4: Add infrastructure to send CPU hot-plug GPE to guest cpu: Add helper cpu_exists(), to check if CPU with specified id exists ...
Diffstat (limited to 'hw')
-rw-r--r--hw/acpi/piix4.c90
-rw-r--r--hw/cpu/Makefile.objs1
-rw-r--r--hw/cpu/icc_bus.c119
-rw-r--r--hw/i386/kvm/apic.c2
-rw-r--r--hw/i386/kvm/clock.c2
-rw-r--r--hw/i386/kvmvapic.c1
-rw-r--r--hw/i386/pc.c88
-rw-r--r--hw/i386/pc_piix.c10
-rw-r--r--hw/i386/pc_q35.c10
-rw-r--r--hw/intc/apic.c2
-rw-r--r--hw/intc/apic_common.c18
-rw-r--r--hw/timer/mc146818rtc.c7
-rw-r--r--hw/xen/xen_apic.c2
13 files changed, 336 insertions, 16 deletions
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 88386d7ea7..c4af1ccbb0 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -48,19 +48,28 @@
#define PCI_EJ_BASE 0xae08
#define PCI_RMV_BASE 0xae0c
+#define PIIX4_PROC_BASE 0xaf00
+#define PIIX4_PROC_LEN 32
+
#define PIIX4_PCI_HOTPLUG_STATUS 2
+#define PIIX4_CPU_HOTPLUG_STATUS 4
struct pci_status {
uint32_t up; /* deprecated, maintained for migration compatibility */
uint32_t down;
};
+typedef struct CPUStatus {
+ uint8_t sts[PIIX4_PROC_LEN];
+} CPUStatus;
+
typedef struct PIIX4PMState {
PCIDevice dev;
MemoryRegion io;
MemoryRegion io_gpe;
MemoryRegion io_pci;
+ MemoryRegion io_cpu;
ACPIREGS ar;
APMState apm;
@@ -82,6 +91,9 @@ typedef struct PIIX4PMState {
uint8_t disable_s3;
uint8_t disable_s4;
uint8_t s4_val;
+
+ CPUStatus gpe_cpu;
+ Notifier cpu_added_notifier;
} PIIX4PMState;
static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
@@ -100,8 +112,8 @@ static void pm_update_sci(PIIX4PMState *s)
ACPI_BITMASK_POWER_BUTTON_ENABLE |
ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
ACPI_BITMASK_TIMER_ENABLE)) != 0) ||
- (((s->ar.gpe.sts[0] & s->ar.gpe.en[0])
- & PIIX4_PCI_HOTPLUG_STATUS) != 0);
+ (((s->ar.gpe.sts[0] & s->ar.gpe.en[0]) &
+ (PIIX4_PCI_HOTPLUG_STATUS | PIIX4_CPU_HOTPLUG_STATUS)) != 0);
qemu_set_irq(s->irq, sci_level);
/* schedule a timer interruption if needed */
@@ -585,6 +597,73 @@ static const MemoryRegionOps piix4_pci_ops = {
},
};
+static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
+{
+ PIIX4PMState *s = opaque;
+ CPUStatus *cpus = &s->gpe_cpu;
+ uint64_t val = cpus->sts[addr];
+
+ return val;
+}
+
+static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned int size)
+{
+ /* TODO: implement VCPU removal on guest signal that CPU can be removed */
+}
+
+static const MemoryRegionOps cpu_hotplug_ops = {
+ .read = cpu_status_read,
+ .write = cpu_status_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+};
+
+typedef enum {
+ PLUG,
+ UNPLUG,
+} HotplugEventType;
+
+static void piix4_cpu_hotplug_req(PIIX4PMState *s, CPUState *cpu,
+ HotplugEventType action)
+{
+ CPUStatus *g = &s->gpe_cpu;
+ ACPIGPE *gpe = &s->ar.gpe;
+ CPUClass *k = CPU_GET_CLASS(cpu);
+ int64_t cpu_id;
+
+ assert(s != NULL);
+
+ *gpe->sts = *gpe->sts | PIIX4_CPU_HOTPLUG_STATUS;
+ cpu_id = k->get_arch_id(CPU(cpu));
+ if (action == PLUG) {
+ g->sts[cpu_id / 8] |= (1 << (cpu_id % 8));
+ } else {
+ g->sts[cpu_id / 8] &= ~(1 << (cpu_id % 8));
+ }
+ pm_update_sci(s);
+}
+
+static void piix4_cpu_added_req(Notifier *n, void *opaque)
+{
+ PIIX4PMState *s = container_of(n, PIIX4PMState, cpu_added_notifier);
+
+ piix4_cpu_hotplug_req(s, CPU(opaque), PLUG);
+}
+
+static void piix4_init_cpu_status(CPUState *cpu, void *data)
+{
+ CPUStatus *g = (CPUStatus *)data;
+ CPUClass *k = CPU_GET_CLASS(cpu);
+ int64_t id = k->get_arch_id(cpu);
+
+ g_assert((id / 8) < PIIX4_PROC_LEN);
+ g->sts[id / 8] |= (1 << (id % 8));
+}
+
static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
PCIHotplugState state);
@@ -600,6 +679,13 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
memory_region_add_subregion(parent, PCI_HOTPLUG_ADDR,
&s->io_pci);
pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
+
+ qemu_for_each_cpu(piix4_init_cpu_status, &s->gpe_cpu);
+ memory_region_init_io(&s->io_cpu, &cpu_hotplug_ops, s, "apci-cpu-hotplug",
+ PIIX4_PROC_LEN);
+ memory_region_add_subregion(parent, PIIX4_PROC_BASE, &s->io_cpu);
+ s->cpu_added_notifier.notify = piix4_cpu_added_req;
+ qemu_register_cpu_added_notifier(&s->cpu_added_notifier);
}
static void enable_device(PIIX4PMState *s, int slot)
diff --git a/hw/cpu/Makefile.objs b/hw/cpu/Makefile.objs
index a49ca04282..4461eceee8 100644
--- a/hw/cpu/Makefile.objs
+++ b/hw/cpu/Makefile.objs
@@ -1,4 +1,5 @@
obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o
obj-$(CONFIG_ARM9MPCORE) += a9mpcore.o
obj-$(CONFIG_ARM15MPCORE) += a15mpcore.o
+obj-$(CONFIG_ICC_BUS) += icc_bus.o
diff --git a/hw/cpu/icc_bus.c b/hw/cpu/icc_bus.c
new file mode 100644
index 0000000000..73a1dc985f
--- /dev/null
+++ b/hw/cpu/icc_bus.c
@@ -0,0 +1,119 @@
+/* icc_bus.c
+ * emulate x86 ICC (Interrupt Controller Communications) bus
+ *
+ * Copyright (c) 2013 Red Hat, Inc
+ *
+ * Authors:
+ * Igor Mammedov <imammedo@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ */
+#include "hw/cpu/icc_bus.h"
+#include "hw/sysbus.h"
+
+/* icc-bridge implementation */
+
+static void icc_bus_init(Object *obj)
+{
+ BusState *b = BUS(obj);
+
+ b->allow_hotplug = true;
+}
+
+static const TypeInfo icc_bus_info = {
+ .name = TYPE_ICC_BUS,
+ .parent = TYPE_BUS,
+ .instance_size = sizeof(ICCBus),
+ .instance_init = icc_bus_init,
+};
+
+
+/* icc-device implementation */
+
+static void icc_device_realize(DeviceState *dev, Error **errp)
+{
+ ICCDevice *id = ICC_DEVICE(dev);
+ ICCDeviceClass *idc = ICC_DEVICE_GET_CLASS(id);
+
+ if (idc->init) {
+ if (idc->init(id) < 0) {
+ error_setg(errp, "%s initialization failed.",
+ object_get_typename(OBJECT(dev)));
+ }
+ }
+}
+
+static void icc_device_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = icc_device_realize;
+ dc->bus_type = TYPE_ICC_BUS;
+}
+
+static const TypeInfo icc_device_info = {
+ .name = TYPE_ICC_DEVICE,
+ .parent = TYPE_DEVICE,
+ .abstract = true,
+ .instance_size = sizeof(ICCDevice),
+ .class_size = sizeof(ICCDeviceClass),
+ .class_init = icc_device_class_init,
+};
+
+
+/* icc-bridge implementation */
+
+typedef struct ICCBridgeState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ ICCBus icc_bus;
+ MemoryRegion apic_container;
+} ICCBridgeState;
+
+#define ICC_BRIGDE(obj) OBJECT_CHECK(ICCBridgeState, (obj), TYPE_ICC_BRIDGE)
+
+static void icc_bridge_init(Object *obj)
+{
+ ICCBridgeState *s = ICC_BRIGDE(obj);
+ SysBusDevice *sb = SYS_BUS_DEVICE(obj);
+
+ qbus_create_inplace(&s->icc_bus, TYPE_ICC_BUS, DEVICE(s), "icc");
+
+ /* Do not change order of registering regions,
+ * APIC must be first registered region, board maps it by 0 index
+ */
+ memory_region_init(&s->apic_container, "icc-apic-container",
+ APIC_SPACE_SIZE);
+ sysbus_init_mmio(sb, &s->apic_container);
+ s->icc_bus.apic_address_space = &s->apic_container;
+}
+
+static const TypeInfo icc_bridge_info = {
+ .name = TYPE_ICC_BRIDGE,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_init = icc_bridge_init,
+ .instance_size = sizeof(ICCBridgeState),
+};
+
+
+static void icc_bus_register_types(void)
+{
+ type_register_static(&icc_bus_info);
+ type_register_static(&icc_device_info);
+ type_register_static(&icc_bridge_info);
+}
+
+type_init(icc_bus_register_types)
diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c
index c6ff9821e3..8f80425ccc 100644
--- a/hw/i386/kvm/apic.c
+++ b/hw/i386/kvm/apic.c
@@ -174,7 +174,7 @@ static const MemoryRegionOps kvm_apic_io_ops = {
static void kvm_apic_init(APICCommonState *s)
{
memory_region_init_io(&s->io_memory, &kvm_apic_io_ops, s, "kvm-apic-msi",
- MSI_SPACE_SIZE);
+ APIC_SPACE_SIZE);
if (kvm_has_gsi_routing()) {
msi_supported = true;
diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c
index fa40e283f7..87d4d0fc92 100644
--- a/hw/i386/kvm/clock.c
+++ b/hw/i386/kvm/clock.c
@@ -129,7 +129,7 @@ static const TypeInfo kvmclock_info = {
void kvmclock_create(void)
{
if (kvm_enabled() &&
- first_cpu->cpuid_kvm_features & ((1ULL << KVM_FEATURE_CLOCKSOURCE) |
+ first_cpu->features[FEAT_KVM] & ((1ULL << KVM_FEATURE_CLOCKSOURCE) |
(1ULL << KVM_FEATURE_CLOCKSOURCE2))) {
sysbus_create_simple("kvmclock", -1, NULL);
}
diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
index 3a10c0710c..5b558aa180 100644
--- a/hw/i386/kvmvapic.c
+++ b/hw/i386/kvmvapic.c
@@ -12,6 +12,7 @@
#include "sysemu/cpus.h"
#include "sysemu/kvm.h"
#include "hw/i386/apic_internal.h"
+#include "hw/sysbus.h"
#define VAPIC_IO_PORT 0x7e
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 29d2703330..197d218715 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -53,6 +53,8 @@
#include "qemu/bitmap.h"
#include "qemu/config-file.h"
#include "hw/acpi/acpi.h"
+#include "hw/cpu/icc_bus.h"
+#include "hw/boards.h"
/* debug PC/ISA interrupts */
//#define DEBUG_IRQ
@@ -338,6 +340,21 @@ static void pc_cmos_init_late(void *opaque)
qemu_unregister_reset(pc_cmos_init_late, opaque);
}
+typedef struct RTCCPUHotplugArg {
+ Notifier cpu_added_notifier;
+ ISADevice *rtc_state;
+} RTCCPUHotplugArg;
+
+static void rtc_notify_cpu_added(Notifier *notifier, void *data)
+{
+ RTCCPUHotplugArg *arg = container_of(notifier, RTCCPUHotplugArg,
+ cpu_added_notifier);
+ ISADevice *s = arg->rtc_state;
+
+ /* increment the number of CPUs */
+ rtc_set_memory(s, 0x5f, rtc_get_memory(s, 0x5f) + 1);
+}
+
void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
const char *boot_device,
ISADevice *floppy, BusState *idebus0, BusState *idebus1,
@@ -346,6 +363,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
int val, nb, i;
FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
static pc_cmos_init_late_arg arg;
+ static RTCCPUHotplugArg cpu_hotplug_cb;
/* various important CMOS locations needed by PC/Bochs bios */
@@ -384,6 +402,10 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
/* set the number of CPU */
rtc_set_memory(s, 0x5f, smp_cpus - 1);
+ /* init CPU hotplug notifier */
+ cpu_hotplug_cb.rtc_state = s;
+ cpu_hotplug_cb.cpu_added_notifier.notify = rtc_notify_cpu_added;
+ qemu_register_cpu_added_notifier(&cpu_hotplug_cb.cpu_added_notifier);
/* set boot devices, and disable floppy signature check if requested */
if (set_boot_dev(s, boot_device, fd_bootchk)) {
@@ -874,9 +896,59 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
}
}
-void pc_cpus_init(const char *cpu_model)
+static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id,
+ DeviceState *icc_bridge, Error **errp)
+{
+ X86CPU *cpu;
+ Error *local_err = NULL;
+
+ cpu = cpu_x86_create(cpu_model, icc_bridge, errp);
+ if (!cpu) {
+ return cpu;
+ }
+
+ object_property_set_int(OBJECT(cpu), apic_id, "apic-id", &local_err);
+ object_property_set_bool(OBJECT(cpu), true, "realized", &local_err);
+
+ if (local_err) {
+ if (cpu != NULL) {
+ object_unref(OBJECT(cpu));
+ cpu = NULL;
+ }
+ error_propagate(errp, local_err);
+ }
+ return cpu;
+}
+
+static const char *current_cpu_model;
+
+void pc_hot_add_cpu(const int64_t id, Error **errp)
+{
+ DeviceState *icc_bridge;
+ int64_t apic_id = x86_cpu_apic_id_from_index(id);
+
+ if (cpu_exists(apic_id)) {
+ error_setg(errp, "Unable to add CPU: %" PRIi64
+ ", it already exists", id);
+ return;
+ }
+
+ if (id >= max_cpus) {
+ error_setg(errp, "Unable to add CPU: %" PRIi64
+ ", max allowed: %d", id, max_cpus - 1);
+ return;
+ }
+
+ icc_bridge = DEVICE(object_resolve_path_type("icc-bridge",
+ TYPE_ICC_BRIDGE, NULL));
+ pc_new_cpu(current_cpu_model, apic_id, icc_bridge, errp);
+}
+
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
{
int i;
+ X86CPU *cpu = NULL;
+ Error *error = NULL;
/* init CPUs */
if (cpu_model == NULL) {
@@ -886,12 +958,24 @@ void pc_cpus_init(const char *cpu_model)
cpu_model = "qemu32";
#endif
}
+ current_cpu_model = cpu_model;
for (i = 0; i < smp_cpus; i++) {
- if (!cpu_x86_init(cpu_model)) {
+ cpu = pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i),
+ icc_bridge, &error);
+ if (error) {
+ fprintf(stderr, "%s\n", error_get_pretty(error));
+ error_free(error);
exit(1);
}
}
+
+ /* map APIC MMIO area if CPU has APIC */
+ if (cpu && cpu->env.apic_state) {
+ /* XXX: what if the base changes? */
+ sysbus_mmio_map_overlap(SYS_BUS_DEVICE(icc_bridge), 0,
+ APIC_DEFAULT_ADDRESS, 0x1000);
+ }
}
void pc_acpi_init(const char *default_dsdt)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 852d63ba2e..fe52e5f94b 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -37,6 +37,7 @@
#include "hw/kvm/clock.h"
#include "sysemu/sysemu.h"
#include "hw/sysbus.h"
+#include "hw/cpu/icc_bus.h"
#include "sysemu/arch_init.h"
#include "sysemu/blockdev.h"
#include "hw/i2c/smbus.h"
@@ -87,9 +88,14 @@ static void pc_init1(MemoryRegion *system_memory,
MemoryRegion *ram_memory;
MemoryRegion *pci_memory;
MemoryRegion *rom_memory;
+ DeviceState *icc_bridge;
void *fw_cfg = NULL;
- pc_cpus_init(cpu_model);
+ icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
+ object_property_add_child(qdev_get_machine(), "icc-bridge",
+ OBJECT(icc_bridge), NULL);
+
+ pc_cpus_init(cpu_model, icc_bridge);
pc_acpi_init("acpi-dsdt.aml");
if (kvmclock_enabled) {
@@ -163,6 +169,7 @@ static void pc_init1(MemoryRegion *system_memory,
if (pci_enabled) {
ioapic_init_gsi(gsi_state, "i440fx");
}
+ qdev_init_nofail(icc_bridge);
pc_register_ferr_irq(gsi[13]);
@@ -328,6 +335,7 @@ static QEMUMachine pc_i440fx_machine_v1_5 = {
.alias = "pc",
.desc = "Standard PC (i440FX + PIIX, 1996)",
.init = pc_init_pci,
+ .hot_add_cpu = pc_hot_add_cpu,
.max_cpus = 255,
.is_default = 1,
DEFAULT_MACHINE_OPTIONS,
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index d094041462..52511e2b69 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -41,6 +41,7 @@
#include "hw/ide/pci.h"
#include "hw/ide/ahci.h"
#include "hw/usb.h"
+#include "hw/cpu/icc_bus.h"
/* ICH9 AHCI has 6 ports */
#define MAX_SATA_PORTS 6
@@ -75,8 +76,13 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
int i;
ICH9LPCState *ich9_lpc;
PCIDevice *ahci;
+ DeviceState *icc_bridge;
- pc_cpus_init(cpu_model);
+ icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
+ object_property_add_child(qdev_get_machine(), "icc-bridge",
+ OBJECT(icc_bridge), NULL);
+
+ pc_cpus_init(cpu_model, icc_bridge);
pc_acpi_init("q35-acpi-dsdt.aml");
kvmclock_create();
@@ -158,6 +164,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
if (pci_enabled) {
ioapic_init_gsi(gsi_state, NULL);
}
+ qdev_init_nofail(icc_bridge);
pc_register_ferr_irq(gsi[13]);
@@ -213,6 +220,7 @@ static QEMUMachine pc_q35_machine_v1_5 = {
.alias = "q35",
.desc = "Standard PC (Q35 + ICH9, 2009)",
.init = pc_q35_init,
+ .hot_add_cpu = pc_hot_add_cpu,
.max_cpus = 255,
DEFAULT_MACHINE_OPTIONS,
};
diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index 2d79a9ea7f..756dff008d 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -874,7 +874,7 @@ static const MemoryRegionOps apic_io_ops = {
static void apic_init(APICCommonState *s)
{
memory_region_init_io(&s->io_memory, &apic_io_ops, s, "apic-msi",
- MSI_SPACE_SIZE);
+ APIC_SPACE_SIZE);
s->timer = qemu_new_timer_ns(vm_clock, apic_timer, s);
local_apics[s->idx] = s;
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index e0ae07afd5..b03e904a7a 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -21,6 +21,8 @@
#include "hw/i386/apic_internal.h"
#include "trace.h"
#include "sysemu/kvm.h"
+#include "hw/qdev.h"
+#include "hw/sysbus.h"
static int apic_irq_delivered;
bool apic_report_tpr_access;
@@ -282,12 +284,13 @@ static int apic_load_old(QEMUFile *f, void *opaque, int version_id)
return 0;
}
-static int apic_init_common(SysBusDevice *dev)
+static int apic_init_common(ICCDevice *dev)
{
APICCommonState *s = APIC_COMMON(dev);
APICCommonClass *info;
static DeviceState *vapic;
static int apic_no;
+ static bool mmio_registered;
if (apic_no >= MAX_APICS) {
return -1;
@@ -296,8 +299,11 @@ static int apic_init_common(SysBusDevice *dev)
info = APIC_COMMON_GET_CLASS(s);
info->init(s);
-
- sysbus_init_mmio(dev, &s->io_memory);
+ if (!mmio_registered) {
+ ICCBus *b = ICC_BUS(qdev_get_parent_bus(DEVICE(dev)));
+ memory_region_add_subregion(b->apic_address_space, 0, &s->io_memory);
+ mmio_registered = true;
+ }
/* Note: We need at least 1M to map the VAPIC option ROM */
if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK &&
@@ -375,19 +381,19 @@ static Property apic_properties_common[] = {
static void apic_common_class_init(ObjectClass *klass, void *data)
{
- SysBusDeviceClass *sc = SYS_BUS_DEVICE_CLASS(klass);
+ ICCDeviceClass *idc = ICC_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
dc->vmsd = &vmstate_apic_common;
dc->reset = apic_reset_common;
dc->no_user = 1;
dc->props = apic_properties_common;
- sc->init = apic_init_common;
+ idc->init = apic_init_common;
}
static const TypeInfo apic_common_type = {
.name = TYPE_APIC_COMMON,
- .parent = TYPE_SYS_BUS_DEVICE,
+ .parent = TYPE_ICC_DEVICE,
.instance_size = sizeof(APICCommonState),
.class_size = sizeof(APICCommonClass),
.class_init = apic_common_class_init,
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index afbd0db298..481604de35 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -680,6 +680,13 @@ void rtc_set_memory(ISADevice *dev, int addr, int val)
s->cmos_data[addr] = val;
}
+int rtc_get_memory(ISADevice *dev, int addr)
+{
+ RTCState *s = MC146818_RTC(dev);
+ assert(addr >= 0 && addr <= 127);
+ return s->cmos_data[addr];
+}
+
static void rtc_set_date_from_host(ISADevice *dev)
{
RTCState *s = MC146818_RTC(dev);
diff --git a/hw/xen/xen_apic.c b/hw/xen/xen_apic.c
index a2eb8a159a..a958782272 100644
--- a/hw/xen/xen_apic.c
+++ b/hw/xen/xen_apic.c
@@ -39,7 +39,7 @@ static const MemoryRegionOps xen_apic_io_ops = {
static void xen_apic_init(APICCommonState *s)
{
memory_region_init_io(&s->io_memory, &xen_apic_io_ops, s, "xen-apic-msi",
- MSI_SPACE_SIZE);
+ APIC_SPACE_SIZE);
#if defined(CONFIG_XEN_CTRL_INTERFACE_VERSION) \
&& CONFIG_XEN_CTRL_INTERFACE_VERSION >= 420