Statistics
| Branch: | Revision:

root / cpu-exec.c @ 2a913eb1

History | View | Annotate | Download (50.8 kB)

1 7d13299d bellard
/*
2 7d13299d bellard
 *  i386 emulator main execution loop
3 5fafdf24 ths
 *
4 66321a11 bellard
 *  Copyright (c) 2003-2005 Fabrice Bellard
5 7d13299d bellard
 *
6 3ef693a0 bellard
 * This library is free software; you can redistribute it and/or
7 3ef693a0 bellard
 * modify it under the terms of the GNU Lesser General Public
8 3ef693a0 bellard
 * License as published by the Free Software Foundation; either
9 3ef693a0 bellard
 * version 2 of the License, or (at your option) any later version.
10 7d13299d bellard
 *
11 3ef693a0 bellard
 * This library is distributed in the hope that it will be useful,
12 3ef693a0 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 3ef693a0 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 3ef693a0 bellard
 * Lesser General Public License for more details.
15 7d13299d bellard
 *
16 3ef693a0 bellard
 * You should have received a copy of the GNU Lesser General Public
17 3ef693a0 bellard
 * License along with this library; if not, write to the Free Software
18 3ef693a0 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 7d13299d bellard
 */
20 e4533c7a bellard
#include "config.h"
21 7cb69cae bellard
#define CPU_NO_GLOBAL_REGS
22 93ac68bc bellard
#include "exec.h"
23 956034d7 bellard
#include "disas.h"
24 7cb69cae bellard
#include "tcg.h"
25 7ba1e619 aliguori
#include "kvm.h"
26 7d13299d bellard
27 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
28 fbf9eeb3 bellard
#undef EAX
29 fbf9eeb3 bellard
#undef ECX
30 fbf9eeb3 bellard
#undef EDX
31 fbf9eeb3 bellard
#undef EBX
32 fbf9eeb3 bellard
#undef ESP
33 fbf9eeb3 bellard
#undef EBP
34 fbf9eeb3 bellard
#undef ESI
35 fbf9eeb3 bellard
#undef EDI
36 fbf9eeb3 bellard
#undef EIP
37 fbf9eeb3 bellard
#include <signal.h>
38 84778508 blueswir1
#ifdef __linux__
39 fbf9eeb3 bellard
#include <sys/ucontext.h>
40 fbf9eeb3 bellard
#endif
41 84778508 blueswir1
#endif
42 fbf9eeb3 bellard
43 572a9d4a blueswir1
#if defined(__sparc__) && !defined(HOST_SOLARIS)
44 572a9d4a blueswir1
// Work around ugly bugs in glibc that mangle global register contents
45 572a9d4a blueswir1
#undef env
46 572a9d4a blueswir1
#define env cpu_single_env
47 572a9d4a blueswir1
#endif
48 572a9d4a blueswir1
49 36bdbe54 bellard
int tb_invalidated_flag;
50 36bdbe54 bellard
51 dc99065b bellard
//#define DEBUG_EXEC
52 9de5e440 bellard
//#define DEBUG_SIGNAL
53 7d13299d bellard
54 e4533c7a bellard
void cpu_loop_exit(void)
55 e4533c7a bellard
{
56 bfed01fc ths
    /* NOTE: the register at this point must be saved by hand because
57 bfed01fc ths
       longjmp restore them */
58 bfed01fc ths
    regs_to_env();
59 e4533c7a bellard
    longjmp(env->jmp_env, 1);
60 e4533c7a bellard
}
61 bfed01fc ths
62 fbf9eeb3 bellard
/* exit the current TB from a signal handler. The host registers are
63 fbf9eeb3 bellard
   restored in a state compatible with the CPU emulator
64 fbf9eeb3 bellard
 */
65 5fafdf24 ths
void cpu_resume_from_signal(CPUState *env1, void *puc)
66 fbf9eeb3 bellard
{
67 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
68 84778508 blueswir1
#ifdef __linux__
69 fbf9eeb3 bellard
    struct ucontext *uc = puc;
70 84778508 blueswir1
#elif defined(__OpenBSD__)
71 84778508 blueswir1
    struct sigcontext *uc = puc;
72 84778508 blueswir1
#endif
73 fbf9eeb3 bellard
#endif
74 fbf9eeb3 bellard
75 fbf9eeb3 bellard
    env = env1;
76 fbf9eeb3 bellard
77 fbf9eeb3 bellard
    /* XXX: restore cpu registers saved in host registers */
78 fbf9eeb3 bellard
79 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
80 fbf9eeb3 bellard
    if (puc) {
81 fbf9eeb3 bellard
        /* XXX: use siglongjmp ? */
82 84778508 blueswir1
#ifdef __linux__
83 fbf9eeb3 bellard
        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
84 84778508 blueswir1
#elif defined(__OpenBSD__)
85 84778508 blueswir1
        sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
86 84778508 blueswir1
#endif
87 fbf9eeb3 bellard
    }
88 fbf9eeb3 bellard
#endif
89 fbf9eeb3 bellard
    longjmp(env->jmp_env, 1);
90 fbf9eeb3 bellard
}
91 fbf9eeb3 bellard
92 2e70f6ef pbrook
/* Execute the code without caching the generated code. An interpreter
93 2e70f6ef pbrook
   could be used if available. */
94 2e70f6ef pbrook
static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
95 2e70f6ef pbrook
{
96 2e70f6ef pbrook
    unsigned long next_tb;
97 2e70f6ef pbrook
    TranslationBlock *tb;
98 2e70f6ef pbrook
99 2e70f6ef pbrook
    /* Should never happen.
100 2e70f6ef pbrook
       We only end up here when an existing TB is too long.  */
101 2e70f6ef pbrook
    if (max_cycles > CF_COUNT_MASK)
102 2e70f6ef pbrook
        max_cycles = CF_COUNT_MASK;
103 2e70f6ef pbrook
104 2e70f6ef pbrook
    tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
105 2e70f6ef pbrook
                     max_cycles);
106 2e70f6ef pbrook
    env->current_tb = tb;
107 2e70f6ef pbrook
    /* execute the generated code */
108 2e70f6ef pbrook
    next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
109 2e70f6ef pbrook
110 2e70f6ef pbrook
    if ((next_tb & 3) == 2) {
111 2e70f6ef pbrook
        /* Restore PC.  This may happen if async event occurs before
112 2e70f6ef pbrook
           the TB starts executing.  */
113 622ed360 aliguori
        cpu_pc_from_tb(env, tb);
114 2e70f6ef pbrook
    }
115 2e70f6ef pbrook
    tb_phys_invalidate(tb, -1);
116 2e70f6ef pbrook
    tb_free(tb);
117 2e70f6ef pbrook
}
118 2e70f6ef pbrook
119 8a40a180 bellard
static TranslationBlock *tb_find_slow(target_ulong pc,
120 8a40a180 bellard
                                      target_ulong cs_base,
121 c068688b j_mayer
                                      uint64_t flags)
122 8a40a180 bellard
{
123 8a40a180 bellard
    TranslationBlock *tb, **ptb1;
124 8a40a180 bellard
    unsigned int h;
125 8a40a180 bellard
    target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
126 3b46e624 ths
127 8a40a180 bellard
    tb_invalidated_flag = 0;
128 3b46e624 ths
129 8a40a180 bellard
    regs_to_env(); /* XXX: do it just before cpu_gen_code() */
130 3b46e624 ths
131 8a40a180 bellard
    /* find translated block using physical mappings */
132 8a40a180 bellard
    phys_pc = get_phys_addr_code(env, pc);
133 8a40a180 bellard
    phys_page1 = phys_pc & TARGET_PAGE_MASK;
134 8a40a180 bellard
    phys_page2 = -1;
135 8a40a180 bellard
    h = tb_phys_hash_func(phys_pc);
136 8a40a180 bellard
    ptb1 = &tb_phys_hash[h];
137 8a40a180 bellard
    for(;;) {
138 8a40a180 bellard
        tb = *ptb1;
139 8a40a180 bellard
        if (!tb)
140 8a40a180 bellard
            goto not_found;
141 5fafdf24 ths
        if (tb->pc == pc &&
142 8a40a180 bellard
            tb->page_addr[0] == phys_page1 &&
143 5fafdf24 ths
            tb->cs_base == cs_base &&
144 8a40a180 bellard
            tb->flags == flags) {
145 8a40a180 bellard
            /* check next page if needed */
146 8a40a180 bellard
            if (tb->page_addr[1] != -1) {
147 5fafdf24 ths
                virt_page2 = (pc & TARGET_PAGE_MASK) +
148 8a40a180 bellard
                    TARGET_PAGE_SIZE;
149 8a40a180 bellard
                phys_page2 = get_phys_addr_code(env, virt_page2);
150 8a40a180 bellard
                if (tb->page_addr[1] == phys_page2)
151 8a40a180 bellard
                    goto found;
152 8a40a180 bellard
            } else {
153 8a40a180 bellard
                goto found;
154 8a40a180 bellard
            }
155 8a40a180 bellard
        }
156 8a40a180 bellard
        ptb1 = &tb->phys_hash_next;
157 8a40a180 bellard
    }
158 8a40a180 bellard
 not_found:
159 2e70f6ef pbrook
   /* if no translated code available, then translate it now */
160 2e70f6ef pbrook
    tb = tb_gen_code(env, pc, cs_base, flags, 0);
161 3b46e624 ths
162 8a40a180 bellard
 found:
163 8a40a180 bellard
    /* we add the TB in the virtual pc hash table */
164 8a40a180 bellard
    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
165 8a40a180 bellard
    return tb;
166 8a40a180 bellard
}
167 8a40a180 bellard
168 8a40a180 bellard
static inline TranslationBlock *tb_find_fast(void)
169 8a40a180 bellard
{
170 8a40a180 bellard
    TranslationBlock *tb;
171 8a40a180 bellard
    target_ulong cs_base, pc;
172 6b917547 aliguori
    int flags;
173 8a40a180 bellard
174 8a40a180 bellard
    /* we record a subset of the CPU state. It will
175 8a40a180 bellard
       always be the same before a given translated block
176 8a40a180 bellard
       is executed. */
177 6b917547 aliguori
    cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
178 bce61846 bellard
    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
179 551bd27f ths
    if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
180 551bd27f ths
                 tb->flags != flags)) {
181 8a40a180 bellard
        tb = tb_find_slow(pc, cs_base, flags);
182 8a40a180 bellard
    }
183 8a40a180 bellard
    return tb;
