Statistics
| Branch: | Revision:

root / cpu-exec.c @ a1c7273b

History | View | Annotate | Download (44.8 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
#include "qemu-barrier.h"
25

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

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

    
48
int tb_invalidated_flag;
49

    
50
//#define CONFIG_DEBUG_EXEC
51
//#define DEBUG_SIGNAL
52

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

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

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

    
77
    env = env1;
78

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

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

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

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

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

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

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

    
136
    tb_invalidated_flag = 0;
137

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

    
169
 found:
170
    /* Move the last found TB to the head of the list */
171
    if (likely(*ptb1)) {
172
        *ptb1 = tb->phys_hash_next;
173
        tb->phys_hash_next = tb_phys_hash[h];
174
        tb_phys_hash[h] = tb;
175
    }
176
    /* we add the TB in the virtual pc hash table */
177
    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
178
    return tb;
179
}
180

    
181
static inline TranslationBlock *tb_find_fast(void)
182
{
183
    TranslationBlock *tb;
184
    target_ulong cs_base, pc;
185
    int flags;
186

    
187
    /* we record a subset of the CPU state. It will
188
       always be the same before a given translated block
189
       is executed. */
190
    cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
191
    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
192
    if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
193
                 tb->flags != flags)) {
194
        tb = tb_find_slow(pc, cs_base, flags);
195
    }
196
    return tb;
197
}
198

    
199
static CPUDebugExcpHandler *debug_excp_handler;
200

    
201
CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
202
{
203
    CPUDebugExcpHandler *old_handler = debug_excp_handler;
204

    
205
    debug_excp_handler = handler;
206
    return old_handler;
207
}
208

    
209
static void cpu_handle_debug_exception(CPUState *env)
210
{
211
    CPUWatchpoint *wp;
212

    
213
    if (!env->watchpoint_hit) {
214
        QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
215
            wp->flags &= ~BP_WATCHPOINT_HIT;
216
        }
217
    }
218
    if (debug_excp_handler) {
219
        debug_excp_handler(env);
220
    }
