From c4cfef5e8a6371aa5e6577f2b980315c2dc46cfb Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 23 Apr 2013 10:29:35 +0200 Subject: [PATCH 01/29] cpu: Make kvm-stub.o available outside softmmu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It will provide stubs for *-user targets once softmmu-specific calls are attempted from common CPU code. Signed-off-by: Igor Mammedov Reviewed-by: Eduardo Habkost Signed-off-by: Andreas Färber --- Makefile.target | 14 +++++++------- include/sysemu/kvm.h | 6 +++--- kvm-stub.c | 7 ++++++- 3 files changed, 16 insertions(+), 11 deletions(-) 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/include/sysemu/kvm.h b/include/sysemu/kvm.h index 75bd7d9934..2bc1f6ba80 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -144,11 +144,11 @@ 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); - -void kvm_flush_coalesced_mmio_buffer(void); #endif +void kvm_setup_guest_memory(void *start, size_t size); +void kvm_flush_coalesced_mmio_buffer(void); + int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr, target_ulong len, int type); int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr, diff --git a/kvm-stub.c b/kvm-stub.c index 5f52186ae7..b22837828e 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -12,10 +12,13 @@ #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; @@ -111,6 +114,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 +138,4 @@ int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq) { return -ENOSYS; } +#endif From 13eed94ed5617b98e657163490584dc2a0cc4b32 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 23 Apr 2013 10:29:36 +0200 Subject: [PATCH 02/29] cpu: Call cpu_synchronize_post_init() from DeviceClass::realize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If hotplugged, synchronize CPU state to KVM. Signed-off-by: Igor Mammedov Reviewed-by: Eduardo Habkost Signed-off-by: Andreas Färber --- include/sysemu/kvm.h | 20 ++++++++++---------- kvm-all.c | 1 + kvm-stub.c | 1 + qom/cpu.c | 6 ++++++ vl.c | 1 - 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 2bc1f6ba80..9735c1dee6 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -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/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 b22837828e..b2c8f9b02d 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -25,6 +25,7 @@ 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) { diff --git a/qom/cpu.c b/qom/cpu.c index e242dcbeb4..66f7c00c29 100644 --- a/qom/cpu.c +++ b/qom/cpu.c @@ -20,6 +20,7 @@ #include "qom/cpu.h" #include "qemu-common.h" +#include "sysemu/kvm.h" void cpu_reset_interrupt(CPUState *cpu, int mask) { @@ -57,6 +58,11 @@ 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); + } } static void cpu_class_init(ObjectClass *klass, void *data) diff --git a/vl.c b/vl.c index b5a547e7e5..41c367db0a 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; From 2993683b0fde0f836777c945baaddcaa5937903f Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 23 Apr 2013 10:29:37 +0200 Subject: [PATCH 03/29] cpu: Introduce cpu_resume(), for single CPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also add a stub for it, to make possible to use it in qom/cpu.c, which is shared with user emulators. Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- cpus.c | 11 ++++++++--- include/qom/cpu.h | 7 +++++++ stubs/Makefile.objs | 1 + stubs/cpus.c | 5 +++++ 4 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 stubs/cpus.c diff --git a/cpus.c b/cpus.c index 5a98a370df..1d8876157c 100644 --- a/cpus.c +++ b/cpus.c @@ -993,6 +993,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 +1007,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/include/qom/cpu.h b/include/qom/cpu.h index 3664a1b631..ac93dcec66 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -256,5 +256,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/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) +{ +} From 6afb4721f3e45da727110470a61aafcd6682395e Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 23 Apr 2013 10:29:38 +0200 Subject: [PATCH 04/29] cpu: Resume CPU from DeviceClass::realize() if hot-plugged MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- qom/cpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/qom/cpu.c b/qom/cpu.c index 66f7c00c29..b91213e6b1 100644 --- a/qom/cpu.c +++ b/qom/cpu.c @@ -62,6 +62,7 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp) if (dev->hotplugged) { cpu_synchronize_post_init(cpu); + cpu_resume(cpu); } } From 066e9b2710be887f435e0e899fa71f1f4314f702 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 23 Apr 2013 10:29:39 +0200 Subject: [PATCH 05/29] cpu: Introduce CPU hot-plug notifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hot-add CPU event will be distributed to acpi_piix4 and rtc_cmos. Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- include/sysemu/sysemu.h | 3 +++ qom/cpu.c | 12 ++++++++++++ 2 files changed, 15 insertions(+) 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/qom/cpu.c b/qom/cpu.c index b91213e6b1..34fa8054b2 100644 --- a/qom/cpu.c +++ b/qom/cpu.c @@ -21,6 +21,17 @@ #include "qom/cpu.h" #include "qemu-common.h" #include "sysemu/kvm.h" +#include "qemu/notify.h" +#include "sysemu/sysemu.h" + +/* 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) { @@ -62,6 +73,7 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp) if (dev->hotplugged) { cpu_synchronize_post_init(cpu); + notifier_list_notify(&cpu_added_notifiers, dev); cpu_resume(cpu); } } From b8b7456d6ab7edb450ae5ec6473d3cd9a80412f4 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 23 Apr 2013 10:29:40 +0200 Subject: [PATCH 06/29] pc: Update rtc_cmos on CPU hot-plug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It provides updated currently available CPUs count to BIOS on reboot. Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- hw/i386/pc.c | 20 ++++++++++++++++++++ hw/timer/mc146818rtc.c | 7 +++++++ include/hw/timer/mc146818rtc.h | 1 + 3 files changed, 28 insertions(+) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 29d2703330..867add7ab0 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -338,6 +338,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 +361,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 +400,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)) { 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/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 */ From 997395d3888fcde6ce41535a8208d7aa919d824b Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 23 Apr 2013 10:29:41 +0200 Subject: [PATCH 07/29] cpu: Introduce get_arch_id() method and override it for X86CPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit get_arch_id() adds possibility for generic code to get a guest-visible CPU ID without accessing CPUArchState. If derived classes don't override it, it will return cpu_index. Override it on target-i386 in X86CPU to return the APIC ID. Signed-off-by: Igor Mammedov Reviewed-by: Eduardo Habkost Reviewed-by: liguang Acked-by: Michael S. Tsirkin Signed-off-by: Andreas Färber --- include/qom/cpu.h | 2 ++ qom/cpu.c | 6 ++++++ target-i386/cpu.c | 10 ++++++++++ 3 files changed, 18 insertions(+) diff --git a/include/qom/cpu.h b/include/qom/cpu.h index ac93dcec66..1b4de17415 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -45,6 +45,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,6 +59,7 @@ typedef struct CPUClass { void (*reset)(CPUState *cpu); void (*do_interrupt)(CPUState *cpu); + int64_t (*get_arch_id)(CPUState *cpu); const struct VMStateDescription *vmsd; } CPUClass; diff --git a/qom/cpu.c b/qom/cpu.c index 34fa8054b2..9a4457ba1b 100644 --- a/qom/cpu.c +++ b/qom/cpu.c @@ -78,6 +78,11 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp) } } +static int64_t cpu_common_get_arch_id(CPUState *cpu) +{ + return cpu->cpu_index; +} + static void cpu_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -85,6 +90,7 @@ 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; dc->realize = cpu_common_realizefn; dc->no_user = 1; } diff --git a/target-i386/cpu.c b/target-i386/cpu.c index e2302d8b05..f34ba23dad 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2272,6 +2272,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); @@ -2286,6 +2294,8 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) cc->do_interrupt = x86_cpu_do_interrupt; cpu_class_set_vmsd(cc, &vmstate_x86_cpu); + + cc->get_arch_id = x86_cpu_get_arch_id; } static const TypeInfo x86_cpu_type_info = { From d6b9e0d60cc511eca210834428bb74508cff3d33 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 24 Apr 2013 22:58:04 +0200 Subject: [PATCH 08/29] cpu: Add qemu_for_each_cpu() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wrapper to avoid open-coded loops and to make CPUState iteration independent of CPUArchState. Signed-off-by: Michael S. Tsirkin Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- exec.c | 10 ++++++++++ include/qom/cpu.h | 9 +++++++++ 2 files changed, 19 insertions(+) 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/include/qom/cpu.h b/include/qom/cpu.h index 1b4de17415..a28e5ffee2 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -215,6 +215,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. From a37677c32bb313f5ba48aaf89f81cdc10c23ce56 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 23 Apr 2013 10:29:42 +0200 Subject: [PATCH 09/29] cpus: Use qemu_for_each_cpu() in TCG thread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces an open-coded loop and hides unused CPUArchState. Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- cpus.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/cpus.c b/cpus.c index 1d8876157c..a2d92c7a88 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 */ From 69e5ff067ae724155fd7465119ee6db5721288b6 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Thu, 25 Apr 2013 16:05:24 +0200 Subject: [PATCH 10/29] cpu: Add helper cpu_exists(), to check if CPU with specified id exists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- include/qom/cpu.h | 10 ++++++++++ qom/cpu.c | 26 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/include/qom/cpu.h b/include/qom/cpu.h index a28e5ffee2..e54579bd4f 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -234,6 +234,16 @@ void qemu_for_each_cpu(void (*func)(CPUState *cpu, 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); diff --git a/qom/cpu.c b/qom/cpu.c index 9a4457ba1b..3dc8208a73 100644 --- a/qom/cpu.c +++ b/qom/cpu.c @@ -24,6 +24,32 @@ #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); From b8622725cf0196f672f272922b0941dc8ba1c408 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Thu, 25 Apr 2013 16:05:25 +0200 Subject: [PATCH 11/29] acpi_piix4: Add infrastructure to send CPU hot-plug GPE to guest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * introduce processor status bitmask visible to guest at 0xaf00 addr, where ACPI asl code expects it * set bit corresponding to APIC ID in processor status bitmask on receiving CPU hot-plug notification * trigger CPU hot-plug SCI, to notify guest about CPU hot-plug event Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- docs/specs/acpi_cpu_hotplug.txt | 22 ++++++++ hw/acpi/piix4.c | 90 ++++++++++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 docs/specs/acpi_cpu_hotplug.txt 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/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) From 72ac2e876ddc6158f5b6d5f758d4e38c436010ed Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Apr 2013 18:04:32 +0200 Subject: [PATCH 12/29] target-i386: Introduce feat2prop() for CPU properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helper replaces '_' with '-' in a uniform way. As a side effect, even custom mappings must use '-' now. Signed-off-by: Igor Mammedov [AF: Split off; operate on NUL-terminated string rather than '=' delimiter] Signed-off-by: Andreas Färber --- target-i386/cpu.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index f34ba23dad..697848da42 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1307,6 +1307,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 +1339,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 +1366,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 +1381,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) { From 310509304e1a83c1926471f1984c1cbf7d813631 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Thu, 25 Apr 2013 16:05:26 +0200 Subject: [PATCH 13/29] target-i386: Introduce apic-id CPU property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The property is used from board level to set APIC ID for CPUs it creates. Do so in a new pc_new_cpu() helper, to be reused for hot-plug. Signed-off-by: Igor Mammedov Reviewed-by: Eduardo Habkost Signed-off-by: Andreas Färber --- hw/i386/pc.c | 29 ++++++++++++++++++++++++++++- target-i386/cpu.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 867add7ab0..656817322e 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -894,9 +894,33 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } } +static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id, Error **errp) +{ + X86CPU *cpu; + Error *local_err = NULL; + + cpu = cpu_x86_create(cpu_model, 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; +} + void pc_cpus_init(const char *cpu_model) { int i; + Error *error = NULL; /* init CPUs */ if (cpu_model == NULL) { @@ -908,7 +932,10 @@ void pc_cpus_init(const char *cpu_model) } for (i = 0; i < smp_cpus; i++) { - if (!cpu_x86_init(cpu_model)) { + pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i), &error); + if (error) { + fprintf(stderr, "%s\n", error_get_pretty(error)); + error_free(error); exit(1); } } diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 697848da42..f1cecc0904 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1271,6 +1271,43 @@ 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); + const int64_t min = 0; + const int64_t max = UINT32_MAX; + Error *error = NULL; + int64_t value; + + 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; @@ -2270,6 +2307,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); From 8d6d4980c9421f3b9d1800dbc320da6a0bf754bd Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Apr 2013 19:51:52 +0200 Subject: [PATCH 14/29] target-i386: Do not allow to set apic-id once CPU is realized MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Reviewed-by: Eduardo Habkost Signed-off-by: Andreas Färber --- target-i386/cpu.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index f1cecc0904..0d9493d1cc 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1284,11 +1284,18 @@ 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); From baaeda08ff34ad17150b50a6f52d0faec9f3db36 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Thu, 25 Apr 2013 16:05:29 +0200 Subject: [PATCH 15/29] target-i386: Replace MSI_SPACE_SIZE with APIC_SPACE_SIZE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Put APIC_SPACE_SIZE in a public header so that it can be reused elsewhere later. Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- hw/i386/kvm/apic.c | 2 +- hw/intc/apic.c | 2 +- hw/xen/xen_apic.c | 2 +- include/hw/i386/apic_internal.h | 2 -- target-i386/cpu.h | 1 + 5 files changed, 4 insertions(+), 5 deletions(-) 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/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/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/i386/apic_internal.h b/include/hw/i386/apic_internal.h index 578241f861..aac62902b7 100644 --- a/include/hw/i386/apic_internal.h +++ b/include/hw/i386/apic_internal.h @@ -66,8 +66,6 @@ #define MAX_APICS 255 -#define MSI_SPACE_SIZE 0x100000 - typedef struct APICCommonState APICCommonState; #define TYPE_APIC_COMMON "apic-common" diff --git a/target-i386/cpu.h b/target-i386/cpu.h index a1614e8e50..ab151d5414 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1270,5 +1270,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 */ From 5f8df3ce6e0a057ec23cea74b6e629e59e085ac4 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Thu, 25 Apr 2013 16:05:30 +0200 Subject: [PATCH 16/29] kvmvapic: Make dependency on sysbus.h explicit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allows kvmvapic to compile if sysbus.h is removed from apic_internal.h, from which it is indirectly included. sysbus.h will be removed from apic_internal.h after converting APICs to ICCDevice. Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- hw/i386/kvmvapic.c | 1 + 1 file changed, 1 insertion(+) 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 From c72bf468259935a80ea185f2cbe807c3da9c1bbd Mon Sep 17 00:00:00 2001 From: Jens Freimann Date: Fri, 19 Apr 2013 16:45:06 +0200 Subject: [PATCH 17/29] cpu: Move cpu_write_elfXX_note() functions to CPUState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert cpu_write_elfXX_note() functions to CPUClass methods and pass CPUState as argument. Update target-i386 accordingly. Signed-off-by: Jens Freimann [AF: Retain stubs as CPUClass' default method implementation; style changes] Signed-off-by: Andreas Färber --- dump-stub.c | 28 ------------------ dump.c | 8 +++--- include/qom/cpu.h | 49 ++++++++++++++++++++++++++++++++ include/sysemu/dump.h | 9 ------ qom/cpu.c | 63 +++++++++++++++++++++++++++++++++++++++++ target-i386/arch_dump.c | 38 ++++++++++++++----------- target-i386/cpu-qom.h | 9 ++++++ target-i386/cpu.c | 6 ++++ 8 files changed, 153 insertions(+), 57 deletions(-) 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/include/qom/cpu.h b/include/qom/cpu.h index e54579bd4f..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 @@ -62,6 +64,14 @@ typedef struct CPUClass { 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; @@ -127,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: 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/qom/cpu.c b/qom/cpu.c index 3dc8208a73..04aefbb956 100644 --- a/qom/cpu.c +++ b/qom/cpu.c @@ -64,6 +64,65 @@ 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); @@ -117,6 +176,10 @@ 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/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 0d9493d1cc..40d51be9f2 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2351,6 +2351,12 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) 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; From f0513d2c0156799e0c75a108ab9a049eea4f9607 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 29 Apr 2013 17:02:50 +0200 Subject: [PATCH 18/29] target-i386: Introduce ICC bus/device/bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provides a hotpluggable bus for APIC and CPU. * icc-bridge will serve as a parent for icc-bus and provide mmio mapping services to child icc-devices. * icc-device will replace SysBusDevice as a parent of APIC and IOAPIC devices. Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- MAINTAINERS | 6 ++ default-configs/i386-softmmu.mak | 1 + default-configs/x86_64-softmmu.mak | 1 + hw/cpu/Makefile.objs | 1 + hw/cpu/icc_bus.c | 109 +++++++++++++++++++++++++++++ hw/i386/pc_piix.c | 7 ++ hw/i386/pc_q35.c | 7 ++ include/hw/cpu/icc_bus.h | 79 +++++++++++++++++++++ 8 files changed, 211 insertions(+) create mode 100644 hw/cpu/icc_bus.c create mode 100644 include/hw/cpu/icc_bus.h 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 +S: Supported +F: include/hw/cpu/icc_bus.h +F: hw/cpu/icc_bus.c + Device Tree M: Peter Crosthwaite M: Alexander Graf 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/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..3ac8eebbdf --- /dev/null +++ b/hw/cpu/icc_bus.c @@ -0,0 +1,109 @@ +/* icc_bus.c + * emulate x86 ICC (Interrupt Controller Communications) bus + * + * Copyright (c) 2013 Red Hat, Inc + * + * Authors: + * Igor Mammedov + * + * 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 + */ +#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; +} ICCBridgeState; + +#define ICC_BRIGDE(obj) OBJECT_CHECK(ICCBridgeState, (obj), TYPE_ICC_BRIDGE) + +static void icc_bridge_init(Object *obj) +{ + ICCBridgeState *s = ICC_BRIGDE(obj); + + qbus_create_inplace(&s->icc_bus, TYPE_ICC_BUS, DEVICE(s), "icc"); +} + +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/pc_piix.c b/hw/i386/pc_piix.c index 852d63ba2e..0ce3fc206b 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,8 +88,13 @@ static void pc_init1(MemoryRegion *system_memory, MemoryRegion *ram_memory; MemoryRegion *pci_memory; MemoryRegion *rom_memory; + DeviceState *icc_bridge; void *fw_cfg = NULL; + 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); pc_acpi_init("acpi-dsdt.aml"); @@ -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]); diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index d094041462..a6ba809ed3 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,6 +76,11 @@ static void pc_q35_init(QEMUMachineInitArgs *args) int i; ICH9LPCState *ich9_lpc; PCIDevice *ahci; + DeviceState *icc_bridge; + + 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); pc_acpi_init("q35-acpi-dsdt.aml"); @@ -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]); diff --git a/include/hw/cpu/icc_bus.h b/include/hw/cpu/icc_bus.h new file mode 100644 index 0000000000..d728a7de3e --- /dev/null +++ b/include/hw/cpu/icc_bus.h @@ -0,0 +1,79 @@ +/* icc_bus.h + * emulate x86 ICC (Interrupt Controller Communications) bus + * + * Copyright (c) 2013 Red Hat, Inc + * + * Authors: + * Igor Mammedov + * + * 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 + */ +#ifndef ICC_BUS_H +#define ICC_BUS_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 >*/ +} 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 From 62fc403f11523169eb4264de31279745f48e3ecc Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 29 Apr 2013 18:54:13 +0200 Subject: [PATCH 19/29] target-i386: Attach ICC bus to CPU on its creation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X86CPU should have parent bus so it could provide bus for child APIC. Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- hw/i386/pc.c | 10 ++++++---- hw/i386/pc_piix.c | 2 +- hw/i386/pc_q35.c | 2 +- include/hw/i386/pc.h | 2 +- target-i386/cpu.c | 15 +++++++++++++-- target-i386/cpu.h | 3 ++- 6 files changed, 24 insertions(+), 10 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 656817322e..c4c4e35251 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -894,12 +894,13 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } } -static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id, Error **errp) +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, errp); + cpu = cpu_x86_create(cpu_model, icc_bridge, errp); if (!cpu) { return cpu; } @@ -917,7 +918,7 @@ static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id, Error **errp) return cpu; } -void pc_cpus_init(const char *cpu_model) +void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) { int i; Error *error = NULL; @@ -932,7 +933,8 @@ void pc_cpus_init(const char *cpu_model) } for (i = 0; i < smp_cpus; i++) { - pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i), &error); + 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); diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 0ce3fc206b..251e18f9a3 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -95,7 +95,7 @@ static void pc_init1(MemoryRegion *system_memory, object_property_add_child(qdev_get_machine(), "icc-bridge", OBJECT(icc_bridge), NULL); - pc_cpus_init(cpu_model); + pc_cpus_init(cpu_model, icc_bridge); pc_acpi_init("acpi-dsdt.aml"); if (kvmclock_enabled) { diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index a6ba809ed3..f46295b490 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -82,7 +82,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args) object_property_add_child(qdev_get_machine(), "icc-bridge", OBJECT(icc_bridge), NULL); - pc_cpus_init(cpu_model); + pc_cpus_init(cpu_model, icc_bridge); pc_acpi_init("q35-acpi-dsdt.aml"); kvmclock_create(); diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index dd6bc249bf..d0bc97281f 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -78,7 +78,7 @@ 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_acpi_init(const char *default_dsdt); void *pc_memory_init(MemoryRegion *system_memory, const char *kernel_filename, diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 40d51be9f2..a165bcf0a7 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -41,6 +41,7 @@ #endif #include "sysemu/sysemu.h" +#include "hw/cpu/icc_bus.h" #ifndef CONFIG_USER_ONLY #include "hw/xen/xen.h" #include "hw/sysbus.h" @@ -1618,7 +1619,8 @@ static void cpu_x86_register(X86CPU *cpu, const char *name, Error **errp) 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; @@ -1635,6 +1637,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; @@ -1659,7 +1669,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; } @@ -2346,6 +2356,7 @@ 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; diff --git a/target-i386/cpu.h b/target-i386/cpu.h index ab151d5414..f193752e5e 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -897,7 +897,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); From 53a89e262bd3e97b2da3afec0a60e5466770ae8c Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 29 Apr 2013 19:03:01 +0200 Subject: [PATCH 20/29] target-i386: Move APIC to ICC bus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It allows APIC to be hotplugged. * map APIC's mmio at board level if it is present * do not register mmio region for each APIC, since only one is used/mapped Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- hw/cpu/icc_bus.c | 10 ++++++++++ hw/i386/pc.c | 13 +++++++++++-- hw/intc/apic_common.c | 18 ++++++++++++------ include/hw/cpu/icc_bus.h | 3 +++ include/hw/i386/apic_internal.h | 6 +++--- target-i386/cpu.c | 16 +++------------- 6 files changed, 42 insertions(+), 24 deletions(-) diff --git a/hw/cpu/icc_bus.c b/hw/cpu/icc_bus.c index 3ac8eebbdf..73a1dc985f 100644 --- a/hw/cpu/icc_bus.c +++ b/hw/cpu/icc_bus.c @@ -80,6 +80,7 @@ typedef struct ICCBridgeState { /*< public >*/ ICCBus icc_bus; + MemoryRegion apic_container; } ICCBridgeState; #define ICC_BRIGDE(obj) OBJECT_CHECK(ICCBridgeState, (obj), TYPE_ICC_BRIDGE) @@ -87,8 +88,17 @@ typedef struct ICCBridgeState { 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 = { diff --git a/hw/i386/pc.c b/hw/i386/pc.c index c4c4e35251..28f958dee6 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -53,6 +53,7 @@ #include "qemu/bitmap.h" #include "qemu/config-file.h" #include "hw/acpi/acpi.h" +#include "hw/cpu/icc_bus.h" /* debug PC/ISA interrupts */ //#define DEBUG_IRQ @@ -921,6 +922,7 @@ static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id, void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) { int i; + X86CPU *cpu = NULL; Error *error = NULL; /* init CPUs */ @@ -933,14 +935,21 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) } for (i = 0; i < smp_cpus; i++) { - pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i), - icc_bridge, &error); + 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/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/include/hw/cpu/icc_bus.h b/include/hw/cpu/icc_bus.h index d728a7de3e..b5500708dc 100644 --- a/include/hw/cpu/icc_bus.h +++ b/include/hw/cpu/icc_bus.h @@ -22,6 +22,7 @@ #ifndef ICC_BUS_H #define ICC_BUS_H +#include "exec/memory.h" #include "hw/qdev-core.h" #define TYPE_ICC_BUS "icc-bus" @@ -37,6 +38,8 @@ typedef struct ICCBus { /*< private >*/ BusState parent_obj; /*< public >*/ + + MemoryRegion *apic_address_space; } ICCBus; #define ICC_BUS(obj) OBJECT_CHECK(ICCBus, (obj), TYPE_ICC_BUS) diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h index aac62902b7..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 */ @@ -78,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); @@ -92,7 +92,7 @@ typedef struct APICCommonClass } APICCommonClass; struct APICCommonState { - SysBusDevice busdev; + ICCDevice busdev; MemoryRegion io_memory; X86CPU *cpu; diff --git a/target-i386/cpu.c b/target-i386/cpu.c index a165bcf0a7..bba41fec69 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -41,10 +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 @@ -2131,6 +2131,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"; @@ -2140,7 +2141,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; @@ -2157,7 +2158,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; @@ -2168,16 +2168,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) From b4fc7b4326112538e0dbdc7fd019652ba8cc3281 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 30 Apr 2013 15:41:24 +0200 Subject: [PATCH 21/29] Add hot_add_cpu hook to QEMUMachine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hook should be set by machines that implement CPU hot-add via cpu-add QMP command. Signed-off-by: Igor Mammedov Reviewed-by: Eduardo Habkost Signed-off-by: Andreas Färber --- include/hw/boards.h | 3 +++ 1 file changed, 3 insertions(+) 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, From 69ca3ea5e192251f27510554611bcff6f036a00b Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 30 Apr 2013 15:41:25 +0200 Subject: [PATCH 22/29] QMP: Add cpu-add command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds "cpu-add id=xxx" QMP command. cpu-add's "id" argument is a CPU number in a range [0..max-cpus) Example QMP command: -> { "execute": "cpu-add", "arguments": { "id": 2 } } <- { "return": {} } Signed-off-by: Igor Mammedov Acked-by: Luiz Capitulino Reviewed-by: Eric Blake Reviewed-by: Eduardo Habkost Signed-off-by: Andreas Färber --- qapi-schema.json | 13 +++++++++++++ qmp-commands.hx | 23 +++++++++++++++++++++++ qmp.c | 10 ++++++++++ 3 files changed, 46 insertions(+) diff --git a/qapi-schema.json b/qapi-schema.json index 65be8f4f37..7797400666 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1389,6 +1389,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: # diff --git a/qmp-commands.hx b/qmp-commands.hx index 0e891323c7..ed99eb80e0 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -382,6 +382,29 @@ Example: 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 { 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 */ From c649983b582687bbdb4019e308f015913e31065e Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 30 Apr 2013 18:00:53 +0200 Subject: [PATCH 23/29] pc: Implement QEMUMachine::hot_add_cpu hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Reviewed-by: Eduardo Habkost Signed-off-by: Andreas Färber --- hw/i386/pc.c | 26 ++++++++++++++++++++++++++ hw/i386/pc_piix.c | 1 + hw/i386/pc_q35.c | 1 + include/hw/i386/pc.h | 1 + 4 files changed, 29 insertions(+) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 28f958dee6..197d218715 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -54,6 +54,7 @@ #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 @@ -919,6 +920,30 @@ static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id, 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; @@ -933,6 +958,7 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) cpu_model = "qemu32"; #endif } + current_cpu_model = cpu_model; for (i = 0; i < smp_cpus; i++) { cpu = pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i), diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 251e18f9a3..fe52e5f94b 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -335,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 f46295b490..52511e2b69 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -220,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/include/hw/i386/pc.h b/include/hw/i386/pc.h index d0bc97281f..41869e56e9 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -79,6 +79,7 @@ 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, 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, From 90e4b0c3de2b3927e71f23d95c3c27d60e5c89cc Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Mon, 22 Apr 2013 16:00:12 -0300 Subject: [PATCH 24/29] target-i386: Group together level, xlevel, xlevel2 fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consolidate level, xlevel, xlevel2 fields in x86_def_t and CPUX86State. Signed-off-by: Eduardo Habkost Reviewed-by: Igor Mammedov Signed-off-by: Andreas Färber --- target-i386/cpu.c | 4 ++-- target-i386/cpu.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index bba41fec69..081b5796e3 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -350,6 +350,8 @@ 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; @@ -357,11 +359,9 @@ typedef struct x86_def_t { int stepping; uint32_t features, ext_features, ext2_features, ext3_features; uint32_t kvm_features, svm_features; - uint32_t xlevel; 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; diff --git a/target-i386/cpu.h b/target-i386/cpu.h index f193752e5e..5d16428360 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -836,19 +836,19 @@ 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; 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; From fc7a504c0126b16aa2bd50d92584e9cc08f636a3 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Mon, 22 Apr 2013 16:00:13 -0300 Subject: [PATCH 25/29] target-i386/kvm.c: Code formatting changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add appropriate spaces around operators, and break line where it needs to be broken to allow feature-words array to be introduced without having too-long lines. Signed-off-by: Eduardo Habkost Reviewed-by: Igor Mammedov Signed-off-by: Andreas Färber --- target-i386/kvm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 0e7cc8113f..03d3059f94 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -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->cpuid_features & (CPUID_MCE | CPUID_MCA)) == + (CPUID_MCE | CPUID_MCA) && kvm_check_extension(cs->kvm_state, KVM_CAP_MCE) > 0) { uint64_t mcg_cap; int banks; From 27861ecc47cf9dc35961ac901e26abbd898c377c Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Mon, 22 Apr 2013 16:00:14 -0300 Subject: [PATCH 26/29] target-i386: Break CPUID feature definition lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Break lines on kvm_check_features_against_host(), kvm_cpu_fill_host(), and builtin_x86_defs, so they don't get too long once the *_features fields are replaced by an array. Signed-off-by: Eduardo Habkost Reviewed-by: Igor Mammedov Signed-off-by: Andreas Färber --- target-i386/cpu.c | 270 ++++++++++++++++++++++++++++++---------------- 1 file changed, 180 insertions(+), 90 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 081b5796e3..424e7c2e70 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -424,13 +424,17 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 2, .stepping = 3, - .features = PPRO_FEATURES | + .features = + 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) | + .ext_features = + CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT, + .ext2_features = + (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, - .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | + .ext3_features = + CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A, .xlevel = 0x8000000A, }, @@ -441,12 +445,15 @@ static x86_def_t builtin_x86_defs[] = { .family = 16, .model = 2, .stepping = 3, - .features = PPRO_FEATURES | + .features = + 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 | + .ext_features = + CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 | CPUID_EXT_POPCNT, - .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | + .ext2_features = + (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, @@ -454,9 +461,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 | + .ext3_features = + CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A, - .svm_features = CPUID_SVM_NPT | CPUID_SVM_LBRV, + .svm_features = + CPUID_SVM_NPT | CPUID_SVM_LBRV, .xlevel = 0x8000001A, .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor" }, @@ -467,15 +476,19 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 15, .stepping = 11, - .features = PPRO_FEATURES | + .features = + 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 | + .ext_features = + 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, + .ext2_features = + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .ext3_features = + CPUID_EXT3_LAHF_LM, .xlevel = 0x80000008, .model_id = "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz", }, @@ -487,19 +500,23 @@ static x86_def_t builtin_x86_defs[] = { .model = 6, .stepping = 1, /* Missing: CPUID_VME, CPUID_HT */ - .features = PPRO_FEATURES | + .features = + 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, + .ext_features = + CPUID_EXT_SSE3 | CPUID_EXT_CX16, /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */ - .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | + .ext2_features = + (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, + .ext3_features = + 0, .xlevel = 0x80000008, .model_id = "Common KVM processor" }, @@ -510,8 +527,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 = + PPRO_FEATURES, + .ext_features = + CPUID_EXT_SSE3 | CPUID_EXT_POPCNT, .xlevel = 0x80000004, }, { @@ -521,11 +540,15 @@ static x86_def_t builtin_x86_defs[] = { .family = 15, .model = 6, .stepping = 1, - .features = PPRO_FEATURES | + .features = + 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, + .ext_features = + CPUID_EXT_SSE3, + .ext2_features = + PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES, + .ext3_features = + 0, .xlevel = 0x80000008, .model_id = "Common 32-bit KVM processor" }, @@ -536,12 +559,15 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 14, .stepping = 8, - .features = PPRO_FEATURES | CPUID_VME | + .features = + 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 | + .ext_features = + 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, + .ext2_features = + CPUID_EXT2_NX, .xlevel = 0x80000008, .model_id = "Genuine Intel(R) CPU T2600 @ 2.16GHz", }, @@ -552,7 +578,8 @@ static x86_def_t builtin_x86_defs[] = { .family = 4, .model = 0, .stepping = 0, - .features = I486_FEATURES, + .features = + I486_FEATURES, .xlevel = 0, }, { @@ -562,7 +589,8 @@ static x86_def_t builtin_x86_defs[] = { .family = 5, .model = 4, .stepping = 3, - .features = PENTIUM_FEATURES, + .features = + PENTIUM_FEATURES, .xlevel = 0, }, { @@ -572,7 +600,8 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 5, .stepping = 2, - .features = PENTIUM2_FEATURES, + .features = + PENTIUM2_FEATURES, .xlevel = 0, }, { @@ -582,7 +611,8 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 7, .stepping = 3, - .features = PENTIUM3_FEATURES, + .features = + PENTIUM3_FEATURES, .xlevel = 0, }, { @@ -592,9 +622,11 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 2, .stepping = 3, - .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | + .features = + PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA, - .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | + .ext2_features = + (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT, .xlevel = 0x80000008, }, @@ -606,15 +638,19 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 28, .stepping = 2, - .features = PPRO_FEATURES | + .features = + 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 | + .ext_features = + 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) | + .ext2_features = + (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | CPUID_EXT2_NX, - .ext3_features = CPUID_EXT3_LAHF_LM, + .ext3_features = + CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz", }, @@ -625,14 +661,18 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 2, .stepping = 3, - .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + .features = + 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, + .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, .xlevel = 0x8000000A, .model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)", }, @@ -643,15 +683,19 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 2, .stepping = 3, - .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + .features = + 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 | + .ext_features = + 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, + .ext2_features = + CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, + .ext3_features = + CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)", }, @@ -662,15 +706,19 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 2, .stepping = 3, - .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + .features = + 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 | + .ext_features = + 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, + .ext2_features = + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .ext3_features = + CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)", }, @@ -681,16 +729,20 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 44, .stepping = 1, - .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + .features = + 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 | + .ext_features = + 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, + .ext2_features = + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .ext3_features = + CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)", }, @@ -701,19 +753,23 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 42, .stepping = 1, - .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + .features = + 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 | + .ext_features = + 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 | + .ext2_features = + CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, - .ext3_features = CPUID_EXT3_LAHF_LM, + .ext3_features = + CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Intel Xeon E312xx (Sandy Bridge)", }, @@ -724,21 +780,26 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 60, .stepping = 1, - .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + .features = + 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 | + .ext_features = + 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 | + .ext2_features = + 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 | + .ext3_features = + CPUID_EXT3_LAHF_LM, + .cpuid_7_0_ebx_features = + 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, @@ -752,13 +813,16 @@ static x86_def_t builtin_x86_defs[] = { .family = 15, .model = 6, .stepping = 1, - .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + .features = + 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 | + .ext_features = + CPUID_EXT_SSE3, + .ext2_features = + 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 | @@ -774,20 +838,24 @@ static x86_def_t builtin_x86_defs[] = { .family = 15, .model = 6, .stepping = 1, - .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + .features = + 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 | + .ext_features = + CPUID_EXT_CX16 | CPUID_EXT_SSE3, + .ext2_features = + 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, + .ext3_features = + CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM, .xlevel = 0x80000008, .model_id = "AMD Opteron 22xx (Gen 2 Class Opteron)", }, @@ -798,21 +866,25 @@ static x86_def_t builtin_x86_defs[] = { .family = 15, .model = 6, .stepping = 1, - .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + .features = + 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 | + .ext_features = + CPUID_EXT_POPCNT | CPUID_EXT_CX16 | CPUID_EXT_MONITOR | CPUID_EXT_SSE3, - .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR | + .ext2_features = + 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 | + .ext3_features = + 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)", @@ -824,23 +896,27 @@ static x86_def_t builtin_x86_defs[] = { .family = 21, .model = 1, .stepping = 2, - .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + .features = + 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 | + .ext_features = + 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 | + .ext2_features = + 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 | + .ext3_features = + 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, @@ -854,23 +930,27 @@ static x86_def_t builtin_x86_defs[] = { .family = 21, .model = 2, .stepping = 0, - .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + .features = + 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 | + .ext_features = + 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 | + .ext2_features = + 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 | + .ext3_features = + 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, @@ -919,8 +999,10 @@ 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 = + 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); if (x86_cpu_def->level >= 7) { x86_cpu_def->cpuid_7_0_ebx_features = @@ -990,21 +1072,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->cpuid_features, + &host_def.features, FEAT_1_EDX }, - {&env->cpuid_ext_features, &host_def.ext_features, + {&env->cpuid_ext_features, + &host_def.ext_features, FEAT_1_ECX }, - {&env->cpuid_ext2_features, &host_def.ext2_features, + {&env->cpuid_ext2_features, + &host_def.ext2_features, FEAT_8000_0001_EDX }, - {&env->cpuid_ext3_features, &host_def.ext3_features, + {&env->cpuid_ext3_features, + &host_def.ext3_features, FEAT_8000_0001_ECX }, - {&env->cpuid_ext4_features, &host_def.ext4_features, + {&env->cpuid_ext4_features, + &host_def.ext4_features, FEAT_C000_0001_EDX }, - {&env->cpuid_7_0_ebx_features, &host_def.cpuid_7_0_ebx_features, + {&env->cpuid_7_0_ebx_features, + &host_def.cpuid_7_0_ebx_features, FEAT_7_0_EBX }, - {&env->cpuid_svm_features, &host_def.svm_features, + {&env->cpuid_svm_features, + &host_def.svm_features, FEAT_SVM }, - {&env->cpuid_kvm_features, &host_def.kvm_features, + {&env->cpuid_kvm_features, + &host_def.kvm_features, FEAT_KVM }, }; From 0514ef2fbb3882afe410ba7800c79fd0ef5dbf00 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Mon, 22 Apr 2013 16:00:15 -0300 Subject: [PATCH 27/29] target-i386: Replace cpuid_*features fields with a feature word array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This replaces the feature-bit fields on both X86CPU and x86_def_t structs with an array. With this, we will be able to simplify code that simply does the same operation on all feature words (e.g. kvm_check_features_against_host(), filter_features_for_kvm(), add_flagname_to_bitmaps(), CPU feature-bit property lookup/registration, and the proposed "feature-words" property) The following field replacements were made on X86CPU and x86_def_t: (cpuid_)features -> features[FEAT_1_EDX] (cpuid_)ext_features -> features[FEAT_1_ECX] (cpuid_)ext2_features -> features[FEAT_8000_0001_EDX] (cpuid_)ext3_features -> features[FEAT_8000_0001_ECX] (cpuid_)ext4_features -> features[FEAT_C000_0001_EDX] (cpuid_)kvm_features -> features[FEAT_KVM] (cpuid_)svm_features -> features[FEAT_SVM] (cpuid_)7_0_ebx_features -> features[FEAT_7_0_EBX] Signed-off-by: Eduardo Habkost Reviewed-by: Igor Mammedov Signed-off-by: Andreas Färber --- bsd-user/elfload.c | 2 +- bsd-user/main.c | 4 +- hw/i386/kvm/clock.c | 2 +- linux-user/elfload.c | 2 +- linux-user/main.c | 4 +- target-i386/cpu.c | 329 +++++++++++++++++++------------------- target-i386/cpu.h | 11 +- target-i386/helper.c | 4 +- target-i386/kvm.c | 4 +- target-i386/misc_helper.c | 14 +- target-i386/translate.c | 10 +- 11 files changed, 186 insertions(+), 200 deletions(-) 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/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/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/target-i386/cpu.c b/target-i386/cpu.c index 424e7c2e70..9f2adad805 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -357,13 +357,8 @@ typedef struct x86_def_t { int family; int model; int stepping; - uint32_t features, ext_features, ext2_features, ext3_features; - uint32_t kvm_features, svm_features; + FeatureWordArray features; char model_id[48]; - /* Store the results of Centaur's CPUID instructions */ - uint32_t ext4_features; - /* 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) @@ -424,16 +419,16 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 2, .stepping = 3, - .features = + .features[FEAT_1_EDX] = PPRO_FEATURES | CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36, - .ext_features = + .features[FEAT_1_ECX] = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT, - .ext2_features = + .features[FEAT_8000_0001_EDX] = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, - .ext3_features = + .features[FEAT_8000_0001_ECX] = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A, .xlevel = 0x8000000A, @@ -445,14 +440,14 @@ static x86_def_t builtin_x86_defs[] = { .family = 16, .model = 2, .stepping = 3, - .features = + .features[FEAT_1_EDX] = PPRO_FEATURES | CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36 | CPUID_VME | CPUID_HT, - .ext_features = + .features[FEAT_1_ECX] = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 | CPUID_EXT_POPCNT, - .ext2_features = + .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 | @@ -461,10 +456,10 @@ static x86_def_t builtin_x86_defs[] = { CPUID_EXT3_CR8LEG, CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH, CPUID_EXT3_OSVW, CPUID_EXT3_IBS */ - .ext3_features = + .features[FEAT_8000_0001_ECX] = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A, - .svm_features = + .features[FEAT_SVM] = CPUID_SVM_NPT | CPUID_SVM_LBRV, .xlevel = 0x8000001A, .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor" @@ -476,18 +471,18 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 15, .stepping = 11, - .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 = + .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 = + .features[FEAT_8000_0001_EDX] = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, - .ext3_features = + .features[FEAT_8000_0001_ECX] = CPUID_EXT3_LAHF_LM, .xlevel = 0x80000008, .model_id = "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz", @@ -500,22 +495,22 @@ static x86_def_t builtin_x86_defs[] = { .model = 6, .stepping = 1, /* Missing: CPUID_VME, CPUID_HT */ - .features = + .features[FEAT_1_EDX] = PPRO_FEATURES | CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36, /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */ - .ext_features = + .features[FEAT_1_ECX] = CPUID_EXT_SSE3 | CPUID_EXT_CX16, /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */ - .ext2_features = + .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 = + .features[FEAT_8000_0001_ECX] = 0, .xlevel = 0x80000008, .model_id = "Common KVM processor" @@ -527,9 +522,9 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 3, .stepping = 3, - .features = + .features[FEAT_1_EDX] = PPRO_FEATURES, - .ext_features = + .features[FEAT_1_ECX] = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT, .xlevel = 0x80000004, }, @@ -540,14 +535,14 @@ static x86_def_t builtin_x86_defs[] = { .family = 15, .model = 6, .stepping = 1, - .features = + .features[FEAT_1_EDX] = PPRO_FEATURES | CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36, - .ext_features = + .features[FEAT_1_ECX] = CPUID_EXT_SSE3, - .ext2_features = + .features[FEAT_8000_0001_EDX] = PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES, - .ext3_features = + .features[FEAT_8000_0001_ECX] = 0, .xlevel = 0x80000008, .model_id = "Common 32-bit KVM processor" @@ -559,14 +554,14 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 14, .stepping = 8, - .features = + .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 = + .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 = + .features[FEAT_8000_0001_EDX] = CPUID_EXT2_NX, .xlevel = 0x80000008, .model_id = "Genuine Intel(R) CPU T2600 @ 2.16GHz", @@ -578,7 +573,7 @@ static x86_def_t builtin_x86_defs[] = { .family = 4, .model = 0, .stepping = 0, - .features = + .features[FEAT_1_EDX] = I486_FEATURES, .xlevel = 0, }, @@ -589,7 +584,7 @@ static x86_def_t builtin_x86_defs[] = { .family = 5, .model = 4, .stepping = 3, - .features = + .features[FEAT_1_EDX] = PENTIUM_FEATURES, .xlevel = 0, }, @@ -600,7 +595,7 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 5, .stepping = 2, - .features = + .features[FEAT_1_EDX] = PENTIUM2_FEATURES, .xlevel = 0, }, @@ -611,7 +606,7 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 7, .stepping = 3, - .features = + .features[FEAT_1_EDX] = PENTIUM3_FEATURES, .xlevel = 0, }, @@ -622,10 +617,10 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 2, .stepping = 3, - .features = + .features[FEAT_1_EDX] = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA, - .ext2_features = + .features[FEAT_8000_0001_EDX] = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT, .xlevel = 0x80000008, @@ -638,18 +633,18 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 28, .stepping = 2, - .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 = + .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 = + .features[FEAT_8000_0001_EDX] = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | CPUID_EXT2_NX, - .ext3_features = + .features[FEAT_8000_0001_ECX] = CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz", @@ -661,17 +656,17 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 2, .stepping = 3, - .features = + .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 = + .features[FEAT_1_ECX] = CPUID_EXT_SSSE3 | CPUID_EXT_SSE3, - .ext2_features = + .features[FEAT_8000_0001_EDX] = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, - .ext3_features = + .features[FEAT_8000_0001_ECX] = CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)", @@ -683,18 +678,18 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 2, .stepping = 3, - .features = + .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 = + .features[FEAT_1_ECX] = CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE3, - .ext2_features = + .features[FEAT_8000_0001_EDX] = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, - .ext3_features = + .features[FEAT_8000_0001_ECX] = CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)", @@ -706,18 +701,18 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 2, .stepping = 3, - .features = + .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 = + .features[FEAT_1_ECX] = CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE3, - .ext2_features = + .features[FEAT_8000_0001_EDX] = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, - .ext3_features = + .features[FEAT_8000_0001_ECX] = CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)", @@ -729,19 +724,19 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 44, .stepping = 1, - .features = + .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 = + .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 = + .features[FEAT_8000_0001_EDX] = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, - .ext3_features = + .features[FEAT_8000_0001_ECX] = CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)", @@ -753,22 +748,22 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 42, .stepping = 1, - .features = + .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 = + .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 = + .features[FEAT_8000_0001_EDX] = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, - .ext3_features = + .features[FEAT_8000_0001_ECX] = CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Intel Xeon E312xx (Sandy Bridge)", @@ -780,25 +775,25 @@ static x86_def_t builtin_x86_defs[] = { .family = 6, .model = 60, .stepping = 1, - .features = + .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 = + .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 = + .features[FEAT_8000_0001_EDX] = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, - .ext3_features = + .features[FEAT_8000_0001_ECX] = CPUID_EXT3_LAHF_LM, - .cpuid_7_0_ebx_features = + .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 | @@ -813,15 +808,15 @@ static x86_def_t builtin_x86_defs[] = { .family = 15, .model = 6, .stepping = 1, - .features = + .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 = + .features[FEAT_1_ECX] = CPUID_EXT_SSE3, - .ext2_features = + .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 | @@ -838,15 +833,15 @@ static x86_def_t builtin_x86_defs[] = { .family = 15, .model = 6, .stepping = 1, - .features = + .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 = + .features[FEAT_1_ECX] = CPUID_EXT_CX16 | CPUID_EXT_SSE3, - .ext2_features = + .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 | @@ -854,7 +849,7 @@ static x86_def_t builtin_x86_defs[] = { 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 = + .features[FEAT_8000_0001_ECX] = CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM, .xlevel = 0x80000008, .model_id = "AMD Opteron 22xx (Gen 2 Class Opteron)", @@ -866,16 +861,16 @@ static x86_def_t builtin_x86_defs[] = { .family = 15, .model = 6, .stepping = 1, - .features = + .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 = + .features[FEAT_1_ECX] = CPUID_EXT_POPCNT | CPUID_EXT_CX16 | CPUID_EXT_MONITOR | CPUID_EXT_SSE3, - .ext2_features = + .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 | @@ -883,7 +878,7 @@ static x86_def_t builtin_x86_defs[] = { 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 = + .features[FEAT_8000_0001_ECX] = CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM, .xlevel = 0x80000008, @@ -896,18 +891,18 @@ static x86_def_t builtin_x86_defs[] = { .family = 21, .model = 1, .stepping = 2, - .features = + .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 = + .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 = + .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 | @@ -915,7 +910,7 @@ static x86_def_t builtin_x86_defs[] = { 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 = + .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 | @@ -930,18 +925,18 @@ static x86_def_t builtin_x86_defs[] = { .family = 21, .model = 2, .stepping = 0, - .features = + .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 = + .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 = + .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 | @@ -949,7 +944,7 @@ static x86_def_t builtin_x86_defs[] = { 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 = + .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 | @@ -999,22 +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 = + x86_cpu_def->features[FEAT_1_EDX] = kvm_arch_get_supported_cpuid(s, 0x1, 0, R_EDX); - x86_cpu_def->ext_features = + 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); @@ -1027,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 */ @@ -1072,29 +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 }, }; @@ -1546,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; @@ -1653,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); } @@ -1686,24 +1681,24 @@ 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); @@ -1782,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 */ @@ -1857,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 */ @@ -1926,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 { @@ -1961,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; @@ -1991,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. @@ -2033,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 */ @@ -2052,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; @@ -2075,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: @@ -2207,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; @@ -2272,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; } @@ -2282,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) { @@ -2312,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; diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 5d16428360..3e2e9f6b72 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -842,16 +842,9 @@ typedef struct CPUX86State { uint32_t cpuid_vendor2; uint32_t cpuid_vendor3; uint32_t cpuid_version; - uint32_t cpuid_features; - uint32_t cpuid_ext_features; + 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_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; 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 03d3059f94..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,7 @@ 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)) == + && (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; 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; From 1085819368e8693f08307e72f0082d759f67ef03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 2 May 2013 11:22:05 +0200 Subject: [PATCH 28/29] cpus: Fix pausing TCG CPUs while in vCPU thread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to a preceding while loop, no CPU would've been put into stopped state. Reinitialize the variable. This fixes commit d798e97456658ea7605303b7c69b04ec7df95c10 (Allow to use pause_all_vcpus from VCPU context) for non-KVM case. While at it, change a 0 to false, amending commit 4fdeee7cd4c8f90ef765537b9346a195d9483ab5 (cpu: Move stop field to CPUState). Reviewed-by: Jan Kiszka Signed-off-by: Andreas Färber --- cpus.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpus.c b/cpus.c index a2d92c7a88..c232265cd2 100644 --- a/cpus.c +++ b/cpus.c @@ -974,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; } From e7bdf659c16e1cefd61f53648503d8c060668d6b Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 20 Aug 2012 20:11:36 +0200 Subject: [PATCH 29/29] Drop redundant resume_all_vcpus() from main() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VCPUs are either resumed directly via vm_start(), after the incoming migration is done, or when a continue command is issued. We don't need the explicit resume before entering main_loop(). Signed-off-by: Jan Kiszka Signed-off-by: Andreas Färber --- vl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/vl.c b/vl.c index 41c367db0a..6e6225f09b 100644 --- a/vl.c +++ b/vl.c @@ -4415,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();