184 8a40a180 bellard
}
185 8a40a180 bellard
186 dde2367e aliguori
static CPUDebugExcpHandler *debug_excp_handler;
187 dde2367e aliguori
188 dde2367e aliguori
CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
189 dde2367e aliguori
{
190 dde2367e aliguori
    CPUDebugExcpHandler *old_handler = debug_excp_handler;
191 dde2367e aliguori
192 dde2367e aliguori
    debug_excp_handler = handler;
193 dde2367e aliguori
    return old_handler;
194 dde2367e aliguori
}
195 dde2367e aliguori
196 6e140f28 aliguori
static void cpu_handle_debug_exception(CPUState *env)
197 6e140f28 aliguori
{
198 6e140f28 aliguori
    CPUWatchpoint *wp;
199 6e140f28 aliguori
200 6e140f28 aliguori
    if (!env->watchpoint_hit)
201 c0ce998e aliguori
        TAILQ_FOREACH(wp, &env->watchpoints, entry)
202 6e140f28 aliguori
            wp->flags &= ~BP_WATCHPOINT_HIT;
203 dde2367e aliguori
204 dde2367e aliguori
    if (debug_excp_handler)
205 dde2367e aliguori
        debug_excp_handler(env);
206 6e140f28 aliguori
}
207 6e140f28 aliguori
208 7d13299d bellard
/* main execution loop */
209 7d13299d bellard
210 e4533c7a bellard
int cpu_exec(CPUState *env1)
211 7d13299d bellard
{
212 1057eaa7 pbrook
#define DECLARE_HOST_REGS 1
213 1057eaa7 pbrook
#include "hostregs_helper.h"
214 8a40a180 bellard
    int ret, interrupt_request;
215 8a40a180 bellard
    TranslationBlock *tb;
216 c27004ec bellard
    uint8_t *tc_ptr;
217 d5975363 pbrook
    unsigned long next_tb;
218 8c6939c0 bellard
219 bfed01fc ths
    if (cpu_halted(env1) == EXCP_HALTED)
220 bfed01fc ths
        return EXCP_HALTED;
221 5a1e3cfc bellard
222 5fafdf24 ths
    cpu_single_env = env1;
223 6a00d601 bellard
224 7d13299d bellard
    /* first we save global registers */
225 1057eaa7 pbrook
#define SAVE_HOST_REGS 1
226 1057eaa7 pbrook
#include "hostregs_helper.h"
227 c27004ec bellard
    env = env1;
228 e4533c7a bellard
229 0d1a29f9 bellard
    env_to_regs();
230 ecb644f4 ths
#if defined(TARGET_I386)
231 9de5e440 bellard
    /* put eflags in CPU temporary format */
232 fc2b4c48 bellard
    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
233 fc2b4c48 bellard
    DF = 1 - (2 * ((env->eflags >> 10) & 1));
234 9de5e440 bellard
    CC_OP = CC_OP_EFLAGS;
235 fc2b4c48 bellard
    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
236 93ac68bc bellard
#elif defined(TARGET_SPARC)
237 e6e5906b pbrook
#elif defined(TARGET_M68K)
238 e6e5906b pbrook
    env->cc_op = CC_OP_FLAGS;
239 e6e5906b pbrook
    env->cc_dest = env->sr & 0xf;
240 e6e5906b pbrook
    env->cc_x = (env->sr >> 4) & 1;
241 ecb644f4 ths
#elif defined(TARGET_ALPHA)
242 ecb644f4 ths
#elif defined(TARGET_ARM)
243 ecb644f4 ths
#elif defined(TARGET_PPC)
244 6af0bf9c bellard
#elif defined(TARGET_MIPS)
245 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
246 f1ccf904 ths
#elif defined(TARGET_CRIS)
247 fdf9b3e8 bellard
    /* XXXXX */
248 e4533c7a bellard
#else
249 e4533c7a bellard
#error unsupported target CPU
250 e4533c7a bellard
#endif
251 3fb2ded1 bellard
    env->exception_index = -1;
252 9d27abd9 bellard
253 7d13299d bellard
    /* prepare setjmp context for exception handling */
254 3fb2ded1 bellard
    for(;;) {
255 3fb2ded1 bellard
        if (setjmp(env->jmp_env) == 0) {
256 ee8b7021 bellard
            env->current_tb = NULL;
257 3fb2ded1 bellard
            /* if an exception is pending, we execute it here */
258 3fb2ded1 bellard
            if (env->exception_index >= 0) {
259 3fb2ded1 bellard
                if (env->exception_index >= EXCP_INTERRUPT) {
260 3fb2ded1 bellard
                    /* exit request from the cpu execution loop */
261 3fb2ded1 bellard
                    ret = env->exception_index;
262 6e140f28 aliguori
                    if (ret == EXCP_DEBUG)
263 6e140f28 aliguori
                        cpu_handle_debug_exception(env);
264 3fb2ded1 bellard
                    break;
265 3fb2ded1 bellard
                } else if (env->user_mode_only) {
266 3fb2ded1 bellard
                    /* if user mode only, we simulate a fake exception
267 9f083493 ths
                       which will be handled outside the cpu execution
268 3fb2ded1 bellard
                       loop */
269 83479e77 bellard
#if defined(TARGET_I386)
270 5fafdf24 ths
                    do_interrupt_user(env->exception_index,
271 5fafdf24 ths
                                      env->exception_is_int,
272 5fafdf24 ths
                                      env->error_code,
273 3fb2ded1 bellard
                                      env->exception_next_eip);
274 eba01623 bellard
                    /* successfully delivered */
275 eba01623 bellard
                    env->old_exception = -1;
276 83479e77 bellard
#endif
277 3fb2ded1 bellard
                    ret = env->exception_index;
278 3fb2ded1 bellard
                    break;
279 3fb2ded1 bellard
                } else {
280 83479e77 bellard
#if defined(TARGET_I386)
281 3fb2ded1 bellard
                    /* simulate a real cpu exception. On i386, it can
282 3fb2ded1 bellard
                       trigger new exceptions, but we do not handle
283 3fb2ded1 bellard
                       double or triple faults yet. */
284 5fafdf24 ths
                    do_interrupt(env->exception_index,
285 5fafdf24 ths
                                 env->exception_is_int,
286 5fafdf24 ths
                                 env->error_code,
287 d05e66d2 bellard
                                 env->exception_next_eip, 0);
288 678dde13 ths
                    /* successfully delivered */
289 678dde13 ths
                    env->old_exception = -1;
290 ce09776b bellard
#elif defined(TARGET_PPC)
291 ce09776b bellard
                    do_interrupt(env);
292 6af0bf9c bellard
#elif defined(TARGET_MIPS)
293 6af0bf9c bellard
                    do_interrupt(env);
294 e95c8d51 bellard
#elif defined(TARGET_SPARC)
295 f2bc7e7f blueswir1
                    do_interrupt(env);
296 b5ff1b31 bellard
#elif defined(TARGET_ARM)
297 b5ff1b31 bellard
                    do_interrupt(env);
298 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
299 fdf9b3e8 bellard
                    do_interrupt(env);
300 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
301 eddf68a6 j_mayer
                    do_interrupt(env);
302 f1ccf904 ths
#elif defined(TARGET_CRIS)
303 f1ccf904 ths
                    do_interrupt(env);
304 0633879f pbrook
#elif defined(TARGET_M68K)
305 0633879f pbrook
                    do_interrupt(0);
306 83479e77 bellard
#endif
307 3fb2ded1 bellard
                }
308 3fb2ded1 bellard
                env->exception_index = -1;
309 5fafdf24 ths
            }
310 9df217a3 bellard
#ifdef USE_KQEMU
311 9df217a3 bellard
            if (kqemu_is_ok(env) && env->interrupt_request == 0) {
312 9df217a3 bellard
                int ret;
313 a7812ae4 pbrook
                env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
314 9df217a3 bellard
                ret = kqemu_cpu_exec(env);
315 9df217a3 bellard
                /* put eflags in CPU temporary format */
316 9df217a3 bellard
                CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
317 9df217a3 bellard
                DF = 1 - (2 * ((env->eflags >> 10) & 1));
318 9df217a3 bellard
                CC_OP = CC_OP_EFLAGS;
319 9df217a3 bellard
                env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
320 9df217a3 bellard
                if (ret == 1) {
321 9df217a3 bellard
                    /* exception */
322 9df217a3 bellard
                    longjmp(env->jmp_env, 1);
323 9df217a3 bellard
                } else if (ret == 2) {
324 9df217a3 bellard
                    /* softmmu execution needed */
325 9df217a3 bellard
                } else {
326 9df217a3 bellard
                    if (env->interrupt_request != 0) {
327 9df217a3 bellard
                        /* hardware interrupt will be executed just after */
328 9df217a3 bellard
                    } else {
329 9df217a3 bellard
                        /* otherwise, we restart */
330 9df217a3 bellard
                        longjmp(env->jmp_env, 1);
331 9df217a3 bellard
                    }
332 9df217a3 bellard
                }
333 3fb2ded1 bellard
            }
334 9df217a3 bellard
#endif
335 9df217a3 bellard
336 7ba1e619 aliguori
            if (kvm_enabled()) {
337 becfc390 aliguori
                kvm_cpu_exec(env);
338 becfc390 aliguori
                longjmp(env->jmp_env, 1);
339 7ba1e619 aliguori
            }
340 7ba1e619 aliguori
341 b5fc09ae blueswir1
            next_tb = 0; /* force lookup of first TB */
342 3fb2ded1 bellard
            for(;;) {
343 68a79315 bellard
                interrupt_request = env->interrupt_request;
344 e1638bd8 malc
                if (unlikely(interrupt_request)) {
345 e1638bd8 malc
                    if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
346 e1638bd8 malc
                        /* Mask out external interrupts for this step. */
347 e1638bd8 malc
                        interrupt_request &= ~(CPU_INTERRUPT_HARD |
348 e1638bd8 malc
                                               CPU_INTERRUPT_FIQ |
349 e1638bd8 malc
                                               CPU_INTERRUPT_SMI |
350 e1638bd8 malc
                                               CPU_INTERRUPT_NMI);
351 e1638bd8 malc
                    }
352 6658ffb8 pbrook
                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
353 6658ffb8 pbrook
                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
354 6658ffb8 pbrook
                        env->exception_index = EXCP_DEBUG;
355 6658ffb8 pbrook
                        cpu_loop_exit();
356 6658ffb8 pbrook
                    }
357 a90b7318 balrog
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
358 f1ccf904 ths
    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
359 a90b7318 balrog
                    if (interrupt_request & CPU_INTERRUPT_HALT) {
360 a90b7318 balrog
                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
361 a90b7318 balrog
                        env->halted = 1;
362 a90b7318 balrog
                        env->exception_index = EXCP_HLT;
363 a90b7318 balrog
                        cpu_loop_exit();
364 a90b7318 balrog
                    }
365 a90b7318 balrog
#endif
366 68a79315 bellard
#if defined(TARGET_I386)
367 db620f46 bellard
                    if (env->hflags2 & HF2_GIF_MASK) {
368 db620f46 bellard
                        if ((interrupt_request & CPU_INTERRUPT_SMI) &&
369 db620f46 bellard
                            !(env->hflags & HF_SMM_MASK)) {
370 db620f46 bellard
                            svm_check_intercept(SVM_EXIT_SMI);
371 db620f46 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_SMI;
372 db620f46 bellard
                            do_smm_enter();
373 db620f46 bellard
                            next_tb = 0;
374 db620f46 bellard
                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
375 db620f46 bellard
                                   !(env->hflags2 & HF2_NMI_MASK)) {
376 db620f46 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
377 db620f46 bellard
                            env->hflags2 |= HF2_NMI_MASK;
378 db620f46 bellard
                            do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
379 db620f46 bellard
                            next_tb = 0;
380 db620f46 bellard
                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
381 db620f46 bellard
                                   (((env->hflags2 & HF2_VINTR_MASK) && 
382 db620f46 bellard
                                     (env->hflags2 & HF2_HIF_MASK)) ||
383 db620f46 bellard
                                    (!(env->hflags2 & HF2_VINTR_MASK) && 
384 db620f46 bellard
                                     (env->eflags & IF_MASK && 
385 db620f46 bellard
                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
386 db620f46 bellard
                            int intno;
387 db620f46 bellard
                            svm_check_intercept(SVM_EXIT_INTR);
388 db620f46 bellard
                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
389 db620f46 bellard
                            intno = cpu_get_pic_interrupt(env);
390 db620f46 bellard
                            if (loglevel & CPU_LOG_TB_IN_ASM) {
391 db620f46 bellard
                                fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
392 db620f46 bellard
                            }
393 db620f46 bellard
                            do_interrupt(intno, 0, 0, 0, 1);
394 db620f46 bellard
                            /* ensure that no TB jump will be modified as
395 db620f46 bellard
                               the program flow was changed */
396 db620f46 bellard
                            next_tb = 0;
397 0573fbfc ths
#if !defined(CONFIG_USER_ONLY)
398 db620f46 bellard
                        } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
399 db620f46 bellard
                                   (env->eflags & IF_MASK) && 
400 db620f46 bellard
                                   !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
401 db620f46 bellard
                            int intno;
402 db620f46 bellard
                            /* FIXME: this should respect TPR */
403 db620f46 bellard
                            svm_check_intercept(SVM_EXIT_VINTR);
404 db620f46 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
405 db620f46 bellard
                            intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
406 db620f46 bellard
                            if (loglevel & CPU_LOG_TB_IN_ASM)
407 db620f46 bellard
                                fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
408 db620f46 bellard
                            do_interrupt(intno, 0, 0, 0, 1);
409 db620f46 bellard
                            next_tb = 0;
410 0573fbfc ths
#endif
411 db620f46 bellard
                        }
412 68a79315 bellard
                    }
413 ce09776b bellard
#elif defined(TARGET_PPC)
414 9fddaa0c bellard
#if 0
415 9fddaa0c bellard
                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
416 9fddaa0c bellard
                        cpu_ppc_reset(env);
417 9fddaa0c bellard
                    }
418 9fddaa0c bellard
#endif
419 47103572 j_mayer
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
420 e9df014c j_mayer
                        ppc_hw_interrupt(env);
421 e9df014c j_mayer
                        if (env->pending_interrupts == 0)
422 e9df014c j_mayer
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
423 b5fc09ae blueswir1
                        next_tb = 0;
424 ce09776b bellard
                    }
425 6af0bf9c bellard
#elif defined(TARGET_MIPS)
426 6af0bf9c bellard
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
427 24c7b0e3 ths
                        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
428 6af0bf9c bellard
                        (env->CP0_Status & (1 << CP0St_IE)) &&
429 24c7b0e3 ths
                        !(env->CP0_Status & (1 << CP0St_EXL)) &&
430 24c7b0e3 ths
                        !(env->CP0_Status & (1 << CP0St_ERL)) &&
431 6af0bf9c bellard
                        !(env->hflags & MIPS_HFLAG_DM)) {
432 6af0bf9c bellard
                        /* Raise it */
433 6af0bf9c bellard
                        env->exception_index = EXCP_EXT_INTERRUPT;
434 6af0bf9c bellard
                        env->error_code = 0;
435 6af0bf9c bellard
                        do_interrupt(env);
436 b5fc09ae blueswir1
                        next_tb = 0;
437 6af0bf9c bellard
                    }
438 e95c8d51 bellard
#elif defined(TARGET_SPARC)
439 66321a11 bellard
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
440 66321a11 bellard
                        (env->psret != 0)) {
441 66321a11 bellard
                        int pil = env->interrupt_index & 15;
442 66321a11 bellard
                        int type = env->interrupt_index & 0xf0;
443 66321a11 bellard
444 66321a11 bellard
                        if (((type == TT_EXTINT) &&
445 66321a11 bellard
                             (pil == 15 || pil > env->psrpil)) ||
446 66321a11 bellard
                            type != TT_EXTINT) {
447 66321a11 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
448 f2bc7e7f blueswir1
                            env->exception_index = env->interrupt_index;
449 f2bc7e7f blueswir1
                            do_interrupt(env);
450 66321a11 bellard
                            env->interrupt_index = 0;
451 327ac2e7 blueswir1
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
452 327ac2e7 blueswir1
                            cpu_check_irqs(env);
453 327ac2e7 blueswir1
#endif
454 b5fc09ae blueswir1
                        next_tb = 0;
455 66321a11 bellard
                        }
456 e95c8d51 bellard
                    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
457 e95c8d51 bellard
                        //do_interrupt(0, 0, 0, 0, 0);
458 e95c8d51 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
459 a90b7318 balrog
                    }
460 b5ff1b31 bellard
#elif defined(TARGET_ARM)
461 b5ff1b31 bellard
                    if (interrupt_request & CPU_INTERRUPT_FIQ
462 b5ff1b31 bellard
                        && !(env->uncached_cpsr & CPSR_F)) {
463 b5ff1b31 bellard
                        env->exception_index = EXCP_FIQ;
464 b5ff1b31 bellard
                        do_interrupt(env);
465 b5fc09ae blueswir1
                        next_tb = 0;
466 b5ff1b31 bellard
                    }
467 9ee6e8bb pbrook
                    /* ARMv7-M interrupt return works by loading a magic value
468 9ee6e8bb pbrook
                       into the PC.  On real hardware the load causes the
469 9ee6e8bb pbrook
                       return to occur.  The qemu implementation performs the
470 9ee6e8bb pbrook
                       jump normally, then does the exception return when the
471 9ee6e8bb pbrook
                       CPU tries to execute code at the magic address.
472 9ee6e8bb pbrook
                       This will cause the magic PC value to be pushed to
473 9ee6e8bb pbrook
                       the stack if an interrupt occured at the wrong time.
474 9ee6e8bb pbrook
                       We avoid this by disabling interrupts when
475 9ee6e8bb pbrook
                       pc contains a magic address.  */
476 b5ff1b31 bellard
                    if (interrupt_request & CPU_INTERRUPT_HARD
477 9ee6e8bb pbrook
                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
478 9ee6e8bb pbrook
                            || !(env->uncached_cpsr & CPSR_I))) {
479 b5ff1b31 bellard
                        env->exception_index = EXCP_IRQ;
480 b5ff1b31 bellard
                        do_interrupt(env);
481 b5fc09ae blueswir1
                        next_tb = 0;
482 b5ff1b31 bellard
                    }
