Statistics
| Branch: | Revision:

root / cpu-exec.c @ c05c7a73

History | View | Annotate | Download (42.2 kB)

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