File:  [Qemu by Fabrice Bellard] / qemu / target-i386 / helper.c
Revision 1.1.1.15 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:02:51 2018 UTC (3 years, 9 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1000, qemu0151, HEAD
qemu 0.15.1

    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: void raise_exception_env(int exception_index, CPUState *env);
 1031: 
 1032: static void breakpoint_handler(CPUState *env)
 1033: {
 1034:     CPUBreakpoint *bp;
 1035: 
 1036:     if (env->watchpoint_hit) {
 1037:         if (env->watchpoint_hit->flags & BP_CPU) {
 1038:             env->watchpoint_hit = NULL;
 1039:             if (check_hw_breakpoints(env, 0))
 1040:                 raise_exception_env(EXCP01_DB, env);
 1041:             else
 1042:                 cpu_resume_from_signal(env, NULL);
 1043:         }
 1044:     } else {
 1045:         QTAILQ_FOREACH(bp, &env->breakpoints, entry)
 1046:             if (bp->pc == env->eip) {
 1047:                 if (bp->flags & BP_CPU) {
 1048:                     check_hw_breakpoints(env, 1);
 1049:                     raise_exception_env(EXCP01_DB, env);
 1050:                 }
 1051:                 break;
 1052:             }
 1053:     }
 1054:     if (prev_debug_excp_handler)
 1055:         prev_debug_excp_handler(env);
 1056: }
 1057: 
 1058: typedef struct MCEInjectionParams {
 1059:     Monitor *mon;
 1060:     CPUState *env;
 1061:     int bank;
 1062:     uint64_t status;
 1063:     uint64_t mcg_status;
 1064:     uint64_t addr;
 1065:     uint64_t misc;
 1066:     int flags;
 1067: } MCEInjectionParams;
 1068: 
 1069: static void do_inject_x86_mce(void *data)
 1070: {
 1071:     MCEInjectionParams *params = data;
 1072:     CPUState *cenv = params->env;
 1073:     uint64_t *banks = cenv->mce_banks + 4 * params->bank;
 1074: 
 1075:     cpu_synchronize_state(cenv);
 1076: 
 1077:     /*
 1078:      * If there is an MCE exception being processed, ignore this SRAO MCE
 1079:      * unless unconditional injection was requested.
 1080:      */
 1081:     if (!(params->flags & MCE_INJECT_UNCOND_AO)
 1082:         && !(params->status & MCI_STATUS_AR)
 1083:         && (cenv->mcg_status & MCG_STATUS_MCIP)) {
 1084:         return;
 1085:     }
 1086: 
 1087:     if (params->status & MCI_STATUS_UC) {
 1088:         /*
 1089:          * if MSR_MCG_CTL is not all 1s, the uncorrected error
 1090:          * reporting is disabled
 1091:          */
 1092:         if ((cenv->mcg_cap & MCG_CTL_P) && cenv->mcg_ctl != ~(uint64_t)0) {
 1093:             monitor_printf(params->mon,
 1094:                            "CPU %d: Uncorrected error reporting disabled\n",
 1095:                            cenv->cpu_index);
 1096:             return;
 1097:         }
 1098: 
 1099:         /*
 1100:          * if MSR_MCi_CTL is not all 1s, the uncorrected error
 1101:          * reporting is disabled for the bank
 1102:          */
 1103:         if (banks[0] != ~(uint64_t)0) {
 1104:             monitor_printf(params->mon,
 1105:                            "CPU %d: Uncorrected error reporting disabled for"
 1106:                            " bank %d\n",
 1107:                            cenv->cpu_index, params->bank);
 1108:             return;
 1109:         }
 1110: 
 1111:         if ((cenv->mcg_status & MCG_STATUS_MCIP) ||
 1112:             !(cenv->cr[4] & CR4_MCE_MASK)) {
 1113:             monitor_printf(params->mon,
 1114:                            "CPU %d: Previous MCE still in progress, raising"
 1115:                            " triple fault\n",
 1116:                            cenv->cpu_index);
 1117:             qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
 1118:             qemu_system_reset_request();
 1119:             return;
 1120:         }
 1121:         if (banks[1] & MCI_STATUS_VAL) {
 1122:             params->status |= MCI_STATUS_OVER;
 1123:         }
 1124:         banks[2] = params->addr;
 1125:         banks[3] = params->misc;
 1126:         cenv->mcg_status = params->mcg_status;
 1127:         banks[1] = params->status;
 1128:         cpu_interrupt(cenv, CPU_INTERRUPT_MCE);
 1129:     } else if (!(banks[1] & MCI_STATUS_VAL)
 1130:                || !(banks[1] & MCI_STATUS_UC)) {
 1131:         if (banks[1] & MCI_STATUS_VAL) {
 1132:             params->status |= MCI_STATUS_OVER;
 1133:         }
 1134:         banks[2] = params->addr;
 1135:         banks[3] = params->misc;
 1136:         banks[1] = params->status;
 1137:     } else {
 1138:         banks[1] |= MCI_STATUS_OVER;
 1139:     }
 1140: }
 1141: 
 1142: void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
 1143:                         uint64_t status, uint64_t mcg_status, uint64_t addr,
 1144:                         uint64_t misc, int flags)
 1145: {
 1146:     MCEInjectionParams params = {
 1147:         .mon = mon,
 1148:         .env = cenv,
 1149:         .bank = bank,
 1150:         .status = status,
 1151:         .mcg_status = mcg_status,
 1152:         .addr = addr,
 1153:         .misc = misc,
 1154:         .flags = flags,
 1155:     };
 1156:     unsigned bank_num = cenv->mcg_cap & 0xff;
 1157:     CPUState *env;
 1158: 
 1159:     if (!cenv->mcg_cap) {
 1160:         monitor_printf(mon, "MCE injection not supported\n");
 1161:         return;
 1162:     }
 1163:     if (bank >= bank_num) {
 1164:         monitor_printf(mon, "Invalid MCE bank number\n");
 1165:         return;
 1166:     }
 1167:     if (!(status & MCI_STATUS_VAL)) {
 1168:         monitor_printf(mon, "Invalid MCE status code\n");
 1169:         return;
 1170:     }
 1171:     if ((flags & MCE_INJECT_BROADCAST)
 1172:         && !cpu_x86_support_mca_broadcast(cenv)) {
 1173:         monitor_printf(mon, "Guest CPU does not support MCA broadcast\n");
 1174:         return;
 1175:     }
 1176: 
 1177:     run_on_cpu(cenv, do_inject_x86_mce, &params);
 1178:     if (flags & MCE_INJECT_BROADCAST) {
 1179:         params.bank = 1;
 1180:         params.status = MCI_STATUS_VAL | MCI_STATUS_UC;
 1181:         params.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV;
 1182:         params.addr = 0;
 1183:         params.misc = 0;
 1184:         for (env = first_cpu; env != NULL; env = env->next_cpu) {
 1185:             if (cenv == env) {
 1186:                 continue;
 1187:             }
 1188:             params.env = env;
 1189:             run_on_cpu(cenv, do_inject_x86_mce, &params);
 1190:         }
 1191:     }
 1192: }
 1193: #endif /* !CONFIG_USER_ONLY */
 1194: 
 1195: static void mce_init(CPUX86State *cenv)
 1196: {
 1197:     unsigned int bank;
 1198: 
 1199:     if (((cenv->cpuid_version >> 8) & 0xf) >= 6
 1200:         && (cenv->cpuid_features & (CPUID_MCE | CPUID_MCA)) ==
 1201:             (CPUID_MCE | CPUID_MCA)) {
 1202:         cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF;
 1203:         cenv->mcg_ctl = ~(uint64_t)0;
 1204:         for (bank = 0; bank < MCE_BANKS_DEF; bank++) {
 1205:             cenv->mce_banks[bank * 4] = ~(uint64_t)0;
 1206:         }
 1207:     }
 1208: }
 1209: 
 1210: int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
 1211:                             target_ulong *base, unsigned int *limit,
 1212:                             unsigned int *flags)
 1213: {
 1214:     SegmentCache *dt;
 1215:     target_ulong ptr;
 1216:     uint32_t e1, e2;
 1217:     int index;
 1218: 
 1219:     if (selector & 0x4)
 1220:         dt = &env->ldt;
 1221:     else
 1222:         dt = &env->gdt;
 1223:     index = selector & ~7;
 1224:     ptr = dt->base + index;
 1225:     if ((index + 7) > dt->limit
 1226:         || cpu_memory_rw_debug(env, ptr, (uint8_t *)&e1, sizeof(e1), 0) != 0
 1227:         || cpu_memory_rw_debug(env, ptr+4, (uint8_t *)&e2, sizeof(e2), 0) != 0)
 1228:         return 0;
 1229: 
 1230:     *base = ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
 1231:     *limit = (e1 & 0xffff) | (e2 & 0x000f0000);
 1232:     if (e2 & DESC_G_MASK)
 1233:         *limit = (*limit << 12) | 0xfff;
 1234:     *flags = e2;
 1235: 
 1236:     return 1;
 1237: }
 1238: 
 1239: CPUX86State *cpu_x86_init(const char *cpu_model)
 1240: {
 1241:     CPUX86State *env;
 1242:     static int inited;
 1243: 
 1244:     env = qemu_mallocz(sizeof(CPUX86State));
 1245:     cpu_exec_init(env);
 1246:     env->cpu_model_str = cpu_model;
 1247: 
 1248:     /* init various static tables */
 1249:     if (!inited) {
 1250:         inited = 1;
 1251:         optimize_flags_init();
 1252: #ifndef CONFIG_USER_ONLY
 1253:         prev_debug_excp_handler =
 1254:             cpu_set_debug_excp_handler(breakpoint_handler);
 1255: #endif
 1256:     }
 1257:     if (cpu_x86_register(env, cpu_model) < 0) {
 1258:         cpu_x86_close(env);
 1259:         return NULL;
 1260:     }
 1261:     mce_init(env);
 1262: 
 1263:     qemu_init_vcpu(env);
 1264: 
 1265:     return env;
 1266: }
 1267: 
 1268: #if !defined(CONFIG_USER_ONLY)
 1269: void do_cpu_init(CPUState *env)
 1270: {
 1271:     int sipi = env->interrupt_request & CPU_INTERRUPT_SIPI;
 1272:     uint64_t pat = env->pat;
 1273: 
 1274:     cpu_reset(env);
 1275:     env->interrupt_request = sipi;
 1276:     env->pat = pat;
 1277:     apic_init_reset(env->apic_state);
 1278:     env->halted = !cpu_is_bsp(env);
 1279: }
 1280: 
 1281: void do_cpu_sipi(CPUState *env)
 1282: {
 1283:     apic_sipi(env->apic_state);
 1284: }
 1285: #else
 1286: void do_cpu_init(CPUState *env)
 1287: {
 1288: }
 1289: void do_cpu_sipi(CPUState *env)
 1290: {
 1291: }
 1292: #endif

unix.superglobalmegacorp.com