221
}
222

    
223
/* main execution loop */
224

    
225
volatile sig_atomic_t exit_request;
226

    
227
int cpu_exec(CPUState *env1)
228
{
229
    volatile host_reg_t saved_env_reg;
230
    int ret, interrupt_request;
231
    TranslationBlock *tb;
232
    uint8_t *tc_ptr;
233
    unsigned long next_tb;
234

    
235
    if (env1->halted) {
236
        if (!cpu_has_work(env1)) {
237
            return EXCP_HALTED;
238
        }
239

    
240
        env1->halted = 0;
241
    }
242

    
243
    cpu_single_env = env1;
244

    
245
    /* the access to env below is actually saving the global register's
246
       value, so that files not including target-xyz/exec.h are free to
247
       use it.  */
248
    QEMU_BUILD_BUG_ON (sizeof (saved_env_reg) != sizeof (env));
249
    saved_env_reg = (host_reg_t) env;
250
    barrier();
251
    env = env1;
252

    
253
    if (unlikely(exit_request)) {
254
        env->exit_request = 1;
255
    }
256

    
257
#if defined(TARGET_I386)
258
    /* put eflags in CPU temporary format */
259
    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
260
    DF = 1 - (2 * ((env->eflags >> 10) & 1));
261
    CC_OP = CC_OP_EFLAGS;
262
    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
263
#elif defined(TARGET_SPARC)
264
#elif defined(TARGET_M68K)
265
    env->cc_op = CC_OP_FLAGS;
266
    env->cc_dest = env->sr & 0xf;
267
    env->cc_x = (env->sr >> 4) & 1;
268
#elif defined(TARGET_ALPHA)
269
#elif defined(TARGET_ARM)
270
#elif defined(TARGET_UNICORE32)
271
#elif defined(TARGET_PPC)
272
#elif defined(TARGET_LM32)
273
#elif defined(TARGET_MICROBLAZE)
274
#elif defined(TARGET_MIPS)
275
#elif defined(TARGET_SH4)
276
#elif defined(TARGET_CRIS)
277
#elif defined(TARGET_S390X)
278
    /* XXXXX */
279
#else
280
#error unsupported target CPU
281
#endif
282
    env->exception_index = -1;
283

    
284
    /* prepare setjmp context for exception handling */
285
    for(;;) {
286
        if (setjmp(env->jmp_env) == 0) {
287
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
288
#undef env
289
            env = cpu_single_env;
290
#define env cpu_single_env
291
#endif
292
            /* if an exception is pending, we execute it here */
293
            if (env->exception_index >= 0) {
294
                if (env->exception_index >= EXCP_INTERRUPT) {
295
                    /* exit request from the cpu execution loop */
296
                    ret = env->exception_index;
297
                    if (ret == EXCP_DEBUG) {
298
                        cpu_handle_debug_exception(env);
299
                    }
300
                    break;
301
                } else {
302
#if defined(CONFIG_USER_ONLY)
303
                    /* if user mode only, we simulate a fake exception
304
                       which will be handled outside the cpu execution
305
                       loop */
306
#if defined(TARGET_I386)
307
                    do_interrupt_user(env->exception_index,
308
                                      env->exception_is_int,
309
                                      env->error_code,
310
                                      env->exception_next_eip);
311
                    /* successfully delivered */
312
                    env->old_exception = -1;
313
#endif
314
                    ret = env->exception_index;
315
                    break;
316
#else
317
#if defined(TARGET_I386)
318
                    /* simulate a real cpu exception. On i386, it can
319
                       trigger new exceptions, but we do not handle
320
                       double or triple faults yet. */
321
                    do_interrupt(env->exception_index,
322
                                 env->exception_is_int,
323
                                 env->error_code,
324
                                 env->exception_next_eip, 0);
325
                    /* successfully delivered */
326
                    env->old_exception = -1;
327
#elif defined(TARGET_PPC)
328
                    do_interrupt(env);
329
#elif defined(TARGET_LM32)
330
                    do_interrupt(env);
331
#elif defined(TARGET_MICROBLAZE)
332
                    do_interrupt(env);
333
#elif defined(TARGET_MIPS)
334
                    do_interrupt(env);
335
#elif defined(TARGET_SPARC)
336
                    do_interrupt(env);
337
#elif defined(TARGET_ARM)
338
                    do_interrupt(env);
339
#elif defined(TARGET_UNICORE32)
340
                    do_interrupt(env);
341
#elif defined(TARGET_SH4)
342
                    do_interrupt(env);
343
#elif defined(TARGET_ALPHA)
344
                    do_interrupt(env);
345
#elif defined(TARGET_CRIS)
346
                    do_interrupt(env);
347
#elif defined(TARGET_M68K)
348
                    do_interrupt(0);
349
#elif defined(TARGET_S390X)
350
                    do_interrupt(env);
351
#endif
352
                    env->exception_index = -1;
353
#endif
354
                }
355
            }
356

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

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

    
628
                /* cpu_interrupt might be called while translating the
629
                   TB, but before it is linked into a potentially
630
                   infinite loop and becomes env->current_tb. Avoid
631
                   starting execution if there is a pending interrupt. */
632
                env->current_tb = tb;
633
                barrier();
634
                if (likely(!env->exit_request)) {
635
                    tc_ptr = tb->tc_ptr;
636
                /* execute the generated code */
637
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
638
#undef env
639
                    env = cpu_single_env;
640
#define env cpu_single_env
641
#endif
642
                    next_tb = tcg_qemu_tb_exec(tc_ptr);
643
                    if ((next_tb & 3) == 2) {
644
                        /* Instruction counter expired.  */
645
                        int insns_left;
646
                        tb = (TranslationBlock *)(long)(next_tb & ~3);
647
                        /* Restore PC.  */
648
                        cpu_pc_from_tb(env, tb);
649
                        insns_left = env->icount_decr.u32;
650
                        if (env->icount_extra && insns_left >= 0) {
651
                            /* Refill decrementer and continue execution.  */
652
                            env->icount_extra += insns_left;
653
                            if (env->icount_extra > 0xffff) {
654
                                insns_left = 0xffff;
655
                            } else {
656
                                insns_left = env->icount_extra;
657
                            }
658
                            env->icount_extra -= insns_left;
659
                            env->icount_decr.u16.low = insns_left;
660
                        } else {
661
                            if (insns_left > 0) {
662
                                /* Execute remaining instructions.  */
663
                                cpu_exec_nocache(insns_left, tb);
664
                            }
665
                            env->exception_index = EXCP_INTERRUPT;
666
                            next_tb = 0;
667
                            cpu_loop_exit();
668
                        }
669
                    }
670
                }
671
                env->current_tb = NULL;
672
                /* reset soft MMU for next block (it can currently
673
                   only be set by a memory fault) */
674
            } /* for(;;) */
675
        }
676
    } /* for(;;) */