483 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
484 e96e2044 ths
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
485 e96e2044 ths
                        do_interrupt(env);
486 b5fc09ae blueswir1
                        next_tb = 0;
487 e96e2044 ths
                    }
488 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
489 eddf68a6 j_mayer
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
490 eddf68a6 j_mayer
                        do_interrupt(env);
491 b5fc09ae blueswir1
                        next_tb = 0;
492 eddf68a6 j_mayer
                    }
493 f1ccf904 ths
#elif defined(TARGET_CRIS)
494 1b1a38b0 edgar_igl
                    if (interrupt_request & CPU_INTERRUPT_HARD
495 1b1a38b0 edgar_igl
                        && (env->pregs[PR_CCS] & I_FLAG)) {
496 1b1a38b0 edgar_igl
                        env->exception_index = EXCP_IRQ;
497 1b1a38b0 edgar_igl
                        do_interrupt(env);
498 1b1a38b0 edgar_igl
                        next_tb = 0;
499 1b1a38b0 edgar_igl
                    }
500 1b1a38b0 edgar_igl
                    if (interrupt_request & CPU_INTERRUPT_NMI
501 1b1a38b0 edgar_igl
                        && (env->pregs[PR_CCS] & M_FLAG)) {
502 1b1a38b0 edgar_igl
                        env->exception_index = EXCP_NMI;
503 f1ccf904 ths
                        do_interrupt(env);
504 b5fc09ae blueswir1
                        next_tb = 0;
505 f1ccf904 ths
                    }
506 0633879f pbrook
#elif defined(TARGET_M68K)
507 0633879f pbrook
                    if (interrupt_request & CPU_INTERRUPT_HARD
508 0633879f pbrook
                        && ((env->sr & SR_I) >> SR_I_SHIFT)
509 0633879f pbrook
                            < env->pending_level) {
510 0633879f pbrook
                        /* Real hardware gets the interrupt vector via an
511 0633879f pbrook
                           IACK cycle at this point.  Current emulated
512 0633879f pbrook
                           hardware doesn't rely on this, so we
513 0633879f pbrook
                           provide/save the vector when the interrupt is
514 0633879f pbrook
                           first signalled.  */
515 0633879f pbrook
                        env->exception_index = env->pending_vector;
516 0633879f pbrook
                        do_interrupt(1);
517 b5fc09ae blueswir1
                        next_tb = 0;
518 0633879f pbrook
                    }
519 68a79315 bellard
#endif
520 9d05095e bellard
                   /* Don't use the cached interupt_request value,
521 9d05095e bellard
                      do_interrupt may have updated the EXITTB flag. */
522 b5ff1b31 bellard
                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
