Statistics
| Branch: | Revision:

root / cpu-exec.c @ 496eb021

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