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