From 0e3bd56294230ad0ee20fce587879c29a83a0d8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 17 Mar 2015 17:46:36 +0100 Subject: [PATCH 1/5] pc: Ensure non-zero CPU ref count after attaching to ICC bus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Setting the parent bus of a device increases its ref count, which we ultimately want to level out. However it is only safe to do so after the last reference to the device in local code, as qom-set or similar operations might decrease the ref count. Therefore move the object_unref() from pc_new_cpu() into its callers. The APIC operations on the last CPU in pc_cpus_init() are still potentially insecure, but that is beyond the scope of this code movement. Signed-off-by: Andreas Färber Acked-by: Michael S. Tsirkin Reviewed-by: Eduardo Habkost Signed-off-by: Eduardo Habkost --- hw/i386/pc.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 1eb1db0372..9c4d0ea730 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1006,7 +1006,6 @@ static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id, } qdev_set_parent_bus(DEVICE(cpu), qdev_get_child_bus(icc_bridge, "icc")); - object_unref(OBJECT(cpu)); object_property_set_int(OBJECT(cpu), apic_id, "apic-id", &local_err); object_property_set_bool(OBJECT(cpu), true, "realized", &local_err); @@ -1025,7 +1024,9 @@ static const char *current_cpu_model; void pc_hot_add_cpu(const int64_t id, Error **errp) { DeviceState *icc_bridge; + X86CPU *cpu; int64_t apic_id = x86_cpu_apic_id_from_index(id); + Error *local_err = NULL; if (id < 0) { error_setg(errp, "Invalid CPU id: %" PRIi64, id); @@ -1053,7 +1054,12 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) icc_bridge = DEVICE(object_resolve_path_type("icc-bridge", TYPE_ICC_BRIDGE, NULL)); - pc_new_cpu(current_cpu_model, apic_id, icc_bridge, errp); + cpu = pc_new_cpu(current_cpu_model, apic_id, icc_bridge, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + object_unref(OBJECT(cpu)); } void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) @@ -1087,6 +1093,7 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) error_report_err(error); exit(1); } + object_unref(OBJECT(cpu)); } /* map APIC MMIO area if CPU has APIC */ From 458cf469f4a1cb520b07092f5537c5a6d2389d23 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Fri, 29 May 2015 16:31:12 -0300 Subject: [PATCH 2/5] target-i386: Fix signedness of MSR_IA32_APICBASE_BASE Existing definition triggers the following when using clang -fsanitize=undefined: hw/intc/apic_common.c:314:55: runtime error: left shift of 1048575 by 12 places cannot be represented in type 'int' Fix it so we won't try to shift a 1 to the sign bit of a signed integer. Suggested-by: Peter Maydell Reviewed-by: Igor Mammedov Signed-off-by: Eduardo Habkost --- target-i386/cpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 4ee12ca2e9..26182bdc7e 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -305,7 +305,7 @@ #define MSR_IA32_APICBASE 0x1b #define MSR_IA32_APICBASE_BSP (1<<8) #define MSR_IA32_APICBASE_ENABLE (1<<11) -#define MSR_IA32_APICBASE_BASE (0xfffff<<12) +#define MSR_IA32_APICBASE_BASE (0xfffffU<<12) #define MSR_IA32_FEATURE_CONTROL 0x0000003a #define MSR_TSC_ADJUST 0x0000003b #define MSR_IA32_TSCDEADLINE 0x6e0 From be9f8a08727e46c790adb8caa8a4525a1e8e9e73 Mon Sep 17 00:00:00 2001 From: Zhu Guihua Date: Wed, 20 May 2015 10:40:47 +0800 Subject: [PATCH 3/5] apic: convert ->busdev.qdev casts to C casts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use C casts to avoid accessing ICCDevice's qdev field directly. Signed-off-by: Zhu Guihua Reviewed-by: Igor Mammedov Reviewed-by: Andreas Färber Acked-by: Andreas Färber Signed-off-by: Eduardo Habkost --- hw/intc/apic.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hw/intc/apic.c b/hw/intc/apic.c index 0f97b47925..77b639cce8 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -370,13 +370,14 @@ static int apic_irq_pending(APICCommonState *s) static void apic_update_irq(APICCommonState *s) { CPUState *cpu; + DeviceState *dev = (DeviceState *)s; cpu = CPU(s->cpu); if (!qemu_cpu_is_self(cpu)) { cpu_interrupt(cpu, CPU_INTERRUPT_POLL); } else if (apic_irq_pending(s) > 0) { cpu_interrupt(cpu, CPU_INTERRUPT_HARD); - } else if (!apic_accept_pic_intr(&s->busdev.qdev) || !pic_get_output(isa_pic)) { + } else if (!apic_accept_pic_intr(dev) || !pic_get_output(isa_pic)) { cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD); } } @@ -549,10 +550,12 @@ static void apic_deliver(DeviceState *dev, uint8_t dest, uint8_t dest_mode, static bool apic_check_pic(APICCommonState *s) { - if (!apic_accept_pic_intr(&s->busdev.qdev) || !pic_get_output(isa_pic)) { + DeviceState *dev = (DeviceState *)s; + + if (!apic_accept_pic_intr(dev) || !pic_get_output(isa_pic)) { return false; } - apic_deliver_pic_intr(&s->busdev.qdev, 1); + apic_deliver_pic_intr(dev, 1); return true; } From 38e5c119c2925812bd441450ab9e5e00fc79e662 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Mon, 23 Mar 2015 17:29:32 -0300 Subject: [PATCH 4/5] target-i386: Register QOM properties for feature flags This uses the feature name arrays to register QOM properties for feature flags. This simply adds properties that can be configured using -global, but doesn't change x86_cpu_parse_featurestr() to use them yet. Reviewed-by: Igor Mammedov Signed-off-by: Eduardo Habkost --- target-i386/cpu.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 3305e09413..99ad551bee 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2841,12 +2841,126 @@ out: } } +typedef struct BitProperty { + uint32_t *ptr; + uint32_t mask; +} BitProperty; + +static void x86_cpu_get_bit_prop(Object *obj, + struct Visitor *v, + void *opaque, + const char *name, + Error **errp) +{ + BitProperty *fp = opaque; + bool value = (*fp->ptr & fp->mask) == fp->mask; + visit_type_bool(v, &value, name, errp); +} + +static void x86_cpu_set_bit_prop(Object *obj, + struct Visitor *v, + void *opaque, + const char *name, + Error **errp) +{ + DeviceState *dev = DEVICE(obj); + BitProperty *fp = opaque; + Error *local_err = NULL; + bool value; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + visit_type_bool(v, &value, name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + if (value) { + *fp->ptr |= fp->mask; + } else { + *fp->ptr &= ~fp->mask; + } +} + +static void x86_cpu_release_bit_prop(Object *obj, const char *name, + void *opaque) +{ + BitProperty *prop = opaque; + g_free(prop); +} + +/* Register a boolean property to get/set a single bit in a uint32_t field. + * + * The same property name can be registered multiple times to make it affect + * multiple bits in the same FeatureWord. In that case, the getter will return + * true only if all bits are set. + */ +static void x86_cpu_register_bit_prop(X86CPU *cpu, + const char *prop_name, + uint32_t *field, + int bitnr) +{ + BitProperty *fp; + ObjectProperty *op; + uint32_t mask = (1UL << bitnr); + + op = object_property_find(OBJECT(cpu), prop_name, NULL); + if (op) { + fp = op->opaque; + assert(fp->ptr == field); + fp->mask |= mask; + } else { + fp = g_new0(BitProperty, 1); + fp->ptr = field; + fp->mask = mask; + object_property_add(OBJECT(cpu), prop_name, "bool", + x86_cpu_get_bit_prop, + x86_cpu_set_bit_prop, + x86_cpu_release_bit_prop, fp, &error_abort); + } +} + +static void x86_cpu_register_feature_bit_props(X86CPU *cpu, + FeatureWord w, + int bitnr) +{ + Object *obj = OBJECT(cpu); + int i; + char **names; + FeatureWordInfo *fi = &feature_word_info[w]; + + if (!fi->feat_names) { + return; + } + if (!fi->feat_names[bitnr]) { + return; + } + + names = g_strsplit(fi->feat_names[bitnr], "|", 0); + + feat2prop(names[0]); + x86_cpu_register_bit_prop(cpu, names[0], &cpu->env.features[w], bitnr); + + for (i = 1; names[i]; i++) { + feat2prop(names[i]); + object_property_add_alias(obj, names[i], obj, g_strdup(names[0]), + &error_abort); + } + + g_strfreev(names); +} + static void x86_cpu_initfn(Object *obj) { CPUState *cs = CPU(obj); X86CPU *cpu = X86_CPU(obj); X86CPUClass *xcc = X86_CPU_GET_CLASS(obj); CPUX86State *env = &cpu->env; + FeatureWord w; static int inited; cs->env_ptr = env; @@ -2887,6 +3001,14 @@ static void x86_cpu_initfn(Object *obj) cpu->apic_id = -1; #endif + for (w = 0; w < FEATURE_WORDS; w++) { + int bitnr; + + for (bitnr = 0; bitnr < 32; bitnr++) { + x86_cpu_register_feature_bit_props(cpu, w, bitnr); + } + } + x86_cpu_load_def(cpu, xcc->cpu_def, &error_abort); /* init various static tables used in TCG mode */ From 1b93c9a1040b3c12320cf55c6284882a2e6e8ff3 Mon Sep 17 00:00:00 2001 From: Ikey Doherty Date: Tue, 26 May 2015 13:54:06 +0100 Subject: [PATCH 5/5] arch_init: Drop target-x86_64.conf The target-x86_64.conf sysconfig file has been empty and essentially ignored now for several years. This change removes the unused file to enable moving towards a stateless configuration. Signed-off-by: Ikey Doherty Acked-by: Paolo Bonzini Reviewed-by: Eduardo Habkost Signed-off-by: Eduardo Habkost --- Makefile | 7 +------ arch_init.c | 1 - sysconfigs/target/target-x86_64.conf | 0 3 files changed, 1 insertion(+), 7 deletions(-) delete mode 100644 sysconfigs/target/target-x86_64.conf diff --git a/Makefile b/Makefile index d94580404c..2d5253680c 100644 --- a/Makefile +++ b/Makefile @@ -389,13 +389,8 @@ ifneq (,$(findstring qemu-ga,$(TOOLS))) endif endif -install-confdir: - $(INSTALL_DIR) "$(DESTDIR)$(qemu_confdir)" -install-sysconfig: install-datadir install-confdir - $(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/target-x86_64.conf "$(DESTDIR)$(qemu_confdir)" - -install: all $(if $(BUILD_DOCS),install-doc) install-sysconfig \ +install: all $(if $(BUILD_DOCS),install-doc) \ install-datadir install-localstatedir ifneq ($(TOOLS),) $(call install-prog,$(TOOLS),$(DESTDIR)$(bindir)) diff --git a/arch_init.c b/arch_init.c index 23d3feba44..b5d90a41fa 100644 --- a/arch_init.c +++ b/arch_init.c @@ -136,7 +136,6 @@ static struct defconfig_file { bool userconfig; } default_config_files[] = { { CONFIG_QEMU_CONFDIR "/qemu.conf", true }, - { CONFIG_QEMU_CONFDIR "/target-" TARGET_NAME ".conf", true }, { NULL }, /* end of list */ }; diff --git a/sysconfigs/target/target-x86_64.conf b/sysconfigs/target/target-x86_64.conf deleted file mode 100644 index e69de29bb2..0000000000