523 bf3e8bf1 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
524 bf3e8bf1 bellard
                        /* ensure that no TB jump will be modified as
525 bf3e8bf1 bellard
                           the program flow was changed */
526 b5fc09ae blueswir1
                        next_tb = 0;
527 bf3e8bf1 bellard
                    }
528 68a79315 bellard
                    if (interrupt_request & CPU_INTERRUPT_EXIT) {
529 68a79315 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
530 68a79315 bellard
                        env->exception_index = EXCP_INTERRUPT;
531 68a79315 bellard
                        cpu_loop_exit();
532 68a79315 bellard
                    }
533 3fb2ded1 bellard
                }
534 7d13299d bellard
#ifdef DEBUG_EXEC
535 b5ff1b31 bellard
                if ((loglevel & CPU_LOG_TB_CPU)) {
536 3fb2ded1 bellard
                    /* restore flags in standard format */
537 ecb644f4 ths
                    regs_to_env();
538 ecb644f4 ths
#if defined(TARGET_I386)
539 a7812ae4 pbrook
                    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
540 7fe48483 bellard
                    cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
541 3fb2ded1 bellard
                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
542 e4533c7a bellard
#elif defined(TARGET_ARM)
543 7fe48483 bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
544 93ac68bc bellard
#elif defined(TARGET_SPARC)
545 3475187d bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
546 67867308 bellard
#elif defined(TARGET_PPC)
547 7fe48483 bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
548 e6e5906b pbrook
#elif defined(TARGET_M68K)
549 e6e5906b pbrook
                    cpu_m68k_flush_flags(env, env->cc_op);
550 e6e5906b pbrook
                    env->cc_op = CC_OP_FLAGS;
551 e6e5906b pbrook
                    env->sr = (env->sr & 0xffe0)
552 e6e5906b pbrook
                              | env->cc_dest | (env->cc_x << 4);
553 e6e5906b pbrook
                    cpu_dump_state(env, logfile, fprintf, 0);
554 6af0bf9c bellard
#elif defined(TARGET_MIPS)
555 6af0bf9c bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
556 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
557 fdf9b3e8 bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
558 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
559 eddf68a6 j_mayer
                    cpu_dump_state(env, logfile, fprintf, 0);
560 f1ccf904 ths
#elif defined(TARGET_CRIS)
561 f1ccf904 ths
                    cpu_dump_state(env, logfile, fprintf, 0);
562 e4533c7a bellard
#else
563 5fafdf24 ths
#error unsupported target CPU
564 e4533c7a bellard
#endif
565 3fb2ded1 bellard
                }
566 7d13299d bellard
#endif
567 d5975363 pbrook
                spin_lock(&tb_lock);
568 8a40a180 bellard
                tb = tb_find_fast();
569 d5975363 pbrook
                /* Note: we do it here to avoid a gcc bug on Mac OS X when
570 d5975363 pbrook
                   doing it in tb_find_slow */
571 d5975363 pbrook
                if (tb_invalidated_flag) {
572 d5975363 pbrook
                    /* as some TB could have been invalidated because
573 d5975363 pbrook
                       of memory exceptions while generating the code, we
574 d5975363 pbrook
                       must recompute the hash index here */
575 d5975363 pbrook
                    next_tb = 0;
576 2e70f6ef pbrook
                    tb_invalidated_flag = 0;
577 d5975363 pbrook
                }
578 9d27abd9 bellard
#ifdef DEBUG_EXEC
579 c1135f61 bellard
                if ((loglevel & CPU_LOG_EXEC)) {
580 c27004ec bellard
                    fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
581 c27004ec bellard
                            (long)tb->tc_ptr, tb->pc,
582 c27004ec bellard
                            lookup_symbol(tb->pc));
583 3fb2ded1 bellard
                }
584 9d27abd9 bellard
#endif
585 8a40a180 bellard
                /* see if we can patch the calling TB. When the TB
586 8a40a180 bellard
                   spans two pages, we cannot safely do a direct
587 8a40a180 bellard
                   jump. */
588 c27004ec bellard
                {
589 b5fc09ae blueswir1
                    if (next_tb != 0 &&
590 4d7a0880 blueswir1
#ifdef USE_KQEMU
591 f32fc648 bellard
                        (env->kqemu_enabled != 2) &&
592 f32fc648 bellard
#endif
593 ec6338ba bellard
                        tb->page_addr[1] == -1) {
594 b5fc09ae blueswir1
                    tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
595 3fb2ded1 bellard
                }
596 c27004ec bellard
                }
597 d5975363 pbrook
                spin_unlock(&tb_lock);
598 83479e77 bellard
                env->current_tb = tb;
599 55e8b85e malc
600 55e8b85e malc
                /* cpu_interrupt might be called while translating the
601 55e8b85e malc
                   TB, but before it is linked into a potentially
602 55e8b85e malc
                   infinite loop and becomes env->current_tb. Avoid
603 55e8b85e malc
                   starting execution if there is a pending interrupt. */
604 55e8b85e malc
                if (unlikely (env->interrupt_request & CPU_INTERRUPT_EXIT))
605 55e8b85e malc
                    env->current_tb = NULL;
606 55e8b85e malc
607 2e70f6ef pbrook
                while (env->current_tb) {
608 2e70f6ef pbrook
                    tc_ptr = tb->tc_ptr;
609 3fb2ded1 bellard
                /* execute the generated code */
610 572a9d4a blueswir1
#if defined(__sparc__) && !defined(HOST_SOLARIS)
611 572a9d4a blueswir1
#undef env
612 2e70f6ef pbrook
                    env = cpu_single_env;
613 572a9d4a blueswir1
#define env cpu_single_env
614 572a9d4a blueswir1
#endif
615 2e70f6ef pbrook
                    next_tb = tcg_qemu_tb_exec(tc_ptr);
616 2e70f6ef pbrook
                    env->current_tb = NULL;
617 2e70f6ef pbrook
                    if ((next_tb & 3) == 2) {
618 bf20dc07 ths
                        /* Instruction counter expired.  */
619 2e70f6ef pbrook
                        int insns_left;
620 2e70f6ef pbrook
                        tb = (TranslationBlock *)(long)(next_tb & ~3);
621 2e70f6ef pbrook
                        /* Restore PC.  */
622 622ed360 aliguori
                        cpu_pc_from_tb(env, tb);
623 2e70f6ef pbrook
                        insns_left = env->icount_decr.u32;
624 2e70f6ef pbrook
                        if (env->icount_extra && insns_left >= 0) {
625 2e70f6ef pbrook
                            /* Refill decrementer and continue execution.  */
626 2e70f6ef pbrook
                            env->icount_extra += insns_left;
627 2e70f6ef pbrook
                            if (env->icount_extra > 0xffff) {
628 2e70f6ef pbrook
                                insns_left = 0xffff;
629 2e70f6ef pbrook
                            } else {
630 2e70f6ef pbrook
                                insns_left = env->icount_extra;
631 2e70f6ef pbrook
                            }
632 2e70f6ef pbrook
                            env->icount_extra -= insns_left;
633 2e70f6ef pbrook
                            env->icount_decr.u16.low = insns_left;
634 2e70f6ef pbrook
                        } else {
635 2e70f6ef pbrook
                            if (insns_left > 0) {
636 2e70f6ef pbrook
                                /* Execute remaining instructions.  */
637 2e70f6ef pbrook
                                cpu_exec_nocache(insns_left, tb);
638 2e70f6ef pbrook
                            }
639 2e70f6ef pbrook
                            env->exception_index = EXCP_INTERRUPT;
640 2e70f6ef pbrook
                            next_tb = 0;
641 2e70f6ef pbrook
                            cpu_loop_exit();
642 2e70f6ef pbrook
                        }
643 2e70f6ef pbrook
                    }
644 2e70f6ef pbrook
                }
645 4cbf74b6 bellard
                /* reset soft MMU for next block (it can currently
646 4cbf74b6 bellard
                   only be set by a memory fault) */
647 f32fc648 bellard
#if defined(USE_KQEMU)
648 f32fc648 bellard
#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
649 f32fc648 bellard
                if (kqemu_is_ok(env) &&
650 f32fc648 bellard
                    (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
651 f32fc648 bellard
                    cpu_loop_exit();
652 f32fc648 bellard
                }
653 f32fc648 bellard
#endif
654 50a518e3 ths
            } /* for(;;) */
655 3fb2ded1 bellard
        } else {
656 0d1a29f9 bellard
            env_to_regs();
657 7d13299d bellard
        }
658 3fb2ded1 bellard
    } /* for(;;) */
659 3fb2ded1 bellard
660 7d13299d bellard
661 e4533c7a bellard
#if defined(TARGET_I386)
662 9de5e440 bellard
    /* restore flags in standard format */
663 a7812ae4 pbrook
    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
664 e4533c7a bellard
#elif defined(TARGET_ARM)
665 b7bcbe95 bellard
    /* XXX: Save/restore host fpu exception state?.  */
666 93ac68bc bellard
#elif defined(TARGET_SPARC)
667 67867308 bellard
#elif defined(TARGET_PPC)
668 e6e5906b pbrook
#elif defined(TARGET_M68K)
669 e6e5906b pbrook
    cpu_m68k_flush_flags(env, env->cc_op);
670 e6e5906b pbrook
    env->cc_op = CC_OP_FLAGS;
671 e6e5906b pbrook
    env->sr = (env->sr & 0xffe0)
672 e6e5906b pbrook
              | env->cc_dest | (env->cc_x << 4);
673 6af0bf9c bellard
#elif defined(TARGET_MIPS)
674 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
675 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
676 f1ccf904 ths
#elif defined(TARGET_CRIS)
677 fdf9b3e8 bellard
    /* XXXXX */
678 e4533c7a bellard
#else
679 e4533c7a bellard
#error unsupported target CPU
680 e4533c7a bellard
#endif
681 1057eaa7 pbrook
682 1057eaa7 pbrook
    /* restore global registers */
683 1057eaa7 pbrook
#include "hostregs_helper.h"
684 1057eaa7 pbrook
685 6a00d601 bellard
    /* fail safe : never use cpu_single_env outside cpu_exec() */
686 5fafdf24 ths
    cpu_single_env = NULL;
687 7d13299d bellard
    return ret;
688 7d13299d bellard
}
689 6dbad63e bellard
690 fbf9eeb3 bellard
/* must only be called from the generated code as an exception can be
691 fbf9eeb3 bellard
   generated */