677

    
678

    
679
#if defined(TARGET_I386)
680
    /* restore flags in standard format */
681
    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
682
#elif defined(TARGET_ARM)
683
    /* XXX: Save/restore host fpu exception state?.  */
684
#elif defined(TARGET_UNICORE32)
685
#elif defined(TARGET_SPARC)
686
#elif defined(TARGET_PPC)
687
#elif defined(TARGET_LM32)
688
#elif defined(TARGET_M68K)
689
    cpu_m68k_flush_flags(env, env->cc_op);
690
    env->cc_op = CC_OP_FLAGS;
691
    env->sr = (env->sr & 0xffe0)
692
              | env->cc_dest | (env->cc_x << 4);
693
#elif defined(TARGET_MICROBLAZE)
694
#elif defined(TARGET_MIPS)
695
#elif defined(TARGET_SH4)
696
#elif defined(TARGET_ALPHA)
697
#elif defined(TARGET_CRIS)
698
#elif defined(TARGET_S390X)
699
    /* XXXXX */
700
#else
701
#error unsupported target CPU
702
#endif
703

    
704
    /* restore global registers */
705
    barrier();
706
    env = (void *) saved_env_reg;
707

    
708
    /* fail safe : never use cpu_single_env outside cpu_exec() */
709
    cpu_single_env = NULL;
710
    return ret;
711
}
712

    
713
/* must only be called from the generated code as an exception can be
714
   generated */
715
void tb_invalidate_page_range(target_ulong start, target_ulong end)
716
{
717
    /* XXX: cannot enable it yet because it yields to MMU exception
718
       where NIP != read address on PowerPC */
719
#if 0
720
    target_ulong phys_addr;
721
    phys_addr = get_phys_addr_code(env, start);
722
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
723
#endif
724
}
725

    
726
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
727

    
728
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
729
{
730
    CPUX86State *saved_env;
731

    
732
    saved_env = env;
733
    env = s;
734
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
735
        selector &= 0xffff;
736
        cpu_x86_load_seg_cache(env, seg_reg, selector,
737
                               (selector << 4), 0xffff, 0);
738
    } else {
739
        helper_load_seg(seg_reg, selector);
740
    }
741
    env = saved_env;
742
}
743

    
744
void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
745
{
746
    CPUX86State *saved_env;
747

    
748
    saved_env = env;
749
    env = s;
750

    
751
    helper_fsave(ptr, data32);
752

    
753
    env = saved_env;
754
}
755

    
756
void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
757
{
758
    CPUX86State *saved_env;
759

    
760
    saved_env = env;
761
    env = s;
762

    
763
    helper_frstor(ptr, data32);
764

    
765
    env = saved_env;
766
}
767

    
768
#endif /* TARGET_I386 */
769

    
770
#if !defined(CONFIG_SOFTMMU)
771

    
772
#if defined(TARGET_I386)
773
#define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code)
774
#else
775
#define EXCEPTION_ACTION cpu_loop_exit()
776
#endif
777

    
778
/* 'pc' is the host PC at which the exception was raised. 'address' is
779
   the effective address of the memory exception. 'is_write' is 1 if a
780
   write caused the exception and otherwise 0'. 'old_set' is the
781
   signal set which should be restored */
782
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
783
                                    int is_write, sigset_t *old_set,
784
                                    void *puc)
785
{
786
    TranslationBlock *tb;
787
    int ret;
788

    
789
    if (cpu_single_env)
790
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
791
#if defined(DEBUG_SIGNAL)
792
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
793
                pc, address, is_write, *(unsigned long *)old_set);
