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
  20#include "qemu/osdep.h"
  21#include "cpu.h"
  22#include "exec/exec-all.h"
  23#include "qemu/qemu-print.h"
  24#include "sysemu/kvm.h"
  25#include "kvm_i386.h"
  26#ifndef CONFIG_USER_ONLY
  27#include "sysemu/sysemu.h"
  28#include "sysemu/tcg.h"
  29#include "sysemu/hw_accel.h"
  30#include "monitor/monitor.h"
  31#include "hw/i386/apic_internal.h"
  32#endif
  33
  34void cpu_sync_bndcs_hflags(CPUX86State *env)
  35{
  36    uint32_t hflags = env->hflags;
  37    uint32_t hflags2 = env->hflags2;
  38    uint32_t bndcsr;
  39
  40    if ((hflags & HF_CPL_MASK) == 3) {
  41        bndcsr = env->bndcs_regs.cfgu;
  42    } else {
  43        bndcsr = env->msr_bndcfgs;
  44    }
  45
  46    if ((env->cr[4] & CR4_OSXSAVE_MASK)
  47        && (env->xcr0 & XSTATE_BNDCSR_MASK)
  48        && (bndcsr & BNDCFG_ENABLE)) {
  49        hflags |= HF_MPX_EN_MASK;
  50    } else {
  51        hflags &= ~HF_MPX_EN_MASK;
  52    }
  53
  54    if (bndcsr & BNDCFG_BNDPRESERVE) {
  55        hflags2 |= HF2_MPX_PR_MASK;
  56    } else {
  57        hflags2 &= ~HF2_MPX_PR_MASK;
  58    }
  59
  60    env->hflags = hflags;
  61    env->hflags2 = hflags2;
  62}
  63
  64static void cpu_x86_version(CPUX86State *env, int *family, int *model)
  65{
  66    int cpuver = env->cpuid_version;
  67
  68    if (family == NULL || model == NULL) {
  69        return;
  70    }
  71
  72    *family = (cpuver >> 8) & 0x0f;
  73    *model = ((cpuver >> 12) & 0xf0) + ((cpuver >> 4) & 0x0f);
  74}
  75
  76/* Broadcast MCA signal for processor version 06H_EH and above */
  77int cpu_x86_support_mca_broadcast(CPUX86State *env)
  78{
  79    int family = 0;
  80    int model = 0;
  81
  82    cpu_x86_version(env, &family, &model);
  83    if ((family == 6 && model >= 14) || family > 6) {
  84        return 1;
  85    }
  86
  87    return 0;
  88}
  89
  90/***********************************************************/
  91/* x86 debug */
  92
  93static const char *cc_op_str[CC_OP_NB] = {
  94    "DYNAMIC",
  95    "EFLAGS",
  96
  97    "MULB",
  98    "MULW",
  99    "MULL",
 100    "MULQ",
 101
 102    "ADDB",
 103    "ADDW",
 104    "ADDL",
 105    "ADDQ",
 106
 107    "ADCB",
 108    "ADCW",
 109    "ADCL",
 110    "ADCQ",
 111
 112    "SUBB",
 113    "SUBW",
 114    "SUBL",
 115    "SUBQ",
 116
 117    "SBBB",
 118    "SBBW",
 119    "SBBL",
 120    "SBBQ",
 121
 122    "LOGICB",
 123    "LOGICW",
 124    "LOGICL",
 125    "LOGICQ",
 126
 127    "INCB",
 128    "INCW",
 129    "INCL",
 130    "INCQ",
 131
 132    "DECB",
 133    "DECW",
 134    "DECL",
 135    "DECQ",
 136
 137    "SHLB",
 138    "SHLW",
 139    "SHLL",
 140    "SHLQ",
 141
 142    "SARB",
 143    "SARW",
 144    "SARL",
 145    "SARQ",
 146
 147    "BMILGB",
 148    "BMILGW",
 149    "BMILGL",
 150    "BMILGQ",
 151
 152    "ADCX",
 153    "ADOX",
 154    "ADCOX",
 155
 156    "CLR",
 157};
 158
 159static void
 160cpu_x86_dump_seg_cache(CPUX86State *env, FILE *f,
 161                       const char *name, struct SegmentCache *sc)
 162{
 163#ifdef TARGET_X86_64
 164    if (env->hflags & HF_CS64_MASK) {
 165        qemu_fprintf(f, "%-3s=%04x %016" PRIx64 " %08x %08x", name,
 166                     sc->selector, sc->base, sc->limit,
 167                     sc->flags & 0x00ffff00);
 168    } else
 169#endif
 170    {
 171        qemu_fprintf(f, "%-3s=%04x %08x %08x %08x", name, sc->selector,
 172                     (uint32_t)sc->base, sc->limit,
 173                     sc->flags & 0x00ffff00);
 174    }
 175
 176    if (!(env->hflags & HF_PE_MASK) || !(sc->flags & DESC_P_MASK))
 177        goto done;
 178
 179    qemu_fprintf(f, " DPL=%d ",
 180                 (sc->flags & DESC_DPL_MASK) >> DESC_DPL_SHIFT);
 181    if (sc->flags & DESC_S_MASK) {
 182        if (sc->flags & DESC_CS_MASK) {
 183            qemu_fprintf(f, (sc->flags & DESC_L_MASK) ? "CS64" :
 184                         ((sc->flags & DESC_B_MASK) ? "CS32" : "CS16"));
 185            qemu_fprintf(f, " [%c%c", (sc->flags & DESC_C_MASK) ? 'C' : '-',
 186                         (sc->flags & DESC_R_MASK) ? 'R' : '-');
 187        } else {
 188            qemu_fprintf(f, (sc->flags & DESC_B_MASK
 189                             || env->hflags & HF_LMA_MASK)
 190                         ? "DS  " : "DS16");
 191            qemu_fprintf(f, " [%c%c", (sc->flags & DESC_E_MASK) ? 'E' : '-',
 192                         (sc->flags & DESC_W_MASK) ? 'W' : '-');
 193        }
 194        qemu_fprintf(f, "%c]", (sc->flags & DESC_A_MASK) ? 'A' : '-');
 195    } else {
 196        static const char *sys_type_name[2][16] = {
 197            { /* 32 bit mode */
 198                "Reserved", "TSS16-avl", "LDT", "TSS16-busy",
 199                "CallGate16", "TaskGate", "IntGate16", "TrapGate16",
 200                "Reserved", "TSS32-avl", "Reserved", "TSS32-busy",
 201                "CallGate32", "Reserved", "IntGate32", "TrapGate32"
 202            },
 203            { /* 64 bit mode */
 204                "<hiword>", "Reserved", "LDT", "Reserved", "Reserved",
 205                "Reserved", "Reserved", "Reserved", "Reserved",
 206                "TSS64-avl", "Reserved", "TSS64-busy", "CallGate64",
 207                "Reserved", "IntGate64", "TrapGate64"
 208            }
 209        };
 210        qemu_fprintf(f, "%s",
 211                     sys_type_name[(env->hflags & HF_LMA_MASK) ? 1 : 0]
 212                     [(sc->flags & DESC_TYPE_MASK) >> DESC_TYPE_SHIFT]);
 213    }
 214done:
 215    qemu_fprintf(f, "\n");
 216}
 217
 218#ifndef CONFIG_USER_ONLY
 219
 220/* ARRAY_SIZE check is not required because
 221 * DeliveryMode(dm) has a size of 3 bit.
 222 */
 223static inline const char *dm2str(uint32_t dm)
 224{
 225    static const char *str[] = {
 226        "Fixed",
 227        "...",
 228        "SMI",
 229        "...",
 230        "NMI",
 231        "INIT",
 232        "...",
 233        "ExtINT"
 234    };
 235    return str[dm];
 236}
 237
 238static void dump_apic_lvt(const char *name, uint32_t lvt, bool is_timer)
 239{
 240    uint32_t dm = (lvt & APIC_LVT_DELIV_MOD) >> APIC_LVT_DELIV_MOD_SHIFT;
 241    qemu_printf("%s\t 0x%08x %s %-5s %-6s %-7s %-12s %-6s",
 242                name, lvt,
 243                lvt & APIC_LVT_INT_POLARITY ? "active-lo" : "active-hi",
 244                lvt & APIC_LVT_LEVEL_TRIGGER ? "level" : "edge",
 245                lvt & APIC_LVT_MASKED ? "masked" : "",
 246                lvt & APIC_LVT_DELIV_STS ? "pending" : "",
 247                !is_timer ?
 248                    "" : lvt & APIC_LVT_TIMER_PERIODIC ?
 249                            "periodic" : lvt & APIC_LVT_TIMER_TSCDEADLINE ?
 250                                            "tsc-deadline" : "one-shot",
 251                dm2str(dm));
 252    if (dm != APIC_DM_NMI) {
 253        qemu_printf(" (vec %u)\n", lvt & APIC_VECTOR_MASK);
 254    } else {
 255        qemu_printf("\n");
 256    }
 257}
 258
 259/* ARRAY_SIZE check is not required because
 260 * destination shorthand has a size of 2 bit.
 261 */
 262static inline const char *shorthand2str(uint32_t shorthand)
 263{
 264    const char *str[] = {
 265        "no-shorthand", "self", "all-self", "all"
 266    };
 267    return str[shorthand];
 268}
 269
 270static inline uint8_t divider_conf(uint32_t divide_conf)
 271{
 272    uint8_t divide_val = ((divide_conf & 0x8) >> 1) | (divide_conf & 0x3);
 273
 274    return divide_val == 7 ? 1 : 2 << divide_val;
 275}
 276
 277static inline void mask2str(char *str, uint32_t val, uint8_t size)
 278{
 279    while (size--) {
 280        *str++ = (val >> size) & 1 ? '1' : '0';
 281    }
 282    *str = 0;
 283}
 284
 285#define MAX_LOGICAL_APIC_ID_MASK_SIZE 16
 286
 287static void dump_apic_icr(APICCommonState *s, CPUX86State *env)
 288{
 289    uint32_t icr = s->icr[0], icr2 = s->icr[1];
 290    uint8_t dest_shorthand = \
 291        (icr & APIC_ICR_DEST_SHORT) >> APIC_ICR_DEST_SHORT_SHIFT;
 292    bool logical_mod = icr & APIC_ICR_DEST_MOD;
 293    char apic_id_str[MAX_LOGICAL_APIC_ID_MASK_SIZE + 1];
 294    uint32_t dest_field;
 295    bool x2apic;
 296
 297    qemu_printf("ICR\t 0x%08x %s %s %s %s\n",
 298                icr,
 299                logical_mod ? "logical" : "physical",
 300                icr & APIC_ICR_TRIGGER_MOD ? "level" : "edge",
 301                icr & APIC_ICR_LEVEL ? "assert" : "de-assert",
 302                shorthand2str(dest_shorthand));
 303
 304    qemu_printf("ICR2\t 0x%08x", icr2);
 305    if (dest_shorthand != 0) {
 306        qemu_printf("\n");
 307        return;
 308    }
 309    x2apic = env->features[FEAT_1_ECX] & CPUID_EXT_X2APIC;
 310    dest_field = x2apic ? icr2 : icr2 >> APIC_ICR_DEST_SHIFT;
 311
 312    if (!logical_mod) {
 313        if (x2apic) {
 314            qemu_printf(" cpu %u (X2APIC ID)\n", dest_field);
 315        } else {
 316            qemu_printf(" cpu %u (APIC ID)\n",
 317                        dest_field & APIC_LOGDEST_XAPIC_ID);
 318        }
 319        return;
 320    }
 321
 322    if (s->dest_mode == 0xf) { /* flat mode */
 323        mask2str(apic_id_str, icr2 >> APIC_ICR_DEST_SHIFT, 8);
 324        qemu_printf(" mask %s (APIC ID)\n", apic_id_str);
 325    } else if (s->dest_mode == 0) { /* cluster mode */
 326        if (x2apic) {
 327            mask2str(apic_id_str, dest_field & APIC_LOGDEST_X2APIC_ID, 16);
 328            qemu_printf(" cluster %u mask %s (X2APIC ID)\n",
 329                        dest_field >> APIC_LOGDEST_X2APIC_SHIFT, apic_id_str);
 330        } else {
 331            mask2str(apic_id_str, dest_field & APIC_LOGDEST_XAPIC_ID, 4);
 332            qemu_printf(" cluster %u mask %s (APIC ID)\n",
 333                        dest_field >> APIC_LOGDEST_XAPIC_SHIFT, apic_id_str);
 334        }
 335    }
 336}
 337
 338static void dump_apic_interrupt(const char *name, uint32_t *ireg_tab,
 339                                uint32_t *tmr_tab)
 340{
 341    int i, empty = true;
 342
 343    qemu_printf("%s\t ", name);
 344    for (i = 0; i < 256; i++) {
 345        if (apic_get_bit(ireg_tab, i)) {
 346            qemu_printf("%u%s ", i,
 347                        apic_get_bit(tmr_tab, i) ? "(level)" : "");
 348            empty = false;
 349        }
 350    }
 351    qemu_printf("%s\n", empty ? "(none)" : "");
 352}
 353
 354void x86_cpu_dump_local_apic_state(CPUState *cs, int flags)
 355{
 356    X86CPU *cpu = X86_CPU(cs);
 357    APICCommonState *s = APIC_COMMON(cpu->apic_state);
 358    if (!s) {
 359        qemu_printf("local apic state not available\n");
 360        return;
 361    }
 362    uint32_t *lvt = s->lvt;
 363
 364    qemu_printf("dumping local APIC state for CPU %-2u\n\n",
 365                CPU(cpu)->cpu_index);
 366    dump_apic_lvt("LVT0", lvt[APIC_LVT_LINT0], false);
 367    dump_apic_lvt("LVT1", lvt[APIC_LVT_LINT1], false);
 368    dump_apic_lvt("LVTPC", lvt[APIC_LVT_PERFORM], false);
 369    dump_apic_lvt("LVTERR", lvt[APIC_LVT_ERROR], false);
 370    dump_apic_lvt("LVTTHMR", lvt[APIC_LVT_THERMAL], false);
 371    dump_apic_lvt("LVTT", lvt[APIC_LVT_TIMER], true);
 372
 373    qemu_printf("Timer\t DCR=0x%x (divide by %u) initial_count = %u\n",
 374                s->divide_conf & APIC_DCR_MASK,
 375                divider_conf(s->divide_conf),
 376                s->initial_count);
 377
 378    qemu_printf("SPIV\t 0x%08x APIC %s, focus=%s, spurious vec %u\n",
 379                s->spurious_vec,
 380                s->spurious_vec & APIC_SPURIO_ENABLED ? "enabled" : "disabled",
 381                s->spurious_vec & APIC_SPURIO_FOCUS ? "on" : "off",
 382                s->spurious_vec & APIC_VECTOR_MASK);
 383
 384    dump_apic_icr(s, &cpu->env);
 385
 386    qemu_printf("ESR\t 0x%08x\n", s->esr);
 387
 388    dump_apic_interrupt("ISR", s->isr, s->tmr);
 389    dump_apic_interrupt("IRR", s->irr, s->tmr);
 390
 391    qemu_printf("\nAPR 0x%02x TPR 0x%02x DFR 0x%02x LDR 0x%02x",
 392                s->arb_id, s->tpr, s->dest_mode, s->log_dest);
 393    if (s->dest_mode == 0) {
 394        qemu_printf("(cluster %u: id %u)",
 395                    s->log_dest >> APIC_LOGDEST_XAPIC_SHIFT,
 396                    s->log_dest & APIC_LOGDEST_XAPIC_ID);
 397    }
 398    qemu_printf(" PPR 0x%02x\n", apic_get_ppr(s));
 399}
 400#else
 401void x86_cpu_dump_local_apic_state(CPUState *cs, int flags)
 402{
 403}
 404#endif /* !CONFIG_USER_ONLY */
 405
 406#define DUMP_CODE_BYTES_TOTAL    50
 407#define DUMP_CODE_BYTES_BACKWARD 20
 408
 409void x86_cpu_dump_state(CPUState *cs, FILE *f, int flags)
 410{
 411    X86CPU *cpu = X86_CPU(cs);
 412    CPUX86State *env = &cpu->env;
 413    int eflags, i, nb;
 414    char cc_op_name[32];
 415    static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
 416
 417    eflags = cpu_compute_eflags(env);
 418#ifdef TARGET_X86_64
 419    if (env->hflags & HF_CS64_MASK) {
 420        qemu_fprintf(f, "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
 421                     "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
 422                     "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
 423                     "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
 424                     "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
 425                     env->regs[R_EAX],
 426                     env->regs[R_EBX],
 427                     env->regs[R_ECX],
 428                     env->regs[R_EDX],
 429                     env->regs[R_ESI],
 430                     env->regs[R_EDI],
 431                     env->regs[R_EBP],
 432                     env->regs[R_ESP],
 433                     env->regs[8],
 434                     env->regs[9],
 435                     env->regs[10],
 436                     env->regs[11],
 437                     env->regs[12],
 438                     env->regs[13],
 439                     env->regs[14],
 440                     env->regs[15],
 441                     env->eip, eflags,
 442                     eflags & DF_MASK ? 'D' : '-',
 443                     eflags & CC_O ? 'O' : '-',
 444                     eflags & CC_S ? 'S' : '-',
 445                     eflags & CC_Z ? 'Z' : '-',
 446                     eflags & CC_A ? 'A' : '-',
 447                     eflags & CC_P ? 'P' : '-',
 448                     eflags & CC_C ? 'C' : '-',
 449                     env->hflags & HF_CPL_MASK,
 450                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
 451                     (env->a20_mask >> 20) & 1,
 452                     (env->hflags >> HF_SMM_SHIFT) & 1,
 453                     cs->halted);
 454    } else
 455#endif
 456    {
 457        qemu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
 458                     "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
 459                     "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
 460                     (uint32_t)env->regs[R_EAX],
 461                     (uint32_t)env->regs[R_EBX],
 462                     (uint32_t)env->regs[R_ECX],
 463                     (uint32_t)env->regs[R_EDX],
 464                     (uint32_t)env->regs[R_ESI],
 465                     (uint32_t)env->regs[R_EDI],
 466                     (uint32_t)env->regs[R_EBP],
 467                     (uint32_t)env->regs[R_ESP],
 468                     (uint32_t)env->eip, eflags,
 469                     eflags & DF_MASK ? 'D' : '-',
 470                     eflags & CC_O ? 'O' : '-',
 471                     eflags & CC_S ? 'S' : '-',
 472                     eflags & CC_Z ? 'Z' : '-',
 473                     eflags & CC_A ? 'A' : '-',
 474                     eflags & CC_P ? 'P' : '-',
 475                     eflags & CC_C ? 'C' : '-',
 476                     env->hflags & HF_CPL_MASK,
 477                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
 478                     (env->a20_mask >> 20) & 1,
 479                     (env->hflags >> HF_SMM_SHIFT) & 1,
 480                     cs->halted);
 481    }
 482
 483    for(i = 0; i < 6; i++) {
 484        cpu_x86_dump_seg_cache(env, f, seg_name[i], &env->segs[i]);
 485    }
 486    cpu_x86_dump_seg_cache(env, f, "LDT", &env->ldt);
 487    cpu_x86_dump_seg_cache(env, f, "TR", &env->tr);
 488
 489#ifdef TARGET_X86_64
 490    if (env->hflags & HF_LMA_MASK) {
 491        qemu_fprintf(f, "GDT=     %016" PRIx64 " %08x\n",
 492                     env->gdt.base, env->gdt.limit);
 493        qemu_fprintf(f, "IDT=     %016" PRIx64 " %08x\n",
 494                     env->idt.base, env->idt.limit);
 495        qemu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
 496                     (uint32_t)env->cr[0],
 497                     env->cr[2],
 498                     env->cr[3],
 499                     (uint32_t)env->cr[4]);
 500        for(i = 0; i < 4; i++)
 501            qemu_fprintf(f, "DR%d=%016" PRIx64 " ", i, env->dr[i]);
 502        qemu_fprintf(f, "\nDR6=%016" PRIx64 " DR7=%016" PRIx64 "\n",
 503                     env->dr[6], env->dr[7]);
 504    } else
 505#endif
 506    {
 507        qemu_fprintf(f, "GDT=     %08x %08x\n",
 508                     (uint32_t)env->gdt.base, env->gdt.limit);
 509        qemu_fprintf(f, "IDT=     %08x %08x\n",
 510                     (uint32_t)env->idt.base, env->idt.limit);
 511        qemu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
 512                     (uint32_t)env->cr[0],
 513                     (uint32_t)env->cr[2],
 514                     (uint32_t)env->cr[3],
 515                     (uint32_t)env->cr[4]);
 516        for(i = 0; i < 4; i++) {
 517            qemu_fprintf(f, "DR%d=" TARGET_FMT_lx " ", i, env->dr[i]);
 518        }
 519        qemu_fprintf(f, "\nDR6=" TARGET_FMT_lx " DR7=" TARGET_FMT_lx "\n",
 520                     env->dr[6], env->dr[7]);
 521    }
 522    if (flags & CPU_DUMP_CCOP) {
 523        if ((unsigned)env->cc_op < CC_OP_NB)
 524            snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
 525        else
 526            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
 527#ifdef TARGET_X86_64
 528        if (env->hflags & HF_CS64_MASK) {
 529            qemu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
 530                         env->cc_src, env->cc_dst,
 531                         cc_op_name);
 532        } else
 533#endif
 534        {
 535            qemu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
 536                         (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
 537                         cc_op_name);
 538        }
 539    }
 540    qemu_fprintf(f, "EFER=%016" PRIx64 "\n", env->efer);
 541    if (flags & CPU_DUMP_FPU) {
 542        int fptag;
 543        fptag = 0;
 544        for(i = 0; i < 8; i++) {
 545            fptag |= ((!env->fptags[i]) << i);
 546        }
 547        qemu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
 548                     env->fpuc,
 549                     (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
 550                     env->fpstt,
 551                     fptag,
 552                     env->mxcsr);
 553        for(i=0;i<8;i++) {
 554            CPU_LDoubleU u;
 555            u.d = env->fpregs[i].d;
 556            qemu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
 557                         i, u.l.lower, u.l.upper);
 558            if ((i & 1) == 1)
 559                qemu_fprintf(f, "\n");
 560            else
 561                qemu_fprintf(f, " ");
 562        }
 563        if (env->hflags & HF_CS64_MASK)
 564            nb = 16;
 565        else
 566            nb = 8;
 567        for(i=0;i<nb;i++) {
 568            qemu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
 569                         i,
 570                         env->xmm_regs[i].ZMM_L(3),
 571                         env->xmm_regs[i].ZMM_L(2),
 572                         env->xmm_regs[i].ZMM_L(1),
 573                         env->xmm_regs[i].ZMM_L(0));
 574            if ((i & 1) == 1)
 575                qemu_fprintf(f, "\n");
 576            else
 577                qemu_fprintf(f, " ");
 578        }
 579    }
 580    if (flags & CPU_DUMP_CODE) {
 581        target_ulong base = env->segs[R_CS].base + env->eip;
 582        target_ulong offs = MIN(env->eip, DUMP_CODE_BYTES_BACKWARD);
 583        uint8_t code;
 584        char codestr[3];
 585
 586        qemu_fprintf(f, "Code=");
 587        for (i = 0; i < DUMP_CODE_BYTES_TOTAL; i++) {
 588            if (cpu_memory_rw_debug(cs, base - offs + i, &code, 1, 0) == 0) {
 589                snprintf(codestr, sizeof(codestr), "%02x", code);
 590            } else {
 591                snprintf(codestr, sizeof(codestr), "??");
 592            }
 593            qemu_fprintf(f, "%s%s%s%s", i > 0 ? " " : "",
 594                         i == offs ? "<" : "", codestr, i == offs ? ">" : "");
 595        }
 596        qemu_fprintf(f, "\n");
 597    }
 598}
 599
 600/***********************************************************/
 601/* x86 mmu */
 602/* XXX: add PGE support */
 603
 604void x86_cpu_set_a20(X86CPU *cpu, int a20_state)
 605{
 606    CPUX86State *env = &cpu->env;
 607
 608    a20_state = (a20_state != 0);
 609    if (a20_state != ((env->a20_mask >> 20) & 1)) {
 610        CPUState *cs = CPU(cpu);
 611
 612        qemu_log_mask(CPU_LOG_MMU, "A20 update: a20=%d\n", a20_state);
 613        /* if the cpu is currently executing code, we must unlink it and
 614           all the potentially executing TB */
 615        cpu_interrupt(cs, CPU_INTERRUPT_EXITTB);
 616
 617        /* when a20 is changed, all the MMU mappings are invalid, so
 618           we must flush everything */
 619        tlb_flush(cs);
 620        env->a20_mask = ~(1 << 20) | (a20_state << 20);
 621    }
 622}
 623
 624void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
 625{
 626    X86CPU *cpu = env_archcpu(env);
 627    int pe_state;
 628
 629    qemu_log_mask(CPU_LOG_MMU, "CR0 update: CR0=0x%08x\n", new_cr0);
 630    if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
 631        (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
 632        tlb_flush(CPU(cpu));
 633    }
 634
 635#ifdef TARGET_X86_64
 636    if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
 637        (env->efer & MSR_EFER_LME)) {
 638        /* enter in long mode */
 639        /* XXX: generate an exception */
 640        if (!(env->cr[4] & CR4_PAE_MASK))
 641            return;
 642        env->efer |= MSR_EFER_LMA;
 643        env->hflags |= HF_LMA_MASK;
 644    } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
 645               (env->efer & MSR_EFER_LMA)) {
 646        /* exit long mode */
 647        env->efer &= ~MSR_EFER_LMA;
 648        env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
 649        env->eip &= 0xffffffff;
 650    }
 651#endif
 652    env->cr[0] = new_cr0 | CR0_ET_MASK;
 653
 654    /* update PE flag in hidden flags */
 655    pe_state = (env->cr[0] & CR0_PE_MASK);
 656    env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
 657    /* ensure that ADDSEG is always set in real mode */
 658    env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
 659    /* update FPU flags */
 660    env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
 661        ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
 662}
 663
 664/* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
 665   the PDPT */
 666void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
 667{
 668    env->cr[3] = new_cr3;
 669    if (env->cr[0] & CR0_PG_MASK) {
 670        qemu_log_mask(CPU_LOG_MMU,
 671                        "CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
 672        tlb_flush(env_cpu(env));
 673    }
 674}
 675
 676void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
 677{
 678    uint32_t hflags;
 679
 680#if defined(DEBUG_MMU)
 681    printf("CR4 update: %08x -> %08x\n", (uint32_t)env->cr[4], new_cr4);
 682#endif
 683    if ((new_cr4 ^ env->cr[4]) &
 684        (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK |
 685         CR4_SMEP_MASK | CR4_SMAP_MASK | CR4_LA57_MASK)) {
 686        tlb_flush(env_cpu(env));
 687    }
 688
 689    /* Clear bits we're going to recompute.  */
 690    hflags = env->hflags & ~(HF_OSFXSR_MASK | HF_SMAP_MASK);
 691
 692    /* SSE handling */
 693    if (!(env->features[FEAT_1_EDX] & CPUID_SSE)) {
 694        new_cr4 &= ~CR4_OSFXSR_MASK;
 695    }
 696    if (new_cr4 & CR4_OSFXSR_MASK) {
 697        hflags |= HF_OSFXSR_MASK;
 698    }
 699
 700    if (!(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_SMAP)) {
 701        new_cr4 &= ~CR4_SMAP_MASK;
 702    }
 703    if (new_cr4 & CR4_SMAP_MASK) {
 704        hflags |= HF_SMAP_MASK;
 705    }
 706
 707    if (!(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_PKU)) {
 708        new_cr4 &= ~CR4_PKE_MASK;
 709    }
 710
 711    env->cr[4] = new_cr4;
 712    env->hflags = hflags;
 713
 714    cpu_sync_bndcs_hflags(env);
 715}
 716
 717#if !defined(CONFIG_USER_ONLY)
 718hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 719{
 720    X86CPU *cpu = X86_CPU(cs);
 721    CPUX86State *env = &cpu->env;
 722    target_ulong pde_addr, pte_addr;
 723    uint64_t pte;
 724    int32_t a20_mask;
 725    uint32_t page_offset;
 726    int page_size;
 727
 728    a20_mask = x86_get_a20_mask(env);
 729    if (!(env->cr[0] & CR0_PG_MASK)) {
 730        pte = addr & a20_mask;
 731        page_size = 4096;
 732    } else if (env->cr[4] & CR4_PAE_MASK) {
 733        target_ulong pdpe_addr;
 734        uint64_t pde, pdpe;
 735
 736#ifdef TARGET_X86_64
 737        if (env->hflags & HF_LMA_MASK) {
 738            bool la57 = env->cr[4] & CR4_LA57_MASK;
 739            uint64_t pml5e_addr, pml5e;
 740            uint64_t pml4e_addr, pml4e;
 741            int32_t sext;
 742
 743            /* test virtual address sign extension */
 744            sext = la57 ? (int64_t)addr >> 56 : (int64_t)addr >> 47;
 745            if (sext != 0 && sext != -1) {
 746                return -1;
 747            }
 748
 749            if (la57) {
 750                pml5e_addr = ((env->cr[3] & ~0xfff) +
 751                        (((addr >> 48) & 0x1ff) << 3)) & a20_mask;
 752                pml5e = x86_ldq_phys(cs, pml5e_addr);
 753                if (!(pml5e & PG_PRESENT_MASK)) {
 754                    return -1;
 755                }
 756            } else {
 757                pml5e = env->cr[3];
 758            }
 759
 760            pml4e_addr = ((pml5e & PG_ADDRESS_MASK) +
 761                    (((addr >> 39) & 0x1ff) << 3)) & a20_mask;
 762            pml4e = x86_ldq_phys(cs, pml4e_addr);
 763            if (!(pml4e & PG_PRESENT_MASK)) {
 764                return -1;
 765            }
 766            pdpe_addr = ((pml4e & PG_ADDRESS_MASK) +
 767                         (((addr >> 30) & 0x1ff) << 3)) & a20_mask;
 768            pdpe = x86_ldq_phys(cs, pdpe_addr);
 769            if (!(pdpe & PG_PRESENT_MASK)) {
 770                return -1;
 771            }
 772            if (pdpe & PG_PSE_MASK) {
 773                page_size = 1024 * 1024 * 1024;
 774                pte = pdpe;
 775                goto out;
 776            }
 777
 778        } else
 779#endif
 780        {
 781            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
 782                a20_mask;
 783            pdpe = x86_ldq_phys(cs, pdpe_addr);
 784            if (!(pdpe & PG_PRESENT_MASK))
 785                return -1;
 786        }
 787
 788        pde_addr = ((pdpe & PG_ADDRESS_MASK) +
 789                    (((addr >> 21) & 0x1ff) << 3)) & a20_mask;
 790        pde = x86_ldq_phys(cs, pde_addr);
 791        if (!(pde & PG_PRESENT_MASK)) {
 792            return -1;
 793        }
 794        if (pde & PG_PSE_MASK) {
 795            /* 2 MB page */
 796            page_size = 2048 * 1024;
 797            pte = pde;
 798        } else {
 799            /* 4 KB page */
 800            pte_addr = ((pde & PG_ADDRESS_MASK) +
 801                        (((addr >> 12) & 0x1ff) << 3)) & a20_mask;
 802            page_size = 4096;
 803            pte = x86_ldq_phys(cs, pte_addr);
 804        }
 805        if (!(pte & PG_PRESENT_MASK)) {
 806            return -1;
 807        }
 808    } else {
 809        uint32_t pde;
 810
 811        /* page directory entry */
 812        pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & a20_mask;
 813        pde = x86_ldl_phys(cs, pde_addr);
 814        if (!(pde & PG_PRESENT_MASK))
 815            return -1;
 816        if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
 817            pte = pde | ((pde & 0x1fe000LL) << (32 - 13));
 818            page_size = 4096 * 1024;
 819        } else {
 820            /* page directory entry */
 821            pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask;
 822            pte = x86_ldl_phys(cs, pte_addr);
 823            if (!(pte & PG_PRESENT_MASK)) {
 824                return -1;
 825            }
 826            page_size = 4096;
 827        }
 828        pte = pte & a20_mask;
 829    }
 830
 831#ifdef TARGET_X86_64
 832out:
 833#endif
 834    pte &= PG_ADDRESS_MASK & ~(page_size - 1);
 835    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
 836    return pte | page_offset;
 837}
 838
 839typedef struct MCEInjectionParams {
 840    Monitor *mon;
 841    int bank;
 842    uint64_t status;
 843    uint64_t mcg_status;
 844    uint64_t addr;
 845    uint64_t misc;
 846    int flags;
 847} MCEInjectionParams;
 848
 849static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data)
 850{
 851    MCEInjectionParams *params = data.host_ptr;
 852    X86CPU *cpu = X86_CPU(cs);
 853    CPUX86State *cenv = &cpu->env;
 854    uint64_t *banks = cenv->mce_banks + 4 * params->bank;
 855
 856    cpu_synchronize_state(cs);
 857
 858    /*
 859     * If there is an MCE exception being processed, ignore this SRAO MCE
 860     * unless unconditional injection was requested.
 861     */
 862    if (!(params->flags & MCE_INJECT_UNCOND_AO)
 863        && !(params->status & MCI_STATUS_AR)
 864        && (cenv->mcg_status & MCG_STATUS_MCIP)) {
 865        return;
 866    }
 867
 868    if (params->status & MCI_STATUS_UC) {
 869        /*
 870         * if MSR_MCG_CTL is not all 1s, the uncorrected error
 871         * reporting is disabled
 872         */
 873        if ((cenv->mcg_cap & MCG_CTL_P) && cenv->mcg_ctl != ~(uint64_t)0) {
 874            monitor_printf(params->mon,
 875                           "CPU %d: Uncorrected error reporting disabled\n",
 876                           cs->cpu_index);
 877            return;
 878        }
 879
 880        /*
 881         * if MSR_MCi_CTL is not all 1s, the uncorrected error
 882         * reporting is disabled for the bank
 883         */
 884        if (banks[0] != ~(uint64_t)0) {
 885            monitor_printf(params->mon,
 886                           "CPU %d: Uncorrected error reporting disabled for"
 887                           " bank %d\n",
 888                           cs->cpu_index, params->bank);
 889            return;
 890        }
 891
 892        if ((cenv->mcg_status & MCG_STATUS_MCIP) ||
 893            !(cenv->cr[4] & CR4_MCE_MASK)) {
 894            monitor_printf(params->mon,
 895                           "CPU %d: Previous MCE still in progress, raising"
 896                           " triple fault\n",
 897                           cs->cpu_index);
 898            qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
 899            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
 900            return;
 901        }
 902        if (banks[1] & MCI_STATUS_VAL) {
 903            params->status |= MCI_STATUS_OVER;
 904        }
 905        banks[2] = params->addr;
 906        banks[3] = params->misc;
 907        cenv->mcg_status = params->mcg_status;
 908        banks[1] = params->status;
 909        cpu_interrupt(cs, CPU_INTERRUPT_MCE);
 910    } else if (!(banks[1] & MCI_STATUS_VAL)
 911               || !(banks[1] & MCI_STATUS_UC)) {
 912        if (banks[1] & MCI_STATUS_VAL) {
 913            params->status |= MCI_STATUS_OVER;
 914        }
 915        banks[2] = params->addr;
 916        banks[3] = params->misc;
 917        banks[1] = params->status;
 918    } else {
 919        banks[1] |= MCI_STATUS_OVER;
 920    }
 921}
 922
 923void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
 924                        uint64_t status, uint64_t mcg_status, uint64_t addr,
 925                        uint64_t misc, int flags)
 926{
 927    CPUState *cs = CPU(cpu);
 928    CPUX86State *cenv = &cpu->env;
 929    MCEInjectionParams params = {
 930        .mon = mon,
 931        .bank = bank,
 932        .status = status,
 933        .mcg_status = mcg_status,
 934        .addr = addr,
 935        .misc = misc,
 936        .flags = flags,
 937    };
 938    unsigned bank_num = cenv->mcg_cap & 0xff;
 939
 940    if (!cenv->mcg_cap) {
 941        monitor_printf(mon, "MCE injection not supported\n");
 942        return;
 943    }
 944    if (bank >= bank_num) {
 945        monitor_printf(mon, "Invalid MCE bank number\n");
 946        return;
 947    }
 948    if (!(status & MCI_STATUS_VAL)) {
 949        monitor_printf(mon, "Invalid MCE status code\n");
 950        return;
 951    }
 952    if ((flags & MCE_INJECT_BROADCAST)
 953        && !cpu_x86_support_mca_broadcast(cenv)) {
 954        monitor_printf(mon, "Guest CPU does not support MCA broadcast\n");
 955        return;
 956    }
 957
 958    run_on_cpu(cs, do_inject_x86_mce, RUN_ON_CPU_HOST_PTR(&params));
 959    if (flags & MCE_INJECT_BROADCAST) {
 960        CPUState *other_cs;
 961
 962        params.bank = 1;
 963        params.status = MCI_STATUS_VAL | MCI_STATUS_UC;
 964        params.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV;
 965        params.addr = 0;
 966        params.misc = 0;
 967        CPU_FOREACH(other_cs) {
 968            if (other_cs == cs) {
 969                continue;
 970            }
 971            run_on_cpu(other_cs, do_inject_x86_mce, RUN_ON_CPU_HOST_PTR(&params));
 972        }
 973    }
 974}
 975
 976void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
 977{
 978    X86CPU *cpu = env_archcpu(env);
 979    CPUState *cs = env_cpu(env);
 980
 981    if (kvm_enabled() || whpx_enabled()) {
 982        env->tpr_access_type = access;
 983
 984        cpu_interrupt(cs, CPU_INTERRUPT_TPR);
 985    } else if (tcg_enabled()) {
 986        cpu_restore_state(cs, cs->mem_io_pc, false);
 987
 988        apic_handle_tpr_access_report(cpu->apic_state, env->eip, access);
 989    }
 990}
 991#endif /* !CONFIG_USER_ONLY */
 992
 993int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
 994                            target_ulong *base, unsigned int *limit,
 995                            unsigned int *flags)
 996{
 997    CPUState *cs = env_cpu(env);
 998    SegmentCache *dt;
 999    target_ulong ptr;
1000    uint32_t e1, e2;
1001    int index;
1002
1003    if (selector & 0x4)
1004        dt = &env->ldt;
1005    else
1006        dt = &env->gdt;
1007    index = selector & ~7;
1008    ptr = dt->base + index;
1009    if ((index + 7) > dt->limit
1010        || cpu_memory_rw_debug(cs, ptr, (uint8_t *)&e1, sizeof(e1), 0) != 0
1011        || cpu_memory_rw_debug(cs, ptr+4, (uint8_t *)&e2, sizeof(e2), 0) != 0)
1012        return 0;
1013
1014    *base = ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
1015    *limit = (e1 & 0xffff) | (e2 & 0x000f0000);
1016    if (e2 & DESC_G_MASK)
1017        *limit = (*limit << 12) | 0xfff;
1018    *flags = e2;
1019
1020    return 1;
1021}
1022
1023#if !defined(CONFIG_USER_ONLY)
1024void do_cpu_init(X86CPU *cpu)
1025{
1026    CPUState *cs = CPU(cpu);
1027    CPUX86State *env = &cpu->env;
1028    CPUX86State *save = g_new(CPUX86State, 1);
1029    int sipi = cs->interrupt_request & CPU_INTERRUPT_SIPI;
1030
1031    *save = *env;
1032
1033    cpu_reset(cs);
1034    cs->interrupt_request = sipi;
1035    memcpy(&env->start_init_save, &save->start_init_save,
1036           offsetof(CPUX86State, end_init_save) -
1037           offsetof(CPUX86State, start_init_save));
1038    g_free(save);
1039
1040    if (kvm_enabled()) {
1041        kvm_arch_do_init_vcpu(cpu);
1042    }
1043    apic_init_reset(cpu->apic_state);
1044}
1045
1046void do_cpu_sipi(X86CPU *cpu)
1047{
1048    apic_sipi(cpu->apic_state);
1049}
1050#else
1051void do_cpu_init(X86CPU *cpu)
1052{
1053}
1054void do_cpu_sipi(X86CPU *cpu)
1055{
1056}
1057#endif
1058
1059/* Frob eflags into and out of the CPU temporary format.  */
1060
1061void x86_cpu_exec_enter(CPUState *cs)
1062{
1063    X86CPU *cpu = X86_CPU(cs);
1064    CPUX86State *env = &cpu->env;
1065
1066    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1067    env->df = 1 - (2 * ((env->eflags >> 10) & 1));
1068    CC_OP = CC_OP_EFLAGS;
1069    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1070}
1071
1072void x86_cpu_exec_exit(CPUState *cs)
1073{
1074    X86CPU *cpu = X86_CPU(cs);
1075    CPUX86State *env = &cpu->env;
1076
1077    env->eflags = cpu_compute_eflags(env);
1078}
1079
1080#ifndef CONFIG_USER_ONLY
1081uint8_t x86_ldub_phys(CPUState *cs, hwaddr addr)
1082{
1083    X86CPU *cpu = X86_CPU(cs);
1084    CPUX86State *env = &cpu->env;
1085    MemTxAttrs attrs = cpu_get_mem_attrs(env);
1086    AddressSpace *as = cpu_addressspace(cs, attrs);
1087
1088    return address_space_ldub(as, addr, attrs, NULL);
1089}
1090
1091uint32_t x86_lduw_phys(CPUState *cs, hwaddr addr)
1092{
1093    X86CPU *cpu = X86_CPU(cs);
1094    CPUX86State *env = &cpu->env;
1095    MemTxAttrs attrs = cpu_get_mem_attrs(env);
1096    AddressSpace *as = cpu_addressspace(cs, attrs);
1097
1098    return address_space_lduw(as, addr, attrs, NULL);
1099}
1100
1101uint32_t x86_ldl_phys(CPUState *cs, hwaddr addr)
1102{
1103    X86CPU *cpu = X86_CPU(cs);
1104    CPUX86State *env = &cpu->env;
1105    MemTxAttrs attrs = cpu_get_mem_attrs(env);
1106    AddressSpace *as = cpu_addressspace(cs, attrs);
1107
1108    return address_space_ldl(as, addr, attrs, NULL);
1109}
1110
1111uint64_t x86_ldq_phys(CPUState *cs, hwaddr addr)
1112{
1113    X86CPU *cpu = X86_CPU(cs);
1114    CPUX86State *env = &cpu->env;
1115    MemTxAttrs attrs = cpu_get_mem_attrs(env);
1116    AddressSpace *as = cpu_addressspace(cs, attrs);
1117
1118    return address_space_ldq(as, addr, attrs, NULL);
1119}
1120
1121void x86_stb_phys(CPUState *cs, hwaddr addr, uint8_t val)
1122{
1123    X86CPU *cpu = X86_CPU(cs);
1124    CPUX86State *env = &cpu->env;
1125    MemTxAttrs attrs = cpu_get_mem_attrs(env);
1126    AddressSpace *as = cpu_addressspace(cs, attrs);
1127
1128    address_space_stb(as, addr, val, attrs, NULL);
1129}
1130
1131void x86_stl_phys_notdirty(CPUState *cs, hwaddr addr, uint32_t val)
1132{
1133    X86CPU *cpu = X86_CPU(cs);
1134    CPUX86State *env = &cpu->env;
1135    MemTxAttrs attrs = cpu_get_mem_attrs(env);
1136    AddressSpace *as = cpu_addressspace(cs, attrs);
1137
1138    address_space_stl_notdirty(as, addr, val, attrs, NULL);
1139}
1140
1141void x86_stw_phys(CPUState *cs, hwaddr addr, uint32_t val)
1142{
1143    X86CPU *cpu = X86_CPU(cs);
1144    CPUX86State *env = &cpu->env;
1145    MemTxAttrs attrs = cpu_get_mem_attrs(env);
1146    AddressSpace *as = cpu_addressspace(cs, attrs);
1147
1148    address_space_stw(as, addr, val, attrs, NULL);
1149}
1150
1151void x86_stl_phys(CPUState *cs, hwaddr addr, uint32_t val)
1152{
1153    X86CPU *cpu = X86_CPU(cs);
1154    CPUX86State *env = &cpu->env;
1155    MemTxAttrs attrs = cpu_get_mem_attrs(env);
1156    AddressSpace *as = cpu_addressspace(cs, attrs);
1157
1158    address_space_stl(as, addr, val, attrs, NULL);
1159}
1160
1161void x86_stq_phys(CPUState *cs, hwaddr addr, uint64_t val)
1162{
1163    X86CPU *cpu = X86_CPU(cs);
1164    CPUX86State *env = &cpu->env;
1165    MemTxAttrs attrs = cpu_get_mem_attrs(env);
1166    AddressSpace *as = cpu_addressspace(cs, attrs);
1167
1168    address_space_stq(as, addr, val, attrs, NULL);
1169}
1170#endif
1171