1
The following changes since commit 3e08b2b9cb64bff2b73fa9128c0e49bfcde0dd40:
1
The following changes since commit 2ecfc0657afa5d29a373271b342f704a1a3c6737:
2
2
3
Merge remote-tracking branch 'remotes/philmd-gitlab/tags/edk2-next-20200121' into staging (2020-01-21 15:29:25 +0000)
3
Merge remote-tracking branch 'remotes/armbru/tags/pull-misc-2020-12-10' into staging (2020-12-10 17:01:05 +0000)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://github.com/rth7680/qemu.git tags/pull-tcg-20200121
7
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20201210
8
8
9
for you to fetch changes up to 75fa376cdab5e5db2c7fdd107358e16f95503ac6:
9
for you to fetch changes up to 9e2658d62ebc23efe7df43fc0e306f129510d874:
10
10
11
scripts/git.orderfile: Display decodetree before C source (2020-01-21 15:26:09 -1000)
11
accel/tcg: rename tcg-cpus functions to match module name (2020-12-10 17:44:10 -0600)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Remove another limit to NB_MMU_MODES.
14
Split CpusAccel for tcg variants
15
Fix compilation using uclibc.
16
Fix defaulting of -accel parameters.
17
Tidy cputlb basic routines.
18
Adjust git.orderfile for decodetree.
19
15
20
----------------------------------------------------------------
16
----------------------------------------------------------------
21
Carlos Santos (1):
17
Claudio Fontana (3):
22
util/cacheinfo: fix crash when compiling with uClibc
18
accel/tcg: split CpusAccel into three TCG variants
19
accel/tcg: split tcg_start_vcpu_thread
20
accel/tcg: rename tcg-cpus functions to match module name
23
21
24
Philippe Mathieu-Daudé (1):
22
accel/tcg/tcg-cpus-icount.h | 17 ++
25
scripts/git.orderfile: Display decodetree before C source
23
accel/tcg/tcg-cpus-rr.h | 21 ++
24
accel/tcg/tcg-cpus.h | 12 +-
25
accel/tcg/tcg-all.c | 13 +-
26
accel/tcg/tcg-cpus-icount.c | 147 +++++++++++++
27
accel/tcg/tcg-cpus-mttcg.c | 140 ++++++++++++
28
accel/tcg/tcg-cpus-rr.c | 305 ++++++++++++++++++++++++++
29
accel/tcg/tcg-cpus.c | 506 +-------------------------------------------
30
softmmu/icount.c | 2 +-
31
accel/tcg/meson.build | 9 +-
32
10 files changed, 670 insertions(+), 502 deletions(-)
33
create mode 100644 accel/tcg/tcg-cpus-icount.h
34
create mode 100644 accel/tcg/tcg-cpus-rr.h
35
create mode 100644 accel/tcg/tcg-cpus-icount.c
36
create mode 100644 accel/tcg/tcg-cpus-mttcg.c
37
create mode 100644 accel/tcg/tcg-cpus-rr.c
26
38
27
Richard Henderson (14):
28
cputlb: Handle NB_MMU_MODES > TARGET_PAGE_BITS_MIN
29
vl: Remove unused variable in configure_accelerators
30
vl: Reduce scope of variables in configure_accelerators
31
vl: Remove useless test in configure_accelerators
32
vl: Only choose enabled accelerators in configure_accelerators
33
cputlb: Merge tlb_table_flush_by_mmuidx into tlb_flush_one_mmuidx_locked
34
cputlb: Make tlb_n_entries private to cputlb.c
35
cputlb: Pass CPUTLBDescFast to tlb_n_entries and sizeof_tlb
36
cputlb: Hoist tlb portions in tlb_mmu_resize_locked
37
cputlb: Hoist tlb portions in tlb_flush_one_mmuidx_locked
38
cputlb: Split out tlb_mmu_flush_locked
39
cputlb: Partially merge tlb_dyn_init into tlb_init
40
cputlb: Initialize tlbs as flushed
41
cputlb: Hoist timestamp outside of loops over tlbs
42
43
include/exec/cpu_ldst.h | 5 -
44
accel/tcg/cputlb.c | 287 +++++++++++++++++++++++++++++++++---------------
45
util/cacheinfo.c | 10 +-
46
vl.c | 27 +++--
47
scripts/git.orderfile | 3 +
48
5 files changed, 223 insertions(+), 109 deletions(-)
49
diff view generated by jsdifflib
1
There is only one caller for tlb_table_flush_by_mmuidx. Place
1
From: Claudio Fontana <cfontana@suse.de>
2
the result at the earlier line number, due to an expected user
3
in the near future.
4
2
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
split up the CpusAccel tcg_cpus into three TCG variants:
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
4
5
tcg_cpus_rr (single threaded, round robin cpus)
6
tcg_cpus_icount (same as rr, but with instruction counting enabled)
7
tcg_cpus_mttcg (multi-threaded cpus)
8
9
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Claudio Fontana <cfontana@suse.de>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-Id: <20201015143217.29337-2-cfontana@suse.de>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
15
---
9
accel/tcg/cputlb.c | 19 +++++++------------
16
accel/tcg/tcg-cpus-icount.h | 17 ++
10
1 file changed, 7 insertions(+), 12 deletions(-)
17
accel/tcg/tcg-cpus-mttcg.h | 21 ++
18
accel/tcg/tcg-cpus-rr.h | 20 ++
19
accel/tcg/tcg-cpus.h | 13 +-
20
accel/tcg/tcg-all.c | 8 +-
21
accel/tcg/tcg-cpus-icount.c | 147 +++++++++++
22
accel/tcg/tcg-cpus-mttcg.c | 117 +++++++++
23
accel/tcg/tcg-cpus-rr.c | 270 ++++++++++++++++++++
24
accel/tcg/tcg-cpus.c | 484 ++----------------------------------
25
softmmu/icount.c | 2 +-
26
accel/tcg/meson.build | 9 +-
27
11 files changed, 646 insertions(+), 462 deletions(-)
28
create mode 100644 accel/tcg/tcg-cpus-icount.h
29
create mode 100644 accel/tcg/tcg-cpus-mttcg.h
30
create mode 100644 accel/tcg/tcg-cpus-rr.h
31
create mode 100644 accel/tcg/tcg-cpus-icount.c
32
create mode 100644 accel/tcg/tcg-cpus-mttcg.c
33
create mode 100644 accel/tcg/tcg-cpus-rr.c
11
34
12
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
35
diff --git a/accel/tcg/tcg-cpus-icount.h b/accel/tcg/tcg-cpus-icount.h
36
new file mode 100644
37
index XXXXXXX..XXXXXXX
38
--- /dev/null
39
+++ b/accel/tcg/tcg-cpus-icount.h
40
@@ -XXX,XX +XXX,XX @@
41
+/*
42
+ * QEMU TCG Single Threaded vCPUs implementation using instruction counting
43
+ *
44
+ * Copyright 2020 SUSE LLC
45
+ *
46
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
47
+ * See the COPYING file in the top-level directory.
48
+ */
49
+
50
+#ifndef TCG_CPUS_ICOUNT_H
51
+#define TCG_CPUS_ICOUNT_H
52
+
53
+void handle_icount_deadline(void);
54
+void prepare_icount_for_run(CPUState *cpu);
55
+void process_icount_data(CPUState *cpu);
56
+
57
+#endif /* TCG_CPUS_ICOUNT_H */
58
diff --git a/accel/tcg/tcg-cpus-mttcg.h b/accel/tcg/tcg-cpus-mttcg.h
59
new file mode 100644
60
index XXXXXXX..XXXXXXX
61
--- /dev/null
62
+++ b/accel/tcg/tcg-cpus-mttcg.h
63
@@ -XXX,XX +XXX,XX @@
64
+/*
65
+ * QEMU TCG Multi Threaded vCPUs implementation
66
+ *
67
+ * Copyright 2020 SUSE LLC
68
+ *
69
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
70
+ * See the COPYING file in the top-level directory.
71
+ */
72
+
73
+#ifndef TCG_CPUS_MTTCG_H
74
+#define TCG_CPUS_MTTCG_H
75
+
76
+/*
77
+ * In the multi-threaded case each vCPU has its own thread. The TLS
78
+ * variable current_cpu can be used deep in the code to find the
79
+ * current CPUState for a given thread.
80
+ */
81
+
82
+void *tcg_cpu_thread_fn(void *arg);
83
+
84
+#endif /* TCG_CPUS_MTTCG_H */
85
diff --git a/accel/tcg/tcg-cpus-rr.h b/accel/tcg/tcg-cpus-rr.h
86
new file mode 100644
87
index XXXXXXX..XXXXXXX
88
--- /dev/null
89
+++ b/accel/tcg/tcg-cpus-rr.h
90
@@ -XXX,XX +XXX,XX @@
91
+/*
92
+ * QEMU TCG Single Threaded vCPUs implementation
93
+ *
94
+ * Copyright 2020 SUSE LLC
95
+ *
96
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
97
+ * See the COPYING file in the top-level directory.
98
+ */
99
+
100
+#ifndef TCG_CPUS_RR_H
101
+#define TCG_CPUS_RR_H
102
+
103
+#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10)
104
+
105
+/* Kick all RR vCPUs. */
106
+void qemu_cpu_kick_rr_cpus(CPUState *unused);
107
+
108
+void *tcg_rr_cpu_thread_fn(void *arg);
109
+
110
+#endif /* TCG_CPUS_RR_H */
111
diff --git a/accel/tcg/tcg-cpus.h b/accel/tcg/tcg-cpus.h
13
index XXXXXXX..XXXXXXX 100644
112
index XXXXXXX..XXXXXXX 100644
14
--- a/accel/tcg/cputlb.c
113
--- a/accel/tcg/tcg-cpus.h
15
+++ b/accel/tcg/cputlb.c
114
+++ b/accel/tcg/tcg-cpus.h
16
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_resize_locked(CPUArchState *env, int mmu_idx)
115
@@ -XXX,XX +XXX,XX @@
116
/*
117
- * Accelerator CPUS Interface
118
+ * QEMU TCG vCPU common functionality
119
+ *
120
+ * Functionality common to all TCG vcpu variants: mttcg, rr and icount.
121
*
122
* Copyright 2020 SUSE LLC
123
*
124
@@ -XXX,XX +XXX,XX @@
125
126
#include "sysemu/cpus.h"
127
128
-extern const CpusAccel tcg_cpus;
129
+extern const CpusAccel tcg_cpus_mttcg;
130
+extern const CpusAccel tcg_cpus_icount;
131
+extern const CpusAccel tcg_cpus_rr;
132
+
133
+void tcg_start_vcpu_thread(CPUState *cpu);
134
+void qemu_tcg_destroy_vcpu(CPUState *cpu);
135
+int tcg_cpu_exec(CPUState *cpu);
136
+void tcg_handle_interrupt(CPUState *cpu, int mask);
137
138
#endif /* TCG_CPUS_H */
139
diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c
140
index XXXXXXX..XXXXXXX 100644
141
--- a/accel/tcg/tcg-all.c
142
+++ b/accel/tcg/tcg-all.c
143
@@ -XXX,XX +XXX,XX @@ static int tcg_init(MachineState *ms)
144
145
tcg_exec_init(s->tb_size * 1024 * 1024);
146
mttcg_enabled = s->mttcg_enabled;
147
- cpus_register_accel(&tcg_cpus);
148
149
+ if (mttcg_enabled) {
150
+ cpus_register_accel(&tcg_cpus_mttcg);
151
+ } else if (icount_enabled()) {
152
+ cpus_register_accel(&tcg_cpus_icount);
153
+ } else {
154
+ cpus_register_accel(&tcg_cpus_rr);
155
+ }
156
return 0;
157
}
158
159
diff --git a/accel/tcg/tcg-cpus-icount.c b/accel/tcg/tcg-cpus-icount.c
160
new file mode 100644
161
index XXXXXXX..XXXXXXX
162
--- /dev/null
163
+++ b/accel/tcg/tcg-cpus-icount.c
164
@@ -XXX,XX +XXX,XX @@
165
+/*
166
+ * QEMU TCG Single Threaded vCPUs implementation using instruction counting
167
+ *
168
+ * Copyright (c) 2003-2008 Fabrice Bellard
169
+ * Copyright (c) 2014 Red Hat Inc.
170
+ *
171
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
172
+ * of this software and associated documentation files (the "Software"), to deal
173
+ * in the Software without restriction, including without limitation the rights
174
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
175
+ * copies of the Software, and to permit persons to whom the Software is
176
+ * furnished to do so, subject to the following conditions:
177
+ *
178
+ * The above copyright notice and this permission notice shall be included in
179
+ * all copies or substantial portions of the Software.
180
+ *
181
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
182
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
183
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
184
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
185
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
186
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
187
+ * THE SOFTWARE.
188
+ */
189
+
190
+#include "qemu/osdep.h"
191
+#include "qemu-common.h"
192
+#include "sysemu/tcg.h"
193
+#include "sysemu/replay.h"
194
+#include "qemu/main-loop.h"
195
+#include "qemu/guest-random.h"
196
+#include "exec/exec-all.h"
197
+#include "hw/boards.h"
198
+
199
+#include "tcg-cpus.h"
200
+#include "tcg-cpus-icount.h"
201
+#include "tcg-cpus-rr.h"
202
+
203
+static int64_t tcg_get_icount_limit(void)
204
+{
205
+ int64_t deadline;
206
+
207
+ if (replay_mode != REPLAY_MODE_PLAY) {
208
+ /*
209
+ * Include all the timers, because they may need an attention.
210
+ * Too long CPU execution may create unnecessary delay in UI.
211
+ */
212
+ deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
213
+ QEMU_TIMER_ATTR_ALL);
214
+ /* Check realtime timers, because they help with input processing */
215
+ deadline = qemu_soonest_timeout(deadline,
216
+ qemu_clock_deadline_ns_all(QEMU_CLOCK_REALTIME,
217
+ QEMU_TIMER_ATTR_ALL));
218
+
219
+ /*
220
+ * Maintain prior (possibly buggy) behaviour where if no deadline
221
+ * was set (as there is no QEMU_CLOCK_VIRTUAL timer) or it is more than
222
+ * INT32_MAX nanoseconds ahead, we still use INT32_MAX
223
+ * nanoseconds.
224
+ */
225
+ if ((deadline < 0) || (deadline > INT32_MAX)) {
226
+ deadline = INT32_MAX;
227
+ }
228
+
229
+ return icount_round(deadline);
230
+ } else {
231
+ return replay_get_instructions();
232
+ }
233
+}
234
+
235
+static void notify_aio_contexts(void)
236
+{
237
+ /* Wake up other AioContexts. */
238
+ qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
239
+ qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL);
240
+}
241
+
242
+void handle_icount_deadline(void)
243
+{
244
+ assert(qemu_in_vcpu_thread());
245
+ int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
246
+ QEMU_TIMER_ATTR_ALL);
247
+
248
+ if (deadline == 0) {
249
+ notify_aio_contexts();
250
+ }
251
+}
252
+
253
+void prepare_icount_for_run(CPUState *cpu)
254
+{
255
+ int insns_left;
256
+
257
+ /*
258
+ * These should always be cleared by process_icount_data after
259
+ * each vCPU execution. However u16.high can be raised
260
+ * asynchronously by cpu_exit/cpu_interrupt/tcg_handle_interrupt
261
+ */
262
+ g_assert(cpu_neg(cpu)->icount_decr.u16.low == 0);
263
+ g_assert(cpu->icount_extra == 0);
264
+
265
+ cpu->icount_budget = tcg_get_icount_limit();
266
+ insns_left = MIN(0xffff, cpu->icount_budget);
267
+ cpu_neg(cpu)->icount_decr.u16.low = insns_left;
268
+ cpu->icount_extra = cpu->icount_budget - insns_left;
269
+
270
+ replay_mutex_lock();
271
+
272
+ if (cpu->icount_budget == 0 && replay_has_checkpoint()) {
273
+ notify_aio_contexts();
274
+ }
275
+}
276
+
277
+void process_icount_data(CPUState *cpu)
278
+{
279
+ /* Account for executed instructions */
280
+ icount_update(cpu);
281
+
282
+ /* Reset the counters */
283
+ cpu_neg(cpu)->icount_decr.u16.low = 0;
284
+ cpu->icount_extra = 0;
285
+ cpu->icount_budget = 0;
286
+
287
+ replay_account_executed_instructions();
288
+
289
+ replay_mutex_unlock();
290
+}
291
+
292
+static void icount_handle_interrupt(CPUState *cpu, int mask)
293
+{
294
+ int old_mask = cpu->interrupt_request;
295
+
296
+ tcg_handle_interrupt(cpu, mask);
297
+ if (qemu_cpu_is_self(cpu) &&
298
+ !cpu->can_do_io
299
+ && (mask & ~old_mask) != 0) {
300
+ cpu_abort(cpu, "Raised interrupt while not in I/O function");
301
+ }
302
+}
303
+
304
+const CpusAccel tcg_cpus_icount = {
305
+ .create_vcpu_thread = tcg_start_vcpu_thread,
306
+ .kick_vcpu_thread = qemu_cpu_kick_rr_cpus,
307
+
308
+ .handle_interrupt = icount_handle_interrupt,
309
+ .get_virtual_clock = icount_get,
310
+ .get_elapsed_ticks = icount_get,
311
+};
312
diff --git a/accel/tcg/tcg-cpus-mttcg.c b/accel/tcg/tcg-cpus-mttcg.c
313
new file mode 100644
314
index XXXXXXX..XXXXXXX
315
--- /dev/null
316
+++ b/accel/tcg/tcg-cpus-mttcg.c
317
@@ -XXX,XX +XXX,XX @@
318
+/*
319
+ * QEMU TCG Multi Threaded vCPUs implementation
320
+ *
321
+ * Copyright (c) 2003-2008 Fabrice Bellard
322
+ * Copyright (c) 2014 Red Hat Inc.
323
+ *
324
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
325
+ * of this software and associated documentation files (the "Software"), to deal
326
+ * in the Software without restriction, including without limitation the rights
327
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
328
+ * copies of the Software, and to permit persons to whom the Software is
329
+ * furnished to do so, subject to the following conditions:
330
+ *
331
+ * The above copyright notice and this permission notice shall be included in
332
+ * all copies or substantial portions of the Software.
333
+ *
334
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
335
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
336
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
337
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
338
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
339
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
340
+ * THE SOFTWARE.
341
+ */
342
+
343
+#include "qemu/osdep.h"
344
+#include "qemu-common.h"
345
+#include "sysemu/tcg.h"
346
+#include "sysemu/replay.h"
347
+#include "qemu/main-loop.h"
348
+#include "qemu/guest-random.h"
349
+#include "exec/exec-all.h"
350
+#include "hw/boards.h"
351
+
352
+#include "tcg-cpus.h"
353
+#include "tcg-cpus-mttcg.h"
354
+
355
+/*
356
+ * In the multi-threaded case each vCPU has its own thread. The TLS
357
+ * variable current_cpu can be used deep in the code to find the
358
+ * current CPUState for a given thread.
359
+ */
360
+
361
+void *tcg_cpu_thread_fn(void *arg)
362
+{
363
+ CPUState *cpu = arg;
364
+
365
+ assert(tcg_enabled());
366
+ g_assert(!icount_enabled());
367
+
368
+ rcu_register_thread();
369
+ tcg_register_thread();
370
+
371
+ qemu_mutex_lock_iothread();
372
+ qemu_thread_get_self(cpu->thread);
373
+
374
+ cpu->thread_id = qemu_get_thread_id();
375
+ cpu->can_do_io = 1;
376
+ current_cpu = cpu;
377
+ cpu_thread_signal_created(cpu);
378
+ qemu_guest_random_seed_thread_part2(cpu->random_seed);
379
+
380
+ /* process any pending work */
381
+ cpu->exit_request = 1;
382
+
383
+ do {
384
+ if (cpu_can_run(cpu)) {
385
+ int r;
386
+ qemu_mutex_unlock_iothread();
387
+ r = tcg_cpu_exec(cpu);
388
+ qemu_mutex_lock_iothread();
389
+ switch (r) {
390
+ case EXCP_DEBUG:
391
+ cpu_handle_guest_debug(cpu);
392
+ break;
393
+ case EXCP_HALTED:
394
+ /*
395
+ * during start-up the vCPU is reset and the thread is
396
+ * kicked several times. If we don't ensure we go back
397
+ * to sleep in the halted state we won't cleanly
398
+ * start-up when the vCPU is enabled.
399
+ *
400
+ * cpu->halted should ensure we sleep in wait_io_event
401
+ */
402
+ g_assert(cpu->halted);
403
+ break;
404
+ case EXCP_ATOMIC:
405
+ qemu_mutex_unlock_iothread();
406
+ cpu_exec_step_atomic(cpu);
407
+ qemu_mutex_lock_iothread();
408
+ default:
409
+ /* Ignore everything else? */
410
+ break;
411
+ }
412
+ }
413
+
414
+ qatomic_mb_set(&cpu->exit_request, 0);
415
+ qemu_wait_io_event(cpu);
416
+ } while (!cpu->unplug || cpu_can_run(cpu));
417
+
418
+ qemu_tcg_destroy_vcpu(cpu);
419
+ qemu_mutex_unlock_iothread();
420
+ rcu_unregister_thread();
421
+ return NULL;
422
+}
423
+
424
+static void mttcg_kick_vcpu_thread(CPUState *cpu)
425
+{
426
+ cpu_exit(cpu);
427
+}
428
+
429
+const CpusAccel tcg_cpus_mttcg = {
430
+ .create_vcpu_thread = tcg_start_vcpu_thread,
431
+ .kick_vcpu_thread = mttcg_kick_vcpu_thread,
432
+
433
+ .handle_interrupt = tcg_handle_interrupt,
434
+};
435
diff --git a/accel/tcg/tcg-cpus-rr.c b/accel/tcg/tcg-cpus-rr.c
436
new file mode 100644
437
index XXXXXXX..XXXXXXX
438
--- /dev/null
439
+++ b/accel/tcg/tcg-cpus-rr.c
440
@@ -XXX,XX +XXX,XX @@
441
+/*
442
+ * QEMU TCG Single Threaded vCPUs implementation
443
+ *
444
+ * Copyright (c) 2003-2008 Fabrice Bellard
445
+ * Copyright (c) 2014 Red Hat Inc.
446
+ *
447
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
448
+ * of this software and associated documentation files (the "Software"), to deal
449
+ * in the Software without restriction, including without limitation the rights
450
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
451
+ * copies of the Software, and to permit persons to whom the Software is
452
+ * furnished to do so, subject to the following conditions:
453
+ *
454
+ * The above copyright notice and this permission notice shall be included in
455
+ * all copies or substantial portions of the Software.
456
+ *
457
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
458
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
459
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
460
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
461
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
462
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
463
+ * THE SOFTWARE.
464
+ */
465
+
466
+#include "qemu/osdep.h"
467
+#include "qemu-common.h"
468
+#include "sysemu/tcg.h"
469
+#include "sysemu/replay.h"
470
+#include "qemu/main-loop.h"
471
+#include "qemu/guest-random.h"
472
+#include "exec/exec-all.h"
473
+#include "hw/boards.h"
474
+
475
+#include "tcg-cpus.h"
476
+#include "tcg-cpus-rr.h"
477
+#include "tcg-cpus-icount.h"
478
+
479
+/* Kick all RR vCPUs */
480
+void qemu_cpu_kick_rr_cpus(CPUState *unused)
481
+{
482
+ CPUState *cpu;
483
+
484
+ CPU_FOREACH(cpu) {
485
+ cpu_exit(cpu);
486
+ };
487
+}
488
+
489
+/*
490
+ * TCG vCPU kick timer
491
+ *
492
+ * The kick timer is responsible for moving single threaded vCPU
493
+ * emulation on to the next vCPU. If more than one vCPU is running a
494
+ * timer event with force a cpu->exit so the next vCPU can get
495
+ * scheduled.
496
+ *
497
+ * The timer is removed if all vCPUs are idle and restarted again once
498
+ * idleness is complete.
499
+ */
500
+
501
+static QEMUTimer *tcg_kick_vcpu_timer;
502
+static CPUState *tcg_current_rr_cpu;
503
+
504
+#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10)
505
+
506
+static inline int64_t qemu_tcg_next_kick(void)
507
+{
508
+ return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + TCG_KICK_PERIOD;
509
+}
510
+
511
+/* Kick the currently round-robin scheduled vCPU to next */
512
+static void qemu_cpu_kick_rr_next_cpu(void)
513
+{
514
+ CPUState *cpu;
515
+ do {
516
+ cpu = qatomic_mb_read(&tcg_current_rr_cpu);
517
+ if (cpu) {
518
+ cpu_exit(cpu);
519
+ }
520
+ } while (cpu != qatomic_mb_read(&tcg_current_rr_cpu));
521
+}
522
+
523
+static void kick_tcg_thread(void *opaque)
524
+{
525
+ timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick());
526
+ qemu_cpu_kick_rr_next_cpu();
527
+}
528
+
529
+static void start_tcg_kick_timer(void)
530
+{
531
+ if (!tcg_kick_vcpu_timer && CPU_NEXT(first_cpu)) {
532
+ tcg_kick_vcpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
533
+ kick_tcg_thread, NULL);
534
+ }
535
+ if (tcg_kick_vcpu_timer && !timer_pending(tcg_kick_vcpu_timer)) {
536
+ timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick());
537
+ }
538
+}
539
+
540
+static void stop_tcg_kick_timer(void)
541
+{
542
+ if (tcg_kick_vcpu_timer && timer_pending(tcg_kick_vcpu_timer)) {
543
+ timer_del(tcg_kick_vcpu_timer);
544
+ }
545
+}
546
+
547
+static void qemu_tcg_rr_wait_io_event(void)
548
+{
549
+ CPUState *cpu;
550
+
551
+ while (all_cpu_threads_idle()) {
552
+ stop_tcg_kick_timer();
553
+ qemu_cond_wait_iothread(first_cpu->halt_cond);
554
+ }
555
+
556
+ start_tcg_kick_timer();
557
+
558
+ CPU_FOREACH(cpu) {
559
+ qemu_wait_io_event_common(cpu);
560
+ }
561
+}
562
+
563
+/*
564
+ * Destroy any remaining vCPUs which have been unplugged and have
565
+ * finished running
566
+ */
567
+static void deal_with_unplugged_cpus(void)
568
+{
569
+ CPUState *cpu;
570
+
571
+ CPU_FOREACH(cpu) {
572
+ if (cpu->unplug && !cpu_can_run(cpu)) {
573
+ qemu_tcg_destroy_vcpu(cpu);
574
+ break;
575
+ }
576
+ }
577
+}
578
+
579
+/*
580
+ * In the single-threaded case each vCPU is simulated in turn. If
581
+ * there is more than a single vCPU we create a simple timer to kick
582
+ * the vCPU and ensure we don't get stuck in a tight loop in one vCPU.
583
+ * This is done explicitly rather than relying on side-effects
584
+ * elsewhere.
585
+ */
586
+
587
+void *tcg_rr_cpu_thread_fn(void *arg)
588
+{
589
+ CPUState *cpu = arg;
590
+
591
+ assert(tcg_enabled());
592
+ rcu_register_thread();
593
+ tcg_register_thread();
594
+
595
+ qemu_mutex_lock_iothread();
596
+ qemu_thread_get_self(cpu->thread);
597
+
598
+ cpu->thread_id = qemu_get_thread_id();
599
+ cpu->can_do_io = 1;
600
+ cpu_thread_signal_created(cpu);
601
+ qemu_guest_random_seed_thread_part2(cpu->random_seed);
602
+
603
+ /* wait for initial kick-off after machine start */
604
+ while (first_cpu->stopped) {
605
+ qemu_cond_wait_iothread(first_cpu->halt_cond);
606
+
607
+ /* process any pending work */
608
+ CPU_FOREACH(cpu) {
609
+ current_cpu = cpu;
610
+ qemu_wait_io_event_common(cpu);
611
+ }
612
+ }
613
+
614
+ start_tcg_kick_timer();
615
+
616
+ cpu = first_cpu;
617
+
618
+ /* process any pending work */
619
+ cpu->exit_request = 1;
620
+
621
+ while (1) {
622
+ qemu_mutex_unlock_iothread();
623
+ replay_mutex_lock();
624
+ qemu_mutex_lock_iothread();
625
+
626
+ if (icount_enabled()) {
627
+ /* Account partial waits to QEMU_CLOCK_VIRTUAL. */
628
+ icount_account_warp_timer();
629
+ /*
630
+ * Run the timers here. This is much more efficient than
631
+ * waking up the I/O thread and waiting for completion.
632
+ */
633
+ handle_icount_deadline();
634
+ }
635
+
636
+ replay_mutex_unlock();
637
+
638
+ if (!cpu) {
639
+ cpu = first_cpu;
640
+ }
641
+
642
+ while (cpu && cpu_work_list_empty(cpu) && !cpu->exit_request) {
643
+
644
+ qatomic_mb_set(&tcg_current_rr_cpu, cpu);
645
+ current_cpu = cpu;
646
+
647
+ qemu_clock_enable(QEMU_CLOCK_VIRTUAL,
648
+ (cpu->singlestep_enabled & SSTEP_NOTIMER) == 0);
649
+
650
+ if (cpu_can_run(cpu)) {
651
+ int r;
652
+
653
+ qemu_mutex_unlock_iothread();
654
+ if (icount_enabled()) {
655
+ prepare_icount_for_run(cpu);
656
+ }
657
+ r = tcg_cpu_exec(cpu);
658
+ if (icount_enabled()) {
659
+ process_icount_data(cpu);
660
+ }
661
+ qemu_mutex_lock_iothread();
662
+
663
+ if (r == EXCP_DEBUG) {
664
+ cpu_handle_guest_debug(cpu);
665
+ break;
666
+ } else if (r == EXCP_ATOMIC) {
667
+ qemu_mutex_unlock_iothread();
668
+ cpu_exec_step_atomic(cpu);
669
+ qemu_mutex_lock_iothread();
670
+ break;
671
+ }
672
+ } else if (cpu->stop) {
673
+ if (cpu->unplug) {
674
+ cpu = CPU_NEXT(cpu);
675
+ }
676
+ break;
677
+ }
678
+
679
+ cpu = CPU_NEXT(cpu);
680
+ } /* while (cpu && !cpu->exit_request).. */
681
+
682
+ /* Does not need qatomic_mb_set because a spurious wakeup is okay. */
683
+ qatomic_set(&tcg_current_rr_cpu, NULL);
684
+
685
+ if (cpu && cpu->exit_request) {
686
+ qatomic_mb_set(&cpu->exit_request, 0);
687
+ }
688
+
689
+ if (icount_enabled() && all_cpu_threads_idle()) {
690
+ /*
691
+ * When all cpus are sleeping (e.g in WFI), to avoid a deadlock
692
+ * in the main_loop, wake it up in order to start the warp timer.
693
+ */
694
+ qemu_notify_event();
695
+ }
696
+
697
+ qemu_tcg_rr_wait_io_event();
698
+ deal_with_unplugged_cpus();
699
+ }
700
+
701
+ rcu_unregister_thread();
702
+ return NULL;
703
+}
704
+
705
+const CpusAccel tcg_cpus_rr = {
706
+ .create_vcpu_thread = tcg_start_vcpu_thread,
707
+ .kick_vcpu_thread = qemu_cpu_kick_rr_cpus,
708
+
709
+ .handle_interrupt = tcg_handle_interrupt,
710
+};
711
diff --git a/accel/tcg/tcg-cpus.c b/accel/tcg/tcg-cpus.c
712
index XXXXXXX..XXXXXXX 100644
713
--- a/accel/tcg/tcg-cpus.c
714
+++ b/accel/tcg/tcg-cpus.c
715
@@ -XXX,XX +XXX,XX @@
716
/*
717
- * QEMU System Emulator
718
+ * QEMU TCG vCPU common functionality
719
+ *
720
+ * Functionality common to all TCG vCPU variants: mttcg, rr and icount.
721
*
722
* Copyright (c) 2003-2008 Fabrice Bellard
723
* Copyright (c) 2014 Red Hat Inc.
724
@@ -XXX,XX +XXX,XX @@
725
#include "hw/boards.h"
726
727
#include "tcg-cpus.h"
728
+#include "tcg-cpus-mttcg.h"
729
+#include "tcg-cpus-rr.h"
730
731
-/* Kick all RR vCPUs */
732
-static void qemu_cpu_kick_rr_cpus(void)
733
-{
734
- CPUState *cpu;
735
+/* common functionality among all TCG variants */
736
737
- CPU_FOREACH(cpu) {
738
- cpu_exit(cpu);
739
- };
740
-}
741
-
742
-static void tcg_kick_vcpu_thread(CPUState *cpu)
743
-{
744
- if (qemu_tcg_mttcg_enabled()) {
745
- cpu_exit(cpu);
746
- } else {
747
- qemu_cpu_kick_rr_cpus();
748
- }
749
-}
750
-
751
-/*
752
- * TCG vCPU kick timer
753
- *
754
- * The kick timer is responsible for moving single threaded vCPU
755
- * emulation on to the next vCPU. If more than one vCPU is running a
756
- * timer event with force a cpu->exit so the next vCPU can get
757
- * scheduled.
758
- *
759
- * The timer is removed if all vCPUs are idle and restarted again once
760
- * idleness is complete.
761
- */
762
-
763
-static QEMUTimer *tcg_kick_vcpu_timer;
764
-static CPUState *tcg_current_rr_cpu;
765
-
766
-#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10)
767
-
768
-static inline int64_t qemu_tcg_next_kick(void)
769
-{
770
- return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + TCG_KICK_PERIOD;
771
-}
772
-
773
-/* Kick the currently round-robin scheduled vCPU to next */
774
-static void qemu_cpu_kick_rr_next_cpu(void)
775
-{
776
- CPUState *cpu;
777
- do {
778
- cpu = qatomic_mb_read(&tcg_current_rr_cpu);
779
- if (cpu) {
780
- cpu_exit(cpu);
781
- }
782
- } while (cpu != qatomic_mb_read(&tcg_current_rr_cpu));
783
-}
784
-
785
-static void kick_tcg_thread(void *opaque)
786
-{
787
- timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick());
788
- qemu_cpu_kick_rr_next_cpu();
789
-}
790
-
791
-static void start_tcg_kick_timer(void)
792
-{
793
- assert(!mttcg_enabled);
794
- if (!tcg_kick_vcpu_timer && CPU_NEXT(first_cpu)) {
795
- tcg_kick_vcpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
796
- kick_tcg_thread, NULL);
797
- }
798
- if (tcg_kick_vcpu_timer && !timer_pending(tcg_kick_vcpu_timer)) {
799
- timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick());
800
- }
801
-}
802
-
803
-static void stop_tcg_kick_timer(void)
804
-{
805
- assert(!mttcg_enabled);
806
- if (tcg_kick_vcpu_timer && timer_pending(tcg_kick_vcpu_timer)) {
807
- timer_del(tcg_kick_vcpu_timer);
808
- }
809
-}
810
-
811
-static void qemu_tcg_destroy_vcpu(CPUState *cpu)
812
-{
813
-}
814
-
815
-static void qemu_tcg_rr_wait_io_event(void)
816
-{
817
- CPUState *cpu;
818
-
819
- while (all_cpu_threads_idle()) {
820
- stop_tcg_kick_timer();
821
- qemu_cond_wait_iothread(first_cpu->halt_cond);
822
- }
823
-
824
- start_tcg_kick_timer();
825
-
826
- CPU_FOREACH(cpu) {
827
- qemu_wait_io_event_common(cpu);
828
- }
829
-}
830
-
831
-static int64_t tcg_get_icount_limit(void)
832
-{
833
- int64_t deadline;
834
-
835
- if (replay_mode != REPLAY_MODE_PLAY) {
836
- /*
837
- * Include all the timers, because they may need an attention.
838
- * Too long CPU execution may create unnecessary delay in UI.
839
- */
840
- deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
841
- QEMU_TIMER_ATTR_ALL);
842
- /* Check realtime timers, because they help with input processing */
843
- deadline = qemu_soonest_timeout(deadline,
844
- qemu_clock_deadline_ns_all(QEMU_CLOCK_REALTIME,
845
- QEMU_TIMER_ATTR_ALL));
846
-
847
- /*
848
- * Maintain prior (possibly buggy) behaviour where if no deadline
849
- * was set (as there is no QEMU_CLOCK_VIRTUAL timer) or it is more than
850
- * INT32_MAX nanoseconds ahead, we still use INT32_MAX
851
- * nanoseconds.
852
- */
853
- if ((deadline < 0) || (deadline > INT32_MAX)) {
854
- deadline = INT32_MAX;
855
- }
856
-
857
- return icount_round(deadline);
858
- } else {
859
- return replay_get_instructions();
860
- }
861
-}
862
-
863
-static void notify_aio_contexts(void)
864
-{
865
- /* Wake up other AioContexts. */
866
- qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
867
- qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL);
868
-}
869
-
870
-static void handle_icount_deadline(void)
871
-{
872
- assert(qemu_in_vcpu_thread());
873
- if (icount_enabled()) {
874
- int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
875
- QEMU_TIMER_ATTR_ALL);
876
-
877
- if (deadline == 0) {
878
- notify_aio_contexts();
879
- }
880
- }
881
-}
882
-
883
-static void prepare_icount_for_run(CPUState *cpu)
884
-{
885
- if (icount_enabled()) {
886
- int insns_left;
887
-
888
- /*
889
- * These should always be cleared by process_icount_data after
890
- * each vCPU execution. However u16.high can be raised
891
- * asynchronously by cpu_exit/cpu_interrupt/tcg_handle_interrupt
892
- */
893
- g_assert(cpu_neg(cpu)->icount_decr.u16.low == 0);
894
- g_assert(cpu->icount_extra == 0);
895
-
896
- cpu->icount_budget = tcg_get_icount_limit();
897
- insns_left = MIN(0xffff, cpu->icount_budget);
898
- cpu_neg(cpu)->icount_decr.u16.low = insns_left;
899
- cpu->icount_extra = cpu->icount_budget - insns_left;
900
-
901
- replay_mutex_lock();
902
-
903
- if (cpu->icount_budget == 0 && replay_has_checkpoint()) {
904
- notify_aio_contexts();
905
- }
906
- }
907
-}
908
-
909
-static void process_icount_data(CPUState *cpu)
910
-{
911
- if (icount_enabled()) {
912
- /* Account for executed instructions */
913
- icount_update(cpu);
914
-
915
- /* Reset the counters */
916
- cpu_neg(cpu)->icount_decr.u16.low = 0;
917
- cpu->icount_extra = 0;
918
- cpu->icount_budget = 0;
919
-
920
- replay_account_executed_instructions();
921
-
922
- replay_mutex_unlock();
923
- }
924
-}
925
-
926
-static int tcg_cpu_exec(CPUState *cpu)
927
-{
928
- int ret;
929
-#ifdef CONFIG_PROFILER
930
- int64_t ti;
931
-#endif
932
-
933
- assert(tcg_enabled());
934
-#ifdef CONFIG_PROFILER
935
- ti = profile_getclock();
936
-#endif
937
- cpu_exec_start(cpu);
938
- ret = cpu_exec(cpu);
939
- cpu_exec_end(cpu);
940
-#ifdef CONFIG_PROFILER
941
- qatomic_set(&tcg_ctx->prof.cpu_exec_time,
942
- tcg_ctx->prof.cpu_exec_time + profile_getclock() - ti);
943
-#endif
944
- return ret;
945
-}
946
-
947
-/*
948
- * Destroy any remaining vCPUs which have been unplugged and have
949
- * finished running
950
- */
951
-static void deal_with_unplugged_cpus(void)
952
-{
953
- CPUState *cpu;
954
-
955
- CPU_FOREACH(cpu) {
956
- if (cpu->unplug && !cpu_can_run(cpu)) {
957
- qemu_tcg_destroy_vcpu(cpu);
958
- cpu_thread_signal_destroyed(cpu);
959
- break;
960
- }
961
- }
962
-}
963
-
964
-/*
965
- * Single-threaded TCG
966
- *
967
- * In the single-threaded case each vCPU is simulated in turn. If
968
- * there is more than a single vCPU we create a simple timer to kick
969
- * the vCPU and ensure we don't get stuck in a tight loop in one vCPU.
970
- * This is done explicitly rather than relying on side-effects
971
- * elsewhere.
972
- */
973
-
974
-static void *tcg_rr_cpu_thread_fn(void *arg)
975
-{
976
- CPUState *cpu = arg;
977
-
978
- assert(tcg_enabled());
979
- rcu_register_thread();
980
- tcg_register_thread();
981
-
982
- qemu_mutex_lock_iothread();
983
- qemu_thread_get_self(cpu->thread);
984
-
985
- cpu->thread_id = qemu_get_thread_id();
986
- cpu->can_do_io = 1;
987
- cpu_thread_signal_created(cpu);
988
- qemu_guest_random_seed_thread_part2(cpu->random_seed);
989
-
990
- /* wait for initial kick-off after machine start */
991
- while (first_cpu->stopped) {
992
- qemu_cond_wait_iothread(first_cpu->halt_cond);
993
-
994
- /* process any pending work */
995
- CPU_FOREACH(cpu) {
996
- current_cpu = cpu;
997
- qemu_wait_io_event_common(cpu);
998
- }
999
- }
1000
-
1001
- start_tcg_kick_timer();
1002
-
1003
- cpu = first_cpu;
1004
-
1005
- /* process any pending work */
1006
- cpu->exit_request = 1;
1007
-
1008
- while (1) {
1009
- qemu_mutex_unlock_iothread();
1010
- replay_mutex_lock();
1011
- qemu_mutex_lock_iothread();
1012
- /* Account partial waits to QEMU_CLOCK_VIRTUAL. */
1013
- icount_account_warp_timer();
1014
-
1015
- /*
1016
- * Run the timers here. This is much more efficient than
1017
- * waking up the I/O thread and waiting for completion.
1018
- */
1019
- handle_icount_deadline();
1020
-
1021
- replay_mutex_unlock();
1022
-
1023
- if (!cpu) {
1024
- cpu = first_cpu;
1025
- }
1026
-
1027
- while (cpu && cpu_work_list_empty(cpu) && !cpu->exit_request) {
1028
-
1029
- qatomic_mb_set(&tcg_current_rr_cpu, cpu);
1030
- current_cpu = cpu;
1031
-
1032
- qemu_clock_enable(QEMU_CLOCK_VIRTUAL,
1033
- (cpu->singlestep_enabled & SSTEP_NOTIMER) == 0);
1034
-
1035
- if (cpu_can_run(cpu)) {
1036
- int r;
1037
-
1038
- qemu_mutex_unlock_iothread();
1039
- prepare_icount_for_run(cpu);
1040
-
1041
- r = tcg_cpu_exec(cpu);
1042
-
1043
- process_icount_data(cpu);
1044
- qemu_mutex_lock_iothread();
1045
-
1046
- if (r == EXCP_DEBUG) {
1047
- cpu_handle_guest_debug(cpu);
1048
- break;
1049
- } else if (r == EXCP_ATOMIC) {
1050
- qemu_mutex_unlock_iothread();
1051
- cpu_exec_step_atomic(cpu);
1052
- qemu_mutex_lock_iothread();
1053
- break;
1054
- }
1055
- } else if (cpu->stop) {
1056
- if (cpu->unplug) {
1057
- cpu = CPU_NEXT(cpu);
1058
- }
1059
- break;
1060
- }
1061
-
1062
- cpu = CPU_NEXT(cpu);
1063
- } /* while (cpu && !cpu->exit_request).. */
1064
-
1065
- /* Does not need qatomic_mb_set because a spurious wakeup is okay. */
1066
- qatomic_set(&tcg_current_rr_cpu, NULL);
1067
-
1068
- if (cpu && cpu->exit_request) {
1069
- qatomic_mb_set(&cpu->exit_request, 0);
1070
- }
1071
-
1072
- if (icount_enabled() && all_cpu_threads_idle()) {
1073
- /*
1074
- * When all cpus are sleeping (e.g in WFI), to avoid a deadlock
1075
- * in the main_loop, wake it up in order to start the warp timer.
1076
- */
1077
- qemu_notify_event();
1078
- }
1079
-
1080
- qemu_tcg_rr_wait_io_event();
1081
- deal_with_unplugged_cpus();
1082
- }
1083
-
1084
- rcu_unregister_thread();
1085
- return NULL;
1086
-}
1087
-
1088
-/*
1089
- * Multi-threaded TCG
1090
- *
1091
- * In the multi-threaded case each vCPU has its own thread. The TLS
1092
- * variable current_cpu can be used deep in the code to find the
1093
- * current CPUState for a given thread.
1094
- */
1095
-
1096
-static void *tcg_cpu_thread_fn(void *arg)
1097
-{
1098
- CPUState *cpu = arg;
1099
-
1100
- assert(tcg_enabled());
1101
- g_assert(!icount_enabled());
1102
-
1103
- rcu_register_thread();
1104
- tcg_register_thread();
1105
-
1106
- qemu_mutex_lock_iothread();
1107
- qemu_thread_get_self(cpu->thread);
1108
-
1109
- cpu->thread_id = qemu_get_thread_id();
1110
- cpu->can_do_io = 1;
1111
- current_cpu = cpu;
1112
- cpu_thread_signal_created(cpu);
1113
- qemu_guest_random_seed_thread_part2(cpu->random_seed);
1114
-
1115
- /* process any pending work */
1116
- cpu->exit_request = 1;
1117
-
1118
- do {
1119
- if (cpu_can_run(cpu)) {
1120
- int r;
1121
- qemu_mutex_unlock_iothread();
1122
- r = tcg_cpu_exec(cpu);
1123
- qemu_mutex_lock_iothread();
1124
- switch (r) {
1125
- case EXCP_DEBUG:
1126
- cpu_handle_guest_debug(cpu);
1127
- break;
1128
- case EXCP_HALTED:
1129
- /*
1130
- * during start-up the vCPU is reset and the thread is
1131
- * kicked several times. If we don't ensure we go back
1132
- * to sleep in the halted state we won't cleanly
1133
- * start-up when the vCPU is enabled.
1134
- *
1135
- * cpu->halted should ensure we sleep in wait_io_event
1136
- */
1137
- g_assert(cpu->halted);
1138
- break;
1139
- case EXCP_ATOMIC:
1140
- qemu_mutex_unlock_iothread();
1141
- cpu_exec_step_atomic(cpu);
1142
- qemu_mutex_lock_iothread();
1143
- default:
1144
- /* Ignore everything else? */
1145
- break;
1146
- }
1147
- }
1148
-
1149
- qatomic_mb_set(&cpu->exit_request, 0);
1150
- qemu_wait_io_event(cpu);
1151
- } while (!cpu->unplug || cpu_can_run(cpu));
1152
-
1153
- qemu_tcg_destroy_vcpu(cpu);
1154
- cpu_thread_signal_destroyed(cpu);
1155
- qemu_mutex_unlock_iothread();
1156
- rcu_unregister_thread();
1157
- return NULL;
1158
-}
1159
-
1160
-static void tcg_start_vcpu_thread(CPUState *cpu)
1161
+void tcg_start_vcpu_thread(CPUState *cpu)
1162
{
1163
char thread_name[VCPU_THREAD_NAME_SIZE];
1164
static QemuCond *single_tcg_halt_cond;
1165
@@ -XXX,XX +XXX,XX @@ static void tcg_start_vcpu_thread(CPUState *cpu)
17
}
1166
}
18
}
1167
}
19
1168
20
-static inline void tlb_table_flush_by_mmuidx(CPUArchState *env, int mmu_idx)
1169
-static int64_t tcg_get_virtual_clock(void)
21
+static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
1170
+void qemu_tcg_destroy_vcpu(CPUState *cpu)
22
{
1171
{
23
tlb_mmu_resize_locked(env, mmu_idx);
1172
- if (icount_enabled()) {
24
- memset(env_tlb(env)->f[mmu_idx].table, -1, sizeof_tlb(env, mmu_idx));
1173
- return icount_get();
25
env_tlb(env)->d[mmu_idx].n_used_entries = 0;
1174
- }
26
+ env_tlb(env)->d[mmu_idx].large_page_addr = -1;
1175
- return cpu_get_clock();
27
+ env_tlb(env)->d[mmu_idx].large_page_mask = -1;
1176
+ cpu_thread_signal_destroyed(cpu);
28
+ env_tlb(env)->d[mmu_idx].vindex = 0;
29
+ memset(env_tlb(env)->f[mmu_idx].table, -1, sizeof_tlb(env, mmu_idx));
30
+ memset(env_tlb(env)->d[mmu_idx].vtable, -1,
31
+ sizeof(env_tlb(env)->d[0].vtable));
32
}
1177
}
33
1178
34
static inline void tlb_n_used_entries_inc(CPUArchState *env, uintptr_t mmu_idx)
1179
-static int64_t tcg_get_elapsed_ticks(void)
35
@@ -XXX,XX +XXX,XX @@ void tlb_flush_counts(size_t *pfull, size_t *ppart, size_t *pelide)
1180
+int tcg_cpu_exec(CPUState *cpu)
36
*pelide = elide;
1181
{
1182
- if (icount_enabled()) {
1183
- return icount_get();
1184
- }
1185
- return cpu_get_ticks();
1186
+ int ret;
1187
+#ifdef CONFIG_PROFILER
1188
+ int64_t ti;
1189
+#endif
1190
+ assert(tcg_enabled());
1191
+#ifdef CONFIG_PROFILER
1192
+ ti = profile_getclock();
1193
+#endif
1194
+ cpu_exec_start(cpu);
1195
+ ret = cpu_exec(cpu);
1196
+ cpu_exec_end(cpu);
1197
+#ifdef CONFIG_PROFILER
1198
+ qatomic_set(&tcg_ctx->prof.cpu_exec_time,
1199
+ tcg_ctx->prof.cpu_exec_time + profile_getclock() - ti);
1200
+#endif
1201
+ return ret;
37
}
1202
}
38
1203
39
-static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
1204
/* mask must never be zero, except for A20 change call */
40
-{
1205
-static void tcg_handle_interrupt(CPUState *cpu, int mask)
41
- tlb_table_flush_by_mmuidx(env, mmu_idx);
1206
+void tcg_handle_interrupt(CPUState *cpu, int mask)
42
- env_tlb(env)->d[mmu_idx].large_page_addr = -1;
43
- env_tlb(env)->d[mmu_idx].large_page_mask = -1;
44
- env_tlb(env)->d[mmu_idx].vindex = 0;
45
- memset(env_tlb(env)->d[mmu_idx].vtable, -1,
46
- sizeof(env_tlb(env)->d[0].vtable));
47
-}
48
-
49
static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
50
{
1207
{
51
CPUArchState *env = cpu->env_ptr;
1208
- int old_mask;
1209
g_assert(qemu_mutex_iothread_locked());
1210
1211
- old_mask = cpu->interrupt_request;
1212
cpu->interrupt_request |= mask;
1213
1214
/*
1215
@@ -XXX,XX +XXX,XX @@ static void tcg_handle_interrupt(CPUState *cpu, int mask)
1216
qemu_cpu_kick(cpu);
1217
} else {
1218
qatomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1);
1219
- if (icount_enabled() &&
1220
- !cpu->can_do_io
1221
- && (mask & ~old_mask) != 0) {
1222
- cpu_abort(cpu, "Raised interrupt while not in I/O function");
1223
- }
1224
}
1225
}
1226
-
1227
-const CpusAccel tcg_cpus = {
1228
- .create_vcpu_thread = tcg_start_vcpu_thread,
1229
- .kick_vcpu_thread = tcg_kick_vcpu_thread,
1230
-
1231
- .handle_interrupt = tcg_handle_interrupt,
1232
-
1233
- .get_virtual_clock = tcg_get_virtual_clock,
1234
- .get_elapsed_ticks = tcg_get_elapsed_ticks,
1235
-};
1236
diff --git a/softmmu/icount.c b/softmmu/icount.c
1237
index XXXXXXX..XXXXXXX 100644
1238
--- a/softmmu/icount.c
1239
+++ b/softmmu/icount.c
1240
@@ -XXX,XX +XXX,XX @@ void icount_start_warp_timer(void)
1241
1242
void icount_account_warp_timer(void)
1243
{
1244
- if (!icount_enabled() || !icount_sleep) {
1245
+ if (!icount_sleep) {
1246
return;
1247
}
1248
1249
diff --git a/accel/tcg/meson.build b/accel/tcg/meson.build
1250
index XXXXXXX..XXXXXXX 100644
1251
--- a/accel/tcg/meson.build
1252
+++ b/accel/tcg/meson.build
1253
@@ -XXX,XX +XXX,XX @@ tcg_ss.add(when: 'CONFIG_SOFTMMU', if_false: files('user-exec-stub.c'))
1254
tcg_ss.add(when: 'CONFIG_PLUGIN', if_true: [files('plugin-gen.c'), libdl])
1255
specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss)
1256
1257
-specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: files('tcg-all.c', 'cputlb.c', 'tcg-cpus.c'))
1258
+specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: files(
1259
+ 'tcg-all.c',
1260
+ 'cputlb.c',
1261
+ 'tcg-cpus.c',
1262
+ 'tcg-cpus-mttcg.c',
1263
+ 'tcg-cpus-icount.c',
1264
+ 'tcg-cpus-rr.c'
1265
+))
52
--
1266
--
53
2.20.1
1267
2.25.1
54
1268
55
1269
diff view generated by jsdifflib
1
In target/arm we will shortly have "too many" mmu_idx.
1
From: Claudio Fontana <cfontana@suse.de>
2
The current minimum barrier is caused by the way in which
2
3
tlb_flush_page_by_mmuidx is coded.
3
after the initial split into 3 tcg variants, we proceed to also
4
4
split tcg_start_vcpu_thread.
5
We can remove this limitation by allocating memory for
5
6
consumption by the worker. Let us assume that this is
6
We actually split it in 2 this time, since the icount variant
7
the unlikely case, as will be the case for the majority
7
just uses the round robin function.
8
of targets which have so far satisfied the BUILD_BUG_ON,
8
9
and only allocate memory when necessary.
9
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
10
10
Signed-off-by: Claudio Fontana <cfontana@suse.de>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-Id: <20201015143217.29337-3-cfontana@suse.de>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
---
13
---
14
accel/tcg/cputlb.c | 167 +++++++++++++++++++++++++++++++++++----------
14
accel/tcg/tcg-cpus-mttcg.h | 21 --------------
15
1 file changed, 132 insertions(+), 35 deletions(-)
15
accel/tcg/tcg-cpus-rr.h | 3 +-
16
16
accel/tcg/tcg-cpus.h | 1 -
17
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
17
accel/tcg/tcg-all.c | 5 ++++
18
index XXXXXXX..XXXXXXX 100644
18
accel/tcg/tcg-cpus-icount.c | 2 +-
19
--- a/accel/tcg/cputlb.c
19
accel/tcg/tcg-cpus-mttcg.c | 29 +++++++++++++++++--
20
+++ b/accel/tcg/cputlb.c
20
accel/tcg/tcg-cpus-rr.c | 39 +++++++++++++++++++++++--
21
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_locked(CPUArchState *env, int midx,
21
accel/tcg/tcg-cpus.c | 58 -------------------------------------
22
}
22
8 files changed, 71 insertions(+), 87 deletions(-)
23
delete mode 100644 accel/tcg/tcg-cpus-mttcg.h
24
25
diff --git a/accel/tcg/tcg-cpus-mttcg.h b/accel/tcg/tcg-cpus-mttcg.h
26
deleted file mode 100644
27
index XXXXXXX..XXXXXXX
28
--- a/accel/tcg/tcg-cpus-mttcg.h
29
+++ /dev/null
30
@@ -XXX,XX +XXX,XX @@
31
-/*
32
- * QEMU TCG Multi Threaded vCPUs implementation
33
- *
34
- * Copyright 2020 SUSE LLC
35
- *
36
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
37
- * See the COPYING file in the top-level directory.
38
- */
39
-
40
-#ifndef TCG_CPUS_MTTCG_H
41
-#define TCG_CPUS_MTTCG_H
42
-
43
-/*
44
- * In the multi-threaded case each vCPU has its own thread. The TLS
45
- * variable current_cpu can be used deep in the code to find the
46
- * current CPUState for a given thread.
47
- */
48
-
49
-void *tcg_cpu_thread_fn(void *arg);
50
-
51
-#endif /* TCG_CPUS_MTTCG_H */
52
diff --git a/accel/tcg/tcg-cpus-rr.h b/accel/tcg/tcg-cpus-rr.h
53
index XXXXXXX..XXXXXXX 100644
54
--- a/accel/tcg/tcg-cpus-rr.h
55
+++ b/accel/tcg/tcg-cpus-rr.h
56
@@ -XXX,XX +XXX,XX @@
57
/* Kick all RR vCPUs. */
58
void qemu_cpu_kick_rr_cpus(CPUState *unused);
59
60
-void *tcg_rr_cpu_thread_fn(void *arg);
61
+/* start the round robin vcpu thread */
62
+void rr_start_vcpu_thread(CPUState *cpu);
63
64
#endif /* TCG_CPUS_RR_H */
65
diff --git a/accel/tcg/tcg-cpus.h b/accel/tcg/tcg-cpus.h
66
index XXXXXXX..XXXXXXX 100644
67
--- a/accel/tcg/tcg-cpus.h
68
+++ b/accel/tcg/tcg-cpus.h
69
@@ -XXX,XX +XXX,XX @@ extern const CpusAccel tcg_cpus_mttcg;
70
extern const CpusAccel tcg_cpus_icount;
71
extern const CpusAccel tcg_cpus_rr;
72
73
-void tcg_start_vcpu_thread(CPUState *cpu);
74
void qemu_tcg_destroy_vcpu(CPUState *cpu);
75
int tcg_cpu_exec(CPUState *cpu);
76
void tcg_handle_interrupt(CPUState *cpu, int mask);
77
diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/accel/tcg/tcg-all.c
80
+++ b/accel/tcg/tcg-all.c
81
@@ -XXX,XX +XXX,XX @@ static int tcg_init(MachineState *ms)
82
tcg_exec_init(s->tb_size * 1024 * 1024);
83
mttcg_enabled = s->mttcg_enabled;
84
85
+ /*
86
+ * Initialize TCG regions
87
+ */
88
+ tcg_region_init();
89
+
90
if (mttcg_enabled) {
91
cpus_register_accel(&tcg_cpus_mttcg);
92
} else if (icount_enabled()) {
93
diff --git a/accel/tcg/tcg-cpus-icount.c b/accel/tcg/tcg-cpus-icount.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/accel/tcg/tcg-cpus-icount.c
96
+++ b/accel/tcg/tcg-cpus-icount.c
97
@@ -XXX,XX +XXX,XX @@ static void icount_handle_interrupt(CPUState *cpu, int mask)
23
}
98
}
24
99
25
-/* As we are going to hijack the bottom bits of the page address for a
100
const CpusAccel tcg_cpus_icount = {
26
- * mmuidx bit mask we need to fail to build if we can't do that
101
- .create_vcpu_thread = tcg_start_vcpu_thread,
27
+/**
102
+ .create_vcpu_thread = rr_start_vcpu_thread,
28
+ * tlb_flush_page_by_mmuidx_async_0:
103
.kick_vcpu_thread = qemu_cpu_kick_rr_cpus,
29
+ * @cpu: cpu on which to flush
104
30
+ * @addr: page of virtual address to flush
105
.handle_interrupt = icount_handle_interrupt,
31
+ * @idxmap: set of mmu_idx to flush
106
diff --git a/accel/tcg/tcg-cpus-mttcg.c b/accel/tcg/tcg-cpus-mttcg.c
32
+ *
107
index XXXXXXX..XXXXXXX 100644
33
+ * Helper for tlb_flush_page_by_mmuidx and friends, flush one page
108
--- a/accel/tcg/tcg-cpus-mttcg.c
34
+ * at @addr from the tlbs indicated by @idxmap from @cpu.
109
+++ b/accel/tcg/tcg-cpus-mttcg.c
110
@@ -XXX,XX +XXX,XX @@
111
#include "hw/boards.h"
112
113
#include "tcg-cpus.h"
114
-#include "tcg-cpus-mttcg.h"
115
116
/*
117
* In the multi-threaded case each vCPU has its own thread. The TLS
118
@@ -XXX,XX +XXX,XX @@
119
* current CPUState for a given thread.
35
*/
120
*/
36
-QEMU_BUILD_BUG_ON(NB_MMU_MODES > TARGET_PAGE_BITS_MIN);
121
37
-
122
-void *tcg_cpu_thread_fn(void *arg)
38
-static void tlb_flush_page_by_mmuidx_async_work(CPUState *cpu,
123
+static void *tcg_cpu_thread_fn(void *arg)
39
- run_on_cpu_data data)
40
+static void tlb_flush_page_by_mmuidx_async_0(CPUState *cpu,
41
+ target_ulong addr,
42
+ uint16_t idxmap)
43
{
124
{
44
CPUArchState *env = cpu->env_ptr;
125
CPUState *cpu = arg;
45
- target_ulong addr_and_mmuidx = (target_ulong) data.target_ptr;
126
46
- target_ulong addr = addr_and_mmuidx & TARGET_PAGE_MASK;
127
@@ -XXX,XX +XXX,XX @@ static void mttcg_kick_vcpu_thread(CPUState *cpu)
47
- unsigned long mmu_idx_bitmap = addr_and_mmuidx & ALL_MMUIDX_BITS;
128
cpu_exit(cpu);
48
int mmu_idx;
49
50
assert_cpu_is_self(cpu);
51
52
- tlb_debug("page addr:" TARGET_FMT_lx " mmu_map:0x%lx\n",
53
- addr, mmu_idx_bitmap);
54
+ tlb_debug("page addr:" TARGET_FMT_lx " mmu_map:0x%x\n", addr, idxmap);
55
56
qemu_spin_lock(&env_tlb(env)->c.lock);
57
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
58
- if (test_bit(mmu_idx, &mmu_idx_bitmap)) {
59
+ if ((idxmap >> mmu_idx) & 1) {
60
tlb_flush_page_locked(env, mmu_idx, addr);
61
}
62
}
63
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_by_mmuidx_async_work(CPUState *cpu,
64
tb_flush_jmp_cache(cpu, addr);
65
}
129
}
66
130
67
+/**
131
+static void mttcg_start_vcpu_thread(CPUState *cpu)
68
+ * tlb_flush_page_by_mmuidx_async_1:
69
+ * @cpu: cpu on which to flush
70
+ * @data: encoded addr + idxmap
71
+ *
72
+ * Helper for tlb_flush_page_by_mmuidx and friends, called through
73
+ * async_run_on_cpu. The idxmap parameter is encoded in the page
74
+ * offset of the target_ptr field. This limits the set of mmu_idx
75
+ * that can be passed via this method.
76
+ */
77
+static void tlb_flush_page_by_mmuidx_async_1(CPUState *cpu,
78
+ run_on_cpu_data data)
79
+{
132
+{
80
+ target_ulong addr_and_idxmap = (target_ulong) data.target_ptr;
133
+ char thread_name[VCPU_THREAD_NAME_SIZE];
81
+ target_ulong addr = addr_and_idxmap & TARGET_PAGE_MASK;
134
+
82
+ uint16_t idxmap = addr_and_idxmap & ~TARGET_PAGE_MASK;
135
+ g_assert(tcg_enabled());
83
+
136
+
84
+ tlb_flush_page_by_mmuidx_async_0(cpu, addr, idxmap);
137
+ parallel_cpus = (current_machine->smp.max_cpus > 1);
138
+
139
+ cpu->thread = g_malloc0(sizeof(QemuThread));
140
+ cpu->halt_cond = g_malloc0(sizeof(QemuCond));
141
+ qemu_cond_init(cpu->halt_cond);
142
+
143
+ /* create a thread per vCPU with TCG (MTTCG) */
144
+ snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/TCG",
145
+ cpu->cpu_index);
146
+
147
+ qemu_thread_create(cpu->thread, thread_name, tcg_cpu_thread_fn,
148
+ cpu, QEMU_THREAD_JOINABLE);
149
+
150
+#ifdef _WIN32
151
+ cpu->hThread = qemu_thread_get_handle(cpu->thread);
152
+#endif
85
+}
153
+}
86
+
154
+
87
+typedef struct {
155
const CpusAccel tcg_cpus_mttcg = {
88
+ target_ulong addr;
156
- .create_vcpu_thread = tcg_start_vcpu_thread,
89
+ uint16_t idxmap;
157
+ .create_vcpu_thread = mttcg_start_vcpu_thread,
90
+} TLBFlushPageByMMUIdxData;
158
.kick_vcpu_thread = mttcg_kick_vcpu_thread,
91
+
159
92
+/**
160
.handle_interrupt = tcg_handle_interrupt,
93
+ * tlb_flush_page_by_mmuidx_async_2:
161
diff --git a/accel/tcg/tcg-cpus-rr.c b/accel/tcg/tcg-cpus-rr.c
94
+ * @cpu: cpu on which to flush
162
index XXXXXXX..XXXXXXX 100644
95
+ * @data: allocated addr + idxmap
163
--- a/accel/tcg/tcg-cpus-rr.c
96
+ *
164
+++ b/accel/tcg/tcg-cpus-rr.c
97
+ * Helper for tlb_flush_page_by_mmuidx and friends, called through
165
@@ -XXX,XX +XXX,XX @@ static void deal_with_unplugged_cpus(void)
98
+ * async_run_on_cpu. The addr+idxmap parameters are stored in a
166
* elsewhere.
99
+ * TLBFlushPageByMMUIdxData structure that has been allocated
167
*/
100
+ * specifically for this helper. Free the structure when done.
168
101
+ */
169
-void *tcg_rr_cpu_thread_fn(void *arg)
102
+static void tlb_flush_page_by_mmuidx_async_2(CPUState *cpu,
170
+static void *tcg_rr_cpu_thread_fn(void *arg)
103
+ run_on_cpu_data data)
171
{
172
CPUState *cpu = arg;
173
174
@@ -XXX,XX +XXX,XX @@ void *tcg_rr_cpu_thread_fn(void *arg)
175
return NULL;
176
}
177
178
+void rr_start_vcpu_thread(CPUState *cpu)
104
+{
179
+{
105
+ TLBFlushPageByMMUIdxData *d = data.host_ptr;
180
+ char thread_name[VCPU_THREAD_NAME_SIZE];
106
+
181
+ static QemuCond *single_tcg_halt_cond;
107
+ tlb_flush_page_by_mmuidx_async_0(cpu, d->addr, d->idxmap);
182
+ static QemuThread *single_tcg_cpu_thread;
108
+ g_free(d);
183
+
184
+ g_assert(tcg_enabled());
185
+ parallel_cpus = false;
186
+
187
+ if (!single_tcg_cpu_thread) {
188
+ cpu->thread = g_malloc0(sizeof(QemuThread));
189
+ cpu->halt_cond = g_malloc0(sizeof(QemuCond));
190
+ qemu_cond_init(cpu->halt_cond);
191
+
192
+ /* share a single thread for all cpus with TCG */
193
+ snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "ALL CPUs/TCG");
194
+ qemu_thread_create(cpu->thread, thread_name,
195
+ tcg_rr_cpu_thread_fn,
196
+ cpu, QEMU_THREAD_JOINABLE);
197
+
198
+ single_tcg_halt_cond = cpu->halt_cond;
199
+ single_tcg_cpu_thread = cpu->thread;
200
+#ifdef _WIN32
201
+ cpu->hThread = qemu_thread_get_handle(cpu->thread);
202
+#endif
203
+ } else {
204
+ /* we share the thread */
205
+ cpu->thread = single_tcg_cpu_thread;
206
+ cpu->halt_cond = single_tcg_halt_cond;
207
+ cpu->thread_id = first_cpu->thread_id;
208
+ cpu->can_do_io = 1;
209
+ cpu->created = true;
210
+ }
109
+}
211
+}
110
+
212
+
111
void tlb_flush_page_by_mmuidx(CPUState *cpu, target_ulong addr, uint16_t idxmap)
213
const CpusAccel tcg_cpus_rr = {
214
- .create_vcpu_thread = tcg_start_vcpu_thread,
215
+ .create_vcpu_thread = rr_start_vcpu_thread,
216
.kick_vcpu_thread = qemu_cpu_kick_rr_cpus,
217
218
.handle_interrupt = tcg_handle_interrupt,
219
diff --git a/accel/tcg/tcg-cpus.c b/accel/tcg/tcg-cpus.c
220
index XXXXXXX..XXXXXXX 100644
221
--- a/accel/tcg/tcg-cpus.c
222
+++ b/accel/tcg/tcg-cpus.c
223
@@ -XXX,XX +XXX,XX @@
224
#include "hw/boards.h"
225
226
#include "tcg-cpus.h"
227
-#include "tcg-cpus-mttcg.h"
228
-#include "tcg-cpus-rr.h"
229
230
/* common functionality among all TCG variants */
231
232
-void tcg_start_vcpu_thread(CPUState *cpu)
233
-{
234
- char thread_name[VCPU_THREAD_NAME_SIZE];
235
- static QemuCond *single_tcg_halt_cond;
236
- static QemuThread *single_tcg_cpu_thread;
237
- static int tcg_region_inited;
238
-
239
- assert(tcg_enabled());
240
- /*
241
- * Initialize TCG regions--once. Now is a good time, because:
242
- * (1) TCG's init context, prologue and target globals have been set up.
243
- * (2) qemu_tcg_mttcg_enabled() works now (TCG init code runs before the
244
- * -accel flag is processed, so the check doesn't work then).
245
- */
246
- if (!tcg_region_inited) {
247
- tcg_region_inited = 1;
248
- tcg_region_init();
249
- parallel_cpus = qemu_tcg_mttcg_enabled() && current_machine->smp.max_cpus > 1;
250
- }
251
-
252
- if (qemu_tcg_mttcg_enabled() || !single_tcg_cpu_thread) {
253
- cpu->thread = g_malloc0(sizeof(QemuThread));
254
- cpu->halt_cond = g_malloc0(sizeof(QemuCond));
255
- qemu_cond_init(cpu->halt_cond);
256
-
257
- if (qemu_tcg_mttcg_enabled()) {
258
- /* create a thread per vCPU with TCG (MTTCG) */
259
- snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/TCG",
260
- cpu->cpu_index);
261
-
262
- qemu_thread_create(cpu->thread, thread_name, tcg_cpu_thread_fn,
263
- cpu, QEMU_THREAD_JOINABLE);
264
-
265
- } else {
266
- /* share a single thread for all cpus with TCG */
267
- snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "ALL CPUs/TCG");
268
- qemu_thread_create(cpu->thread, thread_name,
269
- tcg_rr_cpu_thread_fn,
270
- cpu, QEMU_THREAD_JOINABLE);
271
-
272
- single_tcg_halt_cond = cpu->halt_cond;
273
- single_tcg_cpu_thread = cpu->thread;
274
- }
275
-#ifdef _WIN32
276
- cpu->hThread = qemu_thread_get_handle(cpu->thread);
277
-#endif
278
- } else {
279
- /* For non-MTTCG cases we share the thread */
280
- cpu->thread = single_tcg_cpu_thread;
281
- cpu->halt_cond = single_tcg_halt_cond;
282
- cpu->thread_id = first_cpu->thread_id;
283
- cpu->can_do_io = 1;
284
- cpu->created = true;
285
- }
286
-}
287
-
288
void qemu_tcg_destroy_vcpu(CPUState *cpu)
112
{
289
{
113
- target_ulong addr_and_mmu_idx;
290
cpu_thread_signal_destroyed(cpu);
114
-
115
tlb_debug("addr: "TARGET_FMT_lx" mmu_idx:%" PRIx16 "\n", addr, idxmap);
116
117
/* This should already be page aligned */
118
- addr_and_mmu_idx = addr & TARGET_PAGE_MASK;
119
- addr_and_mmu_idx |= idxmap;
120
+ addr &= TARGET_PAGE_MASK;
121
122
- if (!qemu_cpu_is_self(cpu)) {
123
- async_run_on_cpu(cpu, tlb_flush_page_by_mmuidx_async_work,
124
- RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
125
+ if (qemu_cpu_is_self(cpu)) {
126
+ tlb_flush_page_by_mmuidx_async_0(cpu, addr, idxmap);
127
+ } else if (idxmap < TARGET_PAGE_SIZE) {
128
+ /*
129
+ * Most targets have only a few mmu_idx. In the case where
130
+ * we can stuff idxmap into the low TARGET_PAGE_BITS, avoid
131
+ * allocating memory for this operation.
132
+ */
133
+ async_run_on_cpu(cpu, tlb_flush_page_by_mmuidx_async_1,
134
+ RUN_ON_CPU_TARGET_PTR(addr | idxmap));
135
} else {
136
- tlb_flush_page_by_mmuidx_async_work(
137
- cpu, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
138
+ TLBFlushPageByMMUIdxData *d = g_new(TLBFlushPageByMMUIdxData, 1);
139
+
140
+ /* Otherwise allocate a structure, freed by the worker. */
141
+ d->addr = addr;
142
+ d->idxmap = idxmap;
143
+ async_run_on_cpu(cpu, tlb_flush_page_by_mmuidx_async_2,
144
+ RUN_ON_CPU_HOST_PTR(d));
145
}
146
}
147
148
@@ -XXX,XX +XXX,XX @@ void tlb_flush_page(CPUState *cpu, target_ulong addr)
149
void tlb_flush_page_by_mmuidx_all_cpus(CPUState *src_cpu, target_ulong addr,
150
uint16_t idxmap)
151
{
152
- const run_on_cpu_func fn = tlb_flush_page_by_mmuidx_async_work;
153
- target_ulong addr_and_mmu_idx;
154
-
155
tlb_debug("addr: "TARGET_FMT_lx" mmu_idx:%"PRIx16"\n", addr, idxmap);
156
157
/* This should already be page aligned */
158
- addr_and_mmu_idx = addr & TARGET_PAGE_MASK;
159
- addr_and_mmu_idx |= idxmap;
160
+ addr &= TARGET_PAGE_MASK;
161
162
- flush_all_helper(src_cpu, fn, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
163
- fn(src_cpu, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
164
+ /*
165
+ * Allocate memory to hold addr+idxmap only when needed.
166
+ * See tlb_flush_page_by_mmuidx for details.
167
+ */
168
+ if (idxmap < TARGET_PAGE_SIZE) {
169
+ flush_all_helper(src_cpu, tlb_flush_page_by_mmuidx_async_1,
170
+ RUN_ON_CPU_TARGET_PTR(addr | idxmap));
171
+ } else {
172
+ CPUState *dst_cpu;
173
+
174
+ /* Allocate a separate data block for each destination cpu. */
175
+ CPU_FOREACH(dst_cpu) {
176
+ if (dst_cpu != src_cpu) {
177
+ TLBFlushPageByMMUIdxData *d
178
+ = g_new(TLBFlushPageByMMUIdxData, 1);
179
+
180
+ d->addr = addr;
181
+ d->idxmap = idxmap;
182
+ async_run_on_cpu(dst_cpu, tlb_flush_page_by_mmuidx_async_2,
183
+ RUN_ON_CPU_HOST_PTR(d));
184
+ }
185
+ }
186
+ }
187
+
188
+ tlb_flush_page_by_mmuidx_async_0(src_cpu, addr, idxmap);
189
}
190
191
void tlb_flush_page_all_cpus(CPUState *src, target_ulong addr)
192
@@ -XXX,XX +XXX,XX @@ void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
193
target_ulong addr,
194
uint16_t idxmap)
195
{
196
- const run_on_cpu_func fn = tlb_flush_page_by_mmuidx_async_work;
197
- target_ulong addr_and_mmu_idx;
198
-
199
tlb_debug("addr: "TARGET_FMT_lx" mmu_idx:%"PRIx16"\n", addr, idxmap);
200
201
/* This should already be page aligned */
202
- addr_and_mmu_idx = addr & TARGET_PAGE_MASK;
203
- addr_and_mmu_idx |= idxmap;
204
+ addr &= TARGET_PAGE_MASK;
205
206
- flush_all_helper(src_cpu, fn, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
207
- async_safe_run_on_cpu(src_cpu, fn, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
208
+ /*
209
+ * Allocate memory to hold addr+idxmap only when needed.
210
+ * See tlb_flush_page_by_mmuidx for details.
211
+ */
212
+ if (idxmap < TARGET_PAGE_SIZE) {
213
+ flush_all_helper(src_cpu, tlb_flush_page_by_mmuidx_async_1,
214
+ RUN_ON_CPU_TARGET_PTR(addr | idxmap));
215
+ async_safe_run_on_cpu(src_cpu, tlb_flush_page_by_mmuidx_async_1,
216
+ RUN_ON_CPU_TARGET_PTR(addr | idxmap));
217
+ } else {
218
+ CPUState *dst_cpu;
219
+ TLBFlushPageByMMUIdxData *d;
220
+
221
+ /* Allocate a separate data block for each destination cpu. */
222
+ CPU_FOREACH(dst_cpu) {
223
+ if (dst_cpu != src_cpu) {
224
+ d = g_new(TLBFlushPageByMMUIdxData, 1);
225
+ d->addr = addr;
226
+ d->idxmap = idxmap;
227
+ async_run_on_cpu(dst_cpu, tlb_flush_page_by_mmuidx_async_2,
228
+ RUN_ON_CPU_HOST_PTR(d));
229
+ }
230
+ }
231
+
232
+ d = g_new(TLBFlushPageByMMUIdxData, 1);
233
+ d->addr = addr;
234
+ d->idxmap = idxmap;
235
+ async_safe_run_on_cpu(src_cpu, tlb_flush_page_by_mmuidx_async_2,
236
+ RUN_ON_CPU_HOST_PTR(d));
237
+ }
238
}
239
240
void tlb_flush_page_all_cpus_synced(CPUState *src, target_ulong addr)
241
--
291
--
242
2.20.1
292
2.25.1
243
293
244
294
diff view generated by jsdifflib
Deleted patch
1
From: Carlos Santos <casantos@redhat.com>
2
1
3
uClibc defines _SC_LEVEL1_ICACHE_LINESIZE and _SC_LEVEL1_DCACHE_LINESIZE
4
but the corresponding sysconf calls returns -1, which is a valid result,
5
meaning that the limit is indeterminate.
6
7
Handle this situation using the fallback values instead of crashing due
8
to an assertion failure.
9
10
Signed-off-by: Carlos Santos <casantos@redhat.com>
11
Message-Id: <20191017123713.30192-1-casantos@redhat.com>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
---
14
util/cacheinfo.c | 10 ++++++++--
15
1 file changed, 8 insertions(+), 2 deletions(-)
16
17
diff --git a/util/cacheinfo.c b/util/cacheinfo.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/util/cacheinfo.c
20
+++ b/util/cacheinfo.c
21
@@ -XXX,XX +XXX,XX @@ static void sys_cache_info(int *isize, int *dsize)
22
static void sys_cache_info(int *isize, int *dsize)
23
{
24
# ifdef _SC_LEVEL1_ICACHE_LINESIZE
25
- *isize = sysconf(_SC_LEVEL1_ICACHE_LINESIZE);
26
+ int tmp_isize = (int) sysconf(_SC_LEVEL1_ICACHE_LINESIZE);
27
+ if (tmp_isize > 0) {
28
+ *isize = tmp_isize;
29
+ }
30
# endif
31
# ifdef _SC_LEVEL1_DCACHE_LINESIZE
32
- *dsize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
33
+ int tmp_dsize = (int) sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
34
+ if (tmp_dsize > 0) {
35
+ *dsize = tmp_dsize;
36
+ }
37
# endif
38
}
39
#endif /* sys_cache_info */
40
--
41
2.20.1
42
43
diff view generated by jsdifflib
Deleted patch
1
The accel_initialised variable no longer has any setters.
2
1
3
Fixes: 6f6e1698a68c
4
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed by: Aleksandar Markovic <amarkovic@wavecomp.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
10
vl.c | 3 +--
11
1 file changed, 1 insertion(+), 2 deletions(-)
12
13
diff --git a/vl.c b/vl.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/vl.c
16
+++ b/vl.c
17
@@ -XXX,XX +XXX,XX @@ static void configure_accelerators(const char *progname)
18
{
19
const char *accel;
20
char **accel_list, **tmp;
21
- bool accel_initialised = false;
22
bool init_failed = false;
23
24
qemu_opts_foreach(qemu_find_opts("icount"),
25
@@ -XXX,XX +XXX,XX @@ static void configure_accelerators(const char *progname)
26
27
accel_list = g_strsplit(accel, ":", 0);
28
29
- for (tmp = accel_list; !accel_initialised && tmp && *tmp; tmp++) {
30
+ for (tmp = accel_list; tmp && *tmp; tmp++) {
31
/*
32
* Filter invalid accelerators here, to prevent obscenities
33
* such as "-machine accel=tcg,,thread=single".
34
--
35
2.20.1
36
37
diff view generated by jsdifflib
Deleted patch
1
The accel_list and tmp variables are only used when manufacturing
2
-machine accel, options based on -accel.
3
1
4
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed by: Aleksandar Markovic <amarkovic@wavecomp.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
vl.c | 3 ++-
10
1 file changed, 2 insertions(+), 1 deletion(-)
11
12
diff --git a/vl.c b/vl.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/vl.c
15
+++ b/vl.c
16
@@ -XXX,XX +XXX,XX @@ static int do_configure_accelerator(void *opaque, QemuOpts *opts, Error **errp)
17
static void configure_accelerators(const char *progname)
18
{
19
const char *accel;
20
- char **accel_list, **tmp;
21
bool init_failed = false;
22
23
qemu_opts_foreach(qemu_find_opts("icount"),
24
@@ -XXX,XX +XXX,XX @@ static void configure_accelerators(const char *progname)
25
26
accel = qemu_opt_get(qemu_get_machine_opts(), "accel");
27
if (QTAILQ_EMPTY(&qemu_accel_opts.head)) {
28
+ char **accel_list, **tmp;
29
+
30
if (accel == NULL) {
31
/* Select the default accelerator */
32
if (!accel_find("tcg") && !accel_find("kvm")) {
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
Deleted patch
1
The result of g_strsplit is never NULL.
2
1
3
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed by: Aleksandar Markovic <amarkovic@wavecomp.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
vl.c | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
11
12
diff --git a/vl.c b/vl.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/vl.c
15
+++ b/vl.c
16
@@ -XXX,XX +XXX,XX @@ static void configure_accelerators(const char *progname)
17
18
accel_list = g_strsplit(accel, ":", 0);
19
20
- for (tmp = accel_list; tmp && *tmp; tmp++) {
21
+ for (tmp = accel_list; *tmp; tmp++) {
22
/*
23
* Filter invalid accelerators here, to prevent obscenities
24
* such as "-machine accel=tcg,,thread=single".
25
--
26
2.20.1
27
28
diff view generated by jsdifflib
Deleted patch
1
By choosing "tcg:kvm" when kvm is not enabled, we generate
2
an incorrect warning: "invalid accelerator kvm".
3
1
4
At the same time, use g_str_has_suffix rather than open-coding
5
the same operation.
6
7
Presumably the inverse is also true with --disable-tcg.
8
9
Fixes: 28a0961757fc
10
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Reviewed by: Aleksandar Markovic <amarkovic@wavecomp.com>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
---
15
vl.c | 21 +++++++++++++--------
16
1 file changed, 13 insertions(+), 8 deletions(-)
17
18
diff --git a/vl.c b/vl.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/vl.c
21
+++ b/vl.c
22
@@ -XXX,XX +XXX,XX @@ static void configure_accelerators(const char *progname)
23
24
if (accel == NULL) {
25
/* Select the default accelerator */
26
- if (!accel_find("tcg") && !accel_find("kvm")) {
27
- error_report("No accelerator selected and"
28
- " no default accelerator available");
29
- exit(1);
30
- } else {
31
- int pnlen = strlen(progname);
32
- if (pnlen >= 3 && g_str_equal(&progname[pnlen - 3], "kvm")) {
33
+ bool have_tcg = accel_find("tcg");
34
+ bool have_kvm = accel_find("kvm");
35
+
36
+ if (have_tcg && have_kvm) {
37
+ if (g_str_has_suffix(progname, "kvm")) {
38
/* If the program name ends with "kvm", we prefer KVM */
39
accel = "kvm:tcg";
40
} else {
41
accel = "tcg:kvm";
42
}
43
+ } else if (have_kvm) {
44
+ accel = "kvm";
45
+ } else if (have_tcg) {
46
+ accel = "tcg";
47
+ } else {
48
+ error_report("No accelerator selected and"
49
+ " no default accelerator available");
50
+ exit(1);
51
}
52
}
53
-
54
accel_list = g_strsplit(accel, ":", 0);
55
56
for (tmp = accel_list; *tmp; tmp++) {
57
--
58
2.20.1
59
60
diff view generated by jsdifflib
Deleted patch
1
There are no users of this function outside cputlb.c,
2
and its interface will change in the next patch.
3
1
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
include/exec/cpu_ldst.h | 5 -----
10
accel/tcg/cputlb.c | 5 +++++
11
2 files changed, 5 insertions(+), 5 deletions(-)
12
13
diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/exec/cpu_ldst.h
16
+++ b/include/exec/cpu_ldst.h
17
@@ -XXX,XX +XXX,XX @@ static inline uintptr_t tlb_index(CPUArchState *env, uintptr_t mmu_idx,
18
return (addr >> TARGET_PAGE_BITS) & size_mask;
19
}
20
21
-static inline size_t tlb_n_entries(CPUArchState *env, uintptr_t mmu_idx)
22
-{
23
- return (env_tlb(env)->f[mmu_idx].mask >> CPU_TLB_ENTRY_BITS) + 1;
24
-}
25
-
26
/* Find the TLB entry corresponding to the mmu_idx + address pair. */
27
static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx,
28
target_ulong addr)
29
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/accel/tcg/cputlb.c
32
+++ b/accel/tcg/cputlb.c
33
@@ -XXX,XX +XXX,XX @@ QEMU_BUILD_BUG_ON(sizeof(target_ulong) > sizeof(run_on_cpu_data));
34
QEMU_BUILD_BUG_ON(NB_MMU_MODES > 16);
35
#define ALL_MMUIDX_BITS ((1 << NB_MMU_MODES) - 1)
36
37
+static inline size_t tlb_n_entries(CPUArchState *env, uintptr_t mmu_idx)
38
+{
39
+ return (env_tlb(env)->f[mmu_idx].mask >> CPU_TLB_ENTRY_BITS) + 1;
40
+}
41
+
42
static inline size_t sizeof_tlb(CPUArchState *env, uintptr_t mmu_idx)
43
{
44
return env_tlb(env)->f[mmu_idx].mask + (1 << CPU_TLB_ENTRY_BITS);
45
--
46
2.20.1
47
48
diff view generated by jsdifflib
Deleted patch
1
We do not need the entire CPUArchState to compute these values.
2
1
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
accel/tcg/cputlb.c | 15 ++++++++-------
9
1 file changed, 8 insertions(+), 7 deletions(-)
10
11
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/accel/tcg/cputlb.c
14
+++ b/accel/tcg/cputlb.c
15
@@ -XXX,XX +XXX,XX @@ QEMU_BUILD_BUG_ON(sizeof(target_ulong) > sizeof(run_on_cpu_data));
16
QEMU_BUILD_BUG_ON(NB_MMU_MODES > 16);
17
#define ALL_MMUIDX_BITS ((1 << NB_MMU_MODES) - 1)
18
19
-static inline size_t tlb_n_entries(CPUArchState *env, uintptr_t mmu_idx)
20
+static inline size_t tlb_n_entries(CPUTLBDescFast *fast)
21
{
22
- return (env_tlb(env)->f[mmu_idx].mask >> CPU_TLB_ENTRY_BITS) + 1;
23
+ return (fast->mask >> CPU_TLB_ENTRY_BITS) + 1;
24
}
25
26
-static inline size_t sizeof_tlb(CPUArchState *env, uintptr_t mmu_idx)
27
+static inline size_t sizeof_tlb(CPUTLBDescFast *fast)
28
{
29
- return env_tlb(env)->f[mmu_idx].mask + (1 << CPU_TLB_ENTRY_BITS);
30
+ return fast->mask + (1 << CPU_TLB_ENTRY_BITS);
31
}
32
33
static void tlb_window_reset(CPUTLBDesc *desc, int64_t ns,
34
@@ -XXX,XX +XXX,XX @@ static void tlb_dyn_init(CPUArchState *env)
35
static void tlb_mmu_resize_locked(CPUArchState *env, int mmu_idx)
36
{
37
CPUTLBDesc *desc = &env_tlb(env)->d[mmu_idx];
38
- size_t old_size = tlb_n_entries(env, mmu_idx);
39
+ size_t old_size = tlb_n_entries(&env_tlb(env)->f[mmu_idx]);
40
size_t rate;
41
size_t new_size = old_size;
42
int64_t now = get_clock_realtime();
43
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
44
env_tlb(env)->d[mmu_idx].large_page_addr = -1;
45
env_tlb(env)->d[mmu_idx].large_page_mask = -1;
46
env_tlb(env)->d[mmu_idx].vindex = 0;
47
- memset(env_tlb(env)->f[mmu_idx].table, -1, sizeof_tlb(env, mmu_idx));
48
+ memset(env_tlb(env)->f[mmu_idx].table, -1,
49
+ sizeof_tlb(&env_tlb(env)->f[mmu_idx]));
50
memset(env_tlb(env)->d[mmu_idx].vtable, -1,
51
sizeof(env_tlb(env)->d[0].vtable));
52
}
53
@@ -XXX,XX +XXX,XX @@ void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length)
54
qemu_spin_lock(&env_tlb(env)->c.lock);
55
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
56
unsigned int i;
57
- unsigned int n = tlb_n_entries(env, mmu_idx);
58
+ unsigned int n = tlb_n_entries(&env_tlb(env)->f[mmu_idx]);
59
60
for (i = 0; i < n; i++) {
61
tlb_reset_dirty_range_locked(&env_tlb(env)->f[mmu_idx].table[i],
62
--
63
2.20.1
64
65
diff view generated by jsdifflib
Deleted patch
1
No functional change, but the smaller expressions make
2
the code easier to read.
3
1
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
accel/tcg/cputlb.c | 35 +++++++++++++++++------------------
10
1 file changed, 17 insertions(+), 18 deletions(-)
11
12
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/accel/tcg/cputlb.c
15
+++ b/accel/tcg/cputlb.c
16
@@ -XXX,XX +XXX,XX @@ static void tlb_dyn_init(CPUArchState *env)
17
18
/**
19
* tlb_mmu_resize_locked() - perform TLB resize bookkeeping; resize if necessary
20
- * @env: CPU that owns the TLB
21
- * @mmu_idx: MMU index of the TLB
22
+ * @desc: The CPUTLBDesc portion of the TLB
23
+ * @fast: The CPUTLBDescFast portion of the same TLB
24
*
25
* Called with tlb_lock_held.
26
*
27
@@ -XXX,XX +XXX,XX @@ static void tlb_dyn_init(CPUArchState *env)
28
* high), since otherwise we are likely to have a significant amount of
29
* conflict misses.
30
*/
31
-static void tlb_mmu_resize_locked(CPUArchState *env, int mmu_idx)
32
+static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast)
33
{
34
- CPUTLBDesc *desc = &env_tlb(env)->d[mmu_idx];
35
- size_t old_size = tlb_n_entries(&env_tlb(env)->f[mmu_idx]);
36
+ size_t old_size = tlb_n_entries(fast);
37
size_t rate;
38
size_t new_size = old_size;
39
int64_t now = get_clock_realtime();
40
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_resize_locked(CPUArchState *env, int mmu_idx)
41
return;
42
}
43
44
- g_free(env_tlb(env)->f[mmu_idx].table);
45
- g_free(env_tlb(env)->d[mmu_idx].iotlb);
46
+ g_free(fast->table);
47
+ g_free(desc->iotlb);
48
49
tlb_window_reset(desc, now, 0);
50
/* desc->n_used_entries is cleared by the caller */
51
- env_tlb(env)->f[mmu_idx].mask = (new_size - 1) << CPU_TLB_ENTRY_BITS;
52
- env_tlb(env)->f[mmu_idx].table = g_try_new(CPUTLBEntry, new_size);
53
- env_tlb(env)->d[mmu_idx].iotlb = g_try_new(CPUIOTLBEntry, new_size);
54
+ fast->mask = (new_size - 1) << CPU_TLB_ENTRY_BITS;
55
+ fast->table = g_try_new(CPUTLBEntry, new_size);
56
+ desc->iotlb = g_try_new(CPUIOTLBEntry, new_size);
57
+
58
/*
59
* If the allocations fail, try smaller sizes. We just freed some
60
* memory, so going back to half of new_size has a good chance of working.
61
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_resize_locked(CPUArchState *env, int mmu_idx)
62
* allocations to fail though, so we progressively reduce the allocation
63
* size, aborting if we cannot even allocate the smallest TLB we support.
64
*/
65
- while (env_tlb(env)->f[mmu_idx].table == NULL ||
66
- env_tlb(env)->d[mmu_idx].iotlb == NULL) {
67
+ while (fast->table == NULL || desc->iotlb == NULL) {
68
if (new_size == (1 << CPU_TLB_DYN_MIN_BITS)) {
69
error_report("%s: %s", __func__, strerror(errno));
70
abort();
71
}
72
new_size = MAX(new_size >> 1, 1 << CPU_TLB_DYN_MIN_BITS);
73
- env_tlb(env)->f[mmu_idx].mask = (new_size - 1) << CPU_TLB_ENTRY_BITS;
74
+ fast->mask = (new_size - 1) << CPU_TLB_ENTRY_BITS;
75
76
- g_free(env_tlb(env)->f[mmu_idx].table);
77
- g_free(env_tlb(env)->d[mmu_idx].iotlb);
78
- env_tlb(env)->f[mmu_idx].table = g_try_new(CPUTLBEntry, new_size);
79
- env_tlb(env)->d[mmu_idx].iotlb = g_try_new(CPUIOTLBEntry, new_size);
80
+ g_free(fast->table);
81
+ g_free(desc->iotlb);
82
+ fast->table = g_try_new(CPUTLBEntry, new_size);
83
+ desc->iotlb = g_try_new(CPUIOTLBEntry, new_size);
84
}
85
}
86
87
static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
88
{
89
- tlb_mmu_resize_locked(env, mmu_idx);
90
+ tlb_mmu_resize_locked(&env_tlb(env)->d[mmu_idx], &env_tlb(env)->f[mmu_idx]);
91
env_tlb(env)->d[mmu_idx].n_used_entries = 0;
92
env_tlb(env)->d[mmu_idx].large_page_addr = -1;
93
env_tlb(env)->d[mmu_idx].large_page_mask = -1;
94
--
95
2.20.1
96
97
diff view generated by jsdifflib
Deleted patch
1
No functional change, but the smaller expressions make
2
the code easier to read.
3
1
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
accel/tcg/cputlb.c | 19 ++++++++++---------
10
1 file changed, 10 insertions(+), 9 deletions(-)
11
12
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/accel/tcg/cputlb.c
15
+++ b/accel/tcg/cputlb.c
16
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast)
17
18
static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
19
{
20
- tlb_mmu_resize_locked(&env_tlb(env)->d[mmu_idx], &env_tlb(env)->f[mmu_idx]);
21
- env_tlb(env)->d[mmu_idx].n_used_entries = 0;
22
- env_tlb(env)->d[mmu_idx].large_page_addr = -1;
23
- env_tlb(env)->d[mmu_idx].large_page_mask = -1;
24
- env_tlb(env)->d[mmu_idx].vindex = 0;
25
- memset(env_tlb(env)->f[mmu_idx].table, -1,
26
- sizeof_tlb(&env_tlb(env)->f[mmu_idx]));
27
- memset(env_tlb(env)->d[mmu_idx].vtable, -1,
28
- sizeof(env_tlb(env)->d[0].vtable));
29
+ CPUTLBDesc *desc = &env_tlb(env)->d[mmu_idx];
30
+ CPUTLBDescFast *fast = &env_tlb(env)->f[mmu_idx];
31
+
32
+ tlb_mmu_resize_locked(desc, fast);
33
+ desc->n_used_entries = 0;
34
+ desc->large_page_addr = -1;
35
+ desc->large_page_mask = -1;
36
+ desc->vindex = 0;
37
+ memset(fast->table, -1, sizeof_tlb(fast));
38
+ memset(desc->vtable, -1, sizeof(desc->vtable));
39
}
40
41
static inline void tlb_n_used_entries_inc(CPUArchState *env, uintptr_t mmu_idx)
42
--
43
2.20.1
44
45
diff view generated by jsdifflib
Deleted patch
1
We will want to be able to flush a tlb without resizing.
2
1
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
accel/tcg/cputlb.c | 15 ++++++++++-----
9
1 file changed, 10 insertions(+), 5 deletions(-)
10
11
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/accel/tcg/cputlb.c
14
+++ b/accel/tcg/cputlb.c
15
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast)
16
}
17
}
18
19
-static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
20
+static void tlb_mmu_flush_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast)
21
{
22
- CPUTLBDesc *desc = &env_tlb(env)->d[mmu_idx];
23
- CPUTLBDescFast *fast = &env_tlb(env)->f[mmu_idx];
24
-
25
- tlb_mmu_resize_locked(desc, fast);
26
desc->n_used_entries = 0;
27
desc->large_page_addr = -1;
28
desc->large_page_mask = -1;
29
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
30
memset(desc->vtable, -1, sizeof(desc->vtable));
31
}
32
33
+static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
34
+{
35
+ CPUTLBDesc *desc = &env_tlb(env)->d[mmu_idx];
36
+ CPUTLBDescFast *fast = &env_tlb(env)->f[mmu_idx];
37
+
38
+ tlb_mmu_resize_locked(desc, fast);
39
+ tlb_mmu_flush_locked(desc, fast);
40
+}
41
+
42
static inline void tlb_n_used_entries_inc(CPUArchState *env, uintptr_t mmu_idx)
43
{
44
env_tlb(env)->d[mmu_idx].n_used_entries++;
45
--
46
2.20.1
47
48
diff view generated by jsdifflib
Deleted patch
1
Merge into the only caller, but at the same time split
2
out tlb_mmu_init to initialize a single tlb entry.
3
1
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
accel/tcg/cputlb.c | 33 ++++++++++++++++-----------------
10
1 file changed, 16 insertions(+), 17 deletions(-)
11
12
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/accel/tcg/cputlb.c
15
+++ b/accel/tcg/cputlb.c
16
@@ -XXX,XX +XXX,XX @@ static void tlb_window_reset(CPUTLBDesc *desc, int64_t ns,
17
desc->window_max_entries = max_entries;
18
}
19
20
-static void tlb_dyn_init(CPUArchState *env)
21
-{
22
- int i;
23
-
24
- for (i = 0; i < NB_MMU_MODES; i++) {
25
- CPUTLBDesc *desc = &env_tlb(env)->d[i];
26
- size_t n_entries = 1 << CPU_TLB_DYN_DEFAULT_BITS;
27
-
28
- tlb_window_reset(desc, get_clock_realtime(), 0);
29
- desc->n_used_entries = 0;
30
- env_tlb(env)->f[i].mask = (n_entries - 1) << CPU_TLB_ENTRY_BITS;
31
- env_tlb(env)->f[i].table = g_new(CPUTLBEntry, n_entries);
32
- env_tlb(env)->d[i].iotlb = g_new(CPUIOTLBEntry, n_entries);
33
- }
34
-}
35
-
36
/**
37
* tlb_mmu_resize_locked() - perform TLB resize bookkeeping; resize if necessary
38
* @desc: The CPUTLBDesc portion of the TLB
39
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
40
tlb_mmu_flush_locked(desc, fast);
41
}
42
43
+static void tlb_mmu_init(CPUTLBDesc *desc, CPUTLBDescFast *fast, int64_t now)
44
+{
45
+ size_t n_entries = 1 << CPU_TLB_DYN_DEFAULT_BITS;
46
+
47
+ tlb_window_reset(desc, now, 0);
48
+ desc->n_used_entries = 0;
49
+ fast->mask = (n_entries - 1) << CPU_TLB_ENTRY_BITS;
50
+ fast->table = g_new(CPUTLBEntry, n_entries);
51
+ desc->iotlb = g_new(CPUIOTLBEntry, n_entries);
52
+}
53
+
54
static inline void tlb_n_used_entries_inc(CPUArchState *env, uintptr_t mmu_idx)
55
{
56
env_tlb(env)->d[mmu_idx].n_used_entries++;
57
@@ -XXX,XX +XXX,XX @@ static inline void tlb_n_used_entries_dec(CPUArchState *env, uintptr_t mmu_idx)
58
void tlb_init(CPUState *cpu)
59
{
60
CPUArchState *env = cpu->env_ptr;
61
+ int64_t now = get_clock_realtime();
62
+ int i;
63
64
qemu_spin_init(&env_tlb(env)->c.lock);
65
66
/* Ensure that cpu_reset performs a full flush. */
67
env_tlb(env)->c.dirty = ALL_MMUIDX_BITS;
68
69
- tlb_dyn_init(env);
70
+ for (i = 0; i < NB_MMU_MODES; i++) {
71
+ tlb_mmu_init(&env_tlb(env)->d[i], &env_tlb(env)->f[i], now);
72
+ }
73
}
74
75
/* flush_all_helper: run fn across all cpus
76
--
77
2.20.1
78
79
diff view generated by jsdifflib
Deleted patch
1
There's little point in leaving these data structures half initialized,
2
and relying on a flush to be done during reset.
3
1
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
accel/tcg/cputlb.c | 5 +++--
9
1 file changed, 3 insertions(+), 2 deletions(-)
10
11
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/accel/tcg/cputlb.c
14
+++ b/accel/tcg/cputlb.c
15
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_init(CPUTLBDesc *desc, CPUTLBDescFast *fast, int64_t now)
16
fast->mask = (n_entries - 1) << CPU_TLB_ENTRY_BITS;
17
fast->table = g_new(CPUTLBEntry, n_entries);
18
desc->iotlb = g_new(CPUIOTLBEntry, n_entries);
19
+ tlb_mmu_flush_locked(desc, fast);
20
}
21
22
static inline void tlb_n_used_entries_inc(CPUArchState *env, uintptr_t mmu_idx)
23
@@ -XXX,XX +XXX,XX @@ void tlb_init(CPUState *cpu)
24
25
qemu_spin_init(&env_tlb(env)->c.lock);
26
27
- /* Ensure that cpu_reset performs a full flush. */
28
- env_tlb(env)->c.dirty = ALL_MMUIDX_BITS;
29
+ /* All tlbs are initialized flushed. */
30
+ env_tlb(env)->c.dirty = 0;
31
32
for (i = 0; i < NB_MMU_MODES; i++) {
33
tlb_mmu_init(&env_tlb(env)->d[i], &env_tlb(env)->f[i], now);
34
--
35
2.20.1
36
37
diff view generated by jsdifflib
Deleted patch
1
Do not call get_clock_realtime() in tlb_mmu_resize_locked,
2
but hoist outside of any loop over a set of tlbs. This is
3
only two (indirect) callers, tlb_flush_by_mmuidx_async_work
4
and tlb_flush_page_locked, so not onerous.
5
1
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
11
accel/tcg/cputlb.c | 14 ++++++++------
12
1 file changed, 8 insertions(+), 6 deletions(-)
13
14
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/accel/tcg/cputlb.c
17
+++ b/accel/tcg/cputlb.c
18
@@ -XXX,XX +XXX,XX @@ static void tlb_window_reset(CPUTLBDesc *desc, int64_t ns,
19
* high), since otherwise we are likely to have a significant amount of
20
* conflict misses.
21
*/
22
-static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast)
23
+static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast,
24
+ int64_t now)
25
{
26
size_t old_size = tlb_n_entries(fast);
27
size_t rate;
28
size_t new_size = old_size;
29
- int64_t now = get_clock_realtime();
30
int64_t window_len_ms = 100;
31
int64_t window_len_ns = window_len_ms * 1000 * 1000;
32
bool window_expired = now > desc->window_begin_ns + window_len_ns;
33
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_flush_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast)
34
memset(desc->vtable, -1, sizeof(desc->vtable));
35
}
36
37
-static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
38
+static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx,
39
+ int64_t now)
40
{
41
CPUTLBDesc *desc = &env_tlb(env)->d[mmu_idx];
42
CPUTLBDescFast *fast = &env_tlb(env)->f[mmu_idx];
43
44
- tlb_mmu_resize_locked(desc, fast);
45
+ tlb_mmu_resize_locked(desc, fast, now);
46
tlb_mmu_flush_locked(desc, fast);
47
}
48
49
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
50
CPUArchState *env = cpu->env_ptr;
51
uint16_t asked = data.host_int;
52
uint16_t all_dirty, work, to_clean;
53
+ int64_t now = get_clock_realtime();
54
55
assert_cpu_is_self(cpu);
56
57
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
58
59
for (work = to_clean; work != 0; work &= work - 1) {
60
int mmu_idx = ctz32(work);
61
- tlb_flush_one_mmuidx_locked(env, mmu_idx);
62
+ tlb_flush_one_mmuidx_locked(env, mmu_idx, now);
63
}
64
65
qemu_spin_unlock(&env_tlb(env)->c.lock);
66
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_locked(CPUArchState *env, int midx,
67
tlb_debug("forcing full flush midx %d ("
68
TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
69
midx, lp_addr, lp_mask);
70
- tlb_flush_one_mmuidx_locked(env, midx);
71
+ tlb_flush_one_mmuidx_locked(env, midx, get_clock_realtime());
72
} else {
73
if (tlb_flush_entry_locked(tlb_entry(env, midx, page), page)) {
74
tlb_n_used_entries_dec(env, midx);
75
--
76
2.20.1
77
78
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Claudio Fontana <cfontana@suse.de>
2
2
3
To avoid scrolling each instruction when reviewing tcg
3
Signed-off-by: Claudio Fontana <cfontana@suse.de>
4
helpers written for the decodetree script, display the
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
.decode files (similar to header declarations) before
5
Message-Id: <20201015143217.29337-4-cfontana@suse.de>
6
the C source (implementation of previous declarations).
7
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Message-Id: <20191230082856.30556-1-philmd@redhat.com>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
---
7
---
14
scripts/git.orderfile | 3 +++
8
accel/tcg/tcg-cpus-icount.h | 6 +--
15
1 file changed, 3 insertions(+)
9
accel/tcg/tcg-cpus-rr.h | 2 +-
10
accel/tcg/tcg-cpus.h | 6 +--
11
accel/tcg/tcg-cpus-icount.c | 24 ++++++------
12
accel/tcg/tcg-cpus-mttcg.c | 10 ++---
13
accel/tcg/tcg-cpus-rr.c | 74 ++++++++++++++++++-------------------
14
accel/tcg/tcg-cpus.c | 6 +--
15
7 files changed, 64 insertions(+), 64 deletions(-)
16
16
17
diff --git a/scripts/git.orderfile b/scripts/git.orderfile
17
diff --git a/accel/tcg/tcg-cpus-icount.h b/accel/tcg/tcg-cpus-icount.h
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/scripts/git.orderfile
19
--- a/accel/tcg/tcg-cpus-icount.h
20
+++ b/scripts/git.orderfile
20
+++ b/accel/tcg/tcg-cpus-icount.h
21
@@ -XXX,XX +XXX,XX @@ qga/*.json
21
@@ -XXX,XX +XXX,XX @@
22
# headers
22
#ifndef TCG_CPUS_ICOUNT_H
23
*.h
23
#define TCG_CPUS_ICOUNT_H
24
24
25
+# decoding tree specification
25
-void handle_icount_deadline(void);
26
+*.decode
26
-void prepare_icount_for_run(CPUState *cpu);
27
+
27
-void process_icount_data(CPUState *cpu);
28
# code
28
+void icount_handle_deadline(void);
29
*.c
29
+void icount_prepare_for_run(CPUState *cpu);
30
+void icount_process_data(CPUState *cpu);
31
32
#endif /* TCG_CPUS_ICOUNT_H */
33
diff --git a/accel/tcg/tcg-cpus-rr.h b/accel/tcg/tcg-cpus-rr.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/accel/tcg/tcg-cpus-rr.h
36
+++ b/accel/tcg/tcg-cpus-rr.h
37
@@ -XXX,XX +XXX,XX @@
38
#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10)
39
40
/* Kick all RR vCPUs. */
41
-void qemu_cpu_kick_rr_cpus(CPUState *unused);
42
+void rr_kick_vcpu_thread(CPUState *unused);
43
44
/* start the round robin vcpu thread */
45
void rr_start_vcpu_thread(CPUState *cpu);
46
diff --git a/accel/tcg/tcg-cpus.h b/accel/tcg/tcg-cpus.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/accel/tcg/tcg-cpus.h
49
+++ b/accel/tcg/tcg-cpus.h
50
@@ -XXX,XX +XXX,XX @@ extern const CpusAccel tcg_cpus_mttcg;
51
extern const CpusAccel tcg_cpus_icount;
52
extern const CpusAccel tcg_cpus_rr;
53
54
-void qemu_tcg_destroy_vcpu(CPUState *cpu);
55
-int tcg_cpu_exec(CPUState *cpu);
56
-void tcg_handle_interrupt(CPUState *cpu, int mask);
57
+void tcg_cpus_destroy(CPUState *cpu);
58
+int tcg_cpus_exec(CPUState *cpu);
59
+void tcg_cpus_handle_interrupt(CPUState *cpu, int mask);
60
61
#endif /* TCG_CPUS_H */
62
diff --git a/accel/tcg/tcg-cpus-icount.c b/accel/tcg/tcg-cpus-icount.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/accel/tcg/tcg-cpus-icount.c
65
+++ b/accel/tcg/tcg-cpus-icount.c
66
@@ -XXX,XX +XXX,XX @@
67
#include "tcg-cpus-icount.h"
68
#include "tcg-cpus-rr.h"
69
70
-static int64_t tcg_get_icount_limit(void)
71
+static int64_t icount_get_limit(void)
72
{
73
int64_t deadline;
74
75
@@ -XXX,XX +XXX,XX @@ static int64_t tcg_get_icount_limit(void)
76
}
77
}
78
79
-static void notify_aio_contexts(void)
80
+static void icount_notify_aio_contexts(void)
81
{
82
/* Wake up other AioContexts. */
83
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
84
qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL);
85
}
86
87
-void handle_icount_deadline(void)
88
+void icount_handle_deadline(void)
89
{
90
assert(qemu_in_vcpu_thread());
91
int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
92
QEMU_TIMER_ATTR_ALL);
93
94
if (deadline == 0) {
95
- notify_aio_contexts();
96
+ icount_notify_aio_contexts();
97
}
98
}
99
100
-void prepare_icount_for_run(CPUState *cpu)
101
+void icount_prepare_for_run(CPUState *cpu)
102
{
103
int insns_left;
104
105
/*
106
- * These should always be cleared by process_icount_data after
107
+ * These should always be cleared by icount_process_data after
108
* each vCPU execution. However u16.high can be raised
109
- * asynchronously by cpu_exit/cpu_interrupt/tcg_handle_interrupt
110
+ * asynchronously by cpu_exit/cpu_interrupt/tcg_cpus_handle_interrupt
111
*/
112
g_assert(cpu_neg(cpu)->icount_decr.u16.low == 0);
113
g_assert(cpu->icount_extra == 0);
114
115
- cpu->icount_budget = tcg_get_icount_limit();
116
+ cpu->icount_budget = icount_get_limit();
117
insns_left = MIN(0xffff, cpu->icount_budget);
118
cpu_neg(cpu)->icount_decr.u16.low = insns_left;
119
cpu->icount_extra = cpu->icount_budget - insns_left;
120
@@ -XXX,XX +XXX,XX @@ void prepare_icount_for_run(CPUState *cpu)
121
replay_mutex_lock();
122
123
if (cpu->icount_budget == 0 && replay_has_checkpoint()) {
124
- notify_aio_contexts();
125
+ icount_notify_aio_contexts();
126
}
127
}
128
129
-void process_icount_data(CPUState *cpu)
130
+void icount_process_data(CPUState *cpu)
131
{
132
/* Account for executed instructions */
133
icount_update(cpu);
134
@@ -XXX,XX +XXX,XX @@ static void icount_handle_interrupt(CPUState *cpu, int mask)
135
{
136
int old_mask = cpu->interrupt_request;
137
138
- tcg_handle_interrupt(cpu, mask);
139
+ tcg_cpus_handle_interrupt(cpu, mask);
140
if (qemu_cpu_is_self(cpu) &&
141
!cpu->can_do_io
142
&& (mask & ~old_mask) != 0) {
143
@@ -XXX,XX +XXX,XX @@ static void icount_handle_interrupt(CPUState *cpu, int mask)
144
145
const CpusAccel tcg_cpus_icount = {
146
.create_vcpu_thread = rr_start_vcpu_thread,
147
- .kick_vcpu_thread = qemu_cpu_kick_rr_cpus,
148
+ .kick_vcpu_thread = rr_kick_vcpu_thread,
149
150
.handle_interrupt = icount_handle_interrupt,
151
.get_virtual_clock = icount_get,
152
diff --git a/accel/tcg/tcg-cpus-mttcg.c b/accel/tcg/tcg-cpus-mttcg.c
153
index XXXXXXX..XXXXXXX 100644
154
--- a/accel/tcg/tcg-cpus-mttcg.c
155
+++ b/accel/tcg/tcg-cpus-mttcg.c
156
@@ -XXX,XX +XXX,XX @@
157
* current CPUState for a given thread.
158
*/
159
160
-static void *tcg_cpu_thread_fn(void *arg)
161
+static void *mttcg_cpu_thread_fn(void *arg)
162
{
163
CPUState *cpu = arg;
164
165
@@ -XXX,XX +XXX,XX @@ static void *tcg_cpu_thread_fn(void *arg)
166
if (cpu_can_run(cpu)) {
167
int r;
168
qemu_mutex_unlock_iothread();
169
- r = tcg_cpu_exec(cpu);
170
+ r = tcg_cpus_exec(cpu);
171
qemu_mutex_lock_iothread();
172
switch (r) {
173
case EXCP_DEBUG:
174
@@ -XXX,XX +XXX,XX @@ static void *tcg_cpu_thread_fn(void *arg)
175
qemu_wait_io_event(cpu);
176
} while (!cpu->unplug || cpu_can_run(cpu));
177
178
- qemu_tcg_destroy_vcpu(cpu);
179
+ tcg_cpus_destroy(cpu);
180
qemu_mutex_unlock_iothread();
181
rcu_unregister_thread();
182
return NULL;
183
@@ -XXX,XX +XXX,XX @@ static void mttcg_start_vcpu_thread(CPUState *cpu)
184
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/TCG",
185
cpu->cpu_index);
186
187
- qemu_thread_create(cpu->thread, thread_name, tcg_cpu_thread_fn,
188
+ qemu_thread_create(cpu->thread, thread_name, mttcg_cpu_thread_fn,
189
cpu, QEMU_THREAD_JOINABLE);
190
191
#ifdef _WIN32
192
@@ -XXX,XX +XXX,XX @@ const CpusAccel tcg_cpus_mttcg = {
193
.create_vcpu_thread = mttcg_start_vcpu_thread,
194
.kick_vcpu_thread = mttcg_kick_vcpu_thread,
195
196
- .handle_interrupt = tcg_handle_interrupt,
197
+ .handle_interrupt = tcg_cpus_handle_interrupt,
198
};
199
diff --git a/accel/tcg/tcg-cpus-rr.c b/accel/tcg/tcg-cpus-rr.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/accel/tcg/tcg-cpus-rr.c
202
+++ b/accel/tcg/tcg-cpus-rr.c
203
@@ -XXX,XX +XXX,XX @@
204
#include "tcg-cpus-icount.h"
205
206
/* Kick all RR vCPUs */
207
-void qemu_cpu_kick_rr_cpus(CPUState *unused)
208
+void rr_kick_vcpu_thread(CPUState *unused)
209
{
210
CPUState *cpu;
211
212
@@ -XXX,XX +XXX,XX @@ void qemu_cpu_kick_rr_cpus(CPUState *unused)
213
* idleness is complete.
214
*/
215
216
-static QEMUTimer *tcg_kick_vcpu_timer;
217
-static CPUState *tcg_current_rr_cpu;
218
+static QEMUTimer *rr_kick_vcpu_timer;
219
+static CPUState *rr_current_cpu;
220
221
#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10)
222
223
-static inline int64_t qemu_tcg_next_kick(void)
224
+static inline int64_t rr_next_kick_time(void)
225
{
226
return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + TCG_KICK_PERIOD;
227
}
228
229
/* Kick the currently round-robin scheduled vCPU to next */
230
-static void qemu_cpu_kick_rr_next_cpu(void)
231
+static void rr_kick_next_cpu(void)
232
{
233
CPUState *cpu;
234
do {
235
- cpu = qatomic_mb_read(&tcg_current_rr_cpu);
236
+ cpu = qatomic_mb_read(&rr_current_cpu);
237
if (cpu) {
238
cpu_exit(cpu);
239
}
240
- } while (cpu != qatomic_mb_read(&tcg_current_rr_cpu));
241
+ } while (cpu != qatomic_mb_read(&rr_current_cpu));
242
}
243
244
-static void kick_tcg_thread(void *opaque)
245
+static void rr_kick_thread(void *opaque)
246
{
247
- timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick());
248
- qemu_cpu_kick_rr_next_cpu();
249
+ timer_mod(rr_kick_vcpu_timer, rr_next_kick_time());
250
+ rr_kick_next_cpu();
251
}
252
253
-static void start_tcg_kick_timer(void)
254
+static void rr_start_kick_timer(void)
255
{
256
- if (!tcg_kick_vcpu_timer && CPU_NEXT(first_cpu)) {
257
- tcg_kick_vcpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
258
- kick_tcg_thread, NULL);
259
+ if (!rr_kick_vcpu_timer && CPU_NEXT(first_cpu)) {
260
+ rr_kick_vcpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
261
+ rr_kick_thread, NULL);
262
}
263
- if (tcg_kick_vcpu_timer && !timer_pending(tcg_kick_vcpu_timer)) {
264
- timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick());
265
+ if (rr_kick_vcpu_timer && !timer_pending(rr_kick_vcpu_timer)) {
266
+ timer_mod(rr_kick_vcpu_timer, rr_next_kick_time());
267
}
268
}
269
270
-static void stop_tcg_kick_timer(void)
271
+static void rr_stop_kick_timer(void)
272
{
273
- if (tcg_kick_vcpu_timer && timer_pending(tcg_kick_vcpu_timer)) {
274
- timer_del(tcg_kick_vcpu_timer);
275
+ if (rr_kick_vcpu_timer && timer_pending(rr_kick_vcpu_timer)) {
276
+ timer_del(rr_kick_vcpu_timer);
277
}
278
}
279
280
-static void qemu_tcg_rr_wait_io_event(void)
281
+static void rr_wait_io_event(void)
282
{
283
CPUState *cpu;
284
285
while (all_cpu_threads_idle()) {
286
- stop_tcg_kick_timer();
287
+ rr_stop_kick_timer();
288
qemu_cond_wait_iothread(first_cpu->halt_cond);
289
}
290
291
- start_tcg_kick_timer();
292
+ rr_start_kick_timer();
293
294
CPU_FOREACH(cpu) {
295
qemu_wait_io_event_common(cpu);
296
@@ -XXX,XX +XXX,XX @@ static void qemu_tcg_rr_wait_io_event(void)
297
* Destroy any remaining vCPUs which have been unplugged and have
298
* finished running
299
*/
300
-static void deal_with_unplugged_cpus(void)
301
+static void rr_deal_with_unplugged_cpus(void)
302
{
303
CPUState *cpu;
304
305
CPU_FOREACH(cpu) {
306
if (cpu->unplug && !cpu_can_run(cpu)) {
307
- qemu_tcg_destroy_vcpu(cpu);
308
+ tcg_cpus_destroy(cpu);
309
break;
310
}
311
}
312
@@ -XXX,XX +XXX,XX @@ static void deal_with_unplugged_cpus(void)
313
* elsewhere.
314
*/
315
316
-static void *tcg_rr_cpu_thread_fn(void *arg)
317
+static void *rr_cpu_thread_fn(void *arg)
318
{
319
CPUState *cpu = arg;
320
321
@@ -XXX,XX +XXX,XX @@ static void *tcg_rr_cpu_thread_fn(void *arg)
322
}
323
}
324
325
- start_tcg_kick_timer();
326
+ rr_start_kick_timer();
327
328
cpu = first_cpu;
329
330
@@ -XXX,XX +XXX,XX @@ static void *tcg_rr_cpu_thread_fn(void *arg)
331
* Run the timers here. This is much more efficient than
332
* waking up the I/O thread and waiting for completion.
333
*/
334
- handle_icount_deadline();
335
+ icount_handle_deadline();
336
}
337
338
replay_mutex_unlock();
339
@@ -XXX,XX +XXX,XX @@ static void *tcg_rr_cpu_thread_fn(void *arg)
340
341
while (cpu && cpu_work_list_empty(cpu) && !cpu->exit_request) {
342
343
- qatomic_mb_set(&tcg_current_rr_cpu, cpu);
344
+ qatomic_mb_set(&rr_current_cpu, cpu);
345
current_cpu = cpu;
346
347
qemu_clock_enable(QEMU_CLOCK_VIRTUAL,
348
@@ -XXX,XX +XXX,XX @@ static void *tcg_rr_cpu_thread_fn(void *arg)
349
350
qemu_mutex_unlock_iothread();
351
if (icount_enabled()) {
352
- prepare_icount_for_run(cpu);
353
+ icount_prepare_for_run(cpu);
354
}
355
- r = tcg_cpu_exec(cpu);
356
+ r = tcg_cpus_exec(cpu);
357
if (icount_enabled()) {
358
- process_icount_data(cpu);
359
+ icount_process_data(cpu);
360
}
361
qemu_mutex_lock_iothread();
362
363
@@ -XXX,XX +XXX,XX @@ static void *tcg_rr_cpu_thread_fn(void *arg)
364
} /* while (cpu && !cpu->exit_request).. */
365
366
/* Does not need qatomic_mb_set because a spurious wakeup is okay. */
367
- qatomic_set(&tcg_current_rr_cpu, NULL);
368
+ qatomic_set(&rr_current_cpu, NULL);
369
370
if (cpu && cpu->exit_request) {
371
qatomic_mb_set(&cpu->exit_request, 0);
372
@@ -XXX,XX +XXX,XX @@ static void *tcg_rr_cpu_thread_fn(void *arg)
373
qemu_notify_event();
374
}
375
376
- qemu_tcg_rr_wait_io_event();
377
- deal_with_unplugged_cpus();
378
+ rr_wait_io_event();
379
+ rr_deal_with_unplugged_cpus();
380
}
381
382
rcu_unregister_thread();
383
@@ -XXX,XX +XXX,XX @@ void rr_start_vcpu_thread(CPUState *cpu)
384
/* share a single thread for all cpus with TCG */
385
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "ALL CPUs/TCG");
386
qemu_thread_create(cpu->thread, thread_name,
387
- tcg_rr_cpu_thread_fn,
388
+ rr_cpu_thread_fn,
389
cpu, QEMU_THREAD_JOINABLE);
390
391
single_tcg_halt_cond = cpu->halt_cond;
392
@@ -XXX,XX +XXX,XX @@ void rr_start_vcpu_thread(CPUState *cpu)
393
394
const CpusAccel tcg_cpus_rr = {
395
.create_vcpu_thread = rr_start_vcpu_thread,
396
- .kick_vcpu_thread = qemu_cpu_kick_rr_cpus,
397
+ .kick_vcpu_thread = rr_kick_vcpu_thread,
398
399
- .handle_interrupt = tcg_handle_interrupt,
400
+ .handle_interrupt = tcg_cpus_handle_interrupt,
401
};
402
diff --git a/accel/tcg/tcg-cpus.c b/accel/tcg/tcg-cpus.c
403
index XXXXXXX..XXXXXXX 100644
404
--- a/accel/tcg/tcg-cpus.c
405
+++ b/accel/tcg/tcg-cpus.c
406
@@ -XXX,XX +XXX,XX @@
407
408
/* common functionality among all TCG variants */
409
410
-void qemu_tcg_destroy_vcpu(CPUState *cpu)
411
+void tcg_cpus_destroy(CPUState *cpu)
412
{
413
cpu_thread_signal_destroyed(cpu);
414
}
415
416
-int tcg_cpu_exec(CPUState *cpu)
417
+int tcg_cpus_exec(CPUState *cpu)
418
{
419
int ret;
420
#ifdef CONFIG_PROFILER
421
@@ -XXX,XX +XXX,XX @@ int tcg_cpu_exec(CPUState *cpu)
422
}
423
424
/* mask must never be zero, except for A20 change call */
425
-void tcg_handle_interrupt(CPUState *cpu, int mask)
426
+void tcg_cpus_handle_interrupt(CPUState *cpu, int mask)
427
{
428
g_assert(qemu_mutex_iothread_locked());
429
30
--
430
--
31
2.20.1
431
2.25.1
32
432
33
433
diff view generated by jsdifflib