794
#endif
795
    /* XXX: locking issue */
796
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
797
        return 1;
798
    }
799

    
800
    /* see if it is an MMU fault */
801
    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
802
    if (ret < 0)
803
        return 0; /* not an MMU fault */
804
    if (ret == 0)
805
        return 1; /* the MMU fault was handled without causing real CPU fault */
806
    /* now we have a real cpu fault */
807
    tb = tb_find_pc(pc);
808
    if (tb) {
809
        /* the PC is inside the translated code. It means that we have
810
           a virtual CPU fault */
811
        cpu_restore_state(tb, env, pc);
812
    }
813

    
814
    /* we restore the process signal mask as the sigreturn should
815
       do it (XXX: use sigsetjmp) */
816
    sigprocmask(SIG_SETMASK, old_set, NULL);
817
    EXCEPTION_ACTION;
818

    
819
    /* never comes here */
820
    return 1;
821
}
822

    
823
#if defined(__i386__)
824

    
825
#if defined(__APPLE__)
826
# include <sys/ucontext.h>
827

    
828
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
829
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
830
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
831
# define MASK_sig(context)    ((context)->uc_sigmask)
832
#elif defined (__NetBSD__)
833
# include <ucontext.h>
834

    
835
# define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
836
# define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
837
# define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
838
# define MASK_sig(context)    ((context)->uc_sigmask)
839
#elif defined (__FreeBSD__) || defined(__DragonFly__)
840
# include <ucontext.h>
841

    
842
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
843
# define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
844
# define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
845
# define MASK_sig(context)    ((context)->uc_sigmask)
846
#elif defined(__OpenBSD__)
847
# define EIP_sig(context)     ((context)->sc_eip)
848
# define TRAP_sig(context)    ((context)->sc_trapno)
849
# define ERROR_sig(context)   ((context)->sc_err)
850
# define MASK_sig(context)    ((context)->sc_mask)
851
#else
852
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
853
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
854
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
855
# define MASK_sig(context)    ((context)->uc_sigmask)
856
#endif
857

    
858
int cpu_signal_handler(int host_signum, void *pinfo,
859
                       void *puc)
860
{
861
    siginfo_t *info = pinfo;
862
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
863
    ucontext_t *uc = puc;
864
#elif defined(__OpenBSD__)
865
    struct sigcontext *uc = puc;
866
#else
867
    struct ucontext *uc = puc;
868
#endif
869
    unsigned long pc;
870
    int trapno;
871

    
872
#ifndef REG_EIP
873
/* for glibc 2.1 */
874
#define REG_EIP    EIP
875
#define REG_ERR    ERR
876
#define REG_TRAPNO TRAPNO
877
#endif
878
    pc = EIP_sig(uc);
879
    trapno = TRAP_sig(uc);
880
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
881
                             trapno == 0xe ?
882
                             (ERROR_sig(uc) >> 1) & 1 : 0,
883
                             &MASK_sig(uc), puc);
884
}
885

    
886
#elif defined(__x86_64__)
887

    
888
#ifdef __NetBSD__
889
#define PC_sig(context)       _UC_MACHINE_PC(context)
890
#define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
891
#define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
892
#define MASK_sig(context)     ((context)->uc_sigmask)
893
#elif defined(__OpenBSD__)
894
#define PC_sig(context)       ((context)->sc_rip)
895
#define TRAP_sig(context)     ((context)->sc_trapno)
896
#define ERROR_sig(context)    ((context)->sc_err)
897
#define MASK_sig(context)     ((context)->sc_mask)
898
#elif defined (__FreeBSD__) || defined(__DragonFly__)
899
#include <ucontext.h>
900

    
901
#define PC_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
902
#define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
903
#define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
904
#define MASK_sig(context)     ((context)->uc_sigmask)
905
#else
906
#define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
907
#define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
908
#define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
909
#define MASK_sig(context)     ((context)->uc_sigmask)
910
#endif
911

    
912
int cpu_signal_handler(int host_signum, void *pinfo,
913
                       void *puc)
