Statistics
| Branch: | Revision:

root / cpu-exec.c @ f57040be

History | View | Annotate | Download (42.9 kB)

1
/*
2
 *  i386 emulator main execution loop
3
 *
4
 *  Copyright (c) 2003-2005 Fabrice Bellard
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
#include "config.h"
20
#include "exec.h"
21
#include "disas.h"
22
#include "tcg.h"
23
#include "kvm.h"
24

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

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

    
47
int tb_invalidated_flag;
48

    
49
//#define CONFIG_DEBUG_EXEC
50
//#define DEBUG_SIGNAL
51

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

    
57
void cpu_loop_exit(void)
58
{
59
    env->current_tb = NULL;
60
    longjmp(env->jmp_env, 1);
61
}
62

    
63
/* exit the current TB from a signal handler. The host registers are
64
   restored in a state compatible with the CPU emulator
65
 */
66
void cpu_resume_from_signal(CPUState *env1, void *puc)
67
{
68
#if !defined(CONFIG_SOFTMMU)
69
#ifdef __linux__
70
    struct ucontext *uc = puc;
71
#elif defined(__OpenBSD__)
72
    struct sigcontext *uc = puc;
73
#endif
74
#endif
75

    
76
    env = env1;
77

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

    
80
#if !defined(CONFIG_SOFTMMU)
81
    if (puc) {
82
        /* XXX: use siglongjmp ? */
83
#ifdef __linux__
84
#ifdef __ia64
85
        sigprocmask(SIG_SETMASK, (sigset_t *)&uc->uc_sigmask, NULL);
86
#else
87
        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
88
#endif
89
#elif defined(__OpenBSD__)
90
        sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
91
#endif
92
    }
93
#endif
94
    env->exception_index = -1;
95
    longjmp(env->jmp_env, 1);
96
}
97

    
98
/* Execute the code without caching the generated code. An interpreter
99
   could be used if available. */
100
static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
101
{
102
    unsigned long next_tb;
103
    TranslationBlock *tb;
104

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

    
110
    tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
111
                     max_cycles);
112
    env->current_tb = tb;
113
    /* execute the generated code */
114
    next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
115
    env->current_tb = NULL;
116

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

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

    
135
    tb_invalidated_flag = 0;
136

    
137
    /* find translated block using physical mappings */
138
    phys_pc = get_page_addr_code(env, pc);
139
    phys_page1 = phys_pc & TARGET_PAGE_MASK;
140
    phys_page2 = -1;
141
    h = tb_phys_hash_func(phys_pc);
142
    ptb1 = &tb_phys_hash[h];
143
    for(;;) {
144
        tb = *ptb1;
145
        if (!tb)
146
            goto not_found;
147
        if (tb->pc == pc &&
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) +
154
                    TARGET_PAGE_SIZE;
155
                phys_page2 = get_page_addr_code(env, virt_page2);
156
                if (tb->page_addr[1] == phys_page2)
157
                    goto found;
158
            } else {
159
                goto found;
160
            }
161
        }
162
        ptb1 = &tb->phys_hash_next;
163
    }
164
 not_found:
165
   /* if no translated code available, then translate it now */
166
    tb = tb_gen_code(env, pc, cs_base, flags, 0);
167

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

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

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

    
192
static CPUDebugExcpHandler *debug_excp_handler;
193

    
194
CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
195
{
196
    CPUDebugExcpHandler *old_handler = debug_excp_handler;
197

    
198
    debug_excp_handler = handler;
199
    return old_handler;
200
}
201

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

    
206
    if (!env->watchpoint_hit)
207
        QTAILQ_FOREACH(wp, &env->watchpoints, entry)
208
            wp->flags &= ~BP_WATCHPOINT_HIT;
