Statistics
| Branch: | Revision:

root / cpu-exec.c @ 8f4efc55

History | View | Annotate | Download (41.1 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 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 7d13299d bellard
 */
19 e4533c7a bellard
#include "config.h"
20 93ac68bc bellard
#include "exec.h"
21 956034d7 bellard
#include "disas.h"
22 7cb69cae bellard
#include "tcg.h"
23 7ba1e619 aliguori
#include "kvm.h"
24 7d13299d bellard
25 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
26 fbf9eeb3 bellard
#undef EAX
27 fbf9eeb3 bellard
#undef ECX
28 fbf9eeb3 bellard
#undef EDX
29 fbf9eeb3 bellard
#undef EBX
30 fbf9eeb3 bellard
#undef ESP
31 fbf9eeb3 bellard
#undef EBP
32 fbf9eeb3 bellard
#undef ESI
33 fbf9eeb3 bellard
#undef EDI
34 fbf9eeb3 bellard
#undef EIP
35 fbf9eeb3 bellard
#include <signal.h>
36 84778508 blueswir1
#ifdef __linux__
37 fbf9eeb3 bellard
#include <sys/ucontext.h>
38 fbf9eeb3 bellard
#endif
39 84778508 blueswir1
#endif
40 fbf9eeb3 bellard
41 dfe5fff3 Juan Quintela
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
42 572a9d4a blueswir1
// Work around ugly bugs in glibc that mangle global register contents
43 572a9d4a blueswir1
#undef env
44 572a9d4a blueswir1
#define env cpu_single_env
45 572a9d4a blueswir1
#endif
46 572a9d4a blueswir1
47 36bdbe54 bellard
int tb_invalidated_flag;
48 36bdbe54 bellard
49 f0667e66 Juan Quintela
//#define CONFIG_DEBUG_EXEC
50 9de5e440 bellard
//#define DEBUG_SIGNAL
51 7d13299d bellard
52 6a4955a8 aliguori
int qemu_cpu_has_work(CPUState *env)
53 6a4955a8 aliguori
{
54 6a4955a8 aliguori
    return cpu_has_work(env);
55 6a4955a8 aliguori
}
56 6a4955a8 aliguori
57 e4533c7a bellard
void cpu_loop_exit(void)
58 e4533c7a bellard
{
59 1c3569fe Paolo Bonzini
    env->current_tb = NULL;
60 e4533c7a bellard
    longjmp(env->jmp_env, 1);
61 e4533c7a bellard
}
62 bfed01fc ths
63 fbf9eeb3 bellard
/* exit the current TB from a signal handler. The host registers are
64 fbf9eeb3 bellard
   restored in a state compatible with the CPU emulator
65 fbf9eeb3 bellard
 */
66 5fafdf24 ths
void cpu_resume_from_signal(CPUState *env1, void *puc)
67 fbf9eeb3 bellard
{
68 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
69 84778508 blueswir1
#ifdef __linux__
70 fbf9eeb3 bellard
    struct ucontext *uc = puc;
71 84778508 blueswir1
#elif defined(__OpenBSD__)
72 84778508 blueswir1
    struct sigcontext *uc = puc;
73 84778508 blueswir1
#endif
74 fbf9eeb3 bellard
#endif
75 fbf9eeb3 bellard
76 fbf9eeb3 bellard
    env = env1;
77 fbf9eeb3 bellard
78 fbf9eeb3 bellard
    /* XXX: restore cpu registers saved in host registers */
79 fbf9eeb3 bellard
80 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
81 fbf9eeb3 bellard
    if (puc) {
82 fbf9eeb3 bellard
        /* XXX: use siglongjmp ? */
83 84778508 blueswir1
#ifdef __linux__
84 fbf9eeb3 bellard
        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
85 84778508 blueswir1
#elif defined(__OpenBSD__)
86 84778508 blueswir1
        sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
87 84778508 blueswir1
#endif
88 fbf9eeb3 bellard
    }
89 fbf9eeb3 bellard
#endif
90 9a3ea654 pbrook
    env->exception_index = -1;
91 fbf9eeb3 bellard
    longjmp(env->jmp_env, 1);
92 fbf9eeb3 bellard
}
93 fbf9eeb3 bellard
94 2e70f6ef pbrook
/* Execute the code without caching the generated code. An interpreter
95 2e70f6ef pbrook
   could be used if available. */
96 2e70f6ef pbrook
static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
97 2e70f6ef pbrook
{
98 2e70f6ef pbrook
    unsigned long next_tb;
99 2e70f6ef pbrook
    TranslationBlock *tb;
100 2e70f6ef pbrook
101 2e70f6ef pbrook
    /* Should never happen.
102 2e70f6ef pbrook
       We only end up here when an existing TB is too long.  */
103 2e70f6ef pbrook
    if (max_cycles > CF_COUNT_MASK)
104 2e70f6ef pbrook
        max_cycles = CF_COUNT_MASK;
105 2e70f6ef pbrook
106 2e70f6ef pbrook
    tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
107 2e70f6ef pbrook
                     max_cycles);
108 2e70f6ef pbrook
    env->current_tb = tb;
109 2e70f6ef pbrook
    /* execute the generated code */
110 2e70f6ef pbrook
    next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
111 1c3569fe Paolo Bonzini
    env->current_tb = NULL;
112 2e70f6ef pbrook
113 2e70f6ef pbrook
    if ((next_tb & 3) == 2) {
114 2e70f6ef pbrook
        /* Restore PC.  This may happen if async event occurs before
115 2e70f6ef pbrook
           the TB starts executing.  */
116 622ed360 aliguori
        cpu_pc_from_tb(env, tb);
117 2e70f6ef pbrook
    }
118 2e70f6ef pbrook
    tb_phys_invalidate(tb, -1);
119 2e70f6ef pbrook
    tb_free(tb);
120 2e70f6ef pbrook
}
121 2e70f6ef pbrook
122 8a40a180 bellard
static TranslationBlock *tb_find_slow(target_ulong pc,
123 8a40a180 bellard
                                      target_ulong cs_base,
124 c068688b j_mayer
                                      uint64_t flags)
125 8a40a180 bellard
{
126 8a40a180 bellard
    TranslationBlock *tb, **ptb1;
127 8a40a180 bellard
    unsigned int h;
128 8a40a180 bellard
    target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
129 3b46e624 ths
130 8a40a180 bellard
    tb_invalidated_flag = 0;
131 3b46e624 ths
132 8a40a180 bellard
    /* find translated block using physical mappings */
133 8a40a180 bellard
    phys_pc = get_phys_addr_code(env, pc);
134 8a40a180 bellard
    phys_page1 = phys_pc & TARGET_PAGE_MASK;
135 8a40a180 bellard
    phys_page2 = -1;
136 8a40a180 bellard
    h = tb_phys_hash_func(phys_pc);
137 8a40a180 bellard
    ptb1 = &tb_phys_hash[h];
138 8a40a180 bellard
    for(;;) {
139 8a40a180 bellard
        tb = *ptb1;
140 8a40a180 bellard
        if (!tb)
141 8a40a180 bellard
            goto not_found;
142 5fafdf24 ths
        if (tb->pc == pc &&
143 8a40a180 bellard
            tb->page_addr[0] == phys_page1 &&
144 5fafdf24 ths
            tb->cs_base == cs_base &&
145 8a40a180 bellard
            tb->flags == flags) {
146 8a40a180 bellard
            /* check next page if needed */
147 8a40a180 bellard
            if (tb->page_addr[1] != -1) {
148 5fafdf24 ths
                virt_page2 = (pc & TARGET_PAGE_MASK) +
149 8a40a180 bellard
                    TARGET_PAGE_SIZE;
150 8a40a180 bellard
                phys_page2 = get_phys_addr_code(env, virt_page2);
151 8a40a180 bellard
                if (tb->page_addr[1] == phys_page2)
152 8a40a180 bellard
                    goto found;
153 8a40a180 bellard
            } else {
154 8a40a180 bellard
                goto found;
155 8a40a180 bellard
            }
156 8a40a180 bellard
        }
157 8a40a180 bellard
        ptb1 = &tb->phys_hash_next;
158 8a40a180 bellard
    }
159 8a40a180 bellard
 not_found:
160 2e70f6ef pbrook
   /* if no translated code available, then translate it now */
161 2e70f6ef pbrook
    tb = tb_gen_code(env, pc, cs_base, flags, 0);
162 3b46e624 ths
163 8a40a180 bellard
 found:
164 8a40a180 bellard
    /* we add the TB in the virtual pc hash table */
165 8a40a180 bellard
    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
166 8a40a180 bellard
    return tb;
167 8a40a180 bellard
}
168 8a40a180 bellard
169 8a40a180 bellard
static inline TranslationBlock *tb_find_fast(void)
170 8a40a180 bellard
{
171 8a40a180 bellard
    TranslationBlock *tb;
172 8a40a180 bellard
    target_ulong cs_base, pc;
173 6b917547 aliguori
    int flags;
174 8a40a180 bellard
175 8a40a180 bellard
    /* we record a subset of the CPU state. It will
176 8a40a180 bellard
       always be the same before a given translated block
177 8a40a180 bellard
       is executed. */
178 6b917547 aliguori
    cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
179 bce61846 bellard
    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
180 551bd27f ths
    if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
181 551bd27f ths
                 tb->flags != flags)) {
182 8a40a180 bellard
        tb = tb_find_slow(pc, cs_base, flags);
183 8a40a180 bellard
    }
