xref: /openbmc/qemu/target/i386/tcg/misc_helper.c (revision 729cc683)
1 /*
2  *  x86 misc helpers
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/exec-all.h"
25 #include "exec/cpu_ldst.h"
26 #include "exec/address-spaces.h"
27 #include "helper-tcg.h"
28 
29 /*
30  * NOTE: the translator must set DisasContext.cc_op to CC_OP_EFLAGS
31  * after generating a call to a helper that uses this.
32  */
33 void cpu_load_eflags(CPUX86State *env, int eflags, int update_mask)
34 {
35     CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
36     CC_OP = CC_OP_EFLAGS;
37     env->df = 1 - (2 * ((eflags >> 10) & 1));
38     env->eflags = (env->eflags & ~update_mask) |
39         (eflags & update_mask) | 0x2;
40 }
41 
42 void helper_outb(CPUX86State *env, uint32_t port, uint32_t data)
43 {
44 #ifdef CONFIG_USER_ONLY
45     fprintf(stderr, "outb: port=0x%04x, data=%02x\n", port, data);
46 #else
47     address_space_stb(&address_space_io, port, data,
48                       cpu_get_mem_attrs(env), NULL);
49 #endif
50 }
51 
52 target_ulong helper_inb(CPUX86State *env, uint32_t port)
53 {
54 #ifdef CONFIG_USER_ONLY
55     fprintf(stderr, "inb: port=0x%04x\n", port);
56     return 0;
57 #else
58     return address_space_ldub(&address_space_io, port,
59                               cpu_get_mem_attrs(env), NULL);
60 #endif
61 }
62 
63 void helper_outw(CPUX86State *env, uint32_t port, uint32_t data)
64 {
65 #ifdef CONFIG_USER_ONLY
66     fprintf(stderr, "outw: port=0x%04x, data=%04x\n", port, data);
67 #else
68     address_space_stw(&address_space_io, port, data,
69                       cpu_get_mem_attrs(env), NULL);
70 #endif
71 }
72 
73 target_ulong helper_inw(CPUX86State *env, uint32_t port)
74 {
75 #ifdef CONFIG_USER_ONLY
76     fprintf(stderr, "inw: port=0x%04x\n", port);
77     return 0;
78 #else
79     return address_space_lduw(&address_space_io, port,
80                               cpu_get_mem_attrs(env), NULL);
81 #endif
82 }
83 
84 void helper_outl(CPUX86State *env, uint32_t port, uint32_t data)
85 {
86 #ifdef CONFIG_USER_ONLY
87     fprintf(stderr, "outl: port=0x%04x, data=%08x\n", port, data);
88 #else
89     address_space_stl(&address_space_io, port, data,
90                       cpu_get_mem_attrs(env), NULL);
91 #endif
92 }
93 
94 target_ulong helper_inl(CPUX86State *env, uint32_t port)
95 {
96 #ifdef CONFIG_USER_ONLY
97     fprintf(stderr, "inl: port=0x%04x\n", port);
98     return 0;
99 #else
100     return address_space_ldl(&address_space_io, port,
101                              cpu_get_mem_attrs(env), NULL);
102 #endif
103 }
104 
105 void helper_into(CPUX86State *env, int next_eip_addend)
106 {
107     int eflags;
108 
109     eflags = cpu_cc_compute_all(env, CC_OP);
110     if (eflags & CC_O) {
111         raise_interrupt(env, EXCP04_INTO, 1, 0, next_eip_addend);
112     }
113 }
114 
115 void helper_cpuid(CPUX86State *env)
116 {
117     uint32_t eax, ebx, ecx, edx;
118 
119     cpu_svm_check_intercept_param(env, SVM_EXIT_CPUID, 0, GETPC());
120 
121     cpu_x86_cpuid(env, (uint32_t)env->regs[R_EAX], (uint32_t)env->regs[R_ECX],
122                   &eax, &ebx, &ecx, &edx);
123     env->regs[R_EAX] = eax;
124     env->regs[R_EBX] = ebx;
125     env->regs[R_ECX] = ecx;
126     env->regs[R_EDX] = edx;
127 }
128 
129 #if defined(CONFIG_USER_ONLY)
130 target_ulong helper_read_crN(CPUX86State *env, int reg)
131 {
132     return 0;
133 }
134 
135 void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
136 {
137 }
138 #else
139 target_ulong helper_read_crN(CPUX86State *env, int reg)
140 {
141     target_ulong val;
142 
143     cpu_svm_check_intercept_param(env, SVM_EXIT_READ_CR0 + reg, 0, GETPC());
144     switch (reg) {
145     default:
146         val = env->cr[reg];
147         break;
148     case 8:
149         if (!(env->hflags2 & HF2_VINTR_MASK)) {
150             val = cpu_get_apic_tpr(env_archcpu(env)->apic_state);
151         } else {
152             val = env->v_tpr;
153         }
154         break;
155     }
156     return val;
157 }
158 
159 void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
160 {
161     cpu_svm_check_intercept_param(env, SVM_EXIT_WRITE_CR0 + reg, 0, GETPC());
162     switch (reg) {
163     case 0:
164         cpu_x86_update_cr0(env, t0);
165         break;
166     case 3:
167         cpu_x86_update_cr3(env, t0);
168         break;
169     case 4:
170         cpu_x86_update_cr4(env, t0);
171         break;
172     case 8:
173         if (!(env->hflags2 & HF2_VINTR_MASK)) {
174             qemu_mutex_lock_iothread();
175             cpu_set_apic_tpr(env_archcpu(env)->apic_state, t0);
176             qemu_mutex_unlock_iothread();
177         }
178         env->v_tpr = t0 & 0x0f;
179         break;
180     default:
181         env->cr[reg] = t0;
182         break;
183     }
184 }
185 #endif
186 
187 void helper_lmsw(CPUX86State *env, target_ulong t0)
188 {
189     /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
190        if already set to one. */
191     t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
192     helper_write_crN(env, 0, t0);
193 }
194 
195 void helper_invlpg(CPUX86State *env, target_ulong addr)
196 {
197     X86CPU *cpu = env_archcpu(env);
198 
199     cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0, GETPC());
200     tlb_flush_page(CPU(cpu), addr);
201 }
202 
203 void helper_rdtsc(CPUX86State *env)
204 {
205     uint64_t val;
206 
207     if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
208         raise_exception_ra(env, EXCP0D_GPF, GETPC());
209     }
210     cpu_svm_check_intercept_param(env, SVM_EXIT_RDTSC, 0, GETPC());
211 
212     val = cpu_get_tsc(env) + env->tsc_offset;
213     env->regs[R_EAX] = (uint32_t)(val);
214     env->regs[R_EDX] = (uint32_t)(val >> 32);
215 }
216 
217 void helper_rdtscp(CPUX86State *env)
218 {
219     helper_rdtsc(env);
220     env->regs[R_ECX] = (uint32_t)(env->tsc_aux);
221 }
222 
223 void helper_rdpmc(CPUX86State *env)
224 {
225     if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
226         raise_exception_ra(env, EXCP0D_GPF, GETPC());
227     }
228     cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0, GETPC());
229 
230     /* currently unimplemented */
231     qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n");
232     raise_exception_err(env, EXCP06_ILLOP, 0);
233 }
234 
235 #if defined(CONFIG_USER_ONLY)
236 void helper_wrmsr(CPUX86State *env)
237 {
238 }
239 
240 void helper_rdmsr(CPUX86State *env)
241 {
242 }
243 #else
244 void helper_wrmsr(CPUX86State *env)
245 {
246     uint64_t val;
247 
248     cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC());
249 
250     val = ((uint32_t)env->regs[R_EAX]) |
251         ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
252 
253     switch ((uint32_t)env->regs[R_ECX]) {
254     case MSR_IA32_SYSENTER_CS:
255         env->sysenter_cs = val & 0xffff;
256         break;
257     case MSR_IA32_SYSENTER_ESP:
258         env->sysenter_esp = val;
259         break;
260     case MSR_IA32_SYSENTER_EIP:
261         env->sysenter_eip = val;
262         break;
263     case MSR_IA32_APICBASE:
264         cpu_set_apic_base(env_archcpu(env)->apic_state, val);
265         break;
266     case MSR_EFER:
267         {
268             uint64_t update_mask;
269 
270             update_mask = 0;
271             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) {
272                 update_mask |= MSR_EFER_SCE;
273             }
274             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
275                 update_mask |= MSR_EFER_LME;
276             }
277             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
278                 update_mask |= MSR_EFER_FFXSR;
279             }
280             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) {
281                 update_mask |= MSR_EFER_NXE;
282             }
283             if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
284                 update_mask |= MSR_EFER_SVME;
285             }
286             if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
287                 update_mask |= MSR_EFER_FFXSR;
288             }
289             cpu_load_efer(env, (env->efer & ~update_mask) |
290                           (val & update_mask));
291         }
292         break;
293     case MSR_STAR:
294         env->star = val;
295         break;
296     case MSR_PAT:
297         env->pat = val;
298         break;
299     case MSR_VM_HSAVE_PA:
300         env->vm_hsave = val;
301         break;
302 #ifdef TARGET_X86_64
303     case MSR_LSTAR:
304         env->lstar = val;
305         break;
306     case MSR_CSTAR:
307         env->cstar = val;
308         break;
309     case MSR_FMASK:
310         env->fmask = val;
311         break;
312     case MSR_FSBASE:
313         env->segs[R_FS].base = val;
314         break;
315     case MSR_GSBASE:
316         env->segs[R_GS].base = val;
317         break;
318     case MSR_KERNELGSBASE:
319         env->kernelgsbase = val;
320         break;
321 #endif
322     case MSR_MTRRphysBase(0):
323     case MSR_MTRRphysBase(1):
324     case MSR_MTRRphysBase(2):
325     case MSR_MTRRphysBase(3):
326     case MSR_MTRRphysBase(4):
327     case MSR_MTRRphysBase(5):
328     case MSR_MTRRphysBase(6):
329     case MSR_MTRRphysBase(7):
330         env->mtrr_var[((uint32_t)env->regs[R_ECX] -
331                        MSR_MTRRphysBase(0)) / 2].base = val;
332         break;
333     case MSR_MTRRphysMask(0):
334     case MSR_MTRRphysMask(1):
335     case MSR_MTRRphysMask(2):
336     case MSR_MTRRphysMask(3):
337     case MSR_MTRRphysMask(4):
338     case MSR_MTRRphysMask(5):
339     case MSR_MTRRphysMask(6):
340     case MSR_MTRRphysMask(7):
341         env->mtrr_var[((uint32_t)env->regs[R_ECX] -
342                        MSR_MTRRphysMask(0)) / 2].mask = val;
343         break;
344     case MSR_MTRRfix64K_00000:
345         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
346                         MSR_MTRRfix64K_00000] = val;
347         break;
348     case MSR_MTRRfix16K_80000:
349     case MSR_MTRRfix16K_A0000:
350         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
351                         MSR_MTRRfix16K_80000 + 1] = val;
352         break;
353     case MSR_MTRRfix4K_C0000:
354     case MSR_MTRRfix4K_C8000:
355     case MSR_MTRRfix4K_D0000:
356     case MSR_MTRRfix4K_D8000:
357     case MSR_MTRRfix4K_E0000:
358     case MSR_MTRRfix4K_E8000:
359     case MSR_MTRRfix4K_F0000:
360     case MSR_MTRRfix4K_F8000:
361         env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
362                         MSR_MTRRfix4K_C0000 + 3] = val;
363         break;
364     case MSR_MTRRdefType:
365         env->mtrr_deftype = val;
366         break;
367     case MSR_MCG_STATUS:
368         env->mcg_status = val;
369         break;
370     case MSR_MCG_CTL:
371         if ((env->mcg_cap & MCG_CTL_P)
372             && (val == 0 || val == ~(uint64_t)0)) {
373             env->mcg_ctl = val;
374         }
375         break;
376     case MSR_TSC_AUX:
377         env->tsc_aux = val;
378         break;
379     case MSR_IA32_MISC_ENABLE:
380         env->msr_ia32_misc_enable = val;
381         break;
382     case MSR_IA32_BNDCFGS:
383         /* FIXME: #GP if reserved bits are set.  */
384         /* FIXME: Extend highest implemented bit of linear address.  */
385         env->msr_bndcfgs = val;
386         cpu_sync_bndcs_hflags(env);
387         break;
388     default:
389         if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
390             && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
391             (4 * env->mcg_cap & 0xff)) {
392             uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
393             if ((offset & 0x3) != 0
394                 || (val == 0 || val == ~(uint64_t)0)) {
395                 env->mce_banks[offset] = val;
396             }
397             break;
398         }
399         /* XXX: exception? */
400         break;
401     }
402 }
403 
404 void helper_rdmsr(CPUX86State *env)
405 {
406     X86CPU *x86_cpu = env_archcpu(env);
407     uint64_t val;
408 
409     cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0, GETPC());
410 
411     switch ((uint32_t)env->regs[R_ECX]) {
412     case MSR_IA32_SYSENTER_CS:
413         val = env->sysenter_cs;
414         break;
415     case MSR_IA32_SYSENTER_ESP:
416         val = env->sysenter_esp;
417         break;
418     case MSR_IA32_SYSENTER_EIP:
419         val = env->sysenter_eip;
420         break;
421     case MSR_IA32_APICBASE:
422         val = cpu_get_apic_base(env_archcpu(env)->apic_state);
423         break;
424     case MSR_EFER:
425         val = env->efer;
426         break;
427     case MSR_STAR:
428         val = env->star;
429         break;
430     case MSR_PAT:
431         val = env->pat;
432         break;
433     case MSR_VM_HSAVE_PA:
434         val = env->vm_hsave;
435         break;
436     case MSR_IA32_PERF_STATUS:
437         /* tsc_increment_by_tick */
438         val = 1000ULL;
439         /* CPU multiplier */
440         val |= (((uint64_t)4ULL) << 40);
441         break;
442 #ifdef TARGET_X86_64
443     case MSR_LSTAR:
444         val = env->lstar;
445         break;
446     case MSR_CSTAR:
447         val = env->cstar;
448         break;
449     case MSR_FMASK:
450         val = env->fmask;
451         break;
452     case MSR_FSBASE:
453         val = env->segs[R_FS].base;
454         break;
455     case MSR_GSBASE:
456         val = env->segs[R_GS].base;
457         break;
458     case MSR_KERNELGSBASE:
459         val = env->kernelgsbase;
460         break;
461     case MSR_TSC_AUX:
462         val = env->tsc_aux;
463         break;
464 #endif
465     case MSR_SMI_COUNT:
466         val = env->msr_smi_count;
467         break;
468     case MSR_MTRRphysBase(0):
469     case MSR_MTRRphysBase(1):
470     case MSR_MTRRphysBase(2):
471     case MSR_MTRRphysBase(3):
472     case MSR_MTRRphysBase(4):
473     case MSR_MTRRphysBase(5):
474     case MSR_MTRRphysBase(6):
475     case MSR_MTRRphysBase(7):
476         val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
477                              MSR_MTRRphysBase(0)) / 2].base;
478         break;
479     case MSR_MTRRphysMask(0):
480     case MSR_MTRRphysMask(1):
481     case MSR_MTRRphysMask(2):
482     case MSR_MTRRphysMask(3):
483     case MSR_MTRRphysMask(4):
484     case MSR_MTRRphysMask(5):
485     case MSR_MTRRphysMask(6):
486     case MSR_MTRRphysMask(7):
487         val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
488                              MSR_MTRRphysMask(0)) / 2].mask;
489         break;
490     case MSR_MTRRfix64K_00000:
491         val = env->mtrr_fixed[0];
492         break;
493     case MSR_MTRRfix16K_80000:
494     case MSR_MTRRfix16K_A0000:
495         val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
496                               MSR_MTRRfix16K_80000 + 1];
497         break;
498     case MSR_MTRRfix4K_C0000:
499     case MSR_MTRRfix4K_C8000:
500     case MSR_MTRRfix4K_D0000:
501     case MSR_MTRRfix4K_D8000:
502     case MSR_MTRRfix4K_E0000:
503     case MSR_MTRRfix4K_E8000:
504     case MSR_MTRRfix4K_F0000:
505     case MSR_MTRRfix4K_F8000:
506         val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
507                               MSR_MTRRfix4K_C0000 + 3];
508         break;
509     case MSR_MTRRdefType:
510         val = env->mtrr_deftype;
511         break;
512     case MSR_MTRRcap:
513         if (env->features[FEAT_1_EDX] & CPUID_MTRR) {
514             val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT |
515                 MSR_MTRRcap_WC_SUPPORTED;
516         } else {
517             /* XXX: exception? */
518             val = 0;
519         }
520         break;
521     case MSR_MCG_CAP:
522         val = env->mcg_cap;
523         break;
524     case MSR_MCG_CTL:
525         if (env->mcg_cap & MCG_CTL_P) {
526             val = env->mcg_ctl;
527         } else {
528             val = 0;
529         }
530         break;
531     case MSR_MCG_STATUS:
532         val = env->mcg_status;
533         break;
534     case MSR_IA32_MISC_ENABLE:
535         val = env->msr_ia32_misc_enable;
536         break;
537     case MSR_IA32_BNDCFGS:
538         val = env->msr_bndcfgs;
539         break;
540      case MSR_IA32_UCODE_REV:
541         val = x86_cpu->ucode_rev;
542         break;
543     default:
544         if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
545             && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
546             (4 * env->mcg_cap & 0xff)) {
547             uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
548             val = env->mce_banks[offset];
549             break;
550         }
551         /* XXX: exception? */
552         val = 0;
553         break;
554     }
555     env->regs[R_EAX] = (uint32_t)(val);
556     env->regs[R_EDX] = (uint32_t)(val >> 32);
557 }
558 #endif
559 
560 static void do_pause(X86CPU *cpu)
561 {
562     CPUState *cs = CPU(cpu);
563 
564     /* Just let another CPU run.  */
565     cs->exception_index = EXCP_INTERRUPT;
566     cpu_loop_exit(cs);
567 }
568 
569 static void do_hlt(X86CPU *cpu)
570 {
571     CPUState *cs = CPU(cpu);
572     CPUX86State *env = &cpu->env;
573 
574     env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
575     cs->halted = 1;
576     cs->exception_index = EXCP_HLT;
577     cpu_loop_exit(cs);
578 }
579 
580 void helper_hlt(CPUX86State *env, int next_eip_addend)
581 {
582     X86CPU *cpu = env_archcpu(env);
583 
584     cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC());
585     env->eip += next_eip_addend;
586 
587     do_hlt(cpu);
588 }
589 
590 void helper_monitor(CPUX86State *env, target_ulong ptr)
591 {
592     if ((uint32_t)env->regs[R_ECX] != 0) {
593         raise_exception_ra(env, EXCP0D_GPF, GETPC());
594     }
595     /* XXX: store address? */
596     cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0, GETPC());
597 }
598 
599 void helper_mwait(CPUX86State *env, int next_eip_addend)
600 {
601     CPUState *cs = env_cpu(env);
602     X86CPU *cpu = env_archcpu(env);
603 
604     if ((uint32_t)env->regs[R_ECX] != 0) {
605         raise_exception_ra(env, EXCP0D_GPF, GETPC());
606     }
607     cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0, GETPC());
608     env->eip += next_eip_addend;
609 
610     /* XXX: not complete but not completely erroneous */
611     if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) {
612         do_pause(cpu);
613     } else {
614         do_hlt(cpu);
615     }
616 }
617 
618 void helper_pause(CPUX86State *env, int next_eip_addend)
619 {
620     X86CPU *cpu = env_archcpu(env);
621 
622     cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0, GETPC());
623     env->eip += next_eip_addend;
624 
625     do_pause(cpu);
626 }
627 
628 void helper_debug(CPUX86State *env)
629 {
630     CPUState *cs = env_cpu(env);
631 
632     cs->exception_index = EXCP_DEBUG;
633     cpu_loop_exit(cs);
634 }
635 
636 uint64_t helper_rdpkru(CPUX86State *env, uint32_t ecx)
637 {
638     if ((env->cr[4] & CR4_PKE_MASK) == 0) {
639         raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
640     }
641     if (ecx != 0) {
642         raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
643     }
644 
645     return env->pkru;
646 }
647 
648 void helper_wrpkru(CPUX86State *env, uint32_t ecx, uint64_t val)
649 {
650     CPUState *cs = env_cpu(env);
651 
652     if ((env->cr[4] & CR4_PKE_MASK) == 0) {
653         raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
654     }
655     if (ecx != 0 || (val & 0xFFFFFFFF00000000ull)) {
656         raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
657     }
658 
659     env->pkru = val;
660     tlb_flush(cs);
661 }
662