209

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

    
214
/* main execution loop */
215

    
216
int cpu_exec(CPUState *env1)
217
{
218
    volatile host_reg_t saved_env_reg;
219
    int ret, interrupt_request;
220
    TranslationBlock *tb;
221
    uint8_t *tc_ptr;
222
    unsigned long next_tb;
223

    
224
    if (cpu_halted(env1) == EXCP_HALTED)
225
        return EXCP_HALTED;
226

    
227
    cpu_single_env = env1;
228

    
229
    /* the access to env below is actually saving the global register's
230
       value, so that files not including target-xyz/exec.h are free to
231
       use it.  */
232
    QEMU_BUILD_BUG_ON (sizeof (saved_env_reg) != sizeof (env));
233
    saved_env_reg = (host_reg_t) env;
234
    asm("");
235
    env = env1;
236

    
237
#if defined(TARGET_I386)
238
    if (!kvm_enabled()) {
239
        /* put eflags in CPU temporary format */
240
        CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
241
        DF = 1 - (2 * ((env->eflags >> 10) & 1));
242
        CC_OP = CC_OP_EFLAGS;
243
        env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
244
    }
245
#elif defined(TARGET_SPARC)
246
#elif defined(TARGET_M68K)
247
    env->cc_op = CC_OP_FLAGS;
248
    env->cc_dest = env->sr & 0xf;
249
    env->cc_x = (env->sr >> 4) & 1;
250
#elif defined(TARGET_ALPHA)
251
#elif defined(TARGET_ARM)
252
#elif defined(TARGET_PPC)
253
#elif defined(TARGET_MICROBLAZE)
254
#elif defined(TARGET_MIPS)
255
#elif defined(TARGET_SH4)
256
#elif defined(TARGET_CRIS)
257
#elif defined(TARGET_S390X)
258
    /* XXXXX */
259
#else
260
#error unsupported target CPU
261
#endif
262
    env->exception_index = -1;
263

    
264
    /* prepare setjmp context for exception handling */
265
    for(;;) {
266
        if (setjmp(env->jmp_env) == 0) {
267
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
268
#undef env
269
                    env = cpu_single_env;
270
#define env cpu_single_env
271
#endif
272
            /* if an exception is pending, we execute it here */
273
            if (env->exception_index >= 0) {
274
                if (env->exception_index >= EXCP_INTERRUPT) {
275
                    /* exit request from the cpu execution loop */
276
                    ret = env->exception_index;
277
                    if (ret == EXCP_DEBUG)
278
                        cpu_handle_debug_exception(env);
279
                    break;
280
                } else {
281
#if defined(CONFIG_USER_ONLY)
282
                    /* if user mode only, we simulate a fake exception
283
                       which will be handled outside the cpu execution
284
                       loop */
285
#if defined(TARGET_I386)
286
                    do_interrupt_user(env->exception_index,
287
                                      env->exception_is_int,
288
                                      env->error_code,
289
                                      env->exception_next_eip);
290
                    /* successfully delivered */
291
                    env->old_exception = -1;
292
#endif
293
                    ret = env->exception_index;
294
                    break;
295
#else
296
#if defined(TARGET_I386)
297
                    /* simulate a real cpu exception. On i386, it can
298
                       trigger new exceptions, but we do not handle
299
                       double or triple faults yet. */
300
                    do_interrupt(env->exception_index,
301
                                 env->exception_is_int,
302
                                 env->error_code,
303
                                 env->exception_next_eip, 0);
304
                    /* successfully delivered */
305
                    env->old_exception = -1;
306
#elif defined(TARGET_PPC)
307
                    do_interrupt(env);
308
#elif defined(TARGET_MICROBLAZE)
309
                    do_interrupt(env);
310
#elif defined(TARGET_MIPS)
311
                    do_interrupt(env);
312
#elif defined(TARGET_SPARC)
313
                    do_interrupt(env);
314
#elif defined(TARGET_ARM)
315
                    do_interrupt(env);
316
#elif defined(TARGET_SH4)
317
                    do_interrupt(env);
318
#elif defined(TARGET_ALPHA)
319
                    do_interrupt(env);
320
#elif defined(TARGET_CRIS)
321
                    do_interrupt(env);
322
#elif defined(TARGET_M68K)
323
                    do_interrupt(0);
324
#endif
325
                    env->exception_index = -1;
326
#endif
327
                }
328
            }
329

    
330
            if (kvm_enabled()) {
331
                kvm_cpu_exec(env);
332
                longjmp(env->jmp_env, 1);
333
            }
334

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

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

    
607
                /* cpu_interrupt might be called while translating the
608
                   TB, but before it is linked into a potentially
609
                   infinite loop and becomes env->current_tb. Avoid
610
                   starting execution if there is a pending interrupt. */
611
                if (!unlikely (env->exit_request)) {
612
                    env->current_tb = tb;
613
                    tc_ptr = tb->tc_ptr;
614
                /* execute the generated code */
615
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
616
#undef env
617
                    env = cpu_single_env;
618
#define env cpu_single_env
619
#endif
620
                    next_tb = tcg_qemu_tb_exec(tc_ptr);
621
                    env->current_tb = NULL;
622
                    if ((next_tb & 3) == 2) {
623
                        /* Instruction counter expired.  */
624
                        int insns_left;
625
                        tb = (TranslationBlock *)(long)(next_tb & ~3);
626
                        /* Restore PC.  */
627
                        cpu_pc_from_tb(env, tb);
628
                        insns_left = env->icount_decr.u32;
629
                        if (env->icount_extra && insns_left >= 0) {
630
                            /* Refill decrementer and continue execution.  */
631
                            env->icount_extra += insns_left;
632
                            if (env->icount_extra > 0xffff) {
633
                                insns_left = 0xffff;
634
                            } else {
635
                                insns_left = env->icount_extra;
636
                            }
637
                            env->icount_extra -= insns_left;
638
                            env->icount_decr.u16.low = insns_left;
639
                        } else {
640
                            if (insns_left > 0) {
641
                                /* Execute remaining instructions.  */
642
                                cpu_exec_nocache(insns_left, tb);
643
                            }
644
                            env->exception_index = EXCP_INTERRUPT;
645
                            next_tb = 0;
646
                            cpu_loop_exit();
647
                        }
648
                    }
649
                }
650
                /* reset soft MMU for next block (it can currently
651
                   only be set by a memory fault) */
652
            } /* for(;;) */
653
        }
654
    } /* for(;;) */
