]>
git.proxmox.com Git - qemu.git/blob - cpu-exec.c
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 int tb_invalidated_flag
;
41 static unsigned long next_tb
;
44 //#define DEBUG_SIGNAL
46 #define SAVE_GLOBALS()
47 #define RESTORE_GLOBALS()
49 #if defined(__sparc__) && !defined(HOST_SOLARIS)
51 #if defined(__GLIBC__) && ((__GLIBC__ < 2) || \
52 ((__GLIBC__ == 2) && (__GLIBC_MINOR__ <= 90)))
53 // Work around ugly bugs in glibc that mangle global register contents
55 static volatile void *saved_env
;
57 #define SAVE_GLOBALS() do { \
61 #undef RESTORE_GLOBALS
62 #define RESTORE_GLOBALS() do { \
63 env = (void *)saved_env; \
66 static int sparc_setjmp(jmp_buf buf
)
76 #define setjmp(jmp_buf) sparc_setjmp(jmp_buf)
78 static void sparc_longjmp(jmp_buf buf
, int val
)
83 #define longjmp(jmp_buf, val) sparc_longjmp(jmp_buf, val)
87 void cpu_loop_exit(void)
89 /* NOTE: the register at this point must be saved by hand because
90 longjmp restore them */
92 longjmp(env
->jmp_env
, 1);
95 #if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
99 /* exit the current TB from a signal handler. The host registers are
100 restored in a state compatible with the CPU emulator
102 void cpu_resume_from_signal(CPUState
*env1
, void *puc
)
104 #if !defined(CONFIG_SOFTMMU)
105 struct ucontext
*uc
= puc
;
110 /* XXX: restore cpu registers saved in host registers */
112 #if !defined(CONFIG_SOFTMMU)
114 /* XXX: use siglongjmp ? */
115 sigprocmask(SIG_SETMASK
, &uc
->uc_sigmask
, NULL
);
118 longjmp(env
->jmp_env
, 1);
121 static TranslationBlock
*tb_find_slow(target_ulong pc
,
122 target_ulong cs_base
,
125 TranslationBlock
*tb
, **ptb1
;
128 target_ulong phys_pc
, phys_page1
, phys_page2
, virt_page2
;
133 tb_invalidated_flag
= 0;
135 regs_to_env(); /* XXX: do it just before cpu_gen_code() */
137 /* find translated block using physical mappings */
138 phys_pc
= get_phys_addr_code(env
, pc
);
139 phys_page1
= phys_pc
& TARGET_PAGE_MASK
;
141 h
= tb_phys_hash_func(phys_pc
);
142 ptb1
= &tb_phys_hash
[h
];
148 tb
->page_addr
[0] == phys_page1
&&
149 tb
->cs_base
== cs_base
&&
150 tb
->flags
== flags
) {
151 /* check next page if needed */
152 if (tb
->page_addr
[1] != -1) {
153 virt_page2
= (pc
& TARGET_PAGE_MASK
) +
155 phys_page2
= get_phys_addr_code(env
, virt_page2
);
156 if (tb
->page_addr
[1] == phys_page2
)
162 ptb1
= &tb
->phys_hash_next
;
165 /* if no translated code available, then translate it now */
168 /* flush must be done */
170 /* cannot fail at this point */
172 /* don't forget to invalidate previous TB info */
173 tb_invalidated_flag
= 1;
175 tc_ptr
= code_gen_ptr
;
177 tb
->cs_base
= cs_base
;
180 cpu_gen_code(env
, tb
, &code_gen_size
);
182 code_gen_ptr
= (void *)(((unsigned long)code_gen_ptr
+ code_gen_size
+ CODE_GEN_ALIGN
- 1) & ~(CODE_GEN_ALIGN
- 1));
184 /* check next page if needed */
185 virt_page2
= (pc
+ tb
->size
- 1) & TARGET_PAGE_MASK
;
187 if ((pc
& TARGET_PAGE_MASK
) != virt_page2
) {
188 phys_page2
= get_phys_addr_code(env
, virt_page2
);
190 tb_link_phys(tb
, phys_pc
, phys_page2
);
193 /* we add the TB in the virtual pc hash table */
194 env
->tb_jmp_cache
[tb_jmp_cache_hash_func(pc
)] = tb
;
195 spin_unlock(&tb_lock
);
199 static inline TranslationBlock
*tb_find_fast(void)
201 TranslationBlock
*tb
;
202 target_ulong cs_base
, pc
;
205 /* we record a subset of the CPU state. It will
206 always be the same before a given translated block
208 #if defined(TARGET_I386)
210 flags
|= (env
->eflags
& (IOPL_MASK
| TF_MASK
| VM_MASK
));
211 flags
|= env
->intercept
;
212 cs_base
= env
->segs
[R_CS
].base
;
213 pc
= cs_base
+ env
->eip
;
214 #elif defined(TARGET_ARM)
215 flags
= env
->thumb
| (env
->vfp
.vec_len
<< 1)
216 | (env
->vfp
.vec_stride
<< 4);
217 if ((env
->uncached_cpsr
& CPSR_M
) != ARM_CPU_MODE_USR
)
219 if (env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30))
221 flags
|= (env
->condexec_bits
<< 8);
224 #elif defined(TARGET_SPARC)
225 #ifdef TARGET_SPARC64
226 // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
227 flags
= (((env
->pstate
& PS_PEF
) >> 1) | ((env
->fprs
& FPRS_FEF
) << 2))
228 | (env
->pstate
& PS_PRIV
) | ((env
->lsu
& (DMMU_E
| IMMU_E
)) >> 2);
230 // FPU enable . Supervisor
231 flags
= (env
->psref
<< 4) | env
->psrs
;
235 #elif defined(TARGET_PPC)
239 #elif defined(TARGET_MIPS)
240 flags
= env
->hflags
& (MIPS_HFLAG_TMASK
| MIPS_HFLAG_BMASK
);
242 pc
= env
->PC
[env
->current_tc
];
243 #elif defined(TARGET_M68K)
244 flags
= (env
->fpcr
& M68K_FPCR_PREC
) /* Bit 6 */
245 | (env
->sr
& SR_S
) /* Bit 13 */
246 | ((env
->macsr
>> 4) & 0xf); /* Bits 0-3 */
249 #elif defined(TARGET_SH4)
253 #elif defined(TARGET_ALPHA)
257 #elif defined(TARGET_CRIS)
258 flags
= env
->pregs
[PR_CCS
] & U_FLAG
;
263 #error unsupported CPU
265 tb
= env
->tb_jmp_cache
[tb_jmp_cache_hash_func(pc
)];
266 if (__builtin_expect(!tb
|| tb
->pc
!= pc
|| tb
->cs_base
!= cs_base
||
267 tb
->flags
!= flags
, 0)) {
268 tb
= tb_find_slow(pc
, cs_base
, flags
);
269 /* Note: we do it here to avoid a gcc bug on Mac OS X when
270 doing it in tb_find_slow */
271 if (tb_invalidated_flag
) {
272 /* as some TB could have been invalidated because
273 of memory exceptions while generating the code, we
274 must recompute the hash index here */
281 /* main execution loop */
283 int cpu_exec(CPUState
*env1
)
285 #define DECLARE_HOST_REGS 1
286 #include "hostregs_helper.h"
287 #if defined(TARGET_SPARC)
288 #if defined(reg_REGWPTR)
289 uint32_t *saved_regwptr
;
292 int ret
, interrupt_request
;
293 TranslationBlock
*tb
;
296 if (cpu_halted(env1
) == EXCP_HALTED
)
299 cpu_single_env
= env1
;
301 /* first we save global registers */
302 #define SAVE_HOST_REGS 1
303 #include "hostregs_helper.h"
308 #if defined(TARGET_I386)
309 /* put eflags in CPU temporary format */
310 CC_SRC
= env
->eflags
& (CC_O
| CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
);
311 DF
= 1 - (2 * ((env
->eflags
>> 10) & 1));
312 CC_OP
= CC_OP_EFLAGS
;
313 env
->eflags
&= ~(DF_MASK
| CC_O
| CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
);
314 #elif defined(TARGET_SPARC)
315 #if defined(reg_REGWPTR)
316 saved_regwptr
= REGWPTR
;
318 #elif defined(TARGET_M68K)
319 env
->cc_op
= CC_OP_FLAGS
;
320 env
->cc_dest
= env
->sr
& 0xf;
321 env
->cc_x
= (env
->sr
>> 4) & 1;
322 #elif defined(TARGET_ALPHA)
323 #elif defined(TARGET_ARM)
324 #elif defined(TARGET_PPC)
325 #elif defined(TARGET_MIPS)
326 #elif defined(TARGET_SH4)
327 #elif defined(TARGET_CRIS)
330 #error unsupported target CPU
332 env
->exception_index
= -1;
334 /* prepare setjmp context for exception handling */
336 if (setjmp(env
->jmp_env
) == 0) {
337 env
->current_tb
= NULL
;
338 /* if an exception is pending, we execute it here */
339 if (env
->exception_index
>= 0) {
340 if (env
->exception_index
>= EXCP_INTERRUPT
) {
341 /* exit request from the cpu execution loop */
342 ret
= env
->exception_index
;
344 } else if (env
->user_mode_only
) {
345 /* if user mode only, we simulate a fake exception
346 which will be handled outside the cpu execution
348 #if defined(TARGET_I386)
349 do_interrupt_user(env
->exception_index
,
350 env
->exception_is_int
,
352 env
->exception_next_eip
);
353 /* successfully delivered */
354 env
->old_exception
= -1;
356 ret
= env
->exception_index
;
359 #if defined(TARGET_I386)
360 /* simulate a real cpu exception. On i386, it can
361 trigger new exceptions, but we do not handle
362 double or triple faults yet. */
363 do_interrupt(env
->exception_index
,
364 env
->exception_is_int
,
366 env
->exception_next_eip
, 0);
367 /* successfully delivered */
368 env
->old_exception
= -1;
369 #elif defined(TARGET_PPC)
371 #elif defined(TARGET_MIPS)
373 #elif defined(TARGET_SPARC)
374 do_interrupt(env
->exception_index
);
375 #elif defined(TARGET_ARM)
377 #elif defined(TARGET_SH4)
379 #elif defined(TARGET_ALPHA)
381 #elif defined(TARGET_CRIS)
383 #elif defined(TARGET_M68K)
387 env
->exception_index
= -1;
390 if (kqemu_is_ok(env
) && env
->interrupt_request
== 0) {
392 env
->eflags
= env
->eflags
| cc_table
[CC_OP
].compute_all() | (DF
& DF_MASK
);
393 ret
= kqemu_cpu_exec(env
);
394 /* put eflags in CPU temporary format */
395 CC_SRC
= env
->eflags
& (CC_O
| CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
);
396 DF
= 1 - (2 * ((env
->eflags
>> 10) & 1));
397 CC_OP
= CC_OP_EFLAGS
;
398 env
->eflags
&= ~(DF_MASK
| CC_O
| CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
);
401 longjmp(env
->jmp_env
, 1);
402 } else if (ret
== 2) {
403 /* softmmu execution needed */
405 if (env
->interrupt_request
!= 0) {
406 /* hardware interrupt will be executed just after */
408 /* otherwise, we restart */
409 longjmp(env
->jmp_env
, 1);
415 next_tb
= 0; /* force lookup of first TB */
418 interrupt_request
= env
->interrupt_request
;
419 if (__builtin_expect(interrupt_request
, 0)
420 #if defined(TARGET_I386)
421 && env
->hflags
& HF_GIF_MASK
423 && likely(!(env
->singlestep_enabled
& SSTEP_NOIRQ
))) {
424 if (interrupt_request
& CPU_INTERRUPT_DEBUG
) {
425 env
->interrupt_request
&= ~CPU_INTERRUPT_DEBUG
;
426 env
->exception_index
= EXCP_DEBUG
;
429 #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
430 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
431 if (interrupt_request
& CPU_INTERRUPT_HALT
) {
432 env
->interrupt_request
&= ~CPU_INTERRUPT_HALT
;
434 env
->exception_index
= EXCP_HLT
;
438 #if defined(TARGET_I386)
439 if ((interrupt_request
& CPU_INTERRUPT_SMI
) &&
440 !(env
->hflags
& HF_SMM_MASK
)) {
441 svm_check_intercept(SVM_EXIT_SMI
);
442 env
->interrupt_request
&= ~CPU_INTERRUPT_SMI
;
445 } else if ((interrupt_request
& CPU_INTERRUPT_NMI
) &&
446 !(env
->hflags
& HF_NMI_MASK
)) {
447 env
->interrupt_request
&= ~CPU_INTERRUPT_NMI
;
448 env
->hflags
|= HF_NMI_MASK
;
449 do_interrupt(EXCP02_NMI
, 0, 0, 0, 1);
451 } else if ((interrupt_request
& CPU_INTERRUPT_HARD
) &&
452 (env
->eflags
& IF_MASK
|| env
->hflags
& HF_HIF_MASK
) &&
453 !(env
->hflags
& HF_INHIBIT_IRQ_MASK
)) {
455 svm_check_intercept(SVM_EXIT_INTR
);
456 env
->interrupt_request
&= ~(CPU_INTERRUPT_HARD
| CPU_INTERRUPT_VIRQ
);
457 intno
= cpu_get_pic_interrupt(env
);
458 if (loglevel
& CPU_LOG_TB_IN_ASM
) {
459 fprintf(logfile
, "Servicing hardware INT=0x%02x\n", intno
);
461 do_interrupt(intno
, 0, 0, 0, 1);
462 /* ensure that no TB jump will be modified as
463 the program flow was changed */
465 #if !defined(CONFIG_USER_ONLY)
466 } else if ((interrupt_request
& CPU_INTERRUPT_VIRQ
) &&
467 (env
->eflags
& IF_MASK
) && !(env
->hflags
& HF_INHIBIT_IRQ_MASK
)) {
469 /* FIXME: this should respect TPR */
470 env
->interrupt_request
&= ~CPU_INTERRUPT_VIRQ
;
471 svm_check_intercept(SVM_EXIT_VINTR
);
472 intno
= ldl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.int_vector
));
473 if (loglevel
& CPU_LOG_TB_IN_ASM
)
474 fprintf(logfile
, "Servicing virtual hardware INT=0x%02x\n", intno
);
475 do_interrupt(intno
, 0, 0, -1, 1);
476 stl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.int_ctl
),
477 ldl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.int_ctl
)) & ~V_IRQ_MASK
);
481 #elif defined(TARGET_PPC)
483 if ((interrupt_request
& CPU_INTERRUPT_RESET
)) {
487 if (interrupt_request
& CPU_INTERRUPT_HARD
) {
488 ppc_hw_interrupt(env
);
489 if (env
->pending_interrupts
== 0)
490 env
->interrupt_request
&= ~CPU_INTERRUPT_HARD
;
493 #elif defined(TARGET_MIPS)
494 if ((interrupt_request
& CPU_INTERRUPT_HARD
) &&
495 (env
->CP0_Status
& env
->CP0_Cause
& CP0Ca_IP_mask
) &&
496 (env
->CP0_Status
& (1 << CP0St_IE
)) &&
497 !(env
->CP0_Status
& (1 << CP0St_EXL
)) &&
498 !(env
->CP0_Status
& (1 << CP0St_ERL
)) &&
499 !(env
->hflags
& MIPS_HFLAG_DM
)) {
501 env
->exception_index
= EXCP_EXT_INTERRUPT
;
506 #elif defined(TARGET_SPARC)
507 if ((interrupt_request
& CPU_INTERRUPT_HARD
) &&
509 int pil
= env
->interrupt_index
& 15;
510 int type
= env
->interrupt_index
& 0xf0;
512 if (((type
== TT_EXTINT
) &&
513 (pil
== 15 || pil
> env
->psrpil
)) ||
515 env
->interrupt_request
&= ~CPU_INTERRUPT_HARD
;
516 do_interrupt(env
->interrupt_index
);
517 env
->interrupt_index
= 0;
518 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
523 } else if (interrupt_request
& CPU_INTERRUPT_TIMER
) {
524 //do_interrupt(0, 0, 0, 0, 0);
525 env
->interrupt_request
&= ~CPU_INTERRUPT_TIMER
;
527 #elif defined(TARGET_ARM)
528 if (interrupt_request
& CPU_INTERRUPT_FIQ
529 && !(env
->uncached_cpsr
& CPSR_F
)) {
530 env
->exception_index
= EXCP_FIQ
;
534 /* ARMv7-M interrupt return works by loading a magic value
535 into the PC. On real hardware the load causes the
536 return to occur. The qemu implementation performs the
537 jump normally, then does the exception return when the
538 CPU tries to execute code at the magic address.
539 This will cause the magic PC value to be pushed to
540 the stack if an interrupt occured at the wrong time.
541 We avoid this by disabling interrupts when
542 pc contains a magic address. */
543 if (interrupt_request
& CPU_INTERRUPT_HARD
544 && ((IS_M(env
) && env
->regs
[15] < 0xfffffff0)
545 || !(env
->uncached_cpsr
& CPSR_I
))) {
546 env
->exception_index
= EXCP_IRQ
;
550 #elif defined(TARGET_SH4)
551 if (interrupt_request
& CPU_INTERRUPT_HARD
) {
555 #elif defined(TARGET_ALPHA)
556 if (interrupt_request
& CPU_INTERRUPT_HARD
) {
560 #elif defined(TARGET_CRIS)
561 if (interrupt_request
& CPU_INTERRUPT_HARD
) {
565 #elif defined(TARGET_M68K)
566 if (interrupt_request
& CPU_INTERRUPT_HARD
567 && ((env
->sr
& SR_I
) >> SR_I_SHIFT
)
568 < env
->pending_level
) {
569 /* Real hardware gets the interrupt vector via an
570 IACK cycle at this point. Current emulated
571 hardware doesn't rely on this, so we
572 provide/save the vector when the interrupt is
574 env
->exception_index
= env
->pending_vector
;
579 /* Don't use the cached interupt_request value,
580 do_interrupt may have updated the EXITTB flag. */
581 if (env
->interrupt_request
& CPU_INTERRUPT_EXITTB
) {
582 env
->interrupt_request
&= ~CPU_INTERRUPT_EXITTB
;
583 /* ensure that no TB jump will be modified as
584 the program flow was changed */
587 if (interrupt_request
& CPU_INTERRUPT_EXIT
) {
588 env
->interrupt_request
&= ~CPU_INTERRUPT_EXIT
;
589 env
->exception_index
= EXCP_INTERRUPT
;
594 if ((loglevel
& CPU_LOG_TB_CPU
)) {
595 /* restore flags in standard format */
597 #if defined(TARGET_I386)
598 env
->eflags
= env
->eflags
| cc_table
[CC_OP
].compute_all() | (DF
& DF_MASK
);
599 cpu_dump_state(env
, logfile
, fprintf
, X86_DUMP_CCOP
);
600 env
->eflags
&= ~(DF_MASK
| CC_O
| CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
);
601 #elif defined(TARGET_ARM)
602 cpu_dump_state(env
, logfile
, fprintf
, 0);
603 #elif defined(TARGET_SPARC)
604 REGWPTR
= env
->regbase
+ (env
->cwp
* 16);
605 env
->regwptr
= REGWPTR
;
606 cpu_dump_state(env
, logfile
, fprintf
, 0);
607 #elif defined(TARGET_PPC)
608 cpu_dump_state(env
, logfile
, fprintf
, 0);
609 #elif defined(TARGET_M68K)
610 cpu_m68k_flush_flags(env
, env
->cc_op
);
611 env
->cc_op
= CC_OP_FLAGS
;
612 env
->sr
= (env
->sr
& 0xffe0)
613 | env
->cc_dest
| (env
->cc_x
<< 4);
614 cpu_dump_state(env
, logfile
, fprintf
, 0);
615 #elif defined(TARGET_MIPS)
616 cpu_dump_state(env
, logfile
, fprintf
, 0);
617 #elif defined(TARGET_SH4)
618 cpu_dump_state(env
, logfile
, fprintf
, 0);
619 #elif defined(TARGET_ALPHA)
620 cpu_dump_state(env
, logfile
, fprintf
, 0);
621 #elif defined(TARGET_CRIS)
622 cpu_dump_state(env
, logfile
, fprintf
, 0);
624 #error unsupported target CPU
630 if ((loglevel
& CPU_LOG_EXEC
)) {
631 fprintf(logfile
, "Trace 0x%08lx [" TARGET_FMT_lx
"] %s\n",
632 (long)tb
->tc_ptr
, tb
->pc
,
633 lookup_symbol(tb
->pc
));
637 /* see if we can patch the calling TB. When the TB
638 spans two pages, we cannot safely do a direct
643 (env
->kqemu_enabled
!= 2) &&
645 tb
->page_addr
[1] == -1) {
647 tb_add_jump((TranslationBlock
*)(next_tb
& ~3), next_tb
& 3, tb
);
648 spin_unlock(&tb_lock
);
652 env
->current_tb
= tb
;
653 /* execute the generated code */
654 next_tb
= tcg_qemu_tb_exec(tc_ptr
);
655 env
->current_tb
= NULL
;
656 /* reset soft MMU for next block (it can currently
657 only be set by a memory fault) */
658 #if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
659 if (env
->hflags
& HF_SOFTMMU_MASK
) {
660 env
->hflags
&= ~HF_SOFTMMU_MASK
;
661 /* do not allow linking to another block */
665 #if defined(USE_KQEMU)
666 #define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
667 if (kqemu_is_ok(env
) &&
668 (cpu_get_time_fast() - env
->last_io_time
) >= MIN_CYCLE_BEFORE_SWITCH
) {
679 #if defined(TARGET_I386)
680 /* restore flags in standard format */
681 env
->eflags
= env
->eflags
| cc_table
[CC_OP
].compute_all() | (DF
& DF_MASK
);
682 #elif defined(TARGET_ARM)
683 /* XXX: Save/restore host fpu exception state?. */
684 #elif defined(TARGET_SPARC)
685 #if defined(reg_REGWPTR)
686 REGWPTR
= saved_regwptr
;
688 #elif defined(TARGET_PPC)
689 #elif defined(TARGET_M68K)
690 cpu_m68k_flush_flags(env
, env
->cc_op
);
691 env
->cc_op
= CC_OP_FLAGS
;
692 env
->sr
= (env
->sr
& 0xffe0)
693 | env
->cc_dest
| (env
->cc_x
<< 4);
694 #elif defined(TARGET_MIPS)
695 #elif defined(TARGET_SH4)
696 #elif defined(TARGET_ALPHA)
697 #elif defined(TARGET_CRIS)
700 #error unsupported target CPU
703 /* restore global registers */
705 #include "hostregs_helper.h"
707 /* fail safe : never use cpu_single_env outside cpu_exec() */
708 cpu_single_env
= NULL
;
712 /* must only be called from the generated code as an exception can be
714 void tb_invalidate_page_range(target_ulong start
, target_ulong end
)
716 /* XXX: cannot enable it yet because it yields to MMU exception
717 where NIP != read address on PowerPC */
719 target_ulong phys_addr
;
720 phys_addr
= get_phys_addr_code(env
, start
);
721 tb_invalidate_phys_page_range(phys_addr
, phys_addr
+ end
- start
, 0);
725 #if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
727 void cpu_x86_load_seg(CPUX86State
*s
, int seg_reg
, int selector
)
729 CPUX86State
*saved_env
;
733 if (!(env
->cr
[0] & CR0_PE_MASK
) || (env
->eflags
& VM_MASK
)) {
735 cpu_x86_load_seg_cache(env
, seg_reg
, selector
,
736 (selector
<< 4), 0xffff, 0);
738 helper_load_seg(seg_reg
, selector
);
743 void cpu_x86_fsave(CPUX86State
*s
, target_ulong ptr
, int data32
)
745 CPUX86State
*saved_env
;
750 helper_fsave(ptr
, data32
);
755 void cpu_x86_frstor(CPUX86State
*s
, target_ulong ptr
, int data32
)
757 CPUX86State
*saved_env
;
762 helper_frstor(ptr
, data32
);
767 #endif /* TARGET_I386 */
769 #if !defined(CONFIG_SOFTMMU)
771 #if defined(TARGET_I386)
773 /* 'pc' is the host PC at which the exception was raised. 'address' is
774 the effective address of the memory exception. 'is_write' is 1 if a
775 write caused the exception and otherwise 0'. 'old_set' is the
776 signal set which should be restored */
777 static inline int handle_cpu_signal(unsigned long pc
, unsigned long address
,
778 int is_write
, sigset_t
*old_set
,
781 TranslationBlock
*tb
;
785 env
= cpu_single_env
; /* XXX: find a correct solution for multithread */
786 #if defined(DEBUG_SIGNAL)
787 qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
788 pc
, address
, is_write
, *(unsigned long *)old_set
);
790 /* XXX: locking issue */
791 if (is_write
&& page_unprotect(h2g(address
), pc
, puc
)) {
795 /* see if it is an MMU fault */
796 ret
= cpu_x86_handle_mmu_fault(env
, address
, is_write
, MMU_USER_IDX
, 0);
798 return 0; /* not an MMU fault */
800 return 1; /* the MMU fault was handled without causing real CPU fault */
801 /* now we have a real cpu fault */
804 /* the PC is inside the translated code. It means that we have
805 a virtual CPU fault */
806 cpu_restore_state(tb
, env
, pc
, puc
);
810 printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
811 env
->eip
, env
->cr
[2], env
->error_code
);
813 /* we restore the process signal mask as the sigreturn should
814 do it (XXX: use sigsetjmp) */
815 sigprocmask(SIG_SETMASK
, old_set
, NULL
);
816 raise_exception_err(env
->exception_index
, env
->error_code
);
818 /* activate soft MMU for this block */
819 env
->hflags
|= HF_SOFTMMU_MASK
;
820 cpu_resume_from_signal(env
, puc
);
822 /* never comes here */
826 #elif defined(TARGET_ARM)
827 static inline int handle_cpu_signal(unsigned long pc
, unsigned long address
,
828 int is_write
, sigset_t
*old_set
,
831 TranslationBlock
*tb
;
835 env
= cpu_single_env
; /* XXX: find a correct solution for multithread */
836 #if defined(DEBUG_SIGNAL)
837 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
838 pc
, address
, is_write
, *(unsigned long *)old_set
);
840 /* XXX: locking issue */
841 if (is_write
&& page_unprotect(h2g(address
), pc
, puc
)) {
844 /* see if it is an MMU fault */
845 ret
= cpu_arm_handle_mmu_fault(env
, address
, is_write
, MMU_USER_IDX
, 0);
847 return 0; /* not an MMU fault */
849 return 1; /* the MMU fault was handled without causing real CPU fault */
850 /* now we have a real cpu fault */
853 /* the PC is inside the translated code. It means that we have
854 a virtual CPU fault */
855 cpu_restore_state(tb
, env
, pc
, puc
);
857 /* we restore the process signal mask as the sigreturn should
858 do it (XXX: use sigsetjmp) */
859 sigprocmask(SIG_SETMASK
, old_set
, NULL
);
861 /* never comes here */
864 #elif defined(TARGET_SPARC)
865 static inline int handle_cpu_signal(unsigned long pc
, unsigned long address
,
866 int is_write
, sigset_t
*old_set
,
869 TranslationBlock
*tb
;
873 env
= cpu_single_env
; /* XXX: find a correct solution for multithread */
874 #if defined(DEBUG_SIGNAL)
875 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
876 pc
, address
, is_write
, *(unsigned long *)old_set
);
878 /* XXX: locking issue */
879 if (is_write
&& page_unprotect(h2g(address
), pc
, puc
)) {
882 /* see if it is an MMU fault */
883 ret
= cpu_sparc_handle_mmu_fault(env
, address
, is_write
, MMU_USER_IDX
, 0);
885 return 0; /* not an MMU fault */
887 return 1; /* the MMU fault was handled without causing real CPU fault */
888 /* now we have a real cpu fault */
891 /* the PC is inside the translated code. It means that we have
892 a virtual CPU fault */
893 cpu_restore_state(tb
, env
, pc
, puc
);
895 /* we restore the process signal mask as the sigreturn should
896 do it (XXX: use sigsetjmp) */
897 sigprocmask(SIG_SETMASK
, old_set
, NULL
);
899 /* never comes here */
902 #elif defined (TARGET_PPC)
903 static inline int handle_cpu_signal(unsigned long pc
, unsigned long address
,
904 int is_write
, sigset_t
*old_set
,
907 TranslationBlock
*tb
;
911 env
= cpu_single_env
; /* XXX: find a correct solution for multithread */
912 #if defined(DEBUG_SIGNAL)
913 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
914 pc
, address
, is_write
, *(unsigned long *)old_set
);
916 /* XXX: locking issue */
917 if (is_write
&& page_unprotect(h2g(address
), pc
, puc
)) {
921 /* see if it is an MMU fault */
922 ret
= cpu_ppc_handle_mmu_fault(env
, address
, is_write
, MMU_USER_IDX
, 0);
924 return 0; /* not an MMU fault */
926 return 1; /* the MMU fault was handled without causing real CPU fault */
928 /* now we have a real cpu fault */
931 /* the PC is inside the translated code. It means that we have
932 a virtual CPU fault */
933 cpu_restore_state(tb
, env
, pc
, puc
);
937 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
938 env
->nip
, env
->error_code
, tb
);
940 /* we restore the process signal mask as the sigreturn should
941 do it (XXX: use sigsetjmp) */
942 sigprocmask(SIG_SETMASK
, old_set
, NULL
);
943 do_raise_exception_err(env
->exception_index
, env
->error_code
);
945 /* activate soft MMU for this block */
946 cpu_resume_from_signal(env
, puc
);
948 /* never comes here */
952 #elif defined(TARGET_M68K)
953 static inline int handle_cpu_signal(unsigned long pc
, unsigned long address
,
954 int is_write
, sigset_t
*old_set
,
957 TranslationBlock
*tb
;
961 env
= cpu_single_env
; /* XXX: find a correct solution for multithread */
962 #if defined(DEBUG_SIGNAL)
963 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
964 pc
, address
, is_write
, *(unsigned long *)old_set
);
966 /* XXX: locking issue */
967 if (is_write
&& page_unprotect(address
, pc
, puc
)) {
970 /* see if it is an MMU fault */
971 ret
= cpu_m68k_handle_mmu_fault(env
, address
, is_write
, MMU_USER_IDX
, 0);
973 return 0; /* not an MMU fault */
975 return 1; /* the MMU fault was handled without causing real CPU fault */
976 /* now we have a real cpu fault */
979 /* the PC is inside the translated code. It means that we have
980 a virtual CPU fault */
981 cpu_restore_state(tb
, env
, pc
, puc
);
983 /* we restore the process signal mask as the sigreturn should
984 do it (XXX: use sigsetjmp) */
985 sigprocmask(SIG_SETMASK
, old_set
, NULL
);
987 /* never comes here */
991 #elif defined (TARGET_MIPS)
992 static inline int handle_cpu_signal(unsigned long pc
, unsigned long address
,
993 int is_write
, sigset_t
*old_set
,
996 TranslationBlock
*tb
;
1000 env
= cpu_single_env
; /* XXX: find a correct solution for multithread */
1001 #if defined(DEBUG_SIGNAL)
1002 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1003 pc
, address
, is_write
, *(unsigned long *)old_set
);
1005 /* XXX: locking issue */
1006 if (is_write
&& page_unprotect(h2g(address
), pc
, puc
)) {
1010 /* see if it is an MMU fault */
1011 ret
= cpu_mips_handle_mmu_fault(env
, address
, is_write
, MMU_USER_IDX
, 0);
1013 return 0; /* not an MMU fault */
1015 return 1; /* the MMU fault was handled without causing real CPU fault */
1017 /* now we have a real cpu fault */
1018 tb
= tb_find_pc(pc
);
1020 /* the PC is inside the translated code. It means that we have
1021 a virtual CPU fault */
1022 cpu_restore_state(tb
, env
, pc
, puc
);
1026 printf("PF exception: PC=0x" TARGET_FMT_lx
" error=0x%x %p\n",
1027 env
->PC
, env
->error_code
, tb
);
1029 /* we restore the process signal mask as the sigreturn should
1030 do it (XXX: use sigsetjmp) */
1031 sigprocmask(SIG_SETMASK
, old_set
, NULL
);
1032 do_raise_exception_err(env
->exception_index
, env
->error_code
);
1034 /* activate soft MMU for this block */
1035 cpu_resume_from_signal(env
, puc
);
1037 /* never comes here */
1041 #elif defined (TARGET_SH4)
1042 static inline int handle_cpu_signal(unsigned long pc
, unsigned long address
,
1043 int is_write
, sigset_t
*old_set
,
1046 TranslationBlock
*tb
;
1050 env
= cpu_single_env
; /* XXX: find a correct solution for multithread */
1051 #if defined(DEBUG_SIGNAL)
1052 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1053 pc
, address
, is_write
, *(unsigned long *)old_set
);
1055 /* XXX: locking issue */
1056 if (is_write
&& page_unprotect(h2g(address
), pc
, puc
)) {
1060 /* see if it is an MMU fault */
1061 ret
= cpu_sh4_handle_mmu_fault(env
, address
, is_write
, MMU_USER_IDX
, 0);
1063 return 0; /* not an MMU fault */
1065 return 1; /* the MMU fault was handled without causing real CPU fault */
1067 /* now we have a real cpu fault */
1068 tb
= tb_find_pc(pc
);
1070 /* the PC is inside the translated code. It means that we have
1071 a virtual CPU fault */
1072 cpu_restore_state(tb
, env
, pc
, puc
);
1075 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1076 env
->nip
, env
->error_code
, tb
);
1078 /* we restore the process signal mask as the sigreturn should
1079 do it (XXX: use sigsetjmp) */
1080 sigprocmask(SIG_SETMASK
, old_set
, NULL
);
1082 /* never comes here */
1086 #elif defined (TARGET_ALPHA)
1087 static inline int handle_cpu_signal(unsigned long pc
, unsigned long address
,
1088 int is_write
, sigset_t
*old_set
,
1091 TranslationBlock
*tb
;
1095 env
= cpu_single_env
; /* XXX: find a correct solution for multithread */
1096 #if defined(DEBUG_SIGNAL)
1097 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1098 pc
, address
, is_write
, *(unsigned long *)old_set
);
1100 /* XXX: locking issue */
1101 if (is_write
&& page_unprotect(h2g(address
), pc
, puc
)) {
1105 /* see if it is an MMU fault */
1106 ret
= cpu_alpha_handle_mmu_fault(env
, address
, is_write
, MMU_USER_IDX
, 0);
1108 return 0; /* not an MMU fault */
1110 return 1; /* the MMU fault was handled without causing real CPU fault */
1112 /* now we have a real cpu fault */
1113 tb
= tb_find_pc(pc
);
1115 /* the PC is inside the translated code. It means that we have
1116 a virtual CPU fault */
1117 cpu_restore_state(tb
, env
, pc
, puc
);
1120 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1121 env
->nip
, env
->error_code
, tb
);
1123 /* we restore the process signal mask as the sigreturn should
1124 do it (XXX: use sigsetjmp) */
1125 sigprocmask(SIG_SETMASK
, old_set
, NULL
);
1127 /* never comes here */
1130 #elif defined (TARGET_CRIS)
1131 static inline int handle_cpu_signal(unsigned long pc
, unsigned long address
,
1132 int is_write
, sigset_t
*old_set
,
1135 TranslationBlock
*tb
;
1139 env
= cpu_single_env
; /* XXX: find a correct solution for multithread */
1140 #if defined(DEBUG_SIGNAL)
1141 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1142 pc
, address
, is_write
, *(unsigned long *)old_set
);
1144 /* XXX: locking issue */
1145 if (is_write
&& page_unprotect(h2g(address
), pc
, puc
)) {
1149 /* see if it is an MMU fault */
1150 ret
= cpu_cris_handle_mmu_fault(env
, address
, is_write
, MMU_USER_IDX
, 0);
1152 return 0; /* not an MMU fault */
1154 return 1; /* the MMU fault was handled without causing real CPU fault */
1156 /* now we have a real cpu fault */
1157 tb
= tb_find_pc(pc
);
1159 /* the PC is inside the translated code. It means that we have
1160 a virtual CPU fault */
1161 cpu_restore_state(tb
, env
, pc
, puc
);
1163 /* we restore the process signal mask as the sigreturn should
1164 do it (XXX: use sigsetjmp) */
1165 sigprocmask(SIG_SETMASK
, old_set
, NULL
);
1167 /* never comes here */
1172 #error unsupported target CPU
1175 #if defined(__i386__)
1177 #if defined(__APPLE__)
1178 # include <sys/ucontext.h>
1180 # define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1181 # define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
1182 # define ERROR_sig(context) ((context)->uc_mcontext->es.err)
1184 # define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
1185 # define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
1186 # define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
1189 int cpu_signal_handler(int host_signum
, void *pinfo
,
1192 siginfo_t
*info
= pinfo
;
1193 struct ucontext
*uc
= puc
;
1201 #define REG_TRAPNO TRAPNO
1204 trapno
= TRAP_sig(uc
);
1205 return handle_cpu_signal(pc
, (unsigned long)info
->si_addr
,
1207 (ERROR_sig(uc
) >> 1) & 1 : 0,
1208 &uc
->uc_sigmask
, puc
);
1211 #elif defined(__x86_64__)
1213 int cpu_signal_handler(int host_signum
, void *pinfo
,
1216 siginfo_t
*info
= pinfo
;
1217 struct ucontext
*uc
= puc
;
1220 pc
= uc
->uc_mcontext
.gregs
[REG_RIP
];
1221 return handle_cpu_signal(pc
, (unsigned long)info
->si_addr
,
1222 uc
->uc_mcontext
.gregs
[REG_TRAPNO
] == 0xe ?
1223 (uc
->uc_mcontext
.gregs
[REG_ERR
] >> 1) & 1 : 0,
1224 &uc
->uc_sigmask
, puc
);
1227 #elif defined(__powerpc__)
1229 /***********************************************************************
1230 * signal context platform-specific definitions
1234 /* All Registers access - only for local access */
1235 # define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
1236 /* Gpr Registers access */
1237 # define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
1238 # define IAR_sig(context) REG_sig(nip, context) /* Program counter */
1239 # define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
1240 # define CTR_sig(context) REG_sig(ctr, context) /* Count register */
1241 # define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
1242 # define LR_sig(context) REG_sig(link, context) /* Link register */
1243 # define CR_sig(context) REG_sig(ccr, context) /* Condition register */
1244 /* Float Registers access */
1245 # define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1246 # define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1247 /* Exception Registers access */
1248 # define DAR_sig(context) REG_sig(dar, context)
1249 # define DSISR_sig(context) REG_sig(dsisr, context)
1250 # define TRAP_sig(context) REG_sig(trap, context)
1254 # include <sys/ucontext.h>
1255 typedef struct ucontext SIGCONTEXT
;
1256 /* All Registers access - only for local access */
1257 # define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
1258 # define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
1259 # define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
1260 # define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
1261 /* Gpr Registers access */
1262 # define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
1263 # define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
1264 # define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
1265 # define CTR_sig(context) REG_sig(ctr, context)
1266 # define XER_sig(context) REG_sig(xer, context) /* Link register */
1267 # define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
1268 # define CR_sig(context) REG_sig(cr, context) /* Condition register */
1269 /* Float Registers access */
1270 # define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
1271 # define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
1272 /* Exception Registers access */
1273 # define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
1274 # define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
1275 # define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1276 #endif /* __APPLE__ */
1278 int cpu_signal_handler(int host_signum
, void *pinfo
,
1281 siginfo_t
*info
= pinfo
;
1282 struct ucontext
*uc
= puc
;
1290 if (DSISR_sig(uc
) & 0x00800000)
1293 if (TRAP_sig(uc
) != 0x400 && (DSISR_sig(uc
) & 0x02000000))
1296 return handle_cpu_signal(pc
, (unsigned long)info
->si_addr
,
1297 is_write
, &uc
->uc_sigmask
, puc
);
1300 #elif defined(__alpha__)
1302 int cpu_signal_handler(int host_signum
, void *pinfo
,
1305 siginfo_t
*info
= pinfo
;
1306 struct ucontext
*uc
= puc
;
1307 uint32_t *pc
= uc
->uc_mcontext
.sc_pc
;
1308 uint32_t insn
= *pc
;
1311 /* XXX: need kernel patch to get write flag faster */
1312 switch (insn
>> 26) {
1327 return handle_cpu_signal(pc
, (unsigned long)info
->si_addr
,
1328 is_write
, &uc
->uc_sigmask
, puc
);
1330 #elif defined(__sparc__)
1332 int cpu_signal_handler(int host_signum
, void *pinfo
,
1335 siginfo_t
*info
= pinfo
;
1336 uint32_t *regs
= (uint32_t *)(info
+ 1);
1337 void *sigmask
= (regs
+ 20);
1342 /* XXX: is there a standard glibc define ? */
1344 /* XXX: need kernel patch to get write flag faster */
1346 insn
= *(uint32_t *)pc
;
1347 if ((insn
>> 30) == 3) {
1348 switch((insn
>> 19) & 0x3f) {
1360 return handle_cpu_signal(pc
, (unsigned long)info
->si_addr
,
1361 is_write
, sigmask
, NULL
);
1364 #elif defined(__arm__)
1366 int cpu_signal_handler(int host_signum
, void *pinfo
,
1369 siginfo_t
*info
= pinfo
;
1370 struct ucontext
*uc
= puc
;
1374 pc
= uc
->uc_mcontext
.arm_pc
;
1375 /* XXX: compute is_write */
1377 return handle_cpu_signal(pc
, (unsigned long)info
->si_addr
,
1379 &uc
->uc_sigmask
, puc
);
1382 #elif defined(__mc68000)
1384 int cpu_signal_handler(int host_signum
, void *pinfo
,
1387 siginfo_t
*info
= pinfo
;
1388 struct ucontext
*uc
= puc
;
1392 pc
= uc
->uc_mcontext
.gregs
[16];
1393 /* XXX: compute is_write */
1395 return handle_cpu_signal(pc
, (unsigned long)info
->si_addr
,
1397 &uc
->uc_sigmask
, puc
);
1400 #elif defined(__ia64)
1403 /* This ought to be in <bits/siginfo.h>... */
1404 # define __ISR_VALID 1
1407 int cpu_signal_handler(int host_signum
, void *pinfo
, void *puc
)
1409 siginfo_t
*info
= pinfo
;
1410 struct ucontext
*uc
= puc
;
1414 ip
= uc
->uc_mcontext
.sc_ip
;
1415 switch (host_signum
) {
1421 if (info
->si_code
&& (info
->si_segvflags
& __ISR_VALID
))
1422 /* ISR.W (write-access) is bit 33: */
1423 is_write
= (info
->si_isr
>> 33) & 1;
1429 return handle_cpu_signal(ip
, (unsigned long)info
->si_addr
,
1431 &uc
->uc_sigmask
, puc
);
1434 #elif defined(__s390__)
1436 int cpu_signal_handler(int host_signum
, void *pinfo
,
1439 siginfo_t
*info
= pinfo
;
1440 struct ucontext
*uc
= puc
;
1444 pc
= uc
->uc_mcontext
.psw
.addr
;
1445 /* XXX: compute is_write */
1447 return handle_cpu_signal(pc
, (unsigned long)info
->si_addr
,
1448 is_write
, &uc
->uc_sigmask
, puc
);
1451 #elif defined(__mips__)
1453 int cpu_signal_handler(int host_signum
, void *pinfo
,
1456 siginfo_t
*info
= pinfo
;
1457 struct ucontext
*uc
= puc
;
1458 greg_t pc
= uc
->uc_mcontext
.pc
;
1461 /* XXX: compute is_write */
1463 return handle_cpu_signal(pc
, (unsigned long)info
->si_addr
,
1464 is_write
, &uc
->uc_sigmask
, puc
);
1467 #elif defined(__hppa__)
1469 int cpu_signal_handler(int host_signum
, void *pinfo
,
1472 struct siginfo
*info
= pinfo
;
1473 struct ucontext
*uc
= puc
;
1477 pc
= uc
->uc_mcontext
.sc_iaoq
[0];
1478 /* FIXME: compute is_write */
1480 return handle_cpu_signal(pc
, (unsigned long)info
->si_addr
,
1482 &uc
->uc_sigmask
, puc
);
1487 #error host CPU specific signal handler needed
1491 #endif /* !defined(CONFIG_SOFTMMU) */