xref: /qemu/accel/tcg/tcg-all.c (revision 5e15bb7d66d63cbcd863b6b3f69d3fa6715fb75c)
1a9ded601SYang Zhong /*
2a9ded601SYang Zhong  * QEMU System Emulator, accelerator interfaces
3a9ded601SYang Zhong  *
4a9ded601SYang Zhong  * Copyright (c) 2003-2008 Fabrice Bellard
5a9ded601SYang Zhong  * Copyright (c) 2014 Red Hat Inc.
6a9ded601SYang Zhong  *
7a9ded601SYang Zhong  * Permission is hereby granted, free of charge, to any person obtaining a copy
8a9ded601SYang Zhong  * of this software and associated documentation files (the "Software"), to deal
9a9ded601SYang Zhong  * in the Software without restriction, including without limitation the rights
10a9ded601SYang Zhong  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11a9ded601SYang Zhong  * copies of the Software, and to permit persons to whom the Software is
12a9ded601SYang Zhong  * furnished to do so, subject to the following conditions:
13a9ded601SYang Zhong  *
14a9ded601SYang Zhong  * The above copyright notice and this permission notice shall be included in
15a9ded601SYang Zhong  * all copies or substantial portions of the Software.
16a9ded601SYang Zhong  *
17a9ded601SYang Zhong  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18a9ded601SYang Zhong  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19a9ded601SYang Zhong  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20a9ded601SYang Zhong  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21a9ded601SYang Zhong  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22a9ded601SYang Zhong  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23a9ded601SYang Zhong  * THE SOFTWARE.
24a9ded601SYang Zhong  */
25a9ded601SYang Zhong 
26a9ded601SYang Zhong #include "qemu/osdep.h"
2732cad1ffSPhilippe Mathieu-Daudé #include "system/tcg.h"
285b5968c4SPhilippe Mathieu-Daudé #include "exec/replay-core.h"
29161f5bc8SRichard Henderson #include "exec/icount.h"
30d7ec12f8SRichard Henderson #include "tcg/startup.h"
31dd680bf3SPhilippe Mathieu-Daudé #include "qapi/error.h"
32dd680bf3SPhilippe Mathieu-Daudé #include "qemu/error-report.h"
33940e43aaSClaudio Fontana #include "qemu/accel.h"
340e33928cSPeter Maydell #include "qemu/atomic.h"
35d1aa5772SPhilippe Mathieu-Daudé #include "qapi/qapi-types-common.h"
36fe174132SPaolo Bonzini #include "qapi/qapi-builtin-visit.h"
37efba8ae9SRichard Henderson #include "qemu/units.h"
38*5e15bb7dSPhilippe Mathieu-Daudé #include "qemu/target-info.h"
39558ee1edSPhilippe Mathieu-Daudé #if defined(CONFIG_USER_ONLY)
40558ee1edSPhilippe Mathieu-Daudé #include "hw/qdev-core.h"
41558ee1edSPhilippe Mathieu-Daudé #else
4243b972b7SRichard Henderson #include "hw/boards.h"
4360b2c2e6SPhilippe Mathieu-Daudé #include "system/tcg.h"
4443b972b7SRichard Henderson #endif
45a3d40b5eSPhilippe Mathieu-Daudé #include "accel/tcg/cpu-ops.h"
46eeb6198eSPhilippe Mathieu-Daudé #include "internal-common.h"
47*5e15bb7dSPhilippe Mathieu-Daudé #include "cpu-param.h"
48f441b4d1SRichard Henderson 
49940e43aaSClaudio Fontana 
50db1015e9SEduardo Habkost struct TCGState {
5112ceaef6SPaolo Bonzini     AccelState parent_obj;
5212ceaef6SPaolo Bonzini 
53d1aa5772SPhilippe Mathieu-Daudé     OnOffAuto mttcg_enabled;
543cfb0456SPeter Maydell     bool one_insn_per_tb;
55a35b3e14SRichard Henderson     int splitwx_enabled;
56fe174132SPaolo Bonzini     unsigned long tb_size;
57db1015e9SEduardo Habkost };
58db1015e9SEduardo Habkost typedef struct TCGState TCGState;
5912ceaef6SPaolo Bonzini 
6012ceaef6SPaolo Bonzini #define TYPE_TCG_ACCEL ACCEL_CLASS_NAME("tcg")
6112ceaef6SPaolo Bonzini 
628110fa1dSEduardo Habkost DECLARE_INSTANCE_CHECKER(TCGState, TCG_STATE,
638110fa1dSEduardo Habkost                          TYPE_TCG_ACCEL)
64a9ded601SYang Zhong 
6560b2c2e6SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
6660b2c2e6SPhilippe Mathieu-Daudé bool qemu_tcg_mttcg_enabled(void)
6760b2c2e6SPhilippe Mathieu-Daudé {
6861fc4c2bSRichard Henderson     TCGState *s = TCG_STATE(current_accel());
69d1aa5772SPhilippe Mathieu-Daudé     return s->mttcg_enabled == ON_OFF_AUTO_ON;
7060b2c2e6SPhilippe Mathieu-Daudé }
7160b2c2e6SPhilippe Mathieu-Daudé #endif /* !CONFIG_USER_ONLY */
7260b2c2e6SPhilippe Mathieu-Daudé 
73af0440aeSPaolo Bonzini static void tcg_accel_instance_init(Object *obj)
74af0440aeSPaolo Bonzini {
7512ceaef6SPaolo Bonzini     TCGState *s = TCG_STATE(obj);
7612ceaef6SPaolo Bonzini 
77a35b3e14SRichard Henderson     /* If debugging enabled, default "auto on", otherwise off. */
78940e43aaSClaudio Fontana #if defined(CONFIG_DEBUG_TCG) && !defined(CONFIG_USER_ONLY)
79a35b3e14SRichard Henderson     s->splitwx_enabled = -1;
80a35b3e14SRichard Henderson #else
81a35b3e14SRichard Henderson     s->splitwx_enabled = 0;
82a35b3e14SRichard Henderson #endif
83af0440aeSPaolo Bonzini }
84af0440aeSPaolo Bonzini 
850e33928cSPeter Maydell bool one_insn_per_tb;
86a77dabc3SClaudio Fontana 
877109ef15SRichard Henderson static int tcg_init_machine(MachineState *ms)
88a9ded601SYang Zhong {
894f7f5893SPhilippe Mathieu-Daudé     TCGState *s = TCG_STATE(current_accel());
90a9d107faSRichard Henderson     unsigned max_threads = 1;
9112ceaef6SPaolo Bonzini 
92d1aa5772SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
93*5e15bb7dSPhilippe Mathieu-Daudé     CPUClass *cc = CPU_CLASS(object_class_by_name(target_cpu_type()));
94a3d40b5eSPhilippe Mathieu-Daudé     bool mttcg_supported = cc->tcg_ops->mttcg_supported;
95a3d40b5eSPhilippe Mathieu-Daudé 
9684cde4afSRichard Henderson     switch (s->mttcg_enabled) {
9784cde4afSRichard Henderson     case ON_OFF_AUTO_AUTO:
98d1aa5772SPhilippe Mathieu-Daudé         /*
99d1aa5772SPhilippe Mathieu-Daudé          * We default to false if we know other options have been enabled
100d1aa5772SPhilippe Mathieu-Daudé          * which are currently incompatible with MTTCG. Otherwise when each
101d1aa5772SPhilippe Mathieu-Daudé          * guest (target) has been updated to support:
102d1aa5772SPhilippe Mathieu-Daudé          *   - atomic instructions
103d1aa5772SPhilippe Mathieu-Daudé          *   - memory ordering primitives (barriers)
104d1aa5772SPhilippe Mathieu-Daudé          * they can set the appropriate CONFIG flags in ${target}-softmmu.mak
105d1aa5772SPhilippe Mathieu-Daudé          *
106d1aa5772SPhilippe Mathieu-Daudé          * Once a guest architecture has been converted to the new primitives
107d1aa5772SPhilippe Mathieu-Daudé          * there is one remaining limitation to check:
108d1aa5772SPhilippe Mathieu-Daudé          *   - The guest can't be oversized (e.g. 64 bit guest on 32 bit host)
109d1aa5772SPhilippe Mathieu-Daudé          */
110d1aa5772SPhilippe Mathieu-Daudé         if (mttcg_supported && !icount_enabled()) {
111d1aa5772SPhilippe Mathieu-Daudé             s->mttcg_enabled = ON_OFF_AUTO_ON;
11284cde4afSRichard Henderson             max_threads = ms->smp.max_cpus;
113d1aa5772SPhilippe Mathieu-Daudé         } else {
114d1aa5772SPhilippe Mathieu-Daudé             s->mttcg_enabled = ON_OFF_AUTO_OFF;
115d1aa5772SPhilippe Mathieu-Daudé         }
11684cde4afSRichard Henderson         break;
11784cde4afSRichard Henderson     case ON_OFF_AUTO_ON:
11884cde4afSRichard Henderson         if (!mttcg_supported) {
11984cde4afSRichard Henderson             warn_report("Guest not yet converted to MTTCG - "
12084cde4afSRichard Henderson                         "you may get unexpected results");
121d1aa5772SPhilippe Mathieu-Daudé         }
122d1aa5772SPhilippe Mathieu-Daudé         max_threads = ms->smp.max_cpus;
12384cde4afSRichard Henderson         break;
12484cde4afSRichard Henderson     case ON_OFF_AUTO_OFF:
12584cde4afSRichard Henderson         break;
12684cde4afSRichard Henderson     default:
12784cde4afSRichard Henderson         g_assert_not_reached();
128d1aa5772SPhilippe Mathieu-Daudé     }
129d1aa5772SPhilippe Mathieu-Daudé #endif
130d1aa5772SPhilippe Mathieu-Daudé 
131fa79cde6SRichard Henderson     tcg_allowed = true;
132fa79cde6SRichard Henderson 
133fa79cde6SRichard Henderson     page_init();
134fa79cde6SRichard Henderson     tb_htable_init();
135a9d107faSRichard Henderson     tcg_init(s->tb_size * MiB, s->splitwx_enabled, max_threads);
136fa79cde6SRichard Henderson 
137fa79cde6SRichard Henderson #if defined(CONFIG_SOFTMMU)
138fa79cde6SRichard Henderson     /*
139fa79cde6SRichard Henderson      * There's no guest base to take into account, so go ahead and
140fa79cde6SRichard Henderson      * initialize the prologue now.
141fa79cde6SRichard Henderson      */
142935f75aeSRichard Henderson     tcg_prologue_init();
143fa79cde6SRichard Henderson #endif
144fa79cde6SRichard Henderson 
145558ee1edSPhilippe Mathieu-Daudé #ifdef CONFIG_USER_ONLY
146558ee1edSPhilippe Mathieu-Daudé     qdev_create_fake_machine();
147558ee1edSPhilippe Mathieu-Daudé #endif
148558ee1edSPhilippe Mathieu-Daudé 
149a9ded601SYang Zhong     return 0;
150a9ded601SYang Zhong }
151a9ded601SYang Zhong 
15212ceaef6SPaolo Bonzini static char *tcg_get_thread(Object *obj, Error **errp)
153af0440aeSPaolo Bonzini {
15412ceaef6SPaolo Bonzini     TCGState *s = TCG_STATE(obj);
15512ceaef6SPaolo Bonzini 
156d1aa5772SPhilippe Mathieu-Daudé     return g_strdup(s->mttcg_enabled == ON_OFF_AUTO_ON ? "multi" : "single");
157af0440aeSPaolo Bonzini }
15812ceaef6SPaolo Bonzini 
15912ceaef6SPaolo Bonzini static void tcg_set_thread(Object *obj, const char *value, Error **errp)
16012ceaef6SPaolo Bonzini {
16112ceaef6SPaolo Bonzini     TCGState *s = TCG_STATE(obj);
16212ceaef6SPaolo Bonzini 
16312ceaef6SPaolo Bonzini     if (strcmp(value, "multi") == 0) {
164f441b4d1SRichard Henderson         if (icount_enabled()) {
165af0440aeSPaolo Bonzini             error_setg(errp, "No MTTCG when icount is enabled");
166af0440aeSPaolo Bonzini         } else {
167d1aa5772SPhilippe Mathieu-Daudé             s->mttcg_enabled = ON_OFF_AUTO_ON;
168af0440aeSPaolo Bonzini         }
16912ceaef6SPaolo Bonzini     } else if (strcmp(value, "single") == 0) {
170d1aa5772SPhilippe Mathieu-Daudé         s->mttcg_enabled = ON_OFF_AUTO_OFF;
171af0440aeSPaolo Bonzini     } else {
17212ceaef6SPaolo Bonzini         error_setg(errp, "Invalid 'thread' setting %s", value);
173af0440aeSPaolo Bonzini     }
174af0440aeSPaolo Bonzini }
175af0440aeSPaolo Bonzini 
176fe174132SPaolo Bonzini static void tcg_get_tb_size(Object *obj, Visitor *v,
177fe174132SPaolo Bonzini                             const char *name, void *opaque,
178fe174132SPaolo Bonzini                             Error **errp)
179fe174132SPaolo Bonzini {
180fe174132SPaolo Bonzini     TCGState *s = TCG_STATE(obj);
181fe174132SPaolo Bonzini     uint32_t value = s->tb_size;
182fe174132SPaolo Bonzini 
183fe174132SPaolo Bonzini     visit_type_uint32(v, name, &value, errp);
184fe174132SPaolo Bonzini }
185fe174132SPaolo Bonzini 
186fe174132SPaolo Bonzini static void tcg_set_tb_size(Object *obj, Visitor *v,
187fe174132SPaolo Bonzini                             const char *name, void *opaque,
188fe174132SPaolo Bonzini                             Error **errp)
189fe174132SPaolo Bonzini {
190fe174132SPaolo Bonzini     TCGState *s = TCG_STATE(obj);
191fe174132SPaolo Bonzini     uint32_t value;
192fe174132SPaolo Bonzini 
193668f62ecSMarkus Armbruster     if (!visit_type_uint32(v, name, &value, errp)) {
194fe174132SPaolo Bonzini         return;
195fe174132SPaolo Bonzini     }
196fe174132SPaolo Bonzini 
197fe174132SPaolo Bonzini     s->tb_size = value;
198fe174132SPaolo Bonzini }
199fe174132SPaolo Bonzini 
200a35b3e14SRichard Henderson static bool tcg_get_splitwx(Object *obj, Error **errp)
201a35b3e14SRichard Henderson {
202a35b3e14SRichard Henderson     TCGState *s = TCG_STATE(obj);
203a35b3e14SRichard Henderson     return s->splitwx_enabled;
204a35b3e14SRichard Henderson }
205a35b3e14SRichard Henderson 
206a35b3e14SRichard Henderson static void tcg_set_splitwx(Object *obj, bool value, Error **errp)
207a35b3e14SRichard Henderson {
208a35b3e14SRichard Henderson     TCGState *s = TCG_STATE(obj);
209a35b3e14SRichard Henderson     s->splitwx_enabled = value;
210a35b3e14SRichard Henderson }
211a35b3e14SRichard Henderson 
2123cfb0456SPeter Maydell static bool tcg_get_one_insn_per_tb(Object *obj, Error **errp)
2133cfb0456SPeter Maydell {
2143cfb0456SPeter Maydell     TCGState *s = TCG_STATE(obj);
2153cfb0456SPeter Maydell     return s->one_insn_per_tb;
2163cfb0456SPeter Maydell }
2173cfb0456SPeter Maydell 
2183cfb0456SPeter Maydell static void tcg_set_one_insn_per_tb(Object *obj, bool value, Error **errp)
2193cfb0456SPeter Maydell {
2203cfb0456SPeter Maydell     TCGState *s = TCG_STATE(obj);
2213cfb0456SPeter Maydell     s->one_insn_per_tb = value;
2220e33928cSPeter Maydell     /* Set the global also: this changes the behaviour */
2230e33928cSPeter Maydell     qatomic_set(&one_insn_per_tb, value);
2243cfb0456SPeter Maydell }
2253cfb0456SPeter Maydell 
2263b7a9388SAlex Bennée static int tcg_gdbstub_supported_sstep_flags(void)
2273b7a9388SAlex Bennée {
2283b7a9388SAlex Bennée     /*
2293b7a9388SAlex Bennée      * In replay mode all events will come from the log and can't be
2303b7a9388SAlex Bennée      * suppressed otherwise we would break determinism. However as those
2313b7a9388SAlex Bennée      * events are tied to the number of executed instructions we won't see
2323b7a9388SAlex Bennée      * them occurring every time we single step.
2333b7a9388SAlex Bennée      */
2343b7a9388SAlex Bennée     if (replay_mode != REPLAY_MODE_NONE) {
2353b7a9388SAlex Bennée         return SSTEP_ENABLE;
2363b7a9388SAlex Bennée     } else {
2373b7a9388SAlex Bennée         return SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER;
2383b7a9388SAlex Bennée     }
2393b7a9388SAlex Bennée }
2403b7a9388SAlex Bennée 
24112d1a768SPhilippe Mathieu-Daudé static void tcg_accel_class_init(ObjectClass *oc, const void *data)
242a9ded601SYang Zhong {
243a9ded601SYang Zhong     AccelClass *ac = ACCEL_CLASS(oc);
244a9ded601SYang Zhong     ac->name = "tcg";
2457109ef15SRichard Henderson     ac->init_machine = tcg_init_machine;
24623af78b0SPhilippe Mathieu-Daudé     ac->cpu_common_realize = tcg_exec_realizefn;
24723af78b0SPhilippe Mathieu-Daudé     ac->cpu_common_unrealize = tcg_exec_unrealizefn;
248a9ded601SYang Zhong     ac->allowed = &tcg_allowed;
2493b7a9388SAlex Bennée     ac->gdbstub_supported_sstep_flags = tcg_gdbstub_supported_sstep_flags;
250a9ded601SYang Zhong 
25112ceaef6SPaolo Bonzini     object_class_property_add_str(oc, "thread",
25212ceaef6SPaolo Bonzini                                   tcg_get_thread,
253d2623129SMarkus Armbruster                                   tcg_set_thread);
254fe174132SPaolo Bonzini 
255fe174132SPaolo Bonzini     object_class_property_add(oc, "tb-size", "int",
256fe174132SPaolo Bonzini         tcg_get_tb_size, tcg_set_tb_size,
257d2623129SMarkus Armbruster         NULL, NULL);
258fe174132SPaolo Bonzini     object_class_property_set_description(oc, "tb-size",
2597eecec7dSMarkus Armbruster         "TCG translation block cache size");
260fe174132SPaolo Bonzini 
261a35b3e14SRichard Henderson     object_class_property_add_bool(oc, "split-wx",
262a35b3e14SRichard Henderson         tcg_get_splitwx, tcg_set_splitwx);
263a35b3e14SRichard Henderson     object_class_property_set_description(oc, "split-wx",
264a35b3e14SRichard Henderson         "Map jit pages into separate RW and RX regions");
2653cfb0456SPeter Maydell 
2663cfb0456SPeter Maydell     object_class_property_add_bool(oc, "one-insn-per-tb",
2673cfb0456SPeter Maydell                                    tcg_get_one_insn_per_tb,
2683cfb0456SPeter Maydell                                    tcg_set_one_insn_per_tb);
2693cfb0456SPeter Maydell     object_class_property_set_description(oc, "one-insn-per-tb",
2703cfb0456SPeter Maydell         "Only put one guest insn in each translation block");
27112ceaef6SPaolo Bonzini }
272a9ded601SYang Zhong 
273a9ded601SYang Zhong static const TypeInfo tcg_accel_type = {
274a9ded601SYang Zhong     .name = TYPE_TCG_ACCEL,
275a9ded601SYang Zhong     .parent = TYPE_ACCEL,
276af0440aeSPaolo Bonzini     .instance_init = tcg_accel_instance_init,
277a9ded601SYang Zhong     .class_init = tcg_accel_class_init,
27812ceaef6SPaolo Bonzini     .instance_size = sizeof(TCGState),
279a9ded601SYang Zhong };
2809e5d3b69SGerd Hoffmann module_obj(TYPE_TCG_ACCEL);
281a9ded601SYang Zhong 
282a9ded601SYang Zhong static void register_accel_types(void)
283a9ded601SYang Zhong {
284a9ded601SYang Zhong     type_register_static(&tcg_accel_type);
285a9ded601SYang Zhong }
286a9ded601SYang Zhong 
287a9ded601SYang Zhong type_init(register_accel_types);
288