cpu-exec.c 55.1 KB
Newer Older
B
bellard 已提交
1 2
/*
 *  i386 emulator main execution loop
3
 *
B
bellard 已提交
4
 *  Copyright (c) 2003-2005 Fabrice Bellard
B
bellard 已提交
5
 *
B
bellard 已提交
6 7 8 9
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
B
bellard 已提交
10
 *
B
bellard 已提交
11 12 13 14
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
B
bellard 已提交
15
 *
B
bellard 已提交
16 17
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
B
bellard 已提交
19
 */
B
bellard 已提交
20
#include "config.h"
21
#include "exec.h"
B
log fix  
bellard 已提交
22
#include "disas.h"
23
#include "tcg.h"
A
aliguori 已提交
24
#include "kvm.h"
B
bellard 已提交
25

26 27 28 29 30 31 32 33 34 35 36
#if !defined(CONFIG_SOFTMMU)
#undef EAX
#undef ECX
#undef EDX
#undef EBX
#undef ESP
#undef EBP
#undef ESI
#undef EDI
#undef EIP
#include <signal.h>
B
blueswir1 已提交
37
#ifdef __linux__
38 39
#include <sys/ucontext.h>
#endif
B
blueswir1 已提交
40
#endif
41

42 43 44 45 46 47
#if defined(__sparc__) && !defined(HOST_SOLARIS)
// Work around ugly bugs in glibc that mangle global register contents
#undef env
#define env cpu_single_env
#endif

48 49
int tb_invalidated_flag;

B
bellard 已提交
50
//#define DEBUG_EXEC
B
bellard 已提交
51
//#define DEBUG_SIGNAL
B
bellard 已提交
52

53 54 55 56 57
int qemu_cpu_has_work(CPUState *env)
{
    return cpu_has_work(env);
}

B
bellard 已提交
58 59
void cpu_loop_exit(void)
{
60 61 62
    /* NOTE: the register at this point must be saved by hand because
       longjmp restore them */
    regs_to_env();
B
bellard 已提交
63 64
    longjmp(env->jmp_env, 1);
}
65

66 67 68
/* exit the current TB from a signal handler. The host registers are
   restored in a state compatible with the CPU emulator
 */
69
void cpu_resume_from_signal(CPUState *env1, void *puc)
70 71
{
#if !defined(CONFIG_SOFTMMU)
B
blueswir1 已提交
72
#ifdef __linux__
73
    struct ucontext *uc = puc;
B
blueswir1 已提交
74 75 76
#elif defined(__OpenBSD__)
    struct sigcontext *uc = puc;
#endif
77 78 79 80 81 82 83 84 85
#endif

    env = env1;

    /* XXX: restore cpu registers saved in host registers */

#if !defined(CONFIG_SOFTMMU)
    if (puc) {
        /* XXX: use siglongjmp ? */
B
blueswir1 已提交
86
#ifdef __linux__
87
        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
B
blueswir1 已提交
88 89 90
#elif defined(__OpenBSD__)
        sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
#endif
91 92
    }
#endif
93
    env->exception_index = -1;
94 95 96
    longjmp(env->jmp_env, 1);
}

P
pbrook 已提交
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
/* Execute the code without caching the generated code. An interpreter
   could be used if available. */
static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
{
    unsigned long next_tb;
    TranslationBlock *tb;

    /* Should never happen.
       We only end up here when an existing TB is too long.  */
    if (max_cycles > CF_COUNT_MASK)
        max_cycles = CF_COUNT_MASK;

    tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
                     max_cycles);
    env->current_tb = tb;
    /* execute the generated code */
    next_tb = tcg_qemu_tb_exec(tb->tc_ptr);

    if ((next_tb & 3) == 2) {
        /* Restore PC.  This may happen if async event occurs before
           the TB starts executing.  */
118
        cpu_pc_from_tb(env, tb);
P
pbrook 已提交
119 120 121 122 123
    }
    tb_phys_invalidate(tb, -1);
    tb_free(tb);
}

124 125
static TranslationBlock *tb_find_slow(target_ulong pc,
                                      target_ulong cs_base,
126
                                      uint64_t flags)
127 128 129 130
{
    TranslationBlock *tb, **ptb1;
    unsigned int h;
    target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
131

132
    tb_invalidated_flag = 0;
133

134
    regs_to_env(); /* XXX: do it just before cpu_gen_code() */
135

136 137 138 139 140 141 142 143 144 145
    /* find translated block using physical mappings */
    phys_pc = get_phys_addr_code(env, pc);
    phys_page1 = phys_pc & TARGET_PAGE_MASK;
    phys_page2 = -1;
    h = tb_phys_hash_func(phys_pc);
    ptb1 = &tb_phys_hash[h];
    for(;;) {
        tb = *ptb1;
        if (!tb)
            goto not_found;
146
        if (tb->pc == pc &&
147
            tb->page_addr[0] == phys_page1 &&
148
            tb->cs_base == cs_base &&
149 150 151
            tb->flags == flags) {
            /* check next page if needed */
            if (tb->page_addr[1] != -1) {
152
                virt_page2 = (pc & TARGET_PAGE_MASK) +
153 154 155 156 157 158 159 160 161 162 163
                    TARGET_PAGE_SIZE;
                phys_page2 = get_phys_addr_code(env, virt_page2);
                if (tb->page_addr[1] == phys_page2)
                    goto found;
            } else {
                goto found;
            }
        }
        ptb1 = &tb->phys_hash_next;
    }
 not_found:
P
pbrook 已提交
164 165
   /* if no translated code available, then translate it now */
    tb = tb_gen_code(env, pc, cs_base, flags, 0);
166

167 168 169 170 171 172 173 174 175 176
 found:
    /* we add the TB in the virtual pc hash table */
    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
    return tb;
}

static inline TranslationBlock *tb_find_fast(void)
{
    TranslationBlock *tb;
    target_ulong cs_base, pc;
177
    int flags;
178 179 180 181

    /* we record a subset of the CPU state. It will
       always be the same before a given translated block
       is executed. */
182
    cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
B
bellard 已提交
183
    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
184 185
    if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
                 tb->flags != flags)) {
186 187 188 189 190
        tb = tb_find_slow(pc, cs_base, flags);
    }
    return tb;
}

A
aliguori 已提交
191 192 193 194 195 196 197 198 199 200
static CPUDebugExcpHandler *debug_excp_handler;

CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
{
    CPUDebugExcpHandler *old_handler = debug_excp_handler;

    debug_excp_handler = handler;
    return old_handler;
}

201 202 203 204 205
static void cpu_handle_debug_exception(CPUState *env)
{
    CPUWatchpoint *wp;

    if (!env->watchpoint_hit)
206
        TAILQ_FOREACH(wp, &env->watchpoints, entry)
207
            wp->flags &= ~BP_WATCHPOINT_HIT;
A
aliguori 已提交
208 209 210

    if (debug_excp_handler)
        debug_excp_handler(env);
211 212
}

B
bellard 已提交
213 214
/* main execution loop */

