Statistics
| Branch: | Revision:

root / cpu-exec.c @ 97aff481

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