692 fbf9eeb3 bellard
void tb_invalidate_page_range(target_ulong start, target_ulong end)
693 fbf9eeb3 bellard
{
694 dc5d0b3d bellard
    /* XXX: cannot enable it yet because it yields to MMU exception
695 dc5d0b3d bellard
       where NIP != read address on PowerPC */
696 dc5d0b3d bellard
#if 0
697 fbf9eeb3 bellard
    target_ulong phys_addr;
698 fbf9eeb3 bellard
    phys_addr = get_phys_addr_code(env, start);
699 fbf9eeb3 bellard
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
700 dc5d0b3d bellard
#endif
701 fbf9eeb3 bellard
}
702 fbf9eeb3 bellard
703 1a18c71b bellard
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
704 e4533c7a bellard
705 6dbad63e bellard
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
706 6dbad63e bellard
{
707 6dbad63e bellard
    CPUX86State *saved_env;
708 6dbad63e bellard
709 6dbad63e bellard
    saved_env = env;
710 6dbad63e bellard
    env = s;
711 a412ac57 bellard
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
712 a513fe19 bellard
        selector &= 0xffff;
713 5fafdf24 ths
        cpu_x86_load_seg_cache(env, seg_reg, selector,
714 c27004ec bellard
                               (selector << 4), 0xffff, 0);
715 a513fe19 bellard
    } else {
716 5d97559d bellard
        helper_load_seg(seg_reg, selector);
717 a513fe19 bellard
    }
718 6dbad63e bellard
    env = saved_env;
719 6dbad63e bellard
}
720 9de5e440 bellard
721 6f12a2a6 bellard
void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
722 d0a1ffc9 bellard
{
723 d0a1ffc9 bellard
    CPUX86State *saved_env;
724 d0a1ffc9 bellard
725 d0a1ffc9 bellard
    saved_env = env;
726 d0a1ffc9 bellard
    env = s;
727 3b46e624 ths
728 6f12a2a6 bellard
    helper_fsave(ptr, data32);
729 d0a1ffc9 bellard
730 d0a1ffc9 bellard
    env = saved_env;
731 d0a1ffc9 bellard
}
732 d0a1ffc9 bellard
733 6f12a2a6 bellard
void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
734 d0a1ffc9 bellard
{
735 d0a1ffc9 bellard
    CPUX86State *saved_env;
736 d0a1ffc9 bellard
737 d0a1ffc9 bellard
    saved_env = env;
738 d0a1ffc9 bellard
    env = s;
739 3b46e624 ths
740 6f12a2a6 bellard
    helper_frstor(ptr, data32);
741 d0a1ffc9 bellard
742 d0a1ffc9 bellard
    env = saved_env;
743 d0a1ffc9 bellard
}
744 d0a1ffc9 bellard
745 e4533c7a bellard
#endif /* TARGET_I386 */
746 e4533c7a bellard
747 67b915a5 bellard
#if !defined(CONFIG_SOFTMMU)
748 67b915a5 bellard
749 3fb2ded1 bellard
#if defined(TARGET_I386)
750 3fb2ded1 bellard
751 b56dad1c bellard
/* 'pc' is the host PC at which the exception was raised. 'address' is
752 fd6ce8f6 bellard
   the effective address of the memory exception. 'is_write' is 1 if a
753 fd6ce8f6 bellard
   write caused the exception and otherwise 0'. 'old_set' is the
754 fd6ce8f6 bellard
   signal set which should be restored */
755 2b413144 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
756 5fafdf24 ths
                                    int is_write, sigset_t *old_set,
757 bf3e8bf1 bellard
                                    void *puc)
758 9de5e440 bellard
{
759 a513fe19 bellard
    TranslationBlock *tb;
760 a513fe19 bellard
    int ret;
761 68a79315 bellard
762 83479e77 bellard
    if (cpu_single_env)
763 83479e77 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
764 fd6ce8f6 bellard
#if defined(DEBUG_SIGNAL)
765 5fafdf24 ths
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
766 bf3e8bf1 bellard
                pc, address, is_write, *(unsigned long *)old_set);
767 9de5e440 bellard
#endif
768 25eb4484 bellard
    /* XXX: locking issue */
769 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
770 fd6ce8f6 bellard
        return 1;
771 fd6ce8f6 bellard
    }
772 fbf9eeb3 bellard
773 3fb2ded1 bellard
    /* see if it is an MMU fault */
774 6ebbf390 j_mayer
    ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
775 3fb2ded1 bellard
    if (ret < 0)
776 3fb2ded1 bellard
        return 0; /* not an MMU fault */
777 3fb2ded1 bellard
    if (ret == 0)
778 3fb2ded1 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
779 3fb2ded1 bellard
    /* now we have a real cpu fault */
780 a513fe19 bellard
    tb = tb_find_pc(pc);
781 a513fe19 bellard
    if (tb) {
782 9de5e440 bellard
        /* the PC is inside the translated code. It means that we have
783 9de5e440 bellard
           a virtual CPU fault */
784 bf3e8bf1 bellard
        cpu_restore_state(tb, env, pc, puc);
785 3fb2ded1 bellard
    }
786 4cbf74b6 bellard
    if (ret == 1) {
787 3fb2ded1 bellard
#if 0
788 5fafdf24 ths
        printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
789 4cbf74b6 bellard
               env->eip, env->cr[2], env->error_code);
790 3fb2ded1 bellard
#endif
791 4cbf74b6 bellard
        /* we restore the process signal mask as the sigreturn should
792 4cbf74b6 bellard
           do it (XXX: use sigsetjmp) */
793 4cbf74b6 bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
794 54ca9095 bellard
        raise_exception_err(env->exception_index, env->error_code);
795 4cbf74b6 bellard
    } else {
796 4cbf74b6 bellard
        /* activate soft MMU for this block */
797 3f337316 bellard
        env->hflags |= HF_SOFTMMU_MASK;
798 fbf9eeb3 bellard
        cpu_resume_from_signal(env, puc);
799 4cbf74b6 bellard
    }
800 3fb2ded1 bellard
    /* never comes here */
801 3fb2ded1 bellard
    return 1;
802 3fb2ded1 bellard
}
803 3fb2ded1 bellard
804 e4533c7a bellard
#elif defined(TARGET_ARM)
805 3fb2ded1 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
806 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set,
807 bf3e8bf1 bellard
                                    void *puc)
808 3fb2ded1 bellard
{
809 68016c62 bellard
    TranslationBlock *tb;
810 68016c62 bellard
    int ret;
811 68016c62 bellard
812 68016c62 bellard
    if (cpu_single_env)
813 68016c62 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
814 68016c62 bellard
#if defined(DEBUG_SIGNAL)
815 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
816 68016c62 bellard
           pc, address, is_write, *(unsigned long *)old_set);
817 68016c62 bellard
#endif
818 9f0777ed bellard
    /* XXX: locking issue */
819 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
820 9f0777ed bellard
        return 1;
821 9f0777ed bellard
    }
822 68016c62 bellard
    /* see if it is an MMU fault */
823 6ebbf390 j_mayer
    ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
824 68016c62 bellard
    if (ret < 0)
825 68016c62 bellard
        return 0; /* not an MMU fault */
826 68016c62 bellard
    if (ret == 0)
827 68016c62 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
828 68016c62 bellard
    /* now we have a real cpu fault */
829 68016c62 bellard
    tb = tb_find_pc(pc);
830 68016c62 bellard
    if (tb) {
831 68016c62 bellard
        /* the PC is inside the translated code. It means that we have
832 68016c62 bellard
           a virtual CPU fault */
833 68016c62 bellard
        cpu_restore_state(tb, env, pc, puc);
834 68016c62 bellard
    }
835 68016c62 bellard
    /* we restore the process signal mask as the sigreturn should
836 68016c62 bellard
       do it (XXX: use sigsetjmp) */
837 68016c62 bellard
    sigprocmask(SIG_SETMASK, old_set, NULL);
838 68016c62 bellard
    cpu_loop_exit();
839 968c74da aurel32
    /* never comes here */
840 968c74da aurel32
    return 1;
841 3fb2ded1 bellard
}
842 93ac68bc bellard
#elif defined(TARGET_SPARC)
843 93ac68bc bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
844 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set,
845 bf3e8bf1 bellard
                                    void *puc)
846 93ac68bc bellard
{
847 68016c62 bellard
    TranslationBlock *tb;
848 68016c62 bellard
    int ret;
849 68016c62 bellard
850 68016c62 bellard
    if (cpu_single_env)
851 68016c62 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
852 68016c62 bellard
#if defined(DEBUG_SIGNAL)
853 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
854 68016c62 bellard
           pc, address, is_write, *(unsigned long *)old_set);
855 68016c62 bellard
#endif
856 b453b70b bellard
    /* XXX: locking issue */
857 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
858 b453b70b bellard
        return 1;
859 b453b70b bellard
    }
860 68016c62 bellard
    /* see if it is an MMU fault */
861 6ebbf390 j_mayer
    ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
862 68016c62 bellard
    if (ret < 0)
863 68016c62 bellard
        return 0; /* not an MMU fault */
864 68016c62 bellard
    if (ret == 0)
865 68016c62 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
866 68016c62 bellard
    /* now we have a real cpu fault */
867 68016c62 bellard
    tb = tb_find_pc(pc);
868 68016c62 bellard
    if (tb) {
869 68016c62 bellard
        /* the PC is inside the translated code. It means that we have
870 68016c62 bellard
           a virtual CPU fault */
871 68016c62 bellard
        cpu_restore_state(tb, env, pc, puc);
872 68016c62 bellard
    }
873 68016c62 bellard
    /* we restore the process signal mask as the sigreturn should
874 68016c62 bellard
       do it (XXX: use sigsetjmp) */
875 68016c62 bellard
    sigprocmask(SIG_SETMASK, old_set, NULL);
876 68016c62 bellard
    cpu_loop_exit();
877 968c74da aurel32
    /* never comes here */
878 968c74da aurel32
    return 1;
879 93ac68bc bellard
}
880 67867308 bellard
#elif defined (TARGET_PPC)
881 67867308 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
882 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set,
883 bf3e8bf1 bellard
                                    void *puc)
884 67867308 bellard
{
885 67867308 bellard
    TranslationBlock *tb;
886 ce09776b bellard
    int ret;
887 3b46e624 ths
888 67867308 bellard
    if (cpu_single_env)
889 67867308 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
890 67867308 bellard
#if defined(DEBUG_SIGNAL)
891 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
892 67867308 bellard
           pc, address, is_write, *(unsigned long *)old_set);
893 67867308 bellard
#endif
894 67867308 bellard
    /* XXX: locking issue */
895 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
896 67867308 bellard
        return 1;