184 8a40a180 bellard
    return tb;
185 8a40a180 bellard
}
186 8a40a180 bellard
187 dde2367e aliguori
static CPUDebugExcpHandler *debug_excp_handler;
188 dde2367e aliguori
189 dde2367e aliguori
CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
190 dde2367e aliguori
{
191 dde2367e aliguori
    CPUDebugExcpHandler *old_handler = debug_excp_handler;
192 dde2367e aliguori
193 dde2367e aliguori
    debug_excp_handler = handler;
194 dde2367e aliguori
    return old_handler;
195 dde2367e aliguori
}
196 dde2367e aliguori
197 6e140f28 aliguori
static void cpu_handle_debug_exception(CPUState *env)
198 6e140f28 aliguori
{
199 6e140f28 aliguori
    CPUWatchpoint *wp;
200 6e140f28 aliguori
201 6e140f28 aliguori
    if (!env->watchpoint_hit)
202 72cf2d4f Blue Swirl
        QTAILQ_FOREACH(wp, &env->watchpoints, entry)
203 6e140f28 aliguori
            wp->flags &= ~BP_WATCHPOINT_HIT;
204 dde2367e aliguori
205 dde2367e aliguori
    if (debug_excp_handler)
206 dde2367e aliguori
        debug_excp_handler(env);
207 6e140f28 aliguori
}
208 6e140f28 aliguori
209 7d13299d bellard
/* main execution loop */
210 7d13299d bellard
211 e4533c7a bellard
int cpu_exec(CPUState *env1)
212 7d13299d bellard
{
213 1057eaa7 pbrook
#define DECLARE_HOST_REGS 1
214 1057eaa7 pbrook
#include "hostregs_helper.h"
215 8a40a180 bellard
    int ret, interrupt_request;
216 8a40a180 bellard
    TranslationBlock *tb;
217 c27004ec bellard
    uint8_t *tc_ptr;
218 d5975363 pbrook
    unsigned long next_tb;
219 8c6939c0 bellard
220 bfed01fc ths
    if (cpu_halted(env1) == EXCP_HALTED)
221 bfed01fc ths
        return EXCP_HALTED;
222 5a1e3cfc bellard
223 5fafdf24 ths
    cpu_single_env = env1;
224 6a00d601 bellard
225 7d13299d bellard
    /* first we save global registers */
226 1057eaa7 pbrook
#define SAVE_HOST_REGS 1
227 1057eaa7 pbrook
#include "hostregs_helper.h"
228 c27004ec bellard
    env = env1;
229 e4533c7a bellard
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 b779e29e Edgar E. Iglesias
#elif defined(TARGET_MICROBLAZE)
245 6af0bf9c bellard
#elif defined(TARGET_MIPS)
246 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
247 f1ccf904 ths
#elif defined(TARGET_CRIS)
248 10ec5117 Alexander Graf
#elif defined(TARGET_S390X)
249 fdf9b3e8 bellard
    /* XXXXX */
250 e4533c7a bellard
#else
251 e4533c7a bellard
#error unsupported target CPU
252 e4533c7a bellard
#endif
253 3fb2ded1 bellard
    env->exception_index = -1;
254 9d27abd9 bellard
255 7d13299d bellard
    /* prepare setjmp context for exception handling */
256 3fb2ded1 bellard
    for(;;) {
257 3fb2ded1 bellard
        if (setjmp(env->jmp_env) == 0) {
258 dfe5fff3 Juan Quintela
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
259 9ddff3d2 blueswir1
#undef env
260 9ddff3d2 blueswir1
                    env = cpu_single_env;
261 9ddff3d2 blueswir1
#define env cpu_single_env
262 9ddff3d2 blueswir1
#endif
263 3fb2ded1 bellard
            /* if an exception is pending, we execute it here */
264 3fb2ded1 bellard
            if (env->exception_index >= 0) {
265 3fb2ded1 bellard
                if (env->exception_index >= EXCP_INTERRUPT) {
266 3fb2ded1 bellard
                    /* exit request from the cpu execution loop */
267 3fb2ded1 bellard
                    ret = env->exception_index;
268 6e140f28 aliguori
                    if (ret == EXCP_DEBUG)
269 6e140f28 aliguori
                        cpu_handle_debug_exception(env);
270 3fb2ded1 bellard
                    break;
271 72d239ed aurel32
                } else {
272 72d239ed aurel32
#if defined(CONFIG_USER_ONLY)
273 3fb2ded1 bellard
                    /* if user mode only, we simulate a fake exception
274 9f083493 ths
                       which will be handled outside the cpu execution
275 3fb2ded1 bellard
                       loop */
276 83479e77 bellard
#if defined(TARGET_I386)
277 5fafdf24 ths
                    do_interrupt_user(env->exception_index,
278 5fafdf24 ths
                                      env->exception_is_int,
279 5fafdf24 ths
                                      env->error_code,
280 3fb2ded1 bellard
                                      env->exception_next_eip);
281 eba01623 bellard
                    /* successfully delivered */
282 eba01623 bellard
                    env->old_exception = -1;
283 83479e77 bellard
#endif
284 3fb2ded1 bellard
                    ret = env->exception_index;
285 3fb2ded1 bellard
                    break;
286 72d239ed aurel32
#else
287 83479e77 bellard
#if defined(TARGET_I386)
288 3fb2ded1 bellard
                    /* simulate a real cpu exception. On i386, it can
289 3fb2ded1 bellard
                       trigger new exceptions, but we do not handle
290 3fb2ded1 bellard
                       double or triple faults yet. */
291 5fafdf24 ths
                    do_interrupt(env->exception_index,
292 5fafdf24 ths
                                 env->exception_is_int,
293 5fafdf24 ths
                                 env->error_code,
294 d05e66d2 bellard
                                 env->exception_next_eip, 0);
295 678dde13 ths
                    /* successfully delivered */
296 678dde13 ths
                    env->old_exception = -1;
297 ce09776b bellard
#elif defined(TARGET_PPC)
298 ce09776b bellard
                    do_interrupt(env);
299 b779e29e Edgar E. Iglesias
#elif defined(TARGET_MICROBLAZE)
300 b779e29e Edgar E. Iglesias
                    do_interrupt(env);
301 6af0bf9c bellard
#elif defined(TARGET_MIPS)
302 6af0bf9c bellard
                    do_interrupt(env);
303 e95c8d51 bellard
#elif defined(TARGET_SPARC)
304 f2bc7e7f blueswir1
                    do_interrupt(env);
305 b5ff1b31 bellard
#elif defined(TARGET_ARM)
306 b5ff1b31 bellard
                    do_interrupt(env);
307 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
308 fdf9b3e8 bellard
                    do_interrupt(env);
309 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
310 eddf68a6 j_mayer
                    do_interrupt(env);
311 f1ccf904 ths
#elif defined(TARGET_CRIS)
312 f1ccf904 ths
                    do_interrupt(env);
313 0633879f pbrook
#elif defined(TARGET_M68K)
314 0633879f pbrook
                    do_interrupt(0);
315 83479e77 bellard
#endif
316 301d2908 Paolo Bonzini
                    env->exception_index = -1;
317 72d239ed aurel32
#endif
318 3fb2ded1 bellard
                }
319 5fafdf24 ths
            }
320 9df217a3 bellard
321 7ba1e619 aliguori
            if (kvm_enabled()) {
322 becfc390 aliguori
                kvm_cpu_exec(env);
323 becfc390 aliguori
                longjmp(env->jmp_env, 1);
324 7ba1e619 aliguori
            }
325 7ba1e619 aliguori
326 b5fc09ae blueswir1
            next_tb = 0; /* force lookup of first TB */
327 3fb2ded1 bellard
            for(;;) {
328 68a79315 bellard
                interrupt_request = env->interrupt_request;
329 e1638bd8 malc
                if (unlikely(interrupt_request)) {
330 e1638bd8 malc
                    if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
331 e1638bd8 malc
                        /* Mask out external interrupts for this step. */
332 e1638bd8 malc
                        interrupt_request &= ~(CPU_INTERRUPT_HARD |
333 e1638bd8 malc
                                               CPU_INTERRUPT_FIQ |
334 e1638bd8 malc
                                               CPU_INTERRUPT_SMI |
335 e1638bd8 malc
                                               CPU_INTERRUPT_NMI);
336 e1638bd8 malc
                    }
337 6658ffb8 pbrook
                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
338 6658ffb8 pbrook
                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
339 6658ffb8 pbrook
                        env->exception_index = EXCP_DEBUG;
340 6658ffb8 pbrook
                        cpu_loop_exit();
341 6658ffb8 pbrook
                    }
342 a90b7318 balrog
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
343 b779e29e Edgar E. Iglesias
    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
344 b779e29e Edgar E. Iglesias
    defined(TARGET_MICROBLAZE)
345 a90b7318 balrog
                    if (interrupt_request & CPU_INTERRUPT_HALT) {
346 a90b7318 balrog
                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
347 a90b7318 balrog
                        env->halted = 1;
348 a90b7318 balrog
                        env->exception_index = EXCP_HLT;
349 a90b7318 balrog
                        cpu_loop_exit();
350 a90b7318 balrog
                    }
351 a90b7318 balrog
#endif
352 68a79315 bellard
#if defined(TARGET_I386)
353 b09ea7d5 Gleb Natapov
                    if (interrupt_request & CPU_INTERRUPT_INIT) {
354 b09ea7d5 Gleb Natapov
                            svm_check_intercept(SVM_EXIT_INIT);
355 b09ea7d5 Gleb Natapov
                            do_cpu_init(env);
356 b09ea7d5 Gleb Natapov
                            env->exception_index = EXCP_HALTED;
357 b09ea7d5 Gleb Natapov
                            cpu_loop_exit();
358 b09ea7d5 Gleb Natapov
                    } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
359 b09ea7d5 Gleb Natapov
                            do_cpu_sipi(env);
360 b09ea7d5 Gleb Natapov
                    } else if (env->hflags2 & HF2_GIF_MASK) {
361 db620f46 bellard
                        if ((interrupt_request & CPU_INTERRUPT_SMI) &&
362 db620f46 bellard
                            !(env->hflags & HF_SMM_MASK)) {
363 db620f46 bellard
                            svm_check_intercept(SVM_EXIT_SMI);
364 db620f46 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_SMI;
365 db620f46 bellard
                            do_smm_enter();
366 db620f46 bellard
                            next_tb = 0;
367 db620f46 bellard
                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
368 db620f46 bellard
                                   !(env->hflags2 & HF2_NMI_MASK)) {
369 db620f46 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
370 db620f46 bellard
                            env->hflags2 |= HF2_NMI_MASK;
371 db620f46 bellard
                            do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
372 db620f46 bellard
                            next_tb = 0;
373 79c4f6b0 Huang Ying
                        } else if (interrupt_request & CPU_INTERRUPT_MCE) {
374 79c4f6b0 Huang Ying
                            env->interrupt_request &= ~CPU_INTERRUPT_MCE;
375 79c4f6b0 Huang Ying
                            do_interrupt(EXCP12_MCHK, 0, 0, 0, 0);
376 79c4f6b0 Huang Ying
                            next_tb = 0;
377 db620f46 bellard
                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
378 db620f46 bellard
                                   (((env->hflags2 & HF2_VINTR_MASK) && 
379 db620f46 bellard
                                     (env->hflags2 & HF2_HIF_MASK)) ||
380 db620f46 bellard
                                    (!(env->hflags2 & HF2_VINTR_MASK) && 
381 db620f46 bellard
                                     (env->eflags & IF_MASK && 
382 db620f46 bellard
                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
383 db620f46 bellard
                            int intno;
384 db620f46 bellard
                            svm_check_intercept(SVM_EXIT_INTR);
385 db620f46 bellard
                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
386 db620f46 bellard
                            intno = cpu_get_pic_interrupt(env);
387 93fcfe39 aliguori
                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
388 dfe5fff3 Juan Quintela
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
389 9ddff3d2 blueswir1
#undef env
390 9ddff3d2 blueswir1
                    env = cpu_single_env;
391 9ddff3d2 blueswir1
#define env cpu_single_env
392 9ddff3d2 blueswir1
#endif
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
                            intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
405 93fcfe39 aliguori
                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
406 db620f46 bellard
                            do_interrupt(intno, 0, 0, 0, 1);
407 d40c54d6 aurel32
                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
408 db620f46 bellard
                            next_tb = 0;
409 0573fbfc ths
#endif
410 db620f46 bellard
                        }
411 68a79315 bellard
                    }
412 ce09776b bellard
#elif defined(TARGET_PPC)
413 9fddaa0c bellard
#if 0
414 9fddaa0c bellard
                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
415 d84bda46 Blue Swirl
                        cpu_reset(env);
416 9fddaa0c bellard
                    }
417 9fddaa0c bellard
#endif
418 47103572 j_mayer
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
419 e9df014c j_mayer
                        ppc_hw_interrupt(env);
420 e9df014c j_mayer
                        if (env->pending_interrupts == 0)
421 e9df014c j_mayer
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
422 b5fc09ae blueswir1
                        next_tb = 0;
423 ce09776b bellard
                    }
424 b779e29e Edgar E. Iglesias
#elif defined(TARGET_MICROBLAZE)
425 b779e29e Edgar E. Iglesias
                    if ((interrupt_request & CPU_INTERRUPT_HARD)
426 b779e29e Edgar E. Iglesias
                        && (env->sregs[SR_MSR] & MSR_IE)
427 b779e29e Edgar E. Iglesias
                        && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
428 b779e29e Edgar E. Iglesias
                        && !(env->iflags & (D_FLAG | IMM_FLAG))) {
429 b779e29e Edgar E. Iglesias
                        env->exception_index = EXCP_IRQ;
430 b779e29e Edgar E. Iglesias
                        do_interrupt(env);
431 b779e29e Edgar E. Iglesias
                        next_tb = 0;
432 b779e29e Edgar E. Iglesias
                    }
433 6af0bf9c bellard
#elif defined(TARGET_MIPS)
434 6af0bf9c bellard
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
435 24c7b0e3 ths
                        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
436 6af0bf9c bellard
                        (env->CP0_Status & (1 << CP0St_IE)) &&
437 24c7b0e3 ths
                        !(env->CP0_Status & (1 << CP0St_EXL)) &&
438 24c7b0e3 ths
                        !(env->CP0_Status & (1 << CP0St_ERL)) &&
439 6af0bf9c bellard
                        !(env->hflags & MIPS_HFLAG_DM)) {
440 6af0bf9c bellard
                        /* Raise it */
441 6af0bf9c bellard
                        env->exception_index = EXCP_EXT_INTERRUPT;
442 6af0bf9c bellard
                        env->error_code = 0;
443 6af0bf9c bellard
                        do_interrupt(env);
444 b5fc09ae blueswir1
                        next_tb = 0;
445 6af0bf9c bellard
                    }
446 e95c8d51 bellard
#elif defined(TARGET_SPARC)
447 d532b26c Igor V. Kovalenko
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
448 d532b26c Igor V. Kovalenko
                        if (cpu_interrupts_enabled(env) &&
449 d532b26c Igor V. Kovalenko
                            env->interrupt_index > 0) {
450 d532b26c Igor V. Kovalenko
                            int pil = env->interrupt_index & 0xf;
451 d532b26c Igor V. Kovalenko
                            int type = env->interrupt_index & 0xf0;
452 d532b26c Igor V. Kovalenko
453 d532b26c Igor V. Kovalenko
                            if (((type == TT_EXTINT) &&
454 d532b26c Igor V. Kovalenko
                                  cpu_pil_allowed(env, pil)) ||
455 d532b26c Igor V. Kovalenko
                                  type != TT_EXTINT) {
456 d532b26c Igor V. Kovalenko
                                env->exception_index = env->interrupt_index;
457 d532b26c Igor V. Kovalenko
                                do_interrupt(env);
458 d532b26c Igor V. Kovalenko
                                next_tb = 0;
459 d532b26c Igor V. Kovalenko
                            }
460 d532b26c Igor V. Kovalenko
                        }
461 e95c8d51 bellard
                    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
462 e95c8d51 bellard
                        //do_interrupt(0, 0, 0, 0, 0);
463 e95c8d51 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
464 a90b7318 balrog
                    }
465 b5ff1b31 bellard
#elif defined(TARGET_ARM)
466 b5ff1b31 bellard
                    if (interrupt_request & CPU_INTERRUPT_FIQ
467 b5ff1b31 bellard
                        && !(env->uncached_cpsr & CPSR_F)) {
468 b5ff1b31 bellard
                        env->exception_index = EXCP_FIQ;
469 b5ff1b31 bellard
                        do_interrupt(env);
470 b5fc09ae blueswir1
                        next_tb = 0;
471 b5ff1b31 bellard
                    }
472 9ee6e8bb pbrook
                    /* ARMv7-M interrupt return works by loading a magic value
473 9ee6e8bb pbrook
                       into the PC.  On real hardware the load causes the
474 9ee6e8bb pbrook
                       return to occur.  The qemu implementation performs the
475 9ee6e8bb pbrook
                       jump normally, then does the exception return when the
476 9ee6e8bb pbrook
                       CPU tries to execute code at the magic address.
477 9ee6e8bb pbrook
                       This will cause the magic PC value to be pushed to
478 9ee6e8bb pbrook
                       the stack if an interrupt occured at the wrong time.
479 9ee6e8bb pbrook
                       We avoid this by disabling interrupts when
480 9ee6e8bb pbrook
                       pc contains a magic address.  */
481 b5ff1b31 bellard
                    if (interrupt_request & CPU_INTERRUPT_HARD
482 9ee6e8bb pbrook
                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
483 9ee6e8bb pbrook
                            || !(env->uncached_cpsr & CPSR_I))) {
484 b5ff1b31 bellard
                        env->exception_index = EXCP_IRQ;
485 b5ff1b31 bellard
                        do_interrupt(env);
486 b5fc09ae blueswir1
                        next_tb = 0;
487 b5ff1b31 bellard
                    }
