xref: /qemu/target/i386/tcg/sysemu/misc_helper.c (revision d884e272)
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         if (val & (0xfff | ((~0ULL) << env_archcpu(env)->phys_bits))) {
216             goto error;
217         }
218         env->vm_hsave = val;
219         break;
220 #ifdef TARGET_X86_64
221     case MSR_LSTAR:
222         env->lstar = val;
223         break;
224     case MSR_CSTAR:
225         env->cstar = val;
226         break;
227     case MSR_FMASK:
228         env->fmask = val;
229         break;
230     case MSR_FSBASE:
231         env->segs[R_FS].base = val;
232         break;
233     case MSR_GSBASE:
234         env->segs[R_GS].base = val;
235         break;
236     case MSR_KERNELGSBASE:
237         env->kernelgsbase = val;
238         break;
239 #endif
240     case MSR_MTRRphysBase(0):
241     case MSR_MTRRphysBase(1):
242     case MSR_MTRRphysBase(2):
243     case MSR_MTRRphysBase(3):
244     case MSR_MTRRphysBase(4):
245     case MSR_MTRRphysBase(5):
246     case MSR_MTRRphysBase(6):
247     case MSR_MTRRphysBase(7):
248         env->mtrr_var[((uint32_t)env->regs[R_ECX] -
249                        MSR_MTRRphysBase(0)) / 2].base = val;
250         break;
251     case MSR_MTRRphysMask(0):
252     case MSR_MTRRphysMask(1):
253     case MSR_MTRRphysMask(2):
254     case MSR_MTRRphysMask(3):
255     case MSR_MTRRphysMask(4):
256     case MSR_MTRRphysMask(5):
257     case MSR_MTRRphysMask(6):
258     case MSR_MTRRphysMask(7):
259         env->mtrr_var[((uint32_t)env->regs[R_ECX] -
260                        MSR_MTRRphysMask(0)) / 2].mask = val;
261         break;
262     case MSR_MTRRfix64K_00000:
263         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
264                         MSR_MTRRfix64K_00000] = val;
265         break;
266     case MSR_MTRRfix16K_80000:
267     case MSR_MTRRfix16K_A0000:
268         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
269                         MSR_MTRRfix16K_80000 + 1] = val;
270         break;
271     case MSR_MTRRfix4K_C0000:
272     case MSR_MTRRfix4K_C8000:
273     case MSR_MTRRfix4K_D0000:
274     case MSR_MTRRfix4K_D8000:
275     case MSR_MTRRfix4K_E0000:
276     case MSR_MTRRfix4K_E8000:
277     case MSR_MTRRfix4K_F0000:
278     case MSR_MTRRfix4K_F8000:
279         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
280                         MSR_MTRRfix4K_C0000 + 3] = val;
281         break;
282     case MSR_MTRRdefType:
283         env->mtrr_deftype = val;
284         break;
285     case MSR_MCG_STATUS:
286         env->mcg_status = val;
287         break;
288     case MSR_MCG_CTL:
289         if ((env->mcg_cap & MCG_CTL_P)
290             && (val == 0 || val == ~(uint64_t)0)) {
291             env->mcg_ctl = val;
292         }
293         break;
294     case MSR_TSC_AUX:
295         env->tsc_aux = val;
296         break;
297     case MSR_IA32_MISC_ENABLE:
298         env->msr_ia32_misc_enable = val;
299         break;
300     case MSR_IA32_BNDCFGS:
301         /* FIXME: #GP if reserved bits are set.  */
302         /* FIXME: Extend highest implemented bit of linear address.  */
303         env->msr_bndcfgs = val;
304         cpu_sync_bndcs_hflags(env);
305         break;
306     case MSR_APIC_START ... MSR_APIC_END: {
307         int ret;
308         int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START;
309 
310         bql_lock();
311         ret = apic_msr_write(index, val);
312         bql_unlock();
313         if (ret < 0) {
314             goto error;
315         }
316 
317         break;
318     }
319     default:
320         if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
321             && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
322             (4 * env->mcg_cap & 0xff)) {
323             uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
324             if ((offset & 0x3) != 0
325                 || (val == 0 || val == ~(uint64_t)0)) {
326                 env->mce_banks[offset] = val;
327             }
328             break;
329         }
330         /* XXX: exception? */
331         break;
332     }
333     return;
334 error:
335     raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
336 }
337 
338 void helper_rdmsr(CPUX86State *env)
339 {
340     X86CPU *x86_cpu = env_archcpu(env);
341     uint64_t val;
342 
343     cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0, GETPC());
344 
345     switch ((uint32_t)env->regs[R_ECX]) {
346     case MSR_IA32_SYSENTER_CS:
347         val = env->sysenter_cs;
348         break;
349     case MSR_IA32_SYSENTER_ESP:
350         val = env->sysenter_esp;
351         break;
352     case MSR_IA32_SYSENTER_EIP:
353         val = env->sysenter_eip;
354         break;
355     case MSR_IA32_APICBASE:
356         val = cpu_get_apic_base(env_archcpu(env)->apic_state);
357         break;
358     case MSR_EFER:
359         val = env->efer;
360         break;
361     case MSR_STAR:
362         val = env->star;
363         break;
364     case MSR_PAT:
365         val = env->pat;
366         break;
367     case MSR_IA32_PKRS:
368         val = env->pkrs;
369         break;
370     case MSR_VM_HSAVE_PA:
371         val = env->vm_hsave;
372         break;
373     case MSR_IA32_PERF_STATUS:
374         /* tsc_increment_by_tick */
375         val = 1000ULL;
376         /* CPU multiplier */
377         val |= (((uint64_t)4ULL) << 40);
378         break;
379 #ifdef TARGET_X86_64
380     case MSR_LSTAR:
381         val = env->lstar;
382         break;
383     case MSR_CSTAR:
384         val = env->cstar;
385         break;
386     case MSR_FMASK:
387         val = env->fmask;
388         break;
389     case MSR_FSBASE:
390         val = env->segs[R_FS].base;
391         break;
392     case MSR_GSBASE:
393         val = env->segs[R_GS].base;
394         break;
395     case MSR_KERNELGSBASE:
396         val = env->kernelgsbase;
397         break;
398     case MSR_TSC_AUX:
399         val = env->tsc_aux;
400         break;
401 #endif
402     case MSR_SMI_COUNT:
403         val = env->msr_smi_count;
404         break;
405     case MSR_MTRRphysBase(0):
406     case MSR_MTRRphysBase(1):
407     case MSR_MTRRphysBase(2):
408     case MSR_MTRRphysBase(3):
409     case MSR_MTRRphysBase(4):
410     case MSR_MTRRphysBase(5):
411     case MSR_MTRRphysBase(6):
412     case MSR_MTRRphysBase(7):
413         val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
414                              MSR_MTRRphysBase(0)) / 2].base;
415         break;
416     case MSR_MTRRphysMask(0):
417     case MSR_MTRRphysMask(1):
418     case MSR_MTRRphysMask(2):
419     case MSR_MTRRphysMask(3):
420     case MSR_MTRRphysMask(4):
421     case MSR_MTRRphysMask(5):
422     case MSR_MTRRphysMask(6):
423     case MSR_MTRRphysMask(7):
424         val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
425                              MSR_MTRRphysMask(0)) / 2].mask;
426         break;
427     case MSR_MTRRfix64K_00000:
428         val = env->mtrr_fixed[0];
429         break;
430     case MSR_MTRRfix16K_80000:
431     case MSR_MTRRfix16K_A0000:
432         val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
433                               MSR_MTRRfix16K_80000 + 1];
434         break;
435     case MSR_MTRRfix4K_C0000:
436     case MSR_MTRRfix4K_C8000:
437     case MSR_MTRRfix4K_D0000:
438     case MSR_MTRRfix4K_D8000:
439     case MSR_MTRRfix4K_E0000:
440     case MSR_MTRRfix4K_E8000:
441     case MSR_MTRRfix4K_F0000:
442     case MSR_MTRRfix4K_F8000:
443         val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
444                               MSR_MTRRfix4K_C0000 + 3];
445         break;
446     case MSR_MTRRdefType:
447         val = env->mtrr_deftype;
448         break;
449     case MSR_MTRRcap:
450         if (env->features[FEAT_1_EDX] & CPUID_MTRR) {
451             val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT |
452                 MSR_MTRRcap_WC_SUPPORTED;
453         } else {
454             /* XXX: exception? */
455             val = 0;
456         }
457         break;
458     case MSR_MCG_CAP:
459         val = env->mcg_cap;
460         break;
461     case MSR_MCG_CTL:
462         if (env->mcg_cap & MCG_CTL_P) {
463             val = env->mcg_ctl;
464         } else {
465             val = 0;
466         }
467         break;
468     case MSR_MCG_STATUS:
469         val = env->mcg_status;
470         break;
471     case MSR_IA32_MISC_ENABLE:
472         val = env->msr_ia32_misc_enable;
473         break;
474     case MSR_IA32_BNDCFGS:
475         val = env->msr_bndcfgs;
476         break;
477      case MSR_IA32_UCODE_REV:
478         val = x86_cpu->ucode_rev;
479         break;
480     case MSR_CORE_THREAD_COUNT: {
481         CPUState *cs = CPU(x86_cpu);
482         val = (cs->nr_threads * cs->nr_cores) | (cs->nr_cores << 16);
483         break;
484     }
485     case MSR_APIC_START ... MSR_APIC_END: {
486         int ret;
487         int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START;
488 
489         bql_lock();
490         ret = apic_msr_read(index, &val);
491         bql_unlock();
492         if (ret < 0) {
493             raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
494         }
495 
496         break;
497     }
498     default:
499         if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
500             && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
501             (4 * env->mcg_cap & 0xff)) {
502             uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
503             val = env->mce_banks[offset];
504             break;
505         }
506         /* XXX: exception? */
507         val = 0;
508         break;
509     }
510     env->regs[R_EAX] = (uint32_t)(val);
511     env->regs[R_EDX] = (uint32_t)(val >> 32);
512 }
513 
514 void helper_flush_page(CPUX86State *env, target_ulong addr)
515 {
516     tlb_flush_page(env_cpu(env), addr);
517 }
518 
519 static G_NORETURN
520 void do_hlt(CPUX86State *env)
521 {
522     CPUState *cs = env_cpu(env);
523 
524     env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
525     cs->halted = 1;
526     cs->exception_index = EXCP_HLT;
527     cpu_loop_exit(cs);
528 }
529 
530 G_NORETURN void helper_hlt(CPUX86State *env, int next_eip_addend)
531 {
532     cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC());
533     env->eip += next_eip_addend;
534 
535     do_hlt(env);
536 }
537 
538 void helper_monitor(CPUX86State *env, target_ulong ptr)
539 {
540     if ((uint32_t)env->regs[R_ECX] != 0) {
541         raise_exception_ra(env, EXCP0D_GPF, GETPC());
542     }
543     /* XXX: store address? */
544     cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0, GETPC());
545 }
546 
547 G_NORETURN void helper_mwait(CPUX86State *env, int next_eip_addend)
548 {
549     CPUState *cs = env_cpu(env);
550 
551     if ((uint32_t)env->regs[R_ECX] != 0) {
552         raise_exception_ra(env, EXCP0D_GPF, GETPC());
553     }
554     cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0, GETPC());
555     env->eip += next_eip_addend;
556 
557     /* XXX: not complete but not completely erroneous */
558     if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) {
559         do_pause(env);
560     } else {
561         do_hlt(env);
562     }
563 }
564