897 67867308 bellard
    }
898 67867308 bellard
899 ce09776b bellard
    /* see if it is an MMU fault */
900 6ebbf390 j_mayer
    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
901 ce09776b bellard
    if (ret < 0)
902 ce09776b bellard
        return 0; /* not an MMU fault */
903 ce09776b bellard
    if (ret == 0)
904 ce09776b bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
905 ce09776b bellard
906 67867308 bellard
    /* now we have a real cpu fault */
907 67867308 bellard
    tb = tb_find_pc(pc);
908 67867308 bellard
    if (tb) {
909 67867308 bellard
        /* the PC is inside the translated code. It means that we have
910 67867308 bellard
           a virtual CPU fault */
911 bf3e8bf1 bellard
        cpu_restore_state(tb, env, pc, puc);
912 67867308 bellard
    }
913 ce09776b bellard
    if (ret == 1) {
914 67867308 bellard
#if 0
915 5fafdf24 ths
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
916 ce09776b bellard
               env->nip, env->error_code, tb);
917 67867308 bellard
#endif
918 67867308 bellard
    /* we restore the process signal mask as the sigreturn should
919 67867308 bellard
       do it (XXX: use sigsetjmp) */
920 bf3e8bf1 bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
921 64adab3f aurel32
        raise_exception_err(env, env->exception_index, env->error_code);
922 ce09776b bellard
    } else {
923 ce09776b bellard
        /* activate soft MMU for this block */
924 fbf9eeb3 bellard
        cpu_resume_from_signal(env, puc);
925 ce09776b bellard
    }
926 67867308 bellard
    /* never comes here */
927 e6e5906b pbrook
    return 1;
928 e6e5906b pbrook
}
929 e6e5906b pbrook
930 e6e5906b pbrook
#elif defined(TARGET_M68K)
931 e6e5906b pbrook
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
932 e6e5906b pbrook
                                    int is_write, sigset_t *old_set,
933 e6e5906b pbrook
                                    void *puc)
934 e6e5906b pbrook
{
935 e6e5906b pbrook
    TranslationBlock *tb;
936 e6e5906b pbrook
    int ret;
937 e6e5906b pbrook
938 e6e5906b pbrook
    if (cpu_single_env)
939 e6e5906b pbrook
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
940 e6e5906b pbrook
#if defined(DEBUG_SIGNAL)
941 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
942 e6e5906b pbrook
           pc, address, is_write, *(unsigned long *)old_set);
943 e6e5906b pbrook
#endif
944 e6e5906b pbrook
    /* XXX: locking issue */
945 e6e5906b pbrook
    if (is_write && page_unprotect(address, pc, puc)) {
946 e6e5906b pbrook
        return 1;
947 e6e5906b pbrook
    }
948 e6e5906b pbrook
    /* see if it is an MMU fault */
949 6ebbf390 j_mayer
    ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
950 e6e5906b pbrook
    if (ret < 0)
951 e6e5906b pbrook
        return 0; /* not an MMU fault */
952 e6e5906b pbrook
    if (ret == 0)
953 e6e5906b pbrook
        return 1; /* the MMU fault was handled without causing real CPU fault */
954 e6e5906b pbrook
    /* now we have a real cpu fault */
955 e6e5906b pbrook
    tb = tb_find_pc(pc);
956 e6e5906b pbrook
    if (tb) {
957 e6e5906b pbrook
        /* the PC is inside the translated code. It means that we have
958 e6e5906b pbrook
           a virtual CPU fault */
959 e6e5906b pbrook
        cpu_restore_state(tb, env, pc, puc);
960 e6e5906b pbrook
    }
961 e6e5906b pbrook
    /* we restore the process signal mask as the sigreturn should
962 e6e5906b pbrook
       do it (XXX: use sigsetjmp) */
963 e6e5906b pbrook
    sigprocmask(SIG_SETMASK, old_set, NULL);
964 e6e5906b pbrook
    cpu_loop_exit();
965 e6e5906b pbrook
    /* never comes here */
966 67867308 bellard
    return 1;
967 67867308 bellard
}
968 6af0bf9c bellard
969 6af0bf9c bellard
#elif defined (TARGET_MIPS)
970 6af0bf9c bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
971 6af0bf9c bellard
                                    int is_write, sigset_t *old_set,
972 6af0bf9c bellard
                                    void *puc)
973 6af0bf9c bellard
{
974 6af0bf9c bellard
    TranslationBlock *tb;
975 6af0bf9c bellard
    int ret;
976 3b46e624 ths
977 6af0bf9c bellard
    if (cpu_single_env)
978 6af0bf9c bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
979 6af0bf9c bellard
#if defined(DEBUG_SIGNAL)
980 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
981 6af0bf9c bellard
           pc, address, is_write, *(unsigned long *)old_set);
982 6af0bf9c bellard
#endif
983 6af0bf9c bellard
    /* XXX: locking issue */
984 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
985 6af0bf9c bellard
        return 1;
986 6af0bf9c bellard
    }
987 6af0bf9c bellard
988 6af0bf9c bellard
    /* see if it is an MMU fault */
989 6ebbf390 j_mayer
    ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
990 6af0bf9c bellard
    if (ret < 0)
991 6af0bf9c bellard
        return 0; /* not an MMU fault */
992 6af0bf9c bellard
    if (ret == 0)
993 6af0bf9c bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
994 6af0bf9c bellard
995 6af0bf9c bellard
    /* now we have a real cpu fault */
996 6af0bf9c bellard
    tb = tb_find_pc(pc);
997 6af0bf9c bellard
    if (tb) {
998 6af0bf9c bellard
        /* the PC is inside the translated code. It means that we have
999 6af0bf9c bellard
           a virtual CPU fault */
1000 6af0bf9c bellard
        cpu_restore_state(tb, env, pc, puc);
1001 6af0bf9c bellard
    }
1002 6af0bf9c bellard
    if (ret == 1) {
1003 6af0bf9c bellard
#if 0
1004 5fafdf24 ths
        printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1005 1eb5207b ths
               env->PC, env->error_code, tb);
1006 6af0bf9c bellard
#endif
1007 6af0bf9c bellard
    /* we restore the process signal mask as the sigreturn should
1008 6af0bf9c bellard
       do it (XXX: use sigsetjmp) */
1009 6af0bf9c bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
1010 6af0bf9c bellard
        do_raise_exception_err(env->exception_index, env->error_code);
1011 6af0bf9c bellard
    } else {
1012 6af0bf9c bellard
        /* activate soft MMU for this block */
1013 6af0bf9c bellard
        cpu_resume_from_signal(env, puc);
1014 6af0bf9c bellard
    }
1015 6af0bf9c bellard
    /* never comes here */
1016 6af0bf9c bellard
    return 1;
1017 6af0bf9c bellard
}
1018 6af0bf9c bellard
1019 fdf9b3e8 bellard
#elif defined (TARGET_SH4)
1020 fdf9b3e8 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1021 fdf9b3e8 bellard
                                    int is_write, sigset_t *old_set,
1022 fdf9b3e8 bellard
                                    void *puc)
1023 fdf9b3e8 bellard
{
1024 fdf9b3e8 bellard
    TranslationBlock *tb;
1025 fdf9b3e8 bellard
    int ret;
1026 3b46e624 ths
1027 fdf9b3e8 bellard
    if (cpu_single_env)
1028 fdf9b3e8 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1029 fdf9b3e8 bellard
#if defined(DEBUG_SIGNAL)
1030 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1031 fdf9b3e8 bellard
           pc, address, is_write, *(unsigned long *)old_set);
1032 fdf9b3e8 bellard
#endif
1033 fdf9b3e8 bellard
    /* XXX: locking issue */
1034 fdf9b3e8 bellard
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1035 fdf9b3e8 bellard
        return 1;
1036 fdf9b3e8 bellard
    }
1037 fdf9b3e8 bellard
1038 fdf9b3e8 bellard
    /* see if it is an MMU fault */
1039 6ebbf390 j_mayer
    ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1040 fdf9b3e8 bellard
    if (ret < 0)
1041 fdf9b3e8 bellard
        return 0; /* not an MMU fault */
1042 fdf9b3e8 bellard
    if (ret == 0)
1043 fdf9b3e8 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
1044 fdf9b3e8 bellard
1045 fdf9b3e8 bellard
    /* now we have a real cpu fault */
1046 eddf68a6 j_mayer
    tb = tb_find_pc(pc);
1047 eddf68a6 j_mayer
    if (tb) {
1048 eddf68a6 j_mayer
        /* the PC is inside the translated code. It means that we have
1049 eddf68a6 j_mayer
           a virtual CPU fault */
1050 eddf68a6 j_mayer
        cpu_restore_state(tb, env, pc, puc);
1051 eddf68a6 j_mayer
    }
1052 eddf68a6 j_mayer
#if 0
1053 5fafdf24 ths
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1054 eddf68a6 j_mayer
               env->nip, env->error_code, tb);
1055 eddf68a6 j_mayer
#endif
1056 eddf68a6 j_mayer
    /* we restore the process signal mask as the sigreturn should
1057 eddf68a6 j_mayer
       do it (XXX: use sigsetjmp) */
1058 eddf68a6 j_mayer
    sigprocmask(SIG_SETMASK, old_set, NULL);
1059 eddf68a6 j_mayer
    cpu_loop_exit();
1060 eddf68a6 j_mayer
    /* never comes here */
1061 eddf68a6 j_mayer
    return 1;
1062 eddf68a6 j_mayer
}
1063 eddf68a6 j_mayer
1064 eddf68a6 j_mayer
#elif defined (TARGET_ALPHA)
1065 eddf68a6 j_mayer
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1066 eddf68a6 j_mayer
                                    int is_write, sigset_t *old_set,
1067 eddf68a6 j_mayer
                                    void *puc)
1068 eddf68a6 j_mayer
{
1069 eddf68a6 j_mayer
    TranslationBlock *tb;
1070 eddf68a6 j_mayer
    int ret;
1071 3b46e624 ths
1072 eddf68a6 j_mayer
    if (cpu_single_env)
1073 eddf68a6 j_mayer
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1074 eddf68a6 j_mayer
#if defined(DEBUG_SIGNAL)
1075 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1076 eddf68a6 j_mayer
           pc, address, is_write, *(unsigned long *)old_set);
1077 eddf68a6 j_mayer
#endif
1078 eddf68a6 j_mayer
    /* XXX: locking issue */
1079 eddf68a6 j_mayer
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1080 eddf68a6 j_mayer
        return 1;
1081 eddf68a6 j_mayer
    }