655

    
656

    
657
#if defined(TARGET_I386)
658
    /* restore flags in standard format */
659
    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
660
#elif defined(TARGET_ARM)
661
    /* XXX: Save/restore host fpu exception state?.  */
662
#elif defined(TARGET_SPARC)
663
#elif defined(TARGET_PPC)
664
#elif defined(TARGET_M68K)
665
    cpu_m68k_flush_flags(env, env->cc_op);
666
    env->cc_op = CC_OP_FLAGS;
667
    env->sr = (env->sr & 0xffe0)
668
              | env->cc_dest | (env->cc_x << 4);
669
#elif defined(TARGET_MICROBLAZE)
670
#elif defined(TARGET_MIPS)
671
#elif defined(TARGET_SH4)
672
#elif defined(TARGET_ALPHA)
673
#elif defined(TARGET_CRIS)
674
#elif defined(TARGET_S390X)
675
    /* XXXXX */
676
#else
677
#error unsupported target CPU
678
#endif
679

    
680
    /* restore global registers */
681
    asm("");
682
    env = (void *) saved_env_reg;
683

    
684
    /* fail safe : never use cpu_single_env outside cpu_exec() */
685
    cpu_single_env = NULL;
686
    return ret;
687
}
688

    
689
/* must only be called from the generated code as an exception can be
690
   generated */
691
void tb_invalidate_page_range(target_ulong start, target_ulong end)
692
{
693
    /* XXX: cannot enable it yet because it yields to MMU exception
694
       where NIP != read address on PowerPC */
695
#if 0
696
    target_ulong phys_addr;
697
    phys_addr = get_phys_addr_code(env, start);
698
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
699
#endif
700
}
701

    
702
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
703

    
704
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
705
{
706
    CPUX86State *saved_env;
707

    
708
    saved_env = env;
709
    env = s;
710
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
711
        selector &= 0xffff;
712
        cpu_x86_load_seg_cache(env, seg_reg, selector,
713
                               (selector << 4), 0xffff, 0);
714
    } else {
715
        helper_load_seg(seg_reg, selector);
716
    }
717
    env = saved_env;
