blob: e695f8ba7a738390176b73771e0498f2f1d2ba95 [file] [log] [blame]
bellard2c0262a2003-09-30 20:34:21 +00001/*
bellardeaa728e2008-05-28 12:51:20 +00002 * i386 helpers (without register variable usage)
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard2c0262a2003-09-30 20:34:21 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
bellard2c0262a2003-09-30 20:34:21 +000018 */
bellard2c0262a2003-09-30 20:34:21 +000019
Peter Maydellb6a0aa02016-01-26 18:17:03 +000020#include "qemu/osdep.h"
bellardeaa728e2008-05-28 12:51:20 +000021#include "cpu.h"
Paolo Bonzini63c91552016-03-15 13:18:37 +010022#include "exec/exec-all.h"
Paolo Bonzini9c17d612012-12-17 18:20:04 +010023#include "sysemu/kvm.h"
Paolo Bonzinie0723c42013-03-08 19:21:50 +010024#include "kvm_i386.h"
Jan Kiszka2fa11da2011-03-02 08:56:08 +010025#ifndef CONFIG_USER_ONLY
Paolo Bonzini9c17d612012-12-17 18:20:04 +010026#include "sysemu/sysemu.h"
Vincent Palatinb3946622017-01-10 11:59:55 +010027#include "sysemu/hw_accel.h"
Paolo Bonzini83c90892012-12-17 18:19:49 +010028#include "monitor/monitor.h"
Pavel Butsykin1f871d42015-09-22 16:18:18 +030029#include "hw/i386/apic_internal.h"
Jan Kiszka2fa11da2011-03-02 08:56:08 +010030#endif
bellardf3f2d9b2003-11-13 23:15:36 +000031
Yang Zhongab0a19d2017-07-03 18:12:15 +080032void cpu_sync_bndcs_hflags(CPUX86State *env)
33{
34 uint32_t hflags = env->hflags;
35 uint32_t hflags2 = env->hflags2;
36 uint32_t bndcsr;
37
38 if ((hflags & HF_CPL_MASK) == 3) {
39 bndcsr = env->bndcs_regs.cfgu;
40 } else {
41 bndcsr = env->msr_bndcfgs;
42 }
43
44 if ((env->cr[4] & CR4_OSXSAVE_MASK)
45 && (env->xcr0 & XSTATE_BNDCSR_MASK)
46 && (bndcsr & BNDCFG_ENABLE)) {
47 hflags |= HF_MPX_EN_MASK;
48 } else {
49 hflags &= ~HF_MPX_EN_MASK;
50 }
51
52 if (bndcsr & BNDCFG_BNDPRESERVE) {
53 hflags2 |= HF2_MPX_PR_MASK;
54 } else {
55 hflags2 &= ~HF2_MPX_PR_MASK;
56 }
57
58 env->hflags = hflags;
59 env->hflags2 = hflags2;
60}
61
Andreas Färber317ac622012-03-14 01:38:21 +010062static void cpu_x86_version(CPUX86State *env, int *family, int *model)
Jin Dongming2bd3e042010-12-10 17:21:14 +090063{
64 int cpuver = env->cpuid_version;
65
66 if (family == NULL || model == NULL) {
67 return;
68 }
69
70 *family = (cpuver >> 8) & 0x0f;
71 *model = ((cpuver >> 12) & 0xf0) + ((cpuver >> 4) & 0x0f);
72}
73
74/* Broadcast MCA signal for processor version 06H_EH and above */
Andreas Färber317ac622012-03-14 01:38:21 +010075int cpu_x86_support_mca_broadcast(CPUX86State *env)
Jin Dongming2bd3e042010-12-10 17:21:14 +090076{
77 int family = 0;
78 int model = 0;
79
80 cpu_x86_version(env, &family, &model);
81 if ((family == 6 && model >= 14) || family > 6) {
82 return 1;
83 }
84
85 return 0;
86}
87
bellardeaa728e2008-05-28 12:51:20 +000088/***********************************************************/
89/* x86 debug */
bellard5af45182008-05-12 16:47:36 +000090
Richard Hendersonbc4b43d2013-01-23 16:44:37 -080091static const char *cc_op_str[CC_OP_NB] = {
bellardeaa728e2008-05-28 12:51:20 +000092 "DYNAMIC",
93 "EFLAGS",
bellard5af45182008-05-12 16:47:36 +000094
bellardeaa728e2008-05-28 12:51:20 +000095 "MULB",
96 "MULW",
97 "MULL",
98 "MULQ",
bellard5af45182008-05-12 16:47:36 +000099
bellardeaa728e2008-05-28 12:51:20 +0000100 "ADDB",
101 "ADDW",
102 "ADDL",
103 "ADDQ",
bellardb6abf972008-05-17 12:44:31 +0000104
bellardeaa728e2008-05-28 12:51:20 +0000105 "ADCB",
106 "ADCW",
107 "ADCL",
108 "ADCQ",
bellardb6abf972008-05-17 12:44:31 +0000109
bellardeaa728e2008-05-28 12:51:20 +0000110 "SUBB",
111 "SUBW",
112 "SUBL",
113 "SUBQ",
bellardb6abf972008-05-17 12:44:31 +0000114
bellardeaa728e2008-05-28 12:51:20 +0000115 "SBBB",
116 "SBBW",
117 "SBBL",
118 "SBBQ",
bellardb6abf972008-05-17 12:44:31 +0000119
bellardeaa728e2008-05-28 12:51:20 +0000120 "LOGICB",
121 "LOGICW",
122 "LOGICL",
123 "LOGICQ",
bellardb6abf972008-05-17 12:44:31 +0000124
bellardeaa728e2008-05-28 12:51:20 +0000125 "INCB",
126 "INCW",
127 "INCL",
128 "INCQ",
bellard07d2c592008-05-17 13:57:33 +0000129
bellardeaa728e2008-05-28 12:51:20 +0000130 "DECB",
131 "DECW",
132 "DECL",
133 "DECQ",
bellard6191b052008-05-17 18:44:58 +0000134
bellardeaa728e2008-05-28 12:51:20 +0000135 "SHLB",
136 "SHLW",
137 "SHLL",
138 "SHLQ",
bellard6191b052008-05-17 18:44:58 +0000139
bellardeaa728e2008-05-28 12:51:20 +0000140 "SARB",
141 "SARW",
142 "SARL",
143 "SARQ",
Richard Hendersonbc4b43d2013-01-23 16:44:37 -0800144
145 "BMILGB",
146 "BMILGW",
147 "BMILGL",
148 "BMILGQ",
Richard Hendersoncd7f97c2013-01-23 18:17:33 -0800149
150 "ADCX",
151 "ADOX",
152 "ADCOX",
Richard Henderson436ff2d2013-01-29 13:38:43 -0800153
154 "CLR",
bellard07d2c592008-05-17 13:57:33 +0000155};
156
aliguoria3867ed2009-04-18 15:36:11 +0000157static void
Andreas Färber317ac622012-03-14 01:38:21 +0100158cpu_x86_dump_seg_cache(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
aliguoria3867ed2009-04-18 15:36:11 +0000159 const char *name, struct SegmentCache *sc)
160{
161#ifdef TARGET_X86_64
162 if (env->hflags & HF_CS64_MASK) {
163 cpu_fprintf(f, "%-3s=%04x %016" PRIx64 " %08x %08x", name,
Jan Kiszka4058fd92010-12-27 15:52:24 +0100164 sc->selector, sc->base, sc->limit, sc->flags & 0x00ffff00);
aliguoria3867ed2009-04-18 15:36:11 +0000165 } else
166#endif
167 {
168 cpu_fprintf(f, "%-3s=%04x %08x %08x %08x", name, sc->selector,
Jan Kiszka4058fd92010-12-27 15:52:24 +0100169 (uint32_t)sc->base, sc->limit, sc->flags & 0x00ffff00);
aliguoria3867ed2009-04-18 15:36:11 +0000170 }
171
172 if (!(env->hflags & HF_PE_MASK) || !(sc->flags & DESC_P_MASK))
173 goto done;
174
175 cpu_fprintf(f, " DPL=%d ", (sc->flags & DESC_DPL_MASK) >> DESC_DPL_SHIFT);
176 if (sc->flags & DESC_S_MASK) {
177 if (sc->flags & DESC_CS_MASK) {
178 cpu_fprintf(f, (sc->flags & DESC_L_MASK) ? "CS64" :
179 ((sc->flags & DESC_B_MASK) ? "CS32" : "CS16"));
180 cpu_fprintf(f, " [%c%c", (sc->flags & DESC_C_MASK) ? 'C' : '-',
181 (sc->flags & DESC_R_MASK) ? 'R' : '-');
182 } else {
Tobias Markus469936a2013-08-25 12:20:06 +0200183 cpu_fprintf(f,
184 (sc->flags & DESC_B_MASK || env->hflags & HF_LMA_MASK)
185 ? "DS " : "DS16");
aliguoria3867ed2009-04-18 15:36:11 +0000186 cpu_fprintf(f, " [%c%c", (sc->flags & DESC_E_MASK) ? 'E' : '-',
187 (sc->flags & DESC_W_MASK) ? 'W' : '-');
188 }
189 cpu_fprintf(f, "%c]", (sc->flags & DESC_A_MASK) ? 'A' : '-');
190 } else {
191 static const char *sys_type_name[2][16] = {
192 { /* 32 bit mode */
193 "Reserved", "TSS16-avl", "LDT", "TSS16-busy",
194 "CallGate16", "TaskGate", "IntGate16", "TrapGate16",
195 "Reserved", "TSS32-avl", "Reserved", "TSS32-busy",
196 "CallGate32", "Reserved", "IntGate32", "TrapGate32"
197 },
198 { /* 64 bit mode */
199 "<hiword>", "Reserved", "LDT", "Reserved", "Reserved",
200 "Reserved", "Reserved", "Reserved", "Reserved",
201 "TSS64-avl", "Reserved", "TSS64-busy", "CallGate64",
202 "Reserved", "IntGate64", "TrapGate64"
203 }
204 };
Stefan Weile5c15ef2010-04-01 20:03:30 +0200205 cpu_fprintf(f, "%s",
206 sys_type_name[(env->hflags & HF_LMA_MASK) ? 1 : 0]
207 [(sc->flags & DESC_TYPE_MASK)
208 >> DESC_TYPE_SHIFT]);
aliguoria3867ed2009-04-18 15:36:11 +0000209 }
210done:
211 cpu_fprintf(f, "\n");
212}
213
Pavel Butsykin1f871d42015-09-22 16:18:18 +0300214#ifndef CONFIG_USER_ONLY
215
216/* ARRAY_SIZE check is not required because
217 * DeliveryMode(dm) has a size of 3 bit.
218 */
219static inline const char *dm2str(uint32_t dm)
220{
221 static const char *str[] = {
222 "Fixed",
223 "...",
224 "SMI",
225 "...",
226 "NMI",
227 "INIT",
228 "...",
229 "ExtINT"
230 };
231 return str[dm];
232}
233
234static void dump_apic_lvt(FILE *f, fprintf_function cpu_fprintf,
235 const char *name, uint32_t lvt, bool is_timer)
236{
237 uint32_t dm = (lvt & APIC_LVT_DELIV_MOD) >> APIC_LVT_DELIV_MOD_SHIFT;
238 cpu_fprintf(f,
239 "%s\t 0x%08x %s %-5s %-6s %-7s %-12s %-6s",
240 name, lvt,
241 lvt & APIC_LVT_INT_POLARITY ? "active-lo" : "active-hi",
242 lvt & APIC_LVT_LEVEL_TRIGGER ? "level" : "edge",
243 lvt & APIC_LVT_MASKED ? "masked" : "",
244 lvt & APIC_LVT_DELIV_STS ? "pending" : "",
245 !is_timer ?
246 "" : lvt & APIC_LVT_TIMER_PERIODIC ?
247 "periodic" : lvt & APIC_LVT_TIMER_TSCDEADLINE ?
248 "tsc-deadline" : "one-shot",
249 dm2str(dm));
250 if (dm != APIC_DM_NMI) {
251 cpu_fprintf(f, " (vec %u)\n", lvt & APIC_VECTOR_MASK);
252 } else {
253 cpu_fprintf(f, "\n");
254 }
255}
256
257/* ARRAY_SIZE check is not required because
258 * destination shorthand has a size of 2 bit.
259 */
260static inline const char *shorthand2str(uint32_t shorthand)
261{
262 const char *str[] = {
263 "no-shorthand", "self", "all-self", "all"
264 };
265 return str[shorthand];
266}
267
268static inline uint8_t divider_conf(uint32_t divide_conf)
269{
270 uint8_t divide_val = ((divide_conf & 0x8) >> 1) | (divide_conf & 0x3);
271
272 return divide_val == 7 ? 1 : 2 << divide_val;
273}
274
275static inline void mask2str(char *str, uint32_t val, uint8_t size)
276{
277 while (size--) {
278 *str++ = (val >> size) & 1 ? '1' : '0';
279 }
280 *str = 0;
281}
282
283#define MAX_LOGICAL_APIC_ID_MASK_SIZE 16
284
285static void dump_apic_icr(FILE *f, fprintf_function cpu_fprintf,
286 APICCommonState *s, CPUX86State *env)
287{
288 uint32_t icr = s->icr[0], icr2 = s->icr[1];
289 uint8_t dest_shorthand = \
290 (icr & APIC_ICR_DEST_SHORT) >> APIC_ICR_DEST_SHORT_SHIFT;
291 bool logical_mod = icr & APIC_ICR_DEST_MOD;
292 char apic_id_str[MAX_LOGICAL_APIC_ID_MASK_SIZE + 1];
293 uint32_t dest_field;
294 bool x2apic;
295
296 cpu_fprintf(f, "ICR\t 0x%08x %s %s %s %s\n",
297 icr,
298 logical_mod ? "logical" : "physical",
299 icr & APIC_ICR_TRIGGER_MOD ? "level" : "edge",
300 icr & APIC_ICR_LEVEL ? "assert" : "de-assert",
301 shorthand2str(dest_shorthand));
302
303 cpu_fprintf(f, "ICR2\t 0x%08x", icr2);
304 if (dest_shorthand != 0) {
305 cpu_fprintf(f, "\n");
306 return;
307 }
308 x2apic = env->features[FEAT_1_ECX] & CPUID_EXT_X2APIC;
309 dest_field = x2apic ? icr2 : icr2 >> APIC_ICR_DEST_SHIFT;
310
311 if (!logical_mod) {
312 if (x2apic) {
313 cpu_fprintf(f, " cpu %u (X2APIC ID)\n", dest_field);
314 } else {
315 cpu_fprintf(f, " cpu %u (APIC ID)\n",
316 dest_field & APIC_LOGDEST_XAPIC_ID);
317 }
318 return;
319 }
320
321 if (s->dest_mode == 0xf) { /* flat mode */
322 mask2str(apic_id_str, icr2 >> APIC_ICR_DEST_SHIFT, 8);
323 cpu_fprintf(f, " mask %s (APIC ID)\n", apic_id_str);
324 } else if (s->dest_mode == 0) { /* cluster mode */
325 if (x2apic) {
326 mask2str(apic_id_str, dest_field & APIC_LOGDEST_X2APIC_ID, 16);
327 cpu_fprintf(f, " cluster %u mask %s (X2APIC ID)\n",
328 dest_field >> APIC_LOGDEST_X2APIC_SHIFT, apic_id_str);
329 } else {
330 mask2str(apic_id_str, dest_field & APIC_LOGDEST_XAPIC_ID, 4);
331 cpu_fprintf(f, " cluster %u mask %s (APIC ID)\n",
332 dest_field >> APIC_LOGDEST_XAPIC_SHIFT, apic_id_str);
333 }
334 }
335}
336
337static void dump_apic_interrupt(FILE *f, fprintf_function cpu_fprintf,
338 const char *name, uint32_t *ireg_tab,
339 uint32_t *tmr_tab)
340{
341 int i, empty = true;
342
343 cpu_fprintf(f, "%s\t ", name);
344 for (i = 0; i < 256; i++) {
345 if (apic_get_bit(ireg_tab, i)) {
346 cpu_fprintf(f, "%u%s ", i,
347 apic_get_bit(tmr_tab, i) ? "(level)" : "");
348 empty = false;
349 }
350 }
351 cpu_fprintf(f, "%s\n", empty ? "(none)" : "");
352}
353
354void x86_cpu_dump_local_apic_state(CPUState *cs, FILE *f,
355 fprintf_function cpu_fprintf, int flags)
356{
357 X86CPU *cpu = X86_CPU(cs);
358 APICCommonState *s = APIC_COMMON(cpu->apic_state);
Tejaswini Poluric7f15bc2017-03-28 12:49:43 +0530359 if (!s) {
360 cpu_fprintf(f, "local apic state not available\n");
361 return;
362 }
Pavel Butsykin1f871d42015-09-22 16:18:18 +0300363 uint32_t *lvt = s->lvt;
364
365 cpu_fprintf(f, "dumping local APIC state for CPU %-2u\n\n",
366 CPU(cpu)->cpu_index);
367 dump_apic_lvt(f, cpu_fprintf, "LVT0", lvt[APIC_LVT_LINT0], false);
368 dump_apic_lvt(f, cpu_fprintf, "LVT1", lvt[APIC_LVT_LINT1], false);
369 dump_apic_lvt(f, cpu_fprintf, "LVTPC", lvt[APIC_LVT_PERFORM], false);
370 dump_apic_lvt(f, cpu_fprintf, "LVTERR", lvt[APIC_LVT_ERROR], false);
371 dump_apic_lvt(f, cpu_fprintf, "LVTTHMR", lvt[APIC_LVT_THERMAL], false);
372 dump_apic_lvt(f, cpu_fprintf, "LVTT", lvt[APIC_LVT_TIMER], true);
373
374 cpu_fprintf(f, "Timer\t DCR=0x%x (divide by %u) initial_count = %u\n",
375 s->divide_conf & APIC_DCR_MASK,
376 divider_conf(s->divide_conf),
377 s->initial_count);
378
379 cpu_fprintf(f, "SPIV\t 0x%08x APIC %s, focus=%s, spurious vec %u\n",
380 s->spurious_vec,
381 s->spurious_vec & APIC_SPURIO_ENABLED ? "enabled" : "disabled",
382 s->spurious_vec & APIC_SPURIO_FOCUS ? "on" : "off",
383 s->spurious_vec & APIC_VECTOR_MASK);
384
385 dump_apic_icr(f, cpu_fprintf, s, &cpu->env);
386
387 cpu_fprintf(f, "ESR\t 0x%08x\n", s->esr);
388
389 dump_apic_interrupt(f, cpu_fprintf, "ISR", s->isr, s->tmr);
390 dump_apic_interrupt(f, cpu_fprintf, "IRR", s->irr, s->tmr);
391
392 cpu_fprintf(f, "\nAPR 0x%02x TPR 0x%02x DFR 0x%02x LDR 0x%02x",
393 s->arb_id, s->tpr, s->dest_mode, s->log_dest);
394 if (s->dest_mode == 0) {
395 cpu_fprintf(f, "(cluster %u: id %u)",
396 s->log_dest >> APIC_LOGDEST_XAPIC_SHIFT,
397 s->log_dest & APIC_LOGDEST_XAPIC_ID);
398 }
399 cpu_fprintf(f, " PPR 0x%02x\n", apic_get_ppr(s));
400}
401#else
402void x86_cpu_dump_local_apic_state(CPUState *cs, FILE *f,
403 fprintf_function cpu_fprintf, int flags)
404{
405}
406#endif /* !CONFIG_USER_ONLY */
407
Jan Kiszkaf5c848e2011-01-21 21:48:08 +0100408#define DUMP_CODE_BYTES_TOTAL 50
409#define DUMP_CODE_BYTES_BACKWARD 20
410
Andreas Färber878096e2013-05-27 01:33:50 +0200411void x86_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
412 int flags)
bellardeaa728e2008-05-28 12:51:20 +0000413{
Andreas Färber878096e2013-05-27 01:33:50 +0200414 X86CPU *cpu = X86_CPU(cs);
415 CPUX86State *env = &cpu->env;
bellardeaa728e2008-05-28 12:51:20 +0000416 int eflags, i, nb;
417 char cc_op_name[32];
418 static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
419
Richard Henderson4980ef92013-03-19 12:11:56 -0700420 eflags = cpu_compute_eflags(env);
bellardeaa728e2008-05-28 12:51:20 +0000421#ifdef TARGET_X86_64
422 if (env->hflags & HF_CS64_MASK) {
423 cpu_fprintf(f,
424 "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
425 "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
426 "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
427 "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
428 "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
429 env->regs[R_EAX],
430 env->regs[R_EBX],
431 env->regs[R_ECX],
432 env->regs[R_EDX],
433 env->regs[R_ESI],
434 env->regs[R_EDI],
435 env->regs[R_EBP],
436 env->regs[R_ESP],
437 env->regs[8],
438 env->regs[9],
439 env->regs[10],
440 env->regs[11],
441 env->regs[12],
442 env->regs[13],
443 env->regs[14],
444 env->regs[15],
445 env->eip, eflags,
446 eflags & DF_MASK ? 'D' : '-',
447 eflags & CC_O ? 'O' : '-',
448 eflags & CC_S ? 'S' : '-',
449 eflags & CC_Z ? 'Z' : '-',
450 eflags & CC_A ? 'A' : '-',
451 eflags & CC_P ? 'P' : '-',
452 eflags & CC_C ? 'C' : '-',
453 env->hflags & HF_CPL_MASK,
454 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
Juan Quintela5ee0ffa2009-09-29 22:48:49 +0200455 (env->a20_mask >> 20) & 1,
bellardeaa728e2008-05-28 12:51:20 +0000456 (env->hflags >> HF_SMM_SHIFT) & 1,
Andreas Färber259186a2013-01-17 18:51:17 +0100457 cs->halted);
bellardeaa728e2008-05-28 12:51:20 +0000458 } else
459#endif
460 {
461 cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
462 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
463 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
464 (uint32_t)env->regs[R_EAX],
465 (uint32_t)env->regs[R_EBX],
466 (uint32_t)env->regs[R_ECX],
467 (uint32_t)env->regs[R_EDX],
468 (uint32_t)env->regs[R_ESI],
469 (uint32_t)env->regs[R_EDI],
470 (uint32_t)env->regs[R_EBP],
471 (uint32_t)env->regs[R_ESP],
472 (uint32_t)env->eip, eflags,
473 eflags & DF_MASK ? 'D' : '-',
474 eflags & CC_O ? 'O' : '-',
475 eflags & CC_S ? 'S' : '-',
476 eflags & CC_Z ? 'Z' : '-',
477 eflags & CC_A ? 'A' : '-',
478 eflags & CC_P ? 'P' : '-',
479 eflags & CC_C ? 'C' : '-',
480 env->hflags & HF_CPL_MASK,
481 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
Juan Quintela5ee0ffa2009-09-29 22:48:49 +0200482 (env->a20_mask >> 20) & 1,
bellardeaa728e2008-05-28 12:51:20 +0000483 (env->hflags >> HF_SMM_SHIFT) & 1,
Andreas Färber259186a2013-01-17 18:51:17 +0100484 cs->halted);
bellardeaa728e2008-05-28 12:51:20 +0000485 }
486
aliguoria3867ed2009-04-18 15:36:11 +0000487 for(i = 0; i < 6; i++) {
488 cpu_x86_dump_seg_cache(env, f, cpu_fprintf, seg_name[i],
489 &env->segs[i]);
490 }
491 cpu_x86_dump_seg_cache(env, f, cpu_fprintf, "LDT", &env->ldt);
492 cpu_x86_dump_seg_cache(env, f, cpu_fprintf, "TR", &env->tr);
493
bellardeaa728e2008-05-28 12:51:20 +0000494#ifdef TARGET_X86_64
495 if (env->hflags & HF_LMA_MASK) {
bellardeaa728e2008-05-28 12:51:20 +0000496 cpu_fprintf(f, "GDT= %016" PRIx64 " %08x\n",
497 env->gdt.base, env->gdt.limit);
498 cpu_fprintf(f, "IDT= %016" PRIx64 " %08x\n",
499 env->idt.base, env->idt.limit);
500 cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
501 (uint32_t)env->cr[0],
502 env->cr[2],
503 env->cr[3],
504 (uint32_t)env->cr[4]);
aliguoria59cb4e2008-11-18 21:09:47 +0000505 for(i = 0; i < 4; i++)
506 cpu_fprintf(f, "DR%d=%016" PRIx64 " ", i, env->dr[i]);
507 cpu_fprintf(f, "\nDR6=%016" PRIx64 " DR7=%016" PRIx64 "\n",
aliguorid4b55be2008-12-02 19:40:26 +0000508 env->dr[6], env->dr[7]);
bellardeaa728e2008-05-28 12:51:20 +0000509 } else
510#endif
511 {
bellardeaa728e2008-05-28 12:51:20 +0000512 cpu_fprintf(f, "GDT= %08x %08x\n",
513 (uint32_t)env->gdt.base, env->gdt.limit);
514 cpu_fprintf(f, "IDT= %08x %08x\n",
515 (uint32_t)env->idt.base, env->idt.limit);
516 cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
517 (uint32_t)env->cr[0],
518 (uint32_t)env->cr[2],
519 (uint32_t)env->cr[3],
520 (uint32_t)env->cr[4]);
Stefan Weil9a78eea2010-10-22 23:03:33 +0200521 for(i = 0; i < 4; i++) {
522 cpu_fprintf(f, "DR%d=" TARGET_FMT_lx " ", i, env->dr[i]);
523 }
524 cpu_fprintf(f, "\nDR6=" TARGET_FMT_lx " DR7=" TARGET_FMT_lx "\n",
525 env->dr[6], env->dr[7]);
bellardeaa728e2008-05-28 12:51:20 +0000526 }
Peter Maydell6fd2a022012-10-05 15:04:43 +0100527 if (flags & CPU_DUMP_CCOP) {
bellardeaa728e2008-05-28 12:51:20 +0000528 if ((unsigned)env->cc_op < CC_OP_NB)
529 snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
530 else
531 snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
532#ifdef TARGET_X86_64
533 if (env->hflags & HF_CS64_MASK) {
534 cpu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
535 env->cc_src, env->cc_dst,
536 cc_op_name);
537 } else
538#endif
539 {
540 cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
541 (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
542 cc_op_name);
543 }
544 }
Marcelo Tosattib5e5a932010-03-23 13:37:10 -0300545 cpu_fprintf(f, "EFER=%016" PRIx64 "\n", env->efer);
Peter Maydell6fd2a022012-10-05 15:04:43 +0100546 if (flags & CPU_DUMP_FPU) {
bellardeaa728e2008-05-28 12:51:20 +0000547 int fptag;
548 fptag = 0;
549 for(i = 0; i < 8; i++) {
550 fptag |= ((!env->fptags[i]) << i);
551 }
552 cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
553 env->fpuc,
554 (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
555 env->fpstt,
556 fptag,
557 env->mxcsr);
558 for(i=0;i<8;i++) {
Aurelien Jarno1ffd41e2011-04-14 00:49:29 +0200559 CPU_LDoubleU u;
560 u.d = env->fpregs[i].d;
bellardeaa728e2008-05-28 12:51:20 +0000561 cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
Aurelien Jarno1ffd41e2011-04-14 00:49:29 +0200562 i, u.l.lower, u.l.upper);
bellardeaa728e2008-05-28 12:51:20 +0000563 if ((i & 1) == 1)
564 cpu_fprintf(f, "\n");
565 else
566 cpu_fprintf(f, " ");
567 }
568 if (env->hflags & HF_CS64_MASK)
569 nb = 16;
570 else
571 nb = 8;
572 for(i=0;i<nb;i++) {
573 cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
574 i,
Eduardo Habkost19cbd872015-11-26 17:14:32 -0200575 env->xmm_regs[i].ZMM_L(3),
576 env->xmm_regs[i].ZMM_L(2),
577 env->xmm_regs[i].ZMM_L(1),
578 env->xmm_regs[i].ZMM_L(0));
bellardeaa728e2008-05-28 12:51:20 +0000579 if ((i & 1) == 1)
580 cpu_fprintf(f, "\n");
581 else
582 cpu_fprintf(f, " ");
583 }
584 }
Jan Kiszkaf5c848e2011-01-21 21:48:08 +0100585 if (flags & CPU_DUMP_CODE) {
586 target_ulong base = env->segs[R_CS].base + env->eip;
587 target_ulong offs = MIN(env->eip, DUMP_CODE_BYTES_BACKWARD);
588 uint8_t code;
589 char codestr[3];
590
591 cpu_fprintf(f, "Code=");
592 for (i = 0; i < DUMP_CODE_BYTES_TOTAL; i++) {
Andreas Färberf17ec442013-06-29 19:40:58 +0200593 if (cpu_memory_rw_debug(cs, base - offs + i, &code, 1, 0) == 0) {
Jan Kiszkaf5c848e2011-01-21 21:48:08 +0100594 snprintf(codestr, sizeof(codestr), "%02x", code);
595 } else {
596 snprintf(codestr, sizeof(codestr), "??");
597 }
598 cpu_fprintf(f, "%s%s%s%s", i > 0 ? " " : "",
599 i == offs ? "<" : "", codestr, i == offs ? ">" : "");
600 }
601 cpu_fprintf(f, "\n");
602 }
bellardeaa728e2008-05-28 12:51:20 +0000603}
604
605/***********************************************************/
606/* x86 mmu */
607/* XXX: add PGE support */
608
Andreas Färbercc36a7a2013-01-18 15:19:06 +0100609void x86_cpu_set_a20(X86CPU *cpu, int a20_state)
bellardeaa728e2008-05-28 12:51:20 +0000610{
Andreas Färbercc36a7a2013-01-18 15:19:06 +0100611 CPUX86State *env = &cpu->env;
612
bellardeaa728e2008-05-28 12:51:20 +0000613 a20_state = (a20_state != 0);
614 if (a20_state != ((env->a20_mask >> 20) & 1)) {
Andreas Färber00c8cb02013-09-04 02:19:44 +0200615 CPUState *cs = CPU(cpu);
616
Antony Pavlov339aaf52014-12-13 19:48:18 +0300617 qemu_log_mask(CPU_LOG_MMU, "A20 update: a20=%d\n", a20_state);
bellardeaa728e2008-05-28 12:51:20 +0000618 /* if the cpu is currently executing code, we must unlink it and
619 all the potentially executing TB */
Andreas Färber00c8cb02013-09-04 02:19:44 +0200620 cpu_interrupt(cs, CPU_INTERRUPT_EXITTB);
bellardeaa728e2008-05-28 12:51:20 +0000621
622 /* when a20 is changed, all the MMU mappings are invalid, so
623 we must flush everything */
Alex Bennéed10eb082016-11-14 14:17:28 +0000624 tlb_flush(cs);
Juan Quintela5ee0ffa2009-09-29 22:48:49 +0200625 env->a20_mask = ~(1 << 20) | (a20_state << 20);
bellardeaa728e2008-05-28 12:51:20 +0000626 }
627}
628
629void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
630{
Andreas Färber00c8cb02013-09-04 02:19:44 +0200631 X86CPU *cpu = x86_env_get_cpu(env);
bellardeaa728e2008-05-28 12:51:20 +0000632 int pe_state;
633
Antony Pavlov339aaf52014-12-13 19:48:18 +0300634 qemu_log_mask(CPU_LOG_MMU, "CR0 update: CR0=0x%08x\n", new_cr0);
bellardeaa728e2008-05-28 12:51:20 +0000635 if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
636 (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
Alex Bennéed10eb082016-11-14 14:17:28 +0000637 tlb_flush(CPU(cpu));
bellardeaa728e2008-05-28 12:51:20 +0000638 }
639
640#ifdef TARGET_X86_64
641 if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
642 (env->efer & MSR_EFER_LME)) {
643 /* enter in long mode */
644 /* XXX: generate an exception */
645 if (!(env->cr[4] & CR4_PAE_MASK))
646 return;
647 env->efer |= MSR_EFER_LMA;
648 env->hflags |= HF_LMA_MASK;
649 } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
650 (env->efer & MSR_EFER_LMA)) {
651 /* exit long mode */
652 env->efer &= ~MSR_EFER_LMA;
653 env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
654 env->eip &= 0xffffffff;
655 }
656#endif
657 env->cr[0] = new_cr0 | CR0_ET_MASK;
658
659 /* update PE flag in hidden flags */
660 pe_state = (env->cr[0] & CR0_PE_MASK);
661 env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
662 /* ensure that ADDSEG is always set in real mode */
663 env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
664 /* update FPU flags */
665 env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
666 ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
667}
668
669/* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
670 the PDPT */
671void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
672{
Andreas Färber00c8cb02013-09-04 02:19:44 +0200673 X86CPU *cpu = x86_env_get_cpu(env);
674
bellardeaa728e2008-05-28 12:51:20 +0000675 env->cr[3] = new_cr3;
676 if (env->cr[0] & CR0_PG_MASK) {
Antony Pavlov339aaf52014-12-13 19:48:18 +0300677 qemu_log_mask(CPU_LOG_MMU,
678 "CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
Alex Bennéed10eb082016-11-14 14:17:28 +0000679 tlb_flush(CPU(cpu));
bellardeaa728e2008-05-28 12:51:20 +0000680 }
681}
682
683void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
684{
Andreas Färber00c8cb02013-09-04 02:19:44 +0200685 X86CPU *cpu = x86_env_get_cpu(env);
Richard Henderson19dc85d2015-07-02 14:53:40 +0100686 uint32_t hflags;
Andreas Färber00c8cb02013-09-04 02:19:44 +0200687
bellardeaa728e2008-05-28 12:51:20 +0000688#if defined(DEBUG_MMU)
Kirill A. Shutemov6c7c3c22016-12-15 03:13:05 +0300689 printf("CR4 update: %08x -> %08x\n", (uint32_t)env->cr[4], new_cr4);
bellardeaa728e2008-05-28 12:51:20 +0000690#endif
H. Peter Anvina9321a42012-09-26 13:18:43 -0700691 if ((new_cr4 ^ env->cr[4]) &
692 (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK |
Kirill A. Shutemov6c7c3c22016-12-15 03:13:05 +0300693 CR4_SMEP_MASK | CR4_SMAP_MASK | CR4_LA57_MASK)) {
Alex Bennéed10eb082016-11-14 14:17:28 +0000694 tlb_flush(CPU(cpu));
bellardeaa728e2008-05-28 12:51:20 +0000695 }
Richard Henderson19dc85d2015-07-02 14:53:40 +0100696
697 /* Clear bits we're going to recompute. */
698 hflags = env->hflags & ~(HF_OSFXSR_MASK | HF_SMAP_MASK);
699
bellardeaa728e2008-05-28 12:51:20 +0000700 /* SSE handling */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300701 if (!(env->features[FEAT_1_EDX] & CPUID_SSE)) {
bellardeaa728e2008-05-28 12:51:20 +0000702 new_cr4 &= ~CR4_OSFXSR_MASK;
H. Peter Anvina9321a42012-09-26 13:18:43 -0700703 }
H. Peter Anvina9321a42012-09-26 13:18:43 -0700704 if (new_cr4 & CR4_OSFXSR_MASK) {
Richard Henderson19dc85d2015-07-02 14:53:40 +0100705 hflags |= HF_OSFXSR_MASK;
H. Peter Anvina9321a42012-09-26 13:18:43 -0700706 }
707
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300708 if (!(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_SMAP)) {
H. Peter Anvina9321a42012-09-26 13:18:43 -0700709 new_cr4 &= ~CR4_SMAP_MASK;
710 }
H. Peter Anvina9321a42012-09-26 13:18:43 -0700711 if (new_cr4 & CR4_SMAP_MASK) {
Richard Henderson19dc85d2015-07-02 14:53:40 +0100712 hflags |= HF_SMAP_MASK;
H. Peter Anvina9321a42012-09-26 13:18:43 -0700713 }
bellardeaa728e2008-05-28 12:51:20 +0000714
Paolo Bonzini0f70ed42016-02-09 14:14:28 +0100715 if (!(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_PKU)) {
716 new_cr4 &= ~CR4_PKE_MASK;
717 }
718
bellardeaa728e2008-05-28 12:51:20 +0000719 env->cr[4] = new_cr4;
Richard Henderson19dc85d2015-07-02 14:53:40 +0100720 env->hflags = hflags;
Richard Hendersonf4f11102015-07-02 15:57:14 +0100721
722 cpu_sync_bndcs_hflags(env);
bellardeaa728e2008-05-28 12:51:20 +0000723}
724
Paolo Bonzini6578eb22017-07-03 18:10:00 +0200725#if !defined(CONFIG_USER_ONLY)
Andreas Färber00b941e2013-06-29 18:55:54 +0200726hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
bellardeaa728e2008-05-28 12:51:20 +0000727{
Andreas Färber00b941e2013-06-29 18:55:54 +0200728 X86CPU *cpu = X86_CPU(cs);
729 CPUX86State *env = &cpu->env;
bellardeaa728e2008-05-28 12:51:20 +0000730 target_ulong pde_addr, pte_addr;
731 uint64_t pte;
Paolo Bonzinic8bc83a2017-05-11 13:35:28 +0200732 int32_t a20_mask;
bellardeaa728e2008-05-28 12:51:20 +0000733 uint32_t page_offset;
734 int page_size;
735
Paolo Bonzinic8bc83a2017-05-11 13:35:28 +0200736 a20_mask = x86_get_a20_mask(env);
Paolo Bonzinif2f85602013-08-30 11:58:45 +0200737 if (!(env->cr[0] & CR0_PG_MASK)) {
Paolo Bonzinic8bc83a2017-05-11 13:35:28 +0200738 pte = addr & a20_mask;
Paolo Bonzinif2f85602013-08-30 11:58:45 +0200739 page_size = 4096;
740 } else if (env->cr[4] & CR4_PAE_MASK) {
bellardeaa728e2008-05-28 12:51:20 +0000741 target_ulong pdpe_addr;
742 uint64_t pde, pdpe;
743
744#ifdef TARGET_X86_64
745 if (env->hflags & HF_LMA_MASK) {
Kirill A. Shutemov6c7c3c22016-12-15 03:13:05 +0300746 bool la57 = env->cr[4] & CR4_LA57_MASK;
747 uint64_t pml5e_addr, pml5e;
bellardeaa728e2008-05-28 12:51:20 +0000748 uint64_t pml4e_addr, pml4e;
749 int32_t sext;
750
751 /* test virtual address sign extension */
Kirill A. Shutemov6c7c3c22016-12-15 03:13:05 +0300752 sext = la57 ? (int64_t)addr >> 56 : (int64_t)addr >> 47;
Paolo Bonzini16b96f82014-05-27 14:58:47 +0200753 if (sext != 0 && sext != -1) {
bellardeaa728e2008-05-28 12:51:20 +0000754 return -1;
Paolo Bonzini16b96f82014-05-27 14:58:47 +0200755 }
Kirill A. Shutemov6c7c3c22016-12-15 03:13:05 +0300756
757 if (la57) {
758 pml5e_addr = ((env->cr[3] & ~0xfff) +
Paolo Bonzinic8bc83a2017-05-11 13:35:28 +0200759 (((addr >> 48) & 0x1ff) << 3)) & a20_mask;
Kirill A. Shutemov6c7c3c22016-12-15 03:13:05 +0300760 pml5e = x86_ldq_phys(cs, pml5e_addr);
761 if (!(pml5e & PG_PRESENT_MASK)) {
762 return -1;
763 }
764 } else {
765 pml5e = env->cr[3];
766 }
767
768 pml4e_addr = ((pml5e & PG_ADDRESS_MASK) +
Paolo Bonzinic8bc83a2017-05-11 13:35:28 +0200769 (((addr >> 39) & 0x1ff) << 3)) & a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200770 pml4e = x86_ldq_phys(cs, pml4e_addr);
Paolo Bonzini16b96f82014-05-27 14:58:47 +0200771 if (!(pml4e & PG_PRESENT_MASK)) {
bellardeaa728e2008-05-28 12:51:20 +0000772 return -1;
Paolo Bonzini16b96f82014-05-27 14:58:47 +0200773 }
774 pdpe_addr = ((pml4e & PG_ADDRESS_MASK) +
Paolo Bonzinic8bc83a2017-05-11 13:35:28 +0200775 (((addr >> 30) & 0x1ff) << 3)) & a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200776 pdpe = x86_ldq_phys(cs, pdpe_addr);
Paolo Bonzini16b96f82014-05-27 14:58:47 +0200777 if (!(pdpe & PG_PRESENT_MASK)) {
bellardeaa728e2008-05-28 12:51:20 +0000778 return -1;
Paolo Bonzini16b96f82014-05-27 14:58:47 +0200779 }
Luiz Capitulinoc8c14bc2014-03-19 17:03:53 -0400780 if (pdpe & PG_PSE_MASK) {
781 page_size = 1024 * 1024 * 1024;
Paolo Bonzini16b96f82014-05-27 14:58:47 +0200782 pte = pdpe;
Luiz Capitulinoc8c14bc2014-03-19 17:03:53 -0400783 goto out;
784 }
785
bellardeaa728e2008-05-28 12:51:20 +0000786 } else
787#endif
788 {
789 pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
Paolo Bonzinic8bc83a2017-05-11 13:35:28 +0200790 a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200791 pdpe = x86_ldq_phys(cs, pdpe_addr);
bellardeaa728e2008-05-28 12:51:20 +0000792 if (!(pdpe & PG_PRESENT_MASK))
793 return -1;
794 }
795
Paolo Bonzini16b96f82014-05-27 14:58:47 +0200796 pde_addr = ((pdpe & PG_ADDRESS_MASK) +
Paolo Bonzinic8bc83a2017-05-11 13:35:28 +0200797 (((addr >> 21) & 0x1ff) << 3)) & a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200798 pde = x86_ldq_phys(cs, pde_addr);
bellardeaa728e2008-05-28 12:51:20 +0000799 if (!(pde & PG_PRESENT_MASK)) {
800 return -1;
801 }
802 if (pde & PG_PSE_MASK) {
803 /* 2 MB page */
804 page_size = 2048 * 1024;
Paolo Bonzini16b96f82014-05-27 14:58:47 +0200805 pte = pde;
bellardeaa728e2008-05-28 12:51:20 +0000806 } else {
807 /* 4 KB page */
Paolo Bonzini16b96f82014-05-27 14:58:47 +0200808 pte_addr = ((pde & PG_ADDRESS_MASK) +
Paolo Bonzinic8bc83a2017-05-11 13:35:28 +0200809 (((addr >> 12) & 0x1ff) << 3)) & a20_mask;
bellardeaa728e2008-05-28 12:51:20 +0000810 page_size = 4096;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200811 pte = x86_ldq_phys(cs, pte_addr);
bellardeaa728e2008-05-28 12:51:20 +0000812 }
Paolo Bonzini16b96f82014-05-27 14:58:47 +0200813 if (!(pte & PG_PRESENT_MASK)) {
aliguorica1c9e12008-08-18 18:00:31 +0000814 return -1;
Paolo Bonzini16b96f82014-05-27 14:58:47 +0200815 }
bellardeaa728e2008-05-28 12:51:20 +0000816 } else {
817 uint32_t pde;
818
Paolo Bonzinif2f85602013-08-30 11:58:45 +0200819 /* page directory entry */
Paolo Bonzinic8bc83a2017-05-11 13:35:28 +0200820 pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200821 pde = x86_ldl_phys(cs, pde_addr);
Paolo Bonzinif2f85602013-08-30 11:58:45 +0200822 if (!(pde & PG_PRESENT_MASK))
823 return -1;
824 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
Paolo Bonzini388ee482016-02-09 11:44:35 +0100825 pte = pde | ((pde & 0x1fe000LL) << (32 - 13));
Paolo Bonzinif2f85602013-08-30 11:58:45 +0200826 page_size = 4096 * 1024;
bellardeaa728e2008-05-28 12:51:20 +0000827 } else {
828 /* page directory entry */
Paolo Bonzinic8bc83a2017-05-11 13:35:28 +0200829 pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200830 pte = x86_ldl_phys(cs, pte_addr);
Paolo Bonzini16b96f82014-05-27 14:58:47 +0200831 if (!(pte & PG_PRESENT_MASK)) {
bellardeaa728e2008-05-28 12:51:20 +0000832 return -1;
Paolo Bonzini16b96f82014-05-27 14:58:47 +0200833 }
Paolo Bonzinif2f85602013-08-30 11:58:45 +0200834 page_size = 4096;
bellardeaa728e2008-05-28 12:51:20 +0000835 }
Paolo Bonzinic8bc83a2017-05-11 13:35:28 +0200836 pte = pte & a20_mask;
bellardeaa728e2008-05-28 12:51:20 +0000837 }
838
Luiz Capitulinoc8c14bc2014-03-19 17:03:53 -0400839#ifdef TARGET_X86_64
840out:
841#endif
Paolo Bonzini16b96f82014-05-27 14:58:47 +0200842 pte &= PG_ADDRESS_MASK & ~(page_size - 1);
bellardeaa728e2008-05-28 12:51:20 +0000843 page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
Paolo Bonzini16b96f82014-05-27 14:58:47 +0200844 return pte | page_offset;
bellardeaa728e2008-05-28 12:51:20 +0000845}
aliguori01df0402008-11-18 21:08:15 +0000846
Jan Kiszkad5bfda32011-03-02 08:56:15 +0100847typedef struct MCEInjectionParams {
848 Monitor *mon;
Jan Kiszkad5bfda32011-03-02 08:56:15 +0100849 int bank;
850 uint64_t status;
851 uint64_t mcg_status;
852 uint64_t addr;
853 uint64_t misc;
854 int flags;
855} MCEInjectionParams;
856
Paolo Bonzini14e6fe12016-10-31 10:36:08 +0100857static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data)
Huang Ying79c4f6b2009-06-23 10:05:14 +0800858{
Paolo Bonzini14e6fe12016-10-31 10:36:08 +0100859 MCEInjectionParams *params = data.host_ptr;
Alex Bennéee0eeb4a2016-08-02 18:27:33 +0100860 X86CPU *cpu = X86_CPU(cs);
861 CPUX86State *cenv = &cpu->env;
Jan Kiszkad5bfda32011-03-02 08:56:15 +0100862 uint64_t *banks = cenv->mce_banks + 4 * params->bank;
863
Alex Bennéee0eeb4a2016-08-02 18:27:33 +0100864 cpu_synchronize_state(cs);
Huang Ying79c4f6b2009-06-23 10:05:14 +0800865
Jan Kiszka747461c2011-03-02 08:56:10 +0100866 /*
867 * If there is an MCE exception being processed, ignore this SRAO MCE
868 * unless unconditional injection was requested.
869 */
Jan Kiszkad5bfda32011-03-02 08:56:15 +0100870 if (!(params->flags & MCE_INJECT_UNCOND_AO)
871 && !(params->status & MCI_STATUS_AR)
Jan Kiszka747461c2011-03-02 08:56:10 +0100872 && (cenv->mcg_status & MCG_STATUS_MCIP)) {
873 return;
874 }
Jan Kiszkad5bfda32011-03-02 08:56:15 +0100875
876 if (params->status & MCI_STATUS_UC) {
Jan Kiszka316378e2011-03-02 08:56:09 +0100877 /*
878 * if MSR_MCG_CTL is not all 1s, the uncorrected error
879 * reporting is disabled
880 */
Jan Kiszkad5bfda32011-03-02 08:56:15 +0100881 if ((cenv->mcg_cap & MCG_CTL_P) && cenv->mcg_ctl != ~(uint64_t)0) {
882 monitor_printf(params->mon,
Jan Kiszka316378e2011-03-02 08:56:09 +0100883 "CPU %d: Uncorrected error reporting disabled\n",
Alex Bennéee0eeb4a2016-08-02 18:27:33 +0100884 cs->cpu_index);
Jan Kiszka316378e2011-03-02 08:56:09 +0100885 return;
886 }
887
888 /*
889 * if MSR_MCi_CTL is not all 1s, the uncorrected error
890 * reporting is disabled for the bank
891 */
892 if (banks[0] != ~(uint64_t)0) {
Jan Kiszkad5bfda32011-03-02 08:56:15 +0100893 monitor_printf(params->mon,
894 "CPU %d: Uncorrected error reporting disabled for"
895 " bank %d\n",
Alex Bennéee0eeb4a2016-08-02 18:27:33 +0100896 cs->cpu_index, params->bank);
Jan Kiszka316378e2011-03-02 08:56:09 +0100897 return;
898 }
899
Huang Ying79c4f6b2009-06-23 10:05:14 +0800900 if ((cenv->mcg_status & MCG_STATUS_MCIP) ||
901 !(cenv->cr[4] & CR4_MCE_MASK)) {
Jan Kiszkad5bfda32011-03-02 08:56:15 +0100902 monitor_printf(params->mon,
903 "CPU %d: Previous MCE still in progress, raising"
904 " triple fault\n",
Alex Bennéee0eeb4a2016-08-02 18:27:33 +0100905 cs->cpu_index);
Huang Ying79c4f6b2009-06-23 10:05:14 +0800906 qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
Eric Blakecf83f142017-05-15 16:41:13 -0500907 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
Huang Ying79c4f6b2009-06-23 10:05:14 +0800908 return;
909 }
Jan Kiszka2fa11da2011-03-02 08:56:08 +0100910 if (banks[1] & MCI_STATUS_VAL) {
Jan Kiszkad5bfda32011-03-02 08:56:15 +0100911 params->status |= MCI_STATUS_OVER;
Jan Kiszka2fa11da2011-03-02 08:56:08 +0100912 }
Jan Kiszkad5bfda32011-03-02 08:56:15 +0100913 banks[2] = params->addr;
914 banks[3] = params->misc;
915 cenv->mcg_status = params->mcg_status;
916 banks[1] = params->status;
Alex Bennéee0eeb4a2016-08-02 18:27:33 +0100917 cpu_interrupt(cs, CPU_INTERRUPT_MCE);
Huang Ying79c4f6b2009-06-23 10:05:14 +0800918 } else if (!(banks[1] & MCI_STATUS_VAL)
919 || !(banks[1] & MCI_STATUS_UC)) {
Jan Kiszka2fa11da2011-03-02 08:56:08 +0100920 if (banks[1] & MCI_STATUS_VAL) {
Jan Kiszkad5bfda32011-03-02 08:56:15 +0100921 params->status |= MCI_STATUS_OVER;
Jan Kiszka2fa11da2011-03-02 08:56:08 +0100922 }
Jan Kiszkad5bfda32011-03-02 08:56:15 +0100923 banks[2] = params->addr;
924 banks[3] = params->misc;
925 banks[1] = params->status;
Jan Kiszka2fa11da2011-03-02 08:56:08 +0100926 } else {
Huang Ying79c4f6b2009-06-23 10:05:14 +0800927 banks[1] |= MCI_STATUS_OVER;
Jan Kiszka2fa11da2011-03-02 08:56:08 +0100928 }
Huang Ying79c4f6b2009-06-23 10:05:14 +0800929}
Jin Dongmingb3cd24e2010-12-10 17:20:44 +0900930
Andreas Färber8c5cf3b2012-05-03 15:22:54 +0200931void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
Jan Kiszka316378e2011-03-02 08:56:09 +0100932 uint64_t status, uint64_t mcg_status, uint64_t addr,
Jan Kiszka747461c2011-03-02 08:56:10 +0100933 uint64_t misc, int flags)
Jin Dongmingb3cd24e2010-12-10 17:20:44 +0900934{
Andreas Färber182735e2013-05-29 22:29:20 +0200935 CPUState *cs = CPU(cpu);
Andreas Färber8c5cf3b2012-05-03 15:22:54 +0200936 CPUX86State *cenv = &cpu->env;
Jan Kiszkad5bfda32011-03-02 08:56:15 +0100937 MCEInjectionParams params = {
938 .mon = mon,
Jan Kiszkad5bfda32011-03-02 08:56:15 +0100939 .bank = bank,
940 .status = status,
941 .mcg_status = mcg_status,
942 .addr = addr,
943 .misc = misc,
944 .flags = flags,
945 };
Jin Dongmingb3cd24e2010-12-10 17:20:44 +0900946 unsigned bank_num = cenv->mcg_cap & 0xff;
947
Jan Kiszka316378e2011-03-02 08:56:09 +0100948 if (!cenv->mcg_cap) {
949 monitor_printf(mon, "MCE injection not supported\n");
Jin Dongmingb3cd24e2010-12-10 17:20:44 +0900950 return;
951 }
Jan Kiszka316378e2011-03-02 08:56:09 +0100952 if (bank >= bank_num) {
953 monitor_printf(mon, "Invalid MCE bank number\n");
954 return;
955 }
956 if (!(status & MCI_STATUS_VAL)) {
957 monitor_printf(mon, "Invalid MCE status code\n");
958 return;
959 }
Jan Kiszka747461c2011-03-02 08:56:10 +0100960 if ((flags & MCE_INJECT_BROADCAST)
961 && !cpu_x86_support_mca_broadcast(cenv)) {
Jan Kiszka316378e2011-03-02 08:56:09 +0100962 monitor_printf(mon, "Guest CPU does not support MCA broadcast\n");
963 return;
Jin Dongming2bd3e042010-12-10 17:21:14 +0900964 }
965
Paolo Bonzini14e6fe12016-10-31 10:36:08 +0100966 run_on_cpu(cs, do_inject_x86_mce, RUN_ON_CPU_HOST_PTR(&params));
Jan Kiszkac34d4402011-03-02 08:56:16 +0100967 if (flags & MCE_INJECT_BROADCAST) {
Andreas Färber182735e2013-05-29 22:29:20 +0200968 CPUState *other_cs;
969
Jan Kiszkac34d4402011-03-02 08:56:16 +0100970 params.bank = 1;
971 params.status = MCI_STATUS_VAL | MCI_STATUS_UC;
972 params.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV;
973 params.addr = 0;
974 params.misc = 0;
Andreas Färberbdc44642013-06-24 23:50:24 +0200975 CPU_FOREACH(other_cs) {
Andreas Färber182735e2013-05-29 22:29:20 +0200976 if (other_cs == cs) {
Jan Kiszkac34d4402011-03-02 08:56:16 +0100977 continue;
Jin Dongming31ce5e02010-12-10 17:21:02 +0900978 }
Paolo Bonzini14e6fe12016-10-31 10:36:08 +0100979 run_on_cpu(other_cs, do_inject_x86_mce, RUN_ON_CPU_HOST_PTR(&params));
Jin Dongming31ce5e02010-12-10 17:21:02 +0900980 }
Jin Dongmingb3cd24e2010-12-10 17:20:44 +0900981 }
982}
Jan Kiszkad362e752012-02-17 18:31:17 +0100983
Andreas Färber317ac622012-03-14 01:38:21 +0100984void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
Jan Kiszkad362e752012-02-17 18:31:17 +0100985{
Chen Fan02e51482013-12-23 17:04:02 +0800986 X86CPU *cpu = x86_env_get_cpu(env);
Andreas Färber93afead2013-08-26 03:41:01 +0200987 CPUState *cs = CPU(cpu);
Chen Fan02e51482013-12-23 17:04:02 +0800988
Justin Terry (VM)19306802018-01-22 13:07:49 -0800989 if (kvm_enabled() || whpx_enabled()) {
Jan Kiszkad362e752012-02-17 18:31:17 +0100990 env->tpr_access_type = access;
991
Andreas Färber93afead2013-08-26 03:41:01 +0200992 cpu_interrupt(cs, CPU_INTERRUPT_TPR);
Yang Zhong79c664f2017-07-03 18:12:22 +0800993 } else if (tcg_enabled()) {
Pavel Dovgalyukafd46fc2018-04-09 12:13:20 +0300994 cpu_restore_state(cs, cs->mem_io_pc, false);
Jan Kiszkad362e752012-02-17 18:31:17 +0100995
Chen Fan02e51482013-12-23 17:04:02 +0800996 apic_handle_tpr_access_report(cpu->apic_state, env->eip, access);
Jan Kiszkad362e752012-02-17 18:31:17 +0100997 }
998}
bellardeaa728e2008-05-28 12:51:20 +0000999#endif /* !CONFIG_USER_ONLY */
aliguori6fd805e2008-11-05 15:34:06 +00001000
Jan Kiszka84273172009-06-27 09:53:51 +02001001int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
1002 target_ulong *base, unsigned int *limit,
1003 unsigned int *flags)
1004{
Andreas Färberf17ec442013-06-29 19:40:58 +02001005 X86CPU *cpu = x86_env_get_cpu(env);
1006 CPUState *cs = CPU(cpu);
Jan Kiszka84273172009-06-27 09:53:51 +02001007 SegmentCache *dt;
1008 target_ulong ptr;
1009 uint32_t e1, e2;
1010 int index;
1011
1012 if (selector & 0x4)
1013 dt = &env->ldt;
1014 else
1015 dt = &env->gdt;
1016 index = selector & ~7;
1017 ptr = dt->base + index;
1018 if ((index + 7) > dt->limit
Andreas Färberf17ec442013-06-29 19:40:58 +02001019 || cpu_memory_rw_debug(cs, ptr, (uint8_t *)&e1, sizeof(e1), 0) != 0
1020 || cpu_memory_rw_debug(cs, ptr+4, (uint8_t *)&e2, sizeof(e2), 0) != 0)
Jan Kiszka84273172009-06-27 09:53:51 +02001021 return 0;
1022
1023 *base = ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
1024 *limit = (e1 & 0xffff) | (e2 & 0x000f0000);
1025 if (e2 & DESC_G_MASK)
1026 *limit = (*limit << 12) | 0xfff;
1027 *flags = e2;
1028
1029 return 1;
1030}
1031
Gleb Natapovb09ea7d2009-06-17 23:26:59 +03001032#if !defined(CONFIG_USER_ONLY)
Andreas Färber232fc232012-05-05 01:14:41 +02001033void do_cpu_init(X86CPU *cpu)
Gleb Natapovb09ea7d2009-06-17 23:26:59 +03001034{
Andreas Färber259186a2013-01-17 18:51:17 +01001035 CPUState *cs = CPU(cpu);
Andreas Färber232fc232012-05-05 01:14:41 +02001036 CPUX86State *env = &cpu->env;
Paolo Bonzini43175fa2013-03-12 13:16:28 +01001037 CPUX86State *save = g_new(CPUX86State, 1);
Andreas Färber259186a2013-01-17 18:51:17 +01001038 int sipi = cs->interrupt_request & CPU_INTERRUPT_SIPI;
Paolo Bonzini43175fa2013-03-12 13:16:28 +01001039
1040 *save = *env;
Jan Kiszkaebda3772011-03-15 12:26:21 +01001041
Andreas Färber259186a2013-01-17 18:51:17 +01001042 cpu_reset(cs);
1043 cs->interrupt_request = sipi;
Paolo Bonzini43175fa2013-03-12 13:16:28 +01001044 memcpy(&env->start_init_save, &save->start_init_save,
1045 offsetof(CPUX86State, end_init_save) -
1046 offsetof(CPUX86State, start_init_save));
1047 g_free(save);
1048
Paolo Bonzinie0723c42013-03-08 19:21:50 +01001049 if (kvm_enabled()) {
1050 kvm_arch_do_init_vcpu(cpu);
1051 }
Chen Fan02e51482013-12-23 17:04:02 +08001052 apic_init_reset(cpu->apic_state);
Gleb Natapovb09ea7d2009-06-17 23:26:59 +03001053}
1054
Andreas Färber232fc232012-05-05 01:14:41 +02001055void do_cpu_sipi(X86CPU *cpu)
Gleb Natapovb09ea7d2009-06-17 23:26:59 +03001056{
Chen Fan02e51482013-12-23 17:04:02 +08001057 apic_sipi(cpu->apic_state);
Gleb Natapovb09ea7d2009-06-17 23:26:59 +03001058}
1059#else
Andreas Färber232fc232012-05-05 01:14:41 +02001060void do_cpu_init(X86CPU *cpu)
Gleb Natapovb09ea7d2009-06-17 23:26:59 +03001061{
1062}
Andreas Färber232fc232012-05-05 01:14:41 +02001063void do_cpu_sipi(X86CPU *cpu)
Gleb Natapovb09ea7d2009-06-17 23:26:59 +03001064{
1065}
1066#endif
Richard Henderson374e0cd2014-09-13 09:45:14 -07001067
1068/* Frob eflags into and out of the CPU temporary format. */
1069
1070void x86_cpu_exec_enter(CPUState *cs)
1071{
1072 X86CPU *cpu = X86_CPU(cs);
1073 CPUX86State *env = &cpu->env;
1074
1075 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1076 env->df = 1 - (2 * ((env->eflags >> 10) & 1));
1077 CC_OP = CC_OP_EFLAGS;
1078 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1079}
1080
1081void x86_cpu_exec_exit(CPUState *cs)
1082{
1083 X86CPU *cpu = X86_CPU(cs);
1084 CPUX86State *env = &cpu->env;
1085
1086 env->eflags = cpu_compute_eflags(env);
1087}
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001088
1089#ifndef CONFIG_USER_ONLY
1090uint8_t x86_ldub_phys(CPUState *cs, hwaddr addr)
1091{
1092 X86CPU *cpu = X86_CPU(cs);
1093 CPUX86State *env = &cpu->env;
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001094 MemTxAttrs attrs = cpu_get_mem_attrs(env);
1095 AddressSpace *as = cpu_addressspace(cs, attrs);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001096
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001097 return address_space_ldub(as, addr, attrs, NULL);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001098}
1099
1100uint32_t x86_lduw_phys(CPUState *cs, hwaddr addr)
1101{
1102 X86CPU *cpu = X86_CPU(cs);
1103 CPUX86State *env = &cpu->env;
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001104 MemTxAttrs attrs = cpu_get_mem_attrs(env);
1105 AddressSpace *as = cpu_addressspace(cs, attrs);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001106
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001107 return address_space_lduw(as, addr, attrs, NULL);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001108}
1109
1110uint32_t x86_ldl_phys(CPUState *cs, hwaddr addr)
1111{
1112 X86CPU *cpu = X86_CPU(cs);
1113 CPUX86State *env = &cpu->env;
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001114 MemTxAttrs attrs = cpu_get_mem_attrs(env);
1115 AddressSpace *as = cpu_addressspace(cs, attrs);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001116
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001117 return address_space_ldl(as, addr, attrs, NULL);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001118}
1119
1120uint64_t x86_ldq_phys(CPUState *cs, hwaddr addr)
1121{
1122 X86CPU *cpu = X86_CPU(cs);
1123 CPUX86State *env = &cpu->env;
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001124 MemTxAttrs attrs = cpu_get_mem_attrs(env);
1125 AddressSpace *as = cpu_addressspace(cs, attrs);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001126
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001127 return address_space_ldq(as, addr, attrs, NULL);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001128}
1129
1130void x86_stb_phys(CPUState *cs, hwaddr addr, uint8_t val)
1131{
1132 X86CPU *cpu = X86_CPU(cs);
1133 CPUX86State *env = &cpu->env;
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001134 MemTxAttrs attrs = cpu_get_mem_attrs(env);
1135 AddressSpace *as = cpu_addressspace(cs, attrs);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001136
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001137 address_space_stb(as, addr, val, attrs, NULL);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001138}
1139
1140void x86_stl_phys_notdirty(CPUState *cs, hwaddr addr, uint32_t val)
1141{
1142 X86CPU *cpu = X86_CPU(cs);
1143 CPUX86State *env = &cpu->env;
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001144 MemTxAttrs attrs = cpu_get_mem_attrs(env);
1145 AddressSpace *as = cpu_addressspace(cs, attrs);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001146
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001147 address_space_stl_notdirty(as, addr, val, attrs, NULL);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001148}
1149
1150void x86_stw_phys(CPUState *cs, hwaddr addr, uint32_t val)
1151{
1152 X86CPU *cpu = X86_CPU(cs);
1153 CPUX86State *env = &cpu->env;
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001154 MemTxAttrs attrs = cpu_get_mem_attrs(env);
1155 AddressSpace *as = cpu_addressspace(cs, attrs);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001156
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001157 address_space_stw(as, addr, val, attrs, NULL);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001158}
1159
1160void x86_stl_phys(CPUState *cs, hwaddr addr, uint32_t val)
1161{
1162 X86CPU *cpu = X86_CPU(cs);
1163 CPUX86State *env = &cpu->env;
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001164 MemTxAttrs attrs = cpu_get_mem_attrs(env);
1165 AddressSpace *as = cpu_addressspace(cs, attrs);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001166
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001167 address_space_stl(as, addr, val, attrs, NULL);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001168}
1169
1170void x86_stq_phys(CPUState *cs, hwaddr addr, uint64_t val)
1171{
1172 X86CPU *cpu = X86_CPU(cs);
1173 CPUX86State *env = &cpu->env;
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001174 MemTxAttrs attrs = cpu_get_mem_attrs(env);
1175 AddressSpace *as = cpu_addressspace(cs, attrs);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001176
Paolo Bonzinif8c45c62017-03-01 10:34:48 +01001177 address_space_stq(as, addr, val, attrs, NULL);
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001178}
1179#endif