hw/timer/sse-timer: Model the SSE Subsystem System Timer
[qemu/ar7.git] / target / i386 / tcg / misc_helper.c
blob90b87fdef00395adda8472d1016f7795274a4d9b
1 /*
2 * x86 misc helpers
4 * Copyright (c) 2003 Fabrice Bellard
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.
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.
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/>.
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"
30 * NOTE: the translator must set DisasContext.cc_op to CC_OP_EFLAGS
31 * after generating a call to a helper that uses this.
33 void cpu_load_eflags(CPUX86State *env, int eflags, int update_mask)
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;
42 void helper_outb(CPUX86State *env, uint32_t port, uint32_t data)
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
52 target_ulong helper_inb(CPUX86State *env, uint32_t port)
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
63 void helper_outw(CPUX86State *env, uint32_t port, uint32_t data)
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
73 target_ulong helper_inw(CPUX86State *env, uint32_t port)
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
84 void helper_outl(CPUX86State *env, uint32_t port, uint32_t data)
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
94 target_ulong helper_inl(CPUX86State *env, uint32_t port)
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
105 void helper_into(CPUX86State *env, int next_eip_addend)
107 int eflags;
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);
115 void helper_cpuid(CPUX86State *env)
117 uint32_t eax, ebx, ecx, edx;
119 cpu_svm_check_intercept_param(env, SVM_EXIT_CPUID, 0, GETPC());
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;
129 #if defined(CONFIG_USER_ONLY)
130 target_ulong helper_read_crN(CPUX86State *env, int reg)
132 return 0;
135 void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
138 #else
139 target_ulong helper_read_crN(CPUX86State *env, int reg)
141 target_ulong val;
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;
154 break;
156 return val;
159 void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
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();
178 env->v_tpr = t0 & 0x0f;
179 break;
180 default:
181 env->cr[reg] = t0;
182 break;
185 #endif
187 void helper_lmsw(CPUX86State *env, target_ulong t0)
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);
195 void helper_invlpg(CPUX86State *env, target_ulong addr)
197 X86CPU *cpu = env_archcpu(env);
199 cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0, GETPC());
200 tlb_flush_page(CPU(cpu), addr);
203 void helper_rdtsc(CPUX86State *env)
205 uint64_t val;
207 if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
208 raise_exception_ra(env, EXCP0D_GPF, GETPC());
210 cpu_svm_check_intercept_param(env, SVM_EXIT_RDTSC, 0, GETPC());
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);
217 void helper_rdtscp(CPUX86State *env)
219 helper_rdtsc(env);
220 env->regs[R_ECX] = (uint32_t)(env->tsc_aux);
223 void helper_rdpmc(CPUX86State *env)
225 if (((env->cr[4] & CR4_PCE_MASK) == 0 ) &&
226 ((env->hflags & HF_CPL_MASK) != 0)) {
227 raise_exception_ra(env, EXCP0D_GPF, GETPC());
229 cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0, GETPC());
231 /* currently unimplemented */
232 qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n");
233 raise_exception_err(env, EXCP06_ILLOP, 0);
236 #if defined(CONFIG_USER_ONLY)
237 void helper_wrmsr(CPUX86State *env)
241 void helper_rdmsr(CPUX86State *env)
244 #else
245 void helper_wrmsr(CPUX86State *env)
247 uint64_t val;
248 CPUState *cs = env_cpu(env);
250 cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC());
252 val = ((uint32_t)env->regs[R_EAX]) |
253 ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
255 switch ((uint32_t)env->regs[R_ECX]) {
256 case MSR_IA32_SYSENTER_CS:
257 env->sysenter_cs = val & 0xffff;
258 break;
259 case MSR_IA32_SYSENTER_ESP:
260 env->sysenter_esp = val;
261 break;
262 case MSR_IA32_SYSENTER_EIP:
263 env->sysenter_eip = val;
264 break;
265 case MSR_IA32_APICBASE:
266 cpu_set_apic_base(env_archcpu(env)->apic_state, val);
267 break;
268 case MSR_EFER:
270 uint64_t update_mask;
272 update_mask = 0;
273 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) {
274 update_mask |= MSR_EFER_SCE;
276 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
277 update_mask |= MSR_EFER_LME;
279 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
280 update_mask |= MSR_EFER_FFXSR;
282 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) {
283 update_mask |= MSR_EFER_NXE;
285 if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
286 update_mask |= MSR_EFER_SVME;
288 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
289 update_mask |= MSR_EFER_FFXSR;
291 cpu_load_efer(env, (env->efer & ~update_mask) |
292 (val & update_mask));
294 break;
295 case MSR_STAR:
296 env->star = val;
297 break;
298 case MSR_PAT:
299 env->pat = val;
300 break;
301 case MSR_IA32_PKRS:
302 if (val & 0xFFFFFFFF00000000ull) {
303 goto error;
305 env->pkrs = val;
306 tlb_flush(cs);
307 break;
308 case MSR_VM_HSAVE_PA:
309 env->vm_hsave = val;
310 break;
311 #ifdef TARGET_X86_64
312 case MSR_LSTAR:
313 env->lstar = val;
314 break;
315 case MSR_CSTAR:
316 env->cstar = val;
317 break;
318 case MSR_FMASK:
319 env->fmask = val;
320 break;
321 case MSR_FSBASE:
322 env->segs[R_FS].base = val;
323 break;
324 case MSR_GSBASE:
325 env->segs[R_GS].base = val;
326 break;
327 case MSR_KERNELGSBASE:
328 env->kernelgsbase = val;
329 break;
330 #endif
331 case MSR_MTRRphysBase(0):
332 case MSR_MTRRphysBase(1):
333 case MSR_MTRRphysBase(2):
334 case MSR_MTRRphysBase(3):
335 case MSR_MTRRphysBase(4):
336 case MSR_MTRRphysBase(5):
337 case MSR_MTRRphysBase(6):
338 case MSR_MTRRphysBase(7):
339 env->mtrr_var[((uint32_t)env->regs[R_ECX] -
340 MSR_MTRRphysBase(0)) / 2].base = val;
341 break;
342 case MSR_MTRRphysMask(0):
343 case MSR_MTRRphysMask(1):
344 case MSR_MTRRphysMask(2):
345 case MSR_MTRRphysMask(3):
346 case MSR_MTRRphysMask(4):
347 case MSR_MTRRphysMask(5):
348 case MSR_MTRRphysMask(6):
349 case MSR_MTRRphysMask(7):
350 env->mtrr_var[((uint32_t)env->regs[R_ECX] -
351 MSR_MTRRphysMask(0)) / 2].mask = val;
352 break;
353 case MSR_MTRRfix64K_00000:
354 env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
355 MSR_MTRRfix64K_00000] = val;
356 break;
357 case MSR_MTRRfix16K_80000:
358 case MSR_MTRRfix16K_A0000:
359 env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
360 MSR_MTRRfix16K_80000 + 1] = val;
361 break;
362 case MSR_MTRRfix4K_C0000:
363 case MSR_MTRRfix4K_C8000:
364 case MSR_MTRRfix4K_D0000:
365 case MSR_MTRRfix4K_D8000:
366 case MSR_MTRRfix4K_E0000:
367 case MSR_MTRRfix4K_E8000:
368 case MSR_MTRRfix4K_F0000:
369 case MSR_MTRRfix4K_F8000:
370 env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
371 MSR_MTRRfix4K_C0000 + 3] = val;
372 break;
373 case MSR_MTRRdefType:
374 env->mtrr_deftype = val;
375 break;
376 case MSR_MCG_STATUS:
377 env->mcg_status = val;
378 break;
379 case MSR_MCG_CTL:
380 if ((env->mcg_cap & MCG_CTL_P)
381 && (val == 0 || val == ~(uint64_t)0)) {
382 env->mcg_ctl = val;
384 break;
385 case MSR_TSC_AUX:
386 env->tsc_aux = val;
387 break;
388 case MSR_IA32_MISC_ENABLE:
389 env->msr_ia32_misc_enable = val;
390 break;
391 case MSR_IA32_BNDCFGS:
392 /* FIXME: #GP if reserved bits are set. */
393 /* FIXME: Extend highest implemented bit of linear address. */
394 env->msr_bndcfgs = val;
395 cpu_sync_bndcs_hflags(env);
396 break;
397 default:
398 if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
399 && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
400 (4 * env->mcg_cap & 0xff)) {
401 uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
402 if ((offset & 0x3) != 0
403 || (val == 0 || val == ~(uint64_t)0)) {
404 env->mce_banks[offset] = val;
406 break;
408 /* XXX: exception? */
409 break;
411 return;
412 error:
413 raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
416 void helper_rdmsr(CPUX86State *env)
418 X86CPU *x86_cpu = env_archcpu(env);
419 uint64_t val;
421 cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0, GETPC());
423 switch ((uint32_t)env->regs[R_ECX]) {
424 case MSR_IA32_SYSENTER_CS:
425 val = env->sysenter_cs;
426 break;
427 case MSR_IA32_SYSENTER_ESP:
428 val = env->sysenter_esp;
429 break;
430 case MSR_IA32_SYSENTER_EIP:
431 val = env->sysenter_eip;
432 break;
433 case MSR_IA32_APICBASE:
434 val = cpu_get_apic_base(env_archcpu(env)->apic_state);
435 break;
436 case MSR_EFER:
437 val = env->efer;
438 break;
439 case MSR_STAR:
440 val = env->star;
441 break;
442 case MSR_PAT:
443 val = env->pat;
444 break;
445 case MSR_IA32_PKRS:
446 val = env->pkrs;
447 break;
448 case MSR_VM_HSAVE_PA:
449 val = env->vm_hsave;
450 break;
451 case MSR_IA32_PERF_STATUS:
452 /* tsc_increment_by_tick */
453 val = 1000ULL;
454 /* CPU multiplier */
455 val |= (((uint64_t)4ULL) << 40);
456 break;
457 #ifdef TARGET_X86_64
458 case MSR_LSTAR:
459 val = env->lstar;
460 break;
461 case MSR_CSTAR:
462 val = env->cstar;
463 break;
464 case MSR_FMASK:
465 val = env->fmask;
466 break;
467 case MSR_FSBASE:
468 val = env->segs[R_FS].base;
469 break;
470 case MSR_GSBASE:
471 val = env->segs[R_GS].base;
472 break;
473 case MSR_KERNELGSBASE:
474 val = env->kernelgsbase;
475 break;
476 case MSR_TSC_AUX:
477 val = env->tsc_aux;
478 break;
479 #endif
480 case MSR_SMI_COUNT:
481 val = env->msr_smi_count;
482 break;
483 case MSR_MTRRphysBase(0):
484 case MSR_MTRRphysBase(1):
485 case MSR_MTRRphysBase(2):
486 case MSR_MTRRphysBase(3):
487 case MSR_MTRRphysBase(4):
488 case MSR_MTRRphysBase(5):
489 case MSR_MTRRphysBase(6):
490 case MSR_MTRRphysBase(7):
491 val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
492 MSR_MTRRphysBase(0)) / 2].base;
493 break;
494 case MSR_MTRRphysMask(0):
495 case MSR_MTRRphysMask(1):
496 case MSR_MTRRphysMask(2):
497 case MSR_MTRRphysMask(3):
498 case MSR_MTRRphysMask(4):
499 case MSR_MTRRphysMask(5):
500 case MSR_MTRRphysMask(6):
501 case MSR_MTRRphysMask(7):
502 val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
503 MSR_MTRRphysMask(0)) / 2].mask;
504 break;
505 case MSR_MTRRfix64K_00000:
506 val = env->mtrr_fixed[0];
507 break;
508 case MSR_MTRRfix16K_80000:
509 case MSR_MTRRfix16K_A0000:
510 val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
511 MSR_MTRRfix16K_80000 + 1];
512 break;
513 case MSR_MTRRfix4K_C0000:
514 case MSR_MTRRfix4K_C8000:
515 case MSR_MTRRfix4K_D0000:
516 case MSR_MTRRfix4K_D8000:
517 case MSR_MTRRfix4K_E0000:
518 case MSR_MTRRfix4K_E8000:
519 case MSR_MTRRfix4K_F0000:
520 case MSR_MTRRfix4K_F8000:
521 val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
522 MSR_MTRRfix4K_C0000 + 3];
523 break;
524 case MSR_MTRRdefType:
525 val = env->mtrr_deftype;
526 break;
527 case MSR_MTRRcap:
528 if (env->features[FEAT_1_EDX] & CPUID_MTRR) {
529 val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT |
530 MSR_MTRRcap_WC_SUPPORTED;
531 } else {
532 /* XXX: exception? */
533 val = 0;
535 break;
536 case MSR_MCG_CAP:
537 val = env->mcg_cap;
538 break;
539 case MSR_MCG_CTL:
540 if (env->mcg_cap & MCG_CTL_P) {
541 val = env->mcg_ctl;
542 } else {
543 val = 0;
545 break;
546 case MSR_MCG_STATUS:
547 val = env->mcg_status;
548 break;
549 case MSR_IA32_MISC_ENABLE:
550 val = env->msr_ia32_misc_enable;
551 break;
552 case MSR_IA32_BNDCFGS:
553 val = env->msr_bndcfgs;
554 break;
555 case MSR_IA32_UCODE_REV:
556 val = x86_cpu->ucode_rev;
557 break;
558 default:
559 if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
560 && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
561 (4 * env->mcg_cap & 0xff)) {
562 uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
563 val = env->mce_banks[offset];
564 break;
566 /* XXX: exception? */
567 val = 0;
568 break;
570 env->regs[R_EAX] = (uint32_t)(val);
571 env->regs[R_EDX] = (uint32_t)(val >> 32);
573 #endif
575 static void do_pause(X86CPU *cpu)
577 CPUState *cs = CPU(cpu);
579 /* Just let another CPU run. */
580 cs->exception_index = EXCP_INTERRUPT;
581 cpu_loop_exit(cs);
584 static void do_hlt(X86CPU *cpu)
586 CPUState *cs = CPU(cpu);
587 CPUX86State *env = &cpu->env;
589 env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
590 cs->halted = 1;
591 cs->exception_index = EXCP_HLT;
592 cpu_loop_exit(cs);
595 void helper_hlt(CPUX86State *env, int next_eip_addend)
597 X86CPU *cpu = env_archcpu(env);
599 cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC());
600 env->eip += next_eip_addend;
602 do_hlt(cpu);
605 void helper_monitor(CPUX86State *env, target_ulong ptr)
607 if ((uint32_t)env->regs[R_ECX] != 0) {
608 raise_exception_ra(env, EXCP0D_GPF, GETPC());
610 /* XXX: store address? */
611 cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0, GETPC());
614 void helper_mwait(CPUX86State *env, int next_eip_addend)
616 CPUState *cs = env_cpu(env);
617 X86CPU *cpu = env_archcpu(env);
619 if ((uint32_t)env->regs[R_ECX] != 0) {
620 raise_exception_ra(env, EXCP0D_GPF, GETPC());
622 cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0, GETPC());
623 env->eip += next_eip_addend;
625 /* XXX: not complete but not completely erroneous */
626 if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) {
627 do_pause(cpu);
628 } else {
629 do_hlt(cpu);
633 void helper_pause(CPUX86State *env, int next_eip_addend)
635 X86CPU *cpu = env_archcpu(env);
637 cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0, GETPC());
638 env->eip += next_eip_addend;
640 do_pause(cpu);
643 void helper_debug(CPUX86State *env)
645 CPUState *cs = env_cpu(env);
647 cs->exception_index = EXCP_DEBUG;
648 cpu_loop_exit(cs);
651 uint64_t helper_rdpkru(CPUX86State *env, uint32_t ecx)
653 if ((env->cr[4] & CR4_PKE_MASK) == 0) {
654 raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
656 if (ecx != 0) {
657 raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
660 return env->pkru;
663 void helper_wrpkru(CPUX86State *env, uint32_t ecx, uint64_t val)
665 CPUState *cs = env_cpu(env);
667 if ((env->cr[4] & CR4_PKE_MASK) == 0) {
668 raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
670 if (ecx != 0 || (val & 0xFFFFFFFF00000000ull)) {
671 raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
674 env->pkru = val;
675 tlb_flush(cs);