Statistics
| Branch: | Revision:

root / cpu-exec.c @ 6ce0ca12

History | View | Annotate | Download (50.7 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, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19
 */
20
#include "config.h"
21
#define CPU_NO_GLOBAL_REGS
22
#include "exec.h"
23
#include "disas.h"
24
#include "tcg.h"
25
#include "kvm.h"
26

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

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

    
49
int tb_invalidated_flag;
50

    
51
//#define DEBUG_EXEC
52
//#define DEBUG_SIGNAL
53

    
54
void cpu_loop_exit(void)
55
{
56
    /* NOTE: the register at this point must be saved by hand because
57
       longjmp restore them */
58
    regs_to_env();
59
    longjmp(env->jmp_env, 1);
60
}
61

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

    
75
    env = env1;
76

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

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

    
93
/* Execute the code without caching the generated code. An interpreter
94
   could be used if available. */
95
static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
96
{
97
    unsigned long next_tb;
98
    TranslationBlock *tb;
99

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

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

    
111
    if ((next_tb & 3) == 2) {
112
        /* Restore PC.  This may happen if async event occurs before
113
           the TB starts executing.  */
114
        cpu_pc_from_tb(env, tb);
115
    }
116
    tb_phys_invalidate(tb, -1);
117
    tb_free(tb);
118
}
119

    
120
static TranslationBlock *tb_find_slow(target_ulong pc,
121
                                      target_ulong cs_base,
122
                                      uint64_t flags)
123
{
124
    TranslationBlock *tb, **ptb1;
125
    unsigned int h;
126
    target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
127

    
128
    tb_invalidated_flag = 0;
129

    
130
    regs_to_env(); /* XXX: do it just before cpu_gen_code() */
131

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

    
163
 found:
164
    /* we add the TB in the virtual pc hash table */
165
    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
166
    return tb;
167
}
168

    
169
static inline TranslationBlock *tb_find_fast(void)
170
{
171
    TranslationBlock *tb;
172
    target_ulong cs_base, pc;
173
    int flags;
174

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

    
187
static CPUDebugExcpHandler *debug_excp_handler;
188

    
189
CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
190
{
191
    CPUDebugExcpHandler *old_handler = debug_excp_handler;
192

    
193
    debug_excp_handler = handler;
194
    return old_handler;
195
}
196

    
197
static void cpu_handle_debug_exception(CPUState *env)
198
{
199
    CPUWatchpoint *wp;
200

    
201
    if (!env->watchpoint_hit)
202
        TAILQ_FOREACH(wp, &env->watchpoints, entry)
203
            wp->flags &= ~BP_WATCHPOINT_HIT;
204

    
205
    if (debug_excp_handler)
206
        debug_excp_handler(env);
207
}
208

    
209
/* main execution loop */
210

    
211
int cpu_exec(CPUState *env1)
212
{
213
#define DECLARE_HOST_REGS 1
214
#include "hostregs_helper.h"
215
    int ret, interrupt_request;
216
    TranslationBlock *tb;
217
    uint8_t *tc_ptr;
218
    unsigned long next_tb;
219

    
220
    if (cpu_halted(env1) == EXCP_HALTED)
221
        return EXCP_HALTED;
222

    
223
    cpu_single_env = env1;
224

    
225
    /* first we save global registers */
226
#define SAVE_HOST_REGS 1
227
#include "hostregs_helper.h"
228
    env = env1;
229

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

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

    
339
            if (kvm_enabled()) {
340
                kvm_cpu_exec(env);
341
                longjmp(env->jmp_env, 1);
342
            }
343

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

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

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

    
605
                while (env->current_tb) {
606
                    tc_ptr = tb->tc_ptr;
607
                /* execute the generated code */
608
#if defined(__sparc__) && !defined(HOST_SOLARIS)
609
#undef env
610
                    env = cpu_single_env;
611
#define env cpu_single_env
612
#endif
613
                    next_tb = tcg_qemu_tb_exec(tc_ptr);
614
                    env->current_tb = NULL;
615
                    if ((next_tb & 3) == 2) {
616
                        /* Instruction counter expired.  */
617
                        int insns_left;
618
                        tb = (TranslationBlock *)(long)(next_tb & ~3);
619
                        /* Restore PC.  */
620
                        cpu_pc_from_tb(env, tb);
621
                        insns_left = env->icount_decr.u32;
622
                        if (env->icount_extra && insns_left >= 0) {
623
                            /* Refill decrementer and continue execution.  */
624
                            env->icount_extra += insns_left;
625
                            if (env->icount_extra > 0xffff) {
626
                                insns_left = 0xffff;
627
                            } else {
628
                                insns_left = env->icount_extra;
629
                            }
630
                            env->icount_extra -= insns_left;
631
                            env->icount_decr.u16.low = insns_left;
632
                        } else {
633
                            if (insns_left > 0) {
634
                                /* Execute remaining instructions.  */
635
                                cpu_exec_nocache(insns_left, tb);
636
                            }
637
                            env->exception_index = EXCP_INTERRUPT;
638
                            next_tb = 0;
639
                            cpu_loop_exit();
640
                        }
641
                    }
642
                }
643
                /* reset soft MMU for next block (it can currently
644
                   only be set by a memory fault) */
645
#if defined(USE_KQEMU)
646
#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
647
                if (kqemu_is_ok(env) &&
648
                    (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
649
                    cpu_loop_exit();
650
                }
651
#endif
652
            } /* for(;;) */
653
        } else {
654
            env_to_regs();
655
        }
656
    } /* for(;;) */
657

    
658

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

    
680
    /* restore global registers */
681
#include "hostregs_helper.h"
682

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

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

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

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

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

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

    
723
    saved_env = env;
724
    env = s;
725

    
726
    helper_fsave(ptr, data32);
727

    
728
    env = saved_env;
729
}
730

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

    
735
    saved_env = env;