718
}
719

    
720
void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
721
{
722
    CPUX86State *saved_env;
723

    
724
    saved_env = env;
725
    env = s;
726

    
727
    helper_fsave(ptr, data32);
728

    
729
    env = saved_env;
730
}
731

    
732
void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
733
{
734
    CPUX86State *saved_env;
735

    
736
    saved_env = env;
737
    env = s;
738

    
739
    helper_frstor(ptr, data32);
740

    
741
    env = saved_env;
742
}
743

    
744
#endif /* TARGET_I386 */
745

    
746
#if !defined(CONFIG_SOFTMMU)
747

    
748
#if defined(TARGET_I386)
749
#define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code)
750
#else
751
#define EXCEPTION_ACTION cpu_loop_exit()
752
#endif
753

    
754
/* 'pc' is the host PC at which the exception was raised. 'address' is
755
   the effective address of the memory exception. 'is_write' is 1 if a
756
   write caused the exception and otherwise 0'. 'old_set' is the
757
   signal set which should be restored */
758
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
759
                                    int is_write, sigset_t *old_set,
760
                                    void *puc)
761
{
762
    TranslationBlock *tb;
763
    int ret;
764

    
765
    if (cpu_single_env)
766
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
767
#if defined(DEBUG_SIGNAL)
768
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
769
                pc, address, is_write, *(unsigned long *)old_set);
770
#endif
771
    /* XXX: locking issue */
772
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
773
        return 1;
774
    }
775

    
776
    /* see if it is an MMU fault */
777
    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
778
    if (ret < 0)
779
        return 0; /* not an MMU fault */
780
    if (ret == 0)
781
        return 1; /* the MMU fault was handled without causing real CPU fault */
782
    /* now we have a real cpu fault */
783
    tb = tb_find_pc(pc);
784
    if (tb) {
785
        /* the PC is inside the translated code. It means that we have
786
           a virtual CPU fault */
787
        cpu_restore_state(tb, env, pc, puc);
788
    }
789

    
790
    /* we restore the process signal mask as the sigreturn should
791
       do it (XXX: use sigsetjmp) */
792
    sigprocmask(SIG_SETMASK, old_set, NULL);
793
    EXCEPTION_ACTION;
794

    
795
    /* never comes here */
796
    return 1;
797
}
798

    
799
#if defined(__i386__)
800

    
801
#if defined(__APPLE__)
802
# include <sys/ucontext.h>
803

    
804
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
805
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
806
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
807
# define MASK_sig(context)    ((context)->uc_sigmask)
808
#elif defined (__NetBSD__)
809
# include <ucontext.h>
810

    
811
# define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
812
# define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
813
# define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
814
# define MASK_sig(context)    ((context)->uc_sigmask)
815
#elif defined (__FreeBSD__) || defined(__DragonFly__)
816
# include <ucontext.h>
817

    
818
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
819
# define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
820
# define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
821
# define MASK_sig(context)    ((context)->uc_sigmask)
822
#elif defined(__OpenBSD__)
823
# define EIP_sig(context)     ((context)->sc_eip)
824
# define TRAP_sig(context)    ((context)->sc_trapno)
825
# define ERROR_sig(context)   ((context)->sc_err)
826
# define MASK_sig(context)    ((context)->sc_mask)
827
#else
828
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
829
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
830
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
831
# define MASK_sig(context)    ((context)->uc_sigmask)
832
#endif
833

    
834
int cpu_signal_handler(int host_signum, void *pinfo,
835
                       void *puc)
836
{
837
    siginfo_t *info = pinfo;
838
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
839
    ucontext_t *uc = puc;
840
#elif defined(__OpenBSD__)
841
    struct sigcontext *uc = puc;
842
#else
843
    struct ucontext *uc = puc;
844
#endif
845
    unsigned long pc;
846
    int trapno;
847

    
848
#ifndef REG_EIP
849
/* for glibc 2.1 */
850
#define REG_EIP    EIP
851
#define REG_ERR    ERR
852
#define REG_TRAPNO TRAPNO
853
#endif
854
    pc = EIP_sig(uc);
855
    trapno = TRAP_sig(uc);
856
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
857
                             trapno == 0xe ?
858
                             (ERROR_sig(uc) >> 1) & 1 : 0,
859
                             &MASK_sig(uc), puc);
