1f7b2429fSBlue Swirl /* 2f7b2429fSBlue Swirl * x86 misc helpers 3f7b2429fSBlue Swirl * 4f7b2429fSBlue Swirl * Copyright (c) 2003 Fabrice Bellard 5f7b2429fSBlue Swirl * 6f7b2429fSBlue Swirl * This library is free software; you can redistribute it and/or 7f7b2429fSBlue Swirl * modify it under the terms of the GNU Lesser General Public 8f7b2429fSBlue Swirl * License as published by the Free Software Foundation; either 9d9ff33adSChetan Pant * version 2.1 of the License, or (at your option) any later version. 10f7b2429fSBlue Swirl * 11f7b2429fSBlue Swirl * This library is distributed in the hope that it will be useful, 12f7b2429fSBlue Swirl * but WITHOUT ANY WARRANTY; without even the implied warranty of 13f7b2429fSBlue Swirl * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14f7b2429fSBlue Swirl * Lesser General Public License for more details. 15f7b2429fSBlue Swirl * 16f7b2429fSBlue Swirl * You should have received a copy of the GNU Lesser General Public 17f7b2429fSBlue Swirl * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18f7b2429fSBlue Swirl */ 19f7b2429fSBlue Swirl 20b6a0aa05SPeter Maydell #include "qemu/osdep.h" 21b4e79a50SAlex Bennée #include "qemu/main-loop.h" 22f7b2429fSBlue Swirl #include "cpu.h" 232ef6175aSRichard Henderson #include "exec/helper-proto.h" 2463c91552SPaolo Bonzini #include "exec/exec-all.h" 25f08b6170SPaolo Bonzini #include "exec/cpu_ldst.h" 263f7d8464SPaolo Bonzini #include "exec/address-spaces.h" 27ed69e831SClaudio Fontana #include "helper-tcg.h" 2892fc4b58SBlue Swirl 2969483f31SClaudio Fontana /* 3069483f31SClaudio Fontana * NOTE: the translator must set DisasContext.cc_op to CC_OP_EFLAGS 3169483f31SClaudio Fontana * after generating a call to a helper that uses this. 3269483f31SClaudio Fontana */ 3369483f31SClaudio Fontana void cpu_load_eflags(CPUX86State *env, int eflags, int update_mask) 3469483f31SClaudio Fontana { 3569483f31SClaudio Fontana CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); 3669483f31SClaudio Fontana CC_OP = CC_OP_EFLAGS; 3769483f31SClaudio Fontana env->df = 1 - (2 * ((eflags >> 10) & 1)); 3869483f31SClaudio Fontana env->eflags = (env->eflags & ~update_mask) | 3969483f31SClaudio Fontana (eflags & update_mask) | 0x2; 4069483f31SClaudio Fontana } 4169483f31SClaudio Fontana 423f7d8464SPaolo Bonzini void helper_outb(CPUX86State *env, uint32_t port, uint32_t data) 43f7b2429fSBlue Swirl { 443f7d8464SPaolo Bonzini #ifdef CONFIG_USER_ONLY 453f7d8464SPaolo Bonzini fprintf(stderr, "outb: port=0x%04x, data=%02x\n", port, data); 463f7d8464SPaolo Bonzini #else 473f7d8464SPaolo Bonzini address_space_stb(&address_space_io, port, data, 483f7d8464SPaolo Bonzini cpu_get_mem_attrs(env), NULL); 493f7d8464SPaolo Bonzini #endif 50f7b2429fSBlue Swirl } 51f7b2429fSBlue Swirl 523f7d8464SPaolo Bonzini target_ulong helper_inb(CPUX86State *env, uint32_t port) 53f7b2429fSBlue Swirl { 543f7d8464SPaolo Bonzini #ifdef CONFIG_USER_ONLY 553f7d8464SPaolo Bonzini fprintf(stderr, "inb: port=0x%04x\n", port); 563f7d8464SPaolo Bonzini return 0; 573f7d8464SPaolo Bonzini #else 583f7d8464SPaolo Bonzini return address_space_ldub(&address_space_io, port, 593f7d8464SPaolo Bonzini cpu_get_mem_attrs(env), NULL); 603f7d8464SPaolo Bonzini #endif 61f7b2429fSBlue Swirl } 62f7b2429fSBlue Swirl 633f7d8464SPaolo Bonzini void helper_outw(CPUX86State *env, uint32_t port, uint32_t data) 64f7b2429fSBlue Swirl { 653f7d8464SPaolo Bonzini #ifdef CONFIG_USER_ONLY 663f7d8464SPaolo Bonzini fprintf(stderr, "outw: port=0x%04x, data=%04x\n", port, data); 673f7d8464SPaolo Bonzini #else 683f7d8464SPaolo Bonzini address_space_stw(&address_space_io, port, data, 693f7d8464SPaolo Bonzini cpu_get_mem_attrs(env), NULL); 703f7d8464SPaolo Bonzini #endif 71f7b2429fSBlue Swirl } 72f7b2429fSBlue Swirl 733f7d8464SPaolo Bonzini target_ulong helper_inw(CPUX86State *env, uint32_t port) 74f7b2429fSBlue Swirl { 753f7d8464SPaolo Bonzini #ifdef CONFIG_USER_ONLY 763f7d8464SPaolo Bonzini fprintf(stderr, "inw: port=0x%04x\n", port); 773f7d8464SPaolo Bonzini return 0; 783f7d8464SPaolo Bonzini #else 793f7d8464SPaolo Bonzini return address_space_lduw(&address_space_io, port, 803f7d8464SPaolo Bonzini cpu_get_mem_attrs(env), NULL); 813f7d8464SPaolo Bonzini #endif 82f7b2429fSBlue Swirl } 83f7b2429fSBlue Swirl 843f7d8464SPaolo Bonzini void helper_outl(CPUX86State *env, uint32_t port, uint32_t data) 85f7b2429fSBlue Swirl { 863f7d8464SPaolo Bonzini #ifdef CONFIG_USER_ONLY 87ce8540fdSPhilippe Mathieu-Daudé fprintf(stderr, "outl: port=0x%04x, data=%08x\n", port, data); 883f7d8464SPaolo Bonzini #else 893f7d8464SPaolo Bonzini address_space_stl(&address_space_io, port, data, 903f7d8464SPaolo Bonzini cpu_get_mem_attrs(env), NULL); 913f7d8464SPaolo Bonzini #endif 92f7b2429fSBlue Swirl } 93f7b2429fSBlue Swirl 943f7d8464SPaolo Bonzini target_ulong helper_inl(CPUX86State *env, uint32_t port) 95f7b2429fSBlue Swirl { 963f7d8464SPaolo Bonzini #ifdef CONFIG_USER_ONLY 973f7d8464SPaolo Bonzini fprintf(stderr, "inl: port=0x%04x\n", port); 983f7d8464SPaolo Bonzini return 0; 993f7d8464SPaolo Bonzini #else 1003f7d8464SPaolo Bonzini return address_space_ldl(&address_space_io, port, 1013f7d8464SPaolo Bonzini cpu_get_mem_attrs(env), NULL); 1023f7d8464SPaolo Bonzini #endif 103f7b2429fSBlue Swirl } 104f7b2429fSBlue Swirl 1054a7443beSBlue Swirl void helper_into(CPUX86State *env, int next_eip_addend) 106f7b2429fSBlue Swirl { 107f7b2429fSBlue Swirl int eflags; 108f7b2429fSBlue Swirl 109f0967a1aSBlue Swirl eflags = cpu_cc_compute_all(env, CC_OP); 110f7b2429fSBlue Swirl if (eflags & CC_O) { 111f7b2429fSBlue Swirl raise_interrupt(env, EXCP04_INTO, 1, 0, next_eip_addend); 112f7b2429fSBlue Swirl } 113f7b2429fSBlue Swirl } 114f7b2429fSBlue Swirl 1154a7443beSBlue Swirl void helper_cpuid(CPUX86State *env) 116f7b2429fSBlue Swirl { 117f7b2429fSBlue Swirl uint32_t eax, ebx, ecx, edx; 118f7b2429fSBlue Swirl 11965c9d60aSPaolo Bonzini cpu_svm_check_intercept_param(env, SVM_EXIT_CPUID, 0, GETPC()); 120f7b2429fSBlue Swirl 12190a2541bSliguang cpu_x86_cpuid(env, (uint32_t)env->regs[R_EAX], (uint32_t)env->regs[R_ECX], 12290a2541bSliguang &eax, &ebx, &ecx, &edx); 1234b34e3adSliguang env->regs[R_EAX] = eax; 12470b51365Sliguang env->regs[R_EBX] = ebx; 125a4165610Sliguang env->regs[R_ECX] = ecx; 12600f5e6f2Sliguang env->regs[R_EDX] = edx; 127f7b2429fSBlue Swirl } 128f7b2429fSBlue Swirl 129f7b2429fSBlue Swirl #if defined(CONFIG_USER_ONLY) 1304a7443beSBlue Swirl target_ulong helper_read_crN(CPUX86State *env, int reg) 131f7b2429fSBlue Swirl { 132f7b2429fSBlue Swirl return 0; 133f7b2429fSBlue Swirl } 134f7b2429fSBlue Swirl 1354a7443beSBlue Swirl void helper_write_crN(CPUX86State *env, int reg, target_ulong t0) 136f7b2429fSBlue Swirl { 137f7b2429fSBlue Swirl } 138f7b2429fSBlue Swirl #else 1394a7443beSBlue Swirl target_ulong helper_read_crN(CPUX86State *env, int reg) 140f7b2429fSBlue Swirl { 141f7b2429fSBlue Swirl target_ulong val; 142f7b2429fSBlue Swirl 14365c9d60aSPaolo Bonzini cpu_svm_check_intercept_param(env, SVM_EXIT_READ_CR0 + reg, 0, GETPC()); 144f7b2429fSBlue Swirl switch (reg) { 145f7b2429fSBlue Swirl default: 146f7b2429fSBlue Swirl val = env->cr[reg]; 147f7b2429fSBlue Swirl break; 148f7b2429fSBlue Swirl case 8: 149f7b2429fSBlue Swirl if (!(env->hflags2 & HF2_VINTR_MASK)) { 1506aa9e42fSRichard Henderson val = cpu_get_apic_tpr(env_archcpu(env)->apic_state); 151f7b2429fSBlue Swirl } else { 152f7b2429fSBlue Swirl val = env->v_tpr; 153f7b2429fSBlue Swirl } 154f7b2429fSBlue Swirl break; 155f7b2429fSBlue Swirl } 156f7b2429fSBlue Swirl return val; 157f7b2429fSBlue Swirl } 158f7b2429fSBlue Swirl 1594a7443beSBlue Swirl void helper_write_crN(CPUX86State *env, int reg, target_ulong t0) 160f7b2429fSBlue Swirl { 16165c9d60aSPaolo Bonzini cpu_svm_check_intercept_param(env, SVM_EXIT_WRITE_CR0 + reg, 0, GETPC()); 162f7b2429fSBlue Swirl switch (reg) { 163f7b2429fSBlue Swirl case 0: 164f7b2429fSBlue Swirl cpu_x86_update_cr0(env, t0); 165f7b2429fSBlue Swirl break; 166f7b2429fSBlue Swirl case 3: 167f7b2429fSBlue Swirl cpu_x86_update_cr3(env, t0); 168f7b2429fSBlue Swirl break; 169f7b2429fSBlue Swirl case 4: 170f7b2429fSBlue Swirl cpu_x86_update_cr4(env, t0); 171f7b2429fSBlue Swirl break; 172f7b2429fSBlue Swirl case 8: 173f7b2429fSBlue Swirl if (!(env->hflags2 & HF2_VINTR_MASK)) { 174b4e79a50SAlex Bennée qemu_mutex_lock_iothread(); 1756aa9e42fSRichard Henderson cpu_set_apic_tpr(env_archcpu(env)->apic_state, t0); 176b4e79a50SAlex Bennée qemu_mutex_unlock_iothread(); 177f7b2429fSBlue Swirl } 178f7b2429fSBlue Swirl env->v_tpr = t0 & 0x0f; 179f7b2429fSBlue Swirl break; 180f7b2429fSBlue Swirl default: 181f7b2429fSBlue Swirl env->cr[reg] = t0; 182f7b2429fSBlue Swirl break; 183f7b2429fSBlue Swirl } 184f7b2429fSBlue Swirl } 185f7b2429fSBlue Swirl #endif 186f7b2429fSBlue Swirl 1874a7443beSBlue Swirl void helper_lmsw(CPUX86State *env, target_ulong t0) 188f7b2429fSBlue Swirl { 189f7b2429fSBlue Swirl /* only 4 lower bits of CR0 are modified. PE cannot be set to zero 190f7b2429fSBlue Swirl if already set to one. */ 191f7b2429fSBlue Swirl t0 = (env->cr[0] & ~0xe) | (t0 & 0xf); 1924a7443beSBlue Swirl helper_write_crN(env, 0, t0); 193f7b2429fSBlue Swirl } 194f7b2429fSBlue Swirl 1954a7443beSBlue Swirl void helper_invlpg(CPUX86State *env, target_ulong addr) 196f7b2429fSBlue Swirl { 1976aa9e42fSRichard Henderson X86CPU *cpu = env_archcpu(env); 19831b030d4SAndreas Färber 19965c9d60aSPaolo Bonzini cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0, GETPC()); 20031b030d4SAndreas Färber tlb_flush_page(CPU(cpu), addr); 201f7b2429fSBlue Swirl } 202f7b2429fSBlue Swirl 2034a7443beSBlue Swirl void helper_rdtsc(CPUX86State *env) 204f7b2429fSBlue Swirl { 205f7b2429fSBlue Swirl uint64_t val; 206f7b2429fSBlue Swirl 207f7b2429fSBlue Swirl if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { 2084054cdecSPavel Dovgalyuk raise_exception_ra(env, EXCP0D_GPF, GETPC()); 209f7b2429fSBlue Swirl } 21065c9d60aSPaolo Bonzini cpu_svm_check_intercept_param(env, SVM_EXIT_RDTSC, 0, GETPC()); 211f7b2429fSBlue Swirl 212f7b2429fSBlue Swirl val = cpu_get_tsc(env) + env->tsc_offset; 2134b34e3adSliguang env->regs[R_EAX] = (uint32_t)(val); 21400f5e6f2Sliguang env->regs[R_EDX] = (uint32_t)(val >> 32); 215f7b2429fSBlue Swirl } 216f7b2429fSBlue Swirl 2174a7443beSBlue Swirl void helper_rdtscp(CPUX86State *env) 218f7b2429fSBlue Swirl { 2194a7443beSBlue Swirl helper_rdtsc(env); 220a4165610Sliguang env->regs[R_ECX] = (uint32_t)(env->tsc_aux); 221f7b2429fSBlue Swirl } 222f7b2429fSBlue Swirl 2234a7443beSBlue Swirl void helper_rdpmc(CPUX86State *env) 224f7b2429fSBlue Swirl { 225*c45b426aSZheng Zhan Liang if (((env->cr[4] & CR4_PCE_MASK) == 0 ) && 226*c45b426aSZheng Zhan Liang ((env->hflags & HF_CPL_MASK) != 0)) { 2274054cdecSPavel Dovgalyuk raise_exception_ra(env, EXCP0D_GPF, GETPC()); 228f7b2429fSBlue Swirl } 22965c9d60aSPaolo Bonzini cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0, GETPC()); 230f7b2429fSBlue Swirl 231f7b2429fSBlue Swirl /* currently unimplemented */ 232f7b2429fSBlue Swirl qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n"); 233f7b2429fSBlue Swirl raise_exception_err(env, EXCP06_ILLOP, 0); 234f7b2429fSBlue Swirl } 235f7b2429fSBlue Swirl 236f7b2429fSBlue Swirl #if defined(CONFIG_USER_ONLY) 2374a7443beSBlue Swirl void helper_wrmsr(CPUX86State *env) 238f7b2429fSBlue Swirl { 239f7b2429fSBlue Swirl } 240f7b2429fSBlue Swirl 2414a7443beSBlue Swirl void helper_rdmsr(CPUX86State *env) 242f7b2429fSBlue Swirl { 243f7b2429fSBlue Swirl } 244f7b2429fSBlue Swirl #else 2454a7443beSBlue Swirl void helper_wrmsr(CPUX86State *env) 246f7b2429fSBlue Swirl { 247f7b2429fSBlue Swirl uint64_t val; 248e7e7bdabSPaolo Bonzini CPUState *cs = env_cpu(env); 249f7b2429fSBlue Swirl 25065c9d60aSPaolo Bonzini cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC()); 251f7b2429fSBlue Swirl 25290a2541bSliguang val = ((uint32_t)env->regs[R_EAX]) | 25390a2541bSliguang ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); 254f7b2429fSBlue Swirl 255a4165610Sliguang switch ((uint32_t)env->regs[R_ECX]) { 256f7b2429fSBlue Swirl case MSR_IA32_SYSENTER_CS: 257f7b2429fSBlue Swirl env->sysenter_cs = val & 0xffff; 258f7b2429fSBlue Swirl break; 259f7b2429fSBlue Swirl case MSR_IA32_SYSENTER_ESP: 260f7b2429fSBlue Swirl env->sysenter_esp = val; 261f7b2429fSBlue Swirl break; 262f7b2429fSBlue Swirl case MSR_IA32_SYSENTER_EIP: 263f7b2429fSBlue Swirl env->sysenter_eip = val; 264f7b2429fSBlue Swirl break; 265f7b2429fSBlue Swirl case MSR_IA32_APICBASE: 2666aa9e42fSRichard Henderson cpu_set_apic_base(env_archcpu(env)->apic_state, val); 267f7b2429fSBlue Swirl break; 268f7b2429fSBlue Swirl case MSR_EFER: 269f7b2429fSBlue Swirl { 270f7b2429fSBlue Swirl uint64_t update_mask; 271f7b2429fSBlue Swirl 272f7b2429fSBlue Swirl update_mask = 0; 2730514ef2fSEduardo Habkost if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) { 274f7b2429fSBlue Swirl update_mask |= MSR_EFER_SCE; 275f7b2429fSBlue Swirl } 2760514ef2fSEduardo Habkost if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) { 277f7b2429fSBlue Swirl update_mask |= MSR_EFER_LME; 278f7b2429fSBlue Swirl } 2790514ef2fSEduardo Habkost if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) { 280f7b2429fSBlue Swirl update_mask |= MSR_EFER_FFXSR; 281f7b2429fSBlue Swirl } 2820514ef2fSEduardo Habkost if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) { 283f7b2429fSBlue Swirl update_mask |= MSR_EFER_NXE; 284f7b2429fSBlue Swirl } 2850514ef2fSEduardo Habkost if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) { 286f7b2429fSBlue Swirl update_mask |= MSR_EFER_SVME; 287f7b2429fSBlue Swirl } 2880514ef2fSEduardo Habkost if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) { 289f7b2429fSBlue Swirl update_mask |= MSR_EFER_FFXSR; 290f7b2429fSBlue Swirl } 291f7b2429fSBlue Swirl cpu_load_efer(env, (env->efer & ~update_mask) | 292f7b2429fSBlue Swirl (val & update_mask)); 293f7b2429fSBlue Swirl } 294f7b2429fSBlue Swirl break; 295f7b2429fSBlue Swirl case MSR_STAR: 296f7b2429fSBlue Swirl env->star = val; 297f7b2429fSBlue Swirl break; 298f7b2429fSBlue Swirl case MSR_PAT: 299f7b2429fSBlue Swirl env->pat = val; 300f7b2429fSBlue Swirl break; 301e7e7bdabSPaolo Bonzini case MSR_IA32_PKRS: 302e7e7bdabSPaolo Bonzini if (val & 0xFFFFFFFF00000000ull) { 303e7e7bdabSPaolo Bonzini goto error; 304e7e7bdabSPaolo Bonzini } 305e7e7bdabSPaolo Bonzini env->pkrs = val; 306e7e7bdabSPaolo Bonzini tlb_flush(cs); 307e7e7bdabSPaolo Bonzini break; 308f7b2429fSBlue Swirl case MSR_VM_HSAVE_PA: 309f7b2429fSBlue Swirl env->vm_hsave = val; 310f7b2429fSBlue Swirl break; 311f7b2429fSBlue Swirl #ifdef TARGET_X86_64 312f7b2429fSBlue Swirl case MSR_LSTAR: 313f7b2429fSBlue Swirl env->lstar = val; 314f7b2429fSBlue Swirl break; 315f7b2429fSBlue Swirl case MSR_CSTAR: 316f7b2429fSBlue Swirl env->cstar = val; 317f7b2429fSBlue Swirl break; 318f7b2429fSBlue Swirl case MSR_FMASK: 319f7b2429fSBlue Swirl env->fmask = val; 320f7b2429fSBlue Swirl break; 321f7b2429fSBlue Swirl case MSR_FSBASE: 322f7b2429fSBlue Swirl env->segs[R_FS].base = val; 323f7b2429fSBlue Swirl break; 324f7b2429fSBlue Swirl case MSR_GSBASE: 325f7b2429fSBlue Swirl env->segs[R_GS].base = val; 326f7b2429fSBlue Swirl break; 327f7b2429fSBlue Swirl case MSR_KERNELGSBASE: 328f7b2429fSBlue Swirl env->kernelgsbase = val; 329f7b2429fSBlue Swirl break; 330f7b2429fSBlue Swirl #endif 331f7b2429fSBlue Swirl case MSR_MTRRphysBase(0): 332f7b2429fSBlue Swirl case MSR_MTRRphysBase(1): 333f7b2429fSBlue Swirl case MSR_MTRRphysBase(2): 334f7b2429fSBlue Swirl case MSR_MTRRphysBase(3): 335f7b2429fSBlue Swirl case MSR_MTRRphysBase(4): 336f7b2429fSBlue Swirl case MSR_MTRRphysBase(5): 337f7b2429fSBlue Swirl case MSR_MTRRphysBase(6): 338f7b2429fSBlue Swirl case MSR_MTRRphysBase(7): 33990a2541bSliguang env->mtrr_var[((uint32_t)env->regs[R_ECX] - 34090a2541bSliguang MSR_MTRRphysBase(0)) / 2].base = val; 341f7b2429fSBlue Swirl break; 342f7b2429fSBlue Swirl case MSR_MTRRphysMask(0): 343f7b2429fSBlue Swirl case MSR_MTRRphysMask(1): 344f7b2429fSBlue Swirl case MSR_MTRRphysMask(2): 345f7b2429fSBlue Swirl case MSR_MTRRphysMask(3): 346f7b2429fSBlue Swirl case MSR_MTRRphysMask(4): 347f7b2429fSBlue Swirl case MSR_MTRRphysMask(5): 348f7b2429fSBlue Swirl case MSR_MTRRphysMask(6): 349f7b2429fSBlue Swirl case MSR_MTRRphysMask(7): 35090a2541bSliguang env->mtrr_var[((uint32_t)env->regs[R_ECX] - 35190a2541bSliguang MSR_MTRRphysMask(0)) / 2].mask = val; 352f7b2429fSBlue Swirl break; 353f7b2429fSBlue Swirl case MSR_MTRRfix64K_00000: 35490a2541bSliguang env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - 35590a2541bSliguang MSR_MTRRfix64K_00000] = val; 356f7b2429fSBlue Swirl break; 357f7b2429fSBlue Swirl case MSR_MTRRfix16K_80000: 358f7b2429fSBlue Swirl case MSR_MTRRfix16K_A0000: 35990a2541bSliguang env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - 36090a2541bSliguang MSR_MTRRfix16K_80000 + 1] = val; 361f7b2429fSBlue Swirl break; 362f7b2429fSBlue Swirl case MSR_MTRRfix4K_C0000: 363f7b2429fSBlue Swirl case MSR_MTRRfix4K_C8000: 364f7b2429fSBlue Swirl case MSR_MTRRfix4K_D0000: 365f7b2429fSBlue Swirl case MSR_MTRRfix4K_D8000: 366f7b2429fSBlue Swirl case MSR_MTRRfix4K_E0000: 367f7b2429fSBlue Swirl case MSR_MTRRfix4K_E8000: 368f7b2429fSBlue Swirl case MSR_MTRRfix4K_F0000: 369f7b2429fSBlue Swirl case MSR_MTRRfix4K_F8000: 37090a2541bSliguang env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - 37190a2541bSliguang MSR_MTRRfix4K_C0000 + 3] = val; 372f7b2429fSBlue Swirl break; 373f7b2429fSBlue Swirl case MSR_MTRRdefType: 374f7b2429fSBlue Swirl env->mtrr_deftype = val; 375f7b2429fSBlue Swirl break; 376f7b2429fSBlue Swirl case MSR_MCG_STATUS: 377f7b2429fSBlue Swirl env->mcg_status = val; 378f7b2429fSBlue Swirl break; 379f7b2429fSBlue Swirl case MSR_MCG_CTL: 380f7b2429fSBlue Swirl if ((env->mcg_cap & MCG_CTL_P) 381f7b2429fSBlue Swirl && (val == 0 || val == ~(uint64_t)0)) { 382f7b2429fSBlue Swirl env->mcg_ctl = val; 383f7b2429fSBlue Swirl } 384f7b2429fSBlue Swirl break; 385f7b2429fSBlue Swirl case MSR_TSC_AUX: 386f7b2429fSBlue Swirl env->tsc_aux = val; 387f7b2429fSBlue Swirl break; 388f7b2429fSBlue Swirl case MSR_IA32_MISC_ENABLE: 389f7b2429fSBlue Swirl env->msr_ia32_misc_enable = val; 390f7b2429fSBlue Swirl break; 391f4f1110eSRichard Henderson case MSR_IA32_BNDCFGS: 392f4f1110eSRichard Henderson /* FIXME: #GP if reserved bits are set. */ 393f4f1110eSRichard Henderson /* FIXME: Extend highest implemented bit of linear address. */ 394f4f1110eSRichard Henderson env->msr_bndcfgs = val; 395f4f1110eSRichard Henderson cpu_sync_bndcs_hflags(env); 396f4f1110eSRichard Henderson break; 397f7b2429fSBlue Swirl default: 398a4165610Sliguang if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL 39990a2541bSliguang && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL + 40090a2541bSliguang (4 * env->mcg_cap & 0xff)) { 401a4165610Sliguang uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL; 402f7b2429fSBlue Swirl if ((offset & 0x3) != 0 403f7b2429fSBlue Swirl || (val == 0 || val == ~(uint64_t)0)) { 404f7b2429fSBlue Swirl env->mce_banks[offset] = val; 405f7b2429fSBlue Swirl } 406f7b2429fSBlue Swirl break; 407f7b2429fSBlue Swirl } 408f7b2429fSBlue Swirl /* XXX: exception? */ 409f7b2429fSBlue Swirl break; 410f7b2429fSBlue Swirl } 411e7e7bdabSPaolo Bonzini return; 412e7e7bdabSPaolo Bonzini error: 413e7e7bdabSPaolo Bonzini raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC()); 414f7b2429fSBlue Swirl } 415f7b2429fSBlue Swirl 4164a7443beSBlue Swirl void helper_rdmsr(CPUX86State *env) 417f7b2429fSBlue Swirl { 4189028c75cSPaolo Bonzini X86CPU *x86_cpu = env_archcpu(env); 419f7b2429fSBlue Swirl uint64_t val; 420f7b2429fSBlue Swirl 42165c9d60aSPaolo Bonzini cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0, GETPC()); 422f7b2429fSBlue Swirl 423a4165610Sliguang switch ((uint32_t)env->regs[R_ECX]) { 424f7b2429fSBlue Swirl case MSR_IA32_SYSENTER_CS: 425f7b2429fSBlue Swirl val = env->sysenter_cs; 426f7b2429fSBlue Swirl break; 427f7b2429fSBlue Swirl case MSR_IA32_SYSENTER_ESP: 428f7b2429fSBlue Swirl val = env->sysenter_esp; 429f7b2429fSBlue Swirl break; 430f7b2429fSBlue Swirl case MSR_IA32_SYSENTER_EIP: 431f7b2429fSBlue Swirl val = env->sysenter_eip; 432f7b2429fSBlue Swirl break; 433f7b2429fSBlue Swirl case MSR_IA32_APICBASE: 4346aa9e42fSRichard Henderson val = cpu_get_apic_base(env_archcpu(env)->apic_state); 435f7b2429fSBlue Swirl break; 436f7b2429fSBlue Swirl case MSR_EFER: 437f7b2429fSBlue Swirl val = env->efer; 438f7b2429fSBlue Swirl break; 439f7b2429fSBlue Swirl case MSR_STAR: 440f7b2429fSBlue Swirl val = env->star; 441f7b2429fSBlue Swirl break; 442f7b2429fSBlue Swirl case MSR_PAT: 443f7b2429fSBlue Swirl val = env->pat; 444f7b2429fSBlue Swirl break; 445e7e7bdabSPaolo Bonzini case MSR_IA32_PKRS: 446e7e7bdabSPaolo Bonzini val = env->pkrs; 447e7e7bdabSPaolo Bonzini break; 448f7b2429fSBlue Swirl case MSR_VM_HSAVE_PA: 449f7b2429fSBlue Swirl val = env->vm_hsave; 450f7b2429fSBlue Swirl break; 451f7b2429fSBlue Swirl case MSR_IA32_PERF_STATUS: 452f7b2429fSBlue Swirl /* tsc_increment_by_tick */ 453f7b2429fSBlue Swirl val = 1000ULL; 454f7b2429fSBlue Swirl /* CPU multiplier */ 455f7b2429fSBlue Swirl val |= (((uint64_t)4ULL) << 40); 456f7b2429fSBlue Swirl break; 457f7b2429fSBlue Swirl #ifdef TARGET_X86_64 458f7b2429fSBlue Swirl case MSR_LSTAR: 459f7b2429fSBlue Swirl val = env->lstar; 460f7b2429fSBlue Swirl break; 461f7b2429fSBlue Swirl case MSR_CSTAR: 462f7b2429fSBlue Swirl val = env->cstar; 463f7b2429fSBlue Swirl break; 464f7b2429fSBlue Swirl case MSR_FMASK: 465f7b2429fSBlue Swirl val = env->fmask; 466f7b2429fSBlue Swirl break; 467f7b2429fSBlue Swirl case MSR_FSBASE: 468f7b2429fSBlue Swirl val = env->segs[R_FS].base; 469f7b2429fSBlue Swirl break; 470f7b2429fSBlue Swirl case MSR_GSBASE: 471f7b2429fSBlue Swirl val = env->segs[R_GS].base; 472f7b2429fSBlue Swirl break; 473f7b2429fSBlue Swirl case MSR_KERNELGSBASE: 474f7b2429fSBlue Swirl val = env->kernelgsbase; 475f7b2429fSBlue Swirl break; 476f7b2429fSBlue Swirl case MSR_TSC_AUX: 477f7b2429fSBlue Swirl val = env->tsc_aux; 478f7b2429fSBlue Swirl break; 479f7b2429fSBlue Swirl #endif 4801d3db6bdSPaolo Bonzini case MSR_SMI_COUNT: 4811d3db6bdSPaolo Bonzini val = env->msr_smi_count; 4821d3db6bdSPaolo Bonzini break; 483f7b2429fSBlue Swirl case MSR_MTRRphysBase(0): 484f7b2429fSBlue Swirl case MSR_MTRRphysBase(1): 485f7b2429fSBlue Swirl case MSR_MTRRphysBase(2): 486f7b2429fSBlue Swirl case MSR_MTRRphysBase(3): 487f7b2429fSBlue Swirl case MSR_MTRRphysBase(4): 488f7b2429fSBlue Swirl case MSR_MTRRphysBase(5): 489f7b2429fSBlue Swirl case MSR_MTRRphysBase(6): 490f7b2429fSBlue Swirl case MSR_MTRRphysBase(7): 49190a2541bSliguang val = env->mtrr_var[((uint32_t)env->regs[R_ECX] - 49290a2541bSliguang MSR_MTRRphysBase(0)) / 2].base; 493f7b2429fSBlue Swirl break; 494f7b2429fSBlue Swirl case MSR_MTRRphysMask(0): 495f7b2429fSBlue Swirl case MSR_MTRRphysMask(1): 496f7b2429fSBlue Swirl case MSR_MTRRphysMask(2): 497f7b2429fSBlue Swirl case MSR_MTRRphysMask(3): 498f7b2429fSBlue Swirl case MSR_MTRRphysMask(4): 499f7b2429fSBlue Swirl case MSR_MTRRphysMask(5): 500f7b2429fSBlue Swirl case MSR_MTRRphysMask(6): 501f7b2429fSBlue Swirl case MSR_MTRRphysMask(7): 50290a2541bSliguang val = env->mtrr_var[((uint32_t)env->regs[R_ECX] - 50390a2541bSliguang MSR_MTRRphysMask(0)) / 2].mask; 504f7b2429fSBlue Swirl break; 505f7b2429fSBlue Swirl case MSR_MTRRfix64K_00000: 506f7b2429fSBlue Swirl val = env->mtrr_fixed[0]; 507f7b2429fSBlue Swirl break; 508f7b2429fSBlue Swirl case MSR_MTRRfix16K_80000: 509f7b2429fSBlue Swirl case MSR_MTRRfix16K_A0000: 51090a2541bSliguang val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - 51190a2541bSliguang MSR_MTRRfix16K_80000 + 1]; 512f7b2429fSBlue Swirl break; 513f7b2429fSBlue Swirl case MSR_MTRRfix4K_C0000: 514f7b2429fSBlue Swirl case MSR_MTRRfix4K_C8000: 515f7b2429fSBlue Swirl case MSR_MTRRfix4K_D0000: 516f7b2429fSBlue Swirl case MSR_MTRRfix4K_D8000: 517f7b2429fSBlue Swirl case MSR_MTRRfix4K_E0000: 518f7b2429fSBlue Swirl case MSR_MTRRfix4K_E8000: 519f7b2429fSBlue Swirl case MSR_MTRRfix4K_F0000: 520f7b2429fSBlue Swirl case MSR_MTRRfix4K_F8000: 52190a2541bSliguang val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - 52290a2541bSliguang MSR_MTRRfix4K_C0000 + 3]; 523f7b2429fSBlue Swirl break; 524f7b2429fSBlue Swirl case MSR_MTRRdefType: 525f7b2429fSBlue Swirl val = env->mtrr_deftype; 526f7b2429fSBlue Swirl break; 527f7b2429fSBlue Swirl case MSR_MTRRcap: 5280514ef2fSEduardo Habkost if (env->features[FEAT_1_EDX] & CPUID_MTRR) { 529f7b2429fSBlue Swirl val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT | 530f7b2429fSBlue Swirl MSR_MTRRcap_WC_SUPPORTED; 531f7b2429fSBlue Swirl } else { 532f7b2429fSBlue Swirl /* XXX: exception? */ 533f7b2429fSBlue Swirl val = 0; 534f7b2429fSBlue Swirl } 535f7b2429fSBlue Swirl break; 536f7b2429fSBlue Swirl case MSR_MCG_CAP: 537f7b2429fSBlue Swirl val = env->mcg_cap; 538f7b2429fSBlue Swirl break; 539f7b2429fSBlue Swirl case MSR_MCG_CTL: 540f7b2429fSBlue Swirl if (env->mcg_cap & MCG_CTL_P) { 541f7b2429fSBlue Swirl val = env->mcg_ctl; 542f7b2429fSBlue Swirl } else { 543f7b2429fSBlue Swirl val = 0; 544f7b2429fSBlue Swirl } 545f7b2429fSBlue Swirl break; 546f7b2429fSBlue Swirl case MSR_MCG_STATUS: 547f7b2429fSBlue Swirl val = env->mcg_status; 548f7b2429fSBlue Swirl break; 549f7b2429fSBlue Swirl case MSR_IA32_MISC_ENABLE: 550f7b2429fSBlue Swirl val = env->msr_ia32_misc_enable; 551f7b2429fSBlue Swirl break; 552f4f1110eSRichard Henderson case MSR_IA32_BNDCFGS: 553f4f1110eSRichard Henderson val = env->msr_bndcfgs; 554f4f1110eSRichard Henderson break; 5559028c75cSPaolo Bonzini case MSR_IA32_UCODE_REV: 5569028c75cSPaolo Bonzini val = x86_cpu->ucode_rev; 5579028c75cSPaolo Bonzini break; 558f7b2429fSBlue Swirl default: 559a4165610Sliguang if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL 56090a2541bSliguang && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL + 56190a2541bSliguang (4 * env->mcg_cap & 0xff)) { 562a4165610Sliguang uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL; 563f7b2429fSBlue Swirl val = env->mce_banks[offset]; 564f7b2429fSBlue Swirl break; 565f7b2429fSBlue Swirl } 566f7b2429fSBlue Swirl /* XXX: exception? */ 567f7b2429fSBlue Swirl val = 0; 568f7b2429fSBlue Swirl break; 569f7b2429fSBlue Swirl } 5704b34e3adSliguang env->regs[R_EAX] = (uint32_t)(val); 57100f5e6f2Sliguang env->regs[R_EDX] = (uint32_t)(val >> 32); 572f7b2429fSBlue Swirl } 573f7b2429fSBlue Swirl #endif 574f7b2429fSBlue Swirl 57581f3053bSPaolo Bonzini static void do_pause(X86CPU *cpu) 57681f3053bSPaolo Bonzini { 57727103424SAndreas Färber CPUState *cs = CPU(cpu); 57881f3053bSPaolo Bonzini 57981f3053bSPaolo Bonzini /* Just let another CPU run. */ 58027103424SAndreas Färber cs->exception_index = EXCP_INTERRUPT; 5815638d180SAndreas Färber cpu_loop_exit(cs); 58281f3053bSPaolo Bonzini } 58381f3053bSPaolo Bonzini 584259186a7SAndreas Färber static void do_hlt(X86CPU *cpu) 585f7b2429fSBlue Swirl { 586259186a7SAndreas Färber CPUState *cs = CPU(cpu); 587259186a7SAndreas Färber CPUX86State *env = &cpu->env; 588259186a7SAndreas Färber 589f7b2429fSBlue Swirl env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */ 590259186a7SAndreas Färber cs->halted = 1; 59127103424SAndreas Färber cs->exception_index = EXCP_HLT; 5925638d180SAndreas Färber cpu_loop_exit(cs); 593f7b2429fSBlue Swirl } 594f7b2429fSBlue Swirl 5954a7443beSBlue Swirl void helper_hlt(CPUX86State *env, int next_eip_addend) 596f7b2429fSBlue Swirl { 5976aa9e42fSRichard Henderson X86CPU *cpu = env_archcpu(env); 598259186a7SAndreas Färber 59965c9d60aSPaolo Bonzini cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC()); 600a78d0eabSliguang env->eip += next_eip_addend; 601f7b2429fSBlue Swirl 602259186a7SAndreas Färber do_hlt(cpu); 603f7b2429fSBlue Swirl } 604f7b2429fSBlue Swirl 6054a7443beSBlue Swirl void helper_monitor(CPUX86State *env, target_ulong ptr) 606f7b2429fSBlue Swirl { 607a4165610Sliguang if ((uint32_t)env->regs[R_ECX] != 0) { 6084054cdecSPavel Dovgalyuk raise_exception_ra(env, EXCP0D_GPF, GETPC()); 609f7b2429fSBlue Swirl } 610f7b2429fSBlue Swirl /* XXX: store address? */ 61165c9d60aSPaolo Bonzini cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0, GETPC()); 612f7b2429fSBlue Swirl } 613f7b2429fSBlue Swirl 6144a7443beSBlue Swirl void helper_mwait(CPUX86State *env, int next_eip_addend) 615f7b2429fSBlue Swirl { 6166aa9e42fSRichard Henderson CPUState *cs = env_cpu(env); 6176aa9e42fSRichard Henderson X86CPU *cpu = env_archcpu(env); 61855e5c285SAndreas Färber 619a4165610Sliguang if ((uint32_t)env->regs[R_ECX] != 0) { 6204054cdecSPavel Dovgalyuk raise_exception_ra(env, EXCP0D_GPF, GETPC()); 621f7b2429fSBlue Swirl } 62265c9d60aSPaolo Bonzini cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0, GETPC()); 623a78d0eabSliguang env->eip += next_eip_addend; 624f7b2429fSBlue Swirl 625f7b2429fSBlue Swirl /* XXX: not complete but not completely erroneous */ 626bdc44640SAndreas Färber if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) { 62781f3053bSPaolo Bonzini do_pause(cpu); 628f7b2429fSBlue Swirl } else { 629259186a7SAndreas Färber do_hlt(cpu); 630f7b2429fSBlue Swirl } 631f7b2429fSBlue Swirl } 632f7b2429fSBlue Swirl 63381f3053bSPaolo Bonzini void helper_pause(CPUX86State *env, int next_eip_addend) 63481f3053bSPaolo Bonzini { 6356aa9e42fSRichard Henderson X86CPU *cpu = env_archcpu(env); 63681f3053bSPaolo Bonzini 63765c9d60aSPaolo Bonzini cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0, GETPC()); 63881f3053bSPaolo Bonzini env->eip += next_eip_addend; 63981f3053bSPaolo Bonzini 64081f3053bSPaolo Bonzini do_pause(cpu); 64181f3053bSPaolo Bonzini } 64281f3053bSPaolo Bonzini 6434a7443beSBlue Swirl void helper_debug(CPUX86State *env) 644f7b2429fSBlue Swirl { 6456aa9e42fSRichard Henderson CPUState *cs = env_cpu(env); 64627103424SAndreas Färber 64727103424SAndreas Färber cs->exception_index = EXCP_DEBUG; 6485638d180SAndreas Färber cpu_loop_exit(cs); 649f7b2429fSBlue Swirl } 6500f70ed47SPaolo Bonzini 6510f70ed47SPaolo Bonzini uint64_t helper_rdpkru(CPUX86State *env, uint32_t ecx) 6520f70ed47SPaolo Bonzini { 6530f70ed47SPaolo Bonzini if ((env->cr[4] & CR4_PKE_MASK) == 0) { 6540f70ed47SPaolo Bonzini raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC()); 6550f70ed47SPaolo Bonzini } 6560f70ed47SPaolo Bonzini if (ecx != 0) { 6570f70ed47SPaolo Bonzini raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC()); 6580f70ed47SPaolo Bonzini } 6590f70ed47SPaolo Bonzini 6600f70ed47SPaolo Bonzini return env->pkru; 6610f70ed47SPaolo Bonzini } 6620f70ed47SPaolo Bonzini 6630f70ed47SPaolo Bonzini void helper_wrpkru(CPUX86State *env, uint32_t ecx, uint64_t val) 6640f70ed47SPaolo Bonzini { 6656aa9e42fSRichard Henderson CPUState *cs = env_cpu(env); 6660f70ed47SPaolo Bonzini 6670f70ed47SPaolo Bonzini if ((env->cr[4] & CR4_PKE_MASK) == 0) { 6680f70ed47SPaolo Bonzini raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC()); 6690f70ed47SPaolo Bonzini } 6700f70ed47SPaolo Bonzini if (ecx != 0 || (val & 0xFFFFFFFF00000000ull)) { 6710f70ed47SPaolo Bonzini raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC()); 6720f70ed47SPaolo Bonzini } 6730f70ed47SPaolo Bonzini 6740f70ed47SPaolo Bonzini env->pkru = val; 675d10eb08fSAlex Bennée tlb_flush(cs); 6760f70ed47SPaolo Bonzini } 677