qemu/target-i386/helper.c
<<
>>
Prefs
   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 */
  34void 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
 107void cpu_x86_close(CPUX86State *env)
 108{
 109    qemu_free(env);
 110}
 111
 112/***********************************************************/
 113/* x86 debug */
 114
 115static 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
 170static void
 171cpu_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    }
 222done:
 223    cpu_fprintf(f, "\n");
 224}
 225
 226void 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
 416void 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
 434void 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 */
 477void 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
 488void 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
 510int 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*/
 537int 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
 827target_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
 921void 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
 949void 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
 968int 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
 990static CPUDebugExcpHandler *prev_debug_excp_handler;
 991
 992void raise_exception_env(int exception_index, CPUState *env);
 993
 994static 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... */
1021void qemu_system_reset_request(void);
1022
1023void 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
1075static 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
1089int 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
1118CPUX86State *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)
1148void 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
1157void do_cpu_sipi(CPUState *env)
1158{
1159    apic_sipi(env->apic_state);
1160}
1161#else
1162void do_cpu_init(CPUState *env)
1163{
1164}
1165void do_cpu_sipi(CPUState *env)
1166{
1167}
1168#endif
1169