488 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
489 e96e2044 ths
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
490 e96e2044 ths
                        do_interrupt(env);
491 b5fc09ae blueswir1
                        next_tb = 0;
492 e96e2044 ths
                    }
493 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
494 eddf68a6 j_mayer
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
495 eddf68a6 j_mayer
                        do_interrupt(env);
496 b5fc09ae blueswir1
                        next_tb = 0;
497 eddf68a6 j_mayer
                    }
498 f1ccf904 ths
#elif defined(TARGET_CRIS)
499 1b1a38b0 edgar_igl
                    if (interrupt_request & CPU_INTERRUPT_HARD
500 1b1a38b0 edgar_igl
                        && (env->pregs[PR_CCS] & I_FLAG)) {
501 1b1a38b0 edgar_igl
                        env->exception_index = EXCP_IRQ;
502 1b1a38b0 edgar_igl
                        do_interrupt(env);
503 1b1a38b0 edgar_igl
                        next_tb = 0;
504 1b1a38b0 edgar_igl
                    }
505 1b1a38b0 edgar_igl
                    if (interrupt_request & CPU_INTERRUPT_NMI
506 1b1a38b0 edgar_igl
                        && (env->pregs[PR_CCS] & M_FLAG)) {
507 1b1a38b0 edgar_igl
                        env->exception_index = EXCP_NMI;
508 f1ccf904 ths
                        do_interrupt(env);
509 b5fc09ae blueswir1
                        next_tb = 0;
510 f1ccf904 ths
                    }