860
}
861

    
862
#elif defined(__x86_64__)
863

    
864
#ifdef __NetBSD__
865
#define PC_sig(context)       _UC_MACHINE_PC(context)
866
#define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
867
#define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
868
#define MASK_sig(context)     ((context)->uc_sigmask)
869
#elif defined(__OpenBSD__)
870
#define PC_sig(context)       ((context)->sc_rip)
871
#define TRAP_sig(context)     ((context)->sc_trapno)
872
#define ERROR_sig(context)    ((context)->sc_err)
873
#define MASK_sig(context)     ((context)->sc_mask)
874
#elif defined (__FreeBSD__) || defined(__DragonFly__)
875
#include <ucontext.h>
876

    
877
#define PC_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
878
#define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
879
#define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
880
#define MASK_sig(context)     ((context)->uc_sigmask)
881
#else
882
#define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
883
#define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
884
#define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
885
#define MASK_sig(context)     ((context)->uc_sigmask)
886
#endif
887

    
888
int cpu_signal_handler(int host_signum, void *pinfo,
889
                       void *puc)
890
{
891
    siginfo_t *info = pinfo;
892
    unsigned long pc;
893
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
894
    ucontext_t *uc = puc;
895
#elif defined(__OpenBSD__)
896
    struct sigcontext *uc = puc;
897
#else
898
    struct ucontext *uc = puc;
899
#endif
900

    
901
    pc = PC_sig(uc);
902
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
903
                             TRAP_sig(uc) == 0xe ?
904
                             (ERROR_sig(uc) >> 1) & 1 : 0,
905
                             &MASK_sig(uc), puc);
906
}
907

    
908
#elif defined(_ARCH_PPC)
909

    
910
/***********************************************************************
911
 * signal context platform-specific definitions
912
 * From Wine
913
 */
914
#ifdef linux
915
/* All Registers access - only for local access */
916
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
917
/* Gpr Registers access  */
918
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
919
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
920
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
921
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
922
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
923
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
924
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
925
/* Float Registers access  */
926
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
927
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
928
/* Exception Registers access */
929
# define DAR_sig(context)                        REG_sig(dar, context)
930
# define DSISR_sig(context)                        REG_sig(dsisr, context)
931
# define TRAP_sig(context)                        REG_sig(trap, context)
932
#endif /* linux */
933

    
934
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
935
#include <ucontext.h>
936
# define IAR_sig(context)                ((context)->uc_mcontext.mc_srr0)
937
# define MSR_sig(context)                ((context)->uc_mcontext.mc_srr1)
938
# define CTR_sig(context)                ((context)->uc_mcontext.mc_ctr)
939
# define XER_sig(context)                ((context)->uc_mcontext.mc_xer)
940
# define LR_sig(context)                ((context)->uc_mcontext.mc_lr)
941
# define CR_sig(context)                ((context)->uc_mcontext.mc_cr)
942
/* Exception Registers access */
943
# define DAR_sig(context)                ((context)->uc_mcontext.mc_dar)
944
# define DSISR_sig(context)                ((context)->uc_mcontext.mc_dsisr)
945
# define TRAP_sig(context)                ((context)->uc_mcontext.mc_exc)
946
#endif /* __FreeBSD__|| __FreeBSD_kernel__ */
947

    
948
#ifdef __APPLE__
949
# include <sys/ucontext.h>
950
typedef struct ucontext SIGCONTEXT;
951
/* All Registers access - only for local access */
952
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
953
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
954
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
955
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
956
/* Gpr Registers access */
957
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
958
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
959
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
960
# define CTR_sig(context)                        REG_sig(ctr, context)
961
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
962
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
963
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
964
/* Float Registers access */
965
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
966
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
967
/* Exception Registers access */
968
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
969
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
970
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
971
#endif /* __APPLE__ */
972

    
973
int cpu_signal_handler(int host_signum, void *pinfo,
974
                       void *puc)
975
{
976
    siginfo_t *info = pinfo;
977
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
978
    ucontext_t *uc = puc;
979
#else
980
    struct ucontext *uc = puc;
981
#endif
982
    unsigned long pc;
983
    int is_write;
984

    
985
    pc = IAR_sig(uc);
986
    is_write = 0;
987
#if 0
988
    /* ppc 4xx case */
989
    if (DSISR_sig(uc) & 0x00800000)
990
        is_write = 1;
991
#else
992
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
993
        is_write = 1;
994
#endif
995
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
996
                             is_write, &uc->uc_sigmask, puc);
