summaryrefslogtreecommitdiff
path: root/exec.c
diff options
context:
space:
mode:
authorBharata B Rao <bharata@linux.vnet.ibm.com>2015-06-23 19:31:13 -0700
committerAndreas Färber <afaerber@suse.de>2015-07-09 15:20:40 +0200
commitb7bca7333411bd19c449147e8202ae6b0e4a8e09 (patch)
tree4f0e82f31615e1e55895a115e1faa9130ae2f9ea /exec.c
parent5a790cc4b942e651fec7edc597c19b637fad5a76 (diff)
downloadqemu-b7bca7333411bd19c449147e8202ae6b0e4a8e09.tar.gz
qemu-b7bca7333411bd19c449147e8202ae6b0e4a8e09.tar.bz2
qemu-b7bca7333411bd19c449147e8202ae6b0e4a8e09.zip
cpu: Convert cpu_index into a bitmap
Currently CPUState::cpu_index is monotonically increasing and a newly created CPU always gets the next higher index. The next available index is calculated by counting the existing number of CPUs. This is fine as long as we only add CPUs, but there are architectures which are starting to support CPU removal, too. For an architecture like PowerPC which derives its CPU identifier (device tree ID) from cpu_index, the existing logic of generating cpu_index values causes problems. With the currently proposed method of handling vCPU removal by parking the vCPU fd in QEMU (Ref: http://lists.gnu.org/archive/html/qemu-devel/2015-02/msg02604.html), generating cpu_index this way will not work for PowerPC. This patch changes the way cpu_index is handed out by maintaining a bit map of the CPUs that tracks both addition and removal of CPUs. The CPU bitmap allocation logic is part of cpu_exec_init(), which is called by instance_init routines of various CPU targets. Newly added cpu_exec_exit() API handles the deallocation part and this routine is called from generic CPU instance_finalize. Note: This new CPU enumeration is for !CONFIG_USER_ONLY only. CONFIG_USER_ONLY continues to have the old enumeration logic. Signed-off-by: Bharata B Rao <bharata@linux.vnet.ibm.com> Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> Reviewed-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com> Acked-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com> [AF: max_cpus -> MAX_CPUMASK_BITS] Signed-off-by: Andreas Färber <afaerber@suse.de>
Diffstat (limited to 'exec.c')
-rw-r--r--exec.c58
1 files changed, 53 insertions, 5 deletions
diff --git a/exec.c b/exec.c
index ce5fadd88a..d817e5f025 100644
--- a/exec.c
+++ b/exec.c
@@ -526,12 +526,57 @@ void tcg_cpu_address_space_init(CPUState *cpu, AddressSpace *as)
}
#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;
+}
+
+void cpu_exec_exit(CPUState *cpu)
+{
+ if (cpu->cpu_index == -1) {
+ /* cpu_index was never allocated by this @cpu or was already freed. */
+ return;
+ }
+
+ bitmap_clear(cpu_index_map, cpu->cpu_index, 1);
+ cpu->cpu_index = -1;
+}
+#else
+
+static int cpu_get_free_index(Error **errp)
+{
+ CPUState *some_cpu;
+ int cpu_index = 0;
+
+ CPU_FOREACH(some_cpu) {
+ cpu_index++;
+ }
+ return cpu_index;
+}
+
+void cpu_exec_exit(CPUState *cpu)
+{
+}
+#endif
+
void cpu_exec_init(CPUArchState *env, Error **errp)
{
CPUState *cpu = ENV_GET_CPU(env);
CPUClass *cc = CPU_GET_CLASS(cpu);
- CPUState *some_cpu;
int cpu_index;
+ Error *local_err = NULL;
#ifndef CONFIG_USER_ONLY
cpu->as = &address_space_memory;
@@ -542,11 +587,14 @@ void cpu_exec_init(CPUArchState *env, Error **errp)
#if defined(CONFIG_USER_ONLY)
cpu_list_lock();
#endif
- cpu_index = 0;
- CPU_FOREACH(some_cpu) {
- cpu_index++;
+ cpu_index = 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;
}
- cpu->cpu_index = cpu_index;
QTAILQ_INSERT_TAIL(&cpus, cpu, node);
#if defined(CONFIG_USER_ONLY)
cpu_list_unlock();