736
    env = s;
737

    
738
    helper_frstor(ptr, data32);
739

    
740
    env = saved_env;
741
}
742

    
743
#endif /* TARGET_I386 */
744

    
745
#if !defined(CONFIG_SOFTMMU)
746

    
747
#if defined(TARGET_I386)
748

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

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

    
771
    /* see if it is an MMU fault */
772
    ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
773
    if (ret < 0)
774
        return 0; /* not an MMU fault */
775
    if (ret == 0)
776
        return 1; /* the MMU fault was handled without causing real CPU fault */
777
    /* now we have a real cpu fault */
778
    tb = tb_find_pc(pc);
779
    if (tb) {
780
        /* the PC is inside the translated code. It means that we have
781
           a virtual CPU fault */
782
        cpu_restore_state(tb, env, pc, puc);
783
    }
784
    if (ret == 1) {
785
#if 0
786
        printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
787
               env->eip, env->cr[2], env->error_code);
788
#endif
789
        /* we restore the process signal mask as the sigreturn should
790
           do it (XXX: use sigsetjmp) */
791
        sigprocmask(SIG_SETMASK, old_set, NULL);
792
        raise_exception_err(env->exception_index, env->error_code);
793
    } else {
794
        /* activate soft MMU for this block */
795
        env->hflags |= HF_SOFTMMU_MASK;
796
        cpu_resume_from_signal(env, puc);
797
    }
798
    /* never comes here */
799
    return 1;
800
}
801

    
802
#elif defined(TARGET_ARM)
803
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
804
                                    int is_write, sigset_t *old_set,
805
                                    void *puc)
806
{
807
    TranslationBlock *tb;
808
    int ret;
809

    
810
    if (cpu_single_env)
811
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
812
#if defined(DEBUG_SIGNAL)
813
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
814
           pc, address, is_write, *(unsigned long *)old_set);
815
#endif
816
    /* XXX: locking issue */
817
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
818
        return 1;
819
    }
820
    /* see if it is an MMU fault */
821
    ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