914
{
915
    siginfo_t *info = pinfo;
916
    unsigned long pc;
917
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
918
    ucontext_t *uc = puc;
919
#elif defined(__OpenBSD__)
920
    struct sigcontext *uc = puc;
921
#else
922
    struct ucontext *uc = puc;
923
#endif
924

    
925
    pc = PC_sig(uc);
926
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
927
                             TRAP_sig(uc) == 0xe ?
928
                             (ERROR_sig(uc) >> 1) & 1 : 0,
929
                             &MASK_sig(uc), puc);
930
}
931

    
932
#elif defined(_ARCH_PPC)
933

    
934
/***********************************************************************
935
 * signal context platform-specific definitions
936
 * From Wine
937
 */
938
#ifdef linux
939
/* All Registers access - only for local access */
940
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
941
/* Gpr Registers access  */
942
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
943
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
944
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
945
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
946
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
947
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
948
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
949
/* Float Registers access  */
950
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
951
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
952
/* Exception Registers access */
953
# define DAR_sig(context)                        REG_sig(dar, context)
954
# define DSISR_sig(context)                        REG_sig(dsisr, context)
955
# define TRAP_sig(context)                        REG_sig(trap, context)
956
#endif /* linux */
957

    
958
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
959
#include <ucontext.h>
960
# define IAR_sig(context)                ((context)->uc_mcontext.mc_srr0)
961
# define MSR_sig(context)                ((context)->uc_mcontext.mc_srr1)
962
# define CTR_sig(context)                ((context)->uc_mcontext.mc_ctr)
963
# define XER_sig(context)                ((context)->uc_mcontext.mc_xer)
964
# define LR_sig(context)                ((context)->uc_mcontext.mc_lr)
965
# define CR_sig(context)                ((context)->uc_mcontext.mc_cr)
966
/* Exception Registers access */
967
# define DAR_sig(context)                ((context)->uc_mcontext.mc_dar)
968
# define DSISR_sig(context)                ((context)->uc_mcontext.mc_dsisr)
969
# define TRAP_sig(context)                ((context)->uc_mcontext.mc_exc)
970
#endif /* __FreeBSD__|| __FreeBSD_kernel__ */
971

    
972
#ifdef __APPLE__
973
# include <sys/ucontext.h>
974
typedef struct ucontext SIGCONTEXT;
975
/* All Registers access - only for local access */
976
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
977
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
978
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
979
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
980
/* Gpr Registers access */
981
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
982
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
983
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
984
# define CTR_sig(context)                        REG_sig(ctr, context)
985
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
986
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
987
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
988
/* Float Registers access */
989
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
990
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
991
/* Exception Registers access */
992
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
993
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
994
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
995
#endif /* __APPLE__ */
996

    
997
int cpu_signal_handler(int host_signum, void *pinfo,
998
                       void *puc)
999
{
1000
    siginfo_t *info = pinfo;
1001
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1002
    ucontext_t *uc = puc;
1003
#else
1004
    struct ucontext *uc = puc;
1005
#endif
1006
    unsigned long pc;
1007
    int is_write;
1008

    
1009
    pc = IAR_sig(uc);
1010
    is_write = 0;
1011
#if 0
1012
    /* ppc 4xx case */
1013
    if (DSISR_sig(uc) & 0x00800000)
1014
        is_write = 1;
1015
#else
1016
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1017
        is_write = 1;
1018
#endif
1019
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1020
                             is_write, &uc->uc_sigmask, puc);
1021
}
1022

    
1023
#elif defined(__alpha__)
1024

    
1025
int cpu_signal_handler(int host_signum, void *pinfo,
1026
                           void *puc)
1027
{
1028
    siginfo_t *info = pinfo;
1029
    struct ucontext *uc = puc;
1030
    uint32_t *pc = uc->uc_mcontext.sc_pc;
1031
    uint32_t insn = *pc;
1032
    int is_write = 0;
1033

    
1034
    /* XXX: need kernel patch to get write flag faster */
1035
    switch (insn >> 26) {
1036
    case 0x0d: // stw
1037
    case 0x0e: // stb
1038
    case 0x0f: // stq_u
1039
    case 0x24: // stf
1040
    case 0x25: // stg
1041
    case 0x26: // sts
1042
    case 0x27: // stt
1043
    case 0x2c: // stl
1044
    case 0x2d: // stq
1045
    case 0x2e: // stl_c
1046
    case 0x2f: // stq_c
1047
        is_write = 1;
1048
    }
1049

    
1050
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1051
                             is_write, &uc->uc_sigmask, puc);
