2 * i386 emulator main execution loop
4 * Copyright (c) 2003-2005 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 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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #define CPU_NO_GLOBAL_REGS
26 #if !defined(CONFIG_SOFTMMU)
37 #include <sys/ucontext.h>
40 #if defined(__sparc__) && !defined(HOST_SOLARIS)
41 // Work around ugly bugs in glibc that mangle global register contents
43 #define env cpu_single_env
46 int tb_invalidated_flag;
47 static unsigned long next_tb;
50 //#define DEBUG_SIGNAL
52 void cpu_loop_exit(void)
54 /* NOTE: the register at this point must be saved by hand because
55 longjmp restore them */
57 longjmp(env->jmp_env, 1);
60 #if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
64 /* exit the current TB from a signal handler. The host registers are
65 restored in a state compatible with the CPU emulator
67 void cpu_resume_from_signal(CPUState *env1, void *puc)
69 #if !defined(CONFIG_SOFTMMU)
70 struct ucontext *uc = puc;
75 /* XXX: restore cpu registers saved in host registers */
77 #if !defined(CONFIG_SOFTMMU)
79 /* XXX: use siglongjmp ? */
80 sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
83 longjmp(env->jmp_env, 1);
86 static TranslationBlock *tb_find_slow(target_ulong pc,
90 TranslationBlock *tb, **ptb1;
93 target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
98 tb_invalidated_flag = 0;
100 regs_to_env(); /* XXX: do it just before cpu_gen_code() */
102 /* find translated block using physical mappings */
103 phys_pc = get_phys_addr_code(env, pc);
104 phys_page1 = phys_pc & TARGET_PAGE_MASK;
106 h = tb_phys_hash_func(phys_pc);
107 ptb1 = &tb_phys_hash[h];
113 tb->page_addr[0] == phys_page1 &&
114 tb->cs_base == cs_base &&
115 tb->flags == flags) {
116 /* check next page if needed */
117 if (tb->page_addr[1] != -1) {
118 virt_page2 = (pc & TARGET_PAGE_MASK) +
120 phys_page2 = get_phys_addr_code(env, virt_page2);
121 if (tb->page_addr[1] == phys_page2)
127 ptb1 = &tb->phys_hash_next;
130 /* if no translated code available, then translate it now */
133 /* flush must be done */
135 /* cannot fail at this point */
137 /* don't forget to invalidate previous TB info */
138 tb_invalidated_flag = 1;
140 tc_ptr = code_gen_ptr;
142 tb->cs_base = cs_base;
144 cpu_gen_code(env, tb, &code_gen_size);
145 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
147 /* check next page if needed */
148 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
150 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
151 phys_page2 = get_phys_addr_code(env, virt_page2);
153 tb_link_phys(tb, phys_pc, phys_page2);
156 /* we add the TB in the virtual pc hash table */
157 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
158 spin_unlock(&tb_lock);
162 static inline TranslationBlock *tb_find_fast(void)
164 TranslationBlock *tb;
165 target_ulong cs_base, pc;
168 /* we record a subset of the CPU state. It will
169 always be the same before a given translated block
171 #if defined(TARGET_I386)
173 flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
174 flags |= env->intercept;
175 cs_base = env->segs[R_CS].base;
176 pc = cs_base + env->eip;
177 #elif defined(TARGET_ARM)
178 flags = env->thumb | (env->vfp.vec_len << 1)
179 | (env->vfp.vec_stride << 4);
180 if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
182 if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
184 flags |= (env->condexec_bits << 8);
187 #elif defined(TARGET_SPARC)
188 #ifdef TARGET_SPARC64
189 // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
190 flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
191 | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
193 // FPU enable . Supervisor
194 flags = (env->psref << 4) | env->psrs;
198 #elif defined(TARGET_PPC)
202 #elif defined(TARGET_MIPS)
203 flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
205 pc = env->PC[env->current_tc];
206 #elif defined(TARGET_M68K)
207 flags = (env->fpcr & M68K_FPCR_PREC) /* Bit 6 */
208 | (env->sr & SR_S) /* Bit 13 */
209 | ((env->macsr >> 4) & 0xf); /* Bits 0-3 */
212 #elif defined(TARGET_SH4)
216 #elif defined(TARGET_ALPHA)
220 #elif defined(TARGET_CRIS)
221 flags = env->pregs[PR_CCS] & U_FLAG;
226 #error unsupported CPU
228 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
229 if (__builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base ||
230 tb->flags != flags, 0)) {
231 tb = tb_find_slow(pc, cs_base, flags);
232 /* Note: we do it here to avoid a gcc bug on Mac OS X when
233 doing it in tb_find_slow */
234 if (tb_invalidated_flag) {
235 /* as some TB could have been invalidated because
236 of memory exceptions while generating the code, we
237 must recompute the hash index here */
244 /* main execution loop */
246 int cpu_exec(CPUState *env1)
248 #define DECLARE_HOST_REGS 1
249 #include "hostregs_helper.h"
250 #if defined(TARGET_SPARC)
251 #if defined(reg_REGWPTR)
252 uint32_t *saved_regwptr;
255 int ret, interrupt_request;
256 TranslationBlock *tb;
259 if (cpu_halted(env1) == EXCP_HALTED)
262 cpu_single_env = env1;
264 /* first we save global registers */
265 #define SAVE_HOST_REGS 1
266 #include "hostregs_helper.h"
270 #if defined(TARGET_I386)
271 /* put eflags in CPU temporary format */
272 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
273 DF = 1 - (2 * ((env->eflags >> 10) & 1));
274 CC_OP = CC_OP_EFLAGS;
275 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
276 #elif defined(TARGET_SPARC)
277 #if defined(reg_REGWPTR)
278 saved_regwptr = REGWPTR;
280 #elif defined(TARGET_M68K)
281 env->cc_op = CC_OP_FLAGS;
282 env->cc_dest = env->sr & 0xf;
283 env->cc_x = (env->sr >> 4) & 1;
284 #elif defined(TARGET_ALPHA)
285 #elif defined(TARGET_ARM)
286 #elif defined(TARGET_PPC)
287 #elif defined(TARGET_MIPS)
288 #elif defined(TARGET_SH4)
289 #elif defined(TARGET_CRIS)
292 #error unsupported target CPU
294 env->exception_index = -1;
296 /* prepare setjmp context for exception handling */
298 if (setjmp(env->jmp_env) == 0) {
299 env->current_tb = NULL;
300 /* if an exception is pending, we execute it here */
301 if (env->exception_index >= 0) {
302 if (env->exception_index >= EXCP_INTERRUPT) {
303 /* exit request from the cpu execution loop */
304 ret = env->exception_index;
306 } else if (env->user_mode_only) {
307 /* if user mode only, we simulate a fake exception
308 which will be handled outside the cpu execution
310 #if defined(TARGET_I386)
311 do_interrupt_user(env->exception_index,
312 env->exception_is_int,
314 env->exception_next_eip);
315 /* successfully delivered */
316 env->old_exception = -1;
318 ret = env->exception_index;
321 #if defined(TARGET_I386)
322 /* simulate a real cpu exception. On i386, it can
323 trigger new exceptions, but we do not handle
324 double or triple faults yet. */
325 do_interrupt(env->exception_index,
326 env->exception_is_int,
328 env->exception_next_eip, 0);
329 /* successfully delivered */
330 env->old_exception = -1;
331 #elif defined(TARGET_PPC)
333 #elif defined(TARGET_MIPS)
335 #elif defined(TARGET_SPARC)
336 do_interrupt(env->exception_index);
337 #elif defined(TARGET_ARM)
339 #elif defined(TARGET_SH4)
341 #elif defined(TARGET_ALPHA)
343 #elif defined(TARGET_CRIS)
345 #elif defined(TARGET_M68K)
349 env->exception_index = -1;
352 if (kqemu_is_ok(env) && env->interrupt_request == 0) {
354 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
355 ret = kqemu_cpu_exec(env);
356 /* put eflags in CPU temporary format */
357 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
358 DF = 1 - (2 * ((env->eflags >> 10) & 1));
359 CC_OP = CC_OP_EFLAGS;
360 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
363 longjmp(env->jmp_env, 1);
364 } else if (ret == 2) {
365 /* softmmu execution needed */
367 if (env->interrupt_request != 0) {
368 /* hardware interrupt will be executed just after */
370 /* otherwise, we restart */
371 longjmp(env->jmp_env, 1);
377 next_tb = 0; /* force lookup of first TB */
379 interrupt_request = env->interrupt_request;
380 if (__builtin_expect(interrupt_request, 0)
381 #if defined(TARGET_I386)
382 && env->hflags & HF_GIF_MASK
384 && likely(!(env->singlestep_enabled & SSTEP_NOIRQ))) {
385 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
386 env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
387 env->exception_index = EXCP_DEBUG;
390 #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
391 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
392 if (interrupt_request & CPU_INTERRUPT_HALT) {
393 env->interrupt_request &= ~CPU_INTERRUPT_HALT;
395 env->exception_index = EXCP_HLT;
399 #if defined(TARGET_I386)
400 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
401 !(env->hflags & HF_SMM_MASK)) {
402 svm_check_intercept(SVM_EXIT_SMI);
403 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
406 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
407 !(env->hflags & HF_NMI_MASK)) {
408 env->interrupt_request &= ~CPU_INTERRUPT_NMI;
409 env->hflags |= HF_NMI_MASK;
410 do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
412 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
413 (env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) &&
414 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
416 svm_check_intercept(SVM_EXIT_INTR);
417 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
418 intno = cpu_get_pic_interrupt(env);
419 if (loglevel & CPU_LOG_TB_IN_ASM) {
420 fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
422 do_interrupt(intno, 0, 0, 0, 1);
423 /* ensure that no TB jump will be modified as
424 the program flow was changed */
426 #if !defined(CONFIG_USER_ONLY)
427 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
428 (env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
430 /* FIXME: this should respect TPR */
431 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
432 svm_check_intercept(SVM_EXIT_VINTR);
433 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
434 if (loglevel & CPU_LOG_TB_IN_ASM)
435 fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
436 do_interrupt(intno, 0, 0, -1, 1);
437 stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
438 ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
442 #elif defined(TARGET_PPC)
444 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
448 if (interrupt_request & CPU_INTERRUPT_HARD) {
449 ppc_hw_interrupt(env);
450 if (env->pending_interrupts == 0)
451 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
454 #elif defined(TARGET_MIPS)
455 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
456 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
457 (env->CP0_Status & (1 << CP0St_IE)) &&
458 !(env->CP0_Status & (1 << CP0St_EXL)) &&
459 !(env->CP0_Status & (1 << CP0St_ERL)) &&
460 !(env->hflags & MIPS_HFLAG_DM)) {
462 env->exception_index = EXCP_EXT_INTERRUPT;
467 #elif defined(TARGET_SPARC)
468 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
470 int pil = env->interrupt_index & 15;
471 int type = env->interrupt_index & 0xf0;
473 if (((type == TT_EXTINT) &&
474 (pil == 15 || pil > env->psrpil)) ||
476 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
477 do_interrupt(env->interrupt_index);
478 env->interrupt_index = 0;
479 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
484 } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
485 //do_interrupt(0, 0, 0, 0, 0);
486 env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
488 #elif defined(TARGET_ARM)
489 if (interrupt_request & CPU_INTERRUPT_FIQ
490 && !(env->uncached_cpsr & CPSR_F)) {
491 env->exception_index = EXCP_FIQ;
495 /* ARMv7-M interrupt return works by loading a magic value
496 into the PC. On real hardware the load causes the
497 return to occur. The qemu implementation performs the
498 jump normally, then does the exception return when the
499 CPU tries to execute code at the magic address.
500 This will cause the magic PC value to be pushed to
501 the stack if an interrupt occured at the wrong time.
502 We avoid this by disabling interrupts when
503 pc contains a magic address. */
504 if (interrupt_request & CPU_INTERRUPT_HARD
505 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
506 || !(env->uncached_cpsr & CPSR_I))) {
507 env->exception_index = EXCP_IRQ;
511 #elif defined(TARGET_SH4)
512 if (interrupt_request & CPU_INTERRUPT_HARD) {
516 #elif defined(TARGET_ALPHA)
517 if (interrupt_request & CPU_INTERRUPT_HARD) {
521 #elif defined(TARGET_CRIS)
522 if (interrupt_request & CPU_INTERRUPT_HARD) {
526 #elif defined(TARGET_M68K)
527 if (interrupt_request & CPU_INTERRUPT_HARD
528 && ((env->sr & SR_I) >> SR_I_SHIFT)
529 < env->pending_level) {
530 /* Real hardware gets the interrupt vector via an
531 IACK cycle at this point. Current emulated
532 hardware doesn't rely on this, so we
533 provide/save the vector when the interrupt is
535 env->exception_index = env->pending_vector;
540 /* Don't use the cached interupt_request value,
541 do_interrupt may have updated the EXITTB flag. */
542 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
543 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
544 /* ensure that no TB jump will be modified as
545 the program flow was changed */
548 if (interrupt_request & CPU_INTERRUPT_EXIT) {
549 env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
550 env->exception_index = EXCP_INTERRUPT;
555 if ((loglevel & CPU_LOG_TB_CPU)) {
556 /* restore flags in standard format */
558 #if defined(TARGET_I386)
559 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
560 cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
561 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
562 #elif defined(TARGET_ARM)
563 cpu_dump_state(env, logfile, fprintf, 0);
564 #elif defined(TARGET_SPARC)
565 REGWPTR = env->regbase + (env->cwp * 16);
566 env->regwptr = REGWPTR;
567 cpu_dump_state(env, logfile, fprintf, 0);
568 #elif defined(TARGET_PPC)
569 cpu_dump_state(env, logfile, fprintf, 0);
570 #elif defined(TARGET_M68K)
571 cpu_m68k_flush_flags(env, env->cc_op);
572 env->cc_op = CC_OP_FLAGS;
573 env->sr = (env->sr & 0xffe0)
574 | env->cc_dest | (env->cc_x << 4);
575 cpu_dump_state(env, logfile, fprintf, 0);
576 #elif defined(TARGET_MIPS)
577 cpu_dump_state(env, logfile, fprintf, 0);
578 #elif defined(TARGET_SH4)
579 cpu_dump_state(env, logfile, fprintf, 0);
580 #elif defined(TARGET_ALPHA)
581 cpu_dump_state(env, logfile, fprintf, 0);
582 #elif defined(TARGET_CRIS)
583 cpu_dump_state(env, logfile, fprintf, 0);
585 #error unsupported target CPU
591 if ((loglevel & CPU_LOG_EXEC)) {
592 fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
593 (long)tb->tc_ptr, tb->pc,
594 lookup_symbol(tb->pc));
597 /* see if we can patch the calling TB. When the TB
598 spans two pages, we cannot safely do a direct
603 (env->kqemu_enabled != 2) &&
605 tb->page_addr[1] == -1) {
607 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
608 spin_unlock(&tb_lock);
612 env->current_tb = tb;
613 /* execute the generated code */
614 #if defined(__sparc__) && !defined(HOST_SOLARIS)
616 env = cpu_single_env;
617 #define env cpu_single_env
619 next_tb = tcg_qemu_tb_exec(tc_ptr);
620 env->current_tb = NULL;
621 /* reset soft MMU for next block (it can currently
622 only be set by a memory fault) */
623 #if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
624 if (env->hflags & HF_SOFTMMU_MASK) {
625 env->hflags &= ~HF_SOFTMMU_MASK;
626 /* do not allow linking to another block */
630 #if defined(USE_KQEMU)
631 #define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
632 if (kqemu_is_ok(env) &&
633 (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
644 #if defined(TARGET_I386)
645 /* restore flags in standard format */
646 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
647 #elif defined(TARGET_ARM)
648 /* XXX: Save/restore host fpu exception state?. */
649 #elif defined(TARGET_SPARC)
650 #if defined(reg_REGWPTR)
651 REGWPTR = saved_regwptr;
653 #elif defined(TARGET_PPC)
654 #elif defined(TARGET_M68K)
655 cpu_m68k_flush_flags(env, env->cc_op);
656 env->cc_op = CC_OP_FLAGS;
657 env->sr = (env->sr & 0xffe0)
658 | env->cc_dest | (env->cc_x << 4);
659 #elif defined(TARGET_MIPS)
660 #elif defined(TARGET_SH4)
661 #elif defined(TARGET_ALPHA)
662 #elif defined(TARGET_CRIS)
665 #error unsupported target CPU
668 /* restore global registers */
669 #include "hostregs_helper.h"
671 /* fail safe : never use cpu_single_env outside cpu_exec() */
672 cpu_single_env = NULL;
676 /* must only be called from the generated code as an exception can be
678 void tb_invalidate_page_range(target_ulong start, target_ulong end)
680 /* XXX: cannot enable it yet because it yields to MMU exception
681 where NIP != read address on PowerPC */
683 target_ulong phys_addr;
684 phys_addr = get_phys_addr_code(env, start);
685 tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
689 #if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
691 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
693 CPUX86State *saved_env;
697 if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
699 cpu_x86_load_seg_cache(env, seg_reg, selector,
700 (selector << 4), 0xffff, 0);
702 helper_load_seg(seg_reg, selector);
707 void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
709 CPUX86State *saved_env;
714 helper_fsave(ptr, data32);
719 void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
721 CPUX86State *saved_env;
726 helper_frstor(ptr, data32);
731 #endif /* TARGET_I386 */
733 #if !defined(CONFIG_SOFTMMU)
735 #if defined(TARGET_I386)
737 /* 'pc' is the host PC at which the exception was raised. 'address' is
738 the effective address of the memory exception. 'is_write' is 1 if a
739 write caused the exception and otherwise 0'. 'old_set' is the
740 signal set which should be restored */
741 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
742 int is_write, sigset_t *old_set,
745 TranslationBlock *tb;
749 env = cpu_single_env; /* XXX: find a correct solution for multithread */
750 #if defined(DEBUG_SIGNAL)
751 qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
752 pc, address, is_write, *(unsigned long *)old_set);
754 /* XXX: locking issue */
755 if (is_write && page_unprotect(h2g(address), pc, puc)) {
759 /* see if it is an MMU fault */
760 ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
762 return 0; /* not an MMU fault */
764 return 1; /* the MMU fault was handled without causing real CPU fault */
765 /* now we have a real cpu fault */
768 /* the PC is inside the translated code. It means that we have
769 a virtual CPU fault */
770 cpu_restore_state(tb, env, pc, puc);
774 printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
775 env->eip, env->cr[2], env->error_code);
777 /* we restore the process signal mask as the sigreturn should
778 do it (XXX: use sigsetjmp) */
779 sigprocmask(SIG_SETMASK, old_set, NULL);
780 raise_exception_err(env->exception_index, env->error_code);
782 /* activate soft MMU for this block */
783 env->hflags |= HF_SOFTMMU_MASK;
784 cpu_resume_from_signal(env, puc);
786 /* never comes here */
790 #elif defined(TARGET_ARM)
791 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
792 int is_write, sigset_t *old_set,
795 TranslationBlock *tb;
799 env = cpu_single_env; /* XXX: find a correct solution for multithread */
800 #if defined(DEBUG_SIGNAL)
801 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
802 pc, address, is_write, *(unsigned long *)old_set);
804 /* XXX: locking issue */
805 if (is_write && page_unprotect(h2g(address), pc, puc)) {
808 /* see if it is an MMU fault */
809 ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
811 return 0; /* not an MMU fault */
813 return 1; /* the MMU fault was handled without causing real CPU fault */
814 /* now we have a real cpu fault */
817 /* the PC is inside the translated code. It means that we have
818 a virtual CPU fault */
819 cpu_restore_state(tb, env, pc, puc);
821 /* we restore the process signal mask as the sigreturn should
822 do it (XXX: use sigsetjmp) */
823 sigprocmask(SIG_SETMASK, old_set, NULL);
825 /* never comes here */
828 #elif defined(TARGET_SPARC)
829 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
830 int is_write, sigset_t *old_set,
833 TranslationBlock *tb;
837 env = cpu_single_env; /* XXX: find a correct solution for multithread */
838 #if defined(DEBUG_SIGNAL)
839 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
840 pc, address, is_write, *(unsigned long *)old_set);
842 /* XXX: locking issue */
843 if (is_write && page_unprotect(h2g(address), pc, puc)) {
846 /* see if it is an MMU fault */
847 ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
849 return 0; /* not an MMU fault */
851 return 1; /* the MMU fault was handled without causing real CPU fault */
852 /* now we have a real cpu fault */
855 /* the PC is inside the translated code. It means that we have
856 a virtual CPU fault */
857 cpu_restore_state(tb, env, pc, puc);
859 /* we restore the process signal mask as the sigreturn should
860 do it (XXX: use sigsetjmp) */
861 sigprocmask(SIG_SETMASK, old_set, NULL);
863 /* never comes here */
866 #elif defined (TARGET_PPC)
867 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
868 int is_write, sigset_t *old_set,
871 TranslationBlock *tb;
875 env = cpu_single_env; /* XXX: find a correct solution for multithread */
876 #if defined(DEBUG_SIGNAL)
877 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
878 pc, address, is_write, *(unsigned long *)old_set);
880 /* XXX: locking issue */
881 if (is_write && page_unprotect(h2g(address), pc, puc)) {
885 /* see if it is an MMU fault */
886 ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
888 return 0; /* not an MMU fault */
890 return 1; /* the MMU fault was handled without causing real CPU fault */
892 /* now we have a real cpu fault */
895 /* the PC is inside the translated code. It means that we have
896 a virtual CPU fault */
897 cpu_restore_state(tb, env, pc, puc);
901 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
902 env->nip, env->error_code, tb);
904 /* we restore the process signal mask as the sigreturn should
905 do it (XXX: use sigsetjmp) */
906 sigprocmask(SIG_SETMASK, old_set, NULL);
907 do_raise_exception_err(env->exception_index, env->error_code);
909 /* activate soft MMU for this block */
910 cpu_resume_from_signal(env, puc);
912 /* never comes here */
916 #elif defined(TARGET_M68K)
917 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
918 int is_write, sigset_t *old_set,
921 TranslationBlock *tb;
925 env = cpu_single_env; /* XXX: find a correct solution for multithread */
926 #if defined(DEBUG_SIGNAL)
927 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
928 pc, address, is_write, *(unsigned long *)old_set);
930 /* XXX: locking issue */
931 if (is_write && page_unprotect(address, pc, puc)) {
934 /* see if it is an MMU fault */
935 ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
937 return 0; /* not an MMU fault */
939 return 1; /* the MMU fault was handled without causing real CPU fault */
940 /* now we have a real cpu fault */
943 /* the PC is inside the translated code. It means that we have
944 a virtual CPU fault */
945 cpu_restore_state(tb, env, pc, puc);
947 /* we restore the process signal mask as the sigreturn should
948 do it (XXX: use sigsetjmp) */
949 sigprocmask(SIG_SETMASK, old_set, NULL);
951 /* never comes here */
955 #elif defined (TARGET_MIPS)
956 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
957 int is_write, sigset_t *old_set,
960 TranslationBlock *tb;
964 env = cpu_single_env; /* XXX: find a correct solution for multithread */
965 #if defined(DEBUG_SIGNAL)
966 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
967 pc, address, is_write, *(unsigned long *)old_set);
969 /* XXX: locking issue */
970 if (is_write && page_unprotect(h2g(address), pc, puc)) {
974 /* see if it is an MMU fault */
975 ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
977 return 0; /* not an MMU fault */
979 return 1; /* the MMU fault was handled without causing real CPU fault */
981 /* now we have a real cpu fault */
984 /* the PC is inside the translated code. It means that we have
985 a virtual CPU fault */
986 cpu_restore_state(tb, env, pc, puc);
990 printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
991 env->PC, env->error_code, tb);
993 /* we restore the process signal mask as the sigreturn should
994 do it (XXX: use sigsetjmp) */
995 sigprocmask(SIG_SETMASK, old_set, NULL);
996 do_raise_exception_err(env->exception_index, env->error_code);
998 /* activate soft MMU for this block */
999 cpu_resume_from_signal(env, puc);
1001 /* never comes here */
1005 #elif defined (TARGET_SH4)
1006 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1007 int is_write, sigset_t *old_set,
1010 TranslationBlock *tb;
1014 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1015 #if defined(DEBUG_SIGNAL)
1016 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1017 pc, address, is_write, *(unsigned long *)old_set);
1019 /* XXX: locking issue */
1020 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1024 /* see if it is an MMU fault */
1025 ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1027 return 0; /* not an MMU fault */
1029 return 1; /* the MMU fault was handled without causing real CPU fault */
1031 /* now we have a real cpu fault */
1032 tb = tb_find_pc(pc);
1034 /* the PC is inside the translated code. It means that we have
1035 a virtual CPU fault */
1036 cpu_restore_state(tb, env, pc, puc);
1039 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1040 env->nip, env->error_code, tb);
1042 /* we restore the process signal mask as the sigreturn should
1043 do it (XXX: use sigsetjmp) */
1044 sigprocmask(SIG_SETMASK, old_set, NULL);
1046 /* never comes here */
1050 #elif defined (TARGET_ALPHA)
1051 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1052 int is_write, sigset_t *old_set,
1055 TranslationBlock *tb;
1059 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1060 #if defined(DEBUG_SIGNAL)
1061 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1062 pc, address, is_write, *(unsigned long *)old_set);
1064 /* XXX: locking issue */
1065 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1069 /* see if it is an MMU fault */
1070 ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1072 return 0; /* not an MMU fault */
1074 return 1; /* the MMU fault was handled without causing real CPU fault */
1076 /* now we have a real cpu fault */
1077 tb = tb_find_pc(pc);
1079 /* the PC is inside the translated code. It means that we have
1080 a virtual CPU fault */
1081 cpu_restore_state(tb, env, pc, puc);
1084 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1085 env->nip, env->error_code, tb);
1087 /* we restore the process signal mask as the sigreturn should
1088 do it (XXX: use sigsetjmp) */
1089 sigprocmask(SIG_SETMASK, old_set, NULL);
1091 /* never comes here */
1094 #elif defined (TARGET_CRIS)
1095 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1096 int is_write, sigset_t *old_set,
1099 TranslationBlock *tb;
1103 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1104 #if defined(DEBUG_SIGNAL)
1105 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1106 pc, address, is_write, *(unsigned long *)old_set);
1108 /* XXX: locking issue */
1109 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1113 /* see if it is an MMU fault */
1114 ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1116 return 0; /* not an MMU fault */
1118 return 1; /* the MMU fault was handled without causing real CPU fault */
1120 /* now we have a real cpu fault */
1121 tb = tb_find_pc(pc);
1123 /* the PC is inside the translated code. It means that we have
1124 a virtual CPU fault */
1125 cpu_restore_state(tb, env, pc, puc);
1127 /* we restore the process signal mask as the sigreturn should
1128 do it (XXX: use sigsetjmp) */
1129 sigprocmask(SIG_SETMASK, old_set, NULL);
1131 /* never comes here */
1136 #error unsupported target CPU
1139 #if defined(__i386__)
1141 #if defined(__APPLE__)
1142 # include <sys/ucontext.h>
1144 # define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1145 # define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
1146 # define ERROR_sig(context) ((context)->uc_mcontext->es.err)
1148 # define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
1149 # define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
1150 # define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
1153 int cpu_signal_handler(int host_signum, void *pinfo,
1156 siginfo_t *info = pinfo;
1157 struct ucontext *uc = puc;
1165 #define REG_TRAPNO TRAPNO
1168 trapno = TRAP_sig(uc);
1169 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1171 (ERROR_sig(uc) >> 1) & 1 : 0,
1172 &uc->uc_sigmask, puc);
1175 #elif defined(__x86_64__)
1177 int cpu_signal_handler(int host_signum, void *pinfo,
1180 siginfo_t *info = pinfo;
1181 struct ucontext *uc = puc;
1184 pc = uc->uc_mcontext.gregs[REG_RIP];
1185 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1186 uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
1187 (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1188 &uc->uc_sigmask, puc);
1191 #elif defined(__powerpc__)
1193 /***********************************************************************
1194 * signal context platform-specific definitions
1198 /* All Registers access - only for local access */
1199 # define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
1200 /* Gpr Registers access */
1201 # define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
1202 # define IAR_sig(context) REG_sig(nip, context) /* Program counter */
1203 # define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
1204 # define CTR_sig(context) REG_sig(ctr, context) /* Count register */
1205 # define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
1206 # define LR_sig(context) REG_sig(link, context) /* Link register */
1207 # define CR_sig(context) REG_sig(ccr, context) /* Condition register */
1208 /* Float Registers access */
1209 # define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1210 # define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1211 /* Exception Registers access */
1212 # define DAR_sig(context) REG_sig(dar, context)
1213 # define DSISR_sig(context) REG_sig(dsisr, context)
1214 # define TRAP_sig(context) REG_sig(trap, context)
1218 # include <sys/ucontext.h>
1219 typedef struct ucontext SIGCONTEXT;
1220 /* All Registers access - only for local access */
1221 # define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
1222 # define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
1223 # define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
1224 # define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
1225 /* Gpr Registers access */
1226 # define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
1227 # define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
1228 # define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
1229 # define CTR_sig(context) REG_sig(ctr, context)
1230 # define XER_sig(context) REG_sig(xer, context) /* Link register */
1231 # define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
1232 # define CR_sig(context) REG_sig(cr, context) /* Condition register */
1233 /* Float Registers access */
1234 # define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
1235 # define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
1236 /* Exception Registers access */
1237 # define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
1238 # define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
1239 # define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1240 #endif /* __APPLE__ */
1242 int cpu_signal_handler(int host_signum, void *pinfo,
1245 siginfo_t *info = pinfo;
1246 struct ucontext *uc = puc;
1254 if (DSISR_sig(uc) & 0x00800000)
1257 if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1260 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1261 is_write, &uc->uc_sigmask, puc);
1264 #elif defined(__alpha__)
1266 int cpu_signal_handler(int host_signum, void *pinfo,
1269 siginfo_t *info = pinfo;
1270 struct ucontext *uc = puc;
1271 uint32_t *pc = uc->uc_mcontext.sc_pc;
1272 uint32_t insn = *pc;
1275 /* XXX: need kernel patch to get write flag faster */
1276 switch (insn >> 26) {
1291 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1292 is_write, &uc->uc_sigmask, puc);
1294 #elif defined(__sparc__)
1296 int cpu_signal_handler(int host_signum, void *pinfo,
1299 siginfo_t *info = pinfo;
1302 #if !defined(__arch64__) || defined(HOST_SOLARIS)
1303 uint32_t *regs = (uint32_t *)(info + 1);
1304 void *sigmask = (regs + 20);
1305 /* XXX: is there a standard glibc define ? */
1306 unsigned long pc = regs[1];
1308 struct sigcontext *sc = puc;
1309 unsigned long pc = sc->sigc_regs.tpc;
1310 void *sigmask = (void *)sc->sigc_mask;
1313 /* XXX: need kernel patch to get write flag faster */
1315 insn = *(uint32_t *)pc;
1316 if ((insn >> 30) == 3) {
1317 switch((insn >> 19) & 0x3f) {
1329 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1330 is_write, sigmask, NULL);
1333 #elif defined(__arm__)
1335 int cpu_signal_handler(int host_signum, void *pinfo,
1338 siginfo_t *info = pinfo;
1339 struct ucontext *uc = puc;
1343 pc = uc->uc_mcontext.arm_pc;
1344 /* XXX: compute is_write */
1346 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1348 &uc->uc_sigmask, puc);
1351 #elif defined(__mc68000)
1353 int cpu_signal_handler(int host_signum, void *pinfo,
1356 siginfo_t *info = pinfo;
1357 struct ucontext *uc = puc;
1361 pc = uc->uc_mcontext.gregs[16];
1362 /* XXX: compute is_write */
1364 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1366 &uc->uc_sigmask, puc);
1369 #elif defined(__ia64)
1372 /* This ought to be in <bits/siginfo.h>... */
1373 # define __ISR_VALID 1
1376 int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1378 siginfo_t *info = pinfo;
1379 struct ucontext *uc = puc;
1383 ip = uc->uc_mcontext.sc_ip;
1384 switch (host_signum) {
1390 if (info->si_code && (info->si_segvflags & __ISR_VALID))
1391 /* ISR.W (write-access) is bit 33: */
1392 is_write = (info->si_isr >> 33) & 1;
1398 return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1400 &uc->uc_sigmask, puc);
1403 #elif defined(__s390__)
1405 int cpu_signal_handler(int host_signum, void *pinfo,
1408 siginfo_t *info = pinfo;
1409 struct ucontext *uc = puc;
1413 pc = uc->uc_mcontext.psw.addr;
1414 /* XXX: compute is_write */
1416 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1417 is_write, &uc->uc_sigmask, puc);
1420 #elif defined(__mips__)
1422 int cpu_signal_handler(int host_signum, void *pinfo,
1425 siginfo_t *info = pinfo;
1426 struct ucontext *uc = puc;
1427 greg_t pc = uc->uc_mcontext.pc;
1430 /* XXX: compute is_write */
1432 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1433 is_write, &uc->uc_sigmask, puc);
1436 #elif defined(__hppa__)
1438 int cpu_signal_handler(int host_signum, void *pinfo,
1441 struct siginfo *info = pinfo;
1442 struct ucontext *uc = puc;
1446 pc = uc->uc_mcontext.sc_iaoq[0];
1447 /* FIXME: compute is_write */
1449 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1451 &uc->uc_sigmask, puc);
1456 #error host CPU specific signal handler needed
1460 #endif /* !defined(CONFIG_SOFTMMU) */