From e0eeb4a21a3ca4b296220ce4449d8acef9de9049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2016 18:27:33 +0100 Subject: cpus: pass CPUState to run_on_cpu helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPUState is a fairly common pointer to pass to these helpers. This means if you need other arguments for the async_run_on_cpu case you end up having to do a g_malloc to stuff additional data into the routine. For the current users this isn't a massive deal but for MTTCG this gets cumbersome when the only other parameter is often an address. This adds the typedef run_on_cpu_func for helper functions which has an explicit CPUState * passed as the first parameter. All the users of run_on_cpu and async_run_on_cpu have had their helpers updated to use CPUState where available. Signed-off-by: Alex Bennée [Sergey Fedorov: - eliminate more CPUState in user data; - remove unnecessary user data passing; - fix target-s390x/kvm.c and target-s390x/misc_helper.c] Signed-off-by: Sergey Fedorov Acked-by: David Gibson (ppc parts) Reviewed-by: Christian Borntraeger (s390 parts) Signed-off-by: Alex Bennée Message-Id: <1470158864-17651-3-git-send-email-alex.bennee@linaro.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- include/qom/cpu.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'include/qom/cpu.h') diff --git a/include/qom/cpu.h b/include/qom/cpu.h index ce0c406f27..4aa9e61c5d 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -232,9 +232,11 @@ struct kvm_run; #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) /* work queue */ +typedef void (*run_on_cpu_func)(CPUState *cpu, void *data); + struct qemu_work_item { struct qemu_work_item *next; - void (*func)(void *data); + run_on_cpu_func func; void *data; int done; bool free; @@ -623,7 +625,7 @@ bool cpu_is_stopped(CPUState *cpu); * * Schedules the function @func for execution on the vCPU @cpu. */ -void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data); +void run_on_cpu(CPUState *cpu, run_on_cpu_func func, void *data); /** * async_run_on_cpu: @@ -633,7 +635,7 @@ void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data); * * Schedules the function @func for execution on the vCPU @cpu asynchronously. */ -void async_run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data); +void async_run_on_cpu(CPUState *cpu, run_on_cpu_func func, void *data); /** * qemu_get_cpu: -- cgit v1.2.3 From 267f685b8b20784c97251618b515fcd17b42aad6 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sun, 28 Aug 2016 03:45:14 +0200 Subject: cpus-common: move CPU list management to common code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a mutex for the CPU list to system emulation, as it will be used to manage safe work. Abstract manipulation of the CPU list in new functions cpu_list_add and cpu_list_remove. Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Signed-off-by: Paolo Bonzini --- include/qom/cpu.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'include/qom/cpu.h') diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 4aa9e61c5d..ea3233ff5b 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -544,6 +544,18 @@ static inline int cpu_asidx_from_attrs(CPUState *cpu, MemTxAttrs attrs) } #endif +/** + * cpu_list_add: + * @cpu: The CPU to be added to the list of CPUs. + */ +void cpu_list_add(CPUState *cpu); + +/** + * cpu_list_remove: + * @cpu: The CPU to be removed from the list of CPUs. + */ +void cpu_list_remove(CPUState *cpu); + /** * cpu_reset: * @cpu: The CPU whose state is to be reset. -- cgit v1.2.3 From d148d90ee83738d45a90dc0b2fb7b1712f164103 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Mon, 29 Aug 2016 09:51:00 +0200 Subject: cpus-common: move CPU work item management to common code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make CPU work core functions common between system and user-mode emulation. User-mode does not use run_on_cpu, so do not implement it. Signed-off-by: Sergey Fedorov Signed-off-by: Sergey Fedorov Reviewed-by: Alex Bennée Signed-off-by: Alex Bennée Message-Id: <1470158864-17651-10-git-send-email-alex.bennee@linaro.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- include/qom/cpu.h | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'include/qom/cpu.h') diff --git a/include/qom/cpu.h b/include/qom/cpu.h index ea3233ff5b..c04e510ef1 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -233,14 +233,7 @@ struct kvm_run; /* work queue */ typedef void (*run_on_cpu_func)(CPUState *cpu, void *data); - -struct qemu_work_item { - struct qemu_work_item *next; - run_on_cpu_func func; - void *data; - int done; - bool free; -}; +struct qemu_work_item; /** * CPUState: @@ -629,6 +622,18 @@ void qemu_cpu_kick(CPUState *cpu); */ bool cpu_is_stopped(CPUState *cpu); +/** + * do_run_on_cpu: + * @cpu: The vCPU to run on. + * @func: The function to be executed. + * @data: Data to pass to the function. + * @mutex: Mutex to release while waiting for @func to run. + * + * Used internally in the implementation of run_on_cpu. + */ +void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, void *data, + QemuMutex *mutex); + /** * run_on_cpu: * @cpu: The vCPU to run on. @@ -807,6 +812,12 @@ void cpu_remove(CPUState *cpu); */ void cpu_remove_sync(CPUState *cpu); +/** + * process_queued_cpu_work() - process all items on CPU work queue + * @cpu: The CPU which work queue to process. + */ +void process_queued_cpu_work(CPUState *cpu); + /** * qemu_init_vcpu: * @cpu: The vCPU to initialize. -- cgit v1.2.3 From ab129972c8b41e15b0521895a46fd9c752b68a5e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 31 Aug 2016 16:56:04 +0200 Subject: cpus-common: move exclusive work infrastructure from linux-user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will serve as the base for async_safe_run_on_cpu. Because start_exclusive uses CPU_FOREACH, merge exclusive_lock with qemu_cpu_list_lock: together with a call to exclusive_idle (via cpu_exec_start/end) in cpu_list_add, this protects exclusive work against concurrent CPU addition and removal. Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- include/qom/cpu.h | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'include/qom/cpu.h') diff --git a/include/qom/cpu.h b/include/qom/cpu.h index c04e510ef1..f8726140f6 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -242,7 +242,8 @@ struct qemu_work_item; * @nr_threads: Number of threads within this CPU. * @numa_node: NUMA node this CPU is belonging to. * @host_tid: Host thread ID. - * @running: #true if CPU is currently running (usermode). + * @running: #true if CPU is currently running; + * valid under cpu_list_lock. * @created: Indicates whether the CPU thread has been successfully created. * @interrupt_request: Indicates a pending interrupt request. * @halted: Nonzero if the CPU is in suspended state. @@ -818,6 +819,47 @@ void cpu_remove_sync(CPUState *cpu); */ void process_queued_cpu_work(CPUState *cpu); +/** + * cpu_exec_start: + * @cpu: The CPU for the current thread. + * + * Record that a CPU has started execution and can be interrupted with + * cpu_exit. + */ +void cpu_exec_start(CPUState *cpu); + +/** + * cpu_exec_end: + * @cpu: The CPU for the current thread. + * + * Record that a CPU has stopped execution and exclusive sections + * can be executed without interrupting it. + */ +void cpu_exec_end(CPUState *cpu); + +/** + * start_exclusive: + * + * Wait for a concurrent exclusive section to end, and then start + * a section of work that is run while other CPUs are not running + * between cpu_exec_start and cpu_exec_end. CPUs that are running + * cpu_exec are exited immediately. CPUs that call cpu_exec_start + * during the exclusive section go to sleep until this CPU calls + * end_exclusive. + * + * Returns with the CPU list lock taken (which nests outside all + * other locks except the BQL). + */ +void start_exclusive(void); + +/** + * end_exclusive: + * + * Concludes an exclusive execution section started by start_exclusive. + * Releases the CPU list lock. + */ +void end_exclusive(void); + /** * qemu_init_vcpu: * @cpu: The vCPU to initialize. -- cgit v1.2.3 From 758e1b2b622d7c177dc2d95e887a11aa069b7e68 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 2 Sep 2016 23:33:38 +0200 Subject: cpus-common: simplify locking for start_exclusive/end_exclusive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is not necessary to hold qemu_cpu_list_mutex throughout the exclusive section, because no other exclusive section can run while pending_cpus != 0. exclusive_idle() is called in cpu_exec_start(), and that prevents any CPUs created after start_exclusive() from entering cpu_exec() during an exclusive section. Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Signed-off-by: Paolo Bonzini --- include/qom/cpu.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'include/qom/cpu.h') diff --git a/include/qom/cpu.h b/include/qom/cpu.h index f8726140f6..934c07afbf 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -846,9 +846,6 @@ void cpu_exec_end(CPUState *cpu); * cpu_exec are exited immediately. CPUs that call cpu_exec_start * during the exclusive section go to sleep until this CPU calls * end_exclusive. - * - * Returns with the CPU list lock taken (which nests outside all - * other locks except the BQL). */ void start_exclusive(void); @@ -856,7 +853,6 @@ void start_exclusive(void); * end_exclusive: * * Concludes an exclusive execution section started by start_exclusive. - * Releases the CPU list lock. */ void end_exclusive(void); -- cgit v1.2.3 From 53f5ed95064fe6807890cd5535445a05d3361bd2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sun, 28 Aug 2016 05:38:24 +0200 Subject: cpus-common: Introduce async_safe_run_on_cpu() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Signed-off-by: Paolo Bonzini --- include/qom/cpu.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'include/qom/cpu.h') diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 934c07afbf..4092dd919b 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -655,6 +655,20 @@ void run_on_cpu(CPUState *cpu, run_on_cpu_func func, void *data); */ void async_run_on_cpu(CPUState *cpu, run_on_cpu_func func, void *data); +/** + * async_safe_run_on_cpu: + * @cpu: The vCPU to run on. + * @func: The function to be executed. + * @data: Data to pass to the function. + * + * Schedules the function @func for execution on the vCPU @cpu asynchronously, + * while all other vCPUs are sleeping. + * + * Unlike run_on_cpu and async_run_on_cpu, the function is run outside the + * BQL. + */ +void async_safe_run_on_cpu(CPUState *cpu, run_on_cpu_func func, void *data); + /** * qemu_get_cpu: * @index: The CPUState@cpu_index value of the CPU to obtain. -- cgit v1.2.3 From 3359baad36889b83df40b637ed993a4b816c4906 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Tue, 2 Aug 2016 18:27:43 +0100 Subject: tcg: Make tb_flush() thread safe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use async_safe_run_on_cpu() to make tb_flush() thread safe. This is possible now that code generation does not happen in the middle of execution. It can happen that multiple threads schedule a safe work to flush the translation buffer. To keep statistics and debugging output sane, always check if the translation buffer has already been flushed. Signed-off-by: Sergey Fedorov Signed-off-by: Sergey Fedorov [AJB: minor re-base fixes] Signed-off-by: Alex Bennée Message-Id: <1470158864-17651-13-git-send-email-alex.bennee@linaro.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- include/qom/cpu.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include/qom/cpu.h') diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 4092dd919b..5dfe74a0e7 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -253,7 +253,6 @@ struct qemu_work_item; * @crash_occurred: Indicates the OS reported a crash (panic) for this CPU * @tcg_exit_req: Set to force TCG to stop executing linked TBs for this * CPU and return to its top level loop. - * @tb_flushed: Indicates the translation buffer has been flushed. * @singlestep_enabled: Flags for single-stepping. * @icount_extra: Instructions until next timer event. * @icount_decr: Number of cycles left, with interrupt flag in high bit. @@ -306,7 +305,6 @@ struct CPUState { bool unplug; bool crash_occurred; bool exit_request; - bool tb_flushed; uint32_t interrupt_request; int singlestep_enabled; int64_t icount_extra; -- cgit v1.2.3 From c265e976f4669fd65f5b47e6865f50d1cb66bd02 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 31 Aug 2016 21:33:58 +0200 Subject: cpus-common: lock-free fast path for cpu_exec_start/end Set cpu->running without taking the cpu_list lock, only requiring it if there is a concurrent exclusive section. This requires adding a new field to CPUState, which records whether a running CPU is being counted in pending_cpus. When an exclusive section is started concurrently with cpu_exec_start, cpu_exec_start can use the new field to determine if it has to wait for the end of the exclusive section. Likewise, cpu_exec_end can use it to see if start_exclusive is waiting for that CPU. This a separate patch for easier bisection of issues. Signed-off-by: Paolo Bonzini --- include/qom/cpu.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include/qom/cpu.h') diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 5dfe74a0e7..22b54d6d93 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -242,7 +242,8 @@ struct qemu_work_item; * @nr_threads: Number of threads within this CPU. * @numa_node: NUMA node this CPU is belonging to. * @host_tid: Host thread ID. - * @running: #true if CPU is currently running; + * @running: #true if CPU is currently running (lockless). + * @has_waiter: #true if a CPU is currently waiting for the cpu_exec_end; * valid under cpu_list_lock. * @created: Indicates whether the CPU thread has been successfully created. * @interrupt_request: Indicates a pending interrupt request. @@ -296,7 +297,7 @@ struct CPUState { #endif int thread_id; uint32_t host_tid; - bool running; + bool running, has_waiter; struct QemuCond *halt_cond; bool thread_kicked; bool created; -- cgit v1.2.3