]>
Commit | Line | Data |
---|---|---|
a9ded601 YZ |
1 | /* |
2 | * QEMU System Emulator, accelerator interfaces | |
3 | * | |
4 | * Copyright (c) 2003-2008 Fabrice Bellard | |
5 | * Copyright (c) 2014 Red Hat Inc. | |
6 | * | |
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
8 | * of this software and associated documentation files (the "Software"), to deal | |
9 | * in the Software without restriction, including without limitation the rights | |
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
11 | * copies of the Software, and to permit persons to whom the Software is | |
12 | * furnished to do so, subject to the following conditions: | |
13 | * | |
14 | * The above copyright notice and this permission notice shall be included in | |
15 | * all copies or substantial portions of the Software. | |
16 | * | |
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
23 | * THE SOFTWARE. | |
24 | */ | |
25 | ||
26 | #include "qemu/osdep.h" | |
a77dabc3 | 27 | #include "qemu-common.h" |
14a48c1d | 28 | #include "sysemu/tcg.h" |
740b1759 | 29 | #include "sysemu/cpu-timers.h" |
af0440ae | 30 | #include "tcg/tcg.h" |
dd680bf3 PMD |
31 | #include "qapi/error.h" |
32 | #include "qemu/error-report.h" | |
940e43aa | 33 | #include "qemu/accel.h" |
fe174132 | 34 | #include "qapi/qapi-builtin-visit.h" |
940e43aa | 35 | |
db1015e9 | 36 | struct TCGState { |
12ceaef6 PB |
37 | AccelState parent_obj; |
38 | ||
39 | bool mttcg_enabled; | |
a35b3e14 | 40 | int splitwx_enabled; |
fe174132 | 41 | unsigned long tb_size; |
db1015e9 EH |
42 | }; |
43 | typedef struct TCGState TCGState; | |
12ceaef6 PB |
44 | |
45 | #define TYPE_TCG_ACCEL ACCEL_CLASS_NAME("tcg") | |
46 | ||
8110fa1d EH |
47 | DECLARE_INSTANCE_CHECKER(TCGState, TCG_STATE, |
48 | TYPE_TCG_ACCEL) | |
a9ded601 | 49 | |
af0440ae PB |
50 | /* |
51 | * We default to false if we know other options have been enabled | |
52 | * which are currently incompatible with MTTCG. Otherwise when each | |
53 | * guest (target) has been updated to support: | |
54 | * - atomic instructions | |
55 | * - memory ordering primitives (barriers) | |
56 | * they can set the appropriate CONFIG flags in ${target}-softmmu.mak | |
57 | * | |
58 | * Once a guest architecture has been converted to the new primitives | |
59 | * there are two remaining limitations to check. | |
60 | * | |
61 | * - The guest can't be oversized (e.g. 64 bit guest on 32 bit host) | |
62 | * - The host must have a stronger memory order than the guest | |
63 | * | |
64 | * It may be possible in future to support strong guests on weak hosts | |
65 | * but that will require tagging all load/stores in a guest with their | |
66 | * implicit memory order requirements which would likely slow things | |
67 | * down a lot. | |
68 | */ | |
69 | ||
70 | static bool check_tcg_memory_orders_compatible(void) | |
71 | { | |
72 | #if defined(TCG_GUEST_DEFAULT_MO) && defined(TCG_TARGET_DEFAULT_MO) | |
73 | return (TCG_GUEST_DEFAULT_MO & ~TCG_TARGET_DEFAULT_MO) == 0; | |
74 | #else | |
75 | return false; | |
76 | #endif | |
77 | } | |
78 | ||
79 | static bool default_mttcg_enabled(void) | |
80 | { | |
740b1759 | 81 | if (icount_enabled() || TCG_OVERSIZED_GUEST) { |
af0440ae PB |
82 | return false; |
83 | } else { | |
84 | #ifdef TARGET_SUPPORTS_MTTCG | |
85 | return check_tcg_memory_orders_compatible(); | |
86 | #else | |
87 | return false; | |
88 | #endif | |
89 | } | |
90 | } | |
91 | ||
92 | static void tcg_accel_instance_init(Object *obj) | |
93 | { | |
12ceaef6 PB |
94 | TCGState *s = TCG_STATE(obj); |
95 | ||
96 | s->mttcg_enabled = default_mttcg_enabled(); | |
a35b3e14 RH |
97 | |
98 | /* If debugging enabled, default "auto on", otherwise off. */ | |
940e43aa | 99 | #if defined(CONFIG_DEBUG_TCG) && !defined(CONFIG_USER_ONLY) |
a35b3e14 RH |
100 | s->splitwx_enabled = -1; |
101 | #else | |
102 | s->splitwx_enabled = 0; | |
103 | #endif | |
af0440ae PB |
104 | } |
105 | ||
a77dabc3 CF |
106 | bool mttcg_enabled; |
107 | ||
a9ded601 YZ |
108 | static int tcg_init(MachineState *ms) |
109 | { | |
4f7f5893 | 110 | TCGState *s = TCG_STATE(current_accel()); |
12ceaef6 | 111 | |
a35b3e14 | 112 | tcg_exec_init(s->tb_size * 1024 * 1024, s->splitwx_enabled); |
12ceaef6 | 113 | mttcg_enabled = s->mttcg_enabled; |
a77dabc3 | 114 | |
37c2f9a7 | 115 | /* |
940e43aa CF |
116 | * Initialize TCG regions only for softmmu. |
117 | * | |
118 | * This needs to be done later for user mode, because the prologue | |
119 | * generation needs to be delayed so that GUEST_BASE is already set. | |
37c2f9a7 | 120 | */ |
940e43aa | 121 | #ifndef CONFIG_USER_ONLY |
37c2f9a7 | 122 | tcg_region_init(); |
940e43aa CF |
123 | #endif /* !CONFIG_USER_ONLY */ |
124 | ||
a9ded601 YZ |
125 | return 0; |
126 | } | |
127 | ||
12ceaef6 | 128 | static char *tcg_get_thread(Object *obj, Error **errp) |
af0440ae | 129 | { |
12ceaef6 PB |
130 | TCGState *s = TCG_STATE(obj); |
131 | ||
132 | return g_strdup(s->mttcg_enabled ? "multi" : "single"); | |
133 | } | |
134 | ||
135 | static void tcg_set_thread(Object *obj, const char *value, Error **errp) | |
136 | { | |
137 | TCGState *s = TCG_STATE(obj); | |
138 | ||
139 | if (strcmp(value, "multi") == 0) { | |
af0440ae PB |
140 | if (TCG_OVERSIZED_GUEST) { |
141 | error_setg(errp, "No MTTCG when guest word size > hosts"); | |
740b1759 | 142 | } else if (icount_enabled()) { |
af0440ae PB |
143 | error_setg(errp, "No MTTCG when icount is enabled"); |
144 | } else { | |
145 | #ifndef TARGET_SUPPORTS_MTTCG | |
146 | warn_report("Guest not yet converted to MTTCG - " | |
147 | "you may get unexpected results"); | |
148 | #endif | |
149 | if (!check_tcg_memory_orders_compatible()) { | |
150 | warn_report("Guest expects a stronger memory ordering " | |
151 | "than the host provides"); | |
152 | error_printf("This may cause strange/hard to debug errors\n"); | |
153 | } | |
12ceaef6 | 154 | s->mttcg_enabled = true; |
af0440ae | 155 | } |
12ceaef6 PB |
156 | } else if (strcmp(value, "single") == 0) { |
157 | s->mttcg_enabled = false; | |
af0440ae | 158 | } else { |
12ceaef6 | 159 | error_setg(errp, "Invalid 'thread' setting %s", value); |
af0440ae PB |
160 | } |
161 | } | |
162 | ||
fe174132 PB |
163 | static void tcg_get_tb_size(Object *obj, Visitor *v, |
164 | const char *name, void *opaque, | |
165 | Error **errp) | |
166 | { | |
167 | TCGState *s = TCG_STATE(obj); | |
168 | uint32_t value = s->tb_size; | |
169 | ||
170 | visit_type_uint32(v, name, &value, errp); | |
171 | } | |
172 | ||
173 | static void tcg_set_tb_size(Object *obj, Visitor *v, | |
174 | const char *name, void *opaque, | |
175 | Error **errp) | |
176 | { | |
177 | TCGState *s = TCG_STATE(obj); | |
fe174132 PB |
178 | uint32_t value; |
179 | ||
668f62ec | 180 | if (!visit_type_uint32(v, name, &value, errp)) { |
fe174132 PB |
181 | return; |
182 | } | |
183 | ||
184 | s->tb_size = value; | |
185 | } | |
186 | ||
a35b3e14 RH |
187 | static bool tcg_get_splitwx(Object *obj, Error **errp) |
188 | { | |
189 | TCGState *s = TCG_STATE(obj); | |
190 | return s->splitwx_enabled; | |
191 | } | |
192 | ||
193 | static void tcg_set_splitwx(Object *obj, bool value, Error **errp) | |
194 | { | |
195 | TCGState *s = TCG_STATE(obj); | |
196 | s->splitwx_enabled = value; | |
197 | } | |
198 | ||
a9ded601 YZ |
199 | static void tcg_accel_class_init(ObjectClass *oc, void *data) |
200 | { | |
201 | AccelClass *ac = ACCEL_CLASS(oc); | |
202 | ac->name = "tcg"; | |
203 | ac->init_machine = tcg_init; | |
204 | ac->allowed = &tcg_allowed; | |
a9ded601 | 205 | |
12ceaef6 PB |
206 | object_class_property_add_str(oc, "thread", |
207 | tcg_get_thread, | |
d2623129 | 208 | tcg_set_thread); |
fe174132 PB |
209 | |
210 | object_class_property_add(oc, "tb-size", "int", | |
211 | tcg_get_tb_size, tcg_set_tb_size, | |
d2623129 | 212 | NULL, NULL); |
fe174132 | 213 | object_class_property_set_description(oc, "tb-size", |
7eecec7d | 214 | "TCG translation block cache size"); |
fe174132 | 215 | |
a35b3e14 RH |
216 | object_class_property_add_bool(oc, "split-wx", |
217 | tcg_get_splitwx, tcg_set_splitwx); | |
218 | object_class_property_set_description(oc, "split-wx", | |
219 | "Map jit pages into separate RW and RX regions"); | |
12ceaef6 | 220 | } |
a9ded601 YZ |
221 | |
222 | static const TypeInfo tcg_accel_type = { | |
223 | .name = TYPE_TCG_ACCEL, | |
224 | .parent = TYPE_ACCEL, | |
af0440ae | 225 | .instance_init = tcg_accel_instance_init, |
a9ded601 | 226 | .class_init = tcg_accel_class_init, |
12ceaef6 | 227 | .instance_size = sizeof(TCGState), |
a9ded601 YZ |
228 | }; |
229 | ||
230 | static void register_accel_types(void) | |
231 | { | |
232 | type_register_static(&tcg_accel_type); | |
233 | } | |
234 | ||
235 | type_init(register_accel_types); |