xref: /qemu/target/i386/tcg/misc_helper.c (revision ed69e8314d403d1bfa8c0210f850ffe69bb89dbe)
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"
27*ed69e831SClaudio Fontana #include "helper-tcg.h"
2892fc4b58SBlue Swirl 
293f7d8464SPaolo Bonzini void helper_outb(CPUX86State *env, uint32_t port, uint32_t data)
30f7b2429fSBlue Swirl {
313f7d8464SPaolo Bonzini #ifdef CONFIG_USER_ONLY
323f7d8464SPaolo Bonzini     fprintf(stderr, "outb: port=0x%04x, data=%02x\n", port, data);
333f7d8464SPaolo Bonzini #else
343f7d8464SPaolo Bonzini     address_space_stb(&address_space_io, port, data,
353f7d8464SPaolo Bonzini                       cpu_get_mem_attrs(env), NULL);
363f7d8464SPaolo Bonzini #endif
37f7b2429fSBlue Swirl }
38f7b2429fSBlue Swirl 
393f7d8464SPaolo Bonzini target_ulong helper_inb(CPUX86State *env, uint32_t port)
40f7b2429fSBlue Swirl {
413f7d8464SPaolo Bonzini #ifdef CONFIG_USER_ONLY
423f7d8464SPaolo Bonzini     fprintf(stderr, "inb: port=0x%04x\n", port);
433f7d8464SPaolo Bonzini     return 0;
443f7d8464SPaolo Bonzini #else
453f7d8464SPaolo Bonzini     return address_space_ldub(&address_space_io, port,
463f7d8464SPaolo Bonzini                               cpu_get_mem_attrs(env), NULL);
473f7d8464SPaolo Bonzini #endif
48f7b2429fSBlue Swirl }
49f7b2429fSBlue Swirl 
503f7d8464SPaolo Bonzini void helper_outw(CPUX86State *env, uint32_t port, uint32_t data)
51f7b2429fSBlue Swirl {
523f7d8464SPaolo Bonzini #ifdef CONFIG_USER_ONLY
533f7d8464SPaolo Bonzini     fprintf(stderr, "outw: port=0x%04x, data=%04x\n", port, data);
543f7d8464SPaolo Bonzini #else
553f7d8464SPaolo Bonzini     address_space_stw(&address_space_io, port, data,
563f7d8464SPaolo Bonzini                       cpu_get_mem_attrs(env), NULL);
573f7d8464SPaolo Bonzini #endif
58f7b2429fSBlue Swirl }
59f7b2429fSBlue Swirl 
603f7d8464SPaolo Bonzini target_ulong helper_inw(CPUX86State *env, uint32_t port)
61f7b2429fSBlue Swirl {
623f7d8464SPaolo Bonzini #ifdef CONFIG_USER_ONLY
633f7d8464SPaolo Bonzini     fprintf(stderr, "inw: port=0x%04x\n", port);
643f7d8464SPaolo Bonzini     return 0;
653f7d8464SPaolo Bonzini #else
663f7d8464SPaolo Bonzini     return address_space_lduw(&address_space_io, port,
673f7d8464SPaolo Bonzini                               cpu_get_mem_attrs(env), NULL);
683f7d8464SPaolo Bonzini #endif
69f7b2429fSBlue Swirl }
70f7b2429fSBlue Swirl 
713f7d8464SPaolo Bonzini void helper_outl(CPUX86State *env, uint32_t port, uint32_t data)
72f7b2429fSBlue Swirl {
733f7d8464SPaolo Bonzini #ifdef CONFIG_USER_ONLY
74ce8540fdSPhilippe Mathieu-Daudé     fprintf(stderr, "outl: port=0x%04x, data=%08x\n", port, data);
753f7d8464SPaolo Bonzini #else
763f7d8464SPaolo Bonzini     address_space_stl(&address_space_io, port, data,
773f7d8464SPaolo Bonzini                       cpu_get_mem_attrs(env), NULL);
783f7d8464SPaolo Bonzini #endif
79f7b2429fSBlue Swirl }
80f7b2429fSBlue Swirl 
813f7d8464SPaolo Bonzini target_ulong helper_inl(CPUX86State *env, uint32_t port)
82f7b2429fSBlue Swirl {
833f7d8464SPaolo Bonzini #ifdef CONFIG_USER_ONLY
843f7d8464SPaolo Bonzini     fprintf(stderr, "inl: port=0x%04x\n", port);
853f7d8464SPaolo Bonzini     return 0;
863f7d8464SPaolo Bonzini #else
873f7d8464SPaolo Bonzini     return address_space_ldl(&address_space_io, port,
883f7d8464SPaolo Bonzini                              cpu_get_mem_attrs(env), NULL);
893f7d8464SPaolo Bonzini #endif
90f7b2429fSBlue Swirl }
91f7b2429fSBlue Swirl 
924a7443beSBlue Swirl void helper_into(CPUX86State *env, int next_eip_addend)
93f7b2429fSBlue Swirl {
94f7b2429fSBlue Swirl     int eflags;
95f7b2429fSBlue Swirl 
96f0967a1aSBlue Swirl     eflags = cpu_cc_compute_all(env, CC_OP);
97f7b2429fSBlue Swirl     if (eflags & CC_O) {
98f7b2429fSBlue Swirl         raise_interrupt(env, EXCP04_INTO, 1, 0, next_eip_addend);
99f7b2429fSBlue Swirl     }
100f7b2429fSBlue Swirl }
101f7b2429fSBlue Swirl 
1024a7443beSBlue Swirl void helper_cpuid(CPUX86State *env)
103f7b2429fSBlue Swirl {
104f7b2429fSBlue Swirl     uint32_t eax, ebx, ecx, edx;
105f7b2429fSBlue Swirl 
10665c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_CPUID, 0, GETPC());
107f7b2429fSBlue Swirl 
10890a2541bSliguang     cpu_x86_cpuid(env, (uint32_t)env->regs[R_EAX], (uint32_t)env->regs[R_ECX],
10990a2541bSliguang                   &eax, &ebx, &ecx, &edx);
1104b34e3adSliguang     env->regs[R_EAX] = eax;
11170b51365Sliguang     env->regs[R_EBX] = ebx;
112a4165610Sliguang     env->regs[R_ECX] = ecx;
11300f5e6f2Sliguang     env->regs[R_EDX] = edx;
114f7b2429fSBlue Swirl }
115f7b2429fSBlue Swirl 
116f7b2429fSBlue Swirl #if defined(CONFIG_USER_ONLY)
1174a7443beSBlue Swirl target_ulong helper_read_crN(CPUX86State *env, int reg)
118f7b2429fSBlue Swirl {
119f7b2429fSBlue Swirl     return 0;
120f7b2429fSBlue Swirl }
121f7b2429fSBlue Swirl 
1224a7443beSBlue Swirl void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
123f7b2429fSBlue Swirl {
124f7b2429fSBlue Swirl }
125f7b2429fSBlue Swirl #else
1264a7443beSBlue Swirl target_ulong helper_read_crN(CPUX86State *env, int reg)
127f7b2429fSBlue Swirl {
128f7b2429fSBlue Swirl     target_ulong val;
129f7b2429fSBlue Swirl 
13065c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_READ_CR0 + reg, 0, GETPC());
131f7b2429fSBlue Swirl     switch (reg) {
132f7b2429fSBlue Swirl     default:
133f7b2429fSBlue Swirl         val = env->cr[reg];
134f7b2429fSBlue Swirl         break;
135f7b2429fSBlue Swirl     case 8:
136f7b2429fSBlue Swirl         if (!(env->hflags2 & HF2_VINTR_MASK)) {
1376aa9e42fSRichard Henderson             val = cpu_get_apic_tpr(env_archcpu(env)->apic_state);
138f7b2429fSBlue Swirl         } else {
139f7b2429fSBlue Swirl             val = env->v_tpr;
140f7b2429fSBlue Swirl         }
141f7b2429fSBlue Swirl         break;
142f7b2429fSBlue Swirl     }
143f7b2429fSBlue Swirl     return val;
144f7b2429fSBlue Swirl }
145f7b2429fSBlue Swirl 
1464a7443beSBlue Swirl void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
147f7b2429fSBlue Swirl {
14865c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_WRITE_CR0 + reg, 0, GETPC());
149f7b2429fSBlue Swirl     switch (reg) {
150f7b2429fSBlue Swirl     case 0:
151f7b2429fSBlue Swirl         cpu_x86_update_cr0(env, t0);
152f7b2429fSBlue Swirl         break;
153f7b2429fSBlue Swirl     case 3:
154f7b2429fSBlue Swirl         cpu_x86_update_cr3(env, t0);
155f7b2429fSBlue Swirl         break;
156f7b2429fSBlue Swirl     case 4:
157f7b2429fSBlue Swirl         cpu_x86_update_cr4(env, t0);
158f7b2429fSBlue Swirl         break;
159f7b2429fSBlue Swirl     case 8:
160f7b2429fSBlue Swirl         if (!(env->hflags2 & HF2_VINTR_MASK)) {
161b4e79a50SAlex Bennée             qemu_mutex_lock_iothread();
1626aa9e42fSRichard Henderson             cpu_set_apic_tpr(env_archcpu(env)->apic_state, t0);
163b4e79a50SAlex Bennée             qemu_mutex_unlock_iothread();
164f7b2429fSBlue Swirl         }
165f7b2429fSBlue Swirl         env->v_tpr = t0 & 0x0f;
166f7b2429fSBlue Swirl         break;
167f7b2429fSBlue Swirl     default:
168f7b2429fSBlue Swirl         env->cr[reg] = t0;
169f7b2429fSBlue Swirl         break;
170f7b2429fSBlue Swirl     }
171f7b2429fSBlue Swirl }
172f7b2429fSBlue Swirl #endif
173f7b2429fSBlue Swirl 
1744a7443beSBlue Swirl void helper_lmsw(CPUX86State *env, target_ulong t0)
175f7b2429fSBlue Swirl {
176f7b2429fSBlue Swirl     /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
177f7b2429fSBlue Swirl        if already set to one. */
178f7b2429fSBlue Swirl     t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
1794a7443beSBlue Swirl     helper_write_crN(env, 0, t0);
180f7b2429fSBlue Swirl }
181f7b2429fSBlue Swirl 
1824a7443beSBlue Swirl void helper_invlpg(CPUX86State *env, target_ulong addr)
183f7b2429fSBlue Swirl {
1846aa9e42fSRichard Henderson     X86CPU *cpu = env_archcpu(env);
18531b030d4SAndreas Färber 
18665c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0, GETPC());
18731b030d4SAndreas Färber     tlb_flush_page(CPU(cpu), addr);
188f7b2429fSBlue Swirl }
189f7b2429fSBlue Swirl 
1904a7443beSBlue Swirl void helper_rdtsc(CPUX86State *env)
191f7b2429fSBlue Swirl {
192f7b2429fSBlue Swirl     uint64_t val;
193f7b2429fSBlue Swirl 
194f7b2429fSBlue Swirl     if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
1954054cdecSPavel Dovgalyuk         raise_exception_ra(env, EXCP0D_GPF, GETPC());
196f7b2429fSBlue Swirl     }
19765c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_RDTSC, 0, GETPC());
198f7b2429fSBlue Swirl 
199f7b2429fSBlue Swirl     val = cpu_get_tsc(env) + env->tsc_offset;
2004b34e3adSliguang     env->regs[R_EAX] = (uint32_t)(val);
20100f5e6f2Sliguang     env->regs[R_EDX] = (uint32_t)(val >> 32);
202f7b2429fSBlue Swirl }
203f7b2429fSBlue Swirl 
2044a7443beSBlue Swirl void helper_rdtscp(CPUX86State *env)
205f7b2429fSBlue Swirl {
2064a7443beSBlue Swirl     helper_rdtsc(env);
207a4165610Sliguang     env->regs[R_ECX] = (uint32_t)(env->tsc_aux);
208f7b2429fSBlue Swirl }
209f7b2429fSBlue Swirl 
2104a7443beSBlue Swirl void helper_rdpmc(CPUX86State *env)
211f7b2429fSBlue Swirl {
212f7b2429fSBlue Swirl     if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
2134054cdecSPavel Dovgalyuk         raise_exception_ra(env, EXCP0D_GPF, GETPC());
214f7b2429fSBlue Swirl     }
21565c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0, GETPC());
216f7b2429fSBlue Swirl 
217f7b2429fSBlue Swirl     /* currently unimplemented */
218f7b2429fSBlue Swirl     qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n");
219f7b2429fSBlue Swirl     raise_exception_err(env, EXCP06_ILLOP, 0);
220f7b2429fSBlue Swirl }
221f7b2429fSBlue Swirl 
222f7b2429fSBlue Swirl #if defined(CONFIG_USER_ONLY)
2234a7443beSBlue Swirl void helper_wrmsr(CPUX86State *env)
224f7b2429fSBlue Swirl {
225f7b2429fSBlue Swirl }
226f7b2429fSBlue Swirl 
2274a7443beSBlue Swirl void helper_rdmsr(CPUX86State *env)
228f7b2429fSBlue Swirl {
229f7b2429fSBlue Swirl }
230f7b2429fSBlue Swirl #else
2314a7443beSBlue Swirl void helper_wrmsr(CPUX86State *env)
232f7b2429fSBlue Swirl {
233f7b2429fSBlue Swirl     uint64_t val;
234f7b2429fSBlue Swirl 
23565c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC());
236f7b2429fSBlue Swirl 
23790a2541bSliguang     val = ((uint32_t)env->regs[R_EAX]) |
23890a2541bSliguang         ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
239f7b2429fSBlue Swirl 
240a4165610Sliguang     switch ((uint32_t)env->regs[R_ECX]) {
241f7b2429fSBlue Swirl     case MSR_IA32_SYSENTER_CS:
242f7b2429fSBlue Swirl         env->sysenter_cs = val & 0xffff;
243f7b2429fSBlue Swirl         break;
244f7b2429fSBlue Swirl     case MSR_IA32_SYSENTER_ESP:
245f7b2429fSBlue Swirl         env->sysenter_esp = val;
246f7b2429fSBlue Swirl         break;
247f7b2429fSBlue Swirl     case MSR_IA32_SYSENTER_EIP:
248f7b2429fSBlue Swirl         env->sysenter_eip = val;
249f7b2429fSBlue Swirl         break;
250f7b2429fSBlue Swirl     case MSR_IA32_APICBASE:
2516aa9e42fSRichard Henderson         cpu_set_apic_base(env_archcpu(env)->apic_state, val);
252f7b2429fSBlue Swirl         break;
253f7b2429fSBlue Swirl     case MSR_EFER:
254f7b2429fSBlue Swirl         {
255f7b2429fSBlue Swirl             uint64_t update_mask;
256f7b2429fSBlue Swirl 
257f7b2429fSBlue Swirl             update_mask = 0;
2580514ef2fSEduardo Habkost             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) {
259f7b2429fSBlue Swirl                 update_mask |= MSR_EFER_SCE;
260f7b2429fSBlue Swirl             }
2610514ef2fSEduardo Habkost             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
262f7b2429fSBlue Swirl                 update_mask |= MSR_EFER_LME;
263f7b2429fSBlue Swirl             }
2640514ef2fSEduardo Habkost             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
265f7b2429fSBlue Swirl                 update_mask |= MSR_EFER_FFXSR;
266f7b2429fSBlue Swirl             }
2670514ef2fSEduardo Habkost             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) {
268f7b2429fSBlue Swirl                 update_mask |= MSR_EFER_NXE;
269f7b2429fSBlue Swirl             }
2700514ef2fSEduardo Habkost             if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
271f7b2429fSBlue Swirl                 update_mask |= MSR_EFER_SVME;
272f7b2429fSBlue Swirl             }
2730514ef2fSEduardo Habkost             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
274f7b2429fSBlue Swirl                 update_mask |= MSR_EFER_FFXSR;
275f7b2429fSBlue Swirl             }
276f7b2429fSBlue Swirl             cpu_load_efer(env, (env->efer & ~update_mask) |
277f7b2429fSBlue Swirl                           (val & update_mask));
278f7b2429fSBlue Swirl         }
279f7b2429fSBlue Swirl         break;
280f7b2429fSBlue Swirl     case MSR_STAR:
281f7b2429fSBlue Swirl         env->star = val;
282f7b2429fSBlue Swirl         break;
283f7b2429fSBlue Swirl     case MSR_PAT:
284f7b2429fSBlue Swirl         env->pat = val;
285f7b2429fSBlue Swirl         break;
286f7b2429fSBlue Swirl     case MSR_VM_HSAVE_PA:
287f7b2429fSBlue Swirl         env->vm_hsave = val;
288f7b2429fSBlue Swirl         break;
289f7b2429fSBlue Swirl #ifdef TARGET_X86_64
290f7b2429fSBlue Swirl     case MSR_LSTAR:
291f7b2429fSBlue Swirl         env->lstar = val;
292f7b2429fSBlue Swirl         break;
293f7b2429fSBlue Swirl     case MSR_CSTAR:
294f7b2429fSBlue Swirl         env->cstar = val;
295f7b2429fSBlue Swirl         break;
296f7b2429fSBlue Swirl     case MSR_FMASK:
297f7b2429fSBlue Swirl         env->fmask = val;
298f7b2429fSBlue Swirl         break;
299f7b2429fSBlue Swirl     case MSR_FSBASE:
300f7b2429fSBlue Swirl         env->segs[R_FS].base = val;
301f7b2429fSBlue Swirl         break;
302f7b2429fSBlue Swirl     case MSR_GSBASE:
303f7b2429fSBlue Swirl         env->segs[R_GS].base = val;
304f7b2429fSBlue Swirl         break;
305f7b2429fSBlue Swirl     case MSR_KERNELGSBASE:
306f7b2429fSBlue Swirl         env->kernelgsbase = val;
307f7b2429fSBlue Swirl         break;
308f7b2429fSBlue Swirl #endif
309f7b2429fSBlue Swirl     case MSR_MTRRphysBase(0):
310f7b2429fSBlue Swirl     case MSR_MTRRphysBase(1):
311f7b2429fSBlue Swirl     case MSR_MTRRphysBase(2):
312f7b2429fSBlue Swirl     case MSR_MTRRphysBase(3):
313f7b2429fSBlue Swirl     case MSR_MTRRphysBase(4):
314f7b2429fSBlue Swirl     case MSR_MTRRphysBase(5):
315f7b2429fSBlue Swirl     case MSR_MTRRphysBase(6):
316f7b2429fSBlue Swirl     case MSR_MTRRphysBase(7):
31790a2541bSliguang         env->mtrr_var[((uint32_t)env->regs[R_ECX] -
31890a2541bSliguang                        MSR_MTRRphysBase(0)) / 2].base = val;
319f7b2429fSBlue Swirl         break;
320f7b2429fSBlue Swirl     case MSR_MTRRphysMask(0):
321f7b2429fSBlue Swirl     case MSR_MTRRphysMask(1):
322f7b2429fSBlue Swirl     case MSR_MTRRphysMask(2):
323f7b2429fSBlue Swirl     case MSR_MTRRphysMask(3):
324f7b2429fSBlue Swirl     case MSR_MTRRphysMask(4):
325f7b2429fSBlue Swirl     case MSR_MTRRphysMask(5):
326f7b2429fSBlue Swirl     case MSR_MTRRphysMask(6):
327f7b2429fSBlue Swirl     case MSR_MTRRphysMask(7):
32890a2541bSliguang         env->mtrr_var[((uint32_t)env->regs[R_ECX] -
32990a2541bSliguang                        MSR_MTRRphysMask(0)) / 2].mask = val;
330f7b2429fSBlue Swirl         break;
331f7b2429fSBlue Swirl     case MSR_MTRRfix64K_00000:
33290a2541bSliguang         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
33390a2541bSliguang                         MSR_MTRRfix64K_00000] = val;
334f7b2429fSBlue Swirl         break;
335f7b2429fSBlue Swirl     case MSR_MTRRfix16K_80000:
336f7b2429fSBlue Swirl     case MSR_MTRRfix16K_A0000:
33790a2541bSliguang         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
33890a2541bSliguang                         MSR_MTRRfix16K_80000 + 1] = val;
339f7b2429fSBlue Swirl         break;
340f7b2429fSBlue Swirl     case MSR_MTRRfix4K_C0000:
341f7b2429fSBlue Swirl     case MSR_MTRRfix4K_C8000:
342f7b2429fSBlue Swirl     case MSR_MTRRfix4K_D0000:
343f7b2429fSBlue Swirl     case MSR_MTRRfix4K_D8000:
344f7b2429fSBlue Swirl     case MSR_MTRRfix4K_E0000:
345f7b2429fSBlue Swirl     case MSR_MTRRfix4K_E8000:
346f7b2429fSBlue Swirl     case MSR_MTRRfix4K_F0000:
347f7b2429fSBlue Swirl     case MSR_MTRRfix4K_F8000:
34890a2541bSliguang         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
34990a2541bSliguang                         MSR_MTRRfix4K_C0000 + 3] = val;
350f7b2429fSBlue Swirl         break;
351f7b2429fSBlue Swirl     case MSR_MTRRdefType:
352f7b2429fSBlue Swirl         env->mtrr_deftype = val;
353f7b2429fSBlue Swirl         break;
354f7b2429fSBlue Swirl     case MSR_MCG_STATUS:
355f7b2429fSBlue Swirl         env->mcg_status = val;
356f7b2429fSBlue Swirl         break;
357f7b2429fSBlue Swirl     case MSR_MCG_CTL:
358f7b2429fSBlue Swirl         if ((env->mcg_cap & MCG_CTL_P)
359f7b2429fSBlue Swirl             && (val == 0 || val == ~(uint64_t)0)) {
360f7b2429fSBlue Swirl             env->mcg_ctl = val;
361f7b2429fSBlue Swirl         }
362f7b2429fSBlue Swirl         break;
363f7b2429fSBlue Swirl     case MSR_TSC_AUX:
364f7b2429fSBlue Swirl         env->tsc_aux = val;
365f7b2429fSBlue Swirl         break;
366f7b2429fSBlue Swirl     case MSR_IA32_MISC_ENABLE:
367f7b2429fSBlue Swirl         env->msr_ia32_misc_enable = val;
368f7b2429fSBlue Swirl         break;
369f4f1110eSRichard Henderson     case MSR_IA32_BNDCFGS:
370f4f1110eSRichard Henderson         /* FIXME: #GP if reserved bits are set.  */
371f4f1110eSRichard Henderson         /* FIXME: Extend highest implemented bit of linear address.  */
372f4f1110eSRichard Henderson         env->msr_bndcfgs = val;
373f4f1110eSRichard Henderson         cpu_sync_bndcs_hflags(env);
374f4f1110eSRichard Henderson         break;
375f7b2429fSBlue Swirl     default:
376a4165610Sliguang         if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
37790a2541bSliguang             && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
37890a2541bSliguang             (4 * env->mcg_cap & 0xff)) {
379a4165610Sliguang             uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
380f7b2429fSBlue Swirl             if ((offset & 0x3) != 0
381f7b2429fSBlue Swirl                 || (val == 0 || val == ~(uint64_t)0)) {
382f7b2429fSBlue Swirl                 env->mce_banks[offset] = val;
383f7b2429fSBlue Swirl             }
384f7b2429fSBlue Swirl             break;
385f7b2429fSBlue Swirl         }
386f7b2429fSBlue Swirl         /* XXX: exception? */
387f7b2429fSBlue Swirl         break;
388f7b2429fSBlue Swirl     }
389f7b2429fSBlue Swirl }
390f7b2429fSBlue Swirl 
3914a7443beSBlue Swirl void helper_rdmsr(CPUX86State *env)
392f7b2429fSBlue Swirl {
3939028c75cSPaolo Bonzini     X86CPU *x86_cpu = env_archcpu(env);
394f7b2429fSBlue Swirl     uint64_t val;
395f7b2429fSBlue Swirl 
39665c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0, GETPC());
397f7b2429fSBlue Swirl 
398a4165610Sliguang     switch ((uint32_t)env->regs[R_ECX]) {
399f7b2429fSBlue Swirl     case MSR_IA32_SYSENTER_CS:
400f7b2429fSBlue Swirl         val = env->sysenter_cs;
401f7b2429fSBlue Swirl         break;
402f7b2429fSBlue Swirl     case MSR_IA32_SYSENTER_ESP:
403f7b2429fSBlue Swirl         val = env->sysenter_esp;
404f7b2429fSBlue Swirl         break;
405f7b2429fSBlue Swirl     case MSR_IA32_SYSENTER_EIP:
406f7b2429fSBlue Swirl         val = env->sysenter_eip;
407f7b2429fSBlue Swirl         break;
408f7b2429fSBlue Swirl     case MSR_IA32_APICBASE:
4096aa9e42fSRichard Henderson         val = cpu_get_apic_base(env_archcpu(env)->apic_state);
410f7b2429fSBlue Swirl         break;
411f7b2429fSBlue Swirl     case MSR_EFER:
412f7b2429fSBlue Swirl         val = env->efer;
413f7b2429fSBlue Swirl         break;
414f7b2429fSBlue Swirl     case MSR_STAR:
415f7b2429fSBlue Swirl         val = env->star;
416f7b2429fSBlue Swirl         break;
417f7b2429fSBlue Swirl     case MSR_PAT:
418f7b2429fSBlue Swirl         val = env->pat;
419f7b2429fSBlue Swirl         break;
420f7b2429fSBlue Swirl     case MSR_VM_HSAVE_PA:
421f7b2429fSBlue Swirl         val = env->vm_hsave;
422f7b2429fSBlue Swirl         break;
423f7b2429fSBlue Swirl     case MSR_IA32_PERF_STATUS:
424f7b2429fSBlue Swirl         /* tsc_increment_by_tick */
425f7b2429fSBlue Swirl         val = 1000ULL;
426f7b2429fSBlue Swirl         /* CPU multiplier */
427f7b2429fSBlue Swirl         val |= (((uint64_t)4ULL) << 40);
428f7b2429fSBlue Swirl         break;
429f7b2429fSBlue Swirl #ifdef TARGET_X86_64
430f7b2429fSBlue Swirl     case MSR_LSTAR:
431f7b2429fSBlue Swirl         val = env->lstar;
432f7b2429fSBlue Swirl         break;
433f7b2429fSBlue Swirl     case MSR_CSTAR:
434f7b2429fSBlue Swirl         val = env->cstar;
435f7b2429fSBlue Swirl         break;
436f7b2429fSBlue Swirl     case MSR_FMASK:
437f7b2429fSBlue Swirl         val = env->fmask;
438f7b2429fSBlue Swirl         break;
439f7b2429fSBlue Swirl     case MSR_FSBASE:
440f7b2429fSBlue Swirl         val = env->segs[R_FS].base;
441f7b2429fSBlue Swirl         break;
442f7b2429fSBlue Swirl     case MSR_GSBASE:
443f7b2429fSBlue Swirl         val = env->segs[R_GS].base;
444f7b2429fSBlue Swirl         break;
445f7b2429fSBlue Swirl     case MSR_KERNELGSBASE:
446f7b2429fSBlue Swirl         val = env->kernelgsbase;
447f7b2429fSBlue Swirl         break;
448f7b2429fSBlue Swirl     case MSR_TSC_AUX:
449f7b2429fSBlue Swirl         val = env->tsc_aux;
450f7b2429fSBlue Swirl         break;
451f7b2429fSBlue Swirl #endif
4521d3db6bdSPaolo Bonzini     case MSR_SMI_COUNT:
4531d3db6bdSPaolo Bonzini         val = env->msr_smi_count;
4541d3db6bdSPaolo Bonzini         break;
455f7b2429fSBlue Swirl     case MSR_MTRRphysBase(0):
456f7b2429fSBlue Swirl     case MSR_MTRRphysBase(1):
457f7b2429fSBlue Swirl     case MSR_MTRRphysBase(2):
458f7b2429fSBlue Swirl     case MSR_MTRRphysBase(3):
459f7b2429fSBlue Swirl     case MSR_MTRRphysBase(4):
460f7b2429fSBlue Swirl     case MSR_MTRRphysBase(5):
461f7b2429fSBlue Swirl     case MSR_MTRRphysBase(6):
462f7b2429fSBlue Swirl     case MSR_MTRRphysBase(7):
46390a2541bSliguang         val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
46490a2541bSliguang                              MSR_MTRRphysBase(0)) / 2].base;
465f7b2429fSBlue Swirl         break;
466f7b2429fSBlue Swirl     case MSR_MTRRphysMask(0):
467f7b2429fSBlue Swirl     case MSR_MTRRphysMask(1):
468f7b2429fSBlue Swirl     case MSR_MTRRphysMask(2):
469f7b2429fSBlue Swirl     case MSR_MTRRphysMask(3):
470f7b2429fSBlue Swirl     case MSR_MTRRphysMask(4):
471f7b2429fSBlue Swirl     case MSR_MTRRphysMask(5):
472f7b2429fSBlue Swirl     case MSR_MTRRphysMask(6):
473f7b2429fSBlue Swirl     case MSR_MTRRphysMask(7):
47490a2541bSliguang         val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
47590a2541bSliguang                              MSR_MTRRphysMask(0)) / 2].mask;
476f7b2429fSBlue Swirl         break;
477f7b2429fSBlue Swirl     case MSR_MTRRfix64K_00000:
478f7b2429fSBlue Swirl         val = env->mtrr_fixed[0];
479f7b2429fSBlue Swirl         break;
480f7b2429fSBlue Swirl     case MSR_MTRRfix16K_80000:
481f7b2429fSBlue Swirl     case MSR_MTRRfix16K_A0000:
48290a2541bSliguang         val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
48390a2541bSliguang                               MSR_MTRRfix16K_80000 + 1];
484f7b2429fSBlue Swirl         break;
485f7b2429fSBlue Swirl     case MSR_MTRRfix4K_C0000:
486f7b2429fSBlue Swirl     case MSR_MTRRfix4K_C8000:
487f7b2429fSBlue Swirl     case MSR_MTRRfix4K_D0000:
488f7b2429fSBlue Swirl     case MSR_MTRRfix4K_D8000:
489f7b2429fSBlue Swirl     case MSR_MTRRfix4K_E0000:
490f7b2429fSBlue Swirl     case MSR_MTRRfix4K_E8000:
491f7b2429fSBlue Swirl     case MSR_MTRRfix4K_F0000:
492f7b2429fSBlue Swirl     case MSR_MTRRfix4K_F8000:
49390a2541bSliguang         val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
49490a2541bSliguang                               MSR_MTRRfix4K_C0000 + 3];
495f7b2429fSBlue Swirl         break;
496f7b2429fSBlue Swirl     case MSR_MTRRdefType:
497f7b2429fSBlue Swirl         val = env->mtrr_deftype;
498f7b2429fSBlue Swirl         break;
499f7b2429fSBlue Swirl     case MSR_MTRRcap:
5000514ef2fSEduardo Habkost         if (env->features[FEAT_1_EDX] & CPUID_MTRR) {
501f7b2429fSBlue Swirl             val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT |
502f7b2429fSBlue Swirl                 MSR_MTRRcap_WC_SUPPORTED;
503f7b2429fSBlue Swirl         } else {
504f7b2429fSBlue Swirl             /* XXX: exception? */
505f7b2429fSBlue Swirl             val = 0;
506f7b2429fSBlue Swirl         }
507f7b2429fSBlue Swirl         break;
508f7b2429fSBlue Swirl     case MSR_MCG_CAP:
509f7b2429fSBlue Swirl         val = env->mcg_cap;
510f7b2429fSBlue Swirl         break;
511f7b2429fSBlue Swirl     case MSR_MCG_CTL:
512f7b2429fSBlue Swirl         if (env->mcg_cap & MCG_CTL_P) {
513f7b2429fSBlue Swirl             val = env->mcg_ctl;
514f7b2429fSBlue Swirl         } else {
515f7b2429fSBlue Swirl             val = 0;
516f7b2429fSBlue Swirl         }
517f7b2429fSBlue Swirl         break;
518f7b2429fSBlue Swirl     case MSR_MCG_STATUS:
519f7b2429fSBlue Swirl         val = env->mcg_status;
520f7b2429fSBlue Swirl         break;
521f7b2429fSBlue Swirl     case MSR_IA32_MISC_ENABLE:
522f7b2429fSBlue Swirl         val = env->msr_ia32_misc_enable;
523f7b2429fSBlue Swirl         break;
524f4f1110eSRichard Henderson     case MSR_IA32_BNDCFGS:
525f4f1110eSRichard Henderson         val = env->msr_bndcfgs;
526f4f1110eSRichard Henderson         break;
5279028c75cSPaolo Bonzini      case MSR_IA32_UCODE_REV:
5289028c75cSPaolo Bonzini         val = x86_cpu->ucode_rev;
5299028c75cSPaolo Bonzini         break;
530f7b2429fSBlue Swirl     default:
531a4165610Sliguang         if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
53290a2541bSliguang             && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
53390a2541bSliguang             (4 * env->mcg_cap & 0xff)) {
534a4165610Sliguang             uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
535f7b2429fSBlue Swirl             val = env->mce_banks[offset];
536f7b2429fSBlue Swirl             break;
537f7b2429fSBlue Swirl         }
538f7b2429fSBlue Swirl         /* XXX: exception? */
539f7b2429fSBlue Swirl         val = 0;
540f7b2429fSBlue Swirl         break;
541f7b2429fSBlue Swirl     }
5424b34e3adSliguang     env->regs[R_EAX] = (uint32_t)(val);
54300f5e6f2Sliguang     env->regs[R_EDX] = (uint32_t)(val >> 32);
544f7b2429fSBlue Swirl }
545f7b2429fSBlue Swirl #endif
546f7b2429fSBlue Swirl 
54781f3053bSPaolo Bonzini static void do_pause(X86CPU *cpu)
54881f3053bSPaolo Bonzini {
54927103424SAndreas Färber     CPUState *cs = CPU(cpu);
55081f3053bSPaolo Bonzini 
55181f3053bSPaolo Bonzini     /* Just let another CPU run.  */
55227103424SAndreas Färber     cs->exception_index = EXCP_INTERRUPT;
5535638d180SAndreas Färber     cpu_loop_exit(cs);
55481f3053bSPaolo Bonzini }
55581f3053bSPaolo Bonzini 
556259186a7SAndreas Färber static void do_hlt(X86CPU *cpu)
557f7b2429fSBlue Swirl {
558259186a7SAndreas Färber     CPUState *cs = CPU(cpu);
559259186a7SAndreas Färber     CPUX86State *env = &cpu->env;
560259186a7SAndreas Färber 
561f7b2429fSBlue Swirl     env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
562259186a7SAndreas Färber     cs->halted = 1;
56327103424SAndreas Färber     cs->exception_index = EXCP_HLT;
5645638d180SAndreas Färber     cpu_loop_exit(cs);
565f7b2429fSBlue Swirl }
566f7b2429fSBlue Swirl 
5674a7443beSBlue Swirl void helper_hlt(CPUX86State *env, int next_eip_addend)
568f7b2429fSBlue Swirl {
5696aa9e42fSRichard Henderson     X86CPU *cpu = env_archcpu(env);
570259186a7SAndreas Färber 
57165c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC());
572a78d0eabSliguang     env->eip += next_eip_addend;
573f7b2429fSBlue Swirl 
574259186a7SAndreas Färber     do_hlt(cpu);
575f7b2429fSBlue Swirl }
576f7b2429fSBlue Swirl 
5774a7443beSBlue Swirl void helper_monitor(CPUX86State *env, target_ulong ptr)
578f7b2429fSBlue Swirl {
579a4165610Sliguang     if ((uint32_t)env->regs[R_ECX] != 0) {
5804054cdecSPavel Dovgalyuk         raise_exception_ra(env, EXCP0D_GPF, GETPC());
581f7b2429fSBlue Swirl     }
582f7b2429fSBlue Swirl     /* XXX: store address? */
58365c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0, GETPC());
584f7b2429fSBlue Swirl }
585f7b2429fSBlue Swirl 
5864a7443beSBlue Swirl void helper_mwait(CPUX86State *env, int next_eip_addend)
587f7b2429fSBlue Swirl {
5886aa9e42fSRichard Henderson     CPUState *cs = env_cpu(env);
5896aa9e42fSRichard Henderson     X86CPU *cpu = env_archcpu(env);
59055e5c285SAndreas Färber 
591a4165610Sliguang     if ((uint32_t)env->regs[R_ECX] != 0) {
5924054cdecSPavel Dovgalyuk         raise_exception_ra(env, EXCP0D_GPF, GETPC());
593f7b2429fSBlue Swirl     }
59465c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0, GETPC());
595a78d0eabSliguang     env->eip += next_eip_addend;
596f7b2429fSBlue Swirl 
597f7b2429fSBlue Swirl     /* XXX: not complete but not completely erroneous */
598bdc44640SAndreas Färber     if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) {
59981f3053bSPaolo Bonzini         do_pause(cpu);
600f7b2429fSBlue Swirl     } else {
601259186a7SAndreas Färber         do_hlt(cpu);
602f7b2429fSBlue Swirl     }
603f7b2429fSBlue Swirl }
604f7b2429fSBlue Swirl 
60581f3053bSPaolo Bonzini void helper_pause(CPUX86State *env, int next_eip_addend)
60681f3053bSPaolo Bonzini {
6076aa9e42fSRichard Henderson     X86CPU *cpu = env_archcpu(env);
60881f3053bSPaolo Bonzini 
60965c9d60aSPaolo Bonzini     cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0, GETPC());
61081f3053bSPaolo Bonzini     env->eip += next_eip_addend;
61181f3053bSPaolo Bonzini 
61281f3053bSPaolo Bonzini     do_pause(cpu);
61381f3053bSPaolo Bonzini }
61481f3053bSPaolo Bonzini 
6154a7443beSBlue Swirl void helper_debug(CPUX86State *env)
616f7b2429fSBlue Swirl {
6176aa9e42fSRichard Henderson     CPUState *cs = env_cpu(env);
61827103424SAndreas Färber 
61927103424SAndreas Färber     cs->exception_index = EXCP_DEBUG;
6205638d180SAndreas Färber     cpu_loop_exit(cs);
621f7b2429fSBlue Swirl }
6220f70ed47SPaolo Bonzini 
6230f70ed47SPaolo Bonzini uint64_t helper_rdpkru(CPUX86State *env, uint32_t ecx)
6240f70ed47SPaolo Bonzini {
6250f70ed47SPaolo Bonzini     if ((env->cr[4] & CR4_PKE_MASK) == 0) {
6260f70ed47SPaolo Bonzini         raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
6270f70ed47SPaolo Bonzini     }
6280f70ed47SPaolo Bonzini     if (ecx != 0) {
6290f70ed47SPaolo Bonzini         raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
6300f70ed47SPaolo Bonzini     }
6310f70ed47SPaolo Bonzini 
6320f70ed47SPaolo Bonzini     return env->pkru;
6330f70ed47SPaolo Bonzini }
6340f70ed47SPaolo Bonzini 
6350f70ed47SPaolo Bonzini void helper_wrpkru(CPUX86State *env, uint32_t ecx, uint64_t val)
6360f70ed47SPaolo Bonzini {
6376aa9e42fSRichard Henderson     CPUState *cs = env_cpu(env);
6380f70ed47SPaolo Bonzini 
6390f70ed47SPaolo Bonzini     if ((env->cr[4] & CR4_PKE_MASK) == 0) {
6400f70ed47SPaolo Bonzini         raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
6410f70ed47SPaolo Bonzini     }
6420f70ed47SPaolo Bonzini     if (ecx != 0 || (val & 0xFFFFFFFF00000000ull)) {
6430f70ed47SPaolo Bonzini         raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
6440f70ed47SPaolo Bonzini     }
6450f70ed47SPaolo Bonzini 
6460f70ed47SPaolo Bonzini     env->pkru = val;
647d10eb08fSAlex Bennée     tlb_flush(cs);
6480f70ed47SPaolo Bonzini }
649