summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-07-27 18:18:21 +0100
committerPeter Maydell <peter.maydell@linaro.org>2016-07-27 18:18:21 +0100
commit21a21b853a1bb606358af61e738abfb9aecbd720 (patch)
tree154ad3f9e601dff25552a9e68c666d6cce7a4706
parent51313fe4f4afea65970a20b32ed2d35b44fbf993 (diff)
parent03f28efbbb0ee521611e0eb28b45096b3598fb34 (diff)
downloadqemu-21a21b853a1bb606358af61e738abfb9aecbd720.tar.gz
Merge remote-tracking branch 'remotes/ehabkost/tags/x86-pull-request' into staging
x86 and machine queue, 2016-07-27 Highlights: * Fixes to allow CPU hotplug/unplug in any order; * Exit QEMU on invalid global properties. # gpg: Signature made Wed 27 Jul 2016 15:28:53 BST # gpg: using RSA key 0x2807936F984DC5A6 # gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>" # Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF D1AA 2807 936F 984D C5A6 * remotes/ehabkost/tags/x86-pull-request: vl: exit if a bad property value is passed to -global qdev: ignore GlobalProperty.errp for hotplugged devices machine: Add comment to abort path in machine_set_kernel_irqchip Revert "pc: Enforce adding CPUs contiguously and removing them in opposite order" pc: Init CPUState->cpu_index with index in possible_cpus[] qdev: Fix object reference leak in case device.realize() fails exec: Set cpu_index only if it's not been explictly set exec: Don't use cpu_index to detect if cpu_exec_init()'s been called exec: Reduce CONFIG_USER_ONLY ifdeffenery Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--bsd-user/qemu.h2
-rw-r--r--exec.c66
-rw-r--r--hw/core/machine.c3
-rw-r--r--hw/core/qdev-properties.c4
-rw-r--r--hw/core/qdev.c8
-rw-r--r--hw/i386/pc.c38
-rw-r--r--include/exec/exec-all.h12
-rw-r--r--include/hw/qdev-core.h4
-rw-r--r--include/qom/cpu.h2
-rw-r--r--linux-user/qemu.h2
-rw-r--r--qom/cpu.c2
-rw-r--r--vl.c1
12 files changed, 47 insertions, 97 deletions
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index 6ccc544e7d..2b2b9184e0 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -209,8 +209,6 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
abi_ulong new_addr);
int target_msync(abi_ulong start, abi_ulong len, int flags);
extern unsigned long last_brk;
-void cpu_list_lock(void);
-void cpu_list_unlock(void);
#if defined(CONFIG_USE_NPTL)
void mmap_fork_start(void);
void mmap_fork_end(int child);
diff --git a/exec.c b/exec.c
index 60cf46a5b5..50e3ee237c 100644
--- a/exec.c
+++ b/exec.c
@@ -598,30 +598,7 @@ AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx)
}
#endif
-#ifndef CONFIG_USER_ONLY
-static DECLARE_BITMAP(cpu_index_map, MAX_CPUMASK_BITS);
-
-static int cpu_get_free_index(Error **errp)
-{
- int cpu = find_first_zero_bit(cpu_index_map, MAX_CPUMASK_BITS);
-
- if (cpu >= MAX_CPUMASK_BITS) {
- error_setg(errp, "Trying to use more CPUs than max of %d",
- MAX_CPUMASK_BITS);
- return -1;
- }
-
- bitmap_set(cpu_index_map, cpu, 1);
- return cpu;
-}
-
-static void cpu_release_index(CPUState *cpu)
-{
- bitmap_clear(cpu_index_map, cpu->cpu_index, 1);
-}
-#else
-
-static int cpu_get_free_index(Error **errp)
+static int cpu_get_free_index(void)
{
CPUState *some_cpu;
int cpu_index = 0;
@@ -632,33 +609,21 @@ static int cpu_get_free_index(Error **errp)
return cpu_index;
}
-static void cpu_release_index(CPUState *cpu)
-{
- return;
-}
-#endif
-
void cpu_exec_exit(CPUState *cpu)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
-#if defined(CONFIG_USER_ONLY)
cpu_list_lock();
-#endif
- if (cpu->cpu_index == -1) {
- /* cpu_index was never allocated by this @cpu or was already freed. */
-#if defined(CONFIG_USER_ONLY)
+ if (cpu->node.tqe_prev == NULL) {
+ /* there is nothing to undo since cpu_exec_init() hasn't been called */
cpu_list_unlock();
-#endif
return;
}
QTAILQ_REMOVE(&cpus, cpu, node);
- cpu_release_index(cpu);
- cpu->cpu_index = -1;
-#if defined(CONFIG_USER_ONLY)
+ cpu->node.tqe_prev = NULL;
+ cpu->cpu_index = UNASSIGNED_CPU_INDEX;
cpu_list_unlock();
-#endif
if (cc->vmsd != NULL) {
vmstate_unregister(NULL, cc->vmsd, cpu);
@@ -670,8 +635,8 @@ void cpu_exec_exit(CPUState *cpu)
void cpu_exec_init(CPUState *cpu, Error **errp)
{
- CPUClass *cc = CPU_GET_CLASS(cpu);
- Error *local_err = NULL;
+ CPUClass *cc ATTRIBUTE_UNUSED = CPU_GET_CLASS(cpu);
+ Error *local_err ATTRIBUTE_UNUSED = NULL;
cpu->as = NULL;
cpu->num_ases = 0;
@@ -694,22 +659,15 @@ void cpu_exec_init(CPUState *cpu, Error **errp)
object_ref(OBJECT(cpu->memory));
#endif
-#if defined(CONFIG_USER_ONLY)
cpu_list_lock();
-#endif
- cpu->cpu_index = cpu_get_free_index(&local_err);
- if (local_err) {
- error_propagate(errp, local_err);
-#if defined(CONFIG_USER_ONLY)
- cpu_list_unlock();
-#endif
- return;
+ if (cpu->cpu_index == UNASSIGNED_CPU_INDEX) {
+ cpu->cpu_index = cpu_get_free_index();
+ assert(cpu->cpu_index != UNASSIGNED_CPU_INDEX);
}
QTAILQ_INSERT_TAIL(&cpus, cpu, node);
-#if defined(CONFIG_USER_ONLY)
- (void) cc;
cpu_list_unlock();
-#else
+
+#ifndef CONFIG_USER_ONLY
if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu);
}
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 2fe6ff6f30..e5a456f21d 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -65,6 +65,9 @@ static void machine_set_kernel_irqchip(Object *obj, Visitor *v,
ms->kernel_irqchip_split = true;
break;
default:
+ /* The value was checked in visit_type_OnOffSplit() above. If
+ * we get here, then something is wrong in QEMU.
+ */
abort();
}
}
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 14e544ab17..311af6da76 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -1084,7 +1084,7 @@ int qdev_prop_check_globals(void)
}
static void qdev_prop_set_globals_for_type(DeviceState *dev,
- const char *typename)
+ const char *typename)
{
GList *l;
@@ -1100,7 +1100,7 @@ static void qdev_prop_set_globals_for_type(DeviceState *dev,
if (err != NULL) {
error_prepend(&err, "can't apply global %s.%s=%s: ",
prop->driver, prop->property, prop->value);
- if (prop->errp) {
+ if (!dev->hotplugged && prop->errp) {
error_propagate(prop->errp, err);
} else {
assert(prop->user_provided);
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 6680089154..ee4a083e64 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -885,6 +885,8 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
HotplugHandler *hotplug_ctrl;
BusState *bus;
Error *local_err = NULL;
+ bool unattached_parent = false;
+ static int unattached_count;
if (dev->hotplugged && !dc->hotpluggable) {
error_setg(errp, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj));
@@ -893,12 +895,12 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
if (value && !dev->realized) {
if (!obj->parent) {
- static int unattached_count;
gchar *name = g_strdup_printf("device[%d]", unattached_count++);
object_property_add_child(container_get(qdev_get_machine(),
"/unattached"),
name, obj, &error_abort);
+ unattached_parent = true;
g_free(name);
}
@@ -987,6 +989,10 @@ post_realize_fail:
fail:
error_propagate(errp, local_err);
+ if (unattached_parent) {
+ object_unparent(OBJECT(dev));
+ unattached_count--;
+ }
}
static bool device_get_hotpluggable(Object *obj, Error **errp)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 9e3c70fb23..47593b741a 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1818,23 +1818,6 @@ static void pc_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
goto out;
}
- if (idx < pcms->possible_cpus->len - 1 &&
- pcms->possible_cpus->cpus[idx + 1].cpu != NULL) {
- X86CPU *cpu;
-
- for (idx = pcms->possible_cpus->len - 1;
- pcms->possible_cpus->cpus[idx].cpu == NULL; idx--) {
- ;;
- }
-
- cpu = X86_CPU(pcms->possible_cpus->cpus[idx].cpu);
- error_setg(&local_err, "CPU [socket-id: %u, core-id: %u,"
- " thread-id: %u] should be removed first",
- cpu->socket_id, cpu->core_id, cpu->thread_id);
- goto out;
-
- }
-
hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
@@ -1875,6 +1858,7 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
int idx;
+ CPUState *cs;
CPUArchId *cpu_slot;
X86CPUTopoInfo topo;
X86CPU *cpu = X86_CPU(dev);
@@ -1931,23 +1915,6 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
return;
}
- if (idx != 0 && pcms->possible_cpus->cpus[idx - 1].cpu == NULL) {
- PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
-
- for (idx = 1; pcms->possible_cpus->cpus[idx].cpu != NULL; idx++) {
- ;;
- }
-
- x86_topo_ids_from_apicid(pcms->possible_cpus->cpus[idx].arch_id,
- smp_cores, smp_threads, &topo);
-
- if (!pcmc->legacy_cpu_hotplug) {
- error_setg(errp, "CPU [socket: %u, core: %u, thread: %u] should be"
- " added first", topo.pkg_id, topo.core_id, topo.smt_id);
- return;
- }
- }
-
/* if 'address' properties socket-id/core-id/thread-id are not set, set them
* so that query_hotpluggable_cpus would show correct values
*/
@@ -1975,6 +1942,9 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
return;
}
cpu->thread_id = topo.smt_id;
+
+ cs = CPU(cpu);
+ cs->cpu_index = idx;
}
static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index acda7b613d..d008296c1b 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -56,6 +56,18 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
target_ulong pc, target_ulong cs_base,
uint32_t flags,
int cflags);
+#if defined(CONFIG_USER_ONLY)
+void cpu_list_lock(void);
+void cpu_list_unlock(void);
+#else
+static inline void cpu_list_unlock(void)
+{
+}
+static inline void cpu_list_lock(void)
+{
+}
+#endif
+
void cpu_exec_init(CPUState *cpu, Error **errp);
void QEMU_NORETURN cpu_loop_exit(CPUState *cpu);
void QEMU_NORETURN cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc);
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 1d1f8612a9..4b4b33bec8 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -261,7 +261,9 @@ struct PropertyInfo {
* @used: Set to true if property was used when initializing a device.
* @errp: Error destination, used like first argument of error_setg()
* in case property setting fails later. If @errp is NULL, we
- * print warnings instead of ignoring errors silently.
+ * print warnings instead of ignoring errors silently. For
+ * hotplugged devices, errp is always ignored and warnings are
+ * printed instead.
*/
typedef struct GlobalProperty {
const char *driver;
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index cbcd64c92b..ce0c406f27 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -883,4 +883,6 @@ extern const struct VMStateDescription vmstate_cpu_common;
.offset = 0, \
}
+#define UNASSIGNED_CPU_INDEX -1
+
#endif
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index cdf23a723a..bef465de4d 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -419,8 +419,6 @@ int target_msync(abi_ulong start, abi_ulong len, int flags);
extern unsigned long last_brk;
extern abi_ulong mmap_next_start;
abi_ulong mmap_find_vma(abi_ulong, abi_ulong);
-void cpu_list_lock(void);
-void cpu_list_unlock(void);
void mmap_fork_start(void);
void mmap_fork_end(int child);
diff --git a/qom/cpu.c b/qom/cpu.c
index 42b5631c7c..2553247907 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -340,7 +340,7 @@ static void cpu_common_initfn(Object *obj)
CPUState *cpu = CPU(obj);
CPUClass *cc = CPU_GET_CLASS(obj);
- cpu->cpu_index = -1;
+ cpu->cpu_index = UNASSIGNED_CPU_INDEX;
cpu->gdb_num_regs = cpu->gdb_num_g_regs = cc->gdb_num_core_regs;
qemu_mutex_init(&cpu->work_mutex);
QTAILQ_INIT(&cpu->breakpoints);
diff --git a/vl.c b/vl.c
index a455947b4f..e7c2c628de 100644
--- a/vl.c
+++ b/vl.c
@@ -2922,6 +2922,7 @@ static int global_init_func(void *opaque, QemuOpts *opts, Error **errp)
g->property = qemu_opt_get(opts, "property");
g->value = qemu_opt_get(opts, "value");
g->user_provided = true;
+ g->errp = &error_fatal;
qdev_prop_register_global(g);
return 0;
}