]> git.proxmox.com Git - mirror_qemu.git/blame - target-i386/helper.c
target-i386: commonize checks for PAE and non-PAE
[mirror_qemu.git] / target-i386 / helper.c
CommitLineData
2c0262af 1/*
eaa728ee 2 * i386 helpers (without register variable usage)
5fafdf24 3 *
2c0262af
FB
4 * 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
8167ee88 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
2c0262af 18 */
2c0262af 19
eaa728ee 20#include "cpu.h"
9c17d615 21#include "sysemu/kvm.h"
e0723c45 22#include "kvm_i386.h"
2fa11da0 23#ifndef CONFIG_USER_ONLY
9c17d615 24#include "sysemu/sysemu.h"
83c9089e 25#include "monitor/monitor.h"
2fa11da0 26#endif
f3f2d9be 27
eaa728ee 28//#define DEBUG_MMU
b5ec5ce0 29
317ac620 30static void cpu_x86_version(CPUX86State *env, int *family, int *model)
2bd3e04c
JD
31{
32 int cpuver = env->cpuid_version;
33
34 if (family == NULL || model == NULL) {
35 return;
36 }
37
38 *family = (cpuver >> 8) & 0x0f;
39 *model = ((cpuver >> 12) & 0xf0) + ((cpuver >> 4) & 0x0f);
40}
41
42/* Broadcast MCA signal for processor version 06H_EH and above */
317ac620 43int cpu_x86_support_mca_broadcast(CPUX86State *env)
2bd3e04c
JD
44{
45 int family = 0;
46 int model = 0;
47
48 cpu_x86_version(env, &family, &model);
49 if ((family == 6 && model >= 14) || family > 6) {
50 return 1;
51 }
52
53 return 0;
54}
55
eaa728ee
FB
56/***********************************************************/
57/* x86 debug */
3b46e624 58
bc4b43dc 59static const char *cc_op_str[CC_OP_NB] = {
eaa728ee
FB
60 "DYNAMIC",
61 "EFLAGS",
7e84c249 62
eaa728ee
FB
63 "MULB",
64 "MULW",
65 "MULL",
66 "MULQ",
3b46e624 67
eaa728ee
FB
68 "ADDB",
69 "ADDW",
70 "ADDL",
71 "ADDQ",
3b46e624 72
eaa728ee
FB
73 "ADCB",
74 "ADCW",
75 "ADCL",
76 "ADCQ",
3b46e624 77
eaa728ee
FB
78 "SUBB",
79 "SUBW",
80 "SUBL",
81 "SUBQ",
7e84c249 82
eaa728ee
FB
83 "SBBB",
84 "SBBW",
85 "SBBL",
86 "SBBQ",
7e84c249 87
eaa728ee
FB
88 "LOGICB",
89 "LOGICW",
90 "LOGICL",
91 "LOGICQ",
7e84c249 92
eaa728ee
FB
93 "INCB",
94 "INCW",
95 "INCL",
96 "INCQ",
3b46e624 97
eaa728ee
FB
98 "DECB",
99 "DECW",
100 "DECL",
101 "DECQ",
3b46e624 102
eaa728ee
FB
103 "SHLB",
104 "SHLW",
105 "SHLL",
106 "SHLQ",
3b46e624 107
eaa728ee
FB
108 "SARB",
109 "SARW",
110 "SARL",
111 "SARQ",
bc4b43dc
RH
112
113 "BMILGB",
114 "BMILGW",
115 "BMILGL",
116 "BMILGQ",
cd7f97ca
RH
117
118 "ADCX",
119 "ADOX",
120 "ADCOX",
436ff2d2
RH
121
122 "CLR",
eaa728ee 123};
7e84c249 124
a3867ed2 125static void
317ac620 126cpu_x86_dump_seg_cache(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
a3867ed2
AL
127 const char *name, struct SegmentCache *sc)
128{
129#ifdef TARGET_X86_64
130 if (env->hflags & HF_CS64_MASK) {
131 cpu_fprintf(f, "%-3s=%04x %016" PRIx64 " %08x %08x", name,
4058fd98 132 sc->selector, sc->base, sc->limit, sc->flags & 0x00ffff00);
a3867ed2
AL
133 } else
134#endif
135 {
136 cpu_fprintf(f, "%-3s=%04x %08x %08x %08x", name, sc->selector,
4058fd98 137 (uint32_t)sc->base, sc->limit, sc->flags & 0x00ffff00);
a3867ed2
AL
138 }
139
140 if (!(env->hflags & HF_PE_MASK) || !(sc->flags & DESC_P_MASK))
141 goto done;
142
143 cpu_fprintf(f, " DPL=%d ", (sc->flags & DESC_DPL_MASK) >> DESC_DPL_SHIFT);
144 if (sc->flags & DESC_S_MASK) {
145 if (sc->flags & DESC_CS_MASK) {
146 cpu_fprintf(f, (sc->flags & DESC_L_MASK) ? "CS64" :
147 ((sc->flags & DESC_B_MASK) ? "CS32" : "CS16"));
148 cpu_fprintf(f, " [%c%c", (sc->flags & DESC_C_MASK) ? 'C' : '-',
149 (sc->flags & DESC_R_MASK) ? 'R' : '-');
150 } else {
469936ae
TM
151 cpu_fprintf(f,
152 (sc->flags & DESC_B_MASK || env->hflags & HF_LMA_MASK)
153 ? "DS " : "DS16");
a3867ed2
AL
154 cpu_fprintf(f, " [%c%c", (sc->flags & DESC_E_MASK) ? 'E' : '-',
155 (sc->flags & DESC_W_MASK) ? 'W' : '-');
156 }
157 cpu_fprintf(f, "%c]", (sc->flags & DESC_A_MASK) ? 'A' : '-');
158 } else {
159 static const char *sys_type_name[2][16] = {
160 { /* 32 bit mode */
161 "Reserved", "TSS16-avl", "LDT", "TSS16-busy",
162 "CallGate16", "TaskGate", "IntGate16", "TrapGate16",
163 "Reserved", "TSS32-avl", "Reserved", "TSS32-busy",
164 "CallGate32", "Reserved", "IntGate32", "TrapGate32"
165 },
166 { /* 64 bit mode */
167 "<hiword>", "Reserved", "LDT", "Reserved", "Reserved",
168 "Reserved", "Reserved", "Reserved", "Reserved",
169 "TSS64-avl", "Reserved", "TSS64-busy", "CallGate64",
170 "Reserved", "IntGate64", "TrapGate64"
171 }
172 };
e5c15eff
SW
173 cpu_fprintf(f, "%s",
174 sys_type_name[(env->hflags & HF_LMA_MASK) ? 1 : 0]
175 [(sc->flags & DESC_TYPE_MASK)
176 >> DESC_TYPE_SHIFT]);
a3867ed2
AL
177 }
178done:
179 cpu_fprintf(f, "\n");
180}
181
f5c848ee
JK
182#define DUMP_CODE_BYTES_TOTAL 50
183#define DUMP_CODE_BYTES_BACKWARD 20
184
878096ee
AF
185void x86_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
186 int flags)
eaa728ee 187{
878096ee
AF
188 X86CPU *cpu = X86_CPU(cs);
189 CPUX86State *env = &cpu->env;
eaa728ee
FB
190 int eflags, i, nb;
191 char cc_op_name[32];
192 static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
7e84c249 193
4980ef9e 194 eflags = cpu_compute_eflags(env);
eaa728ee
FB
195#ifdef TARGET_X86_64
196 if (env->hflags & HF_CS64_MASK) {
197 cpu_fprintf(f,
198 "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
199 "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
200 "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
201 "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
202 "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
203 env->regs[R_EAX],
204 env->regs[R_EBX],
205 env->regs[R_ECX],
206 env->regs[R_EDX],
207 env->regs[R_ESI],
208 env->regs[R_EDI],
209 env->regs[R_EBP],
210 env->regs[R_ESP],
211 env->regs[8],
212 env->regs[9],
213 env->regs[10],
214 env->regs[11],
215 env->regs[12],
216 env->regs[13],
217 env->regs[14],
218 env->regs[15],
219 env->eip, eflags,
220 eflags & DF_MASK ? 'D' : '-',
221 eflags & CC_O ? 'O' : '-',
222 eflags & CC_S ? 'S' : '-',
223 eflags & CC_Z ? 'Z' : '-',
224 eflags & CC_A ? 'A' : '-',
225 eflags & CC_P ? 'P' : '-',
226 eflags & CC_C ? 'C' : '-',
227 env->hflags & HF_CPL_MASK,
228 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
5ee0ffaa 229 (env->a20_mask >> 20) & 1,
eaa728ee 230 (env->hflags >> HF_SMM_SHIFT) & 1,
259186a7 231 cs->halted);
eaa728ee
FB
232 } else
233#endif
234 {
235 cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
236 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
237 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
238 (uint32_t)env->regs[R_EAX],
239 (uint32_t)env->regs[R_EBX],
240 (uint32_t)env->regs[R_ECX],
241 (uint32_t)env->regs[R_EDX],
242 (uint32_t)env->regs[R_ESI],
243 (uint32_t)env->regs[R_EDI],
244 (uint32_t)env->regs[R_EBP],
245 (uint32_t)env->regs[R_ESP],
246 (uint32_t)env->eip, eflags,
247 eflags & DF_MASK ? 'D' : '-',
248 eflags & CC_O ? 'O' : '-',
249 eflags & CC_S ? 'S' : '-',
250 eflags & CC_Z ? 'Z' : '-',
251 eflags & CC_A ? 'A' : '-',
252 eflags & CC_P ? 'P' : '-',
253 eflags & CC_C ? 'C' : '-',
254 env->hflags & HF_CPL_MASK,
255 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
5ee0ffaa 256 (env->a20_mask >> 20) & 1,
eaa728ee 257 (env->hflags >> HF_SMM_SHIFT) & 1,
259186a7 258 cs->halted);
8145122b 259 }
3b46e624 260
a3867ed2
AL
261 for(i = 0; i < 6; i++) {
262 cpu_x86_dump_seg_cache(env, f, cpu_fprintf, seg_name[i],
263 &env->segs[i]);
264 }
265 cpu_x86_dump_seg_cache(env, f, cpu_fprintf, "LDT", &env->ldt);
266 cpu_x86_dump_seg_cache(env, f, cpu_fprintf, "TR", &env->tr);
267
eaa728ee
FB
268#ifdef TARGET_X86_64
269 if (env->hflags & HF_LMA_MASK) {
eaa728ee
FB
270 cpu_fprintf(f, "GDT= %016" PRIx64 " %08x\n",
271 env->gdt.base, env->gdt.limit);
272 cpu_fprintf(f, "IDT= %016" PRIx64 " %08x\n",
273 env->idt.base, env->idt.limit);
274 cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
275 (uint32_t)env->cr[0],
276 env->cr[2],
277 env->cr[3],
278 (uint32_t)env->cr[4]);
a59cb4e0
AL
279 for(i = 0; i < 4; i++)
280 cpu_fprintf(f, "DR%d=%016" PRIx64 " ", i, env->dr[i]);
281 cpu_fprintf(f, "\nDR6=%016" PRIx64 " DR7=%016" PRIx64 "\n",
d4b55be5 282 env->dr[6], env->dr[7]);
eaa728ee
FB
283 } else
284#endif
285 {
eaa728ee
FB
286 cpu_fprintf(f, "GDT= %08x %08x\n",
287 (uint32_t)env->gdt.base, env->gdt.limit);
288 cpu_fprintf(f, "IDT= %08x %08x\n",
289 (uint32_t)env->idt.base, env->idt.limit);
290 cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
291 (uint32_t)env->cr[0],
292 (uint32_t)env->cr[2],
293 (uint32_t)env->cr[3],
294 (uint32_t)env->cr[4]);
9a78eead
SW
295 for(i = 0; i < 4; i++) {
296 cpu_fprintf(f, "DR%d=" TARGET_FMT_lx " ", i, env->dr[i]);
297 }
298 cpu_fprintf(f, "\nDR6=" TARGET_FMT_lx " DR7=" TARGET_FMT_lx "\n",
299 env->dr[6], env->dr[7]);
eaa728ee 300 }
6fd2a026 301 if (flags & CPU_DUMP_CCOP) {
eaa728ee
FB
302 if ((unsigned)env->cc_op < CC_OP_NB)
303 snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
304 else
305 snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
306#ifdef TARGET_X86_64
307 if (env->hflags & HF_CS64_MASK) {
308 cpu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
309 env->cc_src, env->cc_dst,
310 cc_op_name);
311 } else
312#endif
313 {
314 cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
315 (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
316 cc_op_name);
317 }
7e84c249 318 }
b5e5a934 319 cpu_fprintf(f, "EFER=%016" PRIx64 "\n", env->efer);
6fd2a026 320 if (flags & CPU_DUMP_FPU) {
eaa728ee
FB
321 int fptag;
322 fptag = 0;
323 for(i = 0; i < 8; i++) {
324 fptag |= ((!env->fptags[i]) << i);
325 }
326 cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
327 env->fpuc,
328 (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
329 env->fpstt,
330 fptag,
331 env->mxcsr);
332 for(i=0;i<8;i++) {
1ffd41ee
AJ
333 CPU_LDoubleU u;
334 u.d = env->fpregs[i].d;
eaa728ee 335 cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
1ffd41ee 336 i, u.l.lower, u.l.upper);
eaa728ee
FB
337 if ((i & 1) == 1)
338 cpu_fprintf(f, "\n");
339 else
340 cpu_fprintf(f, " ");
341 }
342 if (env->hflags & HF_CS64_MASK)
343 nb = 16;
344 else
345 nb = 8;
346 for(i=0;i<nb;i++) {
347 cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
348 i,
349 env->xmm_regs[i].XMM_L(3),
350 env->xmm_regs[i].XMM_L(2),
351 env->xmm_regs[i].XMM_L(1),
352 env->xmm_regs[i].XMM_L(0));
353 if ((i & 1) == 1)
354 cpu_fprintf(f, "\n");
355 else
356 cpu_fprintf(f, " ");
357 }
7e84c249 358 }
f5c848ee
JK
359 if (flags & CPU_DUMP_CODE) {
360 target_ulong base = env->segs[R_CS].base + env->eip;
361 target_ulong offs = MIN(env->eip, DUMP_CODE_BYTES_BACKWARD);
362 uint8_t code;
363 char codestr[3];
364
365 cpu_fprintf(f, "Code=");
366 for (i = 0; i < DUMP_CODE_BYTES_TOTAL; i++) {
f17ec444 367 if (cpu_memory_rw_debug(cs, base - offs + i, &code, 1, 0) == 0) {
f5c848ee
JK
368 snprintf(codestr, sizeof(codestr), "%02x", code);
369 } else {
370 snprintf(codestr, sizeof(codestr), "??");
371 }
372 cpu_fprintf(f, "%s%s%s%s", i > 0 ? " " : "",
373 i == offs ? "<" : "", codestr, i == offs ? ">" : "");
374 }
375 cpu_fprintf(f, "\n");
376 }
2c0262af 377}
7e84c249 378
eaa728ee
FB
379/***********************************************************/
380/* x86 mmu */
381/* XXX: add PGE support */
382
cc36a7a2 383void x86_cpu_set_a20(X86CPU *cpu, int a20_state)
2c0262af 384{
cc36a7a2
AF
385 CPUX86State *env = &cpu->env;
386
eaa728ee
FB
387 a20_state = (a20_state != 0);
388 if (a20_state != ((env->a20_mask >> 20) & 1)) {
00c8cb0a
AF
389 CPUState *cs = CPU(cpu);
390
eaa728ee
FB
391#if defined(DEBUG_MMU)
392 printf("A20 update: a20=%d\n", a20_state);
393#endif
394 /* if the cpu is currently executing code, we must unlink it and
395 all the potentially executing TB */
00c8cb0a 396 cpu_interrupt(cs, CPU_INTERRUPT_EXITTB);
3b46e624 397
eaa728ee
FB
398 /* when a20 is changed, all the MMU mappings are invalid, so
399 we must flush everything */
00c8cb0a 400 tlb_flush(cs, 1);
5ee0ffaa 401 env->a20_mask = ~(1 << 20) | (a20_state << 20);
7e84c249 402 }
2c0262af
FB
403}
404
eaa728ee 405void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
2c0262af 406{
00c8cb0a 407 X86CPU *cpu = x86_env_get_cpu(env);
eaa728ee 408 int pe_state;
2c0262af 409
eaa728ee
FB
410#if defined(DEBUG_MMU)
411 printf("CR0 update: CR0=0x%08x\n", new_cr0);
412#endif
413 if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
414 (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
00c8cb0a 415 tlb_flush(CPU(cpu), 1);
eaa728ee 416 }
2c0262af 417
eaa728ee
FB
418#ifdef TARGET_X86_64
419 if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
420 (env->efer & MSR_EFER_LME)) {
421 /* enter in long mode */
422 /* XXX: generate an exception */
423 if (!(env->cr[4] & CR4_PAE_MASK))
424 return;
425 env->efer |= MSR_EFER_LMA;
426 env->hflags |= HF_LMA_MASK;
427 } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
428 (env->efer & MSR_EFER_LMA)) {
429 /* exit long mode */
430 env->efer &= ~MSR_EFER_LMA;
431 env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
432 env->eip &= 0xffffffff;
433 }
434#endif
435 env->cr[0] = new_cr0 | CR0_ET_MASK;
7e84c249 436
eaa728ee
FB
437 /* update PE flag in hidden flags */
438 pe_state = (env->cr[0] & CR0_PE_MASK);
439 env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
440 /* ensure that ADDSEG is always set in real mode */
441 env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
442 /* update FPU flags */
443 env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
444 ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
7e84c249
FB
445}
446
eaa728ee
FB
447/* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
448 the PDPT */
449void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
7e84c249 450{
00c8cb0a
AF
451 X86CPU *cpu = x86_env_get_cpu(env);
452
eaa728ee
FB
453 env->cr[3] = new_cr3;
454 if (env->cr[0] & CR0_PG_MASK) {
455#if defined(DEBUG_MMU)
456 printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
457#endif
00c8cb0a 458 tlb_flush(CPU(cpu), 0);
eaa728ee 459 }
7e84c249
FB
460}
461
eaa728ee 462void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
7e84c249 463{
00c8cb0a
AF
464 X86CPU *cpu = x86_env_get_cpu(env);
465
eaa728ee
FB
466#if defined(DEBUG_MMU)
467 printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
468#endif
a9321a4d
PA
469 if ((new_cr4 ^ env->cr[4]) &
470 (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK |
471 CR4_SMEP_MASK | CR4_SMAP_MASK)) {
00c8cb0a 472 tlb_flush(CPU(cpu), 1);
eaa728ee
FB
473 }
474 /* SSE handling */
0514ef2f 475 if (!(env->features[FEAT_1_EDX] & CPUID_SSE)) {
eaa728ee 476 new_cr4 &= ~CR4_OSFXSR_MASK;
a9321a4d
PA
477 }
478 env->hflags &= ~HF_OSFXSR_MASK;
479 if (new_cr4 & CR4_OSFXSR_MASK) {
eaa728ee 480 env->hflags |= HF_OSFXSR_MASK;
a9321a4d
PA
481 }
482
0514ef2f 483 if (!(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_SMAP)) {
a9321a4d
PA
484 new_cr4 &= ~CR4_SMAP_MASK;
485 }
486 env->hflags &= ~HF_SMAP_MASK;
487 if (new_cr4 & CR4_SMAP_MASK) {
488 env->hflags |= HF_SMAP_MASK;
489 }
b8b6a50b 490
eaa728ee 491 env->cr[4] = new_cr4;
b8b6a50b
FB
492}
493
eaa728ee
FB
494#if defined(CONFIG_USER_ONLY)
495
7510454e 496int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
97b348e7 497 int is_write, int mmu_idx)
b8b6a50b 498{
7510454e
AF
499 X86CPU *cpu = X86_CPU(cs);
500 CPUX86State *env = &cpu->env;
501
eaa728ee
FB
502 /* user mode only emulation */
503 is_write &= 1;
504 env->cr[2] = addr;
505 env->error_code = (is_write << PG_ERROR_W_BIT);
506 env->error_code |= PG_ERROR_U_MASK;
27103424 507 cs->exception_index = EXCP0E_PAGE;
eaa728ee 508 return 1;
2c0262af
FB
509}
510
8d7b0fbb 511#else
891b38e4 512
eaa728ee
FB
513/* XXX: This value should match the one returned by CPUID
514 * and in exec.c */
eaa728ee 515# if defined(TARGET_X86_64)
2c90d794 516# define PHYS_ADDR_MASK 0xfffffff000LL
eaa728ee 517# else
2c90d794 518# define PHYS_ADDR_MASK 0xffffff000LL
eaa728ee 519# endif
eaa728ee
FB
520
521/* return value:
7510454e
AF
522 * -1 = cannot handle fault
523 * 0 = nothing more to do
524 * 1 = generate PF fault
525 */
526int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
97b348e7 527 int is_write1, int mmu_idx)
eaa728ee 528{
7510454e
AF
529 X86CPU *cpu = X86_CPU(cs);
530 CPUX86State *env = &cpu->env;
eaa728ee
FB
531 uint64_t ptep, pte;
532 target_ulong pde_addr, pte_addr;
d4c430a8 533 int error_code, is_dirty, prot, page_size, is_write, is_user;
a8170e5e 534 hwaddr paddr;
eaa728ee
FB
535 uint32_t page_offset;
536 target_ulong vaddr, virt_addr;
537
538 is_user = mmu_idx == MMU_USER_IDX;
539#if defined(DEBUG_MMU)
7510454e 540 printf("MMU fault: addr=%" VADDR_PRIx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
eaa728ee
FB
541 addr, is_write1, is_user, env->eip);
542#endif
543 is_write = is_write1 & 1;
544
545 if (!(env->cr[0] & CR0_PG_MASK)) {
546 pte = addr;
33dfdb56
AG
547#ifdef TARGET_X86_64
548 if (!(env->hflags & HF_LMA_MASK)) {
549 /* Without long mode we can only address 32bits in real mode */
550 pte = (uint32_t)pte;
551 }
552#endif
eaa728ee
FB
553 virt_addr = addr & TARGET_PAGE_MASK;
554 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
555 page_size = 4096;
556 goto do_mapping;
557 }
558
559 if (env->cr[4] & CR4_PAE_MASK) {
560 uint64_t pde, pdpe;
561 target_ulong pdpe_addr;
2c0262af 562
eaa728ee
FB
563#ifdef TARGET_X86_64
564 if (env->hflags & HF_LMA_MASK) {
565 uint64_t pml4e_addr, pml4e;
566 int32_t sext;
567
568 /* test virtual address sign extension */
569 sext = (int64_t)addr >> 47;
570 if (sext != 0 && sext != -1) {
571 env->error_code = 0;
27103424 572 cs->exception_index = EXCP0D_GPF;
eaa728ee
FB
573 return 1;
574 }
0573fbfc 575
eaa728ee
FB
576 pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
577 env->a20_mask;
2c17449b 578 pml4e = ldq_phys(cs->as, pml4e_addr);
eaa728ee
FB
579 if (!(pml4e & PG_PRESENT_MASK)) {
580 error_code = 0;
581 goto do_fault;
582 }
583 if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {
584 error_code = PG_ERROR_RSVD_MASK;
585 goto do_fault;
586 }
587 if (!(pml4e & PG_ACCESSED_MASK)) {
588 pml4e |= PG_ACCESSED_MASK;
2198a121 589 stl_phys_notdirty(cs->as, pml4e_addr, pml4e);
eaa728ee
FB
590 }
591 ptep = pml4e ^ PG_NX_MASK;
592 pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
593 env->a20_mask;
2c17449b 594 pdpe = ldq_phys(cs->as, pdpe_addr);
eaa728ee
FB
595 if (!(pdpe & PG_PRESENT_MASK)) {
596 error_code = 0;
597 goto do_fault;
598 }
599 if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {
600 error_code = PG_ERROR_RSVD_MASK;
601 goto do_fault;
602 }
603 ptep &= pdpe ^ PG_NX_MASK;
604 if (!(pdpe & PG_ACCESSED_MASK)) {
605 pdpe |= PG_ACCESSED_MASK;
2198a121 606 stl_phys_notdirty(cs->as, pdpe_addr, pdpe);
eaa728ee
FB
607 }
608 } else
609#endif
610 {
611 /* XXX: load them when cr3 is loaded ? */
612 pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
613 env->a20_mask;
2c17449b 614 pdpe = ldq_phys(cs->as, pdpe_addr);
eaa728ee
FB
615 if (!(pdpe & PG_PRESENT_MASK)) {
616 error_code = 0;
617 goto do_fault;
618 }
619 ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
7e84c249 620 }
7e84c249 621
eaa728ee
FB
622 pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
623 env->a20_mask;
2c17449b 624 pde = ldq_phys(cs->as, pde_addr);
eaa728ee
FB
625 if (!(pde & PG_PRESENT_MASK)) {
626 error_code = 0;
627 goto do_fault;
628 }
629 if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {
630 error_code = PG_ERROR_RSVD_MASK;
631 goto do_fault;
632 }
633 ptep &= pde ^ PG_NX_MASK;
634 if (pde & PG_PSE_MASK) {
635 /* 2 MB page */
636 page_size = 2048 * 1024;
00cc3e1d
PB
637 pte_addr = pde_addr;
638 pte = pde;
eaa728ee
FB
639 } else {
640 /* 4 KB page */
641 if (!(pde & PG_ACCESSED_MASK)) {
642 pde |= PG_ACCESSED_MASK;
2198a121 643 stl_phys_notdirty(cs->as, pde_addr, pde);
eaa728ee
FB
644 }
645 pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
646 env->a20_mask;
2c17449b 647 pte = ldq_phys(cs->as, pte_addr);
eaa728ee
FB
648 if (!(pte & PG_PRESENT_MASK)) {
649 error_code = 0;
650 goto do_fault;
651 }
652 if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {
653 error_code = PG_ERROR_RSVD_MASK;
654 goto do_fault;
655 }
656 /* combine pde and pte nx, user and rw protections */
657 ptep &= pte ^ PG_NX_MASK;
00cc3e1d
PB
658 page_size = 4096;
659 }
660
661 ptep ^= PG_NX_MASK;
2c0262af 662 } else {
eaa728ee
FB
663 uint32_t pde;
664
665 /* page directory entry */
666 pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
667 env->a20_mask;
fdfba1a2 668 pde = ldl_phys(cs->as, pde_addr);
eaa728ee
FB
669 if (!(pde & PG_PRESENT_MASK)) {
670 error_code = 0;
671 goto do_fault;
672 }
673 /* if PSE bit is set, then we use a 4MB page */
674 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
675 page_size = 4096 * 1024;
487cad88
PB
676 ptep = pde;
677 pte_addr = pde_addr;
678 pte = pde;
eaa728ee
FB
679 } else {
680 if (!(pde & PG_ACCESSED_MASK)) {
681 pde |= PG_ACCESSED_MASK;
2198a121 682 stl_phys_notdirty(cs->as, pde_addr, pde);
eaa728ee 683 }
891b38e4 684
eaa728ee
FB
685 /* page directory entry */
686 pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
687 env->a20_mask;
fdfba1a2 688 pte = ldl_phys(cs->as, pte_addr);
eaa728ee
FB
689 if (!(pte & PG_PRESENT_MASK)) {
690 error_code = 0;
691 goto do_fault;
8e682019 692 }
eaa728ee
FB
693 /* combine pde and pte user and rw protections */
694 ptep = pte & pde;
487cad88
PB
695 page_size = 4096;
696 }
7c822560 697 }
487cad88 698
7c822560
PB
699 if ((ptep & PG_NX_MASK) && is_write1 == 2) {
700 goto do_fault_protect;
701 }
702 switch (mmu_idx) {
703 case MMU_USER_IDX:
704 if (!(ptep & PG_USER_MASK)) {
705 goto do_fault_protect;
706 }
707 if (is_write && !(ptep & PG_RW_MASK)) {
708 goto do_fault_protect;
709 }
710 break;
487cad88 711
7c822560
PB
712 case MMU_KSMAP_IDX:
713 if (is_write1 != 2 && (ptep & PG_USER_MASK)) {
714 goto do_fault_protect;
2c0262af 715 }
7c822560
PB
716 /* fall through */
717 case MMU_KNOSMAP_IDX:
718 if (is_write1 == 2 && (env->cr[4] & CR4_SMEP_MASK) &&
719 (ptep & PG_USER_MASK)) {
720 goto do_fault_protect;
721 }
722 if ((env->cr[0] & CR0_WP_MASK) &&
723 is_write && !(ptep & PG_RW_MASK)) {
724 goto do_fault_protect;
487cad88 725 }
7c822560
PB
726 break;
727
728 default: /* cannot happen */
729 break;
730 }
731 is_dirty = is_write && !(pte & PG_DIRTY_MASK);
732 if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
733 pte |= PG_ACCESSED_MASK;
734 if (is_dirty) {
735 pte |= PG_DIRTY_MASK;
736 }
737 stl_phys_notdirty(cs->as, pte_addr, pte);
2c0262af 738 }
7c822560
PB
739 /* align to page_size */
740 pte &= ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);
741 virt_addr = addr & ~(page_size - 1);
742
eaa728ee
FB
743 /* the page can be put in the TLB */
744 prot = PAGE_READ;
745 if (!(ptep & PG_NX_MASK))
746 prot |= PAGE_EXEC;
747 if (pte & PG_DIRTY_MASK) {
748 /* only set write access if already dirty... otherwise wait
749 for dirty access */
750 if (is_user) {
751 if (ptep & PG_RW_MASK)
752 prot |= PAGE_WRITE;
753 } else {
754 if (!(env->cr[0] & CR0_WP_MASK) ||
755 (ptep & PG_RW_MASK))
756 prot |= PAGE_WRITE;
8e682019 757 }
891b38e4 758 }
eaa728ee
FB
759 do_mapping:
760 pte = pte & env->a20_mask;
761
762 /* Even if 4MB pages, we map only one 4KB page in the cache to
763 avoid filling it too fast */
764 page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
765 paddr = (pte & TARGET_PAGE_MASK) + page_offset;
766 vaddr = virt_addr + page_offset;
767
0c591eb0 768 tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, page_size);
d4c430a8 769 return 0;
eaa728ee
FB
770 do_fault_protect:
771 error_code = PG_ERROR_P_MASK;
772 do_fault:
773 error_code |= (is_write << PG_ERROR_W_BIT);
774 if (is_user)
775 error_code |= PG_ERROR_U_MASK;
776 if (is_write1 == 2 &&
a9321a4d
PA
777 (((env->efer & MSR_EFER_NXE) &&
778 (env->cr[4] & CR4_PAE_MASK)) ||
779 (env->cr[4] & CR4_SMEP_MASK)))
eaa728ee 780 error_code |= PG_ERROR_I_D_MASK;
872929aa
FB
781 if (env->intercept_exceptions & (1 << EXCP0E_PAGE)) {
782 /* cr2 is not modified in case of exceptions */
f606604f
EI
783 stq_phys(cs->as,
784 env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2),
872929aa 785 addr);
eaa728ee
FB
786 } else {
787 env->cr[2] = addr;
2c0262af 788 }
eaa728ee 789 env->error_code = error_code;
27103424 790 cs->exception_index = EXCP0E_PAGE;
eaa728ee 791 return 1;
14ce26e7
FB
792}
793
00b941e5 794hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
14ce26e7 795{
00b941e5
AF
796 X86CPU *cpu = X86_CPU(cs);
797 CPUX86State *env = &cpu->env;
eaa728ee
FB
798 target_ulong pde_addr, pte_addr;
799 uint64_t pte;
a8170e5e 800 hwaddr paddr;
eaa728ee
FB
801 uint32_t page_offset;
802 int page_size;
14ce26e7 803
f2f8560c
PB
804 if (!(env->cr[0] & CR0_PG_MASK)) {
805 pte = addr & env->a20_mask;
806 page_size = 4096;
807 } else if (env->cr[4] & CR4_PAE_MASK) {
eaa728ee
FB
808 target_ulong pdpe_addr;
809 uint64_t pde, pdpe;
14ce26e7 810
eaa728ee
FB
811#ifdef TARGET_X86_64
812 if (env->hflags & HF_LMA_MASK) {
813 uint64_t pml4e_addr, pml4e;
814 int32_t sext;
815
816 /* test virtual address sign extension */
817 sext = (int64_t)addr >> 47;
818 if (sext != 0 && sext != -1)
819 return -1;
820
821 pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
822 env->a20_mask;
2c17449b 823 pml4e = ldq_phys(cs->as, pml4e_addr);
eaa728ee
FB
824 if (!(pml4e & PG_PRESENT_MASK))
825 return -1;
826
3f2cbf0d
JK
827 pdpe_addr = ((pml4e & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) +
828 (((addr >> 30) & 0x1ff) << 3)) & env->a20_mask;
2c17449b 829 pdpe = ldq_phys(cs->as, pdpe_addr);
eaa728ee
FB
830 if (!(pdpe & PG_PRESENT_MASK))
831 return -1;
c8c14bcb
LC
832
833 if (pdpe & PG_PSE_MASK) {
834 page_size = 1024 * 1024 * 1024;
835 pte = pdpe & ~( (page_size - 1) & ~0xfff);
836 pte &= ~(PG_NX_MASK | PG_HI_USER_MASK);
837 goto out;
838 }
839
eaa728ee
FB
840 } else
841#endif
842 {
843 pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
844 env->a20_mask;
2c17449b 845 pdpe = ldq_phys(cs->as, pdpe_addr);
eaa728ee
FB
846 if (!(pdpe & PG_PRESENT_MASK))
847 return -1;
14ce26e7 848 }
14ce26e7 849
3f2cbf0d
JK
850 pde_addr = ((pdpe & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) +
851 (((addr >> 21) & 0x1ff) << 3)) & env->a20_mask;
2c17449b 852 pde = ldq_phys(cs->as, pde_addr);
eaa728ee
FB
853 if (!(pde & PG_PRESENT_MASK)) {
854 return -1;
855 }
856 if (pde & PG_PSE_MASK) {
857 /* 2 MB page */
858 page_size = 2048 * 1024;
859 pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
860 } else {
861 /* 4 KB page */
3f2cbf0d
JK
862 pte_addr = ((pde & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) +
863 (((addr >> 12) & 0x1ff) << 3)) & env->a20_mask;
eaa728ee 864 page_size = 4096;
2c17449b 865 pte = ldq_phys(cs->as, pte_addr);
eaa728ee 866 }
3f2cbf0d 867 pte &= ~(PG_NX_MASK | PG_HI_USER_MASK);
ca1c9e15
AL
868 if (!(pte & PG_PRESENT_MASK))
869 return -1;
14ce26e7 870 } else {
eaa728ee 871 uint32_t pde;
3b46e624 872
f2f8560c
PB
873 /* page directory entry */
874 pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
fdfba1a2 875 pde = ldl_phys(cs->as, pde_addr);
f2f8560c
PB
876 if (!(pde & PG_PRESENT_MASK))
877 return -1;
878 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
879 pte = pde & ~0x003ff000; /* align to 4MB */
880 page_size = 4096 * 1024;
eaa728ee
FB
881 } else {
882 /* page directory entry */
f2f8560c 883 pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
fdfba1a2 884 pte = ldl_phys(cs->as, pte_addr);
f2f8560c 885 if (!(pte & PG_PRESENT_MASK))
eaa728ee 886 return -1;
f2f8560c 887 page_size = 4096;
eaa728ee
FB
888 }
889 pte = pte & env->a20_mask;
14ce26e7 890 }
14ce26e7 891
c8c14bcb
LC
892#ifdef TARGET_X86_64
893out:
894#endif
eaa728ee
FB
895 page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
896 paddr = (pte & TARGET_PAGE_MASK) + page_offset;
897 return paddr;
3b21e03e 898}
01df040b 899
317ac620 900void hw_breakpoint_insert(CPUX86State *env, int index)
01df040b 901{
75a34036 902 CPUState *cs = CPU(x86_env_get_cpu(env));
1cc21a18 903 int type = 0, err = 0;
01df040b
AL
904
905 switch (hw_breakpoint_type(env->dr[7], index)) {
428065ce 906 case DR7_TYPE_BP_INST:
5902564a 907 if (hw_breakpoint_enabled(env->dr[7], index)) {
b3310ab3 908 err = cpu_breakpoint_insert(cs, env->dr[index], BP_CPU,
01df040b 909 &env->cpu_breakpoint[index]);
5902564a 910 }
01df040b 911 break;
428065ce 912 case DR7_TYPE_DATA_WR:
01df040b 913 type = BP_CPU | BP_MEM_WRITE;
1cc21a18 914 break;
428065ce 915 case DR7_TYPE_IO_RW:
1cc21a18 916 /* No support for I/O watchpoints yet */
01df040b 917 break;
428065ce 918 case DR7_TYPE_DATA_RW:
01df040b 919 type = BP_CPU | BP_MEM_ACCESS;
1cc21a18
LG
920 break;
921 }
922
923 if (type != 0) {
75a34036 924 err = cpu_watchpoint_insert(cs, env->dr[index],
01df040b
AL
925 hw_breakpoint_len(env->dr[7], index),
926 type, &env->cpu_watchpoint[index]);
01df040b 927 }
1cc21a18
LG
928
929 if (err) {
01df040b 930 env->cpu_breakpoint[index] = NULL;
1cc21a18 931 }
01df040b
AL
932}
933
317ac620 934void hw_breakpoint_remove(CPUX86State *env, int index)
01df040b 935{
75a34036
AF
936 CPUState *cs;
937
938 if (!env->cpu_breakpoint[index]) {
01df040b 939 return;
75a34036
AF
940 }
941 cs = CPU(x86_env_get_cpu(env));
01df040b 942 switch (hw_breakpoint_type(env->dr[7], index)) {
428065ce 943 case DR7_TYPE_BP_INST:
5902564a 944 if (hw_breakpoint_enabled(env->dr[7], index)) {
b3310ab3 945 cpu_breakpoint_remove_by_ref(cs, env->cpu_breakpoint[index]);
5902564a 946 }
01df040b 947 break;
428065ce
LG
948 case DR7_TYPE_DATA_WR:
949 case DR7_TYPE_DATA_RW:
75a34036 950 cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]);
01df040b 951 break;
428065ce 952 case DR7_TYPE_IO_RW:
01df040b
AL
953 /* No support for I/O watchpoints yet */
954 break;
955 }
956}
957
e175bce5 958bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update)
01df040b
AL
959{
960 target_ulong dr6;
e175bce5
LG
961 int reg;
962 bool hit_enabled = false;
01df040b
AL
963
964 dr6 = env->dr[6] & ~0xf;
428065ce 965 for (reg = 0; reg < DR7_MAX_BP; reg++) {
e175bce5
LG
966 bool bp_match = false;
967 bool wp_match = false;
968
969 switch (hw_breakpoint_type(env->dr[7], reg)) {
970 case DR7_TYPE_BP_INST:
971 if (env->dr[reg] == env->eip) {
972 bp_match = true;
973 }
974 break;
975 case DR7_TYPE_DATA_WR:
976 case DR7_TYPE_DATA_RW:
977 if (env->cpu_watchpoint[reg] &&
978 env->cpu_watchpoint[reg]->flags & BP_WATCHPOINT_HIT) {
979 wp_match = true;
980 }
981 break;
982 case DR7_TYPE_IO_RW:
983 break;
984 }
985 if (bp_match || wp_match) {
01df040b 986 dr6 |= 1 << reg;
5902564a 987 if (hw_breakpoint_enabled(env->dr[7], reg)) {
e175bce5 988 hit_enabled = true;
5902564a 989 }
01df040b
AL
990 }
991 }
e175bce5
LG
992
993 if (hit_enabled || force_dr6_update) {
01df040b 994 env->dr[6] = dr6;
e175bce5
LG
995 }
996
01df040b
AL
997 return hit_enabled;
998}
999
d65e9815 1000void breakpoint_handler(CPUX86State *env)
01df040b 1001{
ff4700b0 1002 CPUState *cs = CPU(x86_env_get_cpu(env));
01df040b
AL
1003 CPUBreakpoint *bp;
1004
ff4700b0
AF
1005 if (cs->watchpoint_hit) {
1006 if (cs->watchpoint_hit->flags & BP_CPU) {
1007 cs->watchpoint_hit = NULL;
e175bce5 1008 if (check_hw_breakpoints(env, false)) {
77b2bc2c 1009 raise_exception(env, EXCP01_DB);
e175bce5 1010 } else {
0ea8cb88 1011 cpu_resume_from_signal(cs, NULL);
e175bce5 1012 }
01df040b
AL
1013 }
1014 } else {
f0c3c505 1015 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
01df040b
AL
1016 if (bp->pc == env->eip) {
1017 if (bp->flags & BP_CPU) {
e175bce5 1018 check_hw_breakpoints(env, true);
77b2bc2c 1019 raise_exception(env, EXCP01_DB);
01df040b
AL
1020 }
1021 break;
1022 }
f0c3c505 1023 }
01df040b 1024 }
01df040b 1025}
79c4f6b0 1026
d5bfda33
JK
1027typedef struct MCEInjectionParams {
1028 Monitor *mon;
55e5c285 1029 X86CPU *cpu;
d5bfda33
JK
1030 int bank;
1031 uint64_t status;
1032 uint64_t mcg_status;
1033 uint64_t addr;
1034 uint64_t misc;
1035 int flags;
1036} MCEInjectionParams;
1037
1038static void do_inject_x86_mce(void *data)
79c4f6b0 1039{
d5bfda33 1040 MCEInjectionParams *params = data;
55e5c285
AF
1041 CPUX86State *cenv = &params->cpu->env;
1042 CPUState *cpu = CPU(params->cpu);
d5bfda33
JK
1043 uint64_t *banks = cenv->mce_banks + 4 * params->bank;
1044
cb446eca 1045 cpu_synchronize_state(cpu);
316378e4 1046
747461c7
JK
1047 /*
1048 * If there is an MCE exception being processed, ignore this SRAO MCE
1049 * unless unconditional injection was requested.
1050 */
d5bfda33
JK
1051 if (!(params->flags & MCE_INJECT_UNCOND_AO)
1052 && !(params->status & MCI_STATUS_AR)
747461c7
JK
1053 && (cenv->mcg_status & MCG_STATUS_MCIP)) {
1054 return;
1055 }
d5bfda33
JK
1056
1057 if (params->status & MCI_STATUS_UC) {
316378e4
JK
1058 /*
1059 * if MSR_MCG_CTL is not all 1s, the uncorrected error
1060 * reporting is disabled
1061 */
d5bfda33
JK
1062 if ((cenv->mcg_cap & MCG_CTL_P) && cenv->mcg_ctl != ~(uint64_t)0) {
1063 monitor_printf(params->mon,
316378e4 1064 "CPU %d: Uncorrected error reporting disabled\n",
55e5c285 1065 cpu->cpu_index);
316378e4
JK
1066 return;
1067 }
1068
1069 /*
1070 * if MSR_MCi_CTL is not all 1s, the uncorrected error
1071 * reporting is disabled for the bank
1072 */
1073 if (banks[0] != ~(uint64_t)0) {
d5bfda33
JK
1074 monitor_printf(params->mon,
1075 "CPU %d: Uncorrected error reporting disabled for"
1076 " bank %d\n",
55e5c285 1077 cpu->cpu_index, params->bank);
316378e4
JK
1078 return;
1079 }
1080
79c4f6b0
HY
1081 if ((cenv->mcg_status & MCG_STATUS_MCIP) ||
1082 !(cenv->cr[4] & CR4_MCE_MASK)) {
d5bfda33
JK
1083 monitor_printf(params->mon,
1084 "CPU %d: Previous MCE still in progress, raising"
1085 " triple fault\n",
55e5c285 1086 cpu->cpu_index);
79c4f6b0
HY
1087 qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
1088 qemu_system_reset_request();
1089 return;
1090 }
2fa11da0 1091 if (banks[1] & MCI_STATUS_VAL) {
d5bfda33 1092 params->status |= MCI_STATUS_OVER;
2fa11da0 1093 }
d5bfda33
JK
1094 banks[2] = params->addr;
1095 banks[3] = params->misc;
1096 cenv->mcg_status = params->mcg_status;
1097 banks[1] = params->status;
c3affe56 1098 cpu_interrupt(cpu, CPU_INTERRUPT_MCE);
79c4f6b0
HY
1099 } else if (!(banks[1] & MCI_STATUS_VAL)
1100 || !(banks[1] & MCI_STATUS_UC)) {
2fa11da0 1101 if (banks[1] & MCI_STATUS_VAL) {
d5bfda33 1102 params->status |= MCI_STATUS_OVER;
2fa11da0 1103 }
d5bfda33
JK
1104 banks[2] = params->addr;
1105 banks[3] = params->misc;
1106 banks[1] = params->status;
2fa11da0 1107 } else {
79c4f6b0 1108 banks[1] |= MCI_STATUS_OVER;
2fa11da0 1109 }
79c4f6b0 1110}
b3cd24e0 1111
8c5cf3b6 1112void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
316378e4 1113 uint64_t status, uint64_t mcg_status, uint64_t addr,
747461c7 1114 uint64_t misc, int flags)
b3cd24e0 1115{
182735ef 1116 CPUState *cs = CPU(cpu);
8c5cf3b6 1117 CPUX86State *cenv = &cpu->env;
d5bfda33
JK
1118 MCEInjectionParams params = {
1119 .mon = mon,
55e5c285 1120 .cpu = cpu,
d5bfda33
JK
1121 .bank = bank,
1122 .status = status,
1123 .mcg_status = mcg_status,
1124 .addr = addr,
1125 .misc = misc,
1126 .flags = flags,
1127 };
b3cd24e0
JD
1128 unsigned bank_num = cenv->mcg_cap & 0xff;
1129
316378e4
JK
1130 if (!cenv->mcg_cap) {
1131 monitor_printf(mon, "MCE injection not supported\n");
b3cd24e0
JD
1132 return;
1133 }
316378e4
JK
1134 if (bank >= bank_num) {
1135 monitor_printf(mon, "Invalid MCE bank number\n");
1136 return;
1137 }
1138 if (!(status & MCI_STATUS_VAL)) {
1139 monitor_printf(mon, "Invalid MCE status code\n");
1140 return;
1141 }
747461c7
JK
1142 if ((flags & MCE_INJECT_BROADCAST)
1143 && !cpu_x86_support_mca_broadcast(cenv)) {
316378e4
JK
1144 monitor_printf(mon, "Guest CPU does not support MCA broadcast\n");
1145 return;
2bd3e04c
JD
1146 }
1147
182735ef 1148 run_on_cpu(cs, do_inject_x86_mce, &params);
c34d440a 1149 if (flags & MCE_INJECT_BROADCAST) {
182735ef
AF
1150 CPUState *other_cs;
1151
c34d440a
JK
1152 params.bank = 1;
1153 params.status = MCI_STATUS_VAL | MCI_STATUS_UC;
1154 params.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV;
1155 params.addr = 0;
1156 params.misc = 0;
bdc44640 1157 CPU_FOREACH(other_cs) {
182735ef 1158 if (other_cs == cs) {
c34d440a 1159 continue;
31ce5e0c 1160 }
182735ef
AF
1161 params.cpu = X86_CPU(other_cs);
1162 run_on_cpu(other_cs, do_inject_x86_mce, &params);
31ce5e0c 1163 }
b3cd24e0
JD
1164 }
1165}
d362e757 1166
317ac620 1167void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
d362e757 1168{
02e51483 1169 X86CPU *cpu = x86_env_get_cpu(env);
93afeade 1170 CPUState *cs = CPU(cpu);
02e51483 1171
d362e757
JK
1172 if (kvm_enabled()) {
1173 env->tpr_access_type = access;
1174
93afeade 1175 cpu_interrupt(cs, CPU_INTERRUPT_TPR);
d362e757 1176 } else {
3f38f309 1177 cpu_restore_state(cs, cs->mem_io_pc);
d362e757 1178
02e51483 1179 apic_handle_tpr_access_report(cpu->apic_state, env->eip, access);
d362e757
JK
1180 }
1181}
74ce674f 1182#endif /* !CONFIG_USER_ONLY */
6fd805e1 1183
84273177
JK
1184int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
1185 target_ulong *base, unsigned int *limit,
1186 unsigned int *flags)
1187{
f17ec444
AF
1188 X86CPU *cpu = x86_env_get_cpu(env);
1189 CPUState *cs = CPU(cpu);
84273177
JK
1190 SegmentCache *dt;
1191 target_ulong ptr;
1192 uint32_t e1, e2;
1193 int index;
1194
1195 if (selector & 0x4)
1196 dt = &env->ldt;
1197 else
1198 dt = &env->gdt;
1199 index = selector & ~7;
1200 ptr = dt->base + index;
1201 if ((index + 7) > dt->limit
f17ec444
AF
1202 || cpu_memory_rw_debug(cs, ptr, (uint8_t *)&e1, sizeof(e1), 0) != 0
1203 || cpu_memory_rw_debug(cs, ptr+4, (uint8_t *)&e2, sizeof(e2), 0) != 0)
84273177
JK
1204 return 0;
1205
1206 *base = ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
1207 *limit = (e1 & 0xffff) | (e2 & 0x000f0000);
1208 if (e2 & DESC_G_MASK)
1209 *limit = (*limit << 12) | 0xfff;
1210 *flags = e2;
1211
1212 return 1;
1213}
1214
b09ea7d5 1215#if !defined(CONFIG_USER_ONLY)
232fc23b 1216void do_cpu_init(X86CPU *cpu)
b09ea7d5 1217{
259186a7 1218 CPUState *cs = CPU(cpu);
232fc23b 1219 CPUX86State *env = &cpu->env;
43175fa9 1220 CPUX86State *save = g_new(CPUX86State, 1);
259186a7 1221 int sipi = cs->interrupt_request & CPU_INTERRUPT_SIPI;
43175fa9
PB
1222
1223 *save = *env;
ebda377f 1224
259186a7
AF
1225 cpu_reset(cs);
1226 cs->interrupt_request = sipi;
43175fa9
PB
1227 memcpy(&env->start_init_save, &save->start_init_save,
1228 offsetof(CPUX86State, end_init_save) -
1229 offsetof(CPUX86State, start_init_save));
1230 g_free(save);
1231
e0723c45
PB
1232 if (kvm_enabled()) {
1233 kvm_arch_do_init_vcpu(cpu);
1234 }
02e51483 1235 apic_init_reset(cpu->apic_state);
b09ea7d5
GN
1236}
1237
232fc23b 1238void do_cpu_sipi(X86CPU *cpu)
b09ea7d5 1239{
02e51483 1240 apic_sipi(cpu->apic_state);
b09ea7d5
GN
1241}
1242#else
232fc23b 1243void do_cpu_init(X86CPU *cpu)
b09ea7d5
GN
1244{
1245}
232fc23b 1246void do_cpu_sipi(X86CPU *cpu)
b09ea7d5
GN
1247{
1248}
1249#endif