822
    if (ret < 0)
823
        return 0; /* not an MMU fault */
824
    if (ret == 0)
825
        return 1; /* the MMU fault was handled without causing real CPU fault */
826
    /* now we have a real cpu fault */
827
    tb = tb_find_pc(pc);
828
    if (tb) {
829
        /* the PC is inside the translated code. It means that we have
830
           a virtual CPU fault */
831
        cpu_restore_state(tb, env, pc, puc);
832
    }
833
    /* we restore the process signal mask as the sigreturn should
834
       do it (XXX: use sigsetjmp) */
835
    sigprocmask(SIG_SETMASK, old_set, NULL);
836
    cpu_loop_exit();
837
    /* never comes here */
838
    return 1;
839
}
840
#elif defined(TARGET_SPARC)
841
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
842
                                    int is_write, sigset_t *old_set,
843
                                    void *puc)
844
{
845
    TranslationBlock *tb;
846
    int ret;
847

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

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

    
897
    /* see if it is an MMU fault */
898
    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
899
    if (ret < 0)
900
        return 0; /* not an MMU fault */
901
    if (ret == 0)
902
        return 1; /* the MMU fault was handled without causing real CPU fault */
903

    
904
    /* now we have a real cpu fault */
905
    tb = tb_find_pc(pc);
906
    if (tb) {
907
        /* the PC is inside the translated code. It means that we have
908
           a virtual CPU fault */
909
        cpu_restore_state(tb, env, pc, puc);
910
    }
911
    if (ret == 1) {
912
#if 0
913
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
914
               env->nip, env->error_code, tb);
915
#endif
916
    /* we restore the process signal mask as the sigreturn should
917
       do it (XXX: use sigsetjmp) */
918
        sigprocmask(SIG_SETMASK, old_set, NULL);
919
        cpu_loop_exit();
920
    } else {
921
        /* activate soft MMU for this block */
922
        cpu_resume_from_signal(env, puc);
923
    }
924
    /* never comes here */
925
    return 1;
926
}
927

    
928
#elif defined(TARGET_M68K)
929
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
930
                                    int is_write, sigset_t *old_set,
931
                                    void *puc)
932
{
933
    TranslationBlock *tb;
934
    int ret;
935

    
936
    if (cpu_single_env)
937
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
938
#if defined(DEBUG_SIGNAL)
939
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
940
           pc, address, is_write, *(unsigned long *)old_set);
941
#endif
942
    /* XXX: locking issue */
943
    if (is_write && page_unprotect(address, pc, puc)) {
944
        return 1;
945
    }
946
    /* see if it is an MMU fault */
947
    ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
948
    if (ret < 0)
949
        return 0; /* not an MMU fault */
950
    if (ret == 0)
951
        return 1; /* the MMU fault was handled without causing real CPU fault */
952
    /* now we have a real cpu fault */
953
    tb = tb_find_pc(pc);
954
    if (tb) {
955
        /* the PC is inside the translated code. It means that we have
956
           a virtual CPU fault */
957
        cpu_restore_state(tb, env, pc, puc);
958
    }
959
    /* we restore the process signal mask as the sigreturn should
960
       do it (XXX: use sigsetjmp) */
961
    sigprocmask(SIG_SETMASK, old_set, NULL);
962
    cpu_loop_exit();
963
    /* never comes here */
964
    return 1;
965
}
966

    
967
#elif defined (TARGET_MIPS)
968
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
969
                                    int is_write, sigset_t *old_set,
970
                                    void *puc)
