xref: /openbmc/qemu/cpu-common.c (revision 3c55dd58)
1fe0007f3SPhilippe Mathieu-Daudé /*
2fe0007f3SPhilippe Mathieu-Daudé  * CPU thread main loop - common bits for user and system mode emulation
3fe0007f3SPhilippe Mathieu-Daudé  *
4fe0007f3SPhilippe Mathieu-Daudé  *  Copyright (c) 2003-2005 Fabrice Bellard
5fe0007f3SPhilippe Mathieu-Daudé  *
6fe0007f3SPhilippe Mathieu-Daudé  * This library is free software; you can redistribute it and/or
7fe0007f3SPhilippe Mathieu-Daudé  * modify it under the terms of the GNU Lesser General Public
8fe0007f3SPhilippe Mathieu-Daudé  * License as published by the Free Software Foundation; either
9fe0007f3SPhilippe Mathieu-Daudé  * version 2.1 of the License, or (at your option) any later version.
10fe0007f3SPhilippe Mathieu-Daudé  *
11fe0007f3SPhilippe Mathieu-Daudé  * This library is distributed in the hope that it will be useful,
12fe0007f3SPhilippe Mathieu-Daudé  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13fe0007f3SPhilippe Mathieu-Daudé  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14fe0007f3SPhilippe Mathieu-Daudé  * Lesser General Public License for more details.
15fe0007f3SPhilippe Mathieu-Daudé  *
16fe0007f3SPhilippe Mathieu-Daudé  * You should have received a copy of the GNU Lesser General Public
17fe0007f3SPhilippe Mathieu-Daudé  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18fe0007f3SPhilippe Mathieu-Daudé  */
19fe0007f3SPhilippe Mathieu-Daudé 
20fe0007f3SPhilippe Mathieu-Daudé #include "qemu/osdep.h"
21fe0007f3SPhilippe Mathieu-Daudé #include "qemu/main-loop.h"
22fe0007f3SPhilippe Mathieu-Daudé #include "exec/cpu-common.h"
23fe0007f3SPhilippe Mathieu-Daudé #include "hw/core/cpu.h"
24fe0007f3SPhilippe Mathieu-Daudé #include "sysemu/cpus.h"
25fe0007f3SPhilippe Mathieu-Daudé #include "qemu/lockable.h"
26fe0007f3SPhilippe Mathieu-Daudé #include "trace/trace-root.h"
27fe0007f3SPhilippe Mathieu-Daudé 
28fe0007f3SPhilippe Mathieu-Daudé QemuMutex qemu_cpu_list_lock;
29fe0007f3SPhilippe Mathieu-Daudé static QemuCond exclusive_cond;
30fe0007f3SPhilippe Mathieu-Daudé static QemuCond exclusive_resume;
31fe0007f3SPhilippe Mathieu-Daudé static QemuCond qemu_work_cond;
32fe0007f3SPhilippe Mathieu-Daudé 
33fe0007f3SPhilippe Mathieu-Daudé /* >= 1 if a thread is inside start_exclusive/end_exclusive.  Written
34fe0007f3SPhilippe Mathieu-Daudé  * under qemu_cpu_list_lock, read with atomic operations.
35fe0007f3SPhilippe Mathieu-Daudé  */
36fe0007f3SPhilippe Mathieu-Daudé static int pending_cpus;
37fe0007f3SPhilippe Mathieu-Daudé 
38fe0007f3SPhilippe Mathieu-Daudé void qemu_init_cpu_list(void)
39fe0007f3SPhilippe Mathieu-Daudé {
40fe0007f3SPhilippe Mathieu-Daudé     /* This is needed because qemu_init_cpu_list is also called by the
41fe0007f3SPhilippe Mathieu-Daudé      * child process in a fork.  */
42fe0007f3SPhilippe Mathieu-Daudé     pending_cpus = 0;
43fe0007f3SPhilippe Mathieu-Daudé 
44fe0007f3SPhilippe Mathieu-Daudé     qemu_mutex_init(&qemu_cpu_list_lock);
45fe0007f3SPhilippe Mathieu-Daudé     qemu_cond_init(&exclusive_cond);
46fe0007f3SPhilippe Mathieu-Daudé     qemu_cond_init(&exclusive_resume);
47fe0007f3SPhilippe Mathieu-Daudé     qemu_cond_init(&qemu_work_cond);
48fe0007f3SPhilippe Mathieu-Daudé }
49fe0007f3SPhilippe Mathieu-Daudé 
50fe0007f3SPhilippe Mathieu-Daudé void cpu_list_lock(void)
51fe0007f3SPhilippe Mathieu-Daudé {
52fe0007f3SPhilippe Mathieu-Daudé     qemu_mutex_lock(&qemu_cpu_list_lock);
53fe0007f3SPhilippe Mathieu-Daudé }
54fe0007f3SPhilippe Mathieu-Daudé 
55fe0007f3SPhilippe Mathieu-Daudé void cpu_list_unlock(void)
56fe0007f3SPhilippe Mathieu-Daudé {
57fe0007f3SPhilippe Mathieu-Daudé     qemu_mutex_unlock(&qemu_cpu_list_lock);
58fe0007f3SPhilippe Mathieu-Daudé }
59fe0007f3SPhilippe Mathieu-Daudé 
60fe0007f3SPhilippe Mathieu-Daudé static bool cpu_index_auto_assigned;
61fe0007f3SPhilippe Mathieu-Daudé 
62fe0007f3SPhilippe Mathieu-Daudé static int cpu_get_free_index(void)
63fe0007f3SPhilippe Mathieu-Daudé {
64fe0007f3SPhilippe Mathieu-Daudé     CPUState *some_cpu;
65fe0007f3SPhilippe Mathieu-Daudé     int max_cpu_index = 0;
66fe0007f3SPhilippe Mathieu-Daudé 
67fe0007f3SPhilippe Mathieu-Daudé     cpu_index_auto_assigned = true;
68fe0007f3SPhilippe Mathieu-Daudé     CPU_FOREACH(some_cpu) {
69fe0007f3SPhilippe Mathieu-Daudé         if (some_cpu->cpu_index >= max_cpu_index) {
70fe0007f3SPhilippe Mathieu-Daudé             max_cpu_index = some_cpu->cpu_index + 1;
71fe0007f3SPhilippe Mathieu-Daudé         }
72fe0007f3SPhilippe Mathieu-Daudé     }
73fe0007f3SPhilippe Mathieu-Daudé     return max_cpu_index;
74fe0007f3SPhilippe Mathieu-Daudé }
75fe0007f3SPhilippe Mathieu-Daudé 
76*3c55dd58SPhilippe Mathieu-Daudé CPUTailQ cpus_queue = QTAILQ_HEAD_INITIALIZER(cpus_queue);
77fe0007f3SPhilippe Mathieu-Daudé static unsigned int cpu_list_generation_id;
78fe0007f3SPhilippe Mathieu-Daudé 
79fe0007f3SPhilippe Mathieu-Daudé unsigned int cpu_list_generation_id_get(void)
80fe0007f3SPhilippe Mathieu-Daudé {
81fe0007f3SPhilippe Mathieu-Daudé     return cpu_list_generation_id;
82fe0007f3SPhilippe Mathieu-Daudé }
83fe0007f3SPhilippe Mathieu-Daudé 
84fe0007f3SPhilippe Mathieu-Daudé void cpu_list_add(CPUState *cpu)
85fe0007f3SPhilippe Mathieu-Daudé {
86fe0007f3SPhilippe Mathieu-Daudé     QEMU_LOCK_GUARD(&qemu_cpu_list_lock);
87fe0007f3SPhilippe Mathieu-Daudé     if (cpu->cpu_index == UNASSIGNED_CPU_INDEX) {
88fe0007f3SPhilippe Mathieu-Daudé         cpu->cpu_index = cpu_get_free_index();
89fe0007f3SPhilippe Mathieu-Daudé         assert(cpu->cpu_index != UNASSIGNED_CPU_INDEX);
90fe0007f3SPhilippe Mathieu-Daudé     } else {
91fe0007f3SPhilippe Mathieu-Daudé         assert(!cpu_index_auto_assigned);
92fe0007f3SPhilippe Mathieu-Daudé     }
93*3c55dd58SPhilippe Mathieu-Daudé     QTAILQ_INSERT_TAIL_RCU(&cpus_queue, cpu, node);
94fe0007f3SPhilippe Mathieu-Daudé     cpu_list_generation_id++;
95fe0007f3SPhilippe Mathieu-Daudé }
96fe0007f3SPhilippe Mathieu-Daudé 
97fe0007f3SPhilippe Mathieu-Daudé void cpu_list_remove(CPUState *cpu)
98fe0007f3SPhilippe Mathieu-Daudé {
99fe0007f3SPhilippe Mathieu-Daudé     QEMU_LOCK_GUARD(&qemu_cpu_list_lock);
100fe0007f3SPhilippe Mathieu-Daudé     if (!QTAILQ_IN_USE(cpu, node)) {
101fe0007f3SPhilippe Mathieu-Daudé         /* there is nothing to undo since cpu_exec_init() hasn't been called */
102fe0007f3SPhilippe Mathieu-Daudé         return;
103fe0007f3SPhilippe Mathieu-Daudé     }
104fe0007f3SPhilippe Mathieu-Daudé 
105*3c55dd58SPhilippe Mathieu-Daudé     QTAILQ_REMOVE_RCU(&cpus_queue, cpu, node);
106fe0007f3SPhilippe Mathieu-Daudé     cpu->cpu_index = UNASSIGNED_CPU_INDEX;
107fe0007f3SPhilippe Mathieu-Daudé     cpu_list_generation_id++;
108fe0007f3SPhilippe Mathieu-Daudé }
109fe0007f3SPhilippe Mathieu-Daudé 
110fe0007f3SPhilippe Mathieu-Daudé CPUState *qemu_get_cpu(int index)
111fe0007f3SPhilippe Mathieu-Daudé {
112fe0007f3SPhilippe Mathieu-Daudé     CPUState *cpu;
113fe0007f3SPhilippe Mathieu-Daudé 
114fe0007f3SPhilippe Mathieu-Daudé     CPU_FOREACH(cpu) {
115fe0007f3SPhilippe Mathieu-Daudé         if (cpu->cpu_index == index) {
116fe0007f3SPhilippe Mathieu-Daudé             return cpu;
117fe0007f3SPhilippe Mathieu-Daudé         }
118fe0007f3SPhilippe Mathieu-Daudé     }
119fe0007f3SPhilippe Mathieu-Daudé 
120fe0007f3SPhilippe Mathieu-Daudé     return NULL;
121fe0007f3SPhilippe Mathieu-Daudé }
122fe0007f3SPhilippe Mathieu-Daudé 
123fe0007f3SPhilippe Mathieu-Daudé /* current CPU in the current thread. It is only valid inside cpu_exec() */
124fe0007f3SPhilippe Mathieu-Daudé __thread CPUState *current_cpu;
125fe0007f3SPhilippe Mathieu-Daudé 
126fe0007f3SPhilippe Mathieu-Daudé struct qemu_work_item {
127fe0007f3SPhilippe Mathieu-Daudé     QSIMPLEQ_ENTRY(qemu_work_item) node;
128fe0007f3SPhilippe Mathieu-Daudé     run_on_cpu_func func;
129fe0007f3SPhilippe Mathieu-Daudé     run_on_cpu_data data;
130fe0007f3SPhilippe Mathieu-Daudé     bool free, exclusive, done;
131fe0007f3SPhilippe Mathieu-Daudé };
132fe0007f3SPhilippe Mathieu-Daudé 
133fe0007f3SPhilippe Mathieu-Daudé static void queue_work_on_cpu(CPUState *cpu, struct qemu_work_item *wi)
134fe0007f3SPhilippe Mathieu-Daudé {
135fe0007f3SPhilippe Mathieu-Daudé     qemu_mutex_lock(&cpu->work_mutex);
136fe0007f3SPhilippe Mathieu-Daudé     QSIMPLEQ_INSERT_TAIL(&cpu->work_list, wi, node);
137fe0007f3SPhilippe Mathieu-Daudé     wi->done = false;
138fe0007f3SPhilippe Mathieu-Daudé     qemu_mutex_unlock(&cpu->work_mutex);
139fe0007f3SPhilippe Mathieu-Daudé 
140fe0007f3SPhilippe Mathieu-Daudé     qemu_cpu_kick(cpu);
141fe0007f3SPhilippe Mathieu-Daudé }
142fe0007f3SPhilippe Mathieu-Daudé 
143fe0007f3SPhilippe Mathieu-Daudé void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data,
144fe0007f3SPhilippe Mathieu-Daudé                    QemuMutex *mutex)
145fe0007f3SPhilippe Mathieu-Daudé {
146fe0007f3SPhilippe Mathieu-Daudé     struct qemu_work_item wi;
147fe0007f3SPhilippe Mathieu-Daudé 
148fe0007f3SPhilippe Mathieu-Daudé     if (qemu_cpu_is_self(cpu)) {
149fe0007f3SPhilippe Mathieu-Daudé         func(cpu, data);
150fe0007f3SPhilippe Mathieu-Daudé         return;
151fe0007f3SPhilippe Mathieu-Daudé     }
152fe0007f3SPhilippe Mathieu-Daudé 
153fe0007f3SPhilippe Mathieu-Daudé     wi.func = func;
154fe0007f3SPhilippe Mathieu-Daudé     wi.data = data;
155fe0007f3SPhilippe Mathieu-Daudé     wi.done = false;
156fe0007f3SPhilippe Mathieu-Daudé     wi.free = false;
157fe0007f3SPhilippe Mathieu-Daudé     wi.exclusive = false;
158fe0007f3SPhilippe Mathieu-Daudé 
159fe0007f3SPhilippe Mathieu-Daudé     queue_work_on_cpu(cpu, &wi);
160fe0007f3SPhilippe Mathieu-Daudé     while (!qatomic_load_acquire(&wi.done)) {
161fe0007f3SPhilippe Mathieu-Daudé         CPUState *self_cpu = current_cpu;
162fe0007f3SPhilippe Mathieu-Daudé 
163fe0007f3SPhilippe Mathieu-Daudé         qemu_cond_wait(&qemu_work_cond, mutex);
164fe0007f3SPhilippe Mathieu-Daudé         current_cpu = self_cpu;
165fe0007f3SPhilippe Mathieu-Daudé     }
166fe0007f3SPhilippe Mathieu-Daudé }
167fe0007f3SPhilippe Mathieu-Daudé 
168fe0007f3SPhilippe Mathieu-Daudé void async_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data)
169fe0007f3SPhilippe Mathieu-Daudé {
170fe0007f3SPhilippe Mathieu-Daudé     struct qemu_work_item *wi;
171fe0007f3SPhilippe Mathieu-Daudé 
172fe0007f3SPhilippe Mathieu-Daudé     wi = g_new0(struct qemu_work_item, 1);
173fe0007f3SPhilippe Mathieu-Daudé     wi->func = func;
174fe0007f3SPhilippe Mathieu-Daudé     wi->data = data;
175fe0007f3SPhilippe Mathieu-Daudé     wi->free = true;
176fe0007f3SPhilippe Mathieu-Daudé 
177fe0007f3SPhilippe Mathieu-Daudé     queue_work_on_cpu(cpu, wi);
178fe0007f3SPhilippe Mathieu-Daudé }
179fe0007f3SPhilippe Mathieu-Daudé 
180fe0007f3SPhilippe Mathieu-Daudé /* Wait for pending exclusive operations to complete.  The CPU list lock
181fe0007f3SPhilippe Mathieu-Daudé    must be held.  */
182fe0007f3SPhilippe Mathieu-Daudé static inline void exclusive_idle(void)
183fe0007f3SPhilippe Mathieu-Daudé {
184fe0007f3SPhilippe Mathieu-Daudé     while (pending_cpus) {
185fe0007f3SPhilippe Mathieu-Daudé         qemu_cond_wait(&exclusive_resume, &qemu_cpu_list_lock);
186fe0007f3SPhilippe Mathieu-Daudé     }
187fe0007f3SPhilippe Mathieu-Daudé }
188fe0007f3SPhilippe Mathieu-Daudé 
189fe0007f3SPhilippe Mathieu-Daudé /* Start an exclusive operation.
190fe0007f3SPhilippe Mathieu-Daudé    Must only be called from outside cpu_exec.  */
191fe0007f3SPhilippe Mathieu-Daudé void start_exclusive(void)
192fe0007f3SPhilippe Mathieu-Daudé {
193fe0007f3SPhilippe Mathieu-Daudé     CPUState *other_cpu;
194fe0007f3SPhilippe Mathieu-Daudé     int running_cpus;
195fe0007f3SPhilippe Mathieu-Daudé 
196fe0007f3SPhilippe Mathieu-Daudé     if (current_cpu->exclusive_context_count) {
197fe0007f3SPhilippe Mathieu-Daudé         current_cpu->exclusive_context_count++;
198fe0007f3SPhilippe Mathieu-Daudé         return;
199fe0007f3SPhilippe Mathieu-Daudé     }
200fe0007f3SPhilippe Mathieu-Daudé 
201fe0007f3SPhilippe Mathieu-Daudé     qemu_mutex_lock(&qemu_cpu_list_lock);
202fe0007f3SPhilippe Mathieu-Daudé     exclusive_idle();
203fe0007f3SPhilippe Mathieu-Daudé 
204fe0007f3SPhilippe Mathieu-Daudé     /* Make all other cpus stop executing.  */
205fe0007f3SPhilippe Mathieu-Daudé     qatomic_set(&pending_cpus, 1);
206fe0007f3SPhilippe Mathieu-Daudé 
207fe0007f3SPhilippe Mathieu-Daudé     /* Write pending_cpus before reading other_cpu->running.  */
208fe0007f3SPhilippe Mathieu-Daudé     smp_mb();
209fe0007f3SPhilippe Mathieu-Daudé     running_cpus = 0;
210fe0007f3SPhilippe Mathieu-Daudé     CPU_FOREACH(other_cpu) {
211fe0007f3SPhilippe Mathieu-Daudé         if (qatomic_read(&other_cpu->running)) {
212fe0007f3SPhilippe Mathieu-Daudé             other_cpu->has_waiter = true;
213fe0007f3SPhilippe Mathieu-Daudé             running_cpus++;
214fe0007f3SPhilippe Mathieu-Daudé             qemu_cpu_kick(other_cpu);
215fe0007f3SPhilippe Mathieu-Daudé         }
216fe0007f3SPhilippe Mathieu-Daudé     }
217fe0007f3SPhilippe Mathieu-Daudé 
218fe0007f3SPhilippe Mathieu-Daudé     qatomic_set(&pending_cpus, running_cpus + 1);
219fe0007f3SPhilippe Mathieu-Daudé     while (pending_cpus > 1) {
220fe0007f3SPhilippe Mathieu-Daudé         qemu_cond_wait(&exclusive_cond, &qemu_cpu_list_lock);
221fe0007f3SPhilippe Mathieu-Daudé     }
222fe0007f3SPhilippe Mathieu-Daudé 
223fe0007f3SPhilippe Mathieu-Daudé     /* Can release mutex, no one will enter another exclusive
224fe0007f3SPhilippe Mathieu-Daudé      * section until end_exclusive resets pending_cpus to 0.
225fe0007f3SPhilippe Mathieu-Daudé      */
226fe0007f3SPhilippe Mathieu-Daudé     qemu_mutex_unlock(&qemu_cpu_list_lock);
227fe0007f3SPhilippe Mathieu-Daudé 
228fe0007f3SPhilippe Mathieu-Daudé     current_cpu->exclusive_context_count = 1;
229fe0007f3SPhilippe Mathieu-Daudé }
230fe0007f3SPhilippe Mathieu-Daudé 
231fe0007f3SPhilippe Mathieu-Daudé /* Finish an exclusive operation.  */
232fe0007f3SPhilippe Mathieu-Daudé void end_exclusive(void)
233fe0007f3SPhilippe Mathieu-Daudé {
234fe0007f3SPhilippe Mathieu-Daudé     current_cpu->exclusive_context_count--;
235fe0007f3SPhilippe Mathieu-Daudé     if (current_cpu->exclusive_context_count) {
236fe0007f3SPhilippe Mathieu-Daudé         return;
237fe0007f3SPhilippe Mathieu-Daudé     }
238fe0007f3SPhilippe Mathieu-Daudé 
239fe0007f3SPhilippe Mathieu-Daudé     qemu_mutex_lock(&qemu_cpu_list_lock);
240fe0007f3SPhilippe Mathieu-Daudé     qatomic_set(&pending_cpus, 0);
241fe0007f3SPhilippe Mathieu-Daudé     qemu_cond_broadcast(&exclusive_resume);
242fe0007f3SPhilippe Mathieu-Daudé     qemu_mutex_unlock(&qemu_cpu_list_lock);
243fe0007f3SPhilippe Mathieu-Daudé }
244fe0007f3SPhilippe Mathieu-Daudé 
245fe0007f3SPhilippe Mathieu-Daudé /* Wait for exclusive ops to finish, and begin cpu execution.  */
246fe0007f3SPhilippe Mathieu-Daudé void cpu_exec_start(CPUState *cpu)
247fe0007f3SPhilippe Mathieu-Daudé {
248fe0007f3SPhilippe Mathieu-Daudé     qatomic_set(&cpu->running, true);
249fe0007f3SPhilippe Mathieu-Daudé 
250fe0007f3SPhilippe Mathieu-Daudé     /* Write cpu->running before reading pending_cpus.  */
251fe0007f3SPhilippe Mathieu-Daudé     smp_mb();
252fe0007f3SPhilippe Mathieu-Daudé 
253fe0007f3SPhilippe Mathieu-Daudé     /* 1. start_exclusive saw cpu->running == true and pending_cpus >= 1.
254fe0007f3SPhilippe Mathieu-Daudé      * After taking the lock we'll see cpu->has_waiter == true and run---not
255fe0007f3SPhilippe Mathieu-Daudé      * for long because start_exclusive kicked us.  cpu_exec_end will
256fe0007f3SPhilippe Mathieu-Daudé      * decrement pending_cpus and signal the waiter.
257fe0007f3SPhilippe Mathieu-Daudé      *
258fe0007f3SPhilippe Mathieu-Daudé      * 2. start_exclusive saw cpu->running == false but pending_cpus >= 1.
259fe0007f3SPhilippe Mathieu-Daudé      * This includes the case when an exclusive item is running now.
260fe0007f3SPhilippe Mathieu-Daudé      * Then we'll see cpu->has_waiter == false and wait for the item to
261fe0007f3SPhilippe Mathieu-Daudé      * complete.
262fe0007f3SPhilippe Mathieu-Daudé      *
263fe0007f3SPhilippe Mathieu-Daudé      * 3. pending_cpus == 0.  Then start_exclusive is definitely going to
264fe0007f3SPhilippe Mathieu-Daudé      * see cpu->running == true, and it will kick the CPU.
265fe0007f3SPhilippe Mathieu-Daudé      */
266fe0007f3SPhilippe Mathieu-Daudé     if (unlikely(qatomic_read(&pending_cpus))) {
267fe0007f3SPhilippe Mathieu-Daudé         QEMU_LOCK_GUARD(&qemu_cpu_list_lock);
268fe0007f3SPhilippe Mathieu-Daudé         if (!cpu->has_waiter) {
269fe0007f3SPhilippe Mathieu-Daudé             /* Not counted in pending_cpus, let the exclusive item
270fe0007f3SPhilippe Mathieu-Daudé              * run.  Since we have the lock, just set cpu->running to true
271fe0007f3SPhilippe Mathieu-Daudé              * while holding it; no need to check pending_cpus again.
272fe0007f3SPhilippe Mathieu-Daudé              */
273fe0007f3SPhilippe Mathieu-Daudé             qatomic_set(&cpu->running, false);
274fe0007f3SPhilippe Mathieu-Daudé             exclusive_idle();
275fe0007f3SPhilippe Mathieu-Daudé             /* Now pending_cpus is zero.  */
276fe0007f3SPhilippe Mathieu-Daudé             qatomic_set(&cpu->running, true);
277fe0007f3SPhilippe Mathieu-Daudé         } else {
278fe0007f3SPhilippe Mathieu-Daudé             /* Counted in pending_cpus, go ahead and release the
279fe0007f3SPhilippe Mathieu-Daudé              * waiter at cpu_exec_end.
280fe0007f3SPhilippe Mathieu-Daudé              */
281fe0007f3SPhilippe Mathieu-Daudé         }
282fe0007f3SPhilippe Mathieu-Daudé     }
283fe0007f3SPhilippe Mathieu-Daudé }
284fe0007f3SPhilippe Mathieu-Daudé 
285fe0007f3SPhilippe Mathieu-Daudé /* Mark cpu as not executing, and release pending exclusive ops.  */
286fe0007f3SPhilippe Mathieu-Daudé void cpu_exec_end(CPUState *cpu)
287fe0007f3SPhilippe Mathieu-Daudé {
288fe0007f3SPhilippe Mathieu-Daudé     qatomic_set(&cpu->running, false);
289fe0007f3SPhilippe Mathieu-Daudé 
290fe0007f3SPhilippe Mathieu-Daudé     /* Write cpu->running before reading pending_cpus.  */
291fe0007f3SPhilippe Mathieu-Daudé     smp_mb();
292fe0007f3SPhilippe Mathieu-Daudé 
293fe0007f3SPhilippe Mathieu-Daudé     /* 1. start_exclusive saw cpu->running == true.  Then it will increment
294fe0007f3SPhilippe Mathieu-Daudé      * pending_cpus and wait for exclusive_cond.  After taking the lock
295fe0007f3SPhilippe Mathieu-Daudé      * we'll see cpu->has_waiter == true.
296fe0007f3SPhilippe Mathieu-Daudé      *
297fe0007f3SPhilippe Mathieu-Daudé      * 2. start_exclusive saw cpu->running == false but here pending_cpus >= 1.
298fe0007f3SPhilippe Mathieu-Daudé      * This includes the case when an exclusive item started after setting
299fe0007f3SPhilippe Mathieu-Daudé      * cpu->running to false and before we read pending_cpus.  Then we'll see
300fe0007f3SPhilippe Mathieu-Daudé      * cpu->has_waiter == false and not touch pending_cpus.  The next call to
301fe0007f3SPhilippe Mathieu-Daudé      * cpu_exec_start will run exclusive_idle if still necessary, thus waiting
302fe0007f3SPhilippe Mathieu-Daudé      * for the item to complete.
303fe0007f3SPhilippe Mathieu-Daudé      *
304fe0007f3SPhilippe Mathieu-Daudé      * 3. pending_cpus == 0.  Then start_exclusive is definitely going to
305fe0007f3SPhilippe Mathieu-Daudé      * see cpu->running == false, and it can ignore this CPU until the
306fe0007f3SPhilippe Mathieu-Daudé      * next cpu_exec_start.
307fe0007f3SPhilippe Mathieu-Daudé      */
308fe0007f3SPhilippe Mathieu-Daudé     if (unlikely(qatomic_read(&pending_cpus))) {
309fe0007f3SPhilippe Mathieu-Daudé         QEMU_LOCK_GUARD(&qemu_cpu_list_lock);
310fe0007f3SPhilippe Mathieu-Daudé         if (cpu->has_waiter) {
311fe0007f3SPhilippe Mathieu-Daudé             cpu->has_waiter = false;
312fe0007f3SPhilippe Mathieu-Daudé             qatomic_set(&pending_cpus, pending_cpus - 1);
313fe0007f3SPhilippe Mathieu-Daudé             if (pending_cpus == 1) {
314fe0007f3SPhilippe Mathieu-Daudé                 qemu_cond_signal(&exclusive_cond);
315fe0007f3SPhilippe Mathieu-Daudé             }
316fe0007f3SPhilippe Mathieu-Daudé         }
317fe0007f3SPhilippe Mathieu-Daudé     }
318fe0007f3SPhilippe Mathieu-Daudé }
319fe0007f3SPhilippe Mathieu-Daudé 
320fe0007f3SPhilippe Mathieu-Daudé void async_safe_run_on_cpu(CPUState *cpu, run_on_cpu_func func,
321fe0007f3SPhilippe Mathieu-Daudé                            run_on_cpu_data data)
322fe0007f3SPhilippe Mathieu-Daudé {
323fe0007f3SPhilippe Mathieu-Daudé     struct qemu_work_item *wi;
324fe0007f3SPhilippe Mathieu-Daudé 
325fe0007f3SPhilippe Mathieu-Daudé     wi = g_new0(struct qemu_work_item, 1);
326fe0007f3SPhilippe Mathieu-Daudé     wi->func = func;
327fe0007f3SPhilippe Mathieu-Daudé     wi->data = data;
328fe0007f3SPhilippe Mathieu-Daudé     wi->free = true;
329fe0007f3SPhilippe Mathieu-Daudé     wi->exclusive = true;
330fe0007f3SPhilippe Mathieu-Daudé 
331fe0007f3SPhilippe Mathieu-Daudé     queue_work_on_cpu(cpu, wi);
332fe0007f3SPhilippe Mathieu-Daudé }
333fe0007f3SPhilippe Mathieu-Daudé 
334fe0007f3SPhilippe Mathieu-Daudé void process_queued_cpu_work(CPUState *cpu)
335fe0007f3SPhilippe Mathieu-Daudé {
336fe0007f3SPhilippe Mathieu-Daudé     struct qemu_work_item *wi;
337fe0007f3SPhilippe Mathieu-Daudé 
338fe0007f3SPhilippe Mathieu-Daudé     qemu_mutex_lock(&cpu->work_mutex);
339fe0007f3SPhilippe Mathieu-Daudé     if (QSIMPLEQ_EMPTY(&cpu->work_list)) {
340fe0007f3SPhilippe Mathieu-Daudé         qemu_mutex_unlock(&cpu->work_mutex);
341fe0007f3SPhilippe Mathieu-Daudé         return;
342fe0007f3SPhilippe Mathieu-Daudé     }
343fe0007f3SPhilippe Mathieu-Daudé     while (!QSIMPLEQ_EMPTY(&cpu->work_list)) {
344fe0007f3SPhilippe Mathieu-Daudé         wi = QSIMPLEQ_FIRST(&cpu->work_list);
345fe0007f3SPhilippe Mathieu-Daudé         QSIMPLEQ_REMOVE_HEAD(&cpu->work_list, node);
346fe0007f3SPhilippe Mathieu-Daudé         qemu_mutex_unlock(&cpu->work_mutex);
347fe0007f3SPhilippe Mathieu-Daudé         if (wi->exclusive) {
348fe0007f3SPhilippe Mathieu-Daudé             /* Running work items outside the BQL avoids the following deadlock:
349fe0007f3SPhilippe Mathieu-Daudé              * 1) start_exclusive() is called with the BQL taken while another
350fe0007f3SPhilippe Mathieu-Daudé              * CPU is running; 2) cpu_exec in the other CPU tries to takes the
351fe0007f3SPhilippe Mathieu-Daudé              * BQL, so it goes to sleep; start_exclusive() is sleeping too, so
352fe0007f3SPhilippe Mathieu-Daudé              * neither CPU can proceed.
353fe0007f3SPhilippe Mathieu-Daudé              */
354fe0007f3SPhilippe Mathieu-Daudé             qemu_mutex_unlock_iothread();
355fe0007f3SPhilippe Mathieu-Daudé             start_exclusive();
356fe0007f3SPhilippe Mathieu-Daudé             wi->func(cpu, wi->data);
357fe0007f3SPhilippe Mathieu-Daudé             end_exclusive();
358fe0007f3SPhilippe Mathieu-Daudé             qemu_mutex_lock_iothread();
359fe0007f3SPhilippe Mathieu-Daudé         } else {
360fe0007f3SPhilippe Mathieu-Daudé             wi->func(cpu, wi->data);
361fe0007f3SPhilippe Mathieu-Daudé         }
362fe0007f3SPhilippe Mathieu-Daudé         qemu_mutex_lock(&cpu->work_mutex);
363fe0007f3SPhilippe Mathieu-Daudé         if (wi->free) {
364fe0007f3SPhilippe Mathieu-Daudé             g_free(wi);
365fe0007f3SPhilippe Mathieu-Daudé         } else {
366fe0007f3SPhilippe Mathieu-Daudé             qatomic_store_release(&wi->done, true);
367fe0007f3SPhilippe Mathieu-Daudé         }
368fe0007f3SPhilippe Mathieu-Daudé     }
369fe0007f3SPhilippe Mathieu-Daudé     qemu_mutex_unlock(&cpu->work_mutex);
370fe0007f3SPhilippe Mathieu-Daudé     qemu_cond_broadcast(&qemu_work_cond);
371fe0007f3SPhilippe Mathieu-Daudé }
372fe0007f3SPhilippe Mathieu-Daudé 
373fe0007f3SPhilippe Mathieu-Daudé /* Add a breakpoint.  */
374fe0007f3SPhilippe Mathieu-Daudé int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags,
375fe0007f3SPhilippe Mathieu-Daudé                           CPUBreakpoint **breakpoint)
376fe0007f3SPhilippe Mathieu-Daudé {
377fe0007f3SPhilippe Mathieu-Daudé     CPUClass *cc = CPU_GET_CLASS(cpu);
378fe0007f3SPhilippe Mathieu-Daudé     CPUBreakpoint *bp;
379fe0007f3SPhilippe Mathieu-Daudé 
380fe0007f3SPhilippe Mathieu-Daudé     if (cc->gdb_adjust_breakpoint) {
381fe0007f3SPhilippe Mathieu-Daudé         pc = cc->gdb_adjust_breakpoint(cpu, pc);
382fe0007f3SPhilippe Mathieu-Daudé     }
383fe0007f3SPhilippe Mathieu-Daudé 
384fe0007f3SPhilippe Mathieu-Daudé     bp = g_malloc(sizeof(*bp));
385fe0007f3SPhilippe Mathieu-Daudé 
386fe0007f3SPhilippe Mathieu-Daudé     bp->pc = pc;
387fe0007f3SPhilippe Mathieu-Daudé     bp->flags = flags;
388fe0007f3SPhilippe Mathieu-Daudé 
389fe0007f3SPhilippe Mathieu-Daudé     /* keep all GDB-injected breakpoints in front */
390fe0007f3SPhilippe Mathieu-Daudé     if (flags & BP_GDB) {
391fe0007f3SPhilippe Mathieu-Daudé         QTAILQ_INSERT_HEAD(&cpu->breakpoints, bp, entry);
392fe0007f3SPhilippe Mathieu-Daudé     } else {
393fe0007f3SPhilippe Mathieu-Daudé         QTAILQ_INSERT_TAIL(&cpu->breakpoints, bp, entry);
394fe0007f3SPhilippe Mathieu-Daudé     }
395fe0007f3SPhilippe Mathieu-Daudé 
396fe0007f3SPhilippe Mathieu-Daudé     if (breakpoint) {
397fe0007f3SPhilippe Mathieu-Daudé         *breakpoint = bp;
398fe0007f3SPhilippe Mathieu-Daudé     }
399fe0007f3SPhilippe Mathieu-Daudé 
400fe0007f3SPhilippe Mathieu-Daudé     trace_breakpoint_insert(cpu->cpu_index, pc, flags);
401fe0007f3SPhilippe Mathieu-Daudé     return 0;
402fe0007f3SPhilippe Mathieu-Daudé }
403fe0007f3SPhilippe Mathieu-Daudé 
404fe0007f3SPhilippe Mathieu-Daudé /* Remove a specific breakpoint.  */
405fe0007f3SPhilippe Mathieu-Daudé int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags)
406fe0007f3SPhilippe Mathieu-Daudé {
407fe0007f3SPhilippe Mathieu-Daudé     CPUClass *cc = CPU_GET_CLASS(cpu);
408fe0007f3SPhilippe Mathieu-Daudé     CPUBreakpoint *bp;
409fe0007f3SPhilippe Mathieu-Daudé 
410fe0007f3SPhilippe Mathieu-Daudé     if (cc->gdb_adjust_breakpoint) {
411fe0007f3SPhilippe Mathieu-Daudé         pc = cc->gdb_adjust_breakpoint(cpu, pc);
412fe0007f3SPhilippe Mathieu-Daudé     }
413fe0007f3SPhilippe Mathieu-Daudé 
414fe0007f3SPhilippe Mathieu-Daudé     QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
415fe0007f3SPhilippe Mathieu-Daudé         if (bp->pc == pc && bp->flags == flags) {
416fe0007f3SPhilippe Mathieu-Daudé             cpu_breakpoint_remove_by_ref(cpu, bp);
417fe0007f3SPhilippe Mathieu-Daudé             return 0;
418fe0007f3SPhilippe Mathieu-Daudé         }
419fe0007f3SPhilippe Mathieu-Daudé     }
420fe0007f3SPhilippe Mathieu-Daudé     return -ENOENT;
421fe0007f3SPhilippe Mathieu-Daudé }
422fe0007f3SPhilippe Mathieu-Daudé 
423fe0007f3SPhilippe Mathieu-Daudé /* Remove a specific breakpoint by reference.  */
424fe0007f3SPhilippe Mathieu-Daudé void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *bp)
425fe0007f3SPhilippe Mathieu-Daudé {
426fe0007f3SPhilippe Mathieu-Daudé     QTAILQ_REMOVE(&cpu->breakpoints, bp, entry);
427fe0007f3SPhilippe Mathieu-Daudé 
428fe0007f3SPhilippe Mathieu-Daudé     trace_breakpoint_remove(cpu->cpu_index, bp->pc, bp->flags);
429fe0007f3SPhilippe Mathieu-Daudé     g_free(bp);
430fe0007f3SPhilippe Mathieu-Daudé }
431fe0007f3SPhilippe Mathieu-Daudé 
432fe0007f3SPhilippe Mathieu-Daudé /* Remove all matching breakpoints. */
433fe0007f3SPhilippe Mathieu-Daudé void cpu_breakpoint_remove_all(CPUState *cpu, int mask)
434fe0007f3SPhilippe Mathieu-Daudé {
435fe0007f3SPhilippe Mathieu-Daudé     CPUBreakpoint *bp, *next;
436fe0007f3SPhilippe Mathieu-Daudé 
437fe0007f3SPhilippe Mathieu-Daudé     QTAILQ_FOREACH_SAFE(bp, &cpu->breakpoints, entry, next) {
438fe0007f3SPhilippe Mathieu-Daudé         if (bp->flags & mask) {
439fe0007f3SPhilippe Mathieu-Daudé             cpu_breakpoint_remove_by_ref(cpu, bp);
440fe0007f3SPhilippe Mathieu-Daudé         }
441fe0007f3SPhilippe Mathieu-Daudé     }
442fe0007f3SPhilippe Mathieu-Daudé }
443