997
}
998

    
999
#elif defined(__alpha__)
1000

    
1001
int cpu_signal_handler(int host_signum, void *pinfo,
1002
                           void *puc)
1003
{
1004
    siginfo_t *info = pinfo;
1005
    struct ucontext *uc = puc;
1006
    uint32_t *pc = uc->uc_mcontext.sc_pc;
1007
    uint32_t insn = *pc;
1008
    int is_write = 0;
1009

    
1010
    /* XXX: need kernel patch to get write flag faster */
1011
    switch (insn >> 26) {
1012
    case 0x0d: // stw
1013
    case 0x0e: // stb
1014
    case 0x0f: // stq_u
1015
    case 0x24: // stf
1016
    case 0x25: // stg
1017
    case 0x26: // sts
1018
    case 0x27: // stt
1019
    case 0x2c: // stl
1020
    case 0x2d: // stq
1021
    case 0x2e: // stl_c
1022
    case 0x2f: // stq_c
1023
        is_write = 1;
1024
    }
1025

    
1026
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1027
                             is_write, &uc->uc_sigmask, puc);
1028
}
1029
#elif defined(__sparc__)
1030

    
1031
int cpu_signal_handler(int host_signum, void *pinfo,
1032
                       void *puc)
1033
{
1034
    siginfo_t *info = pinfo;
1035
    int is_write;
1036
    uint32_t insn;
1037
#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
1038
    uint32_t *regs = (uint32_t *)(info + 1);
1039
    void *sigmask = (regs + 20);
1040
    /* XXX: is there a standard glibc define ? */
1041
    unsigned long pc = regs[1];
1042
#else
1043
#ifdef __linux__
1044
    struct sigcontext *sc = puc;
1045
    unsigned long pc = sc->sigc_regs.tpc;
1046
    void *sigmask = (void *)sc->sigc_mask;
1047
#elif defined(__OpenBSD__)
1048
    struct sigcontext *uc = puc;
1049
    unsigned long pc = uc->sc_pc;
1050
    void *sigmask = (void *)(long)uc->sc_mask;
1051
#endif
1052
#endif
1053

    
1054
    /* XXX: need kernel patch to get write flag faster */
1055
    is_write = 0;
1056
    insn = *(uint32_t *)pc;
1057
    if ((insn >> 30) == 3) {
1058
      switch((insn >> 19) & 0x3f) {
1059
      case 0x05: // stb
1060
      case 0x15: // stba
1061
      case 0x06: // sth
1062
      case 0x16: // stha
1063
      case 0x04: // st
1064
      case 0x14: // sta
1065
      case 0x07: // std
1066
      case 0x17: // stda
1067
      case 0x0e: // stx
1068
      case 0x1e: // stxa
1069
      case 0x24: // stf
1070
      case 0x34: // stfa
1071
      case 0x27: // stdf
1072
      case 0x37: // stdfa
1073
      case 0x26: // stqf
1074
      case 0x36: // stqfa
1075
      case 0x25: // stfsr
1076
      case 0x3c: // casa
1077
      case 0x3e: // casxa
1078
        is_write = 1;
1079
        break;
1080
      }
1081
    }
1082
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1083
                             is_write, sigmask, NULL);
1084
}
1085

    
1086
#elif defined(__arm__)
1087

    
1088
int cpu_signal_handler(int host_signum, void *pinfo,
1089
                       void *puc)
1090
{
1091
    siginfo_t *info = pinfo;
1092
    struct ucontext *uc = puc;
1093
    unsigned long pc;
1094
    int is_write;
1095

    
1096
#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1097
    pc = uc->uc_mcontext.gregs[R15];
1098
#else
1099
    pc = uc->uc_mcontext.arm_pc;
1100
#endif
1101
    /* XXX: compute is_write */
1102
    is_write = 0;
1103
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1104
                             is_write,
1105
                             &uc->uc_sigmask, puc);
1106
}
1107

    
1108
#elif defined(__mc68000)
1109

    
1110
int cpu_signal_handler(int host_signum, void *pinfo,
1111
                       void *puc)