B
bellard 已提交
215
int cpu_exec(CPUState *env1)
B
bellard 已提交
216
{
P
pbrook 已提交
217 218
#define DECLARE_HOST_REGS 1
#include "hostregs_helper.h"
219 220
    int ret, interrupt_request;
    TranslationBlock *tb;
B
bellard 已提交
221
    uint8_t *tc_ptr;
P
pbrook 已提交
222
    unsigned long next_tb;
223

224 225
    if (cpu_halted(env1) == EXCP_HALTED)
        return EXCP_HALTED;
B
bellard 已提交
226

227
    cpu_single_env = env1;
B
bellard 已提交
228

B
bellard 已提交
229
    /* first we save global registers */
P
pbrook 已提交
230 231
#define SAVE_HOST_REGS 1
#include "hostregs_helper.h"
B
bellard 已提交
232
    env = env1;
B
bellard 已提交
233

B
bellard 已提交
234
    env_to_regs();
235
#if defined(TARGET_I386)
B
bellard 已提交
236
    /* put eflags in CPU temporary format */
B
bellard 已提交
237 238
    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
    DF = 1 - (2 * ((env->eflags >> 10) & 1));
B
bellard 已提交
239
    CC_OP = CC_OP_EFLAGS;
B
bellard 已提交
240
    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
241
#elif defined(TARGET_SPARC)
P
pbrook 已提交
242 243 244 245
#elif defined(TARGET_M68K)
    env->cc_op = CC_OP_FLAGS;
    env->cc_dest = env->sr & 0xf;
    env->cc_x = (env->sr >> 4) & 1;
246 247 248
#elif defined(TARGET_ALPHA)
#elif defined(TARGET_ARM)
#elif defined(TARGET_PPC)
249
#elif defined(TARGET_MICROBLAZE)
B
bellard 已提交
250
#elif defined(TARGET_MIPS)
B
bellard 已提交
251
#elif defined(TARGET_SH4)
252
#elif defined(TARGET_CRIS)
B
bellard 已提交
253
    /* XXXXX */
B
bellard 已提交
254 255 256
#else
#error unsupported target CPU
#endif
257
    env->exception_index = -1;
258

B
bellard 已提交
259
    /* prepare setjmp context for exception handling */
260 261
    for(;;) {
        if (setjmp(env->jmp_env) == 0) {
B
blueswir1 已提交
262 263 264 265 266
#if defined(__sparc__) && !defined(HOST_SOLARIS)
#undef env
                    env = cpu_single_env;
#define env cpu_single_env
#endif
267
            env->current_tb = NULL;
268 269 270 271 272
            /* if an exception is pending, we execute it here */
            if (env->exception_index >= 0) {
                if (env->exception_index >= EXCP_INTERRUPT) {
                    /* exit request from the cpu execution loop */
                    ret = env->exception_index;
273 274
                    if (ret == EXCP_DEBUG)
                        cpu_handle_debug_exception(env);
275
                    break;
A
aurel32 已提交
276 277
                } else {
#if defined(CONFIG_USER_ONLY)
278
                    /* if user mode only, we simulate a fake exception
T
ths 已提交
279
                       which will be handled outside the cpu execution
280
                       loop */
B
bellard 已提交
281
#if defined(TARGET_I386)
282 283 284
                    do_interrupt_user(env->exception_index,
                                      env->exception_is_int,
                                      env->error_code,
285
                                      env->exception_next_eip);
286 287
                    /* successfully delivered */
                    env->old_exception = -1;
B
bellard 已提交
288
#endif
289 290
                    ret = env->exception_index;
                    break;
A
aurel32 已提交
291
#else
B
bellard 已提交
292
#if defined(TARGET_I386)
293 294 295
                    /* simulate a real cpu exception. On i386, it can
                       trigger new exceptions, but we do not handle
                       double or triple faults yet. */
296 297 298
                    do_interrupt(env->exception_index,
                                 env->exception_is_int,
                                 env->error_code,
B
bellard 已提交
299
                                 env->exception_next_eip, 0);
300 301
                    /* successfully delivered */
                    env->old_exception = -1;
302 303
#elif defined(TARGET_PPC)
                    do_interrupt(env);
304 305
#elif defined(TARGET_MICROBLAZE)
                    do_interrupt(env);
B
bellard 已提交
306 307
#elif defined(TARGET_MIPS)
                    do_interrupt(env);
308
#elif defined(TARGET_SPARC)
309
                    do_interrupt(env);
B
bellard 已提交
310 311
#elif defined(TARGET_ARM)
                    do_interrupt(env);
B
bellard 已提交
312 313
#elif defined(TARGET_SH4)
		    do_interrupt(env);
J
j_mayer 已提交
314 315
#elif defined(TARGET_ALPHA)
                    do_interrupt(env);
316 317
#elif defined(TARGET_CRIS)
                    do_interrupt(env);
P
pbrook 已提交
318 319
#elif defined(TARGET_M68K)
                    do_interrupt(0);
A
aurel32 已提交
320
#endif
B
bellard 已提交
321
#endif
322 323
                }
                env->exception_index = -1;
324
            }
325
#ifdef CONFIG_KQEMU
326
            if (kqemu_is_ok(env) && env->interrupt_request == 0 && env->exit_request == 0) {
B
bellard 已提交
327
                int ret;
P
pbrook 已提交
328
                env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
B
bellard 已提交
329 330 331 332 333 334 335 336 337 338 339 340
                ret = kqemu_cpu_exec(env);
                /* put eflags in CPU temporary format */
                CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
                DF = 1 - (2 * ((env->eflags >> 10) & 1));
                CC_OP = CC_OP_EFLAGS;
                env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
                if (ret == 1) {
                    /* exception */
                    longjmp(env->jmp_env, 1);
                } else if (ret == 2) {
                    /* softmmu execution needed */
                } else {
341
                    if (env->interrupt_request != 0 || env->exit_request != 0) {
B
bellard 已提交
342 343 344 345 346 347
                        /* hardware interrupt will be executed just after */
                    } else {
                        /* otherwise, we restart */
                        longjmp(env->jmp_env, 1);
                    }
                }
348
            }
B
bellard 已提交
349 350
#endif

A
aliguori 已提交
351
            if (kvm_enabled()) {
A
aliguori 已提交
352 353
                kvm_cpu_exec(env);
                longjmp(env->jmp_env, 1);
A
aliguori 已提交
354 355
            }

356
            next_tb = 0; /* force lookup of first TB */
357
            for(;;) {
B
bellard 已提交
358
                interrupt_request = env->interrupt_request;
M
malc 已提交
359 360 361 362 363 364 365 366
                if (unlikely(interrupt_request)) {
                    if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
                        /* Mask out external interrupts for this step. */
                        interrupt_request &= ~(CPU_INTERRUPT_HARD |
                                               CPU_INTERRUPT_FIQ |
                                               CPU_INTERRUPT_SMI |
                                               CPU_INTERRUPT_NMI);
                    }
367 368 369 370 371
                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
                        env->exception_index = EXCP_DEBUG;
                        cpu_loop_exit();
                    }
372
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
373 374
    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
    defined(TARGET_MICROBLAZE)
375 376 377 378 379 380 381
                    if (interrupt_request & CPU_INTERRUPT_HALT) {
                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
                        env->halted = 1;
                        env->exception_index = EXCP_HLT;
                        cpu_loop_exit();
                    }
#endif
B
bellard 已提交
382
#if defined(TARGET_I386)
383 384 385 386 387 388 389 390
                    if (interrupt_request & CPU_INTERRUPT_INIT) {
                            svm_check_intercept(SVM_EXIT_INIT);
                            do_cpu_init(env);
                            env->exception_index = EXCP_HALTED;
                            cpu_loop_exit();
                    } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
                            do_cpu_sipi(env);
                    } else if (env->hflags2 & HF2_GIF_MASK) {
391 392 393 394 395 396 397 398 399 400 401 402
                        if ((interrupt_request & CPU_INTERRUPT_SMI) &&
                            !(env->hflags & HF_SMM_MASK)) {
                            svm_check_intercept(SVM_EXIT_SMI);
                            env->interrupt_request &= ~CPU_INTERRUPT_SMI;
                            do_smm_enter();
                            next_tb = 0;
                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
                                   !(env->hflags2 & HF2_NMI_MASK)) {
                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
                            env->hflags2 |= HF2_NMI_MASK;
                            do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
                            next_tb = 0;
403 404 405 406
			} else if (interrupt_request & CPU_INTERRUPT_MCE) {
                            env->interrupt_request &= ~CPU_INTERRUPT_MCE;
                            do_interrupt(EXCP12_MCHK, 0, 0, 0, 0);
                            next_tb = 0;
407 408 409 410 411 412 413 414 415 416
                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
                                   (((env->hflags2 & HF2_VINTR_MASK) && 
                                     (env->hflags2 & HF2_HIF_MASK)) ||
                                    (!(env->hflags2 & HF2_VINTR_MASK) && 
                                     (env->eflags & IF_MASK && 
                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
                            int intno;
                            svm_check_intercept(SVM_EXIT_INTR);
                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
                            intno = cpu_get_pic_interrupt(env);
417
                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
B
blueswir1 已提交
418 419 420 421 422
#if defined(__sparc__) && !defined(HOST_SOLARIS)
#undef env
                    env = cpu_single_env;
#define env cpu_single_env
#endif
423 424 425 426
                            do_interrupt(intno, 0, 0, 0, 1);
                            /* ensure that no TB jump will be modified as
                               the program flow was changed */
                            next_tb = 0;
T
ths 已提交
427
#if !defined(CONFIG_USER_ONLY)
428 429 430 431 432 433 434
                        } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
                                   (env->eflags & IF_MASK) && 
                                   !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
                            int intno;
                            /* FIXME: this should respect TPR */
                            svm_check_intercept(SVM_EXIT_VINTR);
                            intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
435
                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
436
                            do_interrupt(intno, 0, 0, 0, 1);
437
                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
438
                            next_tb = 0;
B
bellard 已提交
439
#endif
440
                        }
B
bellard 已提交
441
                    }
442
#elif defined(TARGET_PPC)
443 444 445 446 447
#if 0
                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
                        cpu_ppc_reset(env);
                    }
#endif
448
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
449 450 451
                        ppc_hw_interrupt(env);
                        if (env->pending_interrupts == 0)
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
452
                        next_tb = 0;
453
                    }
454 455 456 457 458 459 460 461 462
#elif defined(TARGET_MICROBLAZE)
                    if ((interrupt_request & CPU_INTERRUPT_HARD)
                        && (env->sregs[SR_MSR] & MSR_IE)
                        && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
                        && !(env->iflags & (D_FLAG | IMM_FLAG))) {
                        env->exception_index = EXCP_IRQ;
                        do_interrupt(env);
                        next_tb = 0;
                    }
B
bellard 已提交
463 464
#elif defined(TARGET_MIPS)
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
T
ths 已提交
465
                        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
B
bellard 已提交
466
                        (env->CP0_Status & (1 << CP0St_IE)) &&
T
ths 已提交
467 468
                        !(env->CP0_Status & (1 << CP0St_EXL)) &&
                        !(env->CP0_Status & (1 << CP0St_ERL)) &&
B
bellard 已提交
469 470 471 472 473
                        !(env->hflags & MIPS_HFLAG_DM)) {
                        /* Raise it */
                        env->exception_index = EXCP_EXT_INTERRUPT;
                        env->error_code = 0;
                        do_interrupt(env);
474
                        next_tb = 0;
B
bellard 已提交
475
                    }
476
#elif defined(TARGET_SPARC)
B
bellard 已提交
477
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
478
			cpu_interrupts_enabled(env)) {
B
bellard 已提交
479 480 481 482 483 484 485
			int pil = env->interrupt_index & 15;
			int type = env->interrupt_index & 0xf0;

			if (((type == TT_EXTINT) &&
			     (pil == 15 || pil > env->psrpil)) ||
			    type != TT_EXTINT) {
			    env->interrupt_request &= ~CPU_INTERRUPT_HARD;
486 487
                            env->exception_index = env->interrupt_index;
                            do_interrupt(env);
B
bellard 已提交
488
			    env->interrupt_index = 0;
489
#if !defined(CONFIG_USER_ONLY)
B
blueswir1 已提交
490 491
                            cpu_check_irqs(env);
#endif
492
                        next_tb = 0;
B
bellard 已提交
493
			}
494 495 496
		    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
			//do_interrupt(0, 0, 0, 0, 0);
			env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
497
		    }