511 0633879f pbrook
#elif defined(TARGET_M68K)
512 0633879f pbrook
                    if (interrupt_request & CPU_INTERRUPT_HARD
513 0633879f pbrook
                        && ((env->sr & SR_I) >> SR_I_SHIFT)
514 0633879f pbrook
                            < env->pending_level) {
515 0633879f pbrook
                        /* Real hardware gets the interrupt vector via an
516 0633879f pbrook
                           IACK cycle at this point.  Current emulated
517 0633879f pbrook
                           hardware doesn't rely on this, so we
518 0633879f pbrook
                           provide/save the vector when the interrupt is
519 0633879f pbrook
                           first signalled.  */
520 0633879f pbrook
                        env->exception_index = env->pending_vector;
521 0633879f pbrook
                        do_interrupt(1);
522 b5fc09ae blueswir1
                        next_tb = 0;
523 0633879f pbrook
                    }
524 68a79315 bellard
#endif
525 9d05095e bellard
                   /* Don't use the cached interupt_request value,
526 9d05095e bellard
                      do_interrupt may have updated the EXITTB flag. */
527 b5ff1b31 bellard
                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
528 bf3e8bf1 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
529 bf3e8bf1 bellard
                        /* ensure that no TB jump will be modified as
530 bf3e8bf1 bellard
                           the program flow was changed */
531 b5fc09ae blueswir1
                        next_tb = 0;
532 bf3e8bf1 bellard
                    }
533 be214e6c aurel32
                }
534 be214e6c aurel32
                if (unlikely(env->exit_request)) {
535 be214e6c aurel32
                    env->exit_request = 0;
536 be214e6c aurel32
                    env->exception_index = EXCP_INTERRUPT;
537 be214e6c aurel32
                    cpu_loop_exit();
538 3fb2ded1 bellard
                }
539 f0667e66 Juan Quintela
#ifdef CONFIG_DEBUG_EXEC
540 8fec2b8c aliguori
                if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
541 3fb2ded1 bellard
                    /* restore flags in standard format */
542 ecb644f4 ths
#if defined(TARGET_I386)
543 a7812ae4 pbrook
                    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
544 93fcfe39 aliguori
                    log_cpu_state(env, X86_DUMP_CCOP);
545 3fb2ded1 bellard
                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
546 e4533c7a bellard
#elif defined(TARGET_ARM)
547 93fcfe39 aliguori
                    log_cpu_state(env, 0);
548 93ac68bc bellard
#elif defined(TARGET_SPARC)
549 93fcfe39 aliguori
                    log_cpu_state(env, 0);
550 67867308 bellard
#elif defined(TARGET_PPC)
551 93fcfe39 aliguori
                    log_cpu_state(env, 0);
552 e6e5906b pbrook
#elif defined(TARGET_M68K)
553 e6e5906b pbrook
                    cpu_m68k_flush_flags(env, env->cc_op);
554 e6e5906b pbrook
                    env->cc_op = CC_OP_FLAGS;
555 e6e5906b pbrook
                    env->sr = (env->sr & 0xffe0)
556 e6e5906b pbrook
                              | env->cc_dest | (env->cc_x << 4);
557 93fcfe39 aliguori
                    log_cpu_state(env, 0);
558 b779e29e Edgar E. Iglesias
#elif defined(TARGET_MICROBLAZE)
559 b779e29e Edgar E. Iglesias
                    log_cpu_state(env, 0);
560 6af0bf9c bellard
#elif defined(TARGET_MIPS)
561 93fcfe39 aliguori
                    log_cpu_state(env, 0);
562 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
563 93fcfe39 aliguori
                    log_cpu_state(env, 0);
564 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
565 93fcfe39 aliguori
                    log_cpu_state(env, 0);
566 f1ccf904 ths
#elif defined(TARGET_CRIS)
567 93fcfe39 aliguori
                    log_cpu_state(env, 0);
568 e4533c7a bellard
#else
569 5fafdf24 ths
#error unsupported target CPU
570 e4533c7a bellard
#endif
571 3fb2ded1 bellard
                }
572 7d13299d bellard
#endif
573 d5975363 pbrook
                spin_lock(&tb_lock);
574 8a40a180 bellard
                tb = tb_find_fast();
575 d5975363 pbrook
                /* Note: we do it here to avoid a gcc bug on Mac OS X when
576 d5975363 pbrook
                   doing it in tb_find_slow */
