1 /* 2 * x86 misc helpers - sysemu code 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/cpu_ldst.h" 25 #include "exec/address-spaces.h" 26 #include "tcg/helper-tcg.h" 27 28 void helper_outb(CPUX86State *env, uint32_t port, uint32_t data) 29 { 30 address_space_stb(&address_space_io, port, data, 31 cpu_get_mem_attrs(env), NULL); 32 } 33 34 target_ulong helper_inb(CPUX86State *env, uint32_t port) 35 { 36 return address_space_ldub(&address_space_io, port, 37 cpu_get_mem_attrs(env), NULL); 38 } 39 40 void helper_outw(CPUX86State *env, uint32_t port, uint32_t data) 41 { 42 address_space_stw(&address_space_io, port, data, 43 cpu_get_mem_attrs(env), NULL); 44 } 45 46 target_ulong helper_inw(CPUX86State *env, uint32_t port) 47 { 48 return address_space_lduw(&address_space_io, port, 49 cpu_get_mem_attrs(env), NULL); 50 } 51 52 void helper_outl(CPUX86State *env, uint32_t port, uint32_t data) 53 { 54 address_space_stl(&address_space_io, port, data, 55 cpu_get_mem_attrs(env), NULL); 56 } 57 58 target_ulong helper_inl(CPUX86State *env, uint32_t port) 59 { 60 return address_space_ldl(&address_space_io, port, 61 cpu_get_mem_attrs(env), NULL); 62 } 63 64 target_ulong helper_read_crN(CPUX86State *env, int reg) 65 { 66 target_ulong val; 67 68 switch (reg) { 69 default: 70 val = env->cr[reg]; 71 break; 72 case 8: 73 if (!(env->hflags2 & HF2_VINTR_MASK)) { 74 val = cpu_get_apic_tpr(env_archcpu(env)->apic_state); 75 } else { 76 val = env->v_tpr; 77 } 78 break; 79 } 80 return val; 81 } 82 83 void helper_write_crN(CPUX86State *env, int reg, target_ulong t0) 84 { 85 switch (reg) { 86 case 0: 87 cpu_x86_update_cr0(env, t0); 88 break; 89 case 3: 90 cpu_x86_update_cr3(env, t0); 91 break; 92 case 4: 93 if (((t0 ^ env->cr[4]) & CR4_LA57_MASK) && 94 (env->hflags & HF_CS64_MASK)) { 95 raise_exception_ra(env, EXCP0D_GPF, GETPC()); 96 } 97 cpu_x86_update_cr4(env, t0); 98 break; 99 case 8: 100 if (!(env->hflags2 & HF2_VINTR_MASK)) { 101 qemu_mutex_lock_iothread(); 102 cpu_set_apic_tpr(env_archcpu(env)->apic_state, t0); 103 qemu_mutex_unlock_iothread(); 104 } 105 env->v_tpr = t0 & 0x0f; 106 break; 107 default: 108 env->cr[reg] = t0; 109 break; 110 } 111 } 112 113 void helper_wrmsr(CPUX86State *env) 114 { 115 uint64_t val; 116 CPUState *cs = env_cpu(env); 117 118 cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC()); 119 120 val = ((uint32_t)env->regs[R_EAX]) | 121 ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); 122 123 switch ((uint32_t)env->regs[R_ECX]) { 124 case MSR_IA32_SYSENTER_CS: 125 env->sysenter_cs = val & 0xffff; 126 break; 127 case MSR_IA32_SYSENTER_ESP: 128 env->sysenter_esp = val; 129 break; 130 case MSR_IA32_SYSENTER_EIP: 131 env->sysenter_eip = val; 132 break; 133 case MSR_IA32_APICBASE: 134 cpu_set_apic_base(env_archcpu(env)->apic_state, val); 135 break; 136 case MSR_EFER: 137 { 138 uint64_t update_mask; 139 140 update_mask = 0; 141 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) { 142 update_mask |= MSR_EFER_SCE; 143 } 144 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) { 145 update_mask |= MSR_EFER_LME; 146 } 147 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) { 148 update_mask |= MSR_EFER_FFXSR; 149 } 150 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) { 151 update_mask |= MSR_EFER_NXE; 152 } 153 if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) { 154 update_mask |= MSR_EFER_SVME; 155 } 156 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) { 157 update_mask |= MSR_EFER_FFXSR; 158 } 159 cpu_load_efer(env, (env->efer & ~update_mask) | 160 (val & update_mask)); 161 } 162 break; 163 case MSR_STAR: 164 env->star = val; 165 break; 166 case MSR_PAT: 167 env->pat = val; 168 break; 169 case MSR_IA32_PKRS: 170 if (val & 0xFFFFFFFF00000000ull) { 171 goto error; 172 } 173 env->pkrs = val; 174 tlb_flush(cs); 175 break; 176 case MSR_VM_HSAVE_PA: 177 env->vm_hsave = val; 178 break; 179 #ifdef TARGET_X86_64 180 case MSR_LSTAR: 181 env->lstar = val; 182 break; 183 case MSR_CSTAR: 184 env->cstar = val; 185 break; 186 case MSR_FMASK: 187 env->fmask = val; 188 break; 189 case MSR_FSBASE: 190 env->segs[R_FS].base = val; 191 break; 192 case MSR_GSBASE: 193 env->segs[R_GS].base = val; 194 break; 195 case MSR_KERNELGSBASE: 196 env->kernelgsbase = val; 197 break; 198 #endif 199 case MSR_MTRRphysBase(0): 200 case MSR_MTRRphysBase(1): 201 case MSR_MTRRphysBase(2): 202 case MSR_MTRRphysBase(3): 203 case MSR_MTRRphysBase(4): 204 case MSR_MTRRphysBase(5): 205 case MSR_MTRRphysBase(6): 206 case MSR_MTRRphysBase(7): 207 env->mtrr_var[((uint32_t)env->regs[R_ECX] - 208 MSR_MTRRphysBase(0)) / 2].base = val; 209 break; 210 case MSR_MTRRphysMask(0): 211 case MSR_MTRRphysMask(1): 212 case MSR_MTRRphysMask(2): 213 case MSR_MTRRphysMask(3): 214 case MSR_MTRRphysMask(4): 215 case MSR_MTRRphysMask(5): 216 case MSR_MTRRphysMask(6): 217 case MSR_MTRRphysMask(7): 218 env->mtrr_var[((uint32_t)env->regs[R_ECX] - 219 MSR_MTRRphysMask(0)) / 2].mask = val; 220 break; 221 case MSR_MTRRfix64K_00000: 222 env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - 223 MSR_MTRRfix64K_00000] = val; 224 break; 225 case MSR_MTRRfix16K_80000: 226 case MSR_MTRRfix16K_A0000: 227 env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - 228 MSR_MTRRfix16K_80000 + 1] = val; 229 break; 230 case MSR_MTRRfix4K_C0000: 231 case MSR_MTRRfix4K_C8000: 232 case MSR_MTRRfix4K_D0000: 233 case MSR_MTRRfix4K_D8000: 234 case MSR_MTRRfix4K_E0000: 235 case MSR_MTRRfix4K_E8000: 236 case MSR_MTRRfix4K_F0000: 237 case MSR_MTRRfix4K_F8000: 238 env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - 239 MSR_MTRRfix4K_C0000 + 3] = val; 240 break; 241 case MSR_MTRRdefType: 242 env->mtrr_deftype = val; 243 break; 244 case MSR_MCG_STATUS: 245 env->mcg_status = val; 246 break; 247 case MSR_MCG_CTL: 248 if ((env->mcg_cap & MCG_CTL_P) 249 && (val == 0 || val == ~(uint64_t)0)) { 250 env->mcg_ctl = val; 251 } 252 break; 253 case MSR_TSC_AUX: 254 env->tsc_aux = val; 255 break; 256 case MSR_IA32_MISC_ENABLE: 257 env->msr_ia32_misc_enable = val; 258 break; 259 case MSR_IA32_BNDCFGS: 260 /* FIXME: #GP if reserved bits are set. */ 261 /* FIXME: Extend highest implemented bit of linear address. */ 262 env->msr_bndcfgs = val; 263 cpu_sync_bndcs_hflags(env); 264 break; 265 default: 266 if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL 267 && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL + 268 (4 * env->mcg_cap & 0xff)) { 269 uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL; 270 if ((offset & 0x3) != 0 271 || (val == 0 || val == ~(uint64_t)0)) { 272 env->mce_banks[offset] = val; 273 } 274 break; 275 } 276 /* XXX: exception? */ 277 break; 278 } 279 return; 280 error: 281 raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC()); 282 } 283 284 void helper_rdmsr(CPUX86State *env) 285 { 286 X86CPU *x86_cpu = env_archcpu(env); 287 uint64_t val; 288 289 cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0, GETPC()); 290 291 switch ((uint32_t)env->regs[R_ECX]) { 292 case MSR_IA32_SYSENTER_CS: 293 val = env->sysenter_cs; 294 break; 295 case MSR_IA32_SYSENTER_ESP: 296 val = env->sysenter_esp; 297 break; 298 case MSR_IA32_SYSENTER_EIP: 299 val = env->sysenter_eip; 300 break; 301 case MSR_IA32_APICBASE: 302 val = cpu_get_apic_base(env_archcpu(env)->apic_state); 303 break; 304 case MSR_EFER: 305 val = env->efer; 306 break; 307 case MSR_STAR: 308 val = env->star; 309 break; 310 case MSR_PAT: 311 val = env->pat; 312 break; 313 case MSR_IA32_PKRS: 314 val = env->pkrs; 315 break; 316 case MSR_VM_HSAVE_PA: 317 val = env->vm_hsave; 318 break; 319 case MSR_IA32_PERF_STATUS: 320 /* tsc_increment_by_tick */ 321 val = 1000ULL; 322 /* CPU multiplier */ 323 val |= (((uint64_t)4ULL) << 40); 324 break; 325 #ifdef TARGET_X86_64 326 case MSR_LSTAR: 327 val = env->lstar; 328 break; 329 case MSR_CSTAR: 330 val = env->cstar; 331 break; 332 case MSR_FMASK: 333 val = env->fmask; 334 break; 335 case MSR_FSBASE: 336 val = env->segs[R_FS].base; 337 break; 338 case MSR_GSBASE: 339 val = env->segs[R_GS].base; 340 break; 341 case MSR_KERNELGSBASE: 342 val = env->kernelgsbase; 343 break; 344 case MSR_TSC_AUX: 345 val = env->tsc_aux; 346 break; 347 #endif 348 case MSR_SMI_COUNT: 349 val = env->msr_smi_count; 350 break; 351 case MSR_MTRRphysBase(0): 352 case MSR_MTRRphysBase(1): 353 case MSR_MTRRphysBase(2): 354 case MSR_MTRRphysBase(3): 355 case MSR_MTRRphysBase(4): 356 case MSR_MTRRphysBase(5): 357 case MSR_MTRRphysBase(6): 358 case MSR_MTRRphysBase(7): 359 val = env->mtrr_var[((uint32_t)env->regs[R_ECX] - 360 MSR_MTRRphysBase(0)) / 2].base; 361 break; 362 case MSR_MTRRphysMask(0): 363 case MSR_MTRRphysMask(1): 364 case MSR_MTRRphysMask(2): 365 case MSR_MTRRphysMask(3): 366 case MSR_MTRRphysMask(4): 367 case MSR_MTRRphysMask(5): 368 case MSR_MTRRphysMask(6): 369 case MSR_MTRRphysMask(7): 370 val = env->mtrr_var[((uint32_t)env->regs[R_ECX] - 371 MSR_MTRRphysMask(0)) / 2].mask; 372 break; 373 case MSR_MTRRfix64K_00000: 374 val = env->mtrr_fixed[0]; 375 break; 376 case MSR_MTRRfix16K_80000: 377 case MSR_MTRRfix16K_A0000: 378 val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - 379 MSR_MTRRfix16K_80000 + 1]; 380 break; 381 case MSR_MTRRfix4K_C0000: 382 case MSR_MTRRfix4K_C8000: 383 case MSR_MTRRfix4K_D0000: 384 case MSR_MTRRfix4K_D8000: 385 case MSR_MTRRfix4K_E0000: 386 case MSR_MTRRfix4K_E8000: 387 case MSR_MTRRfix4K_F0000: 388 case MSR_MTRRfix4K_F8000: 389 val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - 390 MSR_MTRRfix4K_C0000 + 3]; 391 break; 392 case MSR_MTRRdefType: 393 val = env->mtrr_deftype; 394 break; 395 case MSR_MTRRcap: 396 if (env->features[FEAT_1_EDX] & CPUID_MTRR) { 397 val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT | 398 MSR_MTRRcap_WC_SUPPORTED; 399 } else { 400 /* XXX: exception? */ 401 val = 0; 402 } 403 break; 404 case MSR_MCG_CAP: 405 val = env->mcg_cap; 406 break; 407 case MSR_MCG_CTL: 408 if (env->mcg_cap & MCG_CTL_P) { 409 val = env->mcg_ctl; 410 } else { 411 val = 0; 412 } 413 break; 414 case MSR_MCG_STATUS: 415 val = env->mcg_status; 416 break; 417 case MSR_IA32_MISC_ENABLE: 418 val = env->msr_ia32_misc_enable; 419 break; 420 case MSR_IA32_BNDCFGS: 421 val = env->msr_bndcfgs; 422 break; 423 case MSR_IA32_UCODE_REV: 424 val = x86_cpu->ucode_rev; 425 break; 426 default: 427 if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL 428 && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL + 429 (4 * env->mcg_cap & 0xff)) { 430 uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL; 431 val = env->mce_banks[offset]; 432 break; 433 } 434 /* XXX: exception? */ 435 val = 0; 436 break; 437 } 438 env->regs[R_EAX] = (uint32_t)(val); 439 env->regs[R_EDX] = (uint32_t)(val >> 32); 440 } 441 442 void helper_flush_page(CPUX86State *env, target_ulong addr) 443 { 444 tlb_flush_page(env_cpu(env), addr); 445 } 446 447 static void QEMU_NORETURN do_hlt(CPUX86State *env) 448 { 449 CPUState *cs = env_cpu(env); 450 451 env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */ 452 cs->halted = 1; 453 cs->exception_index = EXCP_HLT; 454 cpu_loop_exit(cs); 455 } 456 457 void QEMU_NORETURN helper_hlt(CPUX86State *env, int next_eip_addend) 458 { 459 cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC()); 460 env->eip += next_eip_addend; 461 462 do_hlt(env); 463 } 464 465 void helper_monitor(CPUX86State *env, target_ulong ptr) 466 { 467 if ((uint32_t)env->regs[R_ECX] != 0) { 468 raise_exception_ra(env, EXCP0D_GPF, GETPC()); 469 } 470 /* XXX: store address? */ 471 cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0, GETPC()); 472 } 473 474 void QEMU_NORETURN helper_mwait(CPUX86State *env, int next_eip_addend) 475 { 476 CPUState *cs = env_cpu(env); 477 478 if ((uint32_t)env->regs[R_ECX] != 0) { 479 raise_exception_ra(env, EXCP0D_GPF, GETPC()); 480 } 481 cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0, GETPC()); 482 env->eip += next_eip_addend; 483 484 /* XXX: not complete but not completely erroneous */ 485 if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) { 486 do_pause(env); 487 } else { 488 do_hlt(env); 489 } 490 } 491