B
bellard 已提交
498 499 500 501 502
#elif defined(TARGET_ARM)
                    if (interrupt_request & CPU_INTERRUPT_FIQ
                        && !(env->uncached_cpsr & CPSR_F)) {
                        env->exception_index = EXCP_FIQ;
                        do_interrupt(env);
503
                        next_tb = 0;
B
bellard 已提交
504
                    }
P
pbrook 已提交
505 506 507 508 509 510 511 512 513
                    /* ARMv7-M interrupt return works by loading a magic value
                       into the PC.  On real hardware the load causes the
                       return to occur.  The qemu implementation performs the
                       jump normally, then does the exception return when the
                       CPU tries to execute code at the magic address.
                       This will cause the magic PC value to be pushed to
                       the stack if an interrupt occured at the wrong time.
                       We avoid this by disabling interrupts when
                       pc contains a magic address.  */
B
bellard 已提交
514
                    if (interrupt_request & CPU_INTERRUPT_HARD
P
pbrook 已提交
515 516
                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
                            || !(env->uncached_cpsr & CPSR_I))) {
B
bellard 已提交
517 518
                        env->exception_index = EXCP_IRQ;
                        do_interrupt(env);
519
                        next_tb = 0;
B
bellard 已提交
520
                    }
B
bellard 已提交
521
#elif defined(TARGET_SH4)
522 523
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
                        do_interrupt(env);
524
                        next_tb = 0;
525
                    }
J
j_mayer 已提交
526 527 528
#elif defined(TARGET_ALPHA)
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
                        do_interrupt(env);
529
                        next_tb = 0;
J
j_mayer 已提交
530
                    }
531
#elif defined(TARGET_CRIS)
E
edgar_igl 已提交
532 533 534 535 536 537 538 539 540
                    if (interrupt_request & CPU_INTERRUPT_HARD
                        && (env->pregs[PR_CCS] & I_FLAG)) {
                        env->exception_index = EXCP_IRQ;
                        do_interrupt(env);
                        next_tb = 0;
                    }
                    if (interrupt_request & CPU_INTERRUPT_NMI
                        && (env->pregs[PR_CCS] & M_FLAG)) {
                        env->exception_index = EXCP_NMI;
541
                        do_interrupt(env);
542
                        next_tb = 0;
543
                    }
P
pbrook 已提交
544 545 546 547 548 549 550 551 552 553 554
#elif defined(TARGET_M68K)
                    if (interrupt_request & CPU_INTERRUPT_HARD
                        && ((env->sr & SR_I) >> SR_I_SHIFT)
                            < env->pending_level) {
                        /* Real hardware gets the interrupt vector via an
                           IACK cycle at this point.  Current emulated
                           hardware doesn't rely on this, so we
                           provide/save the vector when the interrupt is
                           first signalled.  */
                        env->exception_index = env->pending_vector;
                        do_interrupt(1);
555
                        next_tb = 0;
P
pbrook 已提交
556
                    }
B
bellard 已提交
557
#endif
B
bellard 已提交
558 559
                   /* Don't use the cached interupt_request value,
                      do_interrupt may have updated the EXITTB flag. */
B
bellard 已提交
560
                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
561 562 563
                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
                        /* ensure that no TB jump will be modified as
                           the program flow was changed */
564
                        next_tb = 0;
565
                    }
566 567 568 569 570
                }
                if (unlikely(env->exit_request)) {
                    env->exit_request = 0;
                    env->exception_index = EXCP_INTERRUPT;
                    cpu_loop_exit();
571
                }
