aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS6
-rw-r--r--Makefile.target14
-rw-r--r--bsd-user/elfload.c2
-rw-r--r--bsd-user/main.c4
-rw-r--r--cpus.c27
-rw-r--r--default-configs/i386-softmmu.mak1
-rw-r--r--default-configs/x86_64-softmmu.mak1
-rw-r--r--docs/specs/acpi_cpu_hotplug.txt22
-rw-r--r--dump-stub.c28
-rw-r--r--dump.c8
-rw-r--r--exec.c10
-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
-rw-r--r--include/hw/boards.h3
-rw-r--r--include/hw/cpu/icc_bus.h82
-rw-r--r--include/hw/i386/apic_internal.h8
-rw-r--r--include/hw/i386/pc.h3
-rw-r--r--include/hw/timer/mc146818rtc.h1
-rw-r--r--include/qom/cpu.h77
-rw-r--r--include/sysemu/dump.h9
-rw-r--r--include/sysemu/kvm.h24
-rw-r--r--include/sysemu/sysemu.h3
-rw-r--r--kvm-all.c1
-rw-r--r--kvm-stub.c8
-rw-r--r--linux-user/elfload.c2
-rw-r--r--linux-user/main.c4
-rw-r--r--qapi-schema.json13
-rw-r--r--qmp-commands.hx23
-rw-r--r--qmp.c10
-rw-r--r--qom/cpu.c114
-rw-r--r--stubs/Makefile.objs1
-rw-r--r--stubs/cpus.c5
-rw-r--r--target-i386/arch_dump.c38
-rw-r--r--target-i386/cpu-qom.h9
-rw-r--r--target-i386/cpu.c520
-rw-r--r--target-i386/cpu.h19
-rw-r--r--target-i386/helper.c4
-rw-r--r--target-i386/kvm.c5
-rw-r--r--target-i386/misc_helper.c14
-rw-r--r--target-i386/translate.c10
-rw-r--r--vl.c2
52 files changed, 1161 insertions, 326 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 4dfd8bf7ab..be02724e6e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -644,6 +644,12 @@ F: qom/cpu.c
F: include/qemu/cpu.h
F: target-i386/cpu.c
+ICC Bus
+M: Igor Mammedov <imammedo@redhat.com>
+S: Supported
+F: include/hw/cpu/icc_bus.h
+F: hw/cpu/icc_bus.c
+
Device Tree
M: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
M: Alexander Graf <agraf@suse.de>
diff --git a/Makefile.target b/Makefile.target
index 6583b05482..ce4391fca7 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -60,6 +60,12 @@ all: $(PROGS) stap
# Dummy command so that make thinks it has done something
@true
+CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
+CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
+CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
+CONFIG_NO_GET_MEMORY_MAPPING = $(if $(subst n,,$(CONFIG_HAVE_GET_MEMORY_MAPPING)),n,y)
+CONFIG_NO_CORE_DUMP = $(if $(subst n,,$(CONFIG_HAVE_CORE_DUMP)),n,y)
+
#########################################################
# cpu emulator library
obj-y = exec.o translate-all.o cpu-exec.o
@@ -70,6 +76,7 @@ obj-y += fpu/softfloat.o
obj-y += target-$(TARGET_BASE_ARCH)/
obj-y += disas.o
obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o
+obj-$(CONFIG_NO_KVM) += kvm-stub.o
#########################################################
# Linux user emulator target
@@ -98,18 +105,11 @@ endif #CONFIG_BSD_USER
#########################################################
# System emulator target
ifdef CONFIG_SOFTMMU
-CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
-CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
-CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
-CONFIG_NO_GET_MEMORY_MAPPING = $(if $(subst n,,$(CONFIG_HAVE_GET_MEMORY_MAPPING)),n,y)
-CONFIG_NO_CORE_DUMP = $(if $(subst n,,$(CONFIG_HAVE_CORE_DUMP)),n,y)
-
obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o
obj-y += qtest.o
obj-y += hw/
obj-$(CONFIG_FDT) += device_tree.o
obj-$(CONFIG_KVM) += kvm-all.o
-obj-$(CONFIG_NO_KVM) += kvm-stub.o
obj-y += memory.o savevm.o cputlb.o
obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += memory_mapping.o
obj-$(CONFIG_HAVE_CORE_DUMP) += dump.o
diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index a6cd3ab4f3..5e20510309 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -110,7 +110,7 @@ static const char *get_elf_platform(void)
static uint32_t get_elf_hwcap(void)
{
- return thread_env->cpuid_features;
+ return thread_env->features[FEAT_1_EDX];
}
#ifdef TARGET_X86_64
diff --git a/bsd-user/main.c b/bsd-user/main.c
index cc8498187a..0da3ab9e21 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -1004,13 +1004,13 @@ int main(int argc, char **argv)
env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
env->hflags |= HF_PE_MASK;
- if (env->cpuid_features & CPUID_SSE) {
+ if (env->features[FEAT_1_EDX] & CPUID_SSE) {
env->cr[4] |= CR4_OSFXSR_MASK;
env->hflags |= HF_OSFXSR_MASK;
}
#ifndef TARGET_ABI32
/* enable 64 bit mode if possible */
- if (!(env->cpuid_ext2_features & CPUID_EXT2_LM)) {
+ if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
exit(1);
}
diff --git a/cpus.c b/cpus.c
index 5a98a370df..c232265cd2 100644
--- a/cpus.c
+++ b/cpus.c
@@ -812,6 +812,12 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
static void tcg_exec_all(void);
+static void tcg_signal_cpu_creation(CPUState *cpu, void *data)
+{
+ cpu->thread_id = qemu_get_thread_id();
+ cpu->created = true;
+}
+
static void *qemu_tcg_cpu_thread_fn(void *arg)
{
CPUState *cpu = arg;
@@ -820,13 +826,8 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
qemu_tcg_init_cpu_signals();
qemu_thread_get_self(cpu->thread);
- /* signal CPU creation */
qemu_mutex_lock(&qemu_global_mutex);
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
- cpu = ENV_GET_CPU(env);
- cpu->thread_id = qemu_get_thread_id();
- cpu->created = true;
- }
+ qemu_for_each_cpu(tcg_signal_cpu_creation, NULL);
qemu_cond_signal(&qemu_cpu_cond);
/* wait for initial kick-off after machine start */
@@ -973,9 +974,10 @@ void pause_all_vcpus(void)
if (qemu_in_vcpu_thread()) {
cpu_stop_current();
if (!kvm_enabled()) {
+ penv = first_cpu;
while (penv) {
CPUState *pcpu = ENV_GET_CPU(penv);
- pcpu->stop = 0;
+ pcpu->stop = false;
pcpu->stopped = true;
penv = penv->next_cpu;
}
@@ -993,6 +995,13 @@ void pause_all_vcpus(void)
}
}
+void cpu_resume(CPUState *cpu)
+{
+ cpu->stop = false;
+ cpu->stopped = false;
+ qemu_cpu_kick(cpu);
+}
+
void resume_all_vcpus(void)
{
CPUArchState *penv = first_cpu;
@@ -1000,9 +1009,7 @@ void resume_all_vcpus(void)
qemu_clock_enable(vm_clock, true);
while (penv) {
CPUState *pcpu = ENV_GET_CPU(penv);
- pcpu->stop = false;
- pcpu->stopped = false;
- qemu_cpu_kick(pcpu);
+ cpu_resume(pcpu);
penv = penv->next_cpu;
}
}
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 4e30505ae3..03deca2dcb 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -44,4 +44,5 @@ CONFIG_LPC_ICH9=y
CONFIG_PCI_Q35=y
CONFIG_APIC=y
CONFIG_IOAPIC=y
+CONFIG_ICC_BUS=y
CONFIG_PVPANIC=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 5af8fd3c0b..599b63071f 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -44,4 +44,5 @@ CONFIG_LPC_ICH9=y
CONFIG_PCI_Q35=y
CONFIG_APIC=y
CONFIG_IOAPIC=y
+CONFIG_ICC_BUS=y
CONFIG_PVPANIC=y
diff --git a/docs/specs/acpi_cpu_hotplug.txt b/docs/specs/acpi_cpu_hotplug.txt
new file mode 100644
index 0000000000..5dec0c5010
--- /dev/null
+++ b/docs/specs/acpi_cpu_hotplug.txt
@@ -0,0 +1,22 @@
+QEMU<->ACPI BIOS CPU hotplug interface
+--------------------------------------
+
+QEMU supports CPU hotplug via ACPI. This document
+describes the interface between QEMU and the ACPI BIOS.
+
+ACPI GPE block (IO ports 0xafe0-0xafe3, byte access):
+-----------------------------------------
+
+Generic ACPI GPE block. Bit 2 (GPE.2) used to notify CPU
+hot-add/remove event to ACPI BIOS, via SCI interrupt.
+
+CPU present bitmap (IO port 0xaf00-0xae1f, 1-byte access):
+---------------------------------------------------------------
+One bit per CPU. Bit position reflects corresponding CPU APIC ID.
+Read-only.
+
+CPU hot-add/remove notification:
+-----------------------------------------------------
+QEMU sets/clears corresponding CPU bit on hot-add/remove event.
+CPU present map read by ACPI BIOS GPE.2 handler to notify OS of CPU
+hot-(un)plug events.
diff --git a/dump-stub.c b/dump-stub.c
index a9d0b3c67b..b3f42cb2f1 100644
--- a/dump-stub.c
+++ b/dump-stub.c
@@ -24,34 +24,6 @@ void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
error_set(errp, QERR_UNSUPPORTED);
}
-int cpu_write_elf64_note(write_core_dump_function f,
- CPUArchState *env, int cpuid,
- void *opaque)
-{
- return -1;
-}
-
-int cpu_write_elf32_note(write_core_dump_function f,
- CPUArchState *env, int cpuid,
- void *opaque)
-{
- return -1;
-}
-
-int cpu_write_elf64_qemunote(write_core_dump_function f,
- CPUArchState *env,
- void *opaque)
-{
- return -1;
-}
-
-int cpu_write_elf32_qemunote(write_core_dump_function f,
- CPUArchState *env,
- void *opaque)
-{
- return -1;
-}
-
int cpu_get_dump_info(ArchDumpInfo *info)
{
return -1;
diff --git a/dump.c b/dump.c
index b34f143c42..c0d3da515b 100644
--- a/dump.c
+++ b/dump.c
@@ -282,7 +282,7 @@ static int write_elf64_notes(DumpState *s)
for (env = first_cpu; env != NULL; env = env->next_cpu) {
cpu = ENV_GET_CPU(env);
id = cpu_index(cpu);
- ret = cpu_write_elf64_note(fd_write_vmcore, env, id, s);
+ ret = cpu_write_elf64_note(fd_write_vmcore, cpu, id, s);
if (ret < 0) {
dump_error(s, "dump: failed to write elf notes.\n");
return -1;
@@ -290,7 +290,7 @@ static int write_elf64_notes(DumpState *s)
}
for (env = first_cpu; env != NULL; env = env->next_cpu) {
- ret = cpu_write_elf64_qemunote(fd_write_vmcore, env, s);
+ ret = cpu_write_elf64_qemunote(fd_write_vmcore, cpu, s);
if (ret < 0) {
dump_error(s, "dump: failed to write CPU status.\n");
return -1;
@@ -334,7 +334,7 @@ static int write_elf32_notes(DumpState *s)
for (env = first_cpu; env != NULL; env = env->next_cpu) {
cpu = ENV_GET_CPU(env);
id = cpu_index(cpu);
- ret = cpu_write_elf32_note(fd_write_vmcore, env, id, s);
+ ret = cpu_write_elf32_note(fd_write_vmcore, cpu, id, s);
if (ret < 0) {
dump_error(s, "dump: failed to write elf notes.\n");
return -1;
@@ -342,7 +342,7 @@ static int write_elf32_notes(DumpState *s)
}
for (env = first_cpu; env != NULL; env = env->next_cpu) {
- ret = cpu_write_elf32_qemunote(fd_write_vmcore, env, s);
+ ret = cpu_write_elf32_qemunote(fd_write_vmcore, cpu, s);
if (ret < 0) {
dump_error(s, "dump: failed to write CPU status.\n");
return -1;
diff --git a/exec.c b/exec.c
index fa1e0c3d73..19725dbc05 100644
--- a/exec.c
+++ b/exec.c
@@ -265,6 +265,16 @@ CPUState *qemu_get_cpu(int index)
return env ? cpu : NULL;
}
+void qemu_for_each_cpu(void (*func)(CPUState *cpu, void *data), void *data)
+{
+ CPUArchState *env = first_cpu;
+
+ while (env) {
+ func(ENV_GET_CPU(env), data);
+ env = env->next_cpu;
+ }
+}
+
void cpu_exec_init(CPUArchState *env)
{
CPUState *cpu = ENV_GET_CPU(env);
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
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 425bdc74a8..fb7c6f1243 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -22,12 +22,15 @@ typedef void QEMUMachineInitFunc(QEMUMachineInitArgs *args);
typedef void QEMUMachineResetFunc(void);
+typedef void QEMUMachineHotAddCPUFunc(const int64_t id, Error **errp);
+
typedef struct QEMUMachine {
const char *name;
const char *alias;
const char *desc;
QEMUMachineInitFunc *init;
QEMUMachineResetFunc *reset;
+ QEMUMachineHotAddCPUFunc *hot_add_cpu;
BlockInterfaceType block_default_type;
int max_cpus;
unsigned int no_serial:1,
diff --git a/include/hw/cpu/icc_bus.h b/include/hw/cpu/icc_bus.h
new file mode 100644
index 0000000000..b5500708dc
--- /dev/null
+++ b/include/hw/cpu/icc_bus.h
@@ -0,0 +1,82 @@
+/* icc_bus.h
+ * 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/>
+ */
+#ifndef ICC_BUS_H
+#define ICC_BUS_H
+
+#include "exec/memory.h"
+#include "hw/qdev-core.h"
+
+#define TYPE_ICC_BUS "icc-bus"
+
+#ifndef CONFIG_USER_ONLY
+
+/**
+ * ICCBus:
+ *
+ * ICC bus
+ */
+typedef struct ICCBus {
+ /*< private >*/
+ BusState parent_obj;
+ /*< public >*/
+
+ MemoryRegion *apic_address_space;
+} ICCBus;
+
+#define ICC_BUS(obj) OBJECT_CHECK(ICCBus, (obj), TYPE_ICC_BUS)
+
+/**
+ * ICCDevice:
+ *
+ * ICC device
+ */
+typedef struct ICCDevice {
+ /*< private >*/
+ DeviceState qdev;
+ /*< public >*/
+} ICCDevice;
+
+/**
+ * ICCDeviceClass:
+ * @init: Initialization callback for derived classes.
+ *
+ * ICC device class
+ */
+typedef struct ICCDeviceClass {
+ /*< private >*/
+ DeviceClass parent_class;
+ /*< public >*/
+
+ int (*init)(ICCDevice *dev); /* TODO replace with QOM realize */
+} ICCDeviceClass;
+
+#define TYPE_ICC_DEVICE "icc-device"
+#define ICC_DEVICE(obj) OBJECT_CHECK(ICCDevice, (obj), TYPE_ICC_DEVICE)
+#define ICC_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(ICCDeviceClass, (klass), TYPE_ICC_DEVICE)
+#define ICC_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(ICCDeviceClass, (obj), TYPE_ICC_DEVICE)
+
+#define TYPE_ICC_BRIDGE "icc-bridge"
+
+#endif /* CONFIG_USER_ONLY */
+#endif
diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h
index 578241f861..1b0a7fbfad 100644
--- a/include/hw/i386/apic_internal.h
+++ b/include/hw/i386/apic_internal.h
@@ -21,7 +21,7 @@
#define QEMU_APIC_INTERNAL_H
#include "exec/memory.h"
-#include "hw/sysbus.h"
+#include "hw/cpu/icc_bus.h"
#include "qemu/timer.h"
/* APIC Local Vector Table */
@@ -66,8 +66,6 @@
#define MAX_APICS 255
-#define MSI_SPACE_SIZE 0x100000
-
typedef struct APICCommonState APICCommonState;
#define TYPE_APIC_COMMON "apic-common"
@@ -80,7 +78,7 @@ typedef struct APICCommonState APICCommonState;
typedef struct APICCommonClass
{
- SysBusDeviceClass parent_class;
+ ICCDeviceClass parent_class;
void (*init)(APICCommonState *s);
void (*set_base)(APICCommonState *s, uint64_t val);
@@ -94,7 +92,7 @@ typedef struct APICCommonClass
} APICCommonClass;
struct APICCommonState {
- SysBusDevice busdev;
+ ICCDevice busdev;
MemoryRegion io_memory;
X86CPU *cpu;
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index dd6bc249bf..41869e56e9 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -78,7 +78,8 @@ extern int fd_bootchk;
void pc_register_ferr_irq(qemu_irq irq);
void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
-void pc_cpus_init(const char *cpu_model);
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge);
+void pc_hot_add_cpu(const int64_t id, Error **errp);
void pc_acpi_init(const char *default_dsdt);
void *pc_memory_init(MemoryRegion *system_memory,
const char *kernel_filename,
diff --git a/include/hw/timer/mc146818rtc.h b/include/hw/timer/mc146818rtc.h
index 425bd179a4..753dda6ae7 100644
--- a/include/hw/timer/mc146818rtc.h
+++ b/include/hw/timer/mc146818rtc.h
@@ -8,6 +8,7 @@
ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq);
void rtc_set_memory(ISADevice *dev, int addr, int val);
+int rtc_get_memory(ISADevice *dev, int addr);
void rtc_set_date(ISADevice *dev, const struct tm *tm);
#endif /* !MC146818RTC_H */
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 3664a1b631..7cd9442503 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -24,6 +24,8 @@
#include "hw/qdev-core.h"
#include "qemu/thread.h"
+typedef int (*WriteCoreDumpFunction)(void *buf, size_t size, void *opaque);
+
/**
* SECTION:cpu
* @section_id: QEMU-cpu
@@ -45,6 +47,7 @@ typedef struct CPUState CPUState;
* instantiatable CPU type.
* @reset: Callback to reset the #CPUState to its initial state.
* @do_interrupt: Callback for interrupt handling.
+ * @get_arch_id: Callback for getting architecture-dependent CPU ID.
* @vmsd: State description for migration.
*
* Represents a CPU family or model.
@@ -58,8 +61,17 @@ typedef struct CPUClass {
void (*reset)(CPUState *cpu);
void (*do_interrupt)(CPUState *cpu);
+ int64_t (*get_arch_id)(CPUState *cpu);
const struct VMStateDescription *vmsd;
+ int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, void *opaque);
+ int (*write_elf64_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
+ void *opaque);
+ int (*write_elf32_note)(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, void *opaque);
+ int (*write_elf32_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
+ void *opaque);
} CPUClass;
struct KVMState;
@@ -125,6 +137,45 @@ struct CPUState {
uint32_t halted; /* used by alpha, cris, ppc TCG */
};
+/**
+ * cpu_write_elf64_note:
+ * @f: pointer to a function that writes memory to a file
+ * @cpu: The CPU whose memory is to be dumped
+ * @cpuid: ID number of the CPU
+ * @opaque: pointer to the CPUState struct
+ */
+int cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, void *opaque);
+
+/**
+ * cpu_write_elf64_qemunote:
+ * @f: pointer to a function that writes memory to a file
+ * @cpu: The CPU whose memory is to be dumped
+ * @cpuid: ID number of the CPU
+ * @opaque: pointer to the CPUState struct
+ */
+int cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+ void *opaque);
+
+/**
+ * cpu_write_elf32_note:
+ * @f: pointer to a function that writes memory to a file
+ * @cpu: The CPU whose memory is to be dumped
+ * @cpuid: ID number of the CPU
+ * @opaque: pointer to the CPUState struct
+ */
+int cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, void *opaque);
+
+/**
+ * cpu_write_elf32_qemunote:
+ * @f: pointer to a function that writes memory to a file
+ * @cpu: The CPU whose memory is to be dumped
+ * @cpuid: ID number of the CPU
+ * @opaque: pointer to the CPUState struct
+ */
+int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+ void *opaque);
/**
* cpu_reset:
@@ -214,6 +265,15 @@ bool cpu_is_stopped(CPUState *cpu);
void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data);
/**
+ * qemu_for_each_cpu:
+ * @func: The function to be executed.
+ * @data: Data to pass to the function.
+ *
+ * Executes @func for each CPU.
+ */
+void qemu_for_each_cpu(void (*func)(CPUState *cpu, void *data), void *data);
+
+/**
* qemu_get_cpu:
* @index: The CPUState@cpu_index value of the CPU to obtain.
*
@@ -223,6 +283,16 @@ void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data);
*/
CPUState *qemu_get_cpu(int index);
+/**
+ * cpu_exists:
+ * @id: Guest-exposed CPU ID to lookup.
+ *
+ * Search for CPU with specified ID.
+ *
+ * Returns: %true - CPU is found, %false - CPU isn't found.
+ */
+bool cpu_exists(int64_t id);
+
#ifndef CONFIG_USER_ONLY
typedef void (*CPUInterruptHandler)(CPUState *, int);
@@ -256,5 +326,12 @@ void cpu_interrupt(CPUState *cpu, int mask);
*/
void cpu_reset_interrupt(CPUState *cpu, int mask);
+/**
+ * cpu_resume:
+ * @cpu: The CPU to resume.
+ *
+ * Resumes CPU, i.e. puts CPU into runnable state.
+ */
+void cpu_resume(CPUState *cpu);
#endif
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index e25b7cfb73..b8c770f8d9 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -20,15 +20,6 @@ typedef struct ArchDumpInfo {
int d_class; /* ELFCLASS32 or ELFCLASS64 */
} ArchDumpInfo;
-typedef int (*write_core_dump_function)(void *buf, size_t size, void *opaque);
-int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
- int cpuid, void *opaque);
-int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
- int cpuid, void *opaque);
-int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
- void *opaque);
-int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
- void *opaque);
int cpu_get_dump_info(ArchDumpInfo *info);
ssize_t cpu_get_note_size(int class, int machine, int nr_cpus);
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 75bd7d9934..9735c1dee6 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -144,10 +144,10 @@ int kvm_cpu_exec(CPUArchState *env);
#if !defined(CONFIG_USER_ONLY)
void *kvm_vmalloc(ram_addr_t size);
void *kvm_arch_vmalloc(ram_addr_t size);
-void kvm_setup_guest_memory(void *start, size_t size);
+#endif
+void kvm_setup_guest_memory(void *start, size_t size);
void kvm_flush_coalesced_mmio_buffer(void);
-#endif
int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr,
target_ulong len, int type);
@@ -250,8 +250,6 @@ int kvm_check_extension(KVMState *s, unsigned int extension);
uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
uint32_t index, int reg);
void kvm_cpu_synchronize_state(CPUArchState *env);
-void kvm_cpu_synchronize_post_reset(CPUState *cpu);
-void kvm_cpu_synchronize_post_init(CPUState *cpu);
/* generic hooks - to be moved/refactored once there are more users */
@@ -262,6 +260,16 @@ static inline void cpu_synchronize_state(CPUArchState *env)
}
}
+#if !defined(CONFIG_USER_ONLY)
+int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
+ hwaddr *phys_addr);
+#endif
+
+#endif /* NEED_CPU_H */
+
+void kvm_cpu_synchronize_post_reset(CPUState *cpu);
+void kvm_cpu_synchronize_post_init(CPUState *cpu);
+
static inline void cpu_synchronize_post_reset(CPUState *cpu)
{
if (kvm_enabled()) {
@@ -276,14 +284,6 @@ static inline void cpu_synchronize_post_init(CPUState *cpu)
}
}
-
-#if !defined(CONFIG_USER_ONLY)
-int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
- hwaddr *phys_addr);
-#endif
-
-#endif
-
int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg);
void kvm_irqchip_release_virq(KVMState *s, int virq);
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 010e412f0c..2fb71afa25 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -153,6 +153,9 @@ void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict);
/* generic hotplug */
void drive_hot_add(Monitor *mon, const QDict *qdict);
+/* CPU hotplug */
+void qemu_register_cpu_added_notifier(Notifier *notifier);
+
/* pcie aer error injection */
void pcie_aer_inject_error_print(Monitor *mon, const QObject *data);
int do_pcie_aer_inject_error(Monitor *mon,
diff --git a/kvm-all.c b/kvm-all.c
index 2d927217bd..f6c0f4a087 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -109,6 +109,7 @@ bool kvm_async_interrupts_allowed;
bool kvm_irqfds_allowed;
bool kvm_msi_via_irqfd_allowed;
bool kvm_gsi_routing_allowed;
+bool kvm_allowed;
static const KVMCapabilityInfo kvm_required_capabilites[] = {
KVM_CAP_INFO(USER_MEMORY),
diff --git a/kvm-stub.c b/kvm-stub.c
index 5f52186ae7..b2c8f9b02d 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -12,16 +12,20 @@
#include "qemu-common.h"
#include "hw/hw.h"
-#include "hw/pci/msi.h"
#include "cpu.h"
#include "sysemu/kvm.h"
+#ifndef CONFIG_USER_ONLY
+#include "hw/pci/msi.h"
+#endif
+
KVMState *kvm_state;
bool kvm_kernel_irqchip;
bool kvm_async_interrupts_allowed;
bool kvm_irqfds_allowed;
bool kvm_msi_via_irqfd_allowed;
bool kvm_gsi_routing_allowed;
+bool kvm_allowed;
int kvm_init_vcpu(CPUState *cpu)
{
@@ -111,6 +115,7 @@ int kvm_on_sigbus(int code, void *addr)
return 1;
}
+#ifndef CONFIG_USER_ONLY
int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
{
return -ENOSYS;
@@ -134,3 +139,4 @@ int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq)
{
return -ENOSYS;
}
+#endif
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 979b57c7cf..ddef23e6dc 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -137,7 +137,7 @@ static const char *get_elf_platform(void)
static uint32_t get_elf_hwcap(void)
{
- return thread_env->cpuid_features;
+ return thread_env->features[FEAT_1_EDX];
}
#ifdef TARGET_X86_64
diff --git a/linux-user/main.c b/linux-user/main.c
index 4e92a0b4c5..b97b8cfd33 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3764,13 +3764,13 @@ int main(int argc, char **argv, char **envp)
env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
env->hflags |= HF_PE_MASK;
- if (env->cpuid_features & CPUID_SSE) {
+ if (env->features[FEAT_1_EDX] & CPUID_SSE) {
env->cr[4] |= CR4_OSFXSR_MASK;
env->hflags |= HF_OSFXSR_MASK;
}
#ifndef TARGET_ABI32
/* enable 64 bit mode if possible */
- if (!(env->cpuid_ext2_features & CPUID_EXT2_LM)) {
+ if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
exit(1);
}
diff --git a/qapi-schema.json b/qapi-schema.json
index 65be8f4f37..7797400666 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1390,6 +1390,19 @@
{ 'command': 'cpu', 'data': {'index': 'int'} }
##
+# @cpu-add
+#
+# Adds CPU with specified ID
+#
+# @id: ID of CPU to be created, valid values [0..max_cpus)
+#
+# Returns: Nothing on success
+#
+# Since 1.5
+##
+{ 'command': 'cpu-add', 'data': {'id': 'int'} }
+
+##
# @memsave:
#
# Save a portion of guest memory to a file.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index d15bec1f07..ffd130edf6 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -385,6 +385,29 @@ Note: CPUs' indexes are obtained with the 'query-cpus' command.
EQMP
{
+ .name = "cpu-add",
+ .args_type = "id:i",
+ .mhandler.cmd_new = qmp_marshal_input_cpu_add,
+ },
+
+SQMP
+cpu-add
+-------
+
+Adds virtual cpu
+
+Arguments:
+
+- "id": cpu id (json-int)
+
+Example:
+
+-> { "execute": "cpu-add", "arguments": { "id": 2 } }
+<- { "return": {} }
+
+EQMP
+
+ {
.name = "memsave",
.args_type = "val:l,size:i,filename:s,cpu:i?",
.mhandler.cmd_new = qmp_marshal_input_memsave,
diff --git a/qmp.c b/qmp.c
index 4676993805..4c149b33a4 100644
--- a/qmp.c
+++ b/qmp.c
@@ -24,6 +24,7 @@
#include "hw/qdev.h"
#include "sysemu/blockdev.h"
#include "qom/qom-qobject.h"
+#include "hw/boards.h"
NameInfo *qmp_query_name(Error **errp)
{
@@ -108,6 +109,15 @@ void qmp_cpu(int64_t index, Error **errp)
/* Just do nothing */
}
+void qmp_cpu_add(int64_t id, Error **errp)
+{
+ if (current_machine->hot_add_cpu) {
+ current_machine->hot_add_cpu(id, errp);
+ } else {
+ error_setg(errp, "Not supported");
+ }
+}
+
#ifndef CONFIG_VNC
/* If VNC support is enabled, the "true" query-vnc command is
defined in the VNC subsystem */
diff --git a/qom/cpu.c b/qom/cpu.c
index e242dcbeb4..04aefbb956 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -20,12 +20,109 @@
#include "qom/cpu.h"
#include "qemu-common.h"
+#include "sysemu/kvm.h"
+#include "qemu/notify.h"
+#include "sysemu/sysemu.h"
+
+typedef struct CPUExistsArgs {
+ int64_t id;
+ bool found;
+} CPUExistsArgs;
+
+static void cpu_exist_cb(CPUState *cpu, void *data)
+{
+ CPUClass *klass = CPU_GET_CLASS(cpu);
+ CPUExistsArgs *arg = data;
+
+ if (klass->get_arch_id(cpu) == arg->id) {
+ arg->found = true;
+ }
+}
+
+bool cpu_exists(int64_t id)
+{
+ CPUExistsArgs data = {
+ .id = id,
+ .found = false,
+ };
+
+ qemu_for_each_cpu(cpu_exist_cb, &data);
+ return data.found;
+}
+
+/* CPU hot-plug notifiers */
+static NotifierList cpu_added_notifiers =
+ NOTIFIER_LIST_INITIALIZER(cpu_add_notifiers);
+
+void qemu_register_cpu_added_notifier(Notifier *notifier)
+{
+ notifier_list_add(&cpu_added_notifiers, notifier);
+}
void cpu_reset_interrupt(CPUState *cpu, int mask)
{
cpu->interrupt_request &= ~mask;
}
+int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+ void *opaque)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ return (*cc->write_elf32_qemunote)(f, cpu, opaque);
+}
+
+static int cpu_common_write_elf32_qemunote(WriteCoreDumpFunction f,
+ CPUState *cpu, void *opaque)
+{
+ return -1;
+}
+
+int cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, void *opaque)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ return (*cc->write_elf32_note)(f, cpu, cpuid, opaque);
+}
+
+static int cpu_common_write_elf32_note(WriteCoreDumpFunction f,
+ CPUState *cpu, int cpuid,
+ void *opaque)
+{
+ return -1;
+}
+
+int cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+ void *opaque)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ return (*cc->write_elf64_qemunote)(f, cpu, opaque);
+}
+
+static int cpu_common_write_elf64_qemunote(WriteCoreDumpFunction f,
+ CPUState *cpu, void *opaque)
+{
+ return -1;
+}
+
+int cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, void *opaque)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ return (*cc->write_elf64_note)(f, cpu, cpuid, opaque);
+}
+
+static int cpu_common_write_elf64_note(WriteCoreDumpFunction f,
+ CPUState *cpu, int cpuid,
+ void *opaque)
+{
+ return -1;
+}
+
+
void cpu_reset(CPUState *cpu)
{
CPUClass *klass = CPU_GET_CLASS(cpu);
@@ -57,6 +154,18 @@ static ObjectClass *cpu_common_class_by_name(const char *cpu_model)
static void cpu_common_realizefn(DeviceState *dev, Error **errp)
{
+ CPUState *cpu = CPU(dev);
+
+ if (dev->hotplugged) {
+ cpu_synchronize_post_init(cpu);
+ notifier_list_notify(&cpu_added_notifiers, dev);
+ cpu_resume(cpu);
+ }
+}
+
+static int64_t cpu_common_get_arch_id(CPUState *cpu)
+{
+ return cpu->cpu_index;
}
static void cpu_class_init(ObjectClass *klass, void *data)
@@ -66,6 +175,11 @@ static void cpu_class_init(ObjectClass *klass, void *data)
k->class_by_name = cpu_common_class_by_name;
k->reset = cpu_common_reset;
+ k->get_arch_id = cpu_common_get_arch_id;
+ k->write_elf32_qemunote = cpu_common_write_elf32_qemunote;
+ k->write_elf32_note = cpu_common_write_elf32_note;
+ k->write_elf64_qemunote = cpu_common_write_elf64_qemunote;
+ k->write_elf64_note = cpu_common_write_elf64_note;
dc->realize = cpu_common_realizefn;
dc->no_user = 1;
}
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 9c55b34354..03dff202e4 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -23,3 +23,4 @@ stub-obj-y += sysbus.o
stub-obj-y += vm-stop.o
stub-obj-y += vmstate.o
stub-obj-$(CONFIG_WIN32) += fd-register.o
+stub-obj-y += cpus.o
diff --git a/stubs/cpus.c b/stubs/cpus.c
new file mode 100644
index 0000000000..37000dd611
--- /dev/null
+++ b/stubs/cpus.c
@@ -0,0 +1,5 @@
+#include "qom/cpu.h"
+
+void cpu_resume(CPUState *cpu)
+{
+}
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
index 2cd2f7f09e..83898cd00f 100644
--- a/target-i386/arch_dump.c
+++ b/target-i386/arch_dump.c
@@ -34,7 +34,7 @@ typedef struct {
char pad3[8];
} x86_64_elf_prstatus;
-static int x86_64_write_elf64_note(write_core_dump_function f,
+static int x86_64_write_elf64_note(WriteCoreDumpFunction f,
CPUArchState *env, int id,
void *opaque)
{
@@ -144,7 +144,7 @@ static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUArchState *env,
prstatus->pid = id;
}
-static int x86_write_elf64_note(write_core_dump_function f, CPUArchState *env,
+static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUArchState *env,
int id, void *opaque)
{
x86_elf_prstatus prstatus;
@@ -179,18 +179,19 @@ static int x86_write_elf64_note(write_core_dump_function f, CPUArchState *env,
return 0;
}
-int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
- int cpuid, void *opaque)
+int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
+ int cpuid, void *opaque)
{
+ X86CPU *cpu = X86_CPU(cs);
int ret;
#ifdef TARGET_X86_64
bool lma = !!(first_cpu->hflags & HF_LMA_MASK);
if (lma) {
- ret = x86_64_write_elf64_note(f, env, cpuid, opaque);
+ ret = x86_64_write_elf64_note(f, &cpu->env, cpuid, opaque);
} else {
#endif
- ret = x86_write_elf64_note(f, env, cpuid, opaque);
+ ret = x86_write_elf64_note(f, &cpu->env, cpuid, opaque);
#ifdef TARGET_X86_64
}
#endif
@@ -198,9 +199,10 @@ int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
return ret;
}
-int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
- int cpuid, void *opaque)
+int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
+ int cpuid, void *opaque)
{
+ X86CPU *cpu = X86_CPU(cs);
x86_elf_prstatus prstatus;
Elf32_Nhdr *note;
char *buf;
@@ -208,7 +210,7 @@ int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
const char *name = "CORE";
int ret;
- x86_fill_elf_prstatus(&prstatus, env, cpuid);
+ x86_fill_elf_prstatus(&prstatus, &cpu->env, cpuid);
descsz = sizeof(x86_elf_prstatus);
note_size = ((sizeof(Elf32_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
(descsz + 3) / 4) * 4;
@@ -317,7 +319,7 @@ static void qemu_get_cpustate(QEMUCPUState *s, CPUArchState *env)
s->cr[4] = env->cr[4];
}
-static inline int cpu_write_qemu_note(write_core_dump_function f,
+static inline int cpu_write_qemu_note(WriteCoreDumpFunction f,
CPUArchState *env,
void *opaque,
int type)
@@ -370,16 +372,20 @@ static inline int cpu_write_qemu_note(write_core_dump_function f,
return 0;
}
-int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
- void *opaque)
+int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cs,
+ void *opaque)
{
- return cpu_write_qemu_note(f, env, opaque, 1);
+ X86CPU *cpu = X86_CPU(cs);
+
+ return cpu_write_qemu_note(f, &cpu->env, opaque, 1);
}
-int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
- void *opaque)
+int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cs,
+ void *opaque)
{
- return cpu_write_qemu_note(f, env, opaque, 0);
+ X86CPU *cpu = X86_CPU(cs);
+
+ return cpu_write_qemu_note(f, &cpu->env, opaque, 0);
}
int cpu_get_dump_info(ArchDumpInfo *info)
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index 08f9eb67b2..f890f1c912 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -86,4 +86,13 @@ extern const struct VMStateDescription vmstate_x86_cpu;
*/
void x86_cpu_do_interrupt(CPUState *cpu);
+int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, void *opaque);
+int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, void *opaque);
+int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+ void *opaque);
+int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+ void *opaque);
+
#endif
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index e2302d8b05..9f2adad805 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -41,9 +41,10 @@
#endif
#include "sysemu/sysemu.h"
+#include "hw/qdev-properties.h"
+#include "hw/cpu/icc_bus.h"
#ifndef CONFIG_USER_ONLY
#include "hw/xen/xen.h"
-#include "hw/sysbus.h"
#include "hw/i386/apic_internal.h"
#endif
@@ -349,20 +350,15 @@ static void add_flagname_to_bitmaps(const char *flagname,
typedef struct x86_def_t {
const char *name;
uint32_t level;
+ uint32_t xlevel;
+ uint32_t xlevel2;
/* vendor is zero-terminated, 12 character ASCII string */
char vendor[CPUID_VENDOR_SZ + 1];
int family;
int model;
int stepping;
- uint32_t features, ext_features, ext2_features, ext3_features;
- uint32_t kvm_features, svm_features;
- uint32_t xlevel;
+ FeatureWordArray features;
char model_id[48];
- /* Store the results of Centaur's CPUID instructions */
- uint32_t ext4_features;
- uint32_t xlevel2;
- /* The feature bits on CPUID[EAX=7,ECX=0].EBX */
- uint32_t cpuid_7_0_ebx_features;
} x86_def_t;
#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
@@ -423,13 +419,17 @@ static x86_def_t builtin_x86_defs[] = {
.family = 6,
.model = 2,
.stepping = 3,
- .features = PPRO_FEATURES |
+ .features[FEAT_1_EDX] =
+ PPRO_FEATURES |
CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
CPUID_PSE36,
- .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT,
- .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT,
+ .features[FEAT_8000_0001_EDX] =
+ (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
- .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
+ .features[FEAT_8000_0001_ECX] =
+ CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
.xlevel = 0x8000000A,
},
@@ -440,12 +440,15 @@ static x86_def_t builtin_x86_defs[] = {
.family = 16,
.model = 2,
.stepping = 3,
- .features = PPRO_FEATURES |
+ .features[FEAT_1_EDX] =
+ PPRO_FEATURES |
CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
CPUID_PSE36 | CPUID_VME | CPUID_HT,
- .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 |
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 |
CPUID_EXT_POPCNT,
- .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
+ .features[FEAT_8000_0001_EDX] =
+ (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP,
@@ -453,9 +456,11 @@ static x86_def_t builtin_x86_defs[] = {
CPUID_EXT3_CR8LEG,
CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
CPUID_EXT3_OSVW, CPUID_EXT3_IBS */
- .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
+ .features[FEAT_8000_0001_ECX] =
+ CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
- .svm_features = CPUID_SVM_NPT | CPUID_SVM_LBRV,
+ .features[FEAT_SVM] =
+ CPUID_SVM_NPT | CPUID_SVM_LBRV,
.xlevel = 0x8000001A,
.model_id = "AMD Phenom(tm) 9550 Quad-Core Processor"
},
@@ -466,15 +471,19 @@ static x86_def_t builtin_x86_defs[] = {
.family = 6,
.model = 15,
.stepping = 11,
- .features = PPRO_FEATURES |
+ .features[FEAT_1_EDX] =
+ PPRO_FEATURES |
CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
CPUID_PSE36 | CPUID_VME | CPUID_DTS | CPUID_ACPI | CPUID_SS |
CPUID_HT | CPUID_TM | CPUID_PBE,
- .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
CPUID_EXT_DTES64 | CPUID_EXT_DSCPL | CPUID_EXT_VMX | CPUID_EXT_EST |
CPUID_EXT_TM2 | CPUID_EXT_CX16 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
- .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
- .ext3_features = CPUID_EXT3_LAHF_LM,
+ .features[FEAT_8000_0001_EDX] =
+ CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
+ .features[FEAT_8000_0001_ECX] =
+ CPUID_EXT3_LAHF_LM,
.xlevel = 0x80000008,
.model_id = "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz",
},
@@ -486,19 +495,23 @@ static x86_def_t builtin_x86_defs[] = {
.model = 6,
.stepping = 1,
/* Missing: CPUID_VME, CPUID_HT */
- .features = PPRO_FEATURES |
+ .features[FEAT_1_EDX] =
+ PPRO_FEATURES |
CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
CPUID_PSE36,
/* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */
- .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16,
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_SSE3 | CPUID_EXT_CX16,
/* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */
- .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
+ .features[FEAT_8000_0001_EDX] =
+ (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
/* Missing: CPUID_EXT3_LAHF_LM, CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
CPUID_EXT3_CR8LEG, CPUID_EXT3_ABM, CPUID_EXT3_SSE4A,
CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */
- .ext3_features = 0,
+ .features[FEAT_8000_0001_ECX] =
+ 0,
.xlevel = 0x80000008,
.model_id = "Common KVM processor"
},
@@ -509,8 +522,10 @@ static x86_def_t builtin_x86_defs[] = {
.family = 6,
.model = 3,
.stepping = 3,
- .features = PPRO_FEATURES,
- .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
+ .features[FEAT_1_EDX] =
+ PPRO_FEATURES,
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
.xlevel = 0x80000004,
},
{
@@ -520,11 +535,15 @@ static x86_def_t builtin_x86_defs[] = {
.family = 15,
.model = 6,
.stepping = 1,
- .features = PPRO_FEATURES |
+ .features[FEAT_1_EDX] =
+ PPRO_FEATURES |
CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36,
- .ext_features = CPUID_EXT_SSE3,
- .ext2_features = PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES,
- .ext3_features = 0,
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_SSE3,
+ .features[FEAT_8000_0001_EDX] =
+ PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES,
+ .features[FEAT_8000_0001_ECX] =
+ 0,
.xlevel = 0x80000008,
.model_id = "Common 32-bit KVM processor"
},
@@ -535,12 +554,15 @@ static x86_def_t builtin_x86_defs[] = {
.family = 6,
.model = 14,
.stepping = 8,
- .features = PPRO_FEATURES | CPUID_VME |
+ .features[FEAT_1_EDX] =
+ PPRO_FEATURES | CPUID_VME |
CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_DTS | CPUID_ACPI |
CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
- .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_VMX |
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_VMX |
CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
- .ext2_features = CPUID_EXT2_NX,
+ .features[FEAT_8000_0001_EDX] =
+ CPUID_EXT2_NX,
.xlevel = 0x80000008,
.model_id = "Genuine Intel(R) CPU T2600 @ 2.16GHz",
},
@@ -551,7 +573,8 @@ static x86_def_t builtin_x86_defs[] = {
.family = 4,
.model = 0,
.stepping = 0,
- .features = I486_FEATURES,
+ .features[FEAT_1_EDX] =
+ I486_FEATURES,
.xlevel = 0,
},
{
@@ -561,7 +584,8 @@ static x86_def_t builtin_x86_defs[] = {
.family = 5,
.model = 4,
.stepping = 3,
- .features = PENTIUM_FEATURES,
+ .features[FEAT_1_EDX] =
+ PENTIUM_FEATURES,
.xlevel = 0,
},
{
@@ -571,7 +595,8 @@ static x86_def_t builtin_x86_defs[] = {
.family = 6,
.model = 5,
.stepping = 2,
- .features = PENTIUM2_FEATURES,
+ .features[FEAT_1_EDX] =
+ PENTIUM2_FEATURES,
.xlevel = 0,
},
{
@@ -581,7 +606,8 @@ static x86_def_t builtin_x86_defs[] = {
.family = 6,
.model = 7,
.stepping = 3,
- .features = PENTIUM3_FEATURES,
+ .features[FEAT_1_EDX] =
+ PENTIUM3_FEATURES,
.xlevel = 0,
},
{
@@ -591,9 +617,11 @@ static x86_def_t builtin_x86_defs[] = {
.family = 6,
.model = 2,
.stepping = 3,
- .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR |
+ .features[FEAT_1_EDX] =
+ PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR |
CPUID_MCA,
- .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
+ .features[FEAT_8000_0001_EDX] =
+ (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
.xlevel = 0x80000008,
},
@@ -605,15 +633,19 @@ static x86_def_t builtin_x86_defs[] = {
.family = 6,
.model = 28,
.stepping = 2,
- .features = PPRO_FEATURES |
+ .features[FEAT_1_EDX] =
+ PPRO_FEATURES |
CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME | CPUID_DTS |
CPUID_ACPI | CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
/* Some CPUs got no CPUID_SEP */
- .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
CPUID_EXT_DSCPL | CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR,
- .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
+ .features[FEAT_8000_0001_EDX] =
+ (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
CPUID_EXT2_NX,
- .ext3_features = CPUID_EXT3_LAHF_LM,
+ .features[FEAT_8000_0001_ECX] =
+ CPUID_EXT3_LAHF_LM,
.xlevel = 0x8000000A,
.model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz",
},
@@ -624,14 +656,18 @@ static x86_def_t builtin_x86_defs[] = {
.family = 6,
.model = 2,
.stepping = 3,
- .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+ .features[FEAT_1_EDX] =
+ CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
CPUID_DE | CPUID_FP87,
- .ext_features = CPUID_EXT_SSSE3 | CPUID_EXT_SSE3,
- .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
- .ext3_features = CPUID_EXT3_LAHF_LM,
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_SSSE3 | CPUID_EXT_SSE3,
+ .features[FEAT_8000_0001_EDX] =
+ CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
+ .features[FEAT_8000_0001_ECX] =
+ CPUID_EXT3_LAHF_LM,
.xlevel = 0x8000000A,
.model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)",
},
@@ -642,15 +678,19 @@ static x86_def_t builtin_x86_defs[] = {
.family = 6,
.model = 2,
.stepping = 3,
- .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+ .features[FEAT_1_EDX] =
+ CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
CPUID_DE | CPUID_FP87,
- .ext_features = CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
CPUID_EXT_SSE3,
- .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
- .ext3_features = CPUID_EXT3_LAHF_LM,
+ .features[FEAT_8000_0001_EDX] =
+ CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
+ .features[FEAT_8000_0001_ECX] =
+ CPUID_EXT3_LAHF_LM,
.xlevel = 0x8000000A,
.model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)",
},
@@ -661,15 +701,19 @@ static x86_def_t builtin_x86_defs[] = {
.family = 6,
.model = 2,
.stepping = 3,
- .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+ .features[FEAT_1_EDX] =
+ CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
CPUID_DE | CPUID_FP87,
- .ext_features = CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE3,
- .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
- .ext3_features = CPUID_EXT3_LAHF_LM,
+ .features[FEAT_8000_0001_EDX] =
+ CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
+ .features[FEAT_8000_0001_ECX] =
+ CPUID_EXT3_LAHF_LM,
.xlevel = 0x8000000A,
.model_id = "Intel Core i7 9xx (Nehalem Class Core i7)",
},
@@ -680,16 +724,20 @@ static x86_def_t builtin_x86_defs[] = {
.family = 6,
.model = 44,
.stepping = 1,
- .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+ .features[FEAT_1_EDX] =
+ CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
CPUID_DE | CPUID_FP87,
- .ext_features = CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 |
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 |
CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3,
- .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
- .ext3_features = CPUID_EXT3_LAHF_LM,
+ .features[FEAT_8000_0001_EDX] =
+ CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
+ .features[FEAT_8000_0001_ECX] =
+ CPUID_EXT3_LAHF_LM,
.xlevel = 0x8000000A,
.model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)",
},
@@ -700,19 +748,23 @@ static x86_def_t builtin_x86_defs[] = {
.family = 6,
.model = 42,
.stepping = 1,
- .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+ .features[FEAT_1_EDX] =
+ CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
CPUID_DE | CPUID_FP87,
- .ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_POPCNT |
CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ |
CPUID_EXT_SSE3,
- .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
+ .features[FEAT_8000_0001_EDX] =
+ CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
CPUID_EXT2_SYSCALL,
- .ext3_features = CPUID_EXT3_LAHF_LM,
+ .features[FEAT_8000_0001_ECX] =
+ CPUID_EXT3_LAHF_LM,
.xlevel = 0x8000000A,
.model_id = "Intel Xeon E312xx (Sandy Bridge)",
},
@@ -723,21 +775,26 @@ static x86_def_t builtin_x86_defs[] = {
.family = 6,
.model = 60,
.stepping = 1,
- .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+ .features[FEAT_1_EDX] =
+ CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
CPUID_DE | CPUID_FP87,
- .ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
CPUID_EXT_PCID,
- .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
+ .features[FEAT_8000_0001_EDX] =
+ CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
CPUID_EXT2_SYSCALL,
- .ext3_features = CPUID_EXT3_LAHF_LM,
- .cpuid_7_0_ebx_features = CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
+ .features[FEAT_8000_0001_ECX] =
+ CPUID_EXT3_LAHF_LM,
+ .features[FEAT_7_0_EBX] =
+ CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
CPUID_7_0_EBX_RTM,
@@ -751,13 +808,16 @@ static x86_def_t builtin_x86_defs[] = {
.family = 15,
.model = 6,
.stepping = 1,
- .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+ .features[FEAT_1_EDX] =
+ CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
CPUID_DE | CPUID_FP87,
- .ext_features = CPUID_EXT_SSE3,
- .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_SSE3,
+ .features[FEAT_8000_0001_EDX] =
+ CPUID_EXT2_LM | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
@@ -773,20 +833,24 @@ static x86_def_t builtin_x86_defs[] = {
.family = 15,
.model = 6,
.stepping = 1,
- .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+ .features[FEAT_1_EDX] =
+ CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
CPUID_DE | CPUID_FP87,
- .ext_features = CPUID_EXT_CX16 | CPUID_EXT_SSE3,
- .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR |
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_CX16 | CPUID_EXT_SSE3,
+ .features[FEAT_8000_0001_EDX] =
+ CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR |
CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 |
CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA |
CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL |
CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE |
CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE |
CPUID_EXT2_DE | CPUID_EXT2_FPU,
- .ext3_features = CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
+ .features[FEAT_8000_0001_ECX] =
+ CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
.xlevel = 0x80000008,
.model_id = "AMD Opteron 22xx (Gen 2 Class Opteron)",
},
@@ -797,21 +861,25 @@ static x86_def_t builtin_x86_defs[] = {
.family = 15,
.model = 6,
.stepping = 1,
- .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+ .features[FEAT_1_EDX] =
+ CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
CPUID_DE | CPUID_FP87,
- .ext_features = CPUID_EXT_POPCNT | CPUID_EXT_CX16 | CPUID_EXT_MONITOR |
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_POPCNT | CPUID_EXT_CX16 | CPUID_EXT_MONITOR |
CPUID_EXT_SSE3,
- .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR |
+ .features[FEAT_8000_0001_EDX] =
+ CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR |
CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 |
CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA |
CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL |
CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE |
CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE |
CPUID_EXT2_DE | CPUID_EXT2_FPU,
- .ext3_features = CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A |
+ .features[FEAT_8000_0001_ECX] =
+ CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A |
CPUID_EXT3_ABM | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
.xlevel = 0x80000008,
.model_id = "AMD Opteron 23xx (Gen 3 Class Opteron)",
@@ -823,23 +891,27 @@ static x86_def_t builtin_x86_defs[] = {
.family = 21,
.model = 1,
.stepping = 2,
- .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+ .features[FEAT_1_EDX] =
+ CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
CPUID_DE | CPUID_FP87,
- .ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ |
CPUID_EXT_SSE3,
- .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP |
+ .features[FEAT_8000_0001_EDX] =
+ CPUID_EXT2_LM | CPUID_EXT2_RDTSCP |
CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
- .ext3_features = CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
+ .features[FEAT_8000_0001_ECX] =
+ CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
CPUID_EXT3_LAHF_LM,
@@ -853,23 +925,27 @@ static x86_def_t builtin_x86_defs[] = {
.family = 21,
.model = 2,
.stepping = 0,
- .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+ .features[FEAT_1_EDX] =
+ CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
CPUID_DE | CPUID_FP87,
- .ext_features = CPUID_EXT_F16C | CPUID_EXT_AVX | CPUID_EXT_XSAVE |
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_F16C | CPUID_EXT_AVX | CPUID_EXT_XSAVE |
CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 |
CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_FMA |
CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3,
- .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP |
+ .features[FEAT_8000_0001_EDX] =
+ CPUID_EXT2_LM | CPUID_EXT2_RDTSCP |
CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
- .ext3_features = CPUID_EXT3_TBM | CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
+ .features[FEAT_8000_0001_ECX] =
+ CPUID_EXT3_TBM | CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
CPUID_EXT3_LAHF_LM,
@@ -918,20 +994,22 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def)
x86_cpu_def->stepping = eax & 0x0F;
x86_cpu_def->level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
- x86_cpu_def->features = kvm_arch_get_supported_cpuid(s, 0x1, 0, R_EDX);
- x86_cpu_def->ext_features = kvm_arch_get_supported_cpuid(s, 0x1, 0, R_ECX);
+ x86_cpu_def->features[FEAT_1_EDX] =
+ kvm_arch_get_supported_cpuid(s, 0x1, 0, R_EDX);
+ x86_cpu_def->features[FEAT_1_ECX] =
+ kvm_arch_get_supported_cpuid(s, 0x1, 0, R_ECX);
if (x86_cpu_def->level >= 7) {
- x86_cpu_def->cpuid_7_0_ebx_features =
+ x86_cpu_def->features[FEAT_7_0_EBX] =
kvm_arch_get_supported_cpuid(s, 0x7, 0, R_EBX);
} else {
- x86_cpu_def->cpuid_7_0_ebx_features = 0;
+ x86_cpu_def->features[FEAT_7_0_EBX] = 0;
}
x86_cpu_def->xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
- x86_cpu_def->ext2_features =
+ x86_cpu_def->features[FEAT_8000_0001_EDX] =
kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX);
- x86_cpu_def->ext3_features =
+ x86_cpu_def->features[FEAT_8000_0001_ECX] =
kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_ECX);
cpu_x86_fill_model_id(x86_cpu_def->model_id);
@@ -944,15 +1022,15 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def)
/* Support VIA max extended level */
x86_cpu_def->xlevel2 = eax;
host_cpuid(0xC0000001, 0, &eax, &ebx, &ecx, &edx);
- x86_cpu_def->ext4_features =
+ x86_cpu_def->features[FEAT_C000_0001_EDX] =
kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX);
}
}
/* Other KVM-specific feature fields: */
- x86_cpu_def->svm_features =
+ x86_cpu_def->features[FEAT_SVM] =
kvm_arch_get_supported_cpuid(s, 0x8000000A, 0, R_EDX);
- x86_cpu_def->kvm_features =
+ x86_cpu_def->features[FEAT_KVM] =
kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX);
#endif /* CONFIG_KVM */
@@ -989,21 +1067,29 @@ static int kvm_check_features_against_host(X86CPU *cpu)
uint32_t mask;
int rv, i;
struct model_features_t ft[] = {
- {&env->cpuid_features, &host_def.features,
+ {&env->features[FEAT_1_EDX],
+ &host_def.features[FEAT_1_EDX],
FEAT_1_EDX },
- {&env->cpuid_ext_features, &host_def.ext_features,
+ {&env->features[FEAT_1_ECX],
+ &host_def.features[FEAT_1_ECX],
FEAT_1_ECX },
- {&env->cpuid_ext2_features, &host_def.ext2_features,
+ {&env->features[FEAT_8000_0001_EDX],
+ &host_def.features[FEAT_8000_0001_EDX],
FEAT_8000_0001_EDX },
- {&env->cpuid_ext3_features, &host_def.ext3_features,
+ {&env->features[FEAT_8000_0001_ECX],
+ &host_def.features[FEAT_8000_0001_ECX],
FEAT_8000_0001_ECX },
- {&env->cpuid_ext4_features, &host_def.ext4_features,
+ {&env->features[FEAT_C000_0001_EDX],
+ &host_def.features[FEAT_C000_0001_EDX],
FEAT_C000_0001_EDX },
- {&env->cpuid_7_0_ebx_features, &host_def.cpuid_7_0_ebx_features,
+ {&env->features[FEAT_7_0_EBX],
+ &host_def.features[FEAT_7_0_EBX],
FEAT_7_0_EBX },
- {&env->cpuid_svm_features, &host_def.svm_features,
+ {&env->features[FEAT_SVM],
+ &host_def.features[FEAT_SVM],
FEAT_SVM },
- {&env->cpuid_kvm_features, &host_def.kvm_features,
+ {&env->features[FEAT_KVM],
+ &host_def.features[FEAT_KVM],
FEAT_KVM },
};
@@ -1271,6 +1357,50 @@ static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, void *opaque,
cpu->env.tsc_khz = value / 1000;
}
+static void x86_cpuid_get_apic_id(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ int64_t value = cpu->env.cpuid_apic_id;
+
+ visit_type_int(v, &value, name, errp);
+}
+
+static void x86_cpuid_set_apic_id(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ DeviceState *dev = DEVICE(obj);
+ const int64_t min = 0;
+ const int64_t max = UINT32_MAX;
+ Error *error = NULL;
+ int64_t value;
+
+ if (dev->realized) {
+ error_setg(errp, "Attempt to set property '%s' on '%s' after "
+ "it was realized", name, object_get_typename(obj));
+ return;
+ }
+
+ visit_type_int(v, &value, name, &error);
+ if (error) {
+ error_propagate(errp, error);
+ return;
+ }
+ if (value < min || value > max) {
+ error_setg(errp, "Property %s.%s doesn't take value %" PRId64
+ " (minimum: %" PRId64 ", maximum: %" PRId64 ")" ,
+ object_get_typename(obj), name, value, min, max);
+ return;
+ }
+
+ if ((value != cpu->env.cpuid_apic_id) && cpu_exists(value)) {
+ error_setg(errp, "CPU with APIC ID %" PRIi64 " exists", value);
+ return;
+ }
+ cpu->env.cpuid_apic_id = value;
+}
+
static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *name)
{
x86_def_t *def;
@@ -1307,6 +1437,16 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *name)
return -1;
}
+/* Convert all '_' in a feature string option name to '-', to make feature
+ * name conform to QOM property naming rule, which uses '-' instead of '_'.
+ */
+static inline void feat2prop(char *s)
+{
+ while ((s = strchr(s, '_'))) {
+ *s = '-';
+ }
+}
+
/* Parse "+feature,-feature,feature=foo" CPU feature string
*/
static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
@@ -1329,6 +1469,7 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
add_flagname_to_bitmaps(featurestr + 1, minus_features);
} else if ((val = strchr(featurestr, '='))) {
*val = 0; val++;
+ feat2prop(featurestr);
if (!strcmp(featurestr, "family")) {
object_property_parse(OBJECT(cpu), val, featurestr, errp);
} else if (!strcmp(featurestr, "model")) {
@@ -1355,9 +1496,9 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
object_property_parse(OBJECT(cpu), num, featurestr, errp);
} else if (!strcmp(featurestr, "vendor")) {
object_property_parse(OBJECT(cpu), val, featurestr, errp);
- } else if (!strcmp(featurestr, "model_id")) {
- object_property_parse(OBJECT(cpu), val, "model-id", errp);
- } else if (!strcmp(featurestr, "tsc_freq")) {
+ } else if (!strcmp(featurestr, "model-id")) {
+ object_property_parse(OBJECT(cpu), val, featurestr, errp);
+ } else if (!strcmp(featurestr, "tsc-freq")) {
int64_t tsc_freq;
char *err;
char num[32];
@@ -1370,7 +1511,7 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
}
snprintf(num, sizeof(num), "%" PRId64, tsc_freq);
object_property_parse(OBJECT(cpu), num, "tsc-frequency", errp);
- } else if (!strcmp(featurestr, "hv_spinlocks")) {
+ } else if (!strcmp(featurestr, "hv-spinlocks")) {
char *err;
numvalue = strtoul(val, &err, 0);
if (!*val || *err) {
@@ -1400,22 +1541,22 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
}
featurestr = strtok(NULL, ",");
}
- env->cpuid_features |= plus_features[FEAT_1_EDX];
- env->cpuid_ext_features |= plus_features[FEAT_1_ECX];
- env->cpuid_ext2_features |= plus_features[FEAT_8000_0001_EDX];
- env->cpuid_ext3_features |= plus_features[FEAT_8000_0001_ECX];
- env->cpuid_ext4_features |= plus_features[FEAT_C000_0001_EDX];
- env->cpuid_kvm_features |= plus_features[FEAT_KVM];
- env->cpuid_svm_features |= plus_features[FEAT_SVM];
- env->cpuid_7_0_ebx_features |= plus_features[FEAT_7_0_EBX];
- env->cpuid_features &= ~minus_features[FEAT_1_EDX];
- env->cpuid_ext_features &= ~minus_features[FEAT_1_ECX];
- env->cpuid_ext2_features &= ~minus_features[FEAT_8000_0001_EDX];
- env->cpuid_ext3_features &= ~minus_features[FEAT_8000_0001_ECX];
- env->cpuid_ext4_features &= ~minus_features[FEAT_C000_0001_EDX];
- env->cpuid_kvm_features &= ~minus_features[FEAT_KVM];
- env->cpuid_svm_features &= ~minus_features[FEAT_SVM];
- env->cpuid_7_0_ebx_features &= ~minus_features[FEAT_7_0_EBX];
+ env->features[FEAT_1_EDX] |= plus_features[FEAT_1_EDX];
+ env->features[FEAT_1_ECX] |= plus_features[FEAT_1_ECX];
+ env->features[FEAT_8000_0001_EDX] |= plus_features[FEAT_8000_0001_EDX];
+ env->features[FEAT_8000_0001_ECX] |= plus_features[FEAT_8000_0001_ECX];
+ env->features[FEAT_C000_0001_EDX] |= plus_features[FEAT_C000_0001_EDX];
+ env->features[FEAT_KVM] |= plus_features[FEAT_KVM];
+ env->features[FEAT_SVM] |= plus_features[FEAT_SVM];
+ env->features[FEAT_7_0_EBX] |= plus_features[FEAT_7_0_EBX];
+ env->features[FEAT_1_EDX] &= ~minus_features[FEAT_1_EDX];
+ env->features[FEAT_1_ECX] &= ~minus_features[FEAT_1_ECX];
+ env->features[FEAT_8000_0001_EDX] &= ~minus_features[FEAT_8000_0001_EDX];
+ env->features[FEAT_8000_0001_ECX] &= ~minus_features[FEAT_8000_0001_ECX];
+ env->features[FEAT_C000_0001_EDX] &= ~minus_features[FEAT_C000_0001_EDX];
+ env->features[FEAT_KVM] &= ~minus_features[FEAT_KVM];
+ env->features[FEAT_SVM] &= ~minus_features[FEAT_SVM];
+ env->features[FEAT_7_0_EBX] &= ~minus_features[FEAT_7_0_EBX];
out:
return;
@@ -1507,21 +1648,21 @@ static void filter_features_for_kvm(X86CPU *cpu)
CPUX86State *env = &cpu->env;
KVMState *s = kvm_state;
- env->cpuid_features &=
+ env->features[FEAT_1_EDX] &=
kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX);
- env->cpuid_ext_features &=
+ env->features[FEAT_1_ECX] &=
kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX);
- env->cpuid_ext2_features &=
+ env->features[FEAT_8000_0001_EDX] &=
kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX);
- env->cpuid_ext3_features &=
+ env->features[FEAT_8000_0001_ECX] &=
kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_ECX);
- env->cpuid_svm_features &=
+ env->features[FEAT_SVM] &=
kvm_arch_get_supported_cpuid(s, 0x8000000A, 0, R_EDX);
- env->cpuid_7_0_ebx_features &=
+ env->features[FEAT_7_0_EBX] &=
kvm_arch_get_supported_cpuid(s, 7, 0, R_EBX);
- env->cpuid_kvm_features &=
+ env->features[FEAT_KVM] &=
kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX);
- env->cpuid_ext4_features &=
+ env->features[FEAT_C000_0001_EDX] &=
kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX);
}
@@ -1540,30 +1681,31 @@ static void cpu_x86_register(X86CPU *cpu, const char *name, Error **errp)
}
if (kvm_enabled()) {
- def->kvm_features |= kvm_default_features;
+ def->features[FEAT_KVM] |= kvm_default_features;
}
- def->ext_features |= CPUID_EXT_HYPERVISOR;
+ def->features[FEAT_1_ECX] |= CPUID_EXT_HYPERVISOR;
object_property_set_str(OBJECT(cpu), def->vendor, "vendor", errp);
object_property_set_int(OBJECT(cpu), def->level, "level", errp);
object_property_set_int(OBJECT(cpu), def->family, "family", errp);
object_property_set_int(OBJECT(cpu), def->model, "model", errp);
object_property_set_int(OBJECT(cpu), def->stepping, "stepping", errp);
- env->cpuid_features = def->features;
- env->cpuid_ext_features = def->ext_features;
- env->cpuid_ext2_features = def->ext2_features;
- env->cpuid_ext3_features = def->ext3_features;
+ env->features[FEAT_1_EDX] = def->features[FEAT_1_EDX];
+ env->features[FEAT_1_ECX] = def->features[FEAT_1_ECX];
+ env->features[FEAT_8000_0001_EDX] = def->features[FEAT_8000_0001_EDX];
+ env->features[FEAT_8000_0001_ECX] = def->features[FEAT_8000_0001_ECX];
object_property_set_int(OBJECT(cpu), def->xlevel, "xlevel", errp);
- env->cpuid_kvm_features = def->kvm_features;
- env->cpuid_svm_features = def->svm_features;
- env->cpuid_ext4_features = def->ext4_features;
- env->cpuid_7_0_ebx_features = def->cpuid_7_0_ebx_features;
+ env->features[FEAT_KVM] = def->features[FEAT_KVM];
+ env->features[FEAT_SVM] = def->features[FEAT_SVM];
+ env->features[FEAT_C000_0001_EDX] = def->features[FEAT_C000_0001_EDX];
+ env->features[FEAT_7_0_EBX] = def->features[FEAT_7_0_EBX];
env->cpuid_xlevel2 = def->xlevel2;
object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp);
}
-X86CPU *cpu_x86_create(const char *cpu_model, Error **errp)
+X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge,
+ Error **errp)
{
X86CPU *cpu = NULL;
CPUX86State *env;
@@ -1580,6 +1722,14 @@ X86CPU *cpu_x86_create(const char *cpu_model, Error **errp)
features = model_pieces[1];
cpu = X86_CPU(object_new(TYPE_X86_CPU));
+#ifndef CONFIG_USER_ONLY
+ if (icc_bridge == NULL) {
+ error_setg(&error, "Invalid icc-bridge value");
+ goto out;
+ }
+ qdev_set_parent_bus(DEVICE(cpu), qdev_get_child_bus(icc_bridge, "icc"));
+ object_unref(OBJECT(cpu));
+#endif
env = &cpu->env;
env->cpu_model_str = cpu_model;
@@ -1604,7 +1754,7 @@ X86CPU *cpu_x86_init(const char *cpu_model)
Error *error = NULL;
X86CPU *cpu;
- cpu = cpu_x86_create(cpu_model, &error);
+ cpu = cpu_x86_create(cpu_model, NULL, &error);
if (error) {
goto out;
}
@@ -1627,7 +1777,7 @@ out:
void cpu_clear_apic_feature(CPUX86State *env)
{
- env->cpuid_features &= ~CPUID_APIC;
+ env->features[FEAT_1_EDX] &= ~CPUID_APIC;
}
#endif /* !CONFIG_USER_ONLY */
@@ -1702,8 +1852,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
case 1:
*eax = env->cpuid_version;
*ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
- *ecx = env->cpuid_ext_features;
- *edx = env->cpuid_features;
+ *ecx = env->features[FEAT_1_ECX];
+ *edx = env->features[FEAT_1_EDX];
if (cs->nr_cores * cs->nr_threads > 1) {
*ebx |= (cs->nr_cores * cs->nr_threads) << 16;
*edx |= 1 << 28; /* HTT bit */
@@ -1771,7 +1921,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
/* Structured Extended Feature Flags Enumeration Leaf */
if (count == 0) {
*eax = 0; /* Maximum ECX value for sub-leaves */
- *ebx = env->cpuid_7_0_ebx_features; /* Feature flags */
+ *ebx = env->features[FEAT_7_0_EBX]; /* Feature flags */
*ecx = 0; /* Reserved */
*edx = 0; /* Reserved */
} else {
@@ -1806,7 +1956,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
break;
case 0xD:
/* Processor Extended State */
- if (!(env->cpuid_ext_features & CPUID_EXT_XSAVE)) {
+ if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) {
*eax = 0;
*ebx = 0;
*ecx = 0;
@@ -1836,8 +1986,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
case 0x80000001:
*eax = env->cpuid_version;
*ebx = 0;
- *ecx = env->cpuid_ext3_features;
- *edx = env->cpuid_ext2_features;
+ *ecx = env->features[FEAT_8000_0001_ECX];
+ *edx = env->features[FEAT_8000_0001_EDX];
/* The Linux kernel checks for the CMPLegacy bit and
* discards multiple thread information if it is set.
@@ -1878,12 +2028,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
case 0x80000008:
/* virtual & phys address size in low 2 bytes. */
/* XXX: This value must match the one used in the MMU code. */
- if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
+ if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
/* 64 bit processor */
/* XXX: The physical address space is limited to 42 bits in exec.c. */
*eax = 0x00003028; /* 48 bits virtual, 40 bits physical */
} else {
- if (env->cpuid_features & CPUID_PSE36) {
+ if (env->features[FEAT_1_EDX] & CPUID_PSE36) {
*eax = 0x00000024; /* 36 bits physical */
} else {
*eax = 0x00000020; /* 32 bits physical */
@@ -1897,11 +2047,11 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
}
break;
case 0x8000000A:
- if (env->cpuid_ext3_features & CPUID_EXT3_SVM) {
+ if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
*eax = 0x00000001; /* SVM Revision */
*ebx = 0x00000010; /* nr of ASIDs */
*ecx = 0;
- *edx = env->cpuid_svm_features; /* optional features */
+ *edx = env->features[FEAT_SVM]; /* optional features */
} else {
*eax = 0;
*ebx = 0;
@@ -1920,7 +2070,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
*eax = env->cpuid_version;
*ebx = 0;
*ecx = 0;
- *edx = env->cpuid_ext4_features;
+ *edx = env->features[FEAT_C000_0001_EDX];
break;
case 0xC0000002:
case 0xC0000003:
@@ -2052,7 +2202,7 @@ static void mce_init(X86CPU *cpu)
unsigned int bank;
if (((cenv->cpuid_version >> 8) & 0xf) >= 6
- && (cenv->cpuid_features & (CPUID_MCE | CPUID_MCA)) ==
+ && (cenv->features[FEAT_1_EDX] & (CPUID_MCE | CPUID_MCA)) ==
(CPUID_MCE | CPUID_MCA)) {
cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF;
cenv->mcg_ctl = ~(uint64_t)0;
@@ -2066,6 +2216,7 @@ static void mce_init(X86CPU *cpu)
static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
{
CPUX86State *env = &cpu->env;
+ DeviceState *dev = DEVICE(cpu);
APICCommonState *apic;
const char *apic_type = "apic";
@@ -2075,7 +2226,7 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
apic_type = "xen-apic";
}
- env->apic_state = qdev_try_create(NULL, apic_type);
+ env->apic_state = qdev_try_create(qdev_get_parent_bus(dev), apic_type);
if (env->apic_state == NULL) {
error_setg(errp, "APIC device '%s' could not be created", apic_type);
return;
@@ -2092,7 +2243,6 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
{
CPUX86State *env = &cpu->env;
- static int apic_mapped;
if (env->apic_state == NULL) {
return;
@@ -2103,16 +2253,6 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
object_get_typename(OBJECT(env->apic_state)));
return;
}
-
- /* XXX: mapping more APICs at the same memory location */
- if (apic_mapped == 0) {
- /* NOTE: the APIC is directly connected to the CPU - it is not
- on the global memory bus. */
- /* XXX: what if the base changes? */
- sysbus_mmio_map_overlap(SYS_BUS_DEVICE(env->apic_state), 0,
- APIC_DEFAULT_ADDRESS, 0x1000);
- apic_mapped = 1;
- }
}
#else
static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
@@ -2127,7 +2267,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
CPUX86State *env = &cpu->env;
Error *local_err = NULL;
- if (env->cpuid_7_0_ebx_features && env->cpuid_level < 7) {
+ if (env->features[FEAT_7_0_EBX] && env->cpuid_level < 7) {
env->cpuid_level = 7;
}
@@ -2137,21 +2277,21 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
if (env->cpuid_vendor1 == CPUID_VENDOR_AMD_1 &&
env->cpuid_vendor2 == CPUID_VENDOR_AMD_2 &&
env->cpuid_vendor3 == CPUID_VENDOR_AMD_3) {
- env->cpuid_ext2_features &= ~CPUID_EXT2_AMD_ALIASES;
- env->cpuid_ext2_features |= (env->cpuid_features
+ env->features[FEAT_8000_0001_EDX] &= ~CPUID_EXT2_AMD_ALIASES;
+ env->features[FEAT_8000_0001_EDX] |= (env->features[FEAT_1_EDX]
& CPUID_EXT2_AMD_ALIASES);
}
if (!kvm_enabled()) {
- env->cpuid_features &= TCG_FEATURES;
- env->cpuid_ext_features &= TCG_EXT_FEATURES;
- env->cpuid_ext2_features &= (TCG_EXT2_FEATURES
+ env->features[FEAT_1_EDX] &= TCG_FEATURES;
+ env->features[FEAT_1_ECX] &= TCG_EXT_FEATURES;
+ env->features[FEAT_8000_0001_EDX] &= (TCG_EXT2_FEATURES
#ifdef TARGET_X86_64
| CPUID_EXT2_SYSCALL | CPUID_EXT2_LM
#endif
);
- env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
- env->cpuid_svm_features &= TCG_SVM_FEATURES;
+ env->features[FEAT_8000_0001_ECX] &= TCG_EXT3_FEATURES;
+ env->features[FEAT_SVM] &= TCG_SVM_FEATURES;
} else {
if (check_cpuid && kvm_check_features_against_host(cpu)
&& enforce_cpuid) {
@@ -2167,7 +2307,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
#ifndef CONFIG_USER_ONLY
qemu_register_reset(x86_cpu_machine_reset_cb, cpu);
- if (cpu->env.cpuid_features & CPUID_APIC || smp_cpus > 1) {
+ if (cpu->env.features[FEAT_1_EDX] & CPUID_APIC || smp_cpus > 1) {
x86_cpu_apic_create(cpu, &local_err);
if (local_err != NULL) {
goto out;
@@ -2259,6 +2399,9 @@ static void x86_cpu_initfn(Object *obj)
object_property_add(obj, "tsc-frequency", "int",
x86_cpuid_get_tsc_freq,
x86_cpuid_set_tsc_freq, NULL, NULL, NULL);
+ object_property_add(obj, "apic-id", "int",
+ x86_cpuid_get_apic_id,
+ x86_cpuid_set_apic_id, NULL, NULL, NULL);
env->cpuid_apic_id = x86_cpu_apic_id_from_index(cs->cpu_index);
@@ -2272,6 +2415,14 @@ static void x86_cpu_initfn(Object *obj)
}
}
+static int64_t x86_cpu_get_arch_id(CPUState *cs)
+{
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+
+ return env->cpuid_apic_id;
+}
+
static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
{
X86CPUClass *xcc = X86_CPU_CLASS(oc);
@@ -2280,12 +2431,21 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
xcc->parent_realize = dc->realize;
dc->realize = x86_cpu_realizefn;
+ dc->bus_type = TYPE_ICC_BUS;
xcc->parent_reset = cc->reset;
cc->reset = x86_cpu_reset;
cc->do_interrupt = x86_cpu_do_interrupt;
+#ifndef CONFIG_USER_ONLY
+ cc->write_elf64_note = x86_cpu_write_elf64_note;
+ cc->write_elf64_qemunote = x86_cpu_write_elf64_qemunote;
+ cc->write_elf32_note = x86_cpu_write_elf32_note;
+ cc->write_elf32_qemunote = x86_cpu_write_elf32_qemunote;
+#endif
cpu_class_set_vmsd(cc, &vmstate_x86_cpu);
+
+ cc->get_arch_id = x86_cpu_get_arch_id;
}
static const TypeInfo x86_cpu_type_info = {
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index a1614e8e50..3e2e9f6b72 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -836,22 +836,15 @@ typedef struct CPUX86State {
/* processor features (e.g. for CPUID insn) */
uint32_t cpuid_level;
+ uint32_t cpuid_xlevel;
+ uint32_t cpuid_xlevel2;
uint32_t cpuid_vendor1;
uint32_t cpuid_vendor2;
uint32_t cpuid_vendor3;
uint32_t cpuid_version;
- uint32_t cpuid_features;
- uint32_t cpuid_ext_features;
- uint32_t cpuid_xlevel;
+ FeatureWordArray features;
uint32_t cpuid_model[12];
- uint32_t cpuid_ext2_features;
- uint32_t cpuid_ext3_features;
uint32_t cpuid_apic_id;
- /* Store the results of Centaur's CPUID instructions */
- uint32_t cpuid_xlevel2;
- uint32_t cpuid_ext4_features;
- /* Flags from CPUID[EAX=7,ECX=0].EBX */
- uint32_t cpuid_7_0_ebx_features;
/* MTRRs */
uint64_t mtrr_fixed[11];
@@ -865,8 +858,6 @@ typedef struct CPUX86State {
uint8_t soft_interrupt;
uint8_t has_error_code;
uint32_t sipi_vector;
- uint32_t cpuid_kvm_features;
- uint32_t cpuid_svm_features;
bool tsc_valid;
int tsc_khz;
void *kvm_xsave_buf;
@@ -897,7 +888,8 @@ typedef struct CPUX86State {
#include "cpu-qom.h"
X86CPU *cpu_x86_init(const char *cpu_model);
-X86CPU *cpu_x86_create(const char *cpu_model, Error **errp);
+X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge,
+ Error **errp);
int cpu_x86_exec(CPUX86State *s);
void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf);
void x86_cpudef_setup(void);
@@ -1270,5 +1262,6 @@ uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index);
void enable_compat_apic_id_mode(void);
#define APIC_DEFAULT_ADDRESS 0xfee00000
+#define APIC_SPACE_SIZE 0x100000
#endif /* CPU_I386_H */
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 282494fcad..158710a89c 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -463,7 +463,7 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
tlb_flush(env, 1);
}
/* SSE handling */
- if (!(env->cpuid_features & CPUID_SSE)) {
+ if (!(env->features[FEAT_1_EDX] & CPUID_SSE)) {
new_cr4 &= ~CR4_OSFXSR_MASK;
}
env->hflags &= ~HF_OSFXSR_MASK;
@@ -471,7 +471,7 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
env->hflags |= HF_OSFXSR_MASK;
}
- if (!(env->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)) {
+ if (!(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_SMAP)) {
new_cr4 &= ~CR4_SMAP_MASK;
}
env->hflags &= ~HF_SMAP_MASK;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0e7cc8113f..9ffb6ca018 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -454,7 +454,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
c = &cpuid_data.entries[cpuid_i++];
memset(c, 0, sizeof(*c));
c->function = KVM_CPUID_FEATURES;
- c->eax = env->cpuid_kvm_features;
+ c->eax = env->features[FEAT_KVM];
if (hyperv_enabled()) {
memcpy(signature, "Hv#1\0\0\0\0\0\0\0\0", 12);
@@ -613,7 +613,8 @@ int kvm_arch_init_vcpu(CPUState *cs)
cpuid_data.cpuid.nent = cpuid_i;
if (((env->cpuid_version >> 8)&0xF) >= 6
- && (env->cpuid_features&(CPUID_MCE|CPUID_MCA)) == (CPUID_MCE|CPUID_MCA)
+ && (env->features[FEAT_1_EDX] & (CPUID_MCE | CPUID_MCA)) ==
+ (CPUID_MCE | CPUID_MCA)
&& kvm_check_extension(cs->kvm_state, KVM_CAP_MCE) > 0) {
uint64_t mcg_cap;
int banks;
diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c
index dfbc07b7f8..ec834fc67e 100644
--- a/target-i386/misc_helper.c
+++ b/target-i386/misc_helper.c
@@ -291,22 +291,22 @@ void helper_wrmsr(CPUX86State *env)
uint64_t update_mask;
update_mask = 0;
- if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL) {
+ if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) {
update_mask |= MSR_EFER_SCE;
}
- if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
+ if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
update_mask |= MSR_EFER_LME;
}
- if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR) {
+ if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
update_mask |= MSR_EFER_FFXSR;
}
- if (env->cpuid_ext2_features & CPUID_EXT2_NX) {
+ if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) {
update_mask |= MSR_EFER_NXE;
}
- if (env->cpuid_ext3_features & CPUID_EXT3_SVM) {
+ if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
update_mask |= MSR_EFER_SVME;
}
- if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR) {
+ if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
update_mask |= MSR_EFER_FFXSR;
}
cpu_load_efer(env, (env->efer & ~update_mask) |
@@ -513,7 +513,7 @@ void helper_rdmsr(CPUX86State *env)
val = env->mtrr_deftype;
break;
case MSR_MTRRcap:
- if (env->cpuid_features & CPUID_MTRR) {
+ if (env->features[FEAT_1_EDX] & CPUID_MTRR) {
val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT |
MSR_MTRRcap_WC_SUPPORTED;
} else {
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 40f891da14..524a0b480e 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -8290,11 +8290,11 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
if (flags & HF_SOFTMMU_MASK) {
dc->mem_index = (cpu_mmu_index(env) + 1) << 2;
}
- dc->cpuid_features = env->cpuid_features;
- dc->cpuid_ext_features = env->cpuid_ext_features;
- dc->cpuid_ext2_features = env->cpuid_ext2_features;
- dc->cpuid_ext3_features = env->cpuid_ext3_features;
- dc->cpuid_7_0_ebx_features = env->cpuid_7_0_ebx_features;
+ dc->cpuid_features = env->features[FEAT_1_EDX];
+ dc->cpuid_ext_features = env->features[FEAT_1_ECX];
+ dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
+ dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
+ dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
#ifdef TARGET_X86_64
dc->lma = (flags >> HF_LMA_SHIFT) & 1;
dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
diff --git a/vl.c b/vl.c
index b5a547e7e5..6e6225f09b 100644
--- a/vl.c
+++ b/vl.c
@@ -267,7 +267,6 @@ static NotifierList machine_init_done_notifiers =
NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers);
static bool tcg_allowed = true;
-bool kvm_allowed;
bool xen_allowed;
uint32_t xen_domid;
enum xen_mode xen_mode = XEN_EMULATE;
@@ -4416,7 +4415,6 @@ int main(int argc, char **argv, char **envp)
os_setup_post();
- resume_all_vcpus();
main_loop();
bdrv_close_all();
pause_all_vcpus();