1082 eddf68a6 j_mayer
1083 eddf68a6 j_mayer
    /* see if it is an MMU fault */
1084 6ebbf390 j_mayer
    ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1085 eddf68a6 j_mayer
    if (ret < 0)
1086 eddf68a6 j_mayer
        return 0; /* not an MMU fault */
1087 eddf68a6 j_mayer
    if (ret == 0)
1088 eddf68a6 j_mayer
        return 1; /* the MMU fault was handled without causing real CPU fault */
1089 eddf68a6 j_mayer
1090 eddf68a6 j_mayer
    /* now we have a real cpu fault */
1091 fdf9b3e8 bellard
    tb = tb_find_pc(pc);
1092 fdf9b3e8 bellard
    if (tb) {
1093 fdf9b3e8 bellard
        /* the PC is inside the translated code. It means that we have
1094 fdf9b3e8 bellard
           a virtual CPU fault */
1095 fdf9b3e8 bellard
        cpu_restore_state(tb, env, pc, puc);
1096 fdf9b3e8 bellard
    }
1097 fdf9b3e8 bellard
#if 0
1098 5fafdf24 ths
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1099 fdf9b3e8 bellard
               env->nip, env->error_code, tb);
1100 fdf9b3e8 bellard
#endif
1101 fdf9b3e8 bellard
    /* we restore the process signal mask as the sigreturn should
1102 fdf9b3e8 bellard
       do it (XXX: use sigsetjmp) */
1103 355fb23d pbrook
    sigprocmask(SIG_SETMASK, old_set, NULL);
1104 355fb23d pbrook
    cpu_loop_exit();
1105 fdf9b3e8 bellard
    /* never comes here */
1106 fdf9b3e8 bellard
    return 1;
1107 fdf9b3e8 bellard
}
1108 f1ccf904 ths
#elif defined (TARGET_CRIS)
1109 f1ccf904 ths
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1110 f1ccf904 ths
                                    int is_write, sigset_t *old_set,
1111 f1ccf904 ths
                                    void *puc)
1112 f1ccf904 ths
{
1113 f1ccf904 ths
    TranslationBlock *tb;
1114 f1ccf904 ths
    int ret;
1115 f1ccf904 ths
1116 f1ccf904 ths
    if (cpu_single_env)
1117 f1ccf904 ths
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1118 f1ccf904 ths
#if defined(DEBUG_SIGNAL)
1119 f1ccf904 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1120 f1ccf904 ths
           pc, address, is_write, *(unsigned long *)old_set);
1121 f1ccf904 ths
#endif
1122 f1ccf904 ths
    /* XXX: locking issue */
1123 f1ccf904 ths
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1124 f1ccf904 ths
        return 1;
1125 f1ccf904 ths
    }
1126 f1ccf904 ths
1127 f1ccf904 ths
    /* see if it is an MMU fault */
1128 6ebbf390 j_mayer
    ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1129 f1ccf904 ths
    if (ret < 0)
1130 f1ccf904 ths
        return 0; /* not an MMU fault */
1131 f1ccf904 ths
    if (ret == 0)
1132 f1ccf904 ths
        return 1; /* the MMU fault was handled without causing real CPU fault */
1133 f1ccf904 ths
1134 f1ccf904 ths
    /* now we have a real cpu fault */
1135 f1ccf904 ths
    tb = tb_find_pc(pc);
1136 f1ccf904 ths
    if (tb) {
1137 f1ccf904 ths
        /* the PC is inside the translated code. It means that we have
1138 f1ccf904 ths
           a virtual CPU fault */
1139 f1ccf904 ths
        cpu_restore_state(tb, env, pc, puc);
1140 f1ccf904 ths
    }
1141 f1ccf904 ths
    /* we restore the process signal mask as the sigreturn should
1142 f1ccf904 ths
       do it (XXX: use sigsetjmp) */
1143 f1ccf904 ths
    sigprocmask(SIG_SETMASK, old_set, NULL);
1144 f1ccf904 ths
    cpu_loop_exit();
1145 f1ccf904 ths
    /* never comes here */
1146 f1ccf904 ths
    return 1;
1147 f1ccf904 ths
}
1148 f1ccf904 ths
1149 e4533c7a bellard
#else
1150 e4533c7a bellard
#error unsupported target CPU
1151 e4533c7a bellard
#endif
1152 9de5e440 bellard
1153 2b413144 bellard
#if defined(__i386__)
1154 2b413144 bellard
1155 d8ecc0b9 bellard
#if defined(__APPLE__)
1156 d8ecc0b9 bellard
# include <sys/ucontext.h>
1157 d8ecc0b9 bellard
1158 d8ecc0b9 bellard
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1159 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
1160 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
1161 d8ecc0b9 bellard
#else
1162 d8ecc0b9 bellard
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
1163 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
1164 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
1165 d8ecc0b9 bellard
#endif
1166 d8ecc0b9 bellard
1167 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1168 e4533c7a bellard
                       void *puc)
1169 9de5e440 bellard
{
1170 5a7b542b ths
    siginfo_t *info = pinfo;
1171 9de5e440 bellard
    struct ucontext *uc = puc;
1172 9de5e440 bellard
    unsigned long pc;
1173 bf3e8bf1 bellard
    int trapno;
1174 97eb5b14 bellard
1175 d691f669 bellard
#ifndef REG_EIP
1176 d691f669 bellard
/* for glibc 2.1 */
1177 fd6ce8f6 bellard
#define REG_EIP    EIP
1178 fd6ce8f6 bellard
#define REG_ERR    ERR
1179 fd6ce8f6 bellard
#define REG_TRAPNO TRAPNO
1180 d691f669 bellard
#endif
1181 d8ecc0b9 bellard
    pc = EIP_sig(uc);
1182 d8ecc0b9 bellard
    trapno = TRAP_sig(uc);
1183 ec6338ba bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1184 ec6338ba bellard
                             trapno == 0xe ?
1185 ec6338ba bellard
                             (ERROR_sig(uc) >> 1) & 1 : 0,
1186 ec6338ba bellard
                             &uc->uc_sigmask, puc);
1187 2b413144 bellard
}
1188 2b413144 bellard
1189 bc51c5c9 bellard
#elif defined(__x86_64__)
1190 bc51c5c9 bellard
1191 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo,
1192 bc51c5c9 bellard
                       void *puc)
1193 bc51c5c9 bellard
{
1194 5a7b542b ths
    siginfo_t *info = pinfo;
1195 bc51c5c9 bellard
    struct ucontext *uc = puc;
1196 bc51c5c9 bellard
    unsigned long pc;
1197 bc51c5c9 bellard
1198 bc51c5c9 bellard
    pc = uc->uc_mcontext.gregs[REG_RIP];
1199 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1200 5fafdf24 ths
                             uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
1201 bc51c5c9 bellard
                             (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1202 bc51c5c9 bellard
                             &uc->uc_sigmask, puc);
1203 bc51c5c9 bellard
}
1204 bc51c5c9 bellard
1205 83fb7adf bellard
#elif defined(__powerpc__)
1206 2b413144 bellard
1207 83fb7adf bellard
/***********************************************************************
1208 83fb7adf bellard
 * signal context platform-specific definitions
1209 83fb7adf bellard
 * From Wine
1210 83fb7adf bellard
 */
1211 83fb7adf bellard
#ifdef linux
1212 83fb7adf bellard
/* All Registers access - only for local access */
1213 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
1214 83fb7adf bellard
/* Gpr Registers access  */
1215 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
1216 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
1217 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
1218 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
1219 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
1220 83fb7adf bellard
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
1221 83fb7adf bellard
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
1222 83fb7adf bellard
/* Float Registers access  */
1223 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1224 83fb7adf bellard
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1225 83fb7adf bellard
/* Exception Registers access */
1226 83fb7adf bellard
# define DAR_sig(context)                        REG_sig(dar, context)
1227 83fb7adf bellard
# define DSISR_sig(context)                        REG_sig(dsisr, context)
1228 83fb7adf bellard
# define TRAP_sig(context)                        REG_sig(trap, context)
1229 83fb7adf bellard
#endif /* linux */
1230 83fb7adf bellard
1231 83fb7adf bellard
#ifdef __APPLE__
1232 83fb7adf bellard
# include <sys/ucontext.h>
1233 83fb7adf bellard
typedef struct ucontext SIGCONTEXT;
1234 83fb7adf bellard
/* All Registers access - only for local access */
1235 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
1236 83fb7adf bellard
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
1237 83fb7adf bellard
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
1238 83fb7adf bellard
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
1239 83fb7adf bellard
/* Gpr Registers access */
1240 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
1241 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
1242 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
1243 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)
1244 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
1245 83fb7adf bellard
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
1246 83fb7adf bellard
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
1247 83fb7adf bellard
/* Float Registers access */
1248 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
1249 83fb7adf bellard
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
1250 83fb7adf bellard
/* Exception Registers access */
1251 83fb7adf bellard
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
1252 83fb7adf bellard
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
1253 83fb7adf bellard
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1254 83fb7adf bellard
#endif /* __APPLE__ */
1255 83fb7adf bellard
1256 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1257 e4533c7a bellard
                       void *puc)
1258 2b413144 bellard
{
1259 5a7b542b ths
    siginfo_t *info = pinfo;
1260 25eb4484 bellard
    struct ucontext *uc = puc;
1261 25eb4484 bellard
    unsigned long pc;
1262 25eb4484 bellard
    int is_write;
1263 25eb4484 bellard
1264 83fb7adf bellard
    pc = IAR_sig(uc);
1265 25eb4484 bellard
    is_write = 0;
1266 25eb4484 bellard
#if 0
1267 25eb4484 bellard
    /* ppc 4xx case */
1268 83fb7adf bellard
    if (DSISR_sig(uc) & 0x00800000)
1269 25eb4484 bellard
        is_write = 1;
1270 25eb4484 bellard
#else
1271 83fb7adf bellard
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1272 25eb4484 bellard
        is_write = 1;
1273 25eb4484 bellard
#endif
1274 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1275 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
1276 2b413144 bellard
}
1277 2b413144 bellard
1278 2f87c607 bellard
#elif defined(__alpha__)
1279 2f87c607 bellard
1280 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1281 2f87c607 bellard
                           void *puc)