B
bellard 已提交
572
#ifdef DEBUG_EXEC
573
                if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
574
                    /* restore flags in standard format */
575 576
                    regs_to_env();
#if defined(TARGET_I386)
P
pbrook 已提交
577
                    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
578
                    log_cpu_state(env, X86_DUMP_CCOP);
579
                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
B
bellard 已提交
580
#elif defined(TARGET_ARM)
581
                    log_cpu_state(env, 0);
582
#elif defined(TARGET_SPARC)
583
                    log_cpu_state(env, 0);
584
#elif defined(TARGET_PPC)
585
                    log_cpu_state(env, 0);
P
pbrook 已提交
586 587 588 589 590
#elif defined(TARGET_M68K)
                    cpu_m68k_flush_flags(env, env->cc_op);
                    env->cc_op = CC_OP_FLAGS;
                    env->sr = (env->sr & 0xffe0)
                              | env->cc_dest | (env->cc_x << 4);
591
                    log_cpu_state(env, 0);
592 593
#elif defined(TARGET_MICROBLAZE)
                    log_cpu_state(env, 0);
B
bellard 已提交
594
#elif defined(TARGET_MIPS)
595
                    log_cpu_state(env, 0);
B
bellard 已提交
596
#elif defined(TARGET_SH4)
597
		    log_cpu_state(env, 0);
J
j_mayer 已提交
598
#elif defined(TARGET_ALPHA)
599
                    log_cpu_state(env, 0);
600
#elif defined(TARGET_CRIS)
601
                    log_cpu_state(env, 0);
B
bellard 已提交
602
#else
603
#error unsupported target CPU
B
bellard 已提交
604
#endif
605
                }
B
bellard 已提交
606
#endif
P
pbrook 已提交
607
                spin_lock(&tb_lock);
608
                tb = tb_find_fast();
P
pbrook 已提交
609 610 611 612 613 614 615
                /* Note: we do it here to avoid a gcc bug on Mac OS X when
                   doing it in tb_find_slow */
                if (tb_invalidated_flag) {
                    /* as some TB could have been invalidated because
                       of memory exceptions while generating the code, we
                       must recompute the hash index here */
                    next_tb = 0;
P
pbrook 已提交
616
                    tb_invalidated_flag = 0;
P
pbrook 已提交
617
                }
618
#ifdef DEBUG_EXEC
619 620 621
                qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
                             (long)tb->tc_ptr, tb->pc,
                             lookup_symbol(tb->pc));
622
#endif
623 624 625
                /* see if we can patch the calling TB. When the TB
                   spans two pages, we cannot safely do a direct
                   jump. */
B
bellard 已提交
626
                {
627
                    if (next_tb != 0 &&
628
#ifdef CONFIG_KQEMU
629 630
                        (env->kqemu_enabled != 2) &&
#endif
B
bellard 已提交
631
                        tb->page_addr[1] == -1) {
632
                    tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
633
                }
B
bellard 已提交
634
                }
P
pbrook 已提交
635
                spin_unlock(&tb_lock);
B
bellard 已提交
636
                env->current_tb = tb;
637 638 639 640 641

                /* cpu_interrupt might be called while translating the
                   TB, but before it is linked into a potentially
                   infinite loop and becomes env->current_tb. Avoid
                   starting execution if there is a pending interrupt. */
642
                if (unlikely (env->exit_request))
643 644
                    env->current_tb = NULL;

P
pbrook 已提交
645 646
                while (env->current_tb) {
                    tc_ptr = tb->tc_ptr;
647
                /* execute the generated code */
648 649
#if defined(__sparc__) && !defined(HOST_SOLARIS)
#undef env
P
pbrook 已提交
650
                    env = cpu_single_env;
651 652
#define env cpu_single_env
#endif
P
pbrook 已提交
653 654 655
                    next_tb = tcg_qemu_tb_exec(tc_ptr);
                    env->current_tb = NULL;
                    if ((next_tb & 3) == 2) {
T
ths 已提交
656
                        /* Instruction counter expired.  */
P
pbrook 已提交
657 658 659
                        int insns_left;
                        tb = (TranslationBlock *)(long)(next_tb & ~3);
                        /* Restore PC.  */
660
                        cpu_pc_from_tb(env, tb);
P
pbrook 已提交
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682
                        insns_left = env->icount_decr.u32;
                        if (env->icount_extra && insns_left >= 0) {
                            /* Refill decrementer and continue execution.  */
                            env->icount_extra += insns_left;
                            if (env->icount_extra > 0xffff) {
                                insns_left = 0xffff;
                            } else {
                                insns_left = env->icount_extra;
                            }
                            env->icount_extra -= insns_left;
                            env->icount_decr.u16.low = insns_left;
                        } else {
                            if (insns_left > 0) {
                                /* Execute remaining instructions.  */
                                cpu_exec_nocache(insns_left, tb);
                            }
                            env->exception_index = EXCP_INTERRUPT;
                            next_tb = 0;
                            cpu_loop_exit();
                        }
                    }
                }
B
bellard 已提交
683 684
                /* reset soft MMU for next block (it can currently
                   only be set by a memory fault) */
685
#if defined(CONFIG_KQEMU)
686 687 688 689 690
#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
                if (kqemu_is_ok(env) &&
                    (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
                    cpu_loop_exit();
                }
B
bellard 已提交
691
#endif
T
ths 已提交
692
            } /* for(;;) */
693
        } else {
B
bellard 已提交
694
            env_to_regs();
B
bellard 已提交
695
        }
696 697
    } /* for(;;) */

B
bellard 已提交
698

B
bellard 已提交
699
#if defined(TARGET_I386)
B
bellard 已提交
700
    /* restore flags in standard format */
P
pbrook 已提交
701
    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
B
bellard 已提交
702
#elif defined(TARGET_ARM)
B
bellard 已提交
703
    /* XXX: Save/restore host fpu exception state?.  */
704
#elif defined(TARGET_SPARC)
705
#elif defined(TARGET_PPC)
P
pbrook 已提交
706 707 708 709 710
#elif defined(TARGET_M68K)
    cpu_m68k_flush_flags(env, env->cc_op);
    env->cc_op = CC_OP_FLAGS;
    env->sr = (env->sr & 0xffe0)
              | env->cc_dest | (env->cc_x << 4);
711
#elif defined(TARGET_MICROBLAZE)
B
bellard 已提交
712
#elif defined(TARGET_MIPS)
B
bellard 已提交
713
#elif defined(TARGET_SH4)
J
j_mayer 已提交
714
#elif defined(TARGET_ALPHA)
715
#elif defined(TARGET_CRIS)
B
bellard 已提交
716
    /* XXXXX */
B
bellard 已提交
717 718 719
#else
#error unsupported target CPU
#endif
P
pbrook 已提交
720 721 722 723

    /* restore global registers */
#include "hostregs_helper.h"

B
bellard 已提交
724
    /* fail safe : never use cpu_single_env outside cpu_exec() */
725
    cpu_single_env = NULL;
B
bellard 已提交
726 727
    return ret;
}
B
bellard 已提交
728

729 730 731 732
/* must only be called from the generated code as an exception can be
   generated */
void tb_invalidate_page_range(target_ulong start, target_ulong end)
{
733 734 735
    /* XXX: cannot enable it yet because it yields to MMU exception
       where NIP != read address on PowerPC */
#if 0
736 737 738
    target_ulong phys_addr;
    phys_addr = get_phys_addr_code(env, start);
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
739
#endif
740 741
}

B
bellard 已提交
742
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
B
bellard 已提交
743