577 d5975363 pbrook
                if (tb_invalidated_flag) {
578 d5975363 pbrook
                    /* as some TB could have been invalidated because
579 d5975363 pbrook
                       of memory exceptions while generating the code, we
580 d5975363 pbrook
                       must recompute the hash index here */
581 d5975363 pbrook
                    next_tb = 0;
582 2e70f6ef pbrook
                    tb_invalidated_flag = 0;
583 d5975363 pbrook
                }
584 f0667e66 Juan Quintela
#ifdef CONFIG_DEBUG_EXEC
585 93fcfe39 aliguori
                qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
586 93fcfe39 aliguori
                             (long)tb->tc_ptr, tb->pc,
587 93fcfe39 aliguori
                             lookup_symbol(tb->pc));
588 9d27abd9 bellard
#endif
589 8a40a180 bellard
                /* see if we can patch the calling TB. When the TB
590 8a40a180 bellard
                   spans two pages, we cannot safely do a direct
591 8a40a180 bellard
                   jump. */
592 040f2fb2 Paolo Bonzini
                if (next_tb != 0 && tb->page_addr[1] == -1) {
593 b5fc09ae blueswir1
                    tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
594 3fb2ded1 bellard
                }
595 d5975363 pbrook
                spin_unlock(&tb_lock);
596 55e8b85e malc
597 55e8b85e malc
                /* cpu_interrupt might be called while translating the
598 55e8b85e malc
                   TB, but before it is linked into a potentially
599 55e8b85e malc
                   infinite loop and becomes env->current_tb. Avoid
600 55e8b85e malc
                   starting execution if there is a pending interrupt. */
601 6113d6d3 Paolo Bonzini
                if (!unlikely (env->exit_request)) {
602 6113d6d3 Paolo Bonzini
                    env->current_tb = tb;
603 2e70f6ef pbrook
                    tc_ptr = tb->tc_ptr;
604 3fb2ded1 bellard
                /* execute the generated code */
605 dfe5fff3 Juan Quintela
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
606 572a9d4a blueswir1
#undef env
607 2e70f6ef pbrook
                    env = cpu_single_env;
608 572a9d4a blueswir1
#define env cpu_single_env
609 572a9d4a blueswir1
#endif
610 2e70f6ef pbrook
                    next_tb = tcg_qemu_tb_exec(tc_ptr);
611 2e70f6ef pbrook
                    env->current_tb = NULL;
612 2e70f6ef pbrook
                    if ((next_tb & 3) == 2) {
613 bf20dc07 ths
                        /* Instruction counter expired.  */
614 2e70f6ef pbrook
                        int insns_left;
615 2e70f6ef pbrook
                        tb = (TranslationBlock *)(long)(next_tb & ~3);
616 2e70f6ef pbrook
                        /* Restore PC.  */
617 622ed360 aliguori
                        cpu_pc_from_tb(env, tb);
618 2e70f6ef pbrook
                        insns_left = env->icount_decr.u32;
619 2e70f6ef pbrook
                        if (env->icount_extra && insns_left >= 0) {
620 2e70f6ef pbrook
                            /* Refill decrementer and continue execution.  */
621 2e70f6ef pbrook
                            env->icount_extra += insns_left;
622 2e70f6ef pbrook
                            if (env->icount_extra > 0xffff) {
623 2e70f6ef pbrook
                                insns_left = 0xffff;
624 2e70f6ef pbrook
                            } else {
625 2e70f6ef pbrook
                                insns_left = env->icount_extra;
626 2e70f6ef pbrook
                            }
627 2e70f6ef pbrook
                            env->icount_extra -= insns_left;
628 2e70f6ef pbrook
                            env->icount_decr.u16.low = insns_left;
629 2e70f6ef pbrook
                        } else {
630 2e70f6ef pbrook
                            if (insns_left > 0) {
631 2e70f6ef pbrook
                                /* Execute remaining instructions.  */
632 2e70f6ef pbrook
                                cpu_exec_nocache(insns_left, tb);
633 2e70f6ef pbrook
                            }
634 2e70f6ef pbrook
                            env->exception_index = EXCP_INTERRUPT;
635 2e70f6ef pbrook
                            next_tb = 0;
636 2e70f6ef pbrook
                            cpu_loop_exit();
637 2e70f6ef pbrook
                        }
638 2e70f6ef pbrook
                    }
639 2e70f6ef pbrook
                }
640 4cbf74b6 bellard
                /* reset soft MMU for next block (it can currently
641 4cbf74b6 bellard
                   only be set by a memory fault) */
642 50a518e3 ths
            } /* for(;;) */
643 7d13299d bellard
        }
644 3fb2ded1 bellard
    } /* for(;;) */
645 3fb2ded1 bellard
646 7d13299d bellard
647 e4533c7a bellard
#if defined(TARGET_I386)
648 9de5e440 bellard
    /* restore flags in standard format */
649 a7812ae4 pbrook
    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
650 e4533c7a bellard
#elif defined(TARGET_ARM)
651 b7bcbe95 bellard
    /* XXX: Save/restore host fpu exception state?.  */
652 93ac68bc bellard
#elif defined(TARGET_SPARC)
653 67867308 bellard
#elif defined(TARGET_PPC)
654 e6e5906b pbrook
#elif defined(TARGET_M68K)
655 e6e5906b pbrook
    cpu_m68k_flush_flags(env, env->cc_op);
656 e6e5906b pbrook
    env->cc_op = CC_OP_FLAGS;
657 e6e5906b pbrook
    env->sr = (env->sr & 0xffe0)
658 e6e5906b pbrook
              | env->cc_dest | (env->cc_x << 4);
659 b779e29e Edgar E. Iglesias
#elif defined(TARGET_MICROBLAZE)
660 6af0bf9c bellard
#elif defined(TARGET_MIPS)
661 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
662 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
663 f1ccf904 ths
#elif defined(TARGET_CRIS)
664 10ec5117 Alexander Graf
#elif defined(TARGET_S390X)
665 fdf9b3e8 bellard
    /* XXXXX */
666 e4533c7a bellard
#else
667 e4533c7a bellard
#error unsupported target CPU
668 e4533c7a bellard
#endif
669 1057eaa7 pbrook
670 1057eaa7 pbrook
    /* restore global registers */
671 1057eaa7 pbrook
#include "hostregs_helper.h"
672 1057eaa7 pbrook
673 6a00d601 bellard
    /* fail safe : never use cpu_single_env outside cpu_exec() */
674 5fafdf24 ths
    cpu_single_env = NULL;
675 7d13299d bellard
    return ret;
676 7d13299d bellard
}
677 6dbad63e bellard
678 fbf9eeb3 bellard
/* must only be called from the generated code as an exception can be
679 fbf9eeb3 bellard
   generated */
680 fbf9eeb3 bellard
void tb_invalidate_page_range(target_ulong start, target_ulong end)
681 fbf9eeb3 bellard
{
682 dc5d0b3d bellard
    /* XXX: cannot enable it yet because it yields to MMU exception
683 dc5d0b3d bellard
       where NIP != read address on PowerPC */
684 dc5d0b3d bellard
#if 0
685 fbf9eeb3 bellard
    target_ulong phys_addr;
686 fbf9eeb3 bellard
    phys_addr = get_phys_addr_code(env, start);
687 fbf9eeb3 bellard
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
688 dc5d0b3d bellard
#endif
689 fbf9eeb3 bellard
}
690 fbf9eeb3 bellard
691 1a18c71b bellard
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
692 e4533c7a bellard
693 6dbad63e bellard
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
694 6dbad63e bellard
{
695 6dbad63e bellard
    CPUX86State *saved_env;
696 6dbad63e bellard
697 6dbad63e bellard
    saved_env = env;
698 6dbad63e bellard
    env = s;
699 a412ac57 bellard
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
700 a513fe19 bellard
        selector &= 0xffff;
701 5fafdf24 ths
        cpu_x86_load_seg_cache(env, seg_reg, selector,
702 c27004ec bellard
                               (selector << 4), 0xffff, 0);
703 a513fe19 bellard
    } else {
704 5d97559d bellard
        helper_load_seg(seg_reg, selector);
705 a513fe19 bellard
    }
706 6dbad63e bellard
    env = saved_env;
