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