971
{
972
    TranslationBlock *tb;
973
    int ret;
974

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

    
986
    /* see if it is an MMU fault */
987
    ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
988
    if (ret < 0)
989
        return 0; /* not an MMU fault */
990
    if (ret == 0)
991
        return 1; /* the MMU fault was handled without causing real CPU fault */
992

    
993
    /* now we have a real cpu fault */
994
    tb = tb_find_pc(pc);
995
    if (tb) {
996
        /* the PC is inside the translated code. It means that we have
997
           a virtual CPU fault */
998
        cpu_restore_state(tb, env, pc, puc);
999
    }
1000
    if (ret == 1) {
1001
#if 0
1002
        printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1003
               env->PC, env->error_code, tb);
1004
#endif
1005
    /* we restore the process signal mask as the sigreturn should
1006
       do it (XXX: use sigsetjmp) */
1007
        sigprocmask(SIG_SETMASK, old_set, NULL);
1008
        cpu_loop_exit();
1009
    } else {
1010
        /* activate soft MMU for this block */
1011
        cpu_resume_from_signal(env, puc);
1012
    }
1013
    /* never comes here */
1014
    return 1;
1015
}
1016

    
1017
#elif defined (TARGET_SH4)
1018
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1019
                                    int is_write, sigset_t *old_set,
1020
                                    void *puc)
1021
{
1022
    TranslationBlock *tb;
1023
    int ret;
1024

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

    
1036
    /* see if it is an MMU fault */
1037
    ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1038
    if (ret < 0)
1039
        return 0; /* not an MMU fault */
1040
    if (ret == 0)
1041
        return 1; /* the MMU fault was handled without causing real CPU fault */
1042

    
1043
    /* now we have a real cpu fault */
1044
    tb = tb_find_pc(pc);
1045
    if (tb) {
1046
        /* the PC is inside the translated code. It means that we have
1047
           a virtual CPU fault */
1048
        cpu_restore_state(tb, env, pc, puc);
1049
    }
1050
#if 0
1051
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1052
               env->nip, env->error_code, tb);
1053
#endif
1054
    /* we restore the process signal mask as the sigreturn should
1055
       do it (XXX: use sigsetjmp) */
1056
    sigprocmask(SIG_SETMASK, old_set, NULL);
1057
    cpu_loop_exit();
1058
    /* never comes here */
1059
    return 1;
1060
}
1061

    
1062
#elif defined (TARGET_ALPHA)
1063
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1064
                                    int is_write, sigset_t *old_set,
1065
                                    void *puc)
1066
{
1067
    TranslationBlock *tb;
1068
    int ret;
1069

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

    
1081
    /* see if it is an MMU fault */
1082
    ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1083
    if (ret < 0)
1084
        return 0; /* not an MMU fault */
1085
    if (ret == 0)
1086
        return 1; /* the MMU fault was handled without causing real CPU fault */
1087

    
1088
    /* now we have a real cpu fault */
1089
    tb = tb_find_pc(pc);
1090
    if (tb) {
1091
        /* the PC is inside the translated code. It means that we have
1092
           a virtual CPU fault */
1093
        cpu_restore_state(tb, env, pc, puc);
1094
    }
1095
#if 0
1096
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1097
               env->nip, env->error_code, tb);
1098
#endif
1099
    /* we restore the process signal mask as the sigreturn should
1100
       do it (XXX: use sigsetjmp) */
1101
    sigprocmask(SIG_SETMASK, old_set, NULL);
1102
    cpu_loop_exit();
1103
    /* never comes here */
1104
    return 1;
1105
}
1106
#elif defined (TARGET_CRIS)
1107
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1108
                                    int is_write, sigset_t *old_set,
1109
                                    void *puc)
1110
{
1111
    TranslationBlock *tb;
1112
    int ret;
1113

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

    
1125
    /* see if it is an MMU fault */
1126
    ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1127
    if (ret < 0)
1128
        return 0; /* not an MMU fault */
1129
    if (ret == 0)
1130
        return 1; /* the MMU fault was handled without causing real CPU fault */
1131

    
1132
    /* now we have a real cpu fault */
1133
    tb = tb_find_pc(pc);
1134
    if (tb) {
1135
        /* the PC is inside the translated code. It means that we have
1136
           a virtual CPU fault */
1137
        cpu_restore_state(tb, env, pc, puc);
1138
    }
1139
    /* we restore the process signal mask as the sigreturn should
1140
       do it (XXX: use sigsetjmp) */
1141
    sigprocmask(SIG_SETMASK, old_set, NULL);
1142
    cpu_loop_exit();
1143
    /* never comes here */
1144
    return 1;
1145
}
1146

    
1147
#else
1148
#error unsupported target CPU
1149
#endif
1150

    
1151
#if defined(__i386__)
1152

    
1153
#if defined(__APPLE__)
1154
# include <sys/ucontext.h>
1155

    
1156
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1157
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
1158
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
1159
#else
1160
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
1161
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
1162
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
1163
#endif
1164

    
1165
int cpu_signal_handler(int host_signum, void *pinfo,
1166
                       void *puc)