1052
}
1053
#elif defined(__sparc__)
1054

    
1055
int cpu_signal_handler(int host_signum, void *pinfo,
1056
                       void *puc)
1057
{
1058
    siginfo_t *info = pinfo;
1059
    int is_write;
1060
    uint32_t insn;
1061
#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
1062
    uint32_t *regs = (uint32_t *)(info + 1);
1063
    void *sigmask = (regs + 20);
1064
    /* XXX: is there a standard glibc define ? */
1065
    unsigned long pc = regs[1];
1066
#else
1067
#ifdef __linux__
1068
    struct sigcontext *sc = puc;
1069
    unsigned long pc = sc->sigc_regs.tpc;
1070
    void *sigmask = (void *)sc->sigc_mask;
1071
#elif defined(__OpenBSD__)
1072
    struct sigcontext *uc = puc;
1073
    unsigned long pc = uc->sc_pc;
1074
    void *sigmask = (void *)(long)uc->sc_mask;
1075
#endif
1076
#endif
1077

    
1078
    /* XXX: need kernel patch to get write flag faster */
1079
    is_write = 0;
1080
    insn = *(uint32_t *)pc;
1081
    if ((insn >> 30) == 3) {
1082
      switch((insn >> 19) & 0x3f) {
1083
      case 0x05: // stb
1084
      case 0x15: // stba
1085
      case 0x06: // sth
1086
      case 0x16: // stha
1087
      case 0x04: // st
1088
      case 0x14: // sta
1089
      case 0x07: // std
1090
      case 0x17: // stda
1091
      case 0x0e: // stx
1092
      case 0x1e: // stxa
1093
      case 0x24: // stf
1094
      case 0x34: // stfa
1095
      case 0x27: // stdf
1096
      case 0x37: // stdfa
1097
      case 0x26: // stqf
1098
      case 0x36: // stqfa
1099
      case 0x25: // stfsr
1100
      case 0x3c: // casa
1101
      case 0x3e: // casxa
1102
        is_write = 1;
1103
        break;
1104
      }
1105
    }
1106
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1107
                             is_write, sigmask, NULL);
1108
}
1109

    
1110
#elif defined(__arm__)
1111

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

    
1120
#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1121
    pc = uc->uc_mcontext.gregs[R15];
1122
#else
1123
    pc = uc->uc_mcontext.arm_pc;
1124
#endif
1125
    /* XXX: compute is_write */
1126
    is_write = 0;
1127
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1128
                             is_write,
1129
                             &uc->uc_sigmask, puc);
1130
}
1131

    
1132
#elif defined(__mc68000)
1133

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

    
1142
    pc = uc->uc_mcontext.gregs[16];
1143
    /* XXX: compute is_write */
1144
    is_write = 0;
1145
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1146
                             is_write,
1147
                             &uc->uc_sigmask, puc);
1148
}
1149

    
1150
#elif defined(__ia64)
1151

    
1152
#ifndef __ISR_VALID
1153
  /* This ought to be in <bits/siginfo.h>... */
1154
# define __ISR_VALID        1
1155
#endif
1156

    
1157
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1158
{
1159
    siginfo_t *info = pinfo;
1160
    struct ucontext *uc = puc;
1161
    unsigned long ip;
1162
    int is_write = 0;
1163

    
1164
    ip = uc->uc_mcontext.sc_ip;
1165
    switch (host_signum) {
1166
      case SIGILL:
1167
      case SIGFPE:
1168
      case SIGSEGV:
1169
      case SIGBUS:
1170
      case SIGTRAP:
1171
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1172
              /* ISR.W (write-access) is bit 33:  */
1173
              is_write = (info->si_isr >> 33) & 1;
1174
          break;
1175

    
1176
      default:
1177
          break;
1178
    }
1179
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1180
                             is_write,
1181
                             (sigset_t *)&uc->uc_sigmask, puc);