707 6dbad63e bellard
}
708 9de5e440 bellard
709 6f12a2a6 bellard
void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
710 d0a1ffc9 bellard
{
711 d0a1ffc9 bellard
    CPUX86State *saved_env;
712 d0a1ffc9 bellard
713 d0a1ffc9 bellard
    saved_env = env;
714 d0a1ffc9 bellard
    env = s;
715 3b46e624 ths
716 6f12a2a6 bellard
    helper_fsave(ptr, data32);
717 d0a1ffc9 bellard
718 d0a1ffc9 bellard
    env = saved_env;
719 d0a1ffc9 bellard
}
720 d0a1ffc9 bellard
721 6f12a2a6 bellard
void cpu_x86_frstor(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_frstor(ptr, data32);
729 d0a1ffc9 bellard
730 d0a1ffc9 bellard
    env = saved_env;
731 d0a1ffc9 bellard
}
732 d0a1ffc9 bellard
733 e4533c7a bellard
#endif /* TARGET_I386 */
734 e4533c7a bellard
735 67b915a5 bellard
#if !defined(CONFIG_SOFTMMU)
736 67b915a5 bellard
737 3fb2ded1 bellard
#if defined(TARGET_I386)
738 0b5c1ce8 Nathan Froyd
#define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code)
739 0b5c1ce8 Nathan Froyd
#else
740 0b5c1ce8 Nathan Froyd
#define EXCEPTION_ACTION cpu_loop_exit()
741 0b5c1ce8 Nathan Froyd
#endif
742 3fb2ded1 bellard
743 b56dad1c bellard
/* 'pc' is the host PC at which the exception was raised. 'address' is
744 fd6ce8f6 bellard
   the effective address of the memory exception. 'is_write' is 1 if a
745 fd6ce8f6 bellard
   write caused the exception and otherwise 0'. 'old_set' is the
746 fd6ce8f6 bellard
   signal set which should be restored */
747 2b413144 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
748 5fafdf24 ths
                                    int is_write, sigset_t *old_set,
749 bf3e8bf1 bellard
                                    void *puc)
750 9de5e440 bellard
{
751 a513fe19 bellard
    TranslationBlock *tb;
752 a513fe19 bellard
    int ret;
753 68a79315 bellard
754 83479e77 bellard
    if (cpu_single_env)
755 83479e77 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
756 fd6ce8f6 bellard
#if defined(DEBUG_SIGNAL)
757 5fafdf24 ths
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
758 bf3e8bf1 bellard
                pc, address, is_write, *(unsigned long *)old_set);
759 9de5e440 bellard
#endif
760 25eb4484 bellard
    /* XXX: locking issue */
761 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
762 fd6ce8f6 bellard
        return 1;
763 fd6ce8f6 bellard
    }
764 fbf9eeb3 bellard
765 3fb2ded1 bellard
    /* see if it is an MMU fault */
766 0b5c1ce8 Nathan Froyd
    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
767 68016c62 bellard
    if (ret < 0)
768 68016c62 bellard
        return 0; /* not an MMU fault */
769 68016c62 bellard
    if (ret == 0)
770 68016c62 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
771 68016c62 bellard
    /* now we have a real cpu fault */
772 68016c62 bellard
    tb = tb_find_pc(pc);
773 68016c62 bellard
    if (tb) {
774 68016c62 bellard
        /* the PC is inside the translated code. It means that we have
775 68016c62 bellard
           a virtual CPU fault */
776 68016c62 bellard
        cpu_restore_state(tb, env, pc, puc);
777 68016c62 bellard
    }
778 68016c62 bellard
779 68016c62 bellard
    /* we restore the process signal mask as the sigreturn should
780 68016c62 bellard
       do it (XXX: use sigsetjmp) */
781 68016c62 bellard
    sigprocmask(SIG_SETMASK, old_set, NULL);
782 0b5c1ce8 Nathan Froyd
    EXCEPTION_ACTION;
783 e6e5906b pbrook
784 e6e5906b pbrook
    /* never comes here */
785 67867308 bellard
    return 1;
786 67867308 bellard
}
787 6af0bf9c bellard
788 2b413144 bellard
#if defined(__i386__)
789 2b413144 bellard
790 d8ecc0b9 bellard
#if defined(__APPLE__)
791 d8ecc0b9 bellard
# include <sys/ucontext.h>
792 d8ecc0b9 bellard
793 d8ecc0b9 bellard
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
794 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
795 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
796 d39bb24a blueswir1
# define MASK_sig(context)    ((context)->uc_sigmask)
797 78cfb07f Juergen Lock
#elif defined (__NetBSD__)
798 78cfb07f Juergen Lock
# include <ucontext.h>
799 78cfb07f Juergen Lock
800 78cfb07f Juergen Lock
# define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
801 78cfb07f Juergen Lock
# define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
802 78cfb07f Juergen Lock
# define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
803 78cfb07f Juergen Lock
# define MASK_sig(context)    ((context)->uc_sigmask)
804 78cfb07f Juergen Lock
#elif defined (__FreeBSD__) || defined(__DragonFly__)
805 78cfb07f Juergen Lock
# include <ucontext.h>
806 78cfb07f Juergen Lock
807 78cfb07f Juergen Lock
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
808 78cfb07f Juergen Lock
# define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
809 78cfb07f Juergen Lock
# define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
810 78cfb07f Juergen Lock
# define MASK_sig(context)    ((context)->uc_sigmask)
811 d39bb24a blueswir1
#elif defined(__OpenBSD__)
812 d39bb24a blueswir1
# define EIP_sig(context)     ((context)->sc_eip)
813 d39bb24a blueswir1
# define TRAP_sig(context)    ((context)->sc_trapno)
814 d39bb24a blueswir1
# define ERROR_sig(context)   ((context)->sc_err)
815 d39bb24a blueswir1
# define MASK_sig(context)    ((context)->sc_mask)
816 d8ecc0b9 bellard
#else
817 d8ecc0b9 bellard
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
818 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
819 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
820 d39bb24a blueswir1
# define MASK_sig(context)    ((context)->uc_sigmask)
821 d8ecc0b9 bellard
#endif
822 d8ecc0b9 bellard
823 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
824 e4533c7a bellard
                       void *puc)
825 9de5e440 bellard
{
826 5a7b542b ths
    siginfo_t *info = pinfo;
827 78cfb07f Juergen Lock
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
828 78cfb07f Juergen Lock
    ucontext_t *uc = puc;
829 78cfb07f Juergen Lock
#elif defined(__OpenBSD__)
830 d39bb24a blueswir1
    struct sigcontext *uc = puc;
831 d39bb24a blueswir1
#else
832 9de5e440 bellard
    struct ucontext *uc = puc;
833 d39bb24a blueswir1
#endif
834 9de5e440 bellard
    unsigned long pc;
835 bf3e8bf1 bellard
    int trapno;
836 97eb5b14 bellard
837 d691f669 bellard
#ifndef REG_EIP
838 d691f669 bellard
/* for glibc 2.1 */
839 fd6ce8f6 bellard
#define REG_EIP    EIP
840 fd6ce8f6 bellard
#define REG_ERR    ERR
841 fd6ce8f6 bellard
#define REG_TRAPNO TRAPNO
842 d691f669 bellard
#endif
843 d8ecc0b9 bellard
    pc = EIP_sig(uc);
844 d8ecc0b9 bellard
    trapno = TRAP_sig(uc);
845 ec6338ba bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
846 ec6338ba bellard
                             trapno == 0xe ?
847 ec6338ba bellard
                             (ERROR_sig(uc) >> 1) & 1 : 0,
848 d39bb24a blueswir1
                             &MASK_sig(uc), puc);
849 2b413144 bellard
}
850 2b413144 bellard
851 bc51c5c9 bellard
#elif defined(__x86_64__)
852 bc51c5c9 bellard
853 b3efe5c8 blueswir1
#ifdef __NetBSD__
854 d397abbd blueswir1
#define PC_sig(context)       _UC_MACHINE_PC(context)
855 d397abbd blueswir1
#define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
856 d397abbd blueswir1
#define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
857 d397abbd blueswir1
#define MASK_sig(context)     ((context)->uc_sigmask)
858 d397abbd blueswir1
#elif defined(__OpenBSD__)
859 d397abbd blueswir1
#define PC_sig(context)       ((context)->sc_rip)
860 d397abbd blueswir1
#define TRAP_sig(context)     ((context)->sc_trapno)
861 d397abbd blueswir1
#define ERROR_sig(context)    ((context)->sc_err)
862 d397abbd blueswir1
#define MASK_sig(context)     ((context)->sc_mask)
863 78cfb07f Juergen Lock
#elif defined (__FreeBSD__) || defined(__DragonFly__)
864 78cfb07f Juergen Lock
#include <ucontext.h>
865 78cfb07f Juergen Lock
866 78cfb07f Juergen Lock
#define PC_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
867 78cfb07f Juergen Lock
#define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
868 78cfb07f Juergen Lock
#define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
869 78cfb07f Juergen Lock
#define MASK_sig(context)     ((context)->uc_sigmask)
870 b3efe5c8 blueswir1
#else
871 d397abbd blueswir1
#define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
872 d397abbd blueswir1
#define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
873 d397abbd blueswir1
#define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
874 d397abbd blueswir1
#define MASK_sig(context)     ((context)->uc_sigmask)
875 b3efe5c8 blueswir1
#endif
876 b3efe5c8 blueswir1
877 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo,
878 bc51c5c9 bellard
                       void *puc)