1112
{
1113
    siginfo_t *info = pinfo;
1114
    struct ucontext *uc = puc;
1115
    unsigned long pc;
1116
    int is_write;
1117

    
1118
    pc = uc->uc_mcontext.gregs[16];
1119
    /* XXX: compute is_write */
1120
    is_write = 0;
1121
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1122
                             is_write,
1123
                             &uc->uc_sigmask, puc);
1124
}
1125

    
1126
#elif defined(__ia64)
1127

    
1128
#ifndef __ISR_VALID
1129
  /* This ought to be in <bits/siginfo.h>... */
1130
# define __ISR_VALID        1
1131
#endif
1132

    
1133
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1134
{
1135
    siginfo_t *info = pinfo;
1136
    struct ucontext *uc = puc;
1137
    unsigned long ip;
1138
    int is_write = 0;
1139

    
1140
    ip = uc->uc_mcontext.sc_ip;
1141
    switch (host_signum) {
1142
      case SIGILL:
1143
      case SIGFPE:
1144
      case SIGSEGV:
1145
      case SIGBUS:
1146
      case SIGTRAP:
1147
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1148
              /* ISR.W (write-access) is bit 33:  */
1149
              is_write = (info->si_isr >> 33) & 1;
1150
          break;
1151

    
1152
      default:
1153
          break;
1154
    }
1155
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1156
                             is_write,
1157
                             (sigset_t *)&uc->uc_sigmask, puc);
1158
}
1159

    
1160
#elif defined(__s390__)
1161

    
1162
int cpu_signal_handler(int host_signum, void *pinfo,
1163
                       void *puc)
1164
{
1165
    siginfo_t *info = pinfo;
1166
    struct ucontext *uc = puc;
1167
    unsigned long pc;
1168
    int is_write;
1169

    
1170
    pc = uc->uc_mcontext.psw.addr;
1171
    /* XXX: compute is_write */
1172
    is_write = 0;
1173
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1174
                             is_write, &uc->uc_sigmask, puc);
1175
}
1176

    
1177
#elif defined(__mips__)
1178

    
1179
int cpu_signal_handler(int host_signum, void *pinfo,
1180
                       void *puc)
1181
{
1182
    siginfo_t *info = pinfo;
1183
    struct ucontext *uc = puc;
1184
    greg_t pc = uc->uc_mcontext.pc;
1185
    int is_write;
1186

    
1187
    /* XXX: compute is_write */
1188
    is_write = 0;
1189
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1190
                             is_write, &uc->uc_sigmask, puc);
1191
}
1192

    
1193
#elif defined(__hppa__)
1194

    
1195
int cpu_signal_handler(int host_signum, void *pinfo,
1196
                       void *puc)
1197
{
1198
    struct siginfo *info = pinfo;
1199
    struct ucontext *uc = puc;
1200
    unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
1201
    uint32_t insn = *(uint32_t *)pc;
1202
    int is_write = 0;
1203

    
1204
    /* XXX: need kernel patch to get write flag faster.  */
1205
    switch (insn >> 26) {
1206
    case 0x1a: /* STW */
1207
    case 0x19: /* STH */
1208
    case 0x18: /* STB */
1209
    case 0x1b: /* STWM */
1210
        is_write = 1;
1211
        break;
1212

    
1213
    case 0x09: /* CSTWX, FSTWX, FSTWS */
1214
    case 0x0b: /* CSTDX, FSTDX, FSTDS */
1215
        /* Distinguish from coprocessor load ... */
1216
        is_write = (insn >> 9) & 1;
1217
        break;
1218

    
1219
    case 0x03:
1220
        switch ((insn >> 6) & 15) {
1221
        case 0xa: /* STWS */
1222
        case 0x9: /* STHS */
1223
        case 0x8: /* STBS */
1224
        case 0xe: /* STWAS */
1225
        case 0xc: /* STBYS */
1226
            is_write = 1;
1227
        }
1228
        break;
1229
    }
1230

    
1231
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1232
                             is_write, &uc->uc_sigmask, puc);
1233
}
1234

    
1235
#else
1236

    
1237
#error host CPU specific signal handler needed
1238

    
1239
#endif
1240

    
1241
#endif /* !defined(CONFIG_SOFTMMU) */