1167
{
1168
    siginfo_t *info = pinfo;
1169
    struct ucontext *uc = puc;
1170
    unsigned long pc;
1171
    int trapno;
1172

    
1173
#ifndef REG_EIP
1174
/* for glibc 2.1 */
1175
#define REG_EIP    EIP
1176
#define REG_ERR    ERR
1177
#define REG_TRAPNO TRAPNO
1178
#endif
1179
    pc = EIP_sig(uc);
1180
    trapno = TRAP_sig(uc);
1181
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1182
                             trapno == 0xe ?
1183
                             (ERROR_sig(uc) >> 1) & 1 : 0,
1184
                             &uc->uc_sigmask, puc);
1185
}
1186

    
1187
#elif defined(__x86_64__)
1188

    
1189
#ifdef __NetBSD__
1190
#define REG_ERR _REG_ERR
1191
#define REG_TRAPNO _REG_TRAPNO
1192

    
1193
#define QEMU_UC_MCONTEXT_GREGS(uc, reg)        (uc)->uc_mcontext.__gregs[(reg)]
1194
#define QEMU_UC_MACHINE_PC(uc)                _UC_MACHINE_PC(uc)
1195
#else
1196
#define QEMU_UC_MCONTEXT_GREGS(uc, reg)        (uc)->uc_mcontext.gregs[(reg)]
1197
#define QEMU_UC_MACHINE_PC(uc)                QEMU_UC_MCONTEXT_GREGS(uc, REG_RIP)
1198
#endif
1199

    
1200
int cpu_signal_handler(int host_signum, void *pinfo,
1201
                       void *puc)
1202
{
1203
    siginfo_t *info = pinfo;
1204
    unsigned long pc;
1205
#ifdef __NetBSD__
1206
    ucontext_t *uc = puc;
1207
#else
1208
    struct ucontext *uc = puc;
1209
#endif
1210

    
1211
    pc = QEMU_UC_MACHINE_PC(uc);
1212
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1213
                             QEMU_UC_MCONTEXT_GREGS(uc, REG_TRAPNO) == 0xe ?
1214
                             (QEMU_UC_MCONTEXT_GREGS(uc, REG_ERR) >> 1) & 1 : 0,
1215
                             &uc->uc_sigmask, puc);
1216
}
1217

    
1218
#elif defined(_ARCH_PPC)
1219

    
1220
/***********************************************************************
1221
 * signal context platform-specific definitions
1222
 * From Wine
1223
 */
1224
#ifdef linux
1225
/* All Registers access - only for local access */
1226
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
1227
/* Gpr Registers access  */
1228
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
1229
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
1230
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
1231
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
1232
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
1233
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
1234
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
1235
/* Float Registers access  */
1236
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1237
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1238
/* Exception Registers access */
1239
# define DAR_sig(context)                        REG_sig(dar, context)
1240
# define DSISR_sig(context)                        REG_sig(dsisr, context)
1241
# define TRAP_sig(context)                        REG_sig(trap, context)
1242
#endif /* linux */
1243

    
1244
#ifdef __APPLE__
1245
# include <sys/ucontext.h>
1246
typedef struct ucontext SIGCONTEXT;
1247
/* All Registers access - only for local access */
1248
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
1249
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
1250
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
1251
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
1252
/* Gpr Registers access */
1253
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
1254
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
1255
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
1256
# define CTR_sig(context)                        REG_sig(ctr, context)
1257
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
1258
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
1259
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
1260
/* Float Registers access */
1261
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
1262
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
1263
/* Exception Registers access */
1264
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
1265
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
1266
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1267
#endif /* __APPLE__ */
1268

    
1269
int cpu_signal_handler(int host_signum, void *pinfo,
1270
                       void *puc)
