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