B
bellard 已提交
744 745 746 747 748 749
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
{
    CPUX86State *saved_env;

    saved_env = env;
    env = s;
B
bellard 已提交
750
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
B
bellard 已提交
751
        selector &= 0xffff;
752
        cpu_x86_load_seg_cache(env, seg_reg, selector,
B
bellard 已提交
753
                               (selector << 4), 0xffff, 0);
B
bellard 已提交
754
    } else {
B
bellard 已提交
755
        helper_load_seg(seg_reg, selector);
B
bellard 已提交
756
    }
B
bellard 已提交
757 758
    env = saved_env;
}
B
bellard 已提交
759

760
void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
761 762 763 764 765
{
    CPUX86State *saved_env;

    saved_env = env;
    env = s;
766

767
    helper_fsave(ptr, data32);
768 769 770 771

    env = saved_env;
}

772
void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
773 774 775 776 777
{
    CPUX86State *saved_env;

    saved_env = env;
    env = s;
778

779
    helper_frstor(ptr, data32);
780 781 782 783

    env = saved_env;
}

B
bellard 已提交
784 785
#endif /* TARGET_I386 */

B
bellard 已提交
786 787
#if !defined(CONFIG_SOFTMMU)

788 789
#if defined(TARGET_I386)

790
/* 'pc' is the host PC at which the exception was raised. 'address' is
B
bellard 已提交
791 792 793
   the effective address of the memory exception. 'is_write' is 1 if a
   write caused the exception and otherwise 0'. 'old_set' is the
   signal set which should be restored */
B
bellard 已提交
794
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
795
                                    int is_write, sigset_t *old_set,
796
                                    void *puc)
B
bellard 已提交
797
{
B
bellard 已提交
798 799
    TranslationBlock *tb;
    int ret;
B
bellard 已提交
800

B
bellard 已提交
801 802
    if (cpu_single_env)
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
B
bellard 已提交
803
#if defined(DEBUG_SIGNAL)
804
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
805
                pc, address, is_write, *(unsigned long *)old_set);
B
bellard 已提交
806
#endif
807
    /* XXX: locking issue */
808
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
B
bellard 已提交
809 810
        return 1;
    }
811

812
    /* see if it is an MMU fault */
813
    ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
814 815 816 817 818
    if (ret < 0)
        return 0; /* not an MMU fault */
    if (ret == 0)
        return 1; /* the MMU fault was handled without causing real CPU fault */
    /* now we have a real cpu fault */
B
bellard 已提交
819 820
    tb = tb_find_pc(pc);
    if (tb) {
B
bellard 已提交
821 822
        /* the PC is inside the translated code. It means that we have
           a virtual CPU fault */
823
        cpu_restore_state(tb, env, pc, puc);
824
    }
B
bellard 已提交
825
    if (ret == 1) {
826
#if 0
827
        printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
B
bellard 已提交
828
               env->eip, env->cr[2], env->error_code);
829
#endif
B
bellard 已提交
830 831 832
        /* we restore the process signal mask as the sigreturn should
           do it (XXX: use sigsetjmp) */
        sigprocmask(SIG_SETMASK, old_set, NULL);
B
bellard 已提交
833
        raise_exception_err(env->exception_index, env->error_code);
B
bellard 已提交
834 835
    } else {
        /* activate soft MMU for this block */
836
        env->hflags |= HF_SOFTMMU_MASK;
837
        cpu_resume_from_signal(env, puc);
B
bellard 已提交
838
    }
839 840 841 842
    /* never comes here */
    return 1;
}

B
bellard 已提交
843
#elif defined(TARGET_ARM)
844
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
845 846
                                    int is_write, sigset_t *old_set,
                                    void *puc)
847
{
B
bellard 已提交
848 849 850 851 852 853
    TranslationBlock *tb;
    int ret;

    if (cpu_single_env)
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
854
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
B
bellard 已提交
855 856
           pc, address, is_write, *(unsigned long *)old_set);
#endif
B
bellard 已提交
857
    /* XXX: locking issue */
858
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
B
bellard 已提交
859 860
        return 1;
    }
B
bellard 已提交
861
    /* see if it is an MMU fault */
862
    ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
B
bellard 已提交
863 864 865 866 867 868 869 870 871 872 873 874 875 876 877
    if (ret < 0)
        return 0; /* not an MMU fault */
    if (ret == 0)
        return 1; /* the MMU fault was handled without causing real CPU fault */
    /* now we have a real cpu fault */
    tb = tb_find_pc(pc);
    if (tb) {
        /* the PC is inside the translated code. It means that we have
           a virtual CPU fault */
        cpu_restore_state(tb, env, pc, puc);
    }
    /* we restore the process signal mask as the sigreturn should
       do it (XXX: use sigsetjmp) */
    sigprocmask(SIG_SETMASK, old_set, NULL);
    cpu_loop_exit();
A
aurel32 已提交
878 879
    /* never comes here */
    return 1;
880
}
881 882
#elif defined(TARGET_SPARC)
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
883 884
                                    int is_write, sigset_t *old_set,
                                    void *puc)
885
{
B
bellard 已提交
886 887 888 889 890 891
    TranslationBlock *tb;
    int ret;

    if (cpu_single_env)
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
892
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
B
bellard 已提交
893 894
           pc, address, is_write, *(unsigned long *)old_set);
#endif
B
bellard 已提交
895
    /* XXX: locking issue */
896
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
B
bellard 已提交
897 898
        return 1;
    }
B
bellard 已提交
899
    /* see if it is an MMU fault */
900
    ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
B
bellard 已提交
901 902 903 904 905 906 907 908 909 910 911 912 913 914 915
    if (ret < 0)
        return 0; /* not an MMU fault */
    if (ret == 0)
        return 1; /* the MMU fault was handled without causing real CPU fault */
    /* now we have a real cpu fault */
    tb = tb_find_pc(pc);
    if (tb) {
        /* the PC is inside the translated code. It means that we have
           a virtual CPU fault */
        cpu_restore_state(tb, env, pc, puc);
    }
    /* we restore the process signal mask as the sigreturn should
       do it (XXX: use sigsetjmp) */
    sigprocmask(SIG_SETMASK, old_set, NULL);
    cpu_loop_exit();
A
aurel32 已提交
916 917
    /* never comes here */
    return 1;
918
}
919 920
#elif defined (TARGET_PPC)
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
921 922
                                    int is_write, sigset_t *old_set,
                                    void *puc)
923 924
{
    TranslationBlock *tb;
925
    int ret;
926

927 928 929
    if (cpu_single_env)
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
930
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
931 932 933
           pc, address, is_write, *(unsigned long *)old_set);
#endif
    /* XXX: locking issue */
934
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
935 936 937
        return 1;
    }

938
    /* see if it is an MMU fault */
939
    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
940 941 942 943 944
    if (ret < 0)
        return 0; /* not an MMU fault */
    if (ret == 0)
        return 1; /* the MMU fault was handled without causing real CPU fault */

945 946 947 948 949
    /* now we have a real cpu fault */
    tb = tb_find_pc(pc);
    if (tb) {
        /* the PC is inside the translated code. It means that we have
           a virtual CPU fault */
950
        cpu_restore_state(tb, env, pc, puc);
951
    }
952
    if (ret == 1) {
953
#if 0
954
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
955
               env->nip, env->error_code, tb);
956 957 958
#endif
    /* we restore the process signal mask as the sigreturn should
       do it (XXX: use sigsetjmp) */
959
        sigprocmask(SIG_SETMASK, old_set, NULL);
A
aurel32 已提交
960
        cpu_loop_exit();
961 962
    } else {
        /* activate soft MMU for this block */
963
        cpu_resume_from_signal(env, puc);
964
    }
965
    /* never comes here */
P
pbrook 已提交
966 967 968 969 970 971 972 973 974 975 976 977 978 979
    return 1;
}

