Statistics
| Branch: | Revision:

root / cpu-exec.c @ fad6cb1a

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

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

    
342
            next_tb = 0; /* force lookup of first TB */
343
            for(;;) {
344
                interrupt_request = env->interrupt_request;
345
                if (unlikely(interrupt_request)) {
346
                    if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
347
                        /* Mask out external interrupts for this step. */
348
                        interrupt_request &= ~(CPU_INTERRUPT_HARD |
349
                                               CPU_INTERRUPT_FIQ |
350
                                               CPU_INTERRUPT_SMI |
351
                                               CPU_INTERRUPT_NMI);
352
                    }
353
                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
354
                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
355
                        env->exception_index = EXCP_DEBUG;
356
                        cpu_loop_exit();
357
                    }
358
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
359
    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
360
                    if (interrupt_request & CPU_INTERRUPT_HALT) {
361
                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
362
                        env->halted = 1;
363
                        env->exception_index = EXCP_HLT;
364
                        cpu_loop_exit();
365
                    }
366
#endif
367
#if defined(TARGET_I386)
368
                    if (env->hflags2 & HF2_GIF_MASK) {
369
                        if ((interrupt_request & CPU_INTERRUPT_SMI) &&
370
                            !(env->hflags & HF_SMM_MASK)) {
371
                            svm_check_intercept(SVM_EXIT_SMI);
372
                            env->interrupt_request &= ~CPU_INTERRUPT_SMI;
373
                            do_smm_enter();
374
                            next_tb = 0;
375
                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
376
                                   !(env->hflags2 & HF2_NMI_MASK)) {
377
                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
378
                            env->hflags2 |= HF2_NMI_MASK;
379
                            do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
380
                            next_tb = 0;
381
                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
382
                                   (((env->hflags2 & HF2_VINTR_MASK) && 
383
                                     (env->hflags2 & HF2_HIF_MASK)) ||
384
                                    (!(env->hflags2 & HF2_VINTR_MASK) && 
385
                                     (env->eflags & IF_MASK && 
386
                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
387
                            int intno;
388
                            svm_check_intercept(SVM_EXIT_INTR);
389
                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
390
                            intno = cpu_get_pic_interrupt(env);
391
                            if (loglevel & CPU_LOG_TB_IN_ASM) {
392
                                fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
393
                            }
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
                            if (loglevel & CPU_LOG_TB_IN_ASM)
407
                                fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
408
                            do_interrupt(intno, 0, 0, 0, 1);
409
                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
410
                            next_tb = 0;
411
#endif
412
                        }
413
                    }
414
#elif defined(TARGET_PPC)
415
#if 0
416
                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
417
                        cpu_ppc_reset(env);
418
                    }
419
#endif
420
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
421
                        ppc_hw_interrupt(env);
422
                        if (env->pending_interrupts == 0)
423
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
424
                        next_tb = 0;
425
                    }
426
#elif defined(TARGET_MIPS)
427
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
428
                        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
429
                        (env->CP0_Status & (1 << CP0St_IE)) &&
430
                        !(env->CP0_Status & (1 << CP0St_EXL)) &&
431
                        !(env->CP0_Status & (1 << CP0St_ERL)) &&
432
                        !(env->hflags & MIPS_HFLAG_DM)) {
433
                        /* Raise it */
434
                        env->exception_index = EXCP_EXT_INTERRUPT;
435
                        env->error_code = 0;
436
                        do_interrupt(env);
437
                        next_tb = 0;
438
                    }
439
#elif defined(TARGET_SPARC)
440
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
441
                        (env->psret != 0)) {
442
                        int pil = env->interrupt_index & 15;
443
                        int type = env->interrupt_index & 0xf0;
444

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

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

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

    
661

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

    
683
    /* restore global registers */
684
#include "hostregs_helper.h"
685

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

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

    
704
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
705

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

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

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

    
726
    saved_env = env;
727
    env = s;
728

    
729
    helper_fsave(ptr, data32);
730

    
731
    env = saved_env;
732
}
733

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

    
738
    saved_env = env;
739
    env = s;
740

    
741
    helper_frstor(ptr, data32);
742

    
743
    env = saved_env;
744
}
745

    
746
#endif /* TARGET_I386 */
747

    
748
#if !defined(CONFIG_SOFTMMU)
749

    
750
#if defined(TARGET_I386)
751

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1150
#else
1151
#error unsupported target CPU
1152
#endif
1153

    
1154
#if defined(__i386__)
1155

    
1156
#if defined(__APPLE__)
1157
# include <sys/ucontext.h>
1158

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

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

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

    
1190
#elif defined(__x86_64__)
1191

    
1192
#ifdef __NetBSD__
1193
#define REG_ERR _REG_ERR
1194
#define REG_TRAPNO _REG_TRAPNO
1195

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

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

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

    
1221
#elif defined(__powerpc__)
1222

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

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

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

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

    
1294
#elif defined(__alpha__)
1295

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

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

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

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

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

    
1369
#elif defined(__arm__)
1370

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

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

    
1391
#elif defined(__mc68000)
1392

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

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

    
1409
#elif defined(__ia64)
1410

    
1411
#ifndef __ISR_VALID
1412
  /* This ought to be in <bits/siginfo.h>... */
1413
# define __ISR_VALID        1
1414
#endif
1415

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

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

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

    
1443
#elif defined(__s390__)
1444

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

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

    
1460
#elif defined(__mips__)
1461

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

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

    
1476
#elif defined(__hppa__)
1477

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

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

    
1494
#else
1495

    
1496
#error host CPU specific signal handler needed
1497

    
1498
#endif
1499

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