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