#elif defined(TARGET_M68K)
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                                    int is_write, sigset_t *old_set,
                                    void *puc)
{
    TranslationBlock *tb;
    int ret;

    if (cpu_single_env)
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
980
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
P
pbrook 已提交
981 982 983 984 985 986 987
           pc, address, is_write, *(unsigned long *)old_set);
#endif
    /* XXX: locking issue */
    if (is_write && page_unprotect(address, pc, puc)) {
        return 1;
    }
    /* see if it is an MMU fault */
988
    ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
P
pbrook 已提交
989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004
    if (ret < 0)
        return 0; /* not an MMU fault */
    if (ret == 0)
        return 1; /* the MMU fault was handled without causing real CPU fault */
    /* now we have a real cpu fault */
    tb = tb_find_pc(pc);
    if (tb) {
        /* the PC is inside the translated code. It means that we have
           a virtual CPU fault */
        cpu_restore_state(tb, env, pc, puc);
    }
    /* we restore the process signal mask as the sigreturn should
       do it (XXX: use sigsetjmp) */
    sigprocmask(SIG_SETMASK, old_set, NULL);
    cpu_loop_exit();
    /* never comes here */
1005 1006
    return 1;
}
B
bellard 已提交
1007 1008 1009 1010 1011 1012 1013 1014

#elif defined (TARGET_MIPS)
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                                    int is_write, sigset_t *old_set,
                                    void *puc)
{
    TranslationBlock *tb;
    int ret;
1015

B
bellard 已提交
1016 1017 1018
    if (cpu_single_env)
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
1019
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
B
bellard 已提交
1020 1021 1022
           pc, address, is_write, *(unsigned long *)old_set);
#endif
    /* XXX: locking issue */
1023
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
B
bellard 已提交
1024 1025 1026 1027
        return 1;
    }

    /* see if it is an MMU fault */
1028
    ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
B
bellard 已提交
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042
    if (ret < 0)
        return 0; /* not an MMU fault */
    if (ret == 0)
        return 1; /* the MMU fault was handled without causing real CPU fault */

    /* now we have a real cpu fault */
    tb = tb_find_pc(pc);
    if (tb) {
        /* the PC is inside the translated code. It means that we have
           a virtual CPU fault */
        cpu_restore_state(tb, env, pc, puc);
    }
    if (ret == 1) {
#if 0
1043
        printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
T
ths 已提交
1044
               env->PC, env->error_code, tb);
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
#endif
    /* we restore the process signal mask as the sigreturn should
       do it (XXX: use sigsetjmp) */
        sigprocmask(SIG_SETMASK, old_set, NULL);
        cpu_loop_exit();
    } else {
        /* activate soft MMU for this block */
        cpu_resume_from_signal(env, puc);
    }
    /* never comes here */
    return 1;
}

#elif defined (TARGET_MICROBLAZE)
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                                    int is_write, sigset_t *old_set,
                                    void *puc)
{
    TranslationBlock *tb;
    int ret;

    if (cpu_single_env)
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
           pc, address, is_write, *(unsigned long *)old_set);
#endif
    /* XXX: locking issue */
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
        return 1;
    }

    /* see if it is an MMU fault */
    ret = cpu_mb_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
    if (ret < 0)
        return 0; /* not an MMU fault */
    if (ret == 0)
        return 1; /* the MMU fault was handled without causing real CPU fault */

    /* now we have a real cpu fault */
    tb = tb_find_pc(pc);
    if (tb) {
        /* the PC is inside the translated code. It means that we have
           a virtual CPU fault */
        cpu_restore_state(tb, env, pc, puc);
    }
    if (ret == 1) {
#if 0
        printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
               env->PC, env->error_code, tb);
B
bellard 已提交
1095 1096 1097 1098
#endif
    /* we restore the process signal mask as the sigreturn should
       do it (XXX: use sigsetjmp) */
        sigprocmask(SIG_SETMASK, old_set, NULL);
1099
        cpu_loop_exit();
B
bellard 已提交
1100 1101 1102 1103 1104 1105 1106 1107
    } else {
        /* activate soft MMU for this block */
        cpu_resume_from_signal(env, puc);
    }
    /* never comes here */
    return 1;
}

B
bellard 已提交
1108 1109 1110 1111 1112 1113 1114
#elif defined (TARGET_SH4)
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                                    int is_write, sigset_t *old_set,
                                    void *puc)
{
    TranslationBlock *tb;
    int ret;
1115

B
bellard 已提交
1116 1117 1118
    if (cpu_single_env)
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
1119
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
B
bellard 已提交
1120 1121 1122 1123 1124 1125 1126 1127
           pc, address, is_write, *(unsigned long *)old_set);
#endif
    /* XXX: locking issue */
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
        return 1;
    }

    /* see if it is an MMU fault */
1128
    ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
B
bellard 已提交
1129 1130 1131 1132 1133 1134
    if (ret < 0)
        return 0; /* not an MMU fault */
    if (ret == 0)
        return 1; /* the MMU fault was handled without causing real CPU fault */

    /* now we have a real cpu fault */
J
j_mayer 已提交
1135 1136 1137 1138 1139 1140 1141
    tb = tb_find_pc(pc);
    if (tb) {
        /* the PC is inside the translated code. It means that we have
           a virtual CPU fault */
        cpu_restore_state(tb, env, pc, puc);
    }
#if 0
1142
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
J
j_mayer 已提交
1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159
               env->nip, env->error_code, tb);
#endif
    /* we restore the process signal mask as the sigreturn should
       do it (XXX: use sigsetjmp) */
    sigprocmask(SIG_SETMASK, old_set, NULL);
    cpu_loop_exit();
    /* never comes here */
    return 1;
}

#elif defined (TARGET_ALPHA)
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                                    int is_write, sigset_t *old_set,
                                    void *puc)
{
    TranslationBlock *tb;
    int ret;
1160

J
j_mayer 已提交
1161 1162 1163
    if (cpu_single_env)
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
1164
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
J
j_mayer 已提交
1165 1166 1167 1168 1169 1170 1171 1172
           pc, address, is_write, *(unsigned long *)old_set);
#endif
    /* XXX: locking issue */
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
        return 1;
    }

    /* see if it is an MMU fault */
1173
    ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
J
j_mayer 已提交
1174 1175 1176 1177 1178 1179
    if (ret < 0)
        return 0; /* not an MMU fault */
    if (ret == 0)
        return 1; /* the MMU fault was handled without causing real CPU fault */

    /* now we have a real cpu fault */
B
bellard 已提交
1180 1181 1182 1183 1184 1185 1186
    tb = tb_find_pc(pc);
    if (tb) {
        /* the PC is inside the translated code. It means that we have
           a virtual CPU fault */
        cpu_restore_state(tb, env, pc, puc);
    }
#if 0
1187
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
B
bellard 已提交
1188 1189 1190 1191
               env->nip, env->error_code, tb);
#endif
    /* we restore the process signal mask as the sigreturn should
       do it (XXX: use sigsetjmp) */
P
pbrook 已提交
1192 1193
    sigprocmask(SIG_SETMASK, old_set, NULL);
    cpu_loop_exit();
B
bellard 已提交
1194 1195 1196
    /* never comes here */
    return 1;
}
1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216
#elif defined (TARGET_CRIS)
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                                    int is_write, sigset_t *old_set,
                                    void *puc)
{
    TranslationBlock *tb;
    int ret;

    if (cpu_single_env)
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
           pc, address, is_write, *(unsigned long *)old_set);
#endif
    /* XXX: locking issue */
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
        return 1;
    }

    /* see if it is an MMU fault */
