master
c 349 lines 9.72 KB
Raw
1 /*
2 * QEMU TCG Single Threaded vCPUs implementation
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 * Copyright (c) 2014 Red Hat Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26 #include "qemu/osdep.h"
27 #include "qemu/lockable.h"
28 #include "system/tcg.h"
29 #include "system/replay.h"
30 #include "exec/icount.h"
31 #include "qemu/main-loop.h"
32 #include "qemu/notify.h"
33 #include "qemu/guest-random.h"
34 #include "exec/cpu-common.h"
35 #include "accel/tcg/cpu-loop.h"
36 #include "tcg/startup.h"
37 #include "tcg-accel-ops.h"
38 #include "tcg-accel-ops-rr.h"
39 #include "tcg-accel-ops-icount.h"
40
41 /* Kick all RR vCPUs */
42 void rr_kick_vcpu_thread(CPUState *unused)
43 {
44 CPUState *cpu;
45
46 CPU_FOREACH(cpu) {
47 tcg_kick_vcpu_thread(cpu);
48 };
49 }
50
51 /*
52 * TCG vCPU kick timer
53 *
54 * The kick timer is responsible for moving single threaded vCPU
55 * emulation on to the next vCPU. If more than one vCPU is running a
56 * timer event we force a cpu->exit so the next vCPU can get
57 * scheduled.
58 *
59 * The timer is removed if all vCPUs are idle and restarted again once
60 * idleness is complete.
61 */
62
63 static QEMUTimer *rr_kick_vcpu_timer;
64 static CPUState *rr_current_cpu;
65
66 static inline int64_t rr_next_kick_time(void)
67 {
68 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + TCG_KICK_PERIOD;
69 }
70
71 /* Kick the currently round-robin scheduled vCPU to next */
72 static void rr_kick_next_cpu(void)
73 {
74 CPUState *cpu;
75 do {
76 cpu = qatomic_read(&rr_current_cpu);
77 if (cpu) {
78 cpu_exit(cpu);
79 }
80 /* Finish kicking this cpu before reading again. */
81 smp_mb();
82 } while (cpu != qatomic_read(&rr_current_cpu));
83 }
84
85 static void rr_kick_thread(void *opaque)
86 {
87 timer_mod(rr_kick_vcpu_timer, rr_next_kick_time());
88 rr_kick_next_cpu();
89 }
90
91 static void rr_start_kick_timer(void)
92 {
93 if (!rr_kick_vcpu_timer && CPU_NEXT(first_cpu)) {
94 rr_kick_vcpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
95 rr_kick_thread, NULL);
96 }
97 if (rr_kick_vcpu_timer && !timer_pending(rr_kick_vcpu_timer)) {
98 timer_mod(rr_kick_vcpu_timer, rr_next_kick_time());
99 }
100 }
101
102 static void rr_stop_kick_timer(void)
103 {
104 if (rr_kick_vcpu_timer && timer_pending(rr_kick_vcpu_timer)) {
105 timer_del(rr_kick_vcpu_timer);
106 }
107 }
108
109 static void rr_wait_io_event(void)
110 {
111 CPUState *cpu;
112
113 while (all_cpu_threads_idle()) {
114 rr_stop_kick_timer();
115 qemu_cond_wait_bql(first_cpu->halt_cond);
116 }
117
118 rr_start_kick_timer();
119
120 CPU_FOREACH(cpu) {
121 qemu_process_cpu_events_common(cpu);
122 }
123 }
124
125 /*
126 * Destroy any remaining vCPUs which have been unplugged and have
127 * finished running
128 */
129 static void rr_deal_with_unplugged_cpus(void)
130 {
131 CPUState *cpu;
132
133 CPU_FOREACH(cpu) {
134 if (cpu->unplug && !cpu_can_run(cpu)) {
135 tcg_cpu_destroy(cpu);
136 break;
137 }
138 }
139 }
140
141 static void rr_force_rcu(Notifier *notify, void *data)
142 {
143 rr_kick_next_cpu();
144 }
145
146 /*
147 * Calculate the number of CPUs that we will process in a single iteration of
148 * the main CPU thread loop so that we can fairly distribute the instruction
149 * count across CPUs.
150 *
151 * The CPU count is cached based on the CPU list generation ID to avoid
152 * iterating the list every time.
153 */
154 static int rr_cpu_count(void)
155 {
156 static unsigned int last_gen_id = ~0;
157 static int cpu_count;
158 CPUState *cpu;
159
160 QEMU_LOCK_GUARD(&qemu_cpu_list_lock);
161
162 if (cpu_list_generation_id_get() != last_gen_id) {
163 cpu_count = 0;
164 CPU_FOREACH(cpu) {
165 ++cpu_count;
166 }
167 last_gen_id = cpu_list_generation_id_get();
168 }
169
170 return cpu_count;
171 }
172
173 /*
174 * In the single-threaded case each vCPU is simulated in turn. If
175 * there is more than a single vCPU we create a simple timer to kick
176 * the vCPU and ensure we don't get stuck in a tight loop in one vCPU.
177 * This is done explicitly rather than relying on side-effects
178 * elsewhere.
179 */
180
181 static void *rr_cpu_thread_fn(void *arg)
182 {
183 Notifier force_rcu;
184 CPUState *cpu = arg;
185
186 assert(tcg_enabled());
187 rcu_register_thread();
188 force_rcu.notify = rr_force_rcu;
189 rcu_add_force_rcu_notifier(&force_rcu);
190 tcg_register_thread();
191
192 bql_lock();
193 qemu_thread_get_self(cpu->thread);
194
195 cpu->thread_id = qemu_get_thread_id();
196 cpu->neg.can_do_io = true;
197 cpu_thread_signal_created(cpu);
198 qemu_guest_random_seed_thread_part2(cpu->random_seed);
199
200 /* wait for initial kick-off after machine start */
201 while (cpu_is_stopped(first_cpu)) {
202 qemu_cond_wait_bql(first_cpu->halt_cond);
203
204 /* process any pending work */
205 CPU_FOREACH(cpu) {
206 current_cpu = cpu;
207 qemu_process_cpu_events_common(cpu);
208 }
209 }
210
211 rr_start_kick_timer();
212
213 cpu = first_cpu;
214
215 while (1) {
216 /* Only used for icount_enabled() */
217 int64_t cpu_budget = 0;
218
219 if (cpu) {
220 /*
221 * This could even reset exit_request for all CPUs, but in practice
222 * races between CPU exits and changes to "cpu" are so rare that
223 * there's no advantage in doing so.
224 */
225 qatomic_set(&cpu->exit_request, false);
226 }
227
228 if (icount_enabled() && all_cpu_threads_idle()) {
229 /*
230 * When all cpus are sleeping (e.g in WFI), to avoid a deadlock
231 * in the main_loop, wake it up in order to start the warp timer.
232 */
233 qemu_notify_event();
234 }
235
236 rr_wait_io_event();
237 rr_deal_with_unplugged_cpus();
238
239 bql_unlock();
240 replay_mutex_lock();
241 bql_lock();
242
243 if (icount_enabled()) {
244 int cpu_count = rr_cpu_count();
245
246 /* Account partial waits to QEMU_CLOCK_VIRTUAL. */
247 icount_account_warp_timer();
248 /*
249 * Run the timers here. This is much more efficient than
250 * waking up the I/O thread and waiting for completion.
251 */
252 icount_handle_deadline();
253
254 cpu_budget = icount_percpu_budget(cpu_count);
255 }
256
257 replay_mutex_unlock();
258
259 if (!cpu) {
260 cpu = first_cpu;
261 }
262
263 while (cpu && cpu_work_list_empty(cpu)) {
264 /*
265 * Store rr_current_cpu before evaluating cpu->exit_request.
266 * Pairs with rr_kick_next_cpu().
267 */
268 qatomic_set_mb(&rr_current_cpu, cpu);
269
270 /* Pairs with store-release in cpu_exit. */
271 if (qatomic_load_acquire(&cpu->exit_request)) {
272 break;
273 }
274 current_cpu = cpu;
275
276 qemu_clock_enable(QEMU_CLOCK_VIRTUAL,
277 (cpu->singlestep_flags & SSTEP_NOTIMER) == 0);
278
279 if (cpu_can_run(cpu)) {
280 int r;
281
282 bql_unlock();
283 if (icount_enabled()) {
284 icount_prepare_for_run(cpu, cpu_budget);
285 }
286 r = tcg_cpu_exec(cpu);
287 if (icount_enabled()) {
288 icount_process_data(cpu);
289 }
290 bql_lock();
291
292 if (r == EXCP_DEBUG) {
293 cpu_handle_guest_debug(cpu);
294 break;
295 } else if (r == EXCP_ATOMIC) {
296 bql_unlock();
297 cpu_exec_step_atomic(cpu);
298 bql_lock();
299 break;
300 }
301 } else if (cpu->stop) {
302 if (cpu->unplug) {
303 cpu = CPU_NEXT(cpu);
304 }
305 break;
306 }
307
308 cpu = CPU_NEXT(cpu);
309 } /* while (cpu && !cpu->exit_request).. */
310
311 /* Does not need a memory barrier because a spurious wakeup is okay. */
312 qatomic_set(&rr_current_cpu, NULL);
313 }
314
315 g_assert_not_reached();
316 }
317
318 void rr_start_vcpu_thread(CPUState *cpu)
319 {
320 char thread_name[VCPU_THREAD_NAME_SIZE];
321 static QemuCond *single_tcg_halt_cond;
322 static QemuThread *single_tcg_cpu_thread;
323
324 g_assert(tcg_enabled());
325 tcg_cpu_init_cflags(cpu, false);
326
327 if (!single_tcg_cpu_thread) {
328 single_tcg_halt_cond = cpu->halt_cond;
329 single_tcg_cpu_thread = cpu->thread;
330
331 /* share a single thread for all cpus with TCG */
332 snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "ALL CPUs/TCG");
333 qemu_thread_create(cpu->thread, thread_name,
334 rr_cpu_thread_fn,
335 cpu, QEMU_THREAD_JOINABLE);
336 } else {
337 /* we share the thread, dump spare data */
338 g_free(cpu->thread);
339 qemu_cond_destroy(cpu->halt_cond);
340 g_free(cpu->halt_cond);
341 cpu->thread = single_tcg_cpu_thread;
342 cpu->halt_cond = single_tcg_halt_cond;
343
344 /* copy the stuff done at start of rr_cpu_thread_fn */
345 cpu->thread_id = first_cpu->thread_id;
346 cpu->neg.can_do_io = 1;
347 cpu->created = true;
348 }
349 }