1 /* 2 * x86 misc helpers 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 "qemu/main-loop.h" 22 #include "cpu.h" 23 #include "exec/helper-proto.h" 24 #include "exec/exec-all.h" 25 #include "exec/cpu_ldst.h" 26 #include "exec/address-spaces.h" 27 #include "helper-tcg.h" 28 29 /* 30 * NOTE: the translator must set DisasContext.cc_op to CC_OP_EFLAGS 31 * after generating a call to a helper that uses this. 32 */ 33 void cpu_load_eflags(CPUX86State *env, int eflags, int update_mask) 34 { 35 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); 36 CC_OP = CC_OP_EFLAGS; 37 env->df = 1 - (2 * ((eflags >> 10) & 1)); 38 env->eflags = (env->eflags & ~update_mask) | 39 (eflags & update_mask) | 0x2; 40 } 41 42 void helper_outb(CPUX86State *env, uint32_t port, uint32_t data) 43 { 44 #ifdef CONFIG_USER_ONLY 45 fprintf(stderr, "outb: port=0x%04x, data=%02x\n", port, data); 46 #else 47 address_space_stb(&address_space_io, port, data, 48 cpu_get_mem_attrs(env), NULL); 49 #endif 50 } 51 52 target_ulong helper_inb(CPUX86State *env, uint32_t port) 53 { 54 #ifdef CONFIG_USER_ONLY 55 fprintf(stderr, "inb: port=0x%04x\n", port); 56 return 0; 57 #else 58 return address_space_ldub(&address_space_io, port, 59 cpu_get_mem_attrs(env), NULL); 60 #endif 61 } 62 63 void helper_outw(CPUX86State *env, uint32_t port, uint32_t data) 64 { 65 #ifdef CONFIG_USER_ONLY 66 fprintf(stderr, "outw: port=0x%04x, data=%04x\n", port, data); 67 #else 68 address_space_stw(&address_space_io, port, data, 69 cpu_get_mem_attrs(env), NULL); 70 #endif 71 } 72 73 target_ulong helper_inw(CPUX86State *env, uint32_t port) 74 { 75 #ifdef CONFIG_USER_ONLY 76 fprintf(stderr, "inw: port=0x%04x\n", port); 77 return 0; 78 #else 79 return address_space_lduw(&address_space_io, port, 80 cpu_get_mem_attrs(env), NULL); 81 #endif 82 } 83 84 void helper_outl(CPUX86State *env, uint32_t port, uint32_t data) 85 { 86 #ifdef CONFIG_USER_ONLY 87 fprintf(stderr, "outl: port=0x%04x, data=%08x\n", port, data); 88 #else 89 address_space_stl(&address_space_io, port, data, 90 cpu_get_mem_attrs(env), NULL); 91 #endif 92 } 93 94 target_ulong helper_inl(CPUX86State *env, uint32_t port) 95 { 96 #ifdef CONFIG_USER_ONLY 97 fprintf(stderr, "inl: port=0x%04x\n", port); 98 return 0; 99 #else 100 return address_space_ldl(&address_space_io, port, 101 cpu_get_mem_attrs(env), NULL); 102 #endif 103 } 104 105 void helper_into(CPUX86State *env, int next_eip_addend) 106 { 107 int eflags; 108 109 eflags = cpu_cc_compute_all(env, CC_OP); 110 if (eflags & CC_O) { 111 raise_interrupt(env, EXCP04_INTO, 1, 0, next_eip_addend); 112 } 113 } 114 115 void helper_cpuid(CPUX86State *env) 116 { 117 uint32_t eax, ebx, ecx, edx; 118 119 cpu_svm_check_intercept_param(env, SVM_EXIT_CPUID, 0, GETPC()); 120 121 cpu_x86_cpuid(env, (uint32_t)env->regs[R_EAX], (uint32_t)env->regs[R_ECX], 122 &eax, &ebx, &ecx, &edx); 123 env->regs[R_EAX] = eax; 124 env->regs[R_EBX] = ebx; 125 env->regs[R_ECX] = ecx; 126 env->regs[R_EDX] = edx; 127 } 128 129 #if defined(CONFIG_USER_ONLY) 130 target_ulong helper_read_crN(CPUX86State *env, int reg) 131 { 132 return 0; 133 } 134 135 void helper_write_crN(CPUX86State *env, int reg, target_ulong t0) 136 { 137 } 138 #else 139 target_ulong helper_read_crN(CPUX86State *env, int reg) 140 { 141 target_ulong val; 142 143 cpu_svm_check_intercept_param(env, SVM_EXIT_READ_CR0 + reg, 0, GETPC()); 144 switch (reg) { 145 default: 146 val = env->cr[reg]; 147 break; 148 case 8: 149 if (!(env->hflags2 & HF2_VINTR_MASK)) { 150 val = cpu_get_apic_tpr(env_archcpu(env)->apic_state); 151 } else { 152 val = env->v_tpr; 153 } 154 break; 155 } 156 return val; 157 } 158 159 void helper_write_crN(CPUX86State *env, int reg, target_ulong t0) 160 { 161 cpu_svm_check_intercept_param(env, SVM_EXIT_WRITE_CR0 + reg, 0, GETPC()); 162 switch (reg) { 163 case 0: 164 cpu_x86_update_cr0(env, t0); 165 break; 166 case 3: 167 cpu_x86_update_cr3(env, t0); 168 break; 169 case 4: 170 cpu_x86_update_cr4(env, t0); 171 break; 172 case 8: 173 if (!(env->hflags2 & HF2_VINTR_MASK)) { 174 qemu_mutex_lock_iothread(); 175 cpu_set_apic_tpr(env_archcpu(env)->apic_state, t0); 176 qemu_mutex_unlock_iothread(); 177 } 178 env->v_tpr = t0 & 0x0f; 179 break; 180 default: 181 env->cr[reg] = t0; 182 break; 183 } 184 } 185 #endif 186 187 void helper_lmsw(CPUX86State *env, target_ulong t0) 188 { 189 /* only 4 lower bits of CR0 are modified. PE cannot be set to zero 190 if already set to one. */ 191 t0 = (env->cr[0] & ~0xe) | (t0 & 0xf); 192 helper_write_crN(env, 0, t0); 193 } 194 195 void helper_invlpg(CPUX86State *env, target_ulong addr) 196 { 197 X86CPU *cpu = env_archcpu(env); 198 199 cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0, GETPC()); 200 tlb_flush_page(CPU(cpu), addr); 201 } 202 203 void helper_rdtsc(CPUX86State *env) 204 { 205 uint64_t val; 206 207 if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { 208 raise_exception_ra(env, EXCP0D_GPF, GETPC()); 209 } 210 cpu_svm_check_intercept_param(env, SVM_EXIT_RDTSC, 0, GETPC()); 211 212 val = cpu_get_tsc(env) + env->tsc_offset; 213 env->regs[R_EAX] = (uint32_t)(val); 214 env->regs[R_EDX] = (uint32_t)(val >> 32); 215 } 216 217 void helper_rdtscp(CPUX86State *env) 218 { 219 helper_rdtsc(env); 220 env->regs[R_ECX] = (uint32_t)(env->tsc_aux); 221 } 222 223 void helper_rdpmc(CPUX86State *env) 224 { 225 if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { 226 raise_exception_ra(env, EXCP0D_GPF, GETPC()); 227 } 228 cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0, GETPC()); 229 230 /* currently unimplemented */ 231 qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n"); 232 raise_exception_err(env, EXCP06_ILLOP, 0); 233 } 234 235 #if defined(CONFIG_USER_ONLY) 236 void helper_wrmsr(CPUX86State *env) 237 { 238 } 239 240 void helper_rdmsr(CPUX86State *env) 241 { 242 } 243 #else 244 void helper_wrmsr(CPUX86State *env) 245 { 246 uint64_t val; 247 248 cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC()); 249 250 val = ((uint32_t)env->regs[R_EAX]) | 251 ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); 252 253 switch ((uint32_t)env->regs[R_ECX]) { 254 case MSR_IA32_SYSENTER_CS: 255 env->sysenter_cs = val & 0xffff; 256 break; 257 case MSR_IA32_SYSENTER_ESP: 258 env->sysenter_esp = val; 259 break; 260 case MSR_IA32_SYSENTER_EIP: 261 env->sysenter_eip = val; 262 break; 263 case MSR_IA32_APICBASE: 264 cpu_set_apic_base(env_archcpu(env)->apic_state, val); 265 break; 266 case MSR_EFER: 267 { 268 uint64_t update_mask; 269 270 update_mask = 0; 271 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) { 272 update_mask |= MSR_EFER_SCE; 273 } 274 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) { 275 update_mask |= MSR_EFER_LME; 276 } 277 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) { 278 update_mask |= MSR_EFER_FFXSR; 279 } 280 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) { 281 update_mask |= MSR_EFER_NXE; 282 } 283 if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) { 284 update_mask |= MSR_EFER_SVME; 285 } 286 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) { 287 update_mask |= MSR_EFER_FFXSR; 288 } 289 cpu_load_efer(env, (env->efer & ~update_mask) | 290 (val & update_mask)); 291 } 292 break; 293 case MSR_STAR: 294 env->star = val; 295 break; 296 case MSR_PAT: 297 env->pat = val; 298 break; 299 case MSR_VM_HSAVE_PA: 300 env->vm_hsave = val; 301 break; 302 #ifdef TARGET_X86_64 303 case MSR_LSTAR: 304 env->lstar = val; 305 break; 306 case MSR_CSTAR: 307 env->cstar = val; 308 break; 309 case MSR_FMASK: 310 env->fmask = val; 311 break; 312 case MSR_FSBASE: 313 env->segs[R_FS].base = val; 314 break; 315 case MSR_GSBASE: 316 env->segs[R_GS].base = val; 317 break; 318 case MSR_KERNELGSBASE: 319 env->kernelgsbase = val; 320 break; 321 #endif 322 case MSR_MTRRphysBase(0): 323 case MSR_MTRRphysBase(1): 324 case MSR_MTRRphysBase(2): 325 case MSR_MTRRphysBase(3): 326 case MSR_MTRRphysBase(4): 327 case MSR_MTRRphysBase(5): 328 case MSR_MTRRphysBase(6): 329 case MSR_MTRRphysBase(7): 330 env->mtrr_var[((uint32_t)env->regs[R_ECX] - 331 MSR_MTRRphysBase(0)) / 2].base = val; 332 break; 333 case MSR_MTRRphysMask(0): 334 case MSR_MTRRphysMask(1): 335 case MSR_MTRRphysMask(2): 336 case MSR_MTRRphysMask(3): 337 case MSR_MTRRphysMask(4): 338 case MSR_MTRRphysMask(5): 339 case MSR_MTRRphysMask(6): 340 case MSR_MTRRphysMask(7): 341 env->mtrr_var[((uint32_t)env->regs[R_ECX] - 342 MSR_MTRRphysMask(0)) / 2].mask = val; 343 break; 344 case MSR_MTRRfix64K_00000: 345 env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - 346 MSR_MTRRfix64K_00000] = val; 347 break; 348 case MSR_MTRRfix16K_80000: 349 case MSR_MTRRfix16K_A0000: 350 env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - 351 MSR_MTRRfix16K_80000 + 1] = val; 352 break; 353 case MSR_MTRRfix4K_C0000: 354 case MSR_MTRRfix4K_C8000: 355 case MSR_MTRRfix4K_D0000: 356 case MSR_MTRRfix4K_D8000: 357 case MSR_MTRRfix4K_E0000: 358 case MSR_MTRRfix4K_E8000: 359 case MSR_MTRRfix4K_F0000: 360 case MSR_MTRRfix4K_F8000: 361 env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - 362 MSR_MTRRfix4K_C0000 + 3] = val; 363 break; 364 case MSR_MTRRdefType: 365 env->mtrr_deftype = val; 366 break; 367 case MSR_MCG_STATUS: 368 env->mcg_status = val; 369 break; 370 case MSR_MCG_CTL: 371 if ((env->mcg_cap & MCG_CTL_P) 372 && (val == 0 || val == ~(uint64_t)0)) { 373 env->mcg_ctl = val; 374 } 375 break; 376 case MSR_TSC_AUX: 377 env->tsc_aux = val; 378 break; 379 case MSR_IA32_MISC_ENABLE: 380 env->msr_ia32_misc_enable = val; 381 break; 382 case MSR_IA32_BNDCFGS: 383 /* FIXME: #GP if reserved bits are set. */ 384 /* FIXME: Extend highest implemented bit of linear address. */ 385 env->msr_bndcfgs = val; 386 cpu_sync_bndcs_hflags(env); 387 break; 388 default: 389 if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL 390 && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL + 391 (4 * env->mcg_cap & 0xff)) { 392 uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL; 393 if ((offset & 0x3) != 0 394 || (val == 0 || val == ~(uint64_t)0)) { 395 env->mce_banks[offset] = val; 396 } 397 break; 398 } 399 /* XXX: exception? */ 400 break; 401 } 402 } 403 404 void helper_rdmsr(CPUX86State *env) 405 { 406 X86CPU *x86_cpu = env_archcpu(env); 407 uint64_t val; 408 409 cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0, GETPC()); 410 411 switch ((uint32_t)env->regs[R_ECX]) { 412 case MSR_IA32_SYSENTER_CS: 413 val = env->sysenter_cs; 414 break; 415 case MSR_IA32_SYSENTER_ESP: 416 val = env->sysenter_esp; 417 break; 418 case MSR_IA32_SYSENTER_EIP: 419 val = env->sysenter_eip; 420 break; 421 case MSR_IA32_APICBASE: 422 val = cpu_get_apic_base(env_archcpu(env)->apic_state); 423 break; 424 case MSR_EFER: 425 val = env->efer; 426 break; 427 case MSR_STAR: 428 val = env->star; 429 break; 430 case MSR_PAT: 431 val = env->pat; 432 break; 433 case MSR_VM_HSAVE_PA: 434 val = env->vm_hsave; 435 break; 436 case MSR_IA32_PERF_STATUS: 437 /* tsc_increment_by_tick */ 438 val = 1000ULL; 439 /* CPU multiplier */ 440 val |= (((uint64_t)4ULL) << 40); 441 break; 442 #ifdef TARGET_X86_64 443 case MSR_LSTAR: 444 val = env->lstar; 445 break; 446 case MSR_CSTAR: 447 val = env->cstar; 448 break; 449 case MSR_FMASK: 450 val = env->fmask; 451 break; 452 case MSR_FSBASE: 453 val = env->segs[R_FS].base; 454 break; 455 case MSR_GSBASE: 456 val = env->segs[R_GS].base; 457 break; 458 case MSR_KERNELGSBASE: 459 val = env->kernelgsbase; 460 break; 461 case MSR_TSC_AUX: 462 val = env->tsc_aux; 463 break; 464 #endif 465 case MSR_SMI_COUNT: 466 val = env->msr_smi_count; 467 break; 468 case MSR_MTRRphysBase(0): 469 case MSR_MTRRphysBase(1): 470 case MSR_MTRRphysBase(2): 471 case MSR_MTRRphysBase(3): 472 case MSR_MTRRphysBase(4): 473 case MSR_MTRRphysBase(5): 474 case MSR_MTRRphysBase(6): 475 case MSR_MTRRphysBase(7): 476 val = env->mtrr_var[((uint32_t)env->regs[R_ECX] - 477 MSR_MTRRphysBase(0)) / 2].base; 478 break; 479 case MSR_MTRRphysMask(0): 480 case MSR_MTRRphysMask(1): 481 case MSR_MTRRphysMask(2): 482 case MSR_MTRRphysMask(3): 483 case MSR_MTRRphysMask(4): 484 case MSR_MTRRphysMask(5): 485 case MSR_MTRRphysMask(6): 486 case MSR_MTRRphysMask(7): 487 val = env->mtrr_var[((uint32_t)env->regs[R_ECX] - 488 MSR_MTRRphysMask(0)) / 2].mask; 489 break; 490 case MSR_MTRRfix64K_00000: 491 val = env->mtrr_fixed[0]; 492 break; 493 case MSR_MTRRfix16K_80000: 494 case MSR_MTRRfix16K_A0000: 495 val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - 496 MSR_MTRRfix16K_80000 + 1]; 497 break; 498 case MSR_MTRRfix4K_C0000: 499 case MSR_MTRRfix4K_C8000: 500 case MSR_MTRRfix4K_D0000: 501 case MSR_MTRRfix4K_D8000: 502 case MSR_MTRRfix4K_E0000: 503 case MSR_MTRRfix4K_E8000: 504 case MSR_MTRRfix4K_F0000: 505 case MSR_MTRRfix4K_F8000: 506 val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - 507 MSR_MTRRfix4K_C0000 + 3]; 508 break; 509 case MSR_MTRRdefType: 510 val = env->mtrr_deftype; 511 break; 512 case MSR_MTRRcap: 513 if (env->features[FEAT_1_EDX] & CPUID_MTRR) { 514 val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT | 515 MSR_MTRRcap_WC_SUPPORTED; 516 } else { 517 /* XXX: exception? */ 518 val = 0; 519 } 520 break; 521 case MSR_MCG_CAP: 522 val = env->mcg_cap; 523 break; 524 case MSR_MCG_CTL: 525 if (env->mcg_cap & MCG_CTL_P) { 526 val = env->mcg_ctl; 527 } else { 528 val = 0; 529 } 530 break; 531 case MSR_MCG_STATUS: 532 val = env->mcg_status; 533 break; 534 case MSR_IA32_MISC_ENABLE: 535 val = env->msr_ia32_misc_enable; 536 break; 537 case MSR_IA32_BNDCFGS: 538 val = env->msr_bndcfgs; 539 break; 540 case MSR_IA32_UCODE_REV: 541 val = x86_cpu->ucode_rev; 542 break; 543 default: 544 if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL 545 && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL + 546 (4 * env->mcg_cap & 0xff)) { 547 uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL; 548 val = env->mce_banks[offset]; 549 break; 550 } 551 /* XXX: exception? */ 552 val = 0; 553 break; 554 } 555 env->regs[R_EAX] = (uint32_t)(val); 556 env->regs[R_EDX] = (uint32_t)(val >> 32); 557 } 558 #endif 559 560 static void do_pause(X86CPU *cpu) 561 { 562 CPUState *cs = CPU(cpu); 563 564 /* Just let another CPU run. */ 565 cs->exception_index = EXCP_INTERRUPT; 566 cpu_loop_exit(cs); 567 } 568 569 static void do_hlt(X86CPU *cpu) 570 { 571 CPUState *cs = CPU(cpu); 572 CPUX86State *env = &cpu->env; 573 574 env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */ 575 cs->halted = 1; 576 cs->exception_index = EXCP_HLT; 577 cpu_loop_exit(cs); 578 } 579 580 void helper_hlt(CPUX86State *env, int next_eip_addend) 581 { 582 X86CPU *cpu = env_archcpu(env); 583 584 cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC()); 585 env->eip += next_eip_addend; 586 587 do_hlt(cpu); 588 } 589 590 void helper_monitor(CPUX86State *env, target_ulong ptr) 591 { 592 if ((uint32_t)env->regs[R_ECX] != 0) { 593 raise_exception_ra(env, EXCP0D_GPF, GETPC()); 594 } 595 /* XXX: store address? */ 596 cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0, GETPC()); 597 } 598 599 void helper_mwait(CPUX86State *env, int next_eip_addend) 600 { 601 CPUState *cs = env_cpu(env); 602 X86CPU *cpu = env_archcpu(env); 603 604 if ((uint32_t)env->regs[R_ECX] != 0) { 605 raise_exception_ra(env, EXCP0D_GPF, GETPC()); 606 } 607 cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0, GETPC()); 608 env->eip += next_eip_addend; 609 610 /* XXX: not complete but not completely erroneous */ 611 if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) { 612 do_pause(cpu); 613 } else { 614 do_hlt(cpu); 615 } 616 } 617 618 void helper_pause(CPUX86State *env, int next_eip_addend) 619 { 620 X86CPU *cpu = env_archcpu(env); 621 622 cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0, GETPC()); 623 env->eip += next_eip_addend; 624 625 do_pause(cpu); 626 } 627 628 void helper_debug(CPUX86State *env) 629 { 630 CPUState *cs = env_cpu(env); 631 632 cs->exception_index = EXCP_DEBUG; 633 cpu_loop_exit(cs); 634 } 635 636 uint64_t helper_rdpkru(CPUX86State *env, uint32_t ecx) 637 { 638 if ((env->cr[4] & CR4_PKE_MASK) == 0) { 639 raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC()); 640 } 641 if (ecx != 0) { 642 raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC()); 643 } 644 645 return env->pkru; 646 } 647 648 void helper_wrpkru(CPUX86State *env, uint32_t ecx, uint64_t val) 649 { 650 CPUState *cs = env_cpu(env); 651 652 if ((env->cr[4] & CR4_PKE_MASK) == 0) { 653 raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC()); 654 } 655 if (ecx != 0 || (val & 0xFFFFFFFF00000000ull)) { 656 raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC()); 657 } 658 659 env->pkru = val; 660 tlb_flush(cs); 661 } 662