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