xref: /qemu/target/i386/tcg/misc_helper.c (revision e7e7bdababeefff10736c6adf410c66d2f0d46fe)
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 {
225f7b2429fSBlue Swirl     if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
2264054cdecSPavel Dovgalyuk         raise_exception_ra(env, EXCP0D_GPF, GETPC());
227f7b2429fSBlue Swirl     }
22865c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0, GETPC());
229f7b2429fSBlue Swirl 
230f7b2429fSBlue Swirl     /* currently unimplemented */
231f7b2429fSBlue Swirl     qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n");
232f7b2429fSBlue Swirl     raise_exception_err(env, EXCP06_ILLOP, 0);
233f7b2429fSBlue Swirl }
234f7b2429fSBlue Swirl 
235f7b2429fSBlue Swirl #if defined(CONFIG_USER_ONLY)
2364a7443beSBlue Swirl void helper_wrmsr(CPUX86State *env)
237f7b2429fSBlue Swirl {
238f7b2429fSBlue Swirl }
239f7b2429fSBlue Swirl 
2404a7443beSBlue Swirl void helper_rdmsr(CPUX86State *env)
241f7b2429fSBlue Swirl {
242f7b2429fSBlue Swirl }
243f7b2429fSBlue Swirl #else
2444a7443beSBlue Swirl void helper_wrmsr(CPUX86State *env)
245f7b2429fSBlue Swirl {
246f7b2429fSBlue Swirl     uint64_t val;
247*e7e7bdabSPaolo Bonzini     CPUState *cs = env_cpu(env);
248f7b2429fSBlue Swirl 
24965c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC());
250f7b2429fSBlue Swirl 
25190a2541bSliguang     val = ((uint32_t)env->regs[R_EAX]) |
25290a2541bSliguang         ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
253f7b2429fSBlue Swirl 
254a4165610Sliguang     switch ((uint32_t)env->regs[R_ECX]) {
255f7b2429fSBlue Swirl     case MSR_IA32_SYSENTER_CS:
256f7b2429fSBlue Swirl         env->sysenter_cs = val & 0xffff;
257f7b2429fSBlue Swirl         break;
258f7b2429fSBlue Swirl     case MSR_IA32_SYSENTER_ESP:
259f7b2429fSBlue Swirl         env->sysenter_esp = val;
260f7b2429fSBlue Swirl         break;
261f7b2429fSBlue Swirl     case MSR_IA32_SYSENTER_EIP:
262f7b2429fSBlue Swirl         env->sysenter_eip = val;
263f7b2429fSBlue Swirl         break;
264f7b2429fSBlue Swirl     case MSR_IA32_APICBASE:
2656aa9e42fSRichard Henderson         cpu_set_apic_base(env_archcpu(env)->apic_state, val);
266f7b2429fSBlue Swirl         break;
267f7b2429fSBlue Swirl     case MSR_EFER:
268f7b2429fSBlue Swirl         {
269f7b2429fSBlue Swirl             uint64_t update_mask;
270f7b2429fSBlue Swirl 
271f7b2429fSBlue Swirl             update_mask = 0;
2720514ef2fSEduardo Habkost             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) {
273f7b2429fSBlue Swirl                 update_mask |= MSR_EFER_SCE;
274f7b2429fSBlue Swirl             }
2750514ef2fSEduardo Habkost             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
276f7b2429fSBlue Swirl                 update_mask |= MSR_EFER_LME;
277f7b2429fSBlue Swirl             }
2780514ef2fSEduardo Habkost             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
279f7b2429fSBlue Swirl                 update_mask |= MSR_EFER_FFXSR;
280f7b2429fSBlue Swirl             }
2810514ef2fSEduardo Habkost             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) {
282f7b2429fSBlue Swirl                 update_mask |= MSR_EFER_NXE;
283f7b2429fSBlue Swirl             }
2840514ef2fSEduardo Habkost             if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
285f7b2429fSBlue Swirl                 update_mask |= MSR_EFER_SVME;
286f7b2429fSBlue Swirl             }
2870514ef2fSEduardo Habkost             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
288f7b2429fSBlue Swirl                 update_mask |= MSR_EFER_FFXSR;
289f7b2429fSBlue Swirl             }
290f7b2429fSBlue Swirl             cpu_load_efer(env, (env->efer & ~update_mask) |
291f7b2429fSBlue Swirl                           (val & update_mask));
292f7b2429fSBlue Swirl         }
293f7b2429fSBlue Swirl         break;
294f7b2429fSBlue Swirl     case MSR_STAR:
295f7b2429fSBlue Swirl         env->star = val;
296f7b2429fSBlue Swirl         break;
297f7b2429fSBlue Swirl     case MSR_PAT:
298f7b2429fSBlue Swirl         env->pat = val;
299f7b2429fSBlue Swirl         break;
300*e7e7bdabSPaolo Bonzini     case MSR_IA32_PKRS:
301*e7e7bdabSPaolo Bonzini         if (val & 0xFFFFFFFF00000000ull) {
302*e7e7bdabSPaolo Bonzini             goto error;
303*e7e7bdabSPaolo Bonzini         }
304*e7e7bdabSPaolo Bonzini         env->pkrs = val;
305*e7e7bdabSPaolo Bonzini         tlb_flush(cs);
306*e7e7bdabSPaolo Bonzini         break;
307f7b2429fSBlue Swirl     case MSR_VM_HSAVE_PA:
308f7b2429fSBlue Swirl         env->vm_hsave = val;
309f7b2429fSBlue Swirl         break;
310f7b2429fSBlue Swirl #ifdef TARGET_X86_64
311f7b2429fSBlue Swirl     case MSR_LSTAR:
312f7b2429fSBlue Swirl         env->lstar = val;
313f7b2429fSBlue Swirl         break;
314f7b2429fSBlue Swirl     case MSR_CSTAR:
315f7b2429fSBlue Swirl         env->cstar = val;
316f7b2429fSBlue Swirl         break;
317f7b2429fSBlue Swirl     case MSR_FMASK:
318f7b2429fSBlue Swirl         env->fmask = val;
319f7b2429fSBlue Swirl         break;
320f7b2429fSBlue Swirl     case MSR_FSBASE:
321f7b2429fSBlue Swirl         env->segs[R_FS].base = val;
322f7b2429fSBlue Swirl         break;
323f7b2429fSBlue Swirl     case MSR_GSBASE:
324f7b2429fSBlue Swirl         env->segs[R_GS].base = val;
325f7b2429fSBlue Swirl         break;
326f7b2429fSBlue Swirl     case MSR_KERNELGSBASE:
327f7b2429fSBlue Swirl         env->kernelgsbase = val;
328f7b2429fSBlue Swirl         break;
329f7b2429fSBlue Swirl #endif
330f7b2429fSBlue Swirl     case MSR_MTRRphysBase(0):
331f7b2429fSBlue Swirl     case MSR_MTRRphysBase(1):
332f7b2429fSBlue Swirl     case MSR_MTRRphysBase(2):
333f7b2429fSBlue Swirl     case MSR_MTRRphysBase(3):
334f7b2429fSBlue Swirl     case MSR_MTRRphysBase(4):
335f7b2429fSBlue Swirl     case MSR_MTRRphysBase(5):
336f7b2429fSBlue Swirl     case MSR_MTRRphysBase(6):
337f7b2429fSBlue Swirl     case MSR_MTRRphysBase(7):
33890a2541bSliguang         env->mtrr_var[((uint32_t)env->regs[R_ECX] -
33990a2541bSliguang                        MSR_MTRRphysBase(0)) / 2].base = val;
340f7b2429fSBlue Swirl         break;
341f7b2429fSBlue Swirl     case MSR_MTRRphysMask(0):
342f7b2429fSBlue Swirl     case MSR_MTRRphysMask(1):
343f7b2429fSBlue Swirl     case MSR_MTRRphysMask(2):
344f7b2429fSBlue Swirl     case MSR_MTRRphysMask(3):
345f7b2429fSBlue Swirl     case MSR_MTRRphysMask(4):
346f7b2429fSBlue Swirl     case MSR_MTRRphysMask(5):
347f7b2429fSBlue Swirl     case MSR_MTRRphysMask(6):
348f7b2429fSBlue Swirl     case MSR_MTRRphysMask(7):
34990a2541bSliguang         env->mtrr_var[((uint32_t)env->regs[R_ECX] -
35090a2541bSliguang                        MSR_MTRRphysMask(0)) / 2].mask = val;
351f7b2429fSBlue Swirl         break;
352f7b2429fSBlue Swirl     case MSR_MTRRfix64K_00000:
35390a2541bSliguang         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
35490a2541bSliguang                         MSR_MTRRfix64K_00000] = val;
355f7b2429fSBlue Swirl         break;
356f7b2429fSBlue Swirl     case MSR_MTRRfix16K_80000:
357f7b2429fSBlue Swirl     case MSR_MTRRfix16K_A0000:
35890a2541bSliguang         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
35990a2541bSliguang                         MSR_MTRRfix16K_80000 + 1] = val;
360f7b2429fSBlue Swirl         break;
361f7b2429fSBlue Swirl     case MSR_MTRRfix4K_C0000:
362f7b2429fSBlue Swirl     case MSR_MTRRfix4K_C8000:
363f7b2429fSBlue Swirl     case MSR_MTRRfix4K_D0000:
364f7b2429fSBlue Swirl     case MSR_MTRRfix4K_D8000:
365f7b2429fSBlue Swirl     case MSR_MTRRfix4K_E0000:
366f7b2429fSBlue Swirl     case MSR_MTRRfix4K_E8000:
367f7b2429fSBlue Swirl     case MSR_MTRRfix4K_F0000:
368f7b2429fSBlue Swirl     case MSR_MTRRfix4K_F8000:
36990a2541bSliguang         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
37090a2541bSliguang                         MSR_MTRRfix4K_C0000 + 3] = val;
371f7b2429fSBlue Swirl         break;
372f7b2429fSBlue Swirl     case MSR_MTRRdefType:
373f7b2429fSBlue Swirl         env->mtrr_deftype = val;
374f7b2429fSBlue Swirl         break;
375f7b2429fSBlue Swirl     case MSR_MCG_STATUS:
376f7b2429fSBlue Swirl         env->mcg_status = val;
377f7b2429fSBlue Swirl         break;
378f7b2429fSBlue Swirl     case MSR_MCG_CTL:
379f7b2429fSBlue Swirl         if ((env->mcg_cap & MCG_CTL_P)
380f7b2429fSBlue Swirl             && (val == 0 || val == ~(uint64_t)0)) {
381f7b2429fSBlue Swirl             env->mcg_ctl = val;
382f7b2429fSBlue Swirl         }
383f7b2429fSBlue Swirl         break;
384f7b2429fSBlue Swirl     case MSR_TSC_AUX:
385f7b2429fSBlue Swirl         env->tsc_aux = val;
386f7b2429fSBlue Swirl         break;
387f7b2429fSBlue Swirl     case MSR_IA32_MISC_ENABLE:
388f7b2429fSBlue Swirl         env->msr_ia32_misc_enable = val;
389f7b2429fSBlue Swirl         break;
390f4f1110eSRichard Henderson     case MSR_IA32_BNDCFGS:
391f4f1110eSRichard Henderson         /* FIXME: #GP if reserved bits are set.  */
392f4f1110eSRichard Henderson         /* FIXME: Extend highest implemented bit of linear address.  */
393f4f1110eSRichard Henderson         env->msr_bndcfgs = val;
394f4f1110eSRichard Henderson         cpu_sync_bndcs_hflags(env);
395f4f1110eSRichard Henderson         break;
396f7b2429fSBlue Swirl     default:
397a4165610Sliguang         if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
39890a2541bSliguang             && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
39990a2541bSliguang             (4 * env->mcg_cap & 0xff)) {
400a4165610Sliguang             uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
401f7b2429fSBlue Swirl             if ((offset & 0x3) != 0
402f7b2429fSBlue Swirl                 || (val == 0 || val == ~(uint64_t)0)) {
403f7b2429fSBlue Swirl                 env->mce_banks[offset] = val;
404f7b2429fSBlue Swirl             }
405f7b2429fSBlue Swirl             break;
406f7b2429fSBlue Swirl         }
407f7b2429fSBlue Swirl         /* XXX: exception? */
408f7b2429fSBlue Swirl         break;
409f7b2429fSBlue Swirl     }
410*e7e7bdabSPaolo Bonzini     return;
411*e7e7bdabSPaolo Bonzini error:
412*e7e7bdabSPaolo Bonzini     raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
413f7b2429fSBlue Swirl }
414f7b2429fSBlue Swirl 
4154a7443beSBlue Swirl void helper_rdmsr(CPUX86State *env)
416f7b2429fSBlue Swirl {
4179028c75cSPaolo Bonzini     X86CPU *x86_cpu = env_archcpu(env);
418f7b2429fSBlue Swirl     uint64_t val;
419f7b2429fSBlue Swirl 
42065c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0, GETPC());
421f7b2429fSBlue Swirl 
422a4165610Sliguang     switch ((uint32_t)env->regs[R_ECX]) {
423f7b2429fSBlue Swirl     case MSR_IA32_SYSENTER_CS:
424f7b2429fSBlue Swirl         val = env->sysenter_cs;
425f7b2429fSBlue Swirl         break;
426f7b2429fSBlue Swirl     case MSR_IA32_SYSENTER_ESP:
427f7b2429fSBlue Swirl         val = env->sysenter_esp;
428f7b2429fSBlue Swirl         break;
429f7b2429fSBlue Swirl     case MSR_IA32_SYSENTER_EIP:
430f7b2429fSBlue Swirl         val = env->sysenter_eip;
431f7b2429fSBlue Swirl         break;
432f7b2429fSBlue Swirl     case MSR_IA32_APICBASE:
4336aa9e42fSRichard Henderson         val = cpu_get_apic_base(env_archcpu(env)->apic_state);
434f7b2429fSBlue Swirl         break;
435f7b2429fSBlue Swirl     case MSR_EFER:
436f7b2429fSBlue Swirl         val = env->efer;
437f7b2429fSBlue Swirl         break;
438f7b2429fSBlue Swirl     case MSR_STAR:
439f7b2429fSBlue Swirl         val = env->star;
440f7b2429fSBlue Swirl         break;
441f7b2429fSBlue Swirl     case MSR_PAT:
442f7b2429fSBlue Swirl         val = env->pat;
443f7b2429fSBlue Swirl         break;
444*e7e7bdabSPaolo Bonzini     case MSR_IA32_PKRS:
445*e7e7bdabSPaolo Bonzini         val = env->pkrs;
446*e7e7bdabSPaolo Bonzini         break;
447f7b2429fSBlue Swirl     case MSR_VM_HSAVE_PA:
448f7b2429fSBlue Swirl         val = env->vm_hsave;
449f7b2429fSBlue Swirl         break;
450f7b2429fSBlue Swirl     case MSR_IA32_PERF_STATUS:
451f7b2429fSBlue Swirl         /* tsc_increment_by_tick */
452f7b2429fSBlue Swirl         val = 1000ULL;
453f7b2429fSBlue Swirl         /* CPU multiplier */
454f7b2429fSBlue Swirl         val |= (((uint64_t)4ULL) << 40);
455f7b2429fSBlue Swirl         break;
456f7b2429fSBlue Swirl #ifdef TARGET_X86_64
457f7b2429fSBlue Swirl     case MSR_LSTAR:
458f7b2429fSBlue Swirl         val = env->lstar;
459f7b2429fSBlue Swirl         break;
460f7b2429fSBlue Swirl     case MSR_CSTAR:
461f7b2429fSBlue Swirl         val = env->cstar;
462f7b2429fSBlue Swirl         break;
463f7b2429fSBlue Swirl     case MSR_FMASK:
464f7b2429fSBlue Swirl         val = env->fmask;
465f7b2429fSBlue Swirl         break;
466f7b2429fSBlue Swirl     case MSR_FSBASE:
467f7b2429fSBlue Swirl         val = env->segs[R_FS].base;
468f7b2429fSBlue Swirl         break;
469f7b2429fSBlue Swirl     case MSR_GSBASE:
470f7b2429fSBlue Swirl         val = env->segs[R_GS].base;
471f7b2429fSBlue Swirl         break;
472f7b2429fSBlue Swirl     case MSR_KERNELGSBASE:
473f7b2429fSBlue Swirl         val = env->kernelgsbase;
474f7b2429fSBlue Swirl         break;
475f7b2429fSBlue Swirl     case MSR_TSC_AUX:
476f7b2429fSBlue Swirl         val = env->tsc_aux;
477f7b2429fSBlue Swirl         break;
478f7b2429fSBlue Swirl #endif
4791d3db6bdSPaolo Bonzini     case MSR_SMI_COUNT:
4801d3db6bdSPaolo Bonzini         val = env->msr_smi_count;
4811d3db6bdSPaolo Bonzini         break;
482f7b2429fSBlue Swirl     case MSR_MTRRphysBase(0):
483f7b2429fSBlue Swirl     case MSR_MTRRphysBase(1):
484f7b2429fSBlue Swirl     case MSR_MTRRphysBase(2):
485f7b2429fSBlue Swirl     case MSR_MTRRphysBase(3):
486f7b2429fSBlue Swirl     case MSR_MTRRphysBase(4):
487f7b2429fSBlue Swirl     case MSR_MTRRphysBase(5):
488f7b2429fSBlue Swirl     case MSR_MTRRphysBase(6):
489f7b2429fSBlue Swirl     case MSR_MTRRphysBase(7):
49090a2541bSliguang         val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
49190a2541bSliguang                              MSR_MTRRphysBase(0)) / 2].base;
492f7b2429fSBlue Swirl         break;
493f7b2429fSBlue Swirl     case MSR_MTRRphysMask(0):
494f7b2429fSBlue Swirl     case MSR_MTRRphysMask(1):
495f7b2429fSBlue Swirl     case MSR_MTRRphysMask(2):
496f7b2429fSBlue Swirl     case MSR_MTRRphysMask(3):
497f7b2429fSBlue Swirl     case MSR_MTRRphysMask(4):
498f7b2429fSBlue Swirl     case MSR_MTRRphysMask(5):
499f7b2429fSBlue Swirl     case MSR_MTRRphysMask(6):
500f7b2429fSBlue Swirl     case MSR_MTRRphysMask(7):
50190a2541bSliguang         val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
50290a2541bSliguang                              MSR_MTRRphysMask(0)) / 2].mask;
503f7b2429fSBlue Swirl         break;
504f7b2429fSBlue Swirl     case MSR_MTRRfix64K_00000:
505f7b2429fSBlue Swirl         val = env->mtrr_fixed[0];
506f7b2429fSBlue Swirl         break;
507f7b2429fSBlue Swirl     case MSR_MTRRfix16K_80000:
508f7b2429fSBlue Swirl     case MSR_MTRRfix16K_A0000:
50990a2541bSliguang         val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
51090a2541bSliguang                               MSR_MTRRfix16K_80000 + 1];
511f7b2429fSBlue Swirl         break;
512f7b2429fSBlue Swirl     case MSR_MTRRfix4K_C0000:
513f7b2429fSBlue Swirl     case MSR_MTRRfix4K_C8000:
514f7b2429fSBlue Swirl     case MSR_MTRRfix4K_D0000:
515f7b2429fSBlue Swirl     case MSR_MTRRfix4K_D8000:
516f7b2429fSBlue Swirl     case MSR_MTRRfix4K_E0000:
517f7b2429fSBlue Swirl     case MSR_MTRRfix4K_E8000:
518f7b2429fSBlue Swirl     case MSR_MTRRfix4K_F0000:
519f7b2429fSBlue Swirl     case MSR_MTRRfix4K_F8000:
52090a2541bSliguang         val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
52190a2541bSliguang                               MSR_MTRRfix4K_C0000 + 3];
522f7b2429fSBlue Swirl         break;
523f7b2429fSBlue Swirl     case MSR_MTRRdefType:
524f7b2429fSBlue Swirl         val = env->mtrr_deftype;
525f7b2429fSBlue Swirl         break;
526f7b2429fSBlue Swirl     case MSR_MTRRcap:
5270514ef2fSEduardo Habkost         if (env->features[FEAT_1_EDX] & CPUID_MTRR) {
528f7b2429fSBlue Swirl             val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT |
529f7b2429fSBlue Swirl                 MSR_MTRRcap_WC_SUPPORTED;
530f7b2429fSBlue Swirl         } else {
531f7b2429fSBlue Swirl             /* XXX: exception? */
532f7b2429fSBlue Swirl             val = 0;
533f7b2429fSBlue Swirl         }
534f7b2429fSBlue Swirl         break;
535f7b2429fSBlue Swirl     case MSR_MCG_CAP:
536f7b2429fSBlue Swirl         val = env->mcg_cap;
537f7b2429fSBlue Swirl         break;
538f7b2429fSBlue Swirl     case MSR_MCG_CTL:
539f7b2429fSBlue Swirl         if (env->mcg_cap & MCG_CTL_P) {
540f7b2429fSBlue Swirl             val = env->mcg_ctl;
541f7b2429fSBlue Swirl         } else {
542f7b2429fSBlue Swirl             val = 0;
543f7b2429fSBlue Swirl         }
544f7b2429fSBlue Swirl         break;
545f7b2429fSBlue Swirl     case MSR_MCG_STATUS:
546f7b2429fSBlue Swirl         val = env->mcg_status;
547f7b2429fSBlue Swirl         break;
548f7b2429fSBlue Swirl     case MSR_IA32_MISC_ENABLE:
549f7b2429fSBlue Swirl         val = env->msr_ia32_misc_enable;
550f7b2429fSBlue Swirl         break;
551f4f1110eSRichard Henderson     case MSR_IA32_BNDCFGS:
552f4f1110eSRichard Henderson         val = env->msr_bndcfgs;
553f4f1110eSRichard Henderson         break;
5549028c75cSPaolo Bonzini      case MSR_IA32_UCODE_REV:
5559028c75cSPaolo Bonzini         val = x86_cpu->ucode_rev;
5569028c75cSPaolo Bonzini         break;
557f7b2429fSBlue Swirl     default:
558a4165610Sliguang         if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
55990a2541bSliguang             && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
56090a2541bSliguang             (4 * env->mcg_cap & 0xff)) {
561a4165610Sliguang             uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
562f7b2429fSBlue Swirl             val = env->mce_banks[offset];
563f7b2429fSBlue Swirl             break;
564f7b2429fSBlue Swirl         }
565f7b2429fSBlue Swirl         /* XXX: exception? */
566f7b2429fSBlue Swirl         val = 0;
567f7b2429fSBlue Swirl         break;
568f7b2429fSBlue Swirl     }
5694b34e3adSliguang     env->regs[R_EAX] = (uint32_t)(val);
57000f5e6f2Sliguang     env->regs[R_EDX] = (uint32_t)(val >> 32);
571f7b2429fSBlue Swirl }
572f7b2429fSBlue Swirl #endif
573f7b2429fSBlue Swirl 
57481f3053bSPaolo Bonzini static void do_pause(X86CPU *cpu)
57581f3053bSPaolo Bonzini {
57627103424SAndreas Färber     CPUState *cs = CPU(cpu);
57781f3053bSPaolo Bonzini 
57881f3053bSPaolo Bonzini     /* Just let another CPU run.  */
57927103424SAndreas Färber     cs->exception_index = EXCP_INTERRUPT;
5805638d180SAndreas Färber     cpu_loop_exit(cs);
58181f3053bSPaolo Bonzini }
58281f3053bSPaolo Bonzini 
583259186a7SAndreas Färber static void do_hlt(X86CPU *cpu)
584f7b2429fSBlue Swirl {
585259186a7SAndreas Färber     CPUState *cs = CPU(cpu);
586259186a7SAndreas Färber     CPUX86State *env = &cpu->env;
587259186a7SAndreas Färber 
588f7b2429fSBlue Swirl     env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
589259186a7SAndreas Färber     cs->halted = 1;
59027103424SAndreas Färber     cs->exception_index = EXCP_HLT;
5915638d180SAndreas Färber     cpu_loop_exit(cs);
592f7b2429fSBlue Swirl }
593f7b2429fSBlue Swirl 
5944a7443beSBlue Swirl void helper_hlt(CPUX86State *env, int next_eip_addend)
595f7b2429fSBlue Swirl {
5966aa9e42fSRichard Henderson     X86CPU *cpu = env_archcpu(env);
597259186a7SAndreas Färber 
59865c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC());
599a78d0eabSliguang     env->eip += next_eip_addend;
600f7b2429fSBlue Swirl 
601259186a7SAndreas Färber     do_hlt(cpu);
602f7b2429fSBlue Swirl }
603f7b2429fSBlue Swirl 
6044a7443beSBlue Swirl void helper_monitor(CPUX86State *env, target_ulong ptr)
605f7b2429fSBlue Swirl {
606a4165610Sliguang     if ((uint32_t)env->regs[R_ECX] != 0) {
6074054cdecSPavel Dovgalyuk         raise_exception_ra(env, EXCP0D_GPF, GETPC());
608f7b2429fSBlue Swirl     }
609f7b2429fSBlue Swirl     /* XXX: store address? */
61065c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0, GETPC());
611f7b2429fSBlue Swirl }
612f7b2429fSBlue Swirl 
6134a7443beSBlue Swirl void helper_mwait(CPUX86State *env, int next_eip_addend)
614f7b2429fSBlue Swirl {
6156aa9e42fSRichard Henderson     CPUState *cs = env_cpu(env);
6166aa9e42fSRichard Henderson     X86CPU *cpu = env_archcpu(env);
61755e5c285SAndreas Färber 
618a4165610Sliguang     if ((uint32_t)env->regs[R_ECX] != 0) {
6194054cdecSPavel Dovgalyuk         raise_exception_ra(env, EXCP0D_GPF, GETPC());
620f7b2429fSBlue Swirl     }
62165c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0, GETPC());
622a78d0eabSliguang     env->eip += next_eip_addend;
623f7b2429fSBlue Swirl 
624f7b2429fSBlue Swirl     /* XXX: not complete but not completely erroneous */
625bdc44640SAndreas Färber     if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) {
62681f3053bSPaolo Bonzini         do_pause(cpu);
627f7b2429fSBlue Swirl     } else {
628259186a7SAndreas Färber         do_hlt(cpu);
629f7b2429fSBlue Swirl     }
630f7b2429fSBlue Swirl }
631f7b2429fSBlue Swirl 
63281f3053bSPaolo Bonzini void helper_pause(CPUX86State *env, int next_eip_addend)
63381f3053bSPaolo Bonzini {
6346aa9e42fSRichard Henderson     X86CPU *cpu = env_archcpu(env);
63581f3053bSPaolo Bonzini 
63665c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0, GETPC());
63781f3053bSPaolo Bonzini     env->eip += next_eip_addend;
63881f3053bSPaolo Bonzini 
63981f3053bSPaolo Bonzini     do_pause(cpu);
64081f3053bSPaolo Bonzini }
64181f3053bSPaolo Bonzini 
6424a7443beSBlue Swirl void helper_debug(CPUX86State *env)
643f7b2429fSBlue Swirl {
6446aa9e42fSRichard Henderson     CPUState *cs = env_cpu(env);
64527103424SAndreas Färber 
64627103424SAndreas Färber     cs->exception_index = EXCP_DEBUG;
6475638d180SAndreas Färber     cpu_loop_exit(cs);
648f7b2429fSBlue Swirl }
6490f70ed47SPaolo Bonzini 
6500f70ed47SPaolo Bonzini uint64_t helper_rdpkru(CPUX86State *env, uint32_t ecx)
6510f70ed47SPaolo Bonzini {
6520f70ed47SPaolo Bonzini     if ((env->cr[4] & CR4_PKE_MASK) == 0) {
6530f70ed47SPaolo Bonzini         raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
6540f70ed47SPaolo Bonzini     }
6550f70ed47SPaolo Bonzini     if (ecx != 0) {
6560f70ed47SPaolo Bonzini         raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
6570f70ed47SPaolo Bonzini     }
6580f70ed47SPaolo Bonzini 
6590f70ed47SPaolo Bonzini     return env->pkru;
6600f70ed47SPaolo Bonzini }
6610f70ed47SPaolo Bonzini 
6620f70ed47SPaolo Bonzini void helper_wrpkru(CPUX86State *env, uint32_t ecx, uint64_t val)
6630f70ed47SPaolo Bonzini {
6646aa9e42fSRichard Henderson     CPUState *cs = env_cpu(env);
6650f70ed47SPaolo Bonzini 
6660f70ed47SPaolo Bonzini     if ((env->cr[4] & CR4_PKE_MASK) == 0) {
6670f70ed47SPaolo Bonzini         raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
6680f70ed47SPaolo Bonzini     }
6690f70ed47SPaolo Bonzini     if (ecx != 0 || (val & 0xFFFFFFFF00000000ull)) {
6700f70ed47SPaolo Bonzini         raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
6710f70ed47SPaolo Bonzini     }
6720f70ed47SPaolo Bonzini 
6730f70ed47SPaolo Bonzini     env->pkru = val;
674d10eb08fSAlex Bennée     tlb_flush(cs);
6750f70ed47SPaolo Bonzini }
676