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