1271
{
1272
    siginfo_t *info = pinfo;
1273
    struct ucontext *uc = puc;
1274
    unsigned long pc;
1275
    int is_write;
1276

    
1277
    pc = IAR_sig(uc);
1278
    is_write = 0;
1279
#if 0
1280
    /* ppc 4xx case */
1281
    if (DSISR_sig(uc) & 0x00800000)
1282
        is_write = 1;
1283
#else
1284
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1285
        is_write = 1;
1286
#endif
1287
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1288
                             is_write, &uc->uc_sigmask, puc);
1289
}
1290

    
1291
#elif defined(__alpha__)
1292

    
1293
int cpu_signal_handler(int host_signum, void *pinfo,
1294
                           void *puc)
1295
{
1296
    siginfo_t *info = pinfo;
1297
    struct ucontext *uc = puc;
1298
    uint32_t *pc = uc->uc_mcontext.sc_pc;
1299
    uint32_t insn = *pc;
1300
    int is_write = 0;
1301

    
1302
    /* XXX: need kernel patch to get write flag faster */
1303
    switch (insn >> 26) {
1304
    case 0x0d: // stw
1305
    case 0x0e: // stb
1306
    case 0x0f: // stq_u
1307
    case 0x24: // stf
1308
    case 0x25: // stg
1309
    case 0x26: // sts
1310
    case 0x27: // stt
1311
    case 0x2c: // stl
1312
    case 0x2d: // stq
1313
    case 0x2e: // stl_c
1314
    case 0x2f: // stq_c
1315
        is_write = 1;
1316
    }
1317

    
1318
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1319
                             is_write, &uc->uc_sigmask, puc);
1320
}
1321
#elif defined(__sparc__)
1322

    
1323
int cpu_signal_handler(int host_signum, void *pinfo,
1324
                       void *puc)
1325
{
1326
    siginfo_t *info = pinfo;
1327
    int is_write;
1328
    uint32_t insn;
1329
#if !defined(__arch64__) || defined(HOST_SOLARIS)
1330
    uint32_t *regs = (uint32_t *)(info + 1);
1331
    void *sigmask = (regs + 20);
1332
    /* XXX: is there a standard glibc define ? */
1333
    unsigned long pc = regs[1];
1334
#else
1335
#ifdef __linux__
1336
    struct sigcontext *sc = puc;
1337
    unsigned long pc = sc->sigc_regs.tpc;
1338
    void *sigmask = (void *)sc->sigc_mask;
1339
#elif defined(__OpenBSD__)
1340
    struct sigcontext *uc = puc;
1341
    unsigned long pc = uc->sc_pc;
1342
    void *sigmask = (void *)(long)uc->sc_mask;
1343
#endif
1344
#endif
1345

    
1346
    /* XXX: need kernel patch to get write flag faster */
1347
    is_write = 0;
1348
    insn = *(uint32_t *)pc;
1349
    if ((insn >> 30) == 3) {
1350
      switch((insn >> 19) & 0x3f) {
1351
      case 0x05: // stb
1352
      case 0x06: // sth
1353
      case 0x04: // st
1354
      case 0x07: // std
1355
      case 0x24: // stf
1356
      case 0x27: // stdf
1357
      case 0x25: // stfsr
1358
        is_write = 1;
1359
        break;
1360
      }
1361
    }
1362
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1363
                             is_write, sigmask, NULL);
1364
}
1365

    
1366
#elif defined(__arm__)
1367

    
1368
int cpu_signal_handler(int host_signum, void *pinfo,
1369
                       void *puc)
1370
{
1371
    siginfo_t *info = pinfo;
1372
    struct ucontext *uc = puc;
1373
    unsigned long pc;
1374
    int is_write;
1375

    
1376
#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1377
    pc = uc->uc_mcontext.gregs[R15];
1378
#else
1379
    pc = uc->uc_mcontext.arm_pc;
1380
#endif
1381
    /* XXX: compute is_write */
1382
    is_write = 0;
1383
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1384
                             is_write,
1385
                             &uc->uc_sigmask, puc);
1386
}
1387

    
1388
#elif defined(__mc68000)
1389

    
1390
int cpu_signal_handler(int host_signum, void *pinfo,
1391
                       void *puc)
1392
{
1393
    siginfo_t *info = pinfo;
1394
    struct ucontext *uc = puc;
1395
    unsigned long pc;
1396
    int is_write;
1397

    
1398
    pc = uc->uc_mcontext.gregs[16];
1399
    /* XXX: compute is_write */
1400
    is_write = 0;
1401
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1402
                             is_write,
1403
                             &uc->uc_sigmask, puc);
1404
}
1405

    
1406
#elif defined(__ia64)
1407

    
1408
#ifndef __ISR_VALID
1409
  /* This ought to be in <bits/siginfo.h>... */
1410
# define __ISR_VALID        1
1411
#endif
1412

    
1413
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1414
{
1415
    siginfo_t *info = pinfo;
1416
    struct ucontext *uc = puc;
1417
    unsigned long ip;
1418
    int is_write = 0;
1419

    
1420
    ip = uc->uc_mcontext.sc_ip;
1421
    switch (host_signum) {
1422
      case SIGILL:
1423
      case SIGFPE:
1424
      case SIGSEGV:
1425
      case SIGBUS:
1426
      case SIGTRAP:
1427
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1428
              /* ISR.W (write-access) is bit 33:  */
1429
              is_write = (info->si_isr >> 33) & 1;
1430
          break;
1431

    
1432
      default:
1433
          break;
1434
    }
1435
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1436
                             is_write,
1437
                             &uc->uc_sigmask, puc);
1438
}
1439

    
1440
#elif defined(__s390__)
1441

    
1442
int cpu_signal_handler(int host_signum, void *pinfo,
1443
                       void *puc)
1444
{
1445
    siginfo_t *info = pinfo;
1446
    struct ucontext *uc = puc;
1447
    unsigned long pc;
1448
    int is_write;
1449

    
1450
    pc = uc->uc_mcontext.psw.addr;
1451
    /* XXX: compute is_write */
1452
    is_write = 0;
1453
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1454
                             is_write, &uc->uc_sigmask, puc);
1455
}
1456

    
1457
#elif defined(__mips__)
1458

    
1459
int cpu_signal_handler(int host_signum, void *pinfo,
1460
                       void *puc)
1461
{
1462
    siginfo_t *info = pinfo;
1463
    struct ucontext *uc = puc;
1464
    greg_t pc = uc->uc_mcontext.pc;
1465
    int is_write;
1466

    
1467
    /* XXX: compute is_write */
1468
    is_write = 0;
1469
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1470
                             is_write, &uc->uc_sigmask, puc);
1471
}
1472

    
1473
#elif defined(__hppa__)
1474

    
1475
int cpu_signal_handler(int host_signum, void *pinfo,
1476
                       void *puc)
1477
{
1478
    struct siginfo *info = pinfo;
1479
    struct ucontext *uc = puc;
1480
    unsigned long pc;
1481
    int is_write;
1482

    
1483
    pc = uc->uc_mcontext.sc_iaoq[0];
1484
    /* FIXME: compute is_write */
1485
    is_write = 0;
1486
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1487
                             is_write,
1488
                             &uc->uc_sigmask, puc);
1489
}
1490

    
1491
#else
1492

    
1493
#error host CPU specific signal handler needed
1494

    
1495
#endif
1496

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