1182
}
1183

    
1184
#elif defined(__s390__)
1185

    
1186
int cpu_signal_handler(int host_signum, void *pinfo,
1187
                       void *puc)
1188
{
1189
    siginfo_t *info = pinfo;
1190
    struct ucontext *uc = puc;
1191
    unsigned long pc;
1192
    uint16_t *pinsn;
1193
    int is_write = 0;
1194

    
1195
    pc = uc->uc_mcontext.psw.addr;
1196

    
1197
    /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
1198
       of the normal 2 arguments.  The 3rd argument contains the "int_code"
1199
       from the hardware which does in fact contain the is_write value.
1200
       The rt signal handler, as far as I can tell, does not give this value
1201
       at all.  Not that we could get to it from here even if it were.  */
1202
    /* ??? This is not even close to complete, since it ignores all
1203
       of the read-modify-write instructions.  */
1204
    pinsn = (uint16_t *)pc;
1205
    switch (pinsn[0] >> 8) {
1206
    case 0x50: /* ST */
1207
    case 0x42: /* STC */
1208
    case 0x40: /* STH */
1209
        is_write = 1;
1210
        break;
1211
    case 0xc4: /* RIL format insns */
1212
        switch (pinsn[0] & 0xf) {
1213
        case 0xf: /* STRL */
1214
        case 0xb: /* STGRL */
1215
        case 0x7: /* STHRL */
1216
            is_write = 1;
1217
        }
1218
        break;
1219
    case 0xe3: /* RXY format insns */
1220
        switch (pinsn[2] & 0xff) {
1221
        case 0x50: /* STY */
1222
        case 0x24: /* STG */
1223
        case 0x72: /* STCY */
1224
        case 0x70: /* STHY */
1225
        case 0x8e: /* STPQ */
1226
        case 0x3f: /* STRVH */
1227
        case 0x3e: /* STRV */
1228
        case 0x2f: /* STRVG */
1229
            is_write = 1;
1230
        }
1231
        break;
1232
    }
1233
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1234
                             is_write, &uc->uc_sigmask, puc);
1235
}
1236

    
1237
#elif defined(__mips__)
1238

    
1239
int cpu_signal_handler(int host_signum, void *pinfo,
1240
                       void *puc)
1241
{
1242
    siginfo_t *info = pinfo;
1243
    struct ucontext *uc = puc;
1244
    greg_t pc = uc->uc_mcontext.pc;
1245
    int is_write;
1246

    
1247
    /* XXX: compute is_write */
1248
    is_write = 0;
1249
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1250
                             is_write, &uc->uc_sigmask, puc);
1251
}
1252

    
1253
#elif defined(__hppa__)
1254

    
1255
int cpu_signal_handler(int host_signum, void *pinfo,
1256
                       void *puc)
1257
{
1258
    struct siginfo *info = pinfo;
1259
    struct ucontext *uc = puc;
1260
    unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
1261
    uint32_t insn = *(uint32_t *)pc;
1262
    int is_write = 0;
1263

    
1264
    /* XXX: need kernel patch to get write flag faster.  */
1265
    switch (insn >> 26) {
1266
    case 0x1a: /* STW */
1267
    case 0x19: /* STH */
1268
    case 0x18: /* STB */
1269
    case 0x1b: /* STWM */
1270
        is_write = 1;
1271
        break;
1272

    
1273
    case 0x09: /* CSTWX, FSTWX, FSTWS */
1274
    case 0x0b: /* CSTDX, FSTDX, FSTDS */
1275
        /* Distinguish from coprocessor load ... */
1276
        is_write = (insn >> 9) & 1;
1277
        break;
1278

    
1279
    case 0x03:
1280
        switch ((insn >> 6) & 15) {
1281
        case 0xa: /* STWS */
1282
        case 0x9: /* STHS */
1283
        case 0x8: /* STBS */
1284
        case 0xe: /* STWAS */
1285
        case 0xc: /* STBYS */
1286
            is_write = 1;
1287
        }
1288
        break;
1289
    }
1290

    
1291
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1292
                             is_write, &uc->uc_sigmask, puc);
1293
}
1294

    
1295
#else
1296

    
1297
#error host CPU specific signal handler needed
1298

    
1299
#endif
1300

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