879 bc51c5c9 bellard
{
880 5a7b542b ths
    siginfo_t *info = pinfo;
881 bc51c5c9 bellard
    unsigned long pc;
882 78cfb07f Juergen Lock
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
883 b3efe5c8 blueswir1
    ucontext_t *uc = puc;
884 d397abbd blueswir1
#elif defined(__OpenBSD__)
885 d397abbd blueswir1
    struct sigcontext *uc = puc;
886 b3efe5c8 blueswir1
#else
887 b3efe5c8 blueswir1
    struct ucontext *uc = puc;
888 b3efe5c8 blueswir1
#endif
889 bc51c5c9 bellard
890 d397abbd blueswir1
    pc = PC_sig(uc);
891 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
892 d397abbd blueswir1
                             TRAP_sig(uc) == 0xe ?
893 d397abbd blueswir1
                             (ERROR_sig(uc) >> 1) & 1 : 0,
894 d397abbd blueswir1
                             &MASK_sig(uc), puc);
895 bc51c5c9 bellard
}
896 bc51c5c9 bellard
897 e58ffeb3 malc
#elif defined(_ARCH_PPC)
898 2b413144 bellard
899 83fb7adf bellard
/***********************************************************************
900 83fb7adf bellard
 * signal context platform-specific definitions
901 83fb7adf bellard
 * From Wine
902 83fb7adf bellard
 */
903 83fb7adf bellard
#ifdef linux
904 83fb7adf bellard
/* All Registers access - only for local access */
905 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
906 83fb7adf bellard
/* Gpr Registers access  */
907 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
908 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
909 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
910 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
911 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
912 83fb7adf bellard
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
913 83fb7adf bellard
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
914 83fb7adf bellard
/* Float Registers access  */
915 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
916 83fb7adf bellard
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
917 83fb7adf bellard
/* Exception Registers access */
918 83fb7adf bellard
# define DAR_sig(context)                        REG_sig(dar, context)
919 83fb7adf bellard
# define DSISR_sig(context)                        REG_sig(dsisr, context)
920 83fb7adf bellard
# define TRAP_sig(context)                        REG_sig(trap, context)
921 83fb7adf bellard
#endif /* linux */
922 83fb7adf bellard
923 83fb7adf bellard
#ifdef __APPLE__
924 83fb7adf bellard
# include <sys/ucontext.h>
925 83fb7adf bellard
typedef struct ucontext SIGCONTEXT;
926 83fb7adf bellard
/* All Registers access - only for local access */
927 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
928 83fb7adf bellard
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
929 83fb7adf bellard
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
930 83fb7adf bellard
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
931 83fb7adf bellard
/* Gpr Registers access */
932 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
933 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
934 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
935 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)
936 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
937 83fb7adf bellard
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
938 83fb7adf bellard
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
939 83fb7adf bellard
/* Float Registers access */
940 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
941 83fb7adf bellard
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
942 83fb7adf bellard
/* Exception Registers access */
943 83fb7adf bellard
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
944 83fb7adf bellard
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
945 83fb7adf bellard
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
946 83fb7adf bellard
#endif /* __APPLE__ */
947 83fb7adf bellard
948 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
949 e4533c7a bellard
                       void *puc)
950 2b413144 bellard
{
951 5a7b542b ths
    siginfo_t *info = pinfo;
952 25eb4484 bellard
    struct ucontext *uc = puc;
953 25eb4484 bellard
    unsigned long pc;
954 25eb4484 bellard
    int is_write;
955 25eb4484 bellard
956 83fb7adf bellard
    pc = IAR_sig(uc);
957 25eb4484 bellard
    is_write = 0;
958 25eb4484 bellard
#if 0
959 25eb4484 bellard
    /* ppc 4xx case */
960 83fb7adf bellard
    if (DSISR_sig(uc) & 0x00800000)
961 25eb4484 bellard
        is_write = 1;
962 25eb4484 bellard
#else
963 83fb7adf bellard
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
964 25eb4484 bellard
        is_write = 1;
965 25eb4484 bellard
#endif
966 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
967 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
968 2b413144 bellard
}
969 2b413144 bellard
970 2f87c607 bellard
#elif defined(__alpha__)
971 2f87c607 bellard
972 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
973 2f87c607 bellard
                           void *puc)
974 2f87c607 bellard
{
975 5a7b542b ths
    siginfo_t *info = pinfo;
976 2f87c607 bellard
    struct ucontext *uc = puc;
977 2f87c607 bellard
    uint32_t *pc = uc->uc_mcontext.sc_pc;
978 2f87c607 bellard
    uint32_t insn = *pc;
979 2f87c607 bellard
    int is_write = 0;
980 2f87c607 bellard
981 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
982 2f87c607 bellard
    switch (insn >> 26) {
983 2f87c607 bellard
    case 0x0d: // stw
984 2f87c607 bellard
    case 0x0e: // stb
985 2f87c607 bellard
    case 0x0f: // stq_u
986 2f87c607 bellard
    case 0x24: // stf
987 2f87c607 bellard
    case 0x25: // stg
988 2f87c607 bellard
    case 0x26: // sts
989 2f87c607 bellard
    case 0x27: // stt
990 2f87c607 bellard
    case 0x2c: // stl
991 2f87c607 bellard
    case 0x2d: // stq
992 2f87c607 bellard
    case 0x2e: // stl_c
993 2f87c607 bellard
    case 0x2f: // stq_c
994 2f87c607 bellard
        is_write = 1;
995 2f87c607 bellard
    }
996 2f87c607 bellard
997 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
998 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
999 2f87c607 bellard
}
1000 8c6939c0 bellard
#elif defined(__sparc__)
1001 8c6939c0 bellard
1002 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1003 e4533c7a bellard
                       void *puc)
1004 8c6939c0 bellard
{
1005 5a7b542b ths
    siginfo_t *info = pinfo;
1006 8c6939c0 bellard
    int is_write;
1007 8c6939c0 bellard
    uint32_t insn;
1008 dfe5fff3 Juan Quintela
#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
1009 c9e1e2b0 blueswir1
    uint32_t *regs = (uint32_t *)(info + 1);
1010 c9e1e2b0 blueswir1
    void *sigmask = (regs + 20);
1011 8c6939c0 bellard
    /* XXX: is there a standard glibc define ? */
1012 c9e1e2b0 blueswir1
    unsigned long pc = regs[1];
1013 c9e1e2b0 blueswir1
#else
1014 84778508 blueswir1
#ifdef __linux__
1015 c9e1e2b0 blueswir1
    struct sigcontext *sc = puc;
1016 c9e1e2b0 blueswir1
    unsigned long pc = sc->sigc_regs.tpc;
1017 c9e1e2b0 blueswir1
    void *sigmask = (void *)sc->sigc_mask;
1018 84778508 blueswir1
#elif defined(__OpenBSD__)
1019 84778508 blueswir1
    struct sigcontext *uc = puc;
1020 84778508 blueswir1
    unsigned long pc = uc->sc_pc;
1021 84778508 blueswir1
    void *sigmask = (void *)(long)uc->sc_mask;
1022 84778508 blueswir1
#endif
1023 c9e1e2b0 blueswir1
#endif
1024 c9e1e2b0 blueswir1
1025 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1026 8c6939c0 bellard
    is_write = 0;
1027 8c6939c0 bellard
    insn = *(uint32_t *)pc;
1028 8c6939c0 bellard
    if ((insn >> 30) == 3) {
1029 8c6939c0 bellard
      switch((insn >> 19) & 0x3f) {
1030 8c6939c0 bellard
      case 0x05: // stb
1031 d877fa5a Blue Swirl
      case 0x15: // stba
1032 8c6939c0 bellard
      case 0x06: // sth
1033 d877fa5a Blue Swirl
      case 0x16: // stha
1034 8c6939c0 bellard
      case 0x04: // st
1035 d877fa5a Blue Swirl
      case 0x14: // sta
1036 8c6939c0 bellard
      case 0x07: // std
1037 d877fa5a Blue Swirl
      case 0x17: // stda
1038 d877fa5a Blue Swirl
      case 0x0e: // stx
1039 d877fa5a Blue Swirl
      case 0x1e: // stxa
1040 8c6939c0 bellard
      case 0x24: // stf
1041 d877fa5a Blue Swirl
      case 0x34: // stfa
1042 8c6939c0 bellard
      case 0x27: // stdf
1043 d877fa5a Blue Swirl
      case 0x37: // stdfa
1044 d877fa5a Blue Swirl
      case 0x26: // stqf
1045 d877fa5a Blue Swirl
      case 0x36: // stqfa
1046 8c6939c0 bellard
      case 0x25: // stfsr
1047 d877fa5a Blue Swirl
      case 0x3c: // casa
1048 d877fa5a Blue Swirl
      case 0x3e: // casxa
1049 8c6939c0 bellard
        is_write = 1;
1050 8c6939c0 bellard
        break;
1051 8c6939c0 bellard
      }
1052 8c6939c0 bellard
    }
1053 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1054 bf3e8bf1 bellard
                             is_write, sigmask, NULL);
