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