1217
    ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237
    if (ret < 0)
        return 0; /* not an MMU fault */
    if (ret == 0)
        return 1; /* the MMU fault was handled without causing real CPU fault */

    /* now we have a real cpu fault */
    tb = tb_find_pc(pc);
    if (tb) {
        /* the PC is inside the translated code. It means that we have
           a virtual CPU fault */
        cpu_restore_state(tb, env, pc, puc);
    }
    /* we restore the process signal mask as the sigreturn should
       do it (XXX: use sigsetjmp) */
    sigprocmask(SIG_SETMASK, old_set, NULL);
    cpu_loop_exit();
    /* never comes here */
    return 1;
}

B
bellard 已提交
1238 1239 1240
#else
#error unsupported target CPU
#endif
B
bellard 已提交
1241

B
bellard 已提交
1242 1243
#if defined(__i386__)

1244 1245 1246 1247 1248 1249
#if defined(__APPLE__)
# include <sys/ucontext.h>

# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
1250 1251 1252 1253 1254 1255
# define MASK_sig(context)    ((context)->uc_sigmask)
#elif defined(__OpenBSD__)
# define EIP_sig(context)     ((context)->sc_eip)
# define TRAP_sig(context)    ((context)->sc_trapno)
# define ERROR_sig(context)   ((context)->sc_err)
# define MASK_sig(context)    ((context)->sc_mask)
1256 1257 1258 1259
#else
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
1260
# define MASK_sig(context)    ((context)->uc_sigmask)
1261 1262
#endif

1263
int cpu_signal_handler(int host_signum, void *pinfo,
B
bellard 已提交
1264
                       void *puc)
B
bellard 已提交
1265
{
1266
    siginfo_t *info = pinfo;
1267 1268 1269
#if defined(__OpenBSD__)
    struct sigcontext *uc = puc;
#else
B
bellard 已提交
1270
    struct ucontext *uc = puc;
1271
#endif
B
bellard 已提交
1272
    unsigned long pc;
1273
    int trapno;
B
bellard 已提交
1274

1275 1276
#ifndef REG_EIP
/* for glibc 2.1 */
B
bellard 已提交
1277 1278 1279
#define REG_EIP    EIP
#define REG_ERR    ERR
#define REG_TRAPNO TRAPNO
1280
#endif
1281 1282
    pc = EIP_sig(uc);
    trapno = TRAP_sig(uc);
B
bellard 已提交
1283 1284 1285
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                             trapno == 0xe ?
                             (ERROR_sig(uc) >> 1) & 1 : 0,
1286
                             &MASK_sig(uc), puc);
B
bellard 已提交
1287 1288
}

1289 1290
#elif defined(__x86_64__)

1291
#ifdef __NetBSD__
1292 1293 1294 1295 1296 1297 1298 1299 1300
#define PC_sig(context)       _UC_MACHINE_PC(context)
#define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
#define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
#define MASK_sig(context)     ((context)->uc_sigmask)
#elif defined(__OpenBSD__)
#define PC_sig(context)       ((context)->sc_rip)
#define TRAP_sig(context)     ((context)->sc_trapno)
#define ERROR_sig(context)    ((context)->sc_err)
#define MASK_sig(context)     ((context)->sc_mask)
1301
#else
1302 1303 1304 1305
#define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
#define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
#define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
#define MASK_sig(context)     ((context)->uc_sigmask)
1306 1307
#endif

1308
int cpu_signal_handler(int host_signum, void *pinfo,
1309 1310
                       void *puc)
{
1311
    siginfo_t *info = pinfo;
1312
    unsigned long pc;
1313 1314
#ifdef __NetBSD__
    ucontext_t *uc = puc;
1315 1316
#elif defined(__OpenBSD__)
    struct sigcontext *uc = puc;
1317 1318 1319
#else
    struct ucontext *uc = puc;
#endif
1320

1321
    pc = PC_sig(uc);
1322
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1323 1324 1325
                             TRAP_sig(uc) == 0xe ?
                             (ERROR_sig(uc) >> 1) & 1 : 0,
                             &MASK_sig(uc), puc);
1326 1327
}

M
malc 已提交
1328
#elif defined(_ARCH_PPC)
B
bellard 已提交
1329

1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378
/***********************************************************************
 * signal context platform-specific definitions
 * From Wine
 */
#ifdef linux
/* All Registers access - only for local access */
# define REG_sig(reg_name, context)		((context)->uc_mcontext.regs->reg_name)
/* Gpr Registers access  */
# define GPR_sig(reg_num, context)		REG_sig(gpr[reg_num], context)
# define IAR_sig(context)			REG_sig(nip, context)	/* Program counter */
# define MSR_sig(context)			REG_sig(msr, context)   /* Machine State Register (Supervisor) */
# define CTR_sig(context)			REG_sig(ctr, context)   /* Count register */
# define XER_sig(context)			REG_sig(xer, context) /* User's integer exception register */
# define LR_sig(context)			REG_sig(link, context) /* Link register */
# define CR_sig(context)			REG_sig(ccr, context) /* Condition register */
/* Float Registers access  */
# define FLOAT_sig(reg_num, context)		(((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
# define FPSCR_sig(context)			(*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
/* Exception Registers access */
# define DAR_sig(context)			REG_sig(dar, context)
# define DSISR_sig(context)			REG_sig(dsisr, context)
# define TRAP_sig(context)			REG_sig(trap, context)
#endif /* linux */

#ifdef __APPLE__
# include <sys/ucontext.h>
typedef struct ucontext SIGCONTEXT;
/* All Registers access - only for local access */
# define REG_sig(reg_name, context)		((context)->uc_mcontext->ss.reg_name)
# define FLOATREG_sig(reg_name, context)	((context)->uc_mcontext->fs.reg_name)
# define EXCEPREG_sig(reg_name, context)	((context)->uc_mcontext->es.reg_name)
# define VECREG_sig(reg_name, context)		((context)->uc_mcontext->vs.reg_name)
/* Gpr Registers access */
# define GPR_sig(reg_num, context)		REG_sig(r##reg_num, context)
# define IAR_sig(context)			REG_sig(srr0, context)	/* Program counter */
# define MSR_sig(context)			REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
# define CTR_sig(context)			REG_sig(ctr, context)
# define XER_sig(context)			REG_sig(xer, context) /* Link register */
# define LR_sig(context)			REG_sig(lr, context)  /* User's integer exception register */
# define CR_sig(context)			REG_sig(cr, context)  /* Condition register */
/* Float Registers access */
# define FLOAT_sig(reg_num, context)		FLOATREG_sig(fpregs[reg_num], context)
# define FPSCR_sig(context)			((double)FLOATREG_sig(fpscr, context))
/* Exception Registers access */
# define DAR_sig(context)			EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
# define DSISR_sig(context)			EXCEPREG_sig(dsisr, context)
# define TRAP_sig(context)			EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
#endif /* __APPLE__ */

1379
int cpu_signal_handler(int host_signum, void *pinfo,
B
bellard 已提交
1380
                       void *puc)
B
bellard 已提交
1381
{
1382
    siginfo_t *info = pinfo;
1383 1384 1385 1386
    struct ucontext *uc = puc;
    unsigned long pc;
    int is_write;

1387
    pc = IAR_sig(uc);
1388 1389 1390
    is_write = 0;
#if 0
    /* ppc 4xx case */
1391
    if (DSISR_sig(uc) & 0x00800000)
1392 1393
        is_write = 1;
#else
1394
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1395 1396
        is_write = 1;
#endif
1397
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1398
                             is_write, &uc->uc_sigmask, puc);
B
bellard 已提交
1399 1400
}

B
bellard 已提交
1401 1402
#elif defined(__alpha__)

1403
int cpu_signal_handler(int host_signum, void *pinfo,
B
bellard 已提交
1404 1405
                           void *puc)
{
1406
    siginfo_t *info = pinfo;
B
bellard 已提交
1407 1408 1409 1410 1411
    struct ucontext *uc = puc;
    uint32_t *pc = uc->uc_mcontext.sc_pc;
    uint32_t insn = *pc;
    int is_write = 0;

1412
    /* XXX: need kernel patch to get write flag faster */
B
bellard 已提交
1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427
    switch (insn >> 26) {
    case 0x0d: // stw
    case 0x0e: // stb
    case 0x0f: // stq_u
    case 0x24: // stf
    case 0x25: // stg
    case 0x26: // sts
    case 0x27: // stt
    case 0x2c: // stl
    case 0x2d: // stq
    case 0x2e: // stl_c
    case 0x2f: // stq_c
	is_write = 1;
    }

1428
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1429
                             is_write, &uc->uc_sigmask, puc);
B
bellard 已提交
1430
}
1431 1432
#elif defined(__sparc__)

1433
int cpu_signal_handler(int host_signum, void *pinfo,
B
bellard 已提交
1434
                       void *puc)
1435
{
1436
    siginfo_t *info = pinfo;
1437 1438
    int is_write;
    uint32_t insn;
1439
#if !defined(__arch64__) || defined(HOST_SOLARIS)
B
blueswir1 已提交
1440 1441
    uint32_t *regs = (uint32_t *)(info + 1);
    void *sigmask = (regs + 20);
1442
    /* XXX: is there a standard glibc define ? */
B
blueswir1 已提交
1443 1444
    unsigned long pc = regs[1];
#else
B
blueswir1 已提交
1445
#ifdef __linux__
B
blueswir1 已提交
1446 1447 1448
    struct sigcontext *sc = puc;
    unsigned long pc = sc->sigc_regs.tpc;
    void *sigmask = (void *)sc->sigc_mask;
B
blueswir1 已提交
1449 1450 1451 1452 1453
#elif defined(__OpenBSD__)
    struct sigcontext *uc = puc;
    unsigned long pc = uc->sc_pc;
    void *sigmask = (void *)(long)uc->sc_mask;
#endif
B
blueswir1 已提交
1454 1455
#endif

1456 1457 1458 1459 1460 1461
    /* XXX: need kernel patch to get write flag faster */
    is_write = 0;
    insn = *(uint32_t *)pc;
    if ((insn >> 30) == 3) {
      switch((insn >> 19) & 0x3f) {
      case 0x05: // stb
1462
      case 0x15: // stba
1463
      case 0x06: // sth
1464
      case 0x16: // stha
1465
      case 0x04: // st
1466
      case 0x14: // sta
1467
      case 0x07: // std
1468 1469 1470
      case 0x17: // stda
      case 0x0e: // stx
      case 0x1e: // stxa
1471
      case 0x24: // stf
1472
      case 0x34: // stfa
1473
      case 0x27: // stdf
1474 1475 1476
      case 0x37: // stdfa
      case 0x26: // stqf
      case 0x36: // stqfa
1477
      case 0x25: // stfsr
1478 1479
      case 0x3c: // casa
      case 0x3e: // casxa
1480 1481 1482 1483
	is_write = 1;
	break;
      }
    }
1484
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1485
                             is_write, sigmask, NULL);
1486 1487 1488 1489
}

#elif defined(__arm__)

1490
int cpu_signal_handler(int host_signum, void *pinfo,
B
bellard 已提交
1491
                       void *puc)
1492
{
1493
    siginfo_t *info = pinfo;
1494 1495 1496
    struct ucontext *uc = puc;
    unsigned long pc;
    int is_write;
1497

1498
#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1499 1500
    pc = uc->uc_mcontext.gregs[R15];
#else
1501
    pc = uc->uc_mcontext.arm_pc;
1502
#endif
1503 1504
    /* XXX: compute is_write */
    is_write = 0;
1505
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1506
                             is_write,
P
pbrook 已提交
1507
                             &uc->uc_sigmask, puc);
1508 1509
}

B
bellard 已提交
1510 1511
#elif defined(__mc68000)

1512
int cpu_signal_handler(int host_signum, void *pinfo,
B
bellard 已提交
1513 1514
                       void *puc)
{
1515
    siginfo_t *info = pinfo;
B
bellard 已提交
1516 1517 1518
    struct ucontext *uc = puc;
    unsigned long pc;
    int is_write;
1519

B
bellard 已提交
1520 1521 1522
    pc = uc->uc_mcontext.gregs[16];
    /* XXX: compute is_write */
    is_write = 0;
1523
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
B
bellard 已提交
1524
                             is_write,
1525
                             &uc->uc_sigmask, puc);
B
bellard 已提交
1526 1527
}

B
bellard 已提交
1528 1529 1530 1531 1532 1533 1534
#elif defined(__ia64)

#ifndef __ISR_VALID
  /* This ought to be in <bits/siginfo.h>... */
# define __ISR_VALID	1
#endif

1535
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
B
bellard 已提交
1536
{
1537
    siginfo_t *info = pinfo;
B
bellard 已提交
1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548
    struct ucontext *uc = puc;
    unsigned long ip;
    int is_write = 0;

    ip = uc->uc_mcontext.sc_ip;
    switch (host_signum) {
      case SIGILL:
      case SIGFPE:
      case SIGSEGV:
      case SIGBUS:
      case SIGTRAP:
B
bellard 已提交
1549
	  if (info->si_code && (info->si_segvflags & __ISR_VALID))
B
bellard 已提交
1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561
	      /* ISR.W (write-access) is bit 33:  */
	      is_write = (info->si_isr >> 33) & 1;
	  break;

      default:
	  break;
    }
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
                             is_write,
                             &uc->uc_sigmask, puc);
}

B
bellard 已提交
1562 1563
#elif defined(__s390__)

1564
int cpu_signal_handler(int host_signum, void *pinfo,
B
bellard 已提交
1565 1566
                       void *puc)
{
1567
    siginfo_t *info = pinfo;
B
bellard 已提交
1568 1569 1570
    struct ucontext *uc = puc;
    unsigned long pc;
    int is_write;
1571

B
bellard 已提交
1572 1573 1574
    pc = uc->uc_mcontext.psw.addr;
    /* XXX: compute is_write */
    is_write = 0;
1575
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1576 1577 1578 1579 1580
                             is_write, &uc->uc_sigmask, puc);
}

#elif defined(__mips__)

1581
int cpu_signal_handler(int host_signum, void *pinfo,
1582 1583
                       void *puc)
{
T
ths 已提交
1584
    siginfo_t *info = pinfo;
1585 1586 1587
    struct ucontext *uc = puc;
    greg_t pc = uc->uc_mcontext.pc;
    int is_write;
1588

1589 1590
    /* XXX: compute is_write */
    is_write = 0;
1591
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1592
                             is_write, &uc->uc_sigmask, puc);
B
bellard 已提交
1593 1594
}

A
aurel32 已提交
1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612
#elif defined(__hppa__)

int cpu_signal_handler(int host_signum, void *pinfo,
                       void *puc)
{
    struct siginfo *info = pinfo;
    struct ucontext *uc = puc;
    unsigned long pc;
    int is_write;

    pc = uc->uc_mcontext.sc_iaoq[0];
    /* FIXME: compute is_write */
    is_write = 0;
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                             is_write,
                             &uc->uc_sigmask, puc);
}

B
bellard 已提交
1613
#else
B
bellard 已提交
1614

1615
#error host CPU specific signal handler needed
B
bellard 已提交
1616

B
bellard 已提交
1617
#endif
B
bellard 已提交
1618 1619

#endif /* !defined(CONFIG_SOFTMMU) */