1055 8c6939c0 bellard
}
1056 8c6939c0 bellard
1057 8c6939c0 bellard
#elif defined(__arm__)
1058 8c6939c0 bellard
1059 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1060 e4533c7a bellard
                       void *puc)
1061 8c6939c0 bellard
{
1062 5a7b542b ths
    siginfo_t *info = pinfo;
1063 8c6939c0 bellard
    struct ucontext *uc = puc;
1064 8c6939c0 bellard
    unsigned long pc;
1065 8c6939c0 bellard
    int is_write;
1066 3b46e624 ths
1067 48bbf11b blueswir1
#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1068 5c49b363 balrog
    pc = uc->uc_mcontext.gregs[R15];
1069 5c49b363 balrog
#else
1070 4eee57f5 balrog
    pc = uc->uc_mcontext.arm_pc;
1071 5c49b363 balrog
#endif
1072 8c6939c0 bellard
    /* XXX: compute is_write */
1073 8c6939c0 bellard
    is_write = 0;
1074 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1075 8c6939c0 bellard
                             is_write,
1076 f3a9676a pbrook
                             &uc->uc_sigmask, puc);
1077 8c6939c0 bellard
}
1078 8c6939c0 bellard
1079 38e584a0 bellard
#elif defined(__mc68000)
1080 38e584a0 bellard
1081 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1082 38e584a0 bellard
                       void *puc)
1083 38e584a0 bellard
{
1084 5a7b542b ths
    siginfo_t *info = pinfo;
1085 38e584a0 bellard
    struct ucontext *uc = puc;
1086 38e584a0 bellard
    unsigned long pc;
1087 38e584a0 bellard
    int is_write;
1088 3b46e624 ths
1089 38e584a0 bellard
    pc = uc->uc_mcontext.gregs[16];
1090 38e584a0 bellard
    /* XXX: compute is_write */
1091 38e584a0 bellard
    is_write = 0;
1092 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1093 38e584a0 bellard
                             is_write,
1094 bf3e8bf1 bellard
                             &uc->uc_sigmask, puc);
1095 38e584a0 bellard
}
1096 38e584a0 bellard
1097 b8076a74 bellard
#elif defined(__ia64)
1098 b8076a74 bellard
1099 b8076a74 bellard
#ifndef __ISR_VALID
1100 b8076a74 bellard
  /* This ought to be in <bits/siginfo.h>... */
1101 b8076a74 bellard
# define __ISR_VALID        1
1102 b8076a74 bellard
#endif
1103 b8076a74 bellard
1104 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1105 b8076a74 bellard
{
1106 5a7b542b ths
    siginfo_t *info = pinfo;
1107 b8076a74 bellard
    struct ucontext *uc = puc;
1108 b8076a74 bellard
    unsigned long ip;
1109 b8076a74 bellard
    int is_write = 0;
1110 b8076a74 bellard
1111 b8076a74 bellard
    ip = uc->uc_mcontext.sc_ip;
1112 b8076a74 bellard
    switch (host_signum) {
1113 b8076a74 bellard
      case SIGILL:
1114 b8076a74 bellard
      case SIGFPE:
1115 b8076a74 bellard
      case SIGSEGV:
1116 b8076a74 bellard
      case SIGBUS:
1117 b8076a74 bellard
      case SIGTRAP:
1118 fd4a43e4 bellard
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1119 b8076a74 bellard
              /* ISR.W (write-access) is bit 33:  */
1120 b8076a74 bellard
              is_write = (info->si_isr >> 33) & 1;
1121 b8076a74 bellard
          break;
1122 b8076a74 bellard
1123 b8076a74 bellard
      default:
1124 b8076a74 bellard
          break;
1125 b8076a74 bellard
    }
1126 b8076a74 bellard
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1127 b8076a74 bellard
                             is_write,
1128 b8076a74 bellard
                             &uc->uc_sigmask, puc);
1129 b8076a74 bellard
}
1130 b8076a74 bellard
1131 90cb9493 bellard
#elif defined(__s390__)
1132 90cb9493 bellard
1133 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1134 90cb9493 bellard
                       void *puc)
1135 90cb9493 bellard
{
1136 5a7b542b ths
    siginfo_t *info = pinfo;
1137 90cb9493 bellard
    struct ucontext *uc = puc;
1138 90cb9493 bellard
    unsigned long pc;
1139 90cb9493 bellard
    int is_write;
1140 3b46e624 ths
1141 90cb9493 bellard
    pc = uc->uc_mcontext.psw.addr;
1142 90cb9493 bellard
    /* XXX: compute is_write */
1143 90cb9493 bellard
    is_write = 0;
1144 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1145 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1146 c4b89d18 ths
}
1147 c4b89d18 ths
1148 c4b89d18 ths
#elif defined(__mips__)
1149 c4b89d18 ths
1150 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1151 c4b89d18 ths
                       void *puc)
1152 c4b89d18 ths
{
1153 9617efe8 ths
    siginfo_t *info = pinfo;
1154 c4b89d18 ths
    struct ucontext *uc = puc;
1155 c4b89d18 ths
    greg_t pc = uc->uc_mcontext.pc;
1156 c4b89d18 ths
    int is_write;
1157 3b46e624 ths
1158 c4b89d18 ths
    /* XXX: compute is_write */
1159 c4b89d18 ths
    is_write = 0;
1160 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1161 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1162 90cb9493 bellard
}
1163 90cb9493 bellard
1164 f54b3f92 aurel32
#elif defined(__hppa__)
1165 f54b3f92 aurel32
1166 f54b3f92 aurel32
int cpu_signal_handler(int host_signum, void *pinfo,
1167 f54b3f92 aurel32
                       void *puc)
1168 f54b3f92 aurel32
{
1169 f54b3f92 aurel32
    struct siginfo *info = pinfo;
1170 f54b3f92 aurel32
    struct ucontext *uc = puc;
1171 f54b3f92 aurel32
    unsigned long pc;
1172 f54b3f92 aurel32
    int is_write;
1173 f54b3f92 aurel32
1174 f54b3f92 aurel32
    pc = uc->uc_mcontext.sc_iaoq[0];
1175 f54b3f92 aurel32
    /* FIXME: compute is_write */
1176 f54b3f92 aurel32
    is_write = 0;
1177 f54b3f92 aurel32
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1178 f54b3f92 aurel32
                             is_write,
1179 f54b3f92 aurel32
                             &uc->uc_sigmask, puc);
1180 f54b3f92 aurel32
}
1181 f54b3f92 aurel32
1182 9de5e440 bellard
#else
1183 2b413144 bellard
1184 3fb2ded1 bellard
#error host CPU specific signal handler needed
1185 2b413144 bellard
1186 9de5e440 bellard
#endif
1187 67b915a5 bellard
1188 67b915a5 bellard
#endif /* !defined(CONFIG_SOFTMMU) */