blob: 1c250b82452d9fd4c8a2c2e3019dbe9aeaebaf5b [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"
Paolo Bonzini83c90892012-12-17 18:19:49 +010027#include "monitor/monitor.h"
Pavel Butsykin1f871d42015-09-22 16:18:18 +030028#include "hw/i386/apic_internal.h"
Jan Kiszka2fa11da2011-03-02 08:56:08 +010029#endif
bellardf3f2d9b2003-11-13 23:15:36 +000030
Andreas Färber317ac622012-03-14 01:38:21 +010031static void cpu_x86_version(CPUX86State *env, int *family, int *model)
Jin Dongming2bd3e042010-12-10 17:21:14 +090032{
33 int cpuver = env->cpuid_version;
34
35 if (family == NULL || model == NULL) {
36 return;
37 }
38
39 *family = (cpuver >> 8) & 0x0f;
40 *model = ((cpuver >> 12) & 0xf0) + ((cpuver >> 4) & 0x0f);
41}
42
43/* Broadcast MCA signal for processor version 06H_EH and above */
Andreas Färber317ac622012-03-14 01:38:21 +010044int cpu_x86_support_mca_broadcast(CPUX86State *env)
Jin Dongming2bd3e042010-12-10 17:21:14 +090045{
46 int family = 0;
47 int model = 0;
48
49 cpu_x86_version(env, &family, &model);
50 if ((family == 6 && model >= 14) || family > 6) {
51 return 1;
52 }
53
54 return 0;
55}
56
bellardeaa728e2008-05-28 12:51:20 +000057/***********************************************************/
58/* x86 debug */
bellard5af45182008-05-12 16:47:36 +000059
Richard Hendersonbc4b43d2013-01-23 16:44:37 -080060static const char *cc_op_str[CC_OP_NB] = {
bellardeaa728e2008-05-28 12:51:20 +000061 "DYNAMIC",
62 "EFLAGS",
bellard5af45182008-05-12 16:47:36 +000063
bellardeaa728e2008-05-28 12:51:20 +000064 "MULB",
65 "MULW",
66 "MULL",
67 "MULQ",
bellard5af45182008-05-12 16:47:36 +000068
bellardeaa728e2008-05-28 12:51:20 +000069 "ADDB",
70 "ADDW",
71 "ADDL",
72 "ADDQ",
bellardb6abf972008-05-17 12:44:31 +000073
bellardeaa728e2008-05-28 12:51:20 +000074 "ADCB",
75 "ADCW",
76 "ADCL",
77 "ADCQ",
bellardb6abf972008-05-17 12:44:31 +000078
bellardeaa728e2008-05-28 12:51:20 +000079 "SUBB",
80 "SUBW",
81 "SUBL",
82 "SUBQ",
bellardb6abf972008-05-17 12:44:31 +000083
bellardeaa728e2008-05-28 12:51:20 +000084 "SBBB",
85 "SBBW",
86 "SBBL",
87 "SBBQ",
bellardb6abf972008-05-17 12:44:31 +000088
bellardeaa728e2008-05-28 12:51:20 +000089 "LOGICB",
90 "LOGICW",
91 "LOGICL",
92 "LOGICQ",
bellardb6abf972008-05-17 12:44:31 +000093
bellardeaa728e2008-05-28 12:51:20 +000094 "INCB",
95 "INCW",
96 "INCL",
97 "INCQ",
bellard07d2c592008-05-17 13:57:33 +000098
bellardeaa728e2008-05-28 12:51:20 +000099 "DECB",
100 "DECW",
101 "DECL",
102 "DECQ",
bellard6191b052008-05-17 18:44:58 +0000103
bellardeaa728e2008-05-28 12:51:20 +0000104 "SHLB",
105 "SHLW",
106 "SHLL",
107 "SHLQ",
bellard6191b052008-05-17 18:44:58 +0000108
bellardeaa728e2008-05-28 12:51:20 +0000109 "SARB",
110 "SARW",
111 "SARL",
112 "SARQ",
Richard Hendersonbc4b43d2013-01-23 16:44:37 -0800113
114 "BMILGB",
115 "BMILGW",
116 "BMILGL",
117 "BMILGQ",
Richard Hendersoncd7f97c2013-01-23 18:17:33 -0800118
119 "ADCX",
120 "ADOX",
121 "ADCOX",
Richard Henderson436ff2d2013-01-29 13:38:43 -0800122
123 "CLR",
bellard07d2c592008-05-17 13:57:33 +0000124};
125
aliguoria3867ed2009-04-18 15:36:11 +0000126static void
Andreas Färber317ac622012-03-14 01:38:21 +0100127cpu_x86_dump_seg_cache(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
aliguoria3867ed2009-04-18 15:36:11 +0000128 const char *name, struct SegmentCache *sc)
129{
130#ifdef TARGET_X86_64
131 if (env->hflags & HF_CS64_MASK) {
132 cpu_fprintf(f, "%-3s=%04x %016" PRIx64 " %08x %08x", name,
Jan Kiszka4058fd92010-12-27 15:52:24 +0100133 sc->selector, sc->base, sc->limit, sc->flags & 0x00ffff00);
aliguoria3867ed2009-04-18 15:36:11 +0000134 } else
135#endif
136 {
137 cpu_fprintf(f, "%-3s=%04x %08x %08x %08x", name, sc->selector,
Jan Kiszka4058fd92010-12-27 15:52:24 +0100138 (uint32_t)sc->base, sc->limit, sc->flags & 0x00ffff00);
aliguoria3867ed2009-04-18 15:36:11 +0000139 }
140
141 if (!(env->hflags & HF_PE_MASK) || !(sc->flags & DESC_P_MASK))
142 goto done;
143
144 cpu_fprintf(f, " DPL=%d ", (sc->flags & DESC_DPL_MASK) >> DESC_DPL_SHIFT);
145 if (sc->flags & DESC_S_MASK) {
146 if (sc->flags & DESC_CS_MASK) {
147 cpu_fprintf(f, (sc->flags & DESC_L_MASK) ? "CS64" :
148 ((sc->flags & DESC_B_MASK) ? "CS32" : "CS16"));
149 cpu_fprintf(f, " [%c%c", (sc->flags & DESC_C_MASK) ? 'C' : '-',
150 (sc->flags & DESC_R_MASK) ? 'R' : '-');
151 } else {
Tobias Markus469936a2013-08-25 12:20:06 +0200152 cpu_fprintf(f,
153 (sc->flags & DESC_B_MASK || env->hflags & HF_LMA_MASK)
154 ? "DS " : "DS16");
aliguoria3867ed2009-04-18 15:36:11 +0000155 cpu_fprintf(f, " [%c%c", (sc->flags & DESC_E_MASK) ? 'E' : '-',
156 (sc->flags & DESC_W_MASK) ? 'W' : '-');
157 }
158 cpu_fprintf(f, "%c]", (sc->flags & DESC_A_MASK) ? 'A' : '-');
159 } else {
160 static const char *sys_type_name[2][16] = {
161 { /* 32 bit mode */
162 "Reserved", "TSS16-avl", "LDT", "TSS16-busy",
163 "CallGate16", "TaskGate", "IntGate16", "TrapGate16",
164 "Reserved", "TSS32-avl", "Reserved", "TSS32-busy",
165 "CallGate32", "Reserved", "IntGate32", "TrapGate32"
166 },
167 { /* 64 bit mode */
168 "<hiword>", "Reserved", "LDT", "Reserved", "Reserved",
169 "Reserved", "Reserved", "Reserved", "Reserved",
170 "TSS64-avl", "Reserved", "TSS64-busy", "CallGate64",
171 "Reserved", "IntGate64", "TrapGate64"
172 }
173 };
Stefan Weile5c15ef2010-04-01 20:03:30 +0200174 cpu_fprintf(f, "%s",
175 sys_type_name[(env->hflags & HF_LMA_MASK) ? 1 : 0]
176 [(sc->flags & DESC_TYPE_MASK)
177 >> DESC_TYPE_SHIFT]);
aliguoria3867ed2009-04-18 15:36:11 +0000178 }
179done:
180 cpu_fprintf(f, "\n");
181}
182
Pavel Butsykin1f871d42015-09-22 16:18:18 +0300183#ifndef CONFIG_USER_ONLY
184
185/* ARRAY_SIZE check is not required because
186 * DeliveryMode(dm) has a size of 3 bit.
187 */
188static inline const char *dm2str(uint32_t dm)
189{
190 static const char *str[] = {
191 "Fixed",
192 "...",
193 "SMI",
194 "...",
195 "NMI",
196 "INIT",
197 "...",
198 "ExtINT"
199 };
200 return str[dm];
201}
202
203static void dump_apic_lvt(FILE *f, fprintf_function cpu_fprintf,
204 const char *name, uint32_t lvt, bool is_timer)
205{
206 uint32_t dm = (lvt & APIC_LVT_DELIV_MOD) >> APIC_LVT_DELIV_MOD_SHIFT;
207 cpu_fprintf(f,
208 "%s\t 0x%08x %s %-5s %-6s %-7s %-12s %-6s",
209 name, lvt,
210 lvt & APIC_LVT_INT_POLARITY ? "active-lo" : "active-hi",
211 lvt & APIC_LVT_LEVEL_TRIGGER ? "level" : "edge",
212 lvt & APIC_LVT_MASKED ? "masked" : "",
213 lvt & APIC_LVT_DELIV_STS ? "pending" : "",
214 !is_timer ?
215 "" : lvt & APIC_LVT_TIMER_PERIODIC ?
216 "periodic" : lvt & APIC_LVT_TIMER_TSCDEADLINE ?
217 "tsc-deadline" : "one-shot",
218 dm2str(dm));
219 if (dm != APIC_DM_NMI) {
220 cpu_fprintf(f, " (vec %u)\n", lvt & APIC_VECTOR_MASK);
221 } else {
222 cpu_fprintf(f, "\n");
223 }
224}
225
226/* ARRAY_SIZE check is not required because
227 * destination shorthand has a size of 2 bit.
228 */
229static inline const char *shorthand2str(uint32_t shorthand)
230{
231 const char *str[] = {
232 "no-shorthand", "self", "all-self", "all"
233 };
234 return str[shorthand];
235}
236
237static inline uint8_t divider_conf(uint32_t divide_conf)
238{
239 uint8_t divide_val = ((divide_conf & 0x8) >> 1) | (divide_conf & 0x3);
240
241 return divide_val == 7 ? 1 : 2 << divide_val;
242}
243
244static inline void mask2str(char *str, uint32_t val, uint8_t size)
245{
246 while (size--) {
247 *str++ = (val >> size) & 1 ? '1' : '0';
248 }
249 *str = 0;
250}
251
252#define MAX_LOGICAL_APIC_ID_MASK_SIZE 16
253
254static void dump_apic_icr(FILE *f, fprintf_function cpu_fprintf,
255 APICCommonState *s, CPUX86State *env)
256{
257 uint32_t icr = s->icr[0], icr2 = s->icr[1];
258 uint8_t dest_shorthand = \
259 (icr & APIC_ICR_DEST_SHORT) >> APIC_ICR_DEST_SHORT_SHIFT;
260 bool logical_mod = icr & APIC_ICR_DEST_MOD;
261 char apic_id_str[MAX_LOGICAL_APIC_ID_MASK_SIZE + 1];
262 uint32_t dest_field;
263 bool x2apic;
264
265 cpu_fprintf(f, "ICR\t 0x%08x %s %s %s %s\n",
266 icr,
267 logical_mod ? "logical" : "physical",
268 icr & APIC_ICR_TRIGGER_MOD ? "level" : "edge",
269 icr & APIC_ICR_LEVEL ? "assert" : "de-assert",
270 shorthand2str(dest_shorthand));
271
272 cpu_fprintf(f, "ICR2\t 0x%08x", icr2);
273 if (dest_shorthand != 0) {
274 cpu_fprintf(f, "\n");
275 return;
276 }
277 x2apic = env->features[FEAT_1_ECX] & CPUID_EXT_X2APIC;
278 dest_field = x2apic ? icr2 : icr2 >> APIC_ICR_DEST_SHIFT;
279
280 if (!logical_mod) {
281 if (x2apic) {
282 cpu_fprintf(f, " cpu %u (X2APIC ID)\n", dest_field);
283 } else {
284 cpu_fprintf(f, " cpu %u (APIC ID)\n",
285 dest_field & APIC_LOGDEST_XAPIC_ID);
286 }
287 return;
288 }
289
290 if (s->dest_mode == 0xf) { /* flat mode */
291 mask2str(apic_id_str, icr2 >> APIC_ICR_DEST_SHIFT, 8);
292 cpu_fprintf(f, " mask %s (APIC ID)\n", apic_id_str);
293 } else if (s->dest_mode == 0) { /* cluster mode */
294 if (x2apic) {
295 mask2str(apic_id_str, dest_field & APIC_LOGDEST_X2APIC_ID, 16);
296 cpu_fprintf(f, " cluster %u mask %s (X2APIC ID)\n",
297 dest_field >> APIC_LOGDEST_X2APIC_SHIFT, apic_id_str);
298 } else {
299 mask2str(apic_id_str, dest_field & APIC_LOGDEST_XAPIC_ID, 4);
300 cpu_fprintf(f, " cluster %u mask %s (APIC ID)\n",
301 dest_field >> APIC_LOGDEST_XAPIC_SHIFT, apic_id_str);
302 }
303 }
304}
305
306static void dump_apic_interrupt(FILE *f, fprintf_function cpu_fprintf,
307 const char *name, uint32_t *ireg_tab,
308 uint32_t *tmr_tab)
309{
310 int i, empty = true;
311
312 cpu_fprintf(f, "%s\t ", name);
313 for (i = 0; i < 256; i++) {
314 if (apic_get_bit(ireg_tab, i)) {
315 cpu_fprintf(f, "%u%s ", i,
316 apic_get_bit(tmr_tab, i) ? "(level)" : "");
317 empty = false;
318 }
319 }
320 cpu_fprintf(f, "%s\n", empty ? "(none)" : "");
321}
322
323void x86_cpu_dump_local_apic_state(CPUState *cs, FILE *f,
324 fprintf_function cpu_fprintf, int flags)
325{
326 X86CPU *cpu = X86_CPU(cs);
327 APICCommonState *s = APIC_COMMON(cpu->apic_state);
328 uint32_t *lvt = s->lvt;
329
330 cpu_fprintf(f, "dumping local APIC state for CPU %-2u\n\n",
331 CPU(cpu)->cpu_index);
332 dump_apic_lvt(f, cpu_fprintf, "LVT0", lvt[APIC_LVT_LINT0], false);
333 dump_apic_lvt(f, cpu_fprintf, "LVT1", lvt[APIC_LVT_LINT1], false);
334 dump_apic_lvt(f, cpu_fprintf, "LVTPC", lvt[APIC_LVT_PERFORM], false);
335 dump_apic_lvt(f, cpu_fprintf, "LVTERR", lvt[APIC_LVT_ERROR], false);
336 dump_apic_lvt(f, cpu_fprintf, "LVTTHMR", lvt[APIC_LVT_THERMAL], false);
337 dump_apic_lvt(f, cpu_fprintf, "LVTT", lvt[APIC_LVT_TIMER], true);
338
339 cpu_fprintf(f, "Timer\t DCR=0x%x (divide by %u) initial_count = %u\n",
340 s->divide_conf & APIC_DCR_MASK,
341 divider_conf(s->divide_conf),
342 s->initial_count);
343
344 cpu_fprintf(f, "SPIV\t 0x%08x APIC %s, focus=%s, spurious vec %u\n",
345 s->spurious_vec,
346 s->spurious_vec & APIC_SPURIO_ENABLED ? "enabled" : "disabled",
347 s->spurious_vec & APIC_SPURIO_FOCUS ? "on" : "off",
348 s->spurious_vec & APIC_VECTOR_MASK);
349
350 dump_apic_icr(f, cpu_fprintf, s, &cpu->env);
351
352 cpu_fprintf(f, "ESR\t 0x%08x\n", s->esr);
353
354 dump_apic_interrupt(f, cpu_fprintf, "ISR", s->isr, s->tmr);
355 dump_apic_interrupt(f, cpu_fprintf, "IRR", s->irr, s->tmr);
356
357 cpu_fprintf(f, "\nAPR 0x%02x TPR 0x%02x DFR 0x%02x LDR 0x%02x",
358 s->arb_id, s->tpr, s->dest_mode, s->log_dest);
359 if (s->dest_mode == 0) {
360 cpu_fprintf(f, "(cluster %u: id %u)",
361 s->log_dest >> APIC_LOGDEST_XAPIC_SHIFT,
362 s->log_dest & APIC_LOGDEST_XAPIC_ID);
363 }
364 cpu_fprintf(f, " PPR 0x%02x\n", apic_get_ppr(s));
365}
366#else
367void x86_cpu_dump_local_apic_state(CPUState *cs, FILE *f,
368 fprintf_function cpu_fprintf, int flags)
369{
370}
371#endif /* !CONFIG_USER_ONLY */
372
Jan Kiszkaf5c848e2011-01-21 21:48:08 +0100373#define DUMP_CODE_BYTES_TOTAL 50
374#define DUMP_CODE_BYTES_BACKWARD 20
375
Andreas Färber878096e2013-05-27 01:33:50 +0200376void x86_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
377 int flags)
bellardeaa728e2008-05-28 12:51:20 +0000378{
Andreas Färber878096e2013-05-27 01:33:50 +0200379 X86CPU *cpu = X86_CPU(cs);
380 CPUX86State *env = &cpu->env;
bellardeaa728e2008-05-28 12:51:20 +0000381 int eflags, i, nb;
382 char cc_op_name[32];
383 static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
384
Richard Henderson4980ef92013-03-19 12:11:56 -0700385 eflags = cpu_compute_eflags(env);
bellardeaa728e2008-05-28 12:51:20 +0000386#ifdef TARGET_X86_64
387 if (env->hflags & HF_CS64_MASK) {
388 cpu_fprintf(f,
389 "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
390 "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
391 "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
392 "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
393 "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
394 env->regs[R_EAX],
395 env->regs[R_EBX],
396 env->regs[R_ECX],
397 env->regs[R_EDX],
398 env->regs[R_ESI],
399 env->regs[R_EDI],
400 env->regs[R_EBP],
401 env->regs[R_ESP],
402 env->regs[8],
403 env->regs[9],
404 env->regs[10],
405 env->regs[11],
406 env->regs[12],
407 env->regs[13],
408 env->regs[14],
409 env->regs[15],
410 env->eip, eflags,
411 eflags & DF_MASK ? 'D' : '-',
412 eflags & CC_O ? 'O' : '-',
413 eflags & CC_S ? 'S' : '-',
414 eflags & CC_Z ? 'Z' : '-',
415 eflags & CC_A ? 'A' : '-',
416 eflags & CC_P ? 'P' : '-',
417 eflags & CC_C ? 'C' : '-',
418 env->hflags & HF_CPL_MASK,
419 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
Juan Quintela5ee0ffa2009-09-29 22:48:49 +0200420 (env->a20_mask >> 20) & 1,
bellardeaa728e2008-05-28 12:51:20 +0000421 (env->hflags >> HF_SMM_SHIFT) & 1,
Andreas Färber259186a2013-01-17 18:51:17 +0100422 cs->halted);
bellardeaa728e2008-05-28 12:51:20 +0000423 } else
424#endif
425 {
426 cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
427 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
428 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
429 (uint32_t)env->regs[R_EAX],
430 (uint32_t)env->regs[R_EBX],
431 (uint32_t)env->regs[R_ECX],
432 (uint32_t)env->regs[R_EDX],
433 (uint32_t)env->regs[R_ESI],
434 (uint32_t)env->regs[R_EDI],
435 (uint32_t)env->regs[R_EBP],
436 (uint32_t)env->regs[R_ESP],
437 (uint32_t)env->eip, eflags,
438 eflags & DF_MASK ? 'D' : '-',
439 eflags & CC_O ? 'O' : '-',
440 eflags & CC_S ? 'S' : '-',
441 eflags & CC_Z ? 'Z' : '-',
442 eflags & CC_A ? 'A' : '-',
443 eflags & CC_P ? 'P' : '-',
444 eflags & CC_C ? 'C' : '-',
445 env->hflags & HF_CPL_MASK,
446 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
Juan Quintela5ee0ffa2009-09-29 22:48:49 +0200447 (env->a20_mask >> 20) & 1,
bellardeaa728e2008-05-28 12:51:20 +0000448 (env->hflags >> HF_SMM_SHIFT) & 1,
Andreas Färber259186a2013-01-17 18:51:17 +0100449 cs->halted);
bellardeaa728e2008-05-28 12:51:20 +0000450 }
451
aliguoria3867ed2009-04-18 15:36:11 +0000452 for(i = 0; i < 6; i++) {
453 cpu_x86_dump_seg_cache(env, f, cpu_fprintf, seg_name[i],
454 &env->segs[i]);
455 }
456 cpu_x86_dump_seg_cache(env, f, cpu_fprintf, "LDT", &env->ldt);
457 cpu_x86_dump_seg_cache(env, f, cpu_fprintf, "TR", &env->tr);
458
bellardeaa728e2008-05-28 12:51:20 +0000459#ifdef TARGET_X86_64
460 if (env->hflags & HF_LMA_MASK) {
bellardeaa728e2008-05-28 12:51:20 +0000461 cpu_fprintf(f, "GDT= %016" PRIx64 " %08x\n",
462 env->gdt.base, env->gdt.limit);
463 cpu_fprintf(f, "IDT= %016" PRIx64 " %08x\n",
464 env->idt.base, env->idt.limit);
465 cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
466 (uint32_t)env->cr[0],
467 env->cr[2],
468 env->cr[3],
469 (uint32_t)env->cr[4]);
aliguoria59cb4e2008-11-18 21:09:47 +0000470 for(i = 0; i < 4; i++)
471 cpu_fprintf(f, "DR%d=%016" PRIx64 " ", i, env->dr[i]);
472 cpu_fprintf(f, "\nDR6=%016" PRIx64 " DR7=%016" PRIx64 "\n",
aliguorid4b55be2008-12-02 19:40:26 +0000473 env->dr[6], env->dr[7]);
bellardeaa728e2008-05-28 12:51:20 +0000474 } else
475#endif
476 {
bellardeaa728e2008-05-28 12:51:20 +0000477 cpu_fprintf(f, "GDT= %08x %08x\n",
478 (uint32_t)env->gdt.base, env->gdt.limit);
479 cpu_fprintf(f, "IDT= %08x %08x\n",
480 (uint32_t)env->idt.base, env->idt.limit);
481 cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
482 (uint32_t)env->cr[0],
483 (uint32_t)env->cr[2],
484 (uint32_t)env->cr[3],
485 (uint32_t)env->cr[4]);
Stefan Weil9a78eea2010-10-22 23:03:33 +0200486 for(i = 0; i < 4; i++) {
487 cpu_fprintf(f, "DR%d=" TARGET_FMT_lx " ", i, env->dr[i]);
488 }
489 cpu_fprintf(f, "\nDR6=" TARGET_FMT_lx " DR7=" TARGET_FMT_lx "\n",
490 env->dr[6], env->dr[7]);
bellardeaa728e2008-05-28 12:51:20 +0000491 }
Peter Maydell6fd2a022012-10-05 15:04:43 +0100492 if (flags & CPU_DUMP_CCOP) {
bellardeaa728e2008-05-28 12:51:20 +0000493 if ((unsigned)env->cc_op < CC_OP_NB)
494 snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
495 else
496 snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
497#ifdef TARGET_X86_64
498 if (env->hflags & HF_CS64_MASK) {
499 cpu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
500 env->cc_src, env->cc_dst,
501 cc_op_name);
502 } else
503#endif
504 {
505 cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
506 (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
507 cc_op_name);
508 }
509 }
Marcelo Tosattib5e5a932010-03-23 13:37:10 -0300510 cpu_fprintf(f, "EFER=%016" PRIx64 "\n", env->efer);
Peter Maydell6fd2a022012-10-05 15:04:43 +0100511 if (flags & CPU_DUMP_FPU) {
bellardeaa728e2008-05-28 12:51:20 +0000512 int fptag;
513 fptag = 0;
514 for(i = 0; i < 8; i++) {
515 fptag |= ((!env->fptags[i]) << i);
516 }
517 cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
518 env->fpuc,
519 (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
520 env->fpstt,
521 fptag,
522 env->mxcsr);
523 for(i=0;i<8;i++) {
Aurelien Jarno1ffd41e2011-04-14 00:49:29 +0200524 CPU_LDoubleU u;
525 u.d = env->fpregs[i].d;
bellardeaa728e2008-05-28 12:51:20 +0000526 cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
Aurelien Jarno1ffd41e2011-04-14 00:49:29 +0200527 i, u.l.lower, u.l.upper);
bellardeaa728e2008-05-28 12:51:20 +0000528 if ((i & 1) == 1)
529 cpu_fprintf(f, "\n");
530 else
531 cpu_fprintf(f, " ");
532 }
533 if (env->hflags & HF_CS64_MASK)
534 nb = 16;
535 else
536 nb = 8;
537 for(i=0;i<nb;i++) {
538 cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
539 i,
Eduardo Habkost19cbd872015-11-26 17:14:32 -0200540 env->xmm_regs[i].ZMM_L(3),
541 env->xmm_regs[i].ZMM_L(2),
542 env->xmm_regs[i].ZMM_L(1),
543 env->xmm_regs[i].ZMM_L(0));
bellardeaa728e2008-05-28 12:51:20 +0000544 if ((i & 1) == 1)
545 cpu_fprintf(f, "\n");
546 else
547 cpu_fprintf(f, " ");
548 }
549 }
Jan Kiszkaf5c848e2011-01-21 21:48:08 +0100550 if (flags & CPU_DUMP_CODE) {
551 target_ulong base = env->segs[R_CS].base + env->eip;
552 target_ulong offs = MIN(env->eip, DUMP_CODE_BYTES_BACKWARD);
553 uint8_t code;
554 char codestr[3];
555
556 cpu_fprintf(f, "Code=");
557 for (i = 0; i < DUMP_CODE_BYTES_TOTAL; i++) {
Andreas Färberf17ec442013-06-29 19:40:58 +0200558 if (cpu_memory_rw_debug(cs, base - offs + i, &code, 1, 0) == 0) {
Jan Kiszkaf5c848e2011-01-21 21:48:08 +0100559 snprintf(codestr, sizeof(codestr), "%02x", code);
560 } else {
561 snprintf(codestr, sizeof(codestr), "??");
562 }
563 cpu_fprintf(f, "%s%s%s%s", i > 0 ? " " : "",
564 i == offs ? "<" : "", codestr, i == offs ? ">" : "");
565 }
566 cpu_fprintf(f, "\n");
567 }
bellardeaa728e2008-05-28 12:51:20 +0000568}
569
570/***********************************************************/
571/* x86 mmu */
572/* XXX: add PGE support */
573
Andreas Färbercc36a7a2013-01-18 15:19:06 +0100574void x86_cpu_set_a20(X86CPU *cpu, int a20_state)
bellardeaa728e2008-05-28 12:51:20 +0000575{
Andreas Färbercc36a7a2013-01-18 15:19:06 +0100576 CPUX86State *env = &cpu->env;
577
bellardeaa728e2008-05-28 12:51:20 +0000578 a20_state = (a20_state != 0);
579 if (a20_state != ((env->a20_mask >> 20) & 1)) {
Andreas Färber00c8cb02013-09-04 02:19:44 +0200580 CPUState *cs = CPU(cpu);
581
Antony Pavlov339aaf52014-12-13 19:48:18 +0300582 qemu_log_mask(CPU_LOG_MMU, "A20 update: a20=%d\n", a20_state);
bellardeaa728e2008-05-28 12:51:20 +0000583 /* if the cpu is currently executing code, we must unlink it and
584 all the potentially executing TB */
Andreas Färber00c8cb02013-09-04 02:19:44 +0200585 cpu_interrupt(cs, CPU_INTERRUPT_EXITTB);
bellardeaa728e2008-05-28 12:51:20 +0000586
587 /* when a20 is changed, all the MMU mappings are invalid, so
588 we must flush everything */
Andreas Färber00c8cb02013-09-04 02:19:44 +0200589 tlb_flush(cs, 1);
Juan Quintela5ee0ffa2009-09-29 22:48:49 +0200590 env->a20_mask = ~(1 << 20) | (a20_state << 20);
bellardeaa728e2008-05-28 12:51:20 +0000591 }
592}
593
594void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
595{
Andreas Färber00c8cb02013-09-04 02:19:44 +0200596 X86CPU *cpu = x86_env_get_cpu(env);
bellardeaa728e2008-05-28 12:51:20 +0000597 int pe_state;
598
Antony Pavlov339aaf52014-12-13 19:48:18 +0300599 qemu_log_mask(CPU_LOG_MMU, "CR0 update: CR0=0x%08x\n", new_cr0);
bellardeaa728e2008-05-28 12:51:20 +0000600 if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
601 (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
Andreas Färber00c8cb02013-09-04 02:19:44 +0200602 tlb_flush(CPU(cpu), 1);
bellardeaa728e2008-05-28 12:51:20 +0000603 }
604
605#ifdef TARGET_X86_64
606 if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
607 (env->efer & MSR_EFER_LME)) {
608 /* enter in long mode */
609 /* XXX: generate an exception */
610 if (!(env->cr[4] & CR4_PAE_MASK))
611 return;
612 env->efer |= MSR_EFER_LMA;
613 env->hflags |= HF_LMA_MASK;
614 } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
615 (env->efer & MSR_EFER_LMA)) {
616 /* exit long mode */
617 env->efer &= ~MSR_EFER_LMA;
618 env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
619 env->eip &= 0xffffffff;
620 }
621#endif
622 env->cr[0] = new_cr0 | CR0_ET_MASK;
623
624 /* update PE flag in hidden flags */
625 pe_state = (env->cr[0] & CR0_PE_MASK);
626 env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
627 /* ensure that ADDSEG is always set in real mode */
628 env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
629 /* update FPU flags */
630 env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
631 ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
632}
633
634/* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
635 the PDPT */
636void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
637{
Andreas Färber00c8cb02013-09-04 02:19:44 +0200638 X86CPU *cpu = x86_env_get_cpu(env);
639
bellardeaa728e2008-05-28 12:51:20 +0000640 env->cr[3] = new_cr3;
641 if (env->cr[0] & CR0_PG_MASK) {
Antony Pavlov339aaf52014-12-13 19:48:18 +0300642 qemu_log_mask(CPU_LOG_MMU,
643 "CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
Andreas Färber00c8cb02013-09-04 02:19:44 +0200644 tlb_flush(CPU(cpu), 0);
bellardeaa728e2008-05-28 12:51:20 +0000645 }
646}
647
648void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
649{
Andreas Färber00c8cb02013-09-04 02:19:44 +0200650 X86CPU *cpu = x86_env_get_cpu(env);
Richard Henderson19dc85d2015-07-02 14:53:40 +0100651 uint32_t hflags;
Andreas Färber00c8cb02013-09-04 02:19:44 +0200652
bellardeaa728e2008-05-28 12:51:20 +0000653#if defined(DEBUG_MMU)
654 printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
655#endif
H. Peter Anvina9321a42012-09-26 13:18:43 -0700656 if ((new_cr4 ^ env->cr[4]) &
657 (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK |
658 CR4_SMEP_MASK | CR4_SMAP_MASK)) {
Andreas Färber00c8cb02013-09-04 02:19:44 +0200659 tlb_flush(CPU(cpu), 1);
bellardeaa728e2008-05-28 12:51:20 +0000660 }
Richard Henderson19dc85d2015-07-02 14:53:40 +0100661
662 /* Clear bits we're going to recompute. */
663 hflags = env->hflags & ~(HF_OSFXSR_MASK | HF_SMAP_MASK);
664
bellardeaa728e2008-05-28 12:51:20 +0000665 /* SSE handling */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300666 if (!(env->features[FEAT_1_EDX] & CPUID_SSE)) {
bellardeaa728e2008-05-28 12:51:20 +0000667 new_cr4 &= ~CR4_OSFXSR_MASK;
H. Peter Anvina9321a42012-09-26 13:18:43 -0700668 }
H. Peter Anvina9321a42012-09-26 13:18:43 -0700669 if (new_cr4 & CR4_OSFXSR_MASK) {
Richard Henderson19dc85d2015-07-02 14:53:40 +0100670 hflags |= HF_OSFXSR_MASK;
H. Peter Anvina9321a42012-09-26 13:18:43 -0700671 }
672
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300673 if (!(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_SMAP)) {
H. Peter Anvina9321a42012-09-26 13:18:43 -0700674 new_cr4 &= ~CR4_SMAP_MASK;
675 }
H. Peter Anvina9321a42012-09-26 13:18:43 -0700676 if (new_cr4 & CR4_SMAP_MASK) {
Richard Henderson19dc85d2015-07-02 14:53:40 +0100677 hflags |= HF_SMAP_MASK;
H. Peter Anvina9321a42012-09-26 13:18:43 -0700678 }
bellardeaa728e2008-05-28 12:51:20 +0000679
Paolo Bonzini0f70ed42016-02-09 14:14:28 +0100680 if (!(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_PKU)) {
681 new_cr4 &= ~CR4_PKE_MASK;
682 }
683
bellardeaa728e2008-05-28 12:51:20 +0000684 env->cr[4] = new_cr4;
Richard Henderson19dc85d2015-07-02 14:53:40 +0100685 env->hflags = hflags;
Richard Hendersonf4f11102015-07-02 15:57:14 +0100686
687 cpu_sync_bndcs_hflags(env);
bellardeaa728e2008-05-28 12:51:20 +0000688}
689
bellardeaa728e2008-05-28 12:51:20 +0000690#if defined(CONFIG_USER_ONLY)
691
Andreas Färber75104542013-08-26 03:01:33 +0200692int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
Blue Swirl97b348e2011-08-01 16:12:17 +0000693 int is_write, int mmu_idx)
bellardeaa728e2008-05-28 12:51:20 +0000694{
Andreas Färber75104542013-08-26 03:01:33 +0200695 X86CPU *cpu = X86_CPU(cs);
696 CPUX86State *env = &cpu->env;
697
bellardeaa728e2008-05-28 12:51:20 +0000698 /* user mode only emulation */
699 is_write &= 1;
700 env->cr[2] = addr;
701 env->error_code = (is_write << PG_ERROR_W_BIT);
702 env->error_code |= PG_ERROR_U_MASK;
Andreas Färber27103422013-08-26 08:31:06 +0200703 cs->exception_index = EXCP0E_PAGE;
Peter Maydell0c336822016-05-17 15:18:07 +0100704 env->exception_is_int = 0;
705 env->exception_next_eip = -1;
bellardeaa728e2008-05-28 12:51:20 +0000706 return 1;
707}
708
bellardeaa728e2008-05-28 12:51:20 +0000709#else
710
bellardeaa728e2008-05-28 12:51:20 +0000711/* return value:
Andreas Färber75104542013-08-26 03:01:33 +0200712 * -1 = cannot handle fault
713 * 0 = nothing more to do
714 * 1 = generate PF fault
715 */
716int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
Blue Swirl97b348e2011-08-01 16:12:17 +0000717 int is_write1, int mmu_idx)
bellardeaa728e2008-05-28 12:51:20 +0000718{
Andreas Färber75104542013-08-26 03:01:33 +0200719 X86CPU *cpu = X86_CPU(cs);
720 CPUX86State *env = &cpu->env;
bellardeaa728e2008-05-28 12:51:20 +0000721 uint64_t ptep, pte;
722 target_ulong pde_addr, pte_addr;
Paolo Bonzinic1eb2fa2014-05-27 12:16:08 +0200723 int error_code = 0;
724 int is_dirty, prot, page_size, is_write, is_user;
Avi Kivitya8170e52012-10-23 12:30:10 +0200725 hwaddr paddr;
Paolo Bonzinie8f6d002014-05-27 12:58:36 +0200726 uint64_t rsvd_mask = PG_HI_RSVD_MASK;
bellardeaa728e2008-05-28 12:51:20 +0000727 uint32_t page_offset;
Paolo Bonzinie7e898a2014-05-27 14:44:49 +0200728 target_ulong vaddr;
bellardeaa728e2008-05-28 12:51:20 +0000729
730 is_user = mmu_idx == MMU_USER_IDX;
731#if defined(DEBUG_MMU)
Andreas Färber75104542013-08-26 03:01:33 +0200732 printf("MMU fault: addr=%" VADDR_PRIx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
bellardeaa728e2008-05-28 12:51:20 +0000733 addr, is_write1, is_user, env->eip);
734#endif
735 is_write = is_write1 & 1;
736
737 if (!(env->cr[0] & CR0_PG_MASK)) {
738 pte = addr;
Alexander Graf33dfdb52013-12-06 13:52:24 +0100739#ifdef TARGET_X86_64
740 if (!(env->hflags & HF_LMA_MASK)) {
741 /* Without long mode we can only address 32bits in real mode */
742 pte = (uint32_t)pte;
743 }
744#endif
bellardeaa728e2008-05-28 12:51:20 +0000745 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
746 page_size = 4096;
747 goto do_mapping;
748 }
749
Paolo Bonzinie2a32eb2014-05-27 13:58:46 +0200750 if (!(env->efer & MSR_EFER_NXE)) {
751 rsvd_mask |= PG_NX_MASK;
752 }
753
bellardeaa728e2008-05-28 12:51:20 +0000754 if (env->cr[4] & CR4_PAE_MASK) {
755 uint64_t pde, pdpe;
756 target_ulong pdpe_addr;
757
758#ifdef TARGET_X86_64
759 if (env->hflags & HF_LMA_MASK) {
760 uint64_t pml4e_addr, pml4e;
761 int32_t sext;
762
763 /* test virtual address sign extension */
764 sext = (int64_t)addr >> 47;
765 if (sext != 0 && sext != -1) {
766 env->error_code = 0;
Andreas Färber27103422013-08-26 08:31:06 +0200767 cs->exception_index = EXCP0D_GPF;
bellardeaa728e2008-05-28 12:51:20 +0000768 return 1;
769 }
770
771 pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
772 env->a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200773 pml4e = x86_ldq_phys(cs, pml4e_addr);
bellardeaa728e2008-05-28 12:51:20 +0000774 if (!(pml4e & PG_PRESENT_MASK)) {
bellardeaa728e2008-05-28 12:51:20 +0000775 goto do_fault;
776 }
Paolo Bonzinie8f6d002014-05-27 12:58:36 +0200777 if (pml4e & (rsvd_mask | PG_PSE_MASK)) {
Paolo Bonzinib7284642014-05-27 12:39:23 +0200778 goto do_fault_rsvd;
779 }
bellardeaa728e2008-05-28 12:51:20 +0000780 if (!(pml4e & PG_ACCESSED_MASK)) {
781 pml4e |= PG_ACCESSED_MASK;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200782 x86_stl_phys_notdirty(cs, pml4e_addr, pml4e);
bellardeaa728e2008-05-28 12:51:20 +0000783 }
784 ptep = pml4e ^ PG_NX_MASK;
Paolo Bonzinie8f6d002014-05-27 12:58:36 +0200785 pdpe_addr = ((pml4e & PG_ADDRESS_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
bellardeaa728e2008-05-28 12:51:20 +0000786 env->a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200787 pdpe = x86_ldq_phys(cs, pdpe_addr);
bellardeaa728e2008-05-28 12:51:20 +0000788 if (!(pdpe & PG_PRESENT_MASK)) {
bellardeaa728e2008-05-28 12:51:20 +0000789 goto do_fault;
790 }
Paolo Bonzinie8f6d002014-05-27 12:58:36 +0200791 if (pdpe & rsvd_mask) {
792 goto do_fault_rsvd;
793 }
bellardeaa728e2008-05-28 12:51:20 +0000794 ptep &= pdpe ^ PG_NX_MASK;
795 if (!(pdpe & PG_ACCESSED_MASK)) {
796 pdpe |= PG_ACCESSED_MASK;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200797 x86_stl_phys_notdirty(cs, pdpe_addr, pdpe);
bellardeaa728e2008-05-28 12:51:20 +0000798 }
Paolo Bonzini77549a72014-04-04 08:12:28 +0200799 if (pdpe & PG_PSE_MASK) {
800 /* 1 GB page */
801 page_size = 1024 * 1024 * 1024;
802 pte_addr = pdpe_addr;
803 pte = pdpe;
804 goto do_check_protect;
805 }
bellardeaa728e2008-05-28 12:51:20 +0000806 } else
807#endif
808 {
809 /* XXX: load them when cr3 is loaded ? */
810 pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
811 env->a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200812 pdpe = x86_ldq_phys(cs, pdpe_addr);
bellardeaa728e2008-05-28 12:51:20 +0000813 if (!(pdpe & PG_PRESENT_MASK)) {
bellardeaa728e2008-05-28 12:51:20 +0000814 goto do_fault;
815 }
William Grant1844e682014-08-24 15:13:48 +1000816 rsvd_mask |= PG_HI_USER_MASK;
817 if (pdpe & (rsvd_mask | PG_NX_MASK)) {
Paolo Bonzinie8f6d002014-05-27 12:58:36 +0200818 goto do_fault_rsvd;
819 }
bellardeaa728e2008-05-28 12:51:20 +0000820 ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
821 }
822
Paolo Bonzinie8f6d002014-05-27 12:58:36 +0200823 pde_addr = ((pdpe & PG_ADDRESS_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
bellardeaa728e2008-05-28 12:51:20 +0000824 env->a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200825 pde = x86_ldq_phys(cs, pde_addr);
bellardeaa728e2008-05-28 12:51:20 +0000826 if (!(pde & PG_PRESENT_MASK)) {
bellardeaa728e2008-05-28 12:51:20 +0000827 goto do_fault;
828 }
Paolo Bonzinie8f6d002014-05-27 12:58:36 +0200829 if (pde & rsvd_mask) {
830 goto do_fault_rsvd;
831 }
bellardeaa728e2008-05-28 12:51:20 +0000832 ptep &= pde ^ PG_NX_MASK;
833 if (pde & PG_PSE_MASK) {
834 /* 2 MB page */
835 page_size = 2048 * 1024;
Paolo Bonzini00cc3e12014-04-04 07:51:29 +0200836 pte_addr = pde_addr;
837 pte = pde;
Paolo Bonzinib052e452014-04-04 08:11:48 +0200838 goto do_check_protect;
bellardeaa728e2008-05-28 12:51:20 +0000839 }
Paolo Bonzinib052e452014-04-04 08:11:48 +0200840 /* 4 KB page */
841 if (!(pde & PG_ACCESSED_MASK)) {
842 pde |= PG_ACCESSED_MASK;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200843 x86_stl_phys_notdirty(cs, pde_addr, pde);
Paolo Bonzinib052e452014-04-04 08:11:48 +0200844 }
Paolo Bonzinie8f6d002014-05-27 12:58:36 +0200845 pte_addr = ((pde & PG_ADDRESS_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
Paolo Bonzinib052e452014-04-04 08:11:48 +0200846 env->a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200847 pte = x86_ldq_phys(cs, pte_addr);
Paolo Bonzinib052e452014-04-04 08:11:48 +0200848 if (!(pte & PG_PRESENT_MASK)) {
Paolo Bonzinib052e452014-04-04 08:11:48 +0200849 goto do_fault;
850 }
Paolo Bonzinie8f6d002014-05-27 12:58:36 +0200851 if (pte & rsvd_mask) {
852 goto do_fault_rsvd;
853 }
Paolo Bonzinib052e452014-04-04 08:11:48 +0200854 /* combine pde and pte nx, user and rw protections */
855 ptep &= pte ^ PG_NX_MASK;
856 page_size = 4096;
bellardeaa728e2008-05-28 12:51:20 +0000857 } else {
858 uint32_t pde;
859
860 /* page directory entry */
861 pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
862 env->a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200863 pde = x86_ldl_phys(cs, pde_addr);
bellardeaa728e2008-05-28 12:51:20 +0000864 if (!(pde & PG_PRESENT_MASK)) {
bellardeaa728e2008-05-28 12:51:20 +0000865 goto do_fault;
866 }
Paolo Bonzini870a7062014-04-04 08:04:18 +0200867 ptep = pde | PG_NX_MASK;
868
bellardeaa728e2008-05-28 12:51:20 +0000869 /* if PSE bit is set, then we use a 4MB page */
870 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
871 page_size = 4096 * 1024;
Paolo Bonzini487cad82014-04-04 07:57:02 +0200872 pte_addr = pde_addr;
Paolo Bonzinide431a62014-05-27 12:31:28 +0200873
874 /* Bits 20-13 provide bits 39-32 of the address, bit 21 is reserved.
875 * Leave bits 20-13 in place for setting accessed/dirty bits below.
876 */
Paolo Bonzini388ee482016-02-09 11:44:35 +0100877 pte = pde | ((pde & 0x1fe000LL) << (32 - 13));
Paolo Bonzinide431a62014-05-27 12:31:28 +0200878 rsvd_mask = 0x200000;
879 goto do_check_protect_pse36;
bellardeaa728e2008-05-28 12:51:20 +0000880 }
Paolo Bonzinib052e452014-04-04 08:11:48 +0200881
882 if (!(pde & PG_ACCESSED_MASK)) {
883 pde |= PG_ACCESSED_MASK;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200884 x86_stl_phys_notdirty(cs, pde_addr, pde);
Paolo Bonzinib052e452014-04-04 08:11:48 +0200885 }
886
887 /* page directory entry */
888 pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
889 env->a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200890 pte = x86_ldl_phys(cs, pte_addr);
Paolo Bonzinib052e452014-04-04 08:11:48 +0200891 if (!(pte & PG_PRESENT_MASK)) {
Paolo Bonzinib052e452014-04-04 08:11:48 +0200892 goto do_fault;
893 }
894 /* combine pde and pte user and rw protections */
895 ptep &= pte | PG_NX_MASK;
896 page_size = 4096;
Paolo Bonzinie8f6d002014-05-27 12:58:36 +0200897 rsvd_mask = 0;
bellardeaa728e2008-05-28 12:51:20 +0000898 }
Paolo Bonzini7c822562014-04-04 08:00:40 +0200899
Paolo Bonzinib052e452014-04-04 08:11:48 +0200900do_check_protect:
Paolo Bonzinieaad03e2014-05-27 13:03:17 +0200901 rsvd_mask |= (page_size - 1) & PG_ADDRESS_MASK & ~PG_PSE_PAT_MASK;
Paolo Bonzinide431a62014-05-27 12:31:28 +0200902do_check_protect_pse36:
Paolo Bonzinie8f6d002014-05-27 12:58:36 +0200903 if (pte & rsvd_mask) {
904 goto do_fault_rsvd;
905 }
Paolo Bonzini870a7062014-04-04 08:04:18 +0200906 ptep ^= PG_NX_MASK;
Paolo Bonzini76c64d32015-11-17 17:09:33 +0100907
908 /* can the page can be put in the TLB? prot will tell us */
909 if (is_user && !(ptep & PG_USER_MASK)) {
Paolo Bonzini7c822562014-04-04 08:00:40 +0200910 goto do_fault_protect;
911 }
Paolo Bonzini7c822562014-04-04 08:00:40 +0200912
Paolo Bonzini76c64d32015-11-17 17:09:33 +0100913 prot = 0;
914 if (mmu_idx != MMU_KSMAP_IDX || !(ptep & PG_USER_MASK)) {
915 prot |= PAGE_READ;
916 if ((ptep & PG_RW_MASK) || (!is_user && !(env->cr[0] & CR0_WP_MASK))) {
917 prot |= PAGE_WRITE;
Paolo Bonzini7c822562014-04-04 08:00:40 +0200918 }
Paolo Bonzini7c822562014-04-04 08:00:40 +0200919 }
Paolo Bonzini76c64d32015-11-17 17:09:33 +0100920 if (!(ptep & PG_NX_MASK) &&
921 (mmu_idx == MMU_USER_IDX ||
922 !((env->cr[4] & CR4_SMEP_MASK) && (ptep & PG_USER_MASK)))) {
923 prot |= PAGE_EXEC;
924 }
Paolo Bonzini0f70ed42016-02-09 14:14:28 +0100925 if ((env->cr[4] & CR4_PKE_MASK) && (env->hflags & HF_LMA_MASK) &&
926 (ptep & PG_USER_MASK) && env->pkru) {
927 uint32_t pk = (pte & PG_PKRU_MASK) >> PG_PKRU_BIT;
928 uint32_t pkru_ad = (env->pkru >> pk * 2) & 1;
929 uint32_t pkru_wd = (env->pkru >> pk * 2) & 2;
Paolo Bonzini44d066a2016-04-06 09:45:42 +0200930 uint32_t pkru_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
Paolo Bonzini0f70ed42016-02-09 14:14:28 +0100931
932 if (pkru_ad) {
Paolo Bonzini44d066a2016-04-06 09:45:42 +0200933 pkru_prot &= ~(PAGE_READ | PAGE_WRITE);
Paolo Bonzini0f70ed42016-02-09 14:14:28 +0100934 } else if (pkru_wd && (is_user || env->cr[0] & CR0_WP_MASK)) {
Paolo Bonzini44d066a2016-04-06 09:45:42 +0200935 pkru_prot &= ~PAGE_WRITE;
Paolo Bonzini0f70ed42016-02-09 14:14:28 +0100936 }
Paolo Bonzini44d066a2016-04-06 09:45:42 +0200937
938 prot &= pkru_prot;
939 if ((pkru_prot & (1 << is_write1)) == 0) {
Paolo Bonzini0f70ed42016-02-09 14:14:28 +0100940 assert(is_write1 != 2);
941 error_code |= PG_ERROR_PK_MASK;
942 goto do_fault_protect;
943 }
944 }
945
Paolo Bonzini44d066a2016-04-06 09:45:42 +0200946 if ((prot & (1 << is_write1)) == 0) {
947 goto do_fault_protect;
948 }
949
Paolo Bonzini76c64d32015-11-17 17:09:33 +0100950 /* yes, it can! */
Paolo Bonzini7c822562014-04-04 08:00:40 +0200951 is_dirty = is_write && !(pte & PG_DIRTY_MASK);
952 if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
953 pte |= PG_ACCESSED_MASK;
954 if (is_dirty) {
955 pte |= PG_DIRTY_MASK;
956 }
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200957 x86_stl_phys_notdirty(cs, pte_addr, pte);
Paolo Bonzini7c822562014-04-04 08:00:40 +0200958 }
Paolo Bonzini7c822562014-04-04 08:00:40 +0200959
Paolo Bonzini76c64d32015-11-17 17:09:33 +0100960 if (!(pte & PG_DIRTY_MASK)) {
bellardeaa728e2008-05-28 12:51:20 +0000961 /* only set write access if already dirty... otherwise wait
962 for dirty access */
Paolo Bonzini76c64d32015-11-17 17:09:33 +0100963 assert(!is_write);
964 prot &= ~PAGE_WRITE;
bellardeaa728e2008-05-28 12:51:20 +0000965 }
Paolo Bonzini76c64d32015-11-17 17:09:33 +0100966
bellardeaa728e2008-05-28 12:51:20 +0000967 do_mapping:
968 pte = pte & env->a20_mask;
969
Paolo Bonzinie7e898a2014-05-27 14:44:49 +0200970 /* align to page_size */
971 pte &= PG_ADDRESS_MASK & ~(page_size - 1);
972
bellardeaa728e2008-05-28 12:51:20 +0000973 /* Even if 4MB pages, we map only one 4KB page in the cache to
974 avoid filling it too fast */
Paolo Bonzinie7e898a2014-05-27 14:44:49 +0200975 vaddr = addr & TARGET_PAGE_MASK;
976 page_offset = vaddr & (page_size - 1);
977 paddr = pte + page_offset;
bellardeaa728e2008-05-28 12:51:20 +0000978
Paolo Bonzini76c64d32015-11-17 17:09:33 +0100979 assert(prot & (1 << is_write1));
Paolo Bonzinif794aa42015-04-08 14:52:04 +0200980 tlb_set_page_with_attrs(cs, vaddr, paddr, cpu_get_mem_attrs(env),
981 prot, mmu_idx, page_size);
Paul Brookd4c430a2010-03-17 02:14:28 +0000982 return 0;
Paolo Bonzinic1eb2fa2014-05-27 12:16:08 +0200983 do_fault_rsvd:
984 error_code |= PG_ERROR_RSVD_MASK;
bellardeaa728e2008-05-28 12:51:20 +0000985 do_fault_protect:
Paolo Bonzinic1eb2fa2014-05-27 12:16:08 +0200986 error_code |= PG_ERROR_P_MASK;
bellardeaa728e2008-05-28 12:51:20 +0000987 do_fault:
988 error_code |= (is_write << PG_ERROR_W_BIT);
989 if (is_user)
990 error_code |= PG_ERROR_U_MASK;
991 if (is_write1 == 2 &&
H. Peter Anvina9321a42012-09-26 13:18:43 -0700992 (((env->efer & MSR_EFER_NXE) &&
993 (env->cr[4] & CR4_PAE_MASK)) ||
994 (env->cr[4] & CR4_SMEP_MASK)))
bellardeaa728e2008-05-28 12:51:20 +0000995 error_code |= PG_ERROR_I_D_MASK;
bellard872929a2008-05-28 16:16:54 +0000996 if (env->intercept_exceptions & (1 << EXCP0E_PAGE)) {
997 /* cr2 is not modified in case of exceptions */
Paolo Bonzinib216aa62015-04-08 13:39:37 +0200998 x86_stq_phys(cs,
Edgar E. Iglesiasf6066042013-11-28 00:11:44 +0100999 env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2),
bellard872929a2008-05-28 16:16:54 +00001000 addr);
bellardeaa728e2008-05-28 12:51:20 +00001001 } else {
1002 env->cr[2] = addr;
1003 }
1004 env->error_code = error_code;
Andreas Färber27103422013-08-26 08:31:06 +02001005 cs->exception_index = EXCP0E_PAGE;
bellardeaa728e2008-05-28 12:51:20 +00001006 return 1;
1007}
1008
Andreas Färber00b941e2013-06-29 18:55:54 +02001009hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
bellardeaa728e2008-05-28 12:51:20 +00001010{
Andreas Färber00b941e2013-06-29 18:55:54 +02001011 X86CPU *cpu = X86_CPU(cs);
1012 CPUX86State *env = &cpu->env;
bellardeaa728e2008-05-28 12:51:20 +00001013 target_ulong pde_addr, pte_addr;
1014 uint64_t pte;
bellardeaa728e2008-05-28 12:51:20 +00001015 uint32_t page_offset;
1016 int page_size;
1017
Paolo Bonzinif2f85602013-08-30 11:58:45 +02001018 if (!(env->cr[0] & CR0_PG_MASK)) {
1019 pte = addr & env->a20_mask;
1020 page_size = 4096;
1021 } else if (env->cr[4] & CR4_PAE_MASK) {
bellardeaa728e2008-05-28 12:51:20 +00001022 target_ulong pdpe_addr;
1023 uint64_t pde, pdpe;
1024
1025#ifdef TARGET_X86_64
1026 if (env->hflags & HF_LMA_MASK) {
1027 uint64_t pml4e_addr, pml4e;
1028 int32_t sext;
1029
1030 /* test virtual address sign extension */
1031 sext = (int64_t)addr >> 47;
Paolo Bonzini16b96f82014-05-27 14:58:47 +02001032 if (sext != 0 && sext != -1) {
bellardeaa728e2008-05-28 12:51:20 +00001033 return -1;
Paolo Bonzini16b96f82014-05-27 14:58:47 +02001034 }
bellardeaa728e2008-05-28 12:51:20 +00001035 pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
1036 env->a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001037 pml4e = x86_ldq_phys(cs, pml4e_addr);
Paolo Bonzini16b96f82014-05-27 14:58:47 +02001038 if (!(pml4e & PG_PRESENT_MASK)) {
bellardeaa728e2008-05-28 12:51:20 +00001039 return -1;
Paolo Bonzini16b96f82014-05-27 14:58:47 +02001040 }
1041 pdpe_addr = ((pml4e & PG_ADDRESS_MASK) +
Jan Kiszka3f2cbf02012-03-06 15:22:02 +01001042 (((addr >> 30) & 0x1ff) << 3)) & env->a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001043 pdpe = x86_ldq_phys(cs, pdpe_addr);
Paolo Bonzini16b96f82014-05-27 14:58:47 +02001044 if (!(pdpe & PG_PRESENT_MASK)) {
bellardeaa728e2008-05-28 12:51:20 +00001045 return -1;
Paolo Bonzini16b96f82014-05-27 14:58:47 +02001046 }
Luiz Capitulinoc8c14bc2014-03-19 17:03:53 -04001047 if (pdpe & PG_PSE_MASK) {
1048 page_size = 1024 * 1024 * 1024;
Paolo Bonzini16b96f82014-05-27 14:58:47 +02001049 pte = pdpe;
Luiz Capitulinoc8c14bc2014-03-19 17:03:53 -04001050 goto out;
1051 }
1052
bellardeaa728e2008-05-28 12:51:20 +00001053 } else
1054#endif
1055 {
1056 pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
1057 env->a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001058 pdpe = x86_ldq_phys(cs, pdpe_addr);
bellardeaa728e2008-05-28 12:51:20 +00001059 if (!(pdpe & PG_PRESENT_MASK))
1060 return -1;
1061 }
1062
Paolo Bonzini16b96f82014-05-27 14:58:47 +02001063 pde_addr = ((pdpe & PG_ADDRESS_MASK) +
Jan Kiszka3f2cbf02012-03-06 15:22:02 +01001064 (((addr >> 21) & 0x1ff) << 3)) & env->a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001065 pde = x86_ldq_phys(cs, pde_addr);
bellardeaa728e2008-05-28 12:51:20 +00001066 if (!(pde & PG_PRESENT_MASK)) {
1067 return -1;
1068 }
1069 if (pde & PG_PSE_MASK) {
1070 /* 2 MB page */
1071 page_size = 2048 * 1024;
Paolo Bonzini16b96f82014-05-27 14:58:47 +02001072 pte = pde;
bellardeaa728e2008-05-28 12:51:20 +00001073 } else {
1074 /* 4 KB page */
Paolo Bonzini16b96f82014-05-27 14:58:47 +02001075 pte_addr = ((pde & PG_ADDRESS_MASK) +
Jan Kiszka3f2cbf02012-03-06 15:22:02 +01001076 (((addr >> 12) & 0x1ff) << 3)) & env->a20_mask;
bellardeaa728e2008-05-28 12:51:20 +00001077 page_size = 4096;
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001078 pte = x86_ldq_phys(cs, pte_addr);
bellardeaa728e2008-05-28 12:51:20 +00001079 }
Paolo Bonzini16b96f82014-05-27 14:58:47 +02001080 if (!(pte & PG_PRESENT_MASK)) {
aliguorica1c9e12008-08-18 18:00:31 +00001081 return -1;
Paolo Bonzini16b96f82014-05-27 14:58:47 +02001082 }
bellardeaa728e2008-05-28 12:51:20 +00001083 } else {
1084 uint32_t pde;
1085
Paolo Bonzinif2f85602013-08-30 11:58:45 +02001086 /* page directory entry */
1087 pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001088 pde = x86_ldl_phys(cs, pde_addr);
Paolo Bonzinif2f85602013-08-30 11:58:45 +02001089 if (!(pde & PG_PRESENT_MASK))
1090 return -1;
1091 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
Paolo Bonzini388ee482016-02-09 11:44:35 +01001092 pte = pde | ((pde & 0x1fe000LL) << (32 - 13));
Paolo Bonzinif2f85602013-08-30 11:58:45 +02001093 page_size = 4096 * 1024;
bellardeaa728e2008-05-28 12:51:20 +00001094 } else {
1095 /* page directory entry */
Paolo Bonzinif2f85602013-08-30 11:58:45 +02001096 pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001097 pte = x86_ldl_phys(cs, pte_addr);
Paolo Bonzini16b96f82014-05-27 14:58:47 +02001098 if (!(pte & PG_PRESENT_MASK)) {
bellardeaa728e2008-05-28 12:51:20 +00001099 return -1;
Paolo Bonzini16b96f82014-05-27 14:58:47 +02001100 }
Paolo Bonzinif2f85602013-08-30 11:58:45 +02001101 page_size = 4096;
bellardeaa728e2008-05-28 12:51:20 +00001102 }
1103 pte = pte & env->a20_mask;
1104 }
1105
Luiz Capitulinoc8c14bc2014-03-19 17:03:53 -04001106#ifdef TARGET_X86_64
1107out:
1108#endif
Paolo Bonzini16b96f82014-05-27 14:58:47 +02001109 pte &= PG_ADDRESS_MASK & ~(page_size - 1);
bellardeaa728e2008-05-28 12:51:20 +00001110 page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
Paolo Bonzini16b96f82014-05-27 14:58:47 +02001111 return pte | page_offset;
bellardeaa728e2008-05-28 12:51:20 +00001112}
aliguori01df0402008-11-18 21:08:15 +00001113
Jan Kiszkad5bfda32011-03-02 08:56:15 +01001114typedef struct MCEInjectionParams {
1115 Monitor *mon;
Andreas Färber55e5c282012-12-17 06:18:02 +01001116 X86CPU *cpu;
Jan Kiszkad5bfda32011-03-02 08:56:15 +01001117 int bank;
1118 uint64_t status;
1119 uint64_t mcg_status;
1120 uint64_t addr;
1121 uint64_t misc;
1122 int flags;
1123} MCEInjectionParams;
1124
1125static void do_inject_x86_mce(void *data)
Huang Ying79c4f6b2009-06-23 10:05:14 +08001126{
Jan Kiszkad5bfda32011-03-02 08:56:15 +01001127 MCEInjectionParams *params = data;
Andreas Färber55e5c282012-12-17 06:18:02 +01001128 CPUX86State *cenv = &params->cpu->env;
1129 CPUState *cpu = CPU(params->cpu);
Jan Kiszkad5bfda32011-03-02 08:56:15 +01001130 uint64_t *banks = cenv->mce_banks + 4 * params->bank;
1131
Andreas Färbercb446ec2013-05-01 14:24:52 +02001132 cpu_synchronize_state(cpu);
Huang Ying79c4f6b2009-06-23 10:05:14 +08001133
Jan Kiszka747461c2011-03-02 08:56:10 +01001134 /*
1135 * If there is an MCE exception being processed, ignore this SRAO MCE
1136 * unless unconditional injection was requested.
1137 */
Jan Kiszkad5bfda32011-03-02 08:56:15 +01001138 if (!(params->flags & MCE_INJECT_UNCOND_AO)
1139 && !(params->status & MCI_STATUS_AR)
Jan Kiszka747461c2011-03-02 08:56:10 +01001140 && (cenv->mcg_status & MCG_STATUS_MCIP)) {
1141 return;
1142 }
Jan Kiszkad5bfda32011-03-02 08:56:15 +01001143
1144 if (params->status & MCI_STATUS_UC) {
Jan Kiszka316378e2011-03-02 08:56:09 +01001145 /*
1146 * if MSR_MCG_CTL is not all 1s, the uncorrected error
1147 * reporting is disabled
1148 */
Jan Kiszkad5bfda32011-03-02 08:56:15 +01001149 if ((cenv->mcg_cap & MCG_CTL_P) && cenv->mcg_ctl != ~(uint64_t)0) {
1150 monitor_printf(params->mon,
Jan Kiszka316378e2011-03-02 08:56:09 +01001151 "CPU %d: Uncorrected error reporting disabled\n",
Andreas Färber55e5c282012-12-17 06:18:02 +01001152 cpu->cpu_index);
Jan Kiszka316378e2011-03-02 08:56:09 +01001153 return;
1154 }
1155
1156 /*
1157 * if MSR_MCi_CTL is not all 1s, the uncorrected error
1158 * reporting is disabled for the bank
1159 */
1160 if (banks[0] != ~(uint64_t)0) {
Jan Kiszkad5bfda32011-03-02 08:56:15 +01001161 monitor_printf(params->mon,
1162 "CPU %d: Uncorrected error reporting disabled for"
1163 " bank %d\n",
Andreas Färber55e5c282012-12-17 06:18:02 +01001164 cpu->cpu_index, params->bank);
Jan Kiszka316378e2011-03-02 08:56:09 +01001165 return;
1166 }
1167
Huang Ying79c4f6b2009-06-23 10:05:14 +08001168 if ((cenv->mcg_status & MCG_STATUS_MCIP) ||
1169 !(cenv->cr[4] & CR4_MCE_MASK)) {
Jan Kiszkad5bfda32011-03-02 08:56:15 +01001170 monitor_printf(params->mon,
1171 "CPU %d: Previous MCE still in progress, raising"
1172 " triple fault\n",
Andreas Färber55e5c282012-12-17 06:18:02 +01001173 cpu->cpu_index);
Huang Ying79c4f6b2009-06-23 10:05:14 +08001174 qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
1175 qemu_system_reset_request();
1176 return;
1177 }
Jan Kiszka2fa11da2011-03-02 08:56:08 +01001178 if (banks[1] & MCI_STATUS_VAL) {
Jan Kiszkad5bfda32011-03-02 08:56:15 +01001179 params->status |= MCI_STATUS_OVER;
Jan Kiszka2fa11da2011-03-02 08:56:08 +01001180 }
Jan Kiszkad5bfda32011-03-02 08:56:15 +01001181 banks[2] = params->addr;
1182 banks[3] = params->misc;
1183 cenv->mcg_status = params->mcg_status;
1184 banks[1] = params->status;
Andreas Färberc3affe52013-01-18 15:03:43 +01001185 cpu_interrupt(cpu, CPU_INTERRUPT_MCE);
Huang Ying79c4f6b2009-06-23 10:05:14 +08001186 } else if (!(banks[1] & MCI_STATUS_VAL)
1187 || !(banks[1] & MCI_STATUS_UC)) {
Jan Kiszka2fa11da2011-03-02 08:56:08 +01001188 if (banks[1] & MCI_STATUS_VAL) {
Jan Kiszkad5bfda32011-03-02 08:56:15 +01001189 params->status |= MCI_STATUS_OVER;
Jan Kiszka2fa11da2011-03-02 08:56:08 +01001190 }
Jan Kiszkad5bfda32011-03-02 08:56:15 +01001191 banks[2] = params->addr;
1192 banks[3] = params->misc;
1193 banks[1] = params->status;
Jan Kiszka2fa11da2011-03-02 08:56:08 +01001194 } else {
Huang Ying79c4f6b2009-06-23 10:05:14 +08001195 banks[1] |= MCI_STATUS_OVER;
Jan Kiszka2fa11da2011-03-02 08:56:08 +01001196 }
Huang Ying79c4f6b2009-06-23 10:05:14 +08001197}
Jin Dongmingb3cd24e2010-12-10 17:20:44 +09001198
Andreas Färber8c5cf3b2012-05-03 15:22:54 +02001199void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
Jan Kiszka316378e2011-03-02 08:56:09 +01001200 uint64_t status, uint64_t mcg_status, uint64_t addr,
Jan Kiszka747461c2011-03-02 08:56:10 +01001201 uint64_t misc, int flags)
Jin Dongmingb3cd24e2010-12-10 17:20:44 +09001202{
Andreas Färber182735e2013-05-29 22:29:20 +02001203 CPUState *cs = CPU(cpu);
Andreas Färber8c5cf3b2012-05-03 15:22:54 +02001204 CPUX86State *cenv = &cpu->env;
Jan Kiszkad5bfda32011-03-02 08:56:15 +01001205 MCEInjectionParams params = {
1206 .mon = mon,
Andreas Färber55e5c282012-12-17 06:18:02 +01001207 .cpu = cpu,
Jan Kiszkad5bfda32011-03-02 08:56:15 +01001208 .bank = bank,
1209 .status = status,
1210 .mcg_status = mcg_status,
1211 .addr = addr,
1212 .misc = misc,
1213 .flags = flags,
1214 };
Jin Dongmingb3cd24e2010-12-10 17:20:44 +09001215 unsigned bank_num = cenv->mcg_cap & 0xff;
1216
Jan Kiszka316378e2011-03-02 08:56:09 +01001217 if (!cenv->mcg_cap) {
1218 monitor_printf(mon, "MCE injection not supported\n");
Jin Dongmingb3cd24e2010-12-10 17:20:44 +09001219 return;
1220 }
Jan Kiszka316378e2011-03-02 08:56:09 +01001221 if (bank >= bank_num) {
1222 monitor_printf(mon, "Invalid MCE bank number\n");
1223 return;
1224 }
1225 if (!(status & MCI_STATUS_VAL)) {
1226 monitor_printf(mon, "Invalid MCE status code\n");
1227 return;
1228 }
Jan Kiszka747461c2011-03-02 08:56:10 +01001229 if ((flags & MCE_INJECT_BROADCAST)
1230 && !cpu_x86_support_mca_broadcast(cenv)) {
Jan Kiszka316378e2011-03-02 08:56:09 +01001231 monitor_printf(mon, "Guest CPU does not support MCA broadcast\n");
1232 return;
Jin Dongming2bd3e042010-12-10 17:21:14 +09001233 }
1234
Andreas Färber182735e2013-05-29 22:29:20 +02001235 run_on_cpu(cs, do_inject_x86_mce, &params);
Jan Kiszkac34d4402011-03-02 08:56:16 +01001236 if (flags & MCE_INJECT_BROADCAST) {
Andreas Färber182735e2013-05-29 22:29:20 +02001237 CPUState *other_cs;
1238
Jan Kiszkac34d4402011-03-02 08:56:16 +01001239 params.bank = 1;
1240 params.status = MCI_STATUS_VAL | MCI_STATUS_UC;
1241 params.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV;
1242 params.addr = 0;
1243 params.misc = 0;
Andreas Färberbdc44642013-06-24 23:50:24 +02001244 CPU_FOREACH(other_cs) {
Andreas Färber182735e2013-05-29 22:29:20 +02001245 if (other_cs == cs) {
Jan Kiszkac34d4402011-03-02 08:56:16 +01001246 continue;
Jin Dongming31ce5e02010-12-10 17:21:02 +09001247 }
Andreas Färber182735e2013-05-29 22:29:20 +02001248 params.cpu = X86_CPU(other_cs);
1249 run_on_cpu(other_cs, do_inject_x86_mce, &params);
Jin Dongming31ce5e02010-12-10 17:21:02 +09001250 }
Jin Dongmingb3cd24e2010-12-10 17:20:44 +09001251 }
1252}
Jan Kiszkad362e752012-02-17 18:31:17 +01001253
Andreas Färber317ac622012-03-14 01:38:21 +01001254void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
Jan Kiszkad362e752012-02-17 18:31:17 +01001255{
Chen Fan02e51482013-12-23 17:04:02 +08001256 X86CPU *cpu = x86_env_get_cpu(env);
Andreas Färber93afead2013-08-26 03:41:01 +02001257 CPUState *cs = CPU(cpu);
Chen Fan02e51482013-12-23 17:04:02 +08001258
Jan Kiszkad362e752012-02-17 18:31:17 +01001259 if (kvm_enabled()) {
1260 env->tpr_access_type = access;
1261
Andreas Färber93afead2013-08-26 03:41:01 +02001262 cpu_interrupt(cs, CPU_INTERRUPT_TPR);
Jan Kiszkad362e752012-02-17 18:31:17 +01001263 } else {
Andreas Färber3f38f302013-09-01 16:51:34 +02001264 cpu_restore_state(cs, cs->mem_io_pc);
Jan Kiszkad362e752012-02-17 18:31:17 +01001265
Chen Fan02e51482013-12-23 17:04:02 +08001266 apic_handle_tpr_access_report(cpu->apic_state, env->eip, access);
Jan Kiszkad362e752012-02-17 18:31:17 +01001267 }
1268}
bellardeaa728e2008-05-28 12:51:20 +00001269#endif /* !CONFIG_USER_ONLY */
aliguori6fd805e2008-11-05 15:34:06 +00001270
Jan Kiszka84273172009-06-27 09:53:51 +02001271int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
1272 target_ulong *base, unsigned int *limit,
1273 unsigned int *flags)
1274{
Andreas Färberf17ec442013-06-29 19:40:58 +02001275 X86CPU *cpu = x86_env_get_cpu(env);
1276 CPUState *cs = CPU(cpu);
Jan Kiszka84273172009-06-27 09:53:51 +02001277 SegmentCache *dt;
1278 target_ulong ptr;
1279 uint32_t e1, e2;
1280 int index;
1281
1282 if (selector & 0x4)
1283 dt = &env->ldt;
1284 else
1285 dt = &env->gdt;
1286 index = selector & ~7;
1287 ptr = dt->base + index;
1288 if ((index + 7) > dt->limit
Andreas Färberf17ec442013-06-29 19:40:58 +02001289 || cpu_memory_rw_debug(cs, ptr, (uint8_t *)&e1, sizeof(e1), 0) != 0
1290 || cpu_memory_rw_debug(cs, ptr+4, (uint8_t *)&e2, sizeof(e2), 0) != 0)
Jan Kiszka84273172009-06-27 09:53:51 +02001291 return 0;
1292
1293 *base = ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
1294 *limit = (e1 & 0xffff) | (e2 & 0x000f0000);
1295 if (e2 & DESC_G_MASK)
1296 *limit = (*limit << 12) | 0xfff;
1297 *flags = e2;
1298
1299 return 1;
1300}
1301
Gleb Natapovb09ea7d2009-06-17 23:26:59 +03001302#if !defined(CONFIG_USER_ONLY)
Andreas Färber232fc232012-05-05 01:14:41 +02001303void do_cpu_init(X86CPU *cpu)
Gleb Natapovb09ea7d2009-06-17 23:26:59 +03001304{
Andreas Färber259186a2013-01-17 18:51:17 +01001305 CPUState *cs = CPU(cpu);
Andreas Färber232fc232012-05-05 01:14:41 +02001306 CPUX86State *env = &cpu->env;
Paolo Bonzini43175fa2013-03-12 13:16:28 +01001307 CPUX86State *save = g_new(CPUX86State, 1);
Andreas Färber259186a2013-01-17 18:51:17 +01001308 int sipi = cs->interrupt_request & CPU_INTERRUPT_SIPI;
Paolo Bonzini43175fa2013-03-12 13:16:28 +01001309
1310 *save = *env;
Jan Kiszkaebda3772011-03-15 12:26:21 +01001311
Andreas Färber259186a2013-01-17 18:51:17 +01001312 cpu_reset(cs);
1313 cs->interrupt_request = sipi;
Paolo Bonzini43175fa2013-03-12 13:16:28 +01001314 memcpy(&env->start_init_save, &save->start_init_save,
1315 offsetof(CPUX86State, end_init_save) -
1316 offsetof(CPUX86State, start_init_save));
1317 g_free(save);
1318
Paolo Bonzinie0723c42013-03-08 19:21:50 +01001319 if (kvm_enabled()) {
1320 kvm_arch_do_init_vcpu(cpu);
1321 }
Chen Fan02e51482013-12-23 17:04:02 +08001322 apic_init_reset(cpu->apic_state);
Gleb Natapovb09ea7d2009-06-17 23:26:59 +03001323}
1324
Andreas Färber232fc232012-05-05 01:14:41 +02001325void do_cpu_sipi(X86CPU *cpu)
Gleb Natapovb09ea7d2009-06-17 23:26:59 +03001326{
Chen Fan02e51482013-12-23 17:04:02 +08001327 apic_sipi(cpu->apic_state);
Gleb Natapovb09ea7d2009-06-17 23:26:59 +03001328}
1329#else
Andreas Färber232fc232012-05-05 01:14:41 +02001330void do_cpu_init(X86CPU *cpu)
Gleb Natapovb09ea7d2009-06-17 23:26:59 +03001331{
1332}
Andreas Färber232fc232012-05-05 01:14:41 +02001333void do_cpu_sipi(X86CPU *cpu)
Gleb Natapovb09ea7d2009-06-17 23:26:59 +03001334{
1335}
1336#endif
Richard Henderson374e0cd2014-09-13 09:45:14 -07001337
1338/* Frob eflags into and out of the CPU temporary format. */
1339
1340void x86_cpu_exec_enter(CPUState *cs)
1341{
1342 X86CPU *cpu = X86_CPU(cs);
1343 CPUX86State *env = &cpu->env;
1344
1345 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1346 env->df = 1 - (2 * ((env->eflags >> 10) & 1));
1347 CC_OP = CC_OP_EFLAGS;
1348 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1349}
1350
1351void x86_cpu_exec_exit(CPUState *cs)
1352{
1353 X86CPU *cpu = X86_CPU(cs);
1354 CPUX86State *env = &cpu->env;
1355
1356 env->eflags = cpu_compute_eflags(env);
1357}
Paolo Bonzinib216aa62015-04-08 13:39:37 +02001358
1359#ifndef CONFIG_USER_ONLY
1360uint8_t x86_ldub_phys(CPUState *cs, hwaddr addr)
1361{
1362 X86CPU *cpu = X86_CPU(cs);
1363 CPUX86State *env = &cpu->env;
1364
1365 return address_space_ldub(cs->as, addr,
1366 cpu_get_mem_attrs(env),
1367 NULL);
1368}
1369
1370uint32_t x86_lduw_phys(CPUState *cs, hwaddr addr)
1371{
1372 X86CPU *cpu = X86_CPU(cs);
1373 CPUX86State *env = &cpu->env;
1374
1375 return address_space_lduw(cs->as, addr,
1376 cpu_get_mem_attrs(env),
1377 NULL);
1378}
1379
1380uint32_t x86_ldl_phys(CPUState *cs, hwaddr addr)
1381{
1382 X86CPU *cpu = X86_CPU(cs);
1383 CPUX86State *env = &cpu->env;
1384
1385 return address_space_ldl(cs->as, addr,
1386 cpu_get_mem_attrs(env),
1387 NULL);
1388}
1389
1390uint64_t x86_ldq_phys(CPUState *cs, hwaddr addr)
1391{
1392 X86CPU *cpu = X86_CPU(cs);
1393 CPUX86State *env = &cpu->env;
1394
1395 return address_space_ldq(cs->as, addr,
1396 cpu_get_mem_attrs(env),
1397 NULL);
1398}
1399
1400void x86_stb_phys(CPUState *cs, hwaddr addr, uint8_t val)
1401{
1402 X86CPU *cpu = X86_CPU(cs);
1403 CPUX86State *env = &cpu->env;
1404
1405 address_space_stb(cs->as, addr, val,
1406 cpu_get_mem_attrs(env),
1407 NULL);
1408}
1409
1410void x86_stl_phys_notdirty(CPUState *cs, hwaddr addr, uint32_t val)
1411{
1412 X86CPU *cpu = X86_CPU(cs);
1413 CPUX86State *env = &cpu->env;
1414
1415 address_space_stl_notdirty(cs->as, addr, val,
1416 cpu_get_mem_attrs(env),
1417 NULL);
1418}
1419
1420void x86_stw_phys(CPUState *cs, hwaddr addr, uint32_t val)
1421{
1422 X86CPU *cpu = X86_CPU(cs);
1423 CPUX86State *env = &cpu->env;
1424
1425 address_space_stw(cs->as, addr, val,
1426 cpu_get_mem_attrs(env),
1427 NULL);
1428}
1429
1430void x86_stl_phys(CPUState *cs, hwaddr addr, uint32_t val)
1431{
1432 X86CPU *cpu = X86_CPU(cs);
1433 CPUX86State *env = &cpu->env;
1434
1435 address_space_stl(cs->as, addr, val,
1436 cpu_get_mem_attrs(env),
1437 NULL);
1438}
1439
1440void x86_stq_phys(CPUState *cs, hwaddr addr, uint64_t val)
1441{
1442 X86CPU *cpu = X86_CPU(cs);
1443 CPUX86State *env = &cpu->env;
1444
1445 address_space_stq(cs->as, addr, val,
1446 cpu_get_mem_attrs(env),
1447 NULL);
1448}
1449#endif