1282 2f87c607 bellard
{
1283 5a7b542b ths
    siginfo_t *info = pinfo;
1284 2f87c607 bellard
    struct ucontext *uc = puc;
1285 2f87c607 bellard
    uint32_t *pc = uc->uc_mcontext.sc_pc;
1286 2f87c607 bellard
    uint32_t insn = *pc;
1287 2f87c607 bellard
    int is_write = 0;
1288 2f87c607 bellard
1289 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1290 2f87c607 bellard
    switch (insn >> 26) {
1291 2f87c607 bellard
    case 0x0d: // stw
1292 2f87c607 bellard
    case 0x0e: // stb
1293 2f87c607 bellard
    case 0x0f: // stq_u
1294 2f87c607 bellard
    case 0x24: // stf
1295 2f87c607 bellard
    case 0x25: // stg
1296 2f87c607 bellard
    case 0x26: // sts
1297 2f87c607 bellard
    case 0x27: // stt
1298 2f87c607 bellard
    case 0x2c: // stl
1299 2f87c607 bellard
    case 0x2d: // stq
1300 2f87c607 bellard
    case 0x2e: // stl_c
1301 2f87c607 bellard
    case 0x2f: // stq_c
1302 2f87c607 bellard
        is_write = 1;
1303 2f87c607 bellard
    }
1304 2f87c607 bellard
1305 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1306 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
1307 2f87c607 bellard
}
1308 8c6939c0 bellard
#elif defined(__sparc__)
1309 8c6939c0 bellard
1310 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1311 e4533c7a bellard
                       void *puc)
1312 8c6939c0 bellard
{
1313 5a7b542b ths
    siginfo_t *info = pinfo;
1314 8c6939c0 bellard
    int is_write;
1315 8c6939c0 bellard
    uint32_t insn;
1316 6b4c11cd blueswir1
#if !defined(__arch64__) || defined(HOST_SOLARIS)
1317 c9e1e2b0 blueswir1
    uint32_t *regs = (uint32_t *)(info + 1);
1318 c9e1e2b0 blueswir1
    void *sigmask = (regs + 20);
1319 8c6939c0 bellard
    /* XXX: is there a standard glibc define ? */
1320 c9e1e2b0 blueswir1
    unsigned long pc = regs[1];
1321 c9e1e2b0 blueswir1
#else
1322 84778508 blueswir1
#ifdef __linux__
1323 c9e1e2b0 blueswir1
    struct sigcontext *sc = puc;
1324 c9e1e2b0 blueswir1
    unsigned long pc = sc->sigc_regs.tpc;
1325 c9e1e2b0 blueswir1
    void *sigmask = (void *)sc->sigc_mask;
1326 84778508 blueswir1
#elif defined(__OpenBSD__)
1327 84778508 blueswir1
    struct sigcontext *uc = puc;
1328 84778508 blueswir1
    unsigned long pc = uc->sc_pc;
1329 84778508 blueswir1
    void *sigmask = (void *)(long)uc->sc_mask;
1330 84778508 blueswir1
#endif
1331 c9e1e2b0 blueswir1
#endif
1332 c9e1e2b0 blueswir1
1333 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1334 8c6939c0 bellard
    is_write = 0;
1335 8c6939c0 bellard
    insn = *(uint32_t *)pc;
1336 8c6939c0 bellard
    if ((insn >> 30) == 3) {
1337 8c6939c0 bellard
      switch((insn >> 19) & 0x3f) {
1338 8c6939c0 bellard
      case 0x05: // stb
1339 8c6939c0 bellard
      case 0x06: // sth
1340 8c6939c0 bellard
      case 0x04: // st
1341 8c6939c0 bellard
      case 0x07: // std
1342 8c6939c0 bellard
      case 0x24: // stf
1343 8c6939c0 bellard
      case 0x27: // stdf
1344 8c6939c0 bellard
      case 0x25: // stfsr
1345 8c6939c0 bellard
        is_write = 1;
1346 8c6939c0 bellard
        break;
1347 8c6939c0 bellard
      }
1348 8c6939c0 bellard
    }
1349 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1350 bf3e8bf1 bellard
                             is_write, sigmask, NULL);
1351 8c6939c0 bellard
}
1352 8c6939c0 bellard
1353 8c6939c0 bellard
#elif defined(__arm__)
1354 8c6939c0 bellard
1355 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1356 e4533c7a bellard
                       void *puc)
1357 8c6939c0 bellard
{
1358 5a7b542b ths
    siginfo_t *info = pinfo;
1359 8c6939c0 bellard
    struct ucontext *uc = puc;
1360 8c6939c0 bellard
    unsigned long pc;
1361 8c6939c0 bellard
    int is_write;
1362 3b46e624 ths
1363 48bbf11b blueswir1
#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1364 5c49b363 balrog
    pc = uc->uc_mcontext.gregs[R15];
1365 5c49b363 balrog
#else
1366 4eee57f5 balrog
    pc = uc->uc_mcontext.arm_pc;
1367 5c49b363 balrog
#endif
1368 8c6939c0 bellard
    /* XXX: compute is_write */
1369 8c6939c0 bellard
    is_write = 0;
1370 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1371 8c6939c0 bellard
                             is_write,
1372 f3a9676a pbrook
                             &uc->uc_sigmask, puc);
1373 8c6939c0 bellard
}
1374 8c6939c0 bellard
1375 38e584a0 bellard
#elif defined(__mc68000)
1376 38e584a0 bellard
1377 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1378 38e584a0 bellard
                       void *puc)
1379 38e584a0 bellard
{
1380 5a7b542b ths
    siginfo_t *info = pinfo;
1381 38e584a0 bellard
    struct ucontext *uc = puc;
1382 38e584a0 bellard
    unsigned long pc;
1383 38e584a0 bellard
    int is_write;
1384 3b46e624 ths
1385 38e584a0 bellard
    pc = uc->uc_mcontext.gregs[16];
1386 38e584a0 bellard
    /* XXX: compute is_write */
1387 38e584a0 bellard
    is_write = 0;
1388 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1389 38e584a0 bellard
                             is_write,
1390 bf3e8bf1 bellard
                             &uc->uc_sigmask, puc);
1391 38e584a0 bellard
}
1392 38e584a0 bellard
1393 b8076a74 bellard
#elif defined(__ia64)
1394 b8076a74 bellard
1395 b8076a74 bellard
#ifndef __ISR_VALID
1396 b8076a74 bellard
  /* This ought to be in <bits/siginfo.h>... */
1397 b8076a74 bellard
# define __ISR_VALID        1
1398 b8076a74 bellard
#endif
1399 b8076a74 bellard
1400 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1401 b8076a74 bellard
{
1402 5a7b542b ths
    siginfo_t *info = pinfo;
1403 b8076a74 bellard
    struct ucontext *uc = puc;
1404 b8076a74 bellard
    unsigned long ip;
1405 b8076a74 bellard
    int is_write = 0;
1406 b8076a74 bellard
1407 b8076a74 bellard
    ip = uc->uc_mcontext.sc_ip;
1408 b8076a74 bellard
    switch (host_signum) {
1409 b8076a74 bellard
      case SIGILL:
1410 b8076a74 bellard
      case SIGFPE:
1411 b8076a74 bellard
      case SIGSEGV:
1412 b8076a74 bellard
      case SIGBUS:
1413 b8076a74 bellard
      case SIGTRAP:
1414 fd4a43e4 bellard
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1415 b8076a74 bellard
              /* ISR.W (write-access) is bit 33:  */
1416 b8076a74 bellard
              is_write = (info->si_isr >> 33) & 1;
1417 b8076a74 bellard
          break;
1418 b8076a74 bellard
1419 b8076a74 bellard
      default:
1420 b8076a74 bellard
          break;
1421 b8076a74 bellard
    }
1422 b8076a74 bellard
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1423 b8076a74 bellard
                             is_write,
1424 b8076a74 bellard
                             &uc->uc_sigmask, puc);
1425 b8076a74 bellard
}
1426 b8076a74 bellard
1427 90cb9493 bellard
#elif defined(__s390__)
1428 90cb9493 bellard
1429 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1430 90cb9493 bellard
                       void *puc)
1431 90cb9493 bellard
{
1432 5a7b542b ths
    siginfo_t *info = pinfo;
1433 90cb9493 bellard
    struct ucontext *uc = puc;
1434 90cb9493 bellard
    unsigned long pc;
1435 90cb9493 bellard
    int is_write;
1436 3b46e624 ths
1437 90cb9493 bellard
    pc = uc->uc_mcontext.psw.addr;
1438 90cb9493 bellard
    /* XXX: compute is_write */
1439 90cb9493 bellard
    is_write = 0;
1440 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1441 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1442 c4b89d18 ths
}
1443 c4b89d18 ths
1444 c4b89d18 ths
#elif defined(__mips__)
1445 c4b89d18 ths
1446 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1447 c4b89d18 ths
                       void *puc)
1448 c4b89d18 ths
{
1449 9617efe8 ths
    siginfo_t *info = pinfo;
1450 c4b89d18 ths
    struct ucontext *uc = puc;
1451 c4b89d18 ths
    greg_t pc = uc->uc_mcontext.pc;
1452 c4b89d18 ths
    int is_write;
1453 3b46e624 ths
1454 c4b89d18 ths
    /* XXX: compute is_write */
1455 c4b89d18 ths
    is_write = 0;
1456 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1457 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1458 90cb9493 bellard
}
1459 90cb9493 bellard
1460 f54b3f92 aurel32
#elif defined(__hppa__)
1461 f54b3f92 aurel32
1462 f54b3f92 aurel32
int cpu_signal_handler(int host_signum, void *pinfo,
1463 f54b3f92 aurel32
                       void *puc)
1464 f54b3f92 aurel32
{
1465 f54b3f92 aurel32
    struct siginfo *info = pinfo;
1466 f54b3f92 aurel32
    struct ucontext *uc = puc;
1467 f54b3f92 aurel32
    unsigned long pc;
1468 f54b3f92 aurel32
    int is_write;
1469 f54b3f92 aurel32
1470 f54b3f92 aurel32
    pc = uc->uc_mcontext.sc_iaoq[0];
1471 f54b3f92 aurel32
    /* FIXME: compute is_write */
1472 f54b3f92 aurel32
    is_write = 0;
1473 f54b3f92 aurel32
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1474 f54b3f92 aurel32
                             is_write,
1475 f54b3f92 aurel32
                             &uc->uc_sigmask, puc);
1476 f54b3f92 aurel32
}
1477 f54b3f92 aurel32
1478 9de5e440 bellard
#else
1479 2b413144 bellard
1480 3fb2ded1 bellard
#error host CPU specific signal handler needed
1481 2b413144 bellard
1482 9de5e440 bellard
#endif
1483 67b915a5 bellard
1484 67b915a5 bellard
#endif /* !defined(CONFIG_SOFTMMU) */