Statistics
| Branch: | Revision:

root / cpu-exec.c @ de7890db

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 8a40a180 bellard
    target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
129 3b46e624 ths
130 8a40a180 bellard
    tb_invalidated_flag = 0;
131 3b46e624 ths
132 8a40a180 bellard
    /* find translated block using physical mappings */
133 8a40a180 bellard
    phys_pc = get_phys_addr_code(env, pc);
134 8a40a180 bellard
    phys_page1 = phys_pc & TARGET_PAGE_MASK;
135 8a40a180 bellard
    phys_page2 = -1;
136 8a40a180 bellard
    h = tb_phys_hash_func(phys_pc);
137 8a40a180 bellard
    ptb1 = &tb_phys_hash[h];
138 8a40a180 bellard
    for(;;) {
139 8a40a180 bellard
        tb = *ptb1;
140 8a40a180 bellard
        if (!tb)
141 8a40a180 bellard
            goto not_found;
142 5fafdf24 ths
        if (tb->pc == pc &&
143 8a40a180 bellard
            tb->page_addr[0] == phys_page1 &&
144 5fafdf24 ths
            tb->cs_base == cs_base &&
145 8a40a180 bellard
            tb->flags == flags) {
146 8a40a180 bellard
            /* check next page if needed */
147 8a40a180 bellard
            if (tb->page_addr[1] != -1) {
148 5fafdf24 ths
                virt_page2 = (pc & TARGET_PAGE_MASK) +
149 8a40a180 bellard
                    TARGET_PAGE_SIZE;
150 8a40a180 bellard
                phys_page2 = get_phys_addr_code(env, virt_page2);
151 8a40a180 bellard
                if (tb->page_addr[1] == phys_page2)
152 8a40a180 bellard
                    goto found;
153 8a40a180 bellard
            } else {
154 8a40a180 bellard
                goto found;
155 8a40a180 bellard
            }
156 8a40a180 bellard
        }
157 8a40a180 bellard
        ptb1 = &tb->phys_hash_next;
158 8a40a180 bellard
    }
159 8a40a180 bellard
 not_found:
160 2e70f6ef pbrook
   /* if no translated code available, then translate it now */
161 2e70f6ef pbrook
    tb = tb_gen_code(env, pc, cs_base, flags, 0);
162 3b46e624 ths
163 8a40a180 bellard
 found:
164 8a40a180 bellard
    /* we add the TB in the virtual pc hash table */
165 8a40a180 bellard
    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
166 8a40a180 bellard
    return tb;
167 8a40a180 bellard
}
168 8a40a180 bellard
169 8a40a180 bellard
static inline TranslationBlock *tb_find_fast(void)
170 8a40a180 bellard
{
171 8a40a180 bellard
    TranslationBlock *tb;
172 8a40a180 bellard
    target_ulong cs_base, pc;
173 6b917547 aliguori
    int flags;
174 8a40a180 bellard
175 8a40a180 bellard
    /* we record a subset of the CPU state. It will
176 8a40a180 bellard
       always be the same before a given translated block
177 8a40a180 bellard
       is executed. */
178 6b917547 aliguori
    cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
179 bce61846 bellard
    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
180 551bd27f ths
    if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
181 551bd27f ths
                 tb->flags != flags)) {
182 8a40a180 bellard
        tb = tb_find_slow(pc, cs_base, flags);
183 8a40a180 bellard
    }
184 8a40a180 bellard
    return tb;
185 8a40a180 bellard
}
186 8a40a180 bellard
187 dde2367e aliguori
static CPUDebugExcpHandler *debug_excp_handler;
188 dde2367e aliguori
189 dde2367e aliguori
CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
190 dde2367e aliguori
{
191 dde2367e aliguori
    CPUDebugExcpHandler *old_handler = debug_excp_handler;
192 dde2367e aliguori
193 dde2367e aliguori
    debug_excp_handler = handler;
194 dde2367e aliguori
    return old_handler;
195 dde2367e aliguori
}
196 dde2367e aliguori
197 6e140f28 aliguori
static void cpu_handle_debug_exception(CPUState *env)
198 6e140f28 aliguori
{
199 6e140f28 aliguori
    CPUWatchpoint *wp;
200 6e140f28 aliguori
201 6e140f28 aliguori
    if (!env->watchpoint_hit)
202 72cf2d4f Blue Swirl
        QTAILQ_FOREACH(wp, &env->watchpoints, entry)
203 6e140f28 aliguori
            wp->flags &= ~BP_WATCHPOINT_HIT;
204 dde2367e aliguori
205 dde2367e aliguori
    if (debug_excp_handler)
206 dde2367e aliguori
        debug_excp_handler(env);
207 6e140f28 aliguori
}
208 6e140f28 aliguori
209 7d13299d bellard
/* main execution loop */
210 7d13299d bellard
211 e4533c7a bellard
int cpu_exec(CPUState *env1)
212 7d13299d bellard
{
213 1d9000e8 Paolo Bonzini
    volatile host_reg_t saved_env_reg;
214 8a40a180 bellard
    int ret, interrupt_request;
215 8a40a180 bellard
    TranslationBlock *tb;
216 c27004ec bellard
    uint8_t *tc_ptr;
217 d5975363 pbrook
    unsigned long next_tb;
218 8c6939c0 bellard
219 bfed01fc ths
    if (cpu_halted(env1) == EXCP_HALTED)
220 bfed01fc ths
        return EXCP_HALTED;
221 5a1e3cfc bellard
222 5fafdf24 ths
    cpu_single_env = env1;
223 6a00d601 bellard
224 24ebf5f3 Paolo Bonzini
    /* the access to env below is actually saving the global register's
225 24ebf5f3 Paolo Bonzini
       value, so that files not including target-xyz/exec.h are free to
226 24ebf5f3 Paolo Bonzini
       use it.  */
227 24ebf5f3 Paolo Bonzini
    QEMU_BUILD_BUG_ON (sizeof (saved_env_reg) != sizeof (env));
228 24ebf5f3 Paolo Bonzini
    saved_env_reg = (host_reg_t) env;
229 24ebf5f3 Paolo Bonzini
    asm("");
230 c27004ec bellard
    env = env1;
231 e4533c7a bellard
232 ecb644f4 ths
#if defined(TARGET_I386)
233 14dcc3e2 Jan Kiszka
    if (!kvm_enabled()) {
234 14dcc3e2 Jan Kiszka
        /* put eflags in CPU temporary format */
235 14dcc3e2 Jan Kiszka
        CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
236 14dcc3e2 Jan Kiszka
        DF = 1 - (2 * ((env->eflags >> 10) & 1));
237 14dcc3e2 Jan Kiszka
        CC_OP = CC_OP_EFLAGS;
238 14dcc3e2 Jan Kiszka
        env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
239 14dcc3e2 Jan Kiszka
    }
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 10ec5117 Alexander Graf
#elif defined(TARGET_S390X)
253 fdf9b3e8 bellard
    /* XXXXX */
254 e4533c7a bellard
#else
255 e4533c7a bellard
#error unsupported target CPU
256 e4533c7a bellard
#endif
257 3fb2ded1 bellard
    env->exception_index = -1;
258 9d27abd9 bellard
259 7d13299d bellard
    /* prepare setjmp context for exception handling */
260 3fb2ded1 bellard
    for(;;) {
261 3fb2ded1 bellard
        if (setjmp(env->jmp_env) == 0) {
262 dfe5fff3 Juan Quintela
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
263 9ddff3d2 blueswir1
#undef env
264 9ddff3d2 blueswir1
                    env = cpu_single_env;
265 9ddff3d2 blueswir1
#define env cpu_single_env
266 9ddff3d2 blueswir1
#endif
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 301d2908 Paolo Bonzini
                    env->exception_index = -1;
321 72d239ed aurel32
#endif
322 3fb2ded1 bellard
                }
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 d84bda46 Blue Swirl
                        cpu_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 d532b26c Igor V. Kovalenko
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
452 d532b26c Igor V. Kovalenko
                        if (cpu_interrupts_enabled(env) &&
453 d532b26c Igor V. Kovalenko
                            env->interrupt_index > 0) {
454 d532b26c Igor V. Kovalenko
                            int pil = env->interrupt_index & 0xf;
455 d532b26c Igor V. Kovalenko
                            int type = env->interrupt_index & 0xf0;
456 d532b26c Igor V. Kovalenko
457 d532b26c Igor V. Kovalenko
                            if (((type == TT_EXTINT) &&
458 d532b26c Igor V. Kovalenko
                                  cpu_pil_allowed(env, pil)) ||
459 d532b26c Igor V. Kovalenko
                                  type != TT_EXTINT) {
460 d532b26c Igor V. Kovalenko
                                env->exception_index = env->interrupt_index;
461 d532b26c Igor V. Kovalenko
                                do_interrupt(env);
462 d532b26c Igor V. Kovalenko
                                next_tb = 0;
463 d532b26c Igor V. Kovalenko
                            }
464 d532b26c Igor V. Kovalenko
                        }
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 fb9fb692 Edgar E. Iglesias
                        && (env->pregs[PR_CCS] & I_FLAG)
505 fb9fb692 Edgar E. Iglesias
                        && !env->locked_irq) {
506 1b1a38b0 edgar_igl
                        env->exception_index = EXCP_IRQ;
507 1b1a38b0 edgar_igl
                        do_interrupt(env);
508 1b1a38b0 edgar_igl
                        next_tb = 0;
509 1b1a38b0 edgar_igl
                    }
510 1b1a38b0 edgar_igl
                    if (interrupt_request & CPU_INTERRUPT_NMI
511 1b1a38b0 edgar_igl
                        && (env->pregs[PR_CCS] & M_FLAG)) {
512 1b1a38b0 edgar_igl
                        env->exception_index = EXCP_NMI;
513 f1ccf904 ths
                        do_interrupt(env);
514 b5fc09ae blueswir1
                        next_tb = 0;
515 f1ccf904 ths
                    }
516 0633879f pbrook
#elif defined(TARGET_M68K)
517 0633879f pbrook
                    if (interrupt_request & CPU_INTERRUPT_HARD
518 0633879f pbrook
                        && ((env->sr & SR_I) >> SR_I_SHIFT)
519 0633879f pbrook
                            < env->pending_level) {
520 0633879f pbrook
                        /* Real hardware gets the interrupt vector via an
521 0633879f pbrook
                           IACK cycle at this point.  Current emulated
522 0633879f pbrook
                           hardware doesn't rely on this, so we
523 0633879f pbrook
                           provide/save the vector when the interrupt is
524 0633879f pbrook
                           first signalled.  */
525 0633879f pbrook
                        env->exception_index = env->pending_vector;
526 0633879f pbrook
                        do_interrupt(1);
527 b5fc09ae blueswir1
                        next_tb = 0;
528 0633879f pbrook
                    }
529 68a79315 bellard
#endif
530 9d05095e bellard
                   /* Don't use the cached interupt_request value,
531 9d05095e bellard
                      do_interrupt may have updated the EXITTB flag. */
532 b5ff1b31 bellard
                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
533 bf3e8bf1 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
534 bf3e8bf1 bellard
                        /* ensure that no TB jump will be modified as
535 bf3e8bf1 bellard
                           the program flow was changed */
536 b5fc09ae blueswir1
                        next_tb = 0;
537 bf3e8bf1 bellard
                    }
538 be214e6c aurel32
                }
539 be214e6c aurel32
                if (unlikely(env->exit_request)) {
540 be214e6c aurel32
                    env->exit_request = 0;
541 be214e6c aurel32
                    env->exception_index = EXCP_INTERRUPT;
542 be214e6c aurel32
                    cpu_loop_exit();
543 3fb2ded1 bellard
                }
544 f0667e66 Juan Quintela
#ifdef CONFIG_DEBUG_EXEC
545 8fec2b8c aliguori
                if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
546 3fb2ded1 bellard
                    /* restore flags in standard format */
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 040f2fb2 Paolo Bonzini
                if (next_tb != 0 && tb->page_addr[1] == -1) {
598 b5fc09ae blueswir1
                    tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
599 3fb2ded1 bellard
                }
600 d5975363 pbrook
                spin_unlock(&tb_lock);
601 55e8b85e malc
602 55e8b85e malc
                /* cpu_interrupt might be called while translating the
603 55e8b85e malc
                   TB, but before it is linked into a potentially
604 55e8b85e malc
                   infinite loop and becomes env->current_tb. Avoid
605 55e8b85e malc
                   starting execution if there is a pending interrupt. */
606 6113d6d3 Paolo Bonzini
                if (!unlikely (env->exit_request)) {
607 6113d6d3 Paolo Bonzini
                    env->current_tb = tb;
608 2e70f6ef pbrook
                    tc_ptr = tb->tc_ptr;
609 3fb2ded1 bellard
                /* execute the generated code */
610 dfe5fff3 Juan Quintela
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
611 572a9d4a blueswir1
#undef env
612 2e70f6ef pbrook
                    env = cpu_single_env;
613 572a9d4a blueswir1
#define env cpu_single_env
614 572a9d4a blueswir1
#endif
615 2e70f6ef pbrook
                    next_tb = tcg_qemu_tb_exec(tc_ptr);
616 2e70f6ef pbrook
                    env->current_tb = NULL;
617 2e70f6ef pbrook
                    if ((next_tb & 3) == 2) {
618 bf20dc07 ths
                        /* Instruction counter expired.  */
619 2e70f6ef pbrook
                        int insns_left;
620 2e70f6ef pbrook
                        tb = (TranslationBlock *)(long)(next_tb & ~3);
621 2e70f6ef pbrook
                        /* Restore PC.  */
622 622ed360 aliguori
                        cpu_pc_from_tb(env, tb);
623 2e70f6ef pbrook
                        insns_left = env->icount_decr.u32;
624 2e70f6ef pbrook
                        if (env->icount_extra && insns_left >= 0) {
625 2e70f6ef pbrook
                            /* Refill decrementer and continue execution.  */
626 2e70f6ef pbrook
                            env->icount_extra += insns_left;
627 2e70f6ef pbrook
                            if (env->icount_extra > 0xffff) {
628 2e70f6ef pbrook
                                insns_left = 0xffff;
629 2e70f6ef pbrook
                            } else {
630 2e70f6ef pbrook
                                insns_left = env->icount_extra;
631 2e70f6ef pbrook
                            }
632 2e70f6ef pbrook
                            env->icount_extra -= insns_left;
633 2e70f6ef pbrook
                            env->icount_decr.u16.low = insns_left;
634 2e70f6ef pbrook
                        } else {
635 2e70f6ef pbrook
                            if (insns_left > 0) {
636 2e70f6ef pbrook
                                /* Execute remaining instructions.  */
637 2e70f6ef pbrook
                                cpu_exec_nocache(insns_left, tb);
638 2e70f6ef pbrook
                            }
639 2e70f6ef pbrook
                            env->exception_index = EXCP_INTERRUPT;
640 2e70f6ef pbrook
                            next_tb = 0;
641 2e70f6ef pbrook
                            cpu_loop_exit();
642 2e70f6ef pbrook
                        }
643 2e70f6ef pbrook
                    }
644 2e70f6ef pbrook
                }
645 4cbf74b6 bellard
                /* reset soft MMU for next block (it can currently
646 4cbf74b6 bellard
                   only be set by a memory fault) */
647 50a518e3 ths
            } /* for(;;) */
648 7d13299d bellard
        }
649 3fb2ded1 bellard
    } /* for(;;) */
650 3fb2ded1 bellard
651 7d13299d bellard
652 e4533c7a bellard
#if defined(TARGET_I386)
653 9de5e440 bellard
    /* restore flags in standard format */
654 a7812ae4 pbrook
    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
655 e4533c7a bellard
#elif defined(TARGET_ARM)
656 b7bcbe95 bellard
    /* XXX: Save/restore host fpu exception state?.  */
657 93ac68bc bellard
#elif defined(TARGET_SPARC)
658 67867308 bellard
#elif defined(TARGET_PPC)
659 e6e5906b pbrook
#elif defined(TARGET_M68K)
660 e6e5906b pbrook
    cpu_m68k_flush_flags(env, env->cc_op);
661 e6e5906b pbrook
    env->cc_op = CC_OP_FLAGS;
662 e6e5906b pbrook
    env->sr = (env->sr & 0xffe0)
663 e6e5906b pbrook
              | env->cc_dest | (env->cc_x << 4);
664 b779e29e Edgar E. Iglesias
#elif defined(TARGET_MICROBLAZE)
665 6af0bf9c bellard
#elif defined(TARGET_MIPS)
666 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
667 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
668 f1ccf904 ths
#elif defined(TARGET_CRIS)
669 10ec5117 Alexander Graf
#elif defined(TARGET_S390X)
670 fdf9b3e8 bellard
    /* XXXXX */
671 e4533c7a bellard
#else
672 e4533c7a bellard
#error unsupported target CPU
673 e4533c7a bellard
#endif
674 1057eaa7 pbrook
675 1057eaa7 pbrook
    /* restore global registers */
676 24ebf5f3 Paolo Bonzini
    asm("");
677 24ebf5f3 Paolo Bonzini
    env = (void *) saved_env_reg;
678 1057eaa7 pbrook
679 6a00d601 bellard
    /* fail safe : never use cpu_single_env outside cpu_exec() */
680 5fafdf24 ths
    cpu_single_env = NULL;
681 7d13299d bellard
    return ret;
682 7d13299d bellard
}
683 6dbad63e bellard
684 fbf9eeb3 bellard
/* must only be called from the generated code as an exception can be
685 fbf9eeb3 bellard
   generated */
686 fbf9eeb3 bellard
void tb_invalidate_page_range(target_ulong start, target_ulong end)
687 fbf9eeb3 bellard
{
688 dc5d0b3d bellard
    /* XXX: cannot enable it yet because it yields to MMU exception
689 dc5d0b3d bellard
       where NIP != read address on PowerPC */
690 dc5d0b3d bellard
#if 0
691 fbf9eeb3 bellard
    target_ulong phys_addr;
692 fbf9eeb3 bellard
    phys_addr = get_phys_addr_code(env, start);
693 fbf9eeb3 bellard
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
694 dc5d0b3d bellard
#endif
695 fbf9eeb3 bellard
}
696 fbf9eeb3 bellard
697 1a18c71b bellard
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
698 e4533c7a bellard
699 6dbad63e bellard
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
700 6dbad63e bellard
{
701 6dbad63e bellard
    CPUX86State *saved_env;
702 6dbad63e bellard
703 6dbad63e bellard
    saved_env = env;
704 6dbad63e bellard
    env = s;
705 a412ac57 bellard
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
706 a513fe19 bellard
        selector &= 0xffff;
707 5fafdf24 ths
        cpu_x86_load_seg_cache(env, seg_reg, selector,
708 c27004ec bellard
                               (selector << 4), 0xffff, 0);
709 a513fe19 bellard
    } else {
710 5d97559d bellard
        helper_load_seg(seg_reg, selector);
711 a513fe19 bellard
    }
712 6dbad63e bellard
    env = saved_env;
713 6dbad63e bellard
}
714 9de5e440 bellard
715 6f12a2a6 bellard
void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
716 d0a1ffc9 bellard
{
717 d0a1ffc9 bellard
    CPUX86State *saved_env;
718 d0a1ffc9 bellard
719 d0a1ffc9 bellard
    saved_env = env;
720 d0a1ffc9 bellard
    env = s;
721 3b46e624 ths
722 6f12a2a6 bellard
    helper_fsave(ptr, data32);
723 d0a1ffc9 bellard
724 d0a1ffc9 bellard
    env = saved_env;
725 d0a1ffc9 bellard
}
726 d0a1ffc9 bellard
727 6f12a2a6 bellard
void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
728 d0a1ffc9 bellard
{
729 d0a1ffc9 bellard
    CPUX86State *saved_env;
730 d0a1ffc9 bellard
731 d0a1ffc9 bellard
    saved_env = env;
732 d0a1ffc9 bellard
    env = s;
733 3b46e624 ths
734 6f12a2a6 bellard
    helper_frstor(ptr, data32);
735 d0a1ffc9 bellard
736 d0a1ffc9 bellard
    env = saved_env;
737 d0a1ffc9 bellard
}
738 d0a1ffc9 bellard
739 e4533c7a bellard
#endif /* TARGET_I386 */
740 e4533c7a bellard
741 67b915a5 bellard
#if !defined(CONFIG_SOFTMMU)
742 67b915a5 bellard
743 3fb2ded1 bellard
#if defined(TARGET_I386)
744 0b5c1ce8 Nathan Froyd
#define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code)
745 0b5c1ce8 Nathan Froyd
#else
746 0b5c1ce8 Nathan Froyd
#define EXCEPTION_ACTION cpu_loop_exit()
747 0b5c1ce8 Nathan Froyd
#endif
748 3fb2ded1 bellard
749 b56dad1c bellard
/* 'pc' is the host PC at which the exception was raised. 'address' is
750 fd6ce8f6 bellard
   the effective address of the memory exception. 'is_write' is 1 if a
751 fd6ce8f6 bellard
   write caused the exception and otherwise 0'. 'old_set' is the
752 fd6ce8f6 bellard
   signal set which should be restored */
753 2b413144 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
754 5fafdf24 ths
                                    int is_write, sigset_t *old_set,
755 bf3e8bf1 bellard
                                    void *puc)
756 9de5e440 bellard
{
757 a513fe19 bellard
    TranslationBlock *tb;
758 a513fe19 bellard
    int ret;
759 68a79315 bellard
760 83479e77 bellard
    if (cpu_single_env)
761 83479e77 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
762 fd6ce8f6 bellard
#if defined(DEBUG_SIGNAL)
763 5fafdf24 ths
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
764 bf3e8bf1 bellard
                pc, address, is_write, *(unsigned long *)old_set);
765 9de5e440 bellard
#endif
766 25eb4484 bellard
    /* XXX: locking issue */
767 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
768 fd6ce8f6 bellard
        return 1;
769 fd6ce8f6 bellard
    }
770 fbf9eeb3 bellard
771 3fb2ded1 bellard
    /* see if it is an MMU fault */
772 0b5c1ce8 Nathan Froyd
    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
773 68016c62 bellard
    if (ret < 0)
774 68016c62 bellard
        return 0; /* not an MMU fault */
775 68016c62 bellard
    if (ret == 0)
776 68016c62 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
777 68016c62 bellard
    /* now we have a real cpu fault */
778 68016c62 bellard
    tb = tb_find_pc(pc);
779 68016c62 bellard
    if (tb) {
780 68016c62 bellard
        /* the PC is inside the translated code. It means that we have
781 68016c62 bellard
           a virtual CPU fault */
782 68016c62 bellard
        cpu_restore_state(tb, env, pc, puc);
783 68016c62 bellard
    }
784 68016c62 bellard
785 68016c62 bellard
    /* we restore the process signal mask as the sigreturn should
786 68016c62 bellard
       do it (XXX: use sigsetjmp) */
787 68016c62 bellard
    sigprocmask(SIG_SETMASK, old_set, NULL);
788 0b5c1ce8 Nathan Froyd
    EXCEPTION_ACTION;
789 e6e5906b pbrook
790 e6e5906b pbrook
    /* never comes here */
791 67867308 bellard
    return 1;
792 67867308 bellard
}
793 6af0bf9c bellard
794 2b413144 bellard
#if defined(__i386__)
795 2b413144 bellard
796 d8ecc0b9 bellard
#if defined(__APPLE__)
797 d8ecc0b9 bellard
# include <sys/ucontext.h>
798 d8ecc0b9 bellard
799 d8ecc0b9 bellard
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
800 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
801 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
802 d39bb24a blueswir1
# define MASK_sig(context)    ((context)->uc_sigmask)
803 78cfb07f Juergen Lock
#elif defined (__NetBSD__)
804 78cfb07f Juergen Lock
# include <ucontext.h>
805 78cfb07f Juergen Lock
806 78cfb07f Juergen Lock
# define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
807 78cfb07f Juergen Lock
# define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
808 78cfb07f Juergen Lock
# define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
809 78cfb07f Juergen Lock
# define MASK_sig(context)    ((context)->uc_sigmask)
810 78cfb07f Juergen Lock
#elif defined (__FreeBSD__) || defined(__DragonFly__)
811 78cfb07f Juergen Lock
# include <ucontext.h>
812 78cfb07f Juergen Lock
813 78cfb07f Juergen Lock
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
814 78cfb07f Juergen Lock
# define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
815 78cfb07f Juergen Lock
# define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
816 78cfb07f Juergen Lock
# define MASK_sig(context)    ((context)->uc_sigmask)
817 d39bb24a blueswir1
#elif defined(__OpenBSD__)
818 d39bb24a blueswir1
# define EIP_sig(context)     ((context)->sc_eip)
819 d39bb24a blueswir1
# define TRAP_sig(context)    ((context)->sc_trapno)
820 d39bb24a blueswir1
# define ERROR_sig(context)   ((context)->sc_err)
821 d39bb24a blueswir1
# define MASK_sig(context)    ((context)->sc_mask)
822 d8ecc0b9 bellard
#else
823 d8ecc0b9 bellard
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
824 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
825 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
826 d39bb24a blueswir1
# define MASK_sig(context)    ((context)->uc_sigmask)
827 d8ecc0b9 bellard
#endif
828 d8ecc0b9 bellard
829 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
830 e4533c7a bellard
                       void *puc)
831 9de5e440 bellard
{
832 5a7b542b ths
    siginfo_t *info = pinfo;
833 78cfb07f Juergen Lock
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
834 78cfb07f Juergen Lock
    ucontext_t *uc = puc;
835 78cfb07f Juergen Lock
#elif defined(__OpenBSD__)
836 d39bb24a blueswir1
    struct sigcontext *uc = puc;
837 d39bb24a blueswir1
#else
838 9de5e440 bellard
    struct ucontext *uc = puc;
839 d39bb24a blueswir1
#endif
840 9de5e440 bellard
    unsigned long pc;
841 bf3e8bf1 bellard
    int trapno;
842 97eb5b14 bellard
843 d691f669 bellard
#ifndef REG_EIP
844 d691f669 bellard
/* for glibc 2.1 */
845 fd6ce8f6 bellard
#define REG_EIP    EIP
846 fd6ce8f6 bellard
#define REG_ERR    ERR
847 fd6ce8f6 bellard
#define REG_TRAPNO TRAPNO
848 d691f669 bellard
#endif
849 d8ecc0b9 bellard
    pc = EIP_sig(uc);
850 d8ecc0b9 bellard
    trapno = TRAP_sig(uc);
851 ec6338ba bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
852 ec6338ba bellard
                             trapno == 0xe ?
853 ec6338ba bellard
                             (ERROR_sig(uc) >> 1) & 1 : 0,
854 d39bb24a blueswir1
                             &MASK_sig(uc), puc);
855 2b413144 bellard
}
856 2b413144 bellard
857 bc51c5c9 bellard
#elif defined(__x86_64__)
858 bc51c5c9 bellard
859 b3efe5c8 blueswir1
#ifdef __NetBSD__
860 d397abbd blueswir1
#define PC_sig(context)       _UC_MACHINE_PC(context)
861 d397abbd blueswir1
#define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
862 d397abbd blueswir1
#define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
863 d397abbd blueswir1
#define MASK_sig(context)     ((context)->uc_sigmask)
864 d397abbd blueswir1
#elif defined(__OpenBSD__)
865 d397abbd blueswir1
#define PC_sig(context)       ((context)->sc_rip)
866 d397abbd blueswir1
#define TRAP_sig(context)     ((context)->sc_trapno)
867 d397abbd blueswir1
#define ERROR_sig(context)    ((context)->sc_err)
868 d397abbd blueswir1
#define MASK_sig(context)     ((context)->sc_mask)
869 78cfb07f Juergen Lock
#elif defined (__FreeBSD__) || defined(__DragonFly__)
870 78cfb07f Juergen Lock
#include <ucontext.h>
871 78cfb07f Juergen Lock
872 78cfb07f Juergen Lock
#define PC_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
873 78cfb07f Juergen Lock
#define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
874 78cfb07f Juergen Lock
#define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
875 78cfb07f Juergen Lock
#define MASK_sig(context)     ((context)->uc_sigmask)
876 b3efe5c8 blueswir1
#else
877 d397abbd blueswir1
#define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
878 d397abbd blueswir1
#define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
879 d397abbd blueswir1
#define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
880 d397abbd blueswir1
#define MASK_sig(context)     ((context)->uc_sigmask)
881 b3efe5c8 blueswir1
#endif
882 b3efe5c8 blueswir1
883 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo,
884 bc51c5c9 bellard
                       void *puc)
885 bc51c5c9 bellard
{
886 5a7b542b ths
    siginfo_t *info = pinfo;
887 bc51c5c9 bellard
    unsigned long pc;
888 78cfb07f Juergen Lock
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
889 b3efe5c8 blueswir1
    ucontext_t *uc = puc;
890 d397abbd blueswir1
#elif defined(__OpenBSD__)
891 d397abbd blueswir1
    struct sigcontext *uc = puc;
892 b3efe5c8 blueswir1
#else
893 b3efe5c8 blueswir1
    struct ucontext *uc = puc;
894 b3efe5c8 blueswir1
#endif
895 bc51c5c9 bellard
896 d397abbd blueswir1
    pc = PC_sig(uc);
897 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
898 d397abbd blueswir1
                             TRAP_sig(uc) == 0xe ?
899 d397abbd blueswir1
                             (ERROR_sig(uc) >> 1) & 1 : 0,
900 d397abbd blueswir1
                             &MASK_sig(uc), puc);
901 bc51c5c9 bellard
}
902 bc51c5c9 bellard
903 e58ffeb3 malc
#elif defined(_ARCH_PPC)
904 2b413144 bellard
905 83fb7adf bellard
/***********************************************************************
906 83fb7adf bellard
 * signal context platform-specific definitions
907 83fb7adf bellard
 * From Wine
908 83fb7adf bellard
 */
909 83fb7adf bellard
#ifdef linux
910 83fb7adf bellard
/* All Registers access - only for local access */
911 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
912 83fb7adf bellard
/* Gpr Registers access  */
913 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
914 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
915 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
916 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
917 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
918 83fb7adf bellard
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
919 83fb7adf bellard
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
920 83fb7adf bellard
/* Float Registers access  */
921 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
922 83fb7adf bellard
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
923 83fb7adf bellard
/* Exception Registers access */
924 83fb7adf bellard
# define DAR_sig(context)                        REG_sig(dar, context)
925 83fb7adf bellard
# define DSISR_sig(context)                        REG_sig(dsisr, context)
926 83fb7adf bellard
# define TRAP_sig(context)                        REG_sig(trap, context)
927 83fb7adf bellard
#endif /* linux */
928 83fb7adf bellard
929 58d9b1e0 Juergen Lock
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
930 58d9b1e0 Juergen Lock
#include <ucontext.h>
931 58d9b1e0 Juergen Lock
# define IAR_sig(context)                ((context)->uc_mcontext.mc_srr0)
932 58d9b1e0 Juergen Lock
# define MSR_sig(context)                ((context)->uc_mcontext.mc_srr1)
933 58d9b1e0 Juergen Lock
# define CTR_sig(context)                ((context)->uc_mcontext.mc_ctr)
934 58d9b1e0 Juergen Lock
# define XER_sig(context)                ((context)->uc_mcontext.mc_xer)
935 58d9b1e0 Juergen Lock
# define LR_sig(context)                ((context)->uc_mcontext.mc_lr)
936 58d9b1e0 Juergen Lock
# define CR_sig(context)                ((context)->uc_mcontext.mc_cr)
937 58d9b1e0 Juergen Lock
/* Exception Registers access */
938 58d9b1e0 Juergen Lock
# define DAR_sig(context)                ((context)->uc_mcontext.mc_dar)
939 58d9b1e0 Juergen Lock
# define DSISR_sig(context)                ((context)->uc_mcontext.mc_dsisr)
940 58d9b1e0 Juergen Lock
# define TRAP_sig(context)                ((context)->uc_mcontext.mc_exc)
941 58d9b1e0 Juergen Lock
#endif /* __FreeBSD__|| __FreeBSD_kernel__ */
942 58d9b1e0 Juergen Lock
943 83fb7adf bellard
#ifdef __APPLE__
944 83fb7adf bellard
# include <sys/ucontext.h>
945 83fb7adf bellard
typedef struct ucontext SIGCONTEXT;
946 83fb7adf bellard
/* All Registers access - only for local access */
947 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
948 83fb7adf bellard
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
949 83fb7adf bellard
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
950 83fb7adf bellard
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
951 83fb7adf bellard
/* Gpr Registers access */
952 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
953 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
954 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
955 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)
956 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
957 83fb7adf bellard
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
958 83fb7adf bellard
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
959 83fb7adf bellard
/* Float Registers access */
960 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
961 83fb7adf bellard
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
962 83fb7adf bellard
/* Exception Registers access */
963 83fb7adf bellard
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
964 83fb7adf bellard
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
965 83fb7adf bellard
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
966 83fb7adf bellard
#endif /* __APPLE__ */
967 83fb7adf bellard
968 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
969 e4533c7a bellard
                       void *puc)
970 2b413144 bellard
{
971 5a7b542b ths
    siginfo_t *info = pinfo;
972 58d9b1e0 Juergen Lock
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
973 58d9b1e0 Juergen Lock
    ucontext_t *uc = puc;
974 58d9b1e0 Juergen Lock
#else
975 25eb4484 bellard
    struct ucontext *uc = puc;
976 58d9b1e0 Juergen Lock
#endif
977 25eb4484 bellard
    unsigned long pc;
978 25eb4484 bellard
    int is_write;
979 25eb4484 bellard
980 83fb7adf bellard
    pc = IAR_sig(uc);
981 25eb4484 bellard
    is_write = 0;
982 25eb4484 bellard
#if 0
983 25eb4484 bellard
    /* ppc 4xx case */
984 83fb7adf bellard
    if (DSISR_sig(uc) & 0x00800000)
985 25eb4484 bellard
        is_write = 1;
986 25eb4484 bellard
#else
987 83fb7adf bellard
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
988 25eb4484 bellard
        is_write = 1;
989 25eb4484 bellard
#endif
990 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
991 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
992 2b413144 bellard
}
993 2b413144 bellard
994 2f87c607 bellard
#elif defined(__alpha__)
995 2f87c607 bellard
996 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
997 2f87c607 bellard
                           void *puc)
998 2f87c607 bellard
{
999 5a7b542b ths
    siginfo_t *info = pinfo;
1000 2f87c607 bellard
    struct ucontext *uc = puc;
1001 2f87c607 bellard
    uint32_t *pc = uc->uc_mcontext.sc_pc;
1002 2f87c607 bellard
    uint32_t insn = *pc;
1003 2f87c607 bellard
    int is_write = 0;
1004 2f87c607 bellard
1005 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1006 2f87c607 bellard
    switch (insn >> 26) {
1007 2f87c607 bellard
    case 0x0d: // stw
1008 2f87c607 bellard
    case 0x0e: // stb
1009 2f87c607 bellard
    case 0x0f: // stq_u
1010 2f87c607 bellard
    case 0x24: // stf
1011 2f87c607 bellard
    case 0x25: // stg
1012 2f87c607 bellard
    case 0x26: // sts
1013 2f87c607 bellard
    case 0x27: // stt
1014 2f87c607 bellard
    case 0x2c: // stl
1015 2f87c607 bellard
    case 0x2d: // stq
1016 2f87c607 bellard
    case 0x2e: // stl_c
1017 2f87c607 bellard
    case 0x2f: // stq_c
1018 2f87c607 bellard
        is_write = 1;
1019 2f87c607 bellard
    }
1020 2f87c607 bellard
1021 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1022 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
1023 2f87c607 bellard
}
1024 8c6939c0 bellard
#elif defined(__sparc__)
1025 8c6939c0 bellard
1026 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1027 e4533c7a bellard
                       void *puc)
1028 8c6939c0 bellard
{
1029 5a7b542b ths
    siginfo_t *info = pinfo;
1030 8c6939c0 bellard
    int is_write;
1031 8c6939c0 bellard
    uint32_t insn;
1032 dfe5fff3 Juan Quintela
#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
1033 c9e1e2b0 blueswir1
    uint32_t *regs = (uint32_t *)(info + 1);
1034 c9e1e2b0 blueswir1
    void *sigmask = (regs + 20);
1035 8c6939c0 bellard
    /* XXX: is there a standard glibc define ? */
1036 c9e1e2b0 blueswir1
    unsigned long pc = regs[1];
1037 c9e1e2b0 blueswir1
#else
1038 84778508 blueswir1
#ifdef __linux__
1039 c9e1e2b0 blueswir1
    struct sigcontext *sc = puc;
1040 c9e1e2b0 blueswir1
    unsigned long pc = sc->sigc_regs.tpc;
1041 c9e1e2b0 blueswir1
    void *sigmask = (void *)sc->sigc_mask;
1042 84778508 blueswir1
#elif defined(__OpenBSD__)
1043 84778508 blueswir1
    struct sigcontext *uc = puc;
1044 84778508 blueswir1
    unsigned long pc = uc->sc_pc;
1045 84778508 blueswir1
    void *sigmask = (void *)(long)uc->sc_mask;
1046 84778508 blueswir1
#endif
1047 c9e1e2b0 blueswir1
#endif
1048 c9e1e2b0 blueswir1
1049 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1050 8c6939c0 bellard
    is_write = 0;
1051 8c6939c0 bellard
    insn = *(uint32_t *)pc;
1052 8c6939c0 bellard
    if ((insn >> 30) == 3) {
1053 8c6939c0 bellard
      switch((insn >> 19) & 0x3f) {
1054 8c6939c0 bellard
      case 0x05: // stb
1055 d877fa5a Blue Swirl
      case 0x15: // stba
1056 8c6939c0 bellard
      case 0x06: // sth
1057 d877fa5a Blue Swirl
      case 0x16: // stha
1058 8c6939c0 bellard
      case 0x04: // st
1059 d877fa5a Blue Swirl
      case 0x14: // sta
1060 8c6939c0 bellard
      case 0x07: // std
1061 d877fa5a Blue Swirl
      case 0x17: // stda
1062 d877fa5a Blue Swirl
      case 0x0e: // stx
1063 d877fa5a Blue Swirl
      case 0x1e: // stxa
1064 8c6939c0 bellard
      case 0x24: // stf
1065 d877fa5a Blue Swirl
      case 0x34: // stfa
1066 8c6939c0 bellard
      case 0x27: // stdf
1067 d877fa5a Blue Swirl
      case 0x37: // stdfa
1068 d877fa5a Blue Swirl
      case 0x26: // stqf
1069 d877fa5a Blue Swirl
      case 0x36: // stqfa
1070 8c6939c0 bellard
      case 0x25: // stfsr
1071 d877fa5a Blue Swirl
      case 0x3c: // casa
1072 d877fa5a Blue Swirl
      case 0x3e: // casxa
1073 8c6939c0 bellard
        is_write = 1;
1074 8c6939c0 bellard
        break;
1075 8c6939c0 bellard
      }
1076 8c6939c0 bellard
    }
1077 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1078 bf3e8bf1 bellard
                             is_write, sigmask, NULL);
1079 8c6939c0 bellard
}
1080 8c6939c0 bellard
1081 8c6939c0 bellard
#elif defined(__arm__)
1082 8c6939c0 bellard
1083 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1084 e4533c7a bellard
                       void *puc)
1085 8c6939c0 bellard
{
1086 5a7b542b ths
    siginfo_t *info = pinfo;
1087 8c6939c0 bellard
    struct ucontext *uc = puc;
1088 8c6939c0 bellard
    unsigned long pc;
1089 8c6939c0 bellard
    int is_write;
1090 3b46e624 ths
1091 48bbf11b blueswir1
#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1092 5c49b363 balrog
    pc = uc->uc_mcontext.gregs[R15];
1093 5c49b363 balrog
#else
1094 4eee57f5 balrog
    pc = uc->uc_mcontext.arm_pc;
1095 5c49b363 balrog
#endif
1096 8c6939c0 bellard
    /* XXX: compute is_write */
1097 8c6939c0 bellard
    is_write = 0;
1098 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1099 8c6939c0 bellard
                             is_write,
1100 f3a9676a pbrook
                             &uc->uc_sigmask, puc);
1101 8c6939c0 bellard
}
1102 8c6939c0 bellard
1103 38e584a0 bellard
#elif defined(__mc68000)
1104 38e584a0 bellard
1105 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1106 38e584a0 bellard
                       void *puc)
1107 38e584a0 bellard
{
1108 5a7b542b ths
    siginfo_t *info = pinfo;
1109 38e584a0 bellard
    struct ucontext *uc = puc;
1110 38e584a0 bellard
    unsigned long pc;
1111 38e584a0 bellard
    int is_write;
1112 3b46e624 ths
1113 38e584a0 bellard
    pc = uc->uc_mcontext.gregs[16];
1114 38e584a0 bellard
    /* XXX: compute is_write */
1115 38e584a0 bellard
    is_write = 0;
1116 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1117 38e584a0 bellard
                             is_write,
1118 bf3e8bf1 bellard
                             &uc->uc_sigmask, puc);
1119 38e584a0 bellard
}
1120 38e584a0 bellard
1121 b8076a74 bellard
#elif defined(__ia64)
1122 b8076a74 bellard
1123 b8076a74 bellard
#ifndef __ISR_VALID
1124 b8076a74 bellard
  /* This ought to be in <bits/siginfo.h>... */
1125 b8076a74 bellard
# define __ISR_VALID        1
1126 b8076a74 bellard
#endif
1127 b8076a74 bellard
1128 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1129 b8076a74 bellard
{
1130 5a7b542b ths
    siginfo_t *info = pinfo;
1131 b8076a74 bellard
    struct ucontext *uc = puc;
1132 b8076a74 bellard
    unsigned long ip;
1133 b8076a74 bellard
    int is_write = 0;
1134 b8076a74 bellard
1135 b8076a74 bellard
    ip = uc->uc_mcontext.sc_ip;
1136 b8076a74 bellard
    switch (host_signum) {
1137 b8076a74 bellard
      case SIGILL:
1138 b8076a74 bellard
      case SIGFPE:
1139 b8076a74 bellard
      case SIGSEGV:
1140 b8076a74 bellard
      case SIGBUS:
1141 b8076a74 bellard
      case SIGTRAP:
1142 fd4a43e4 bellard
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1143 b8076a74 bellard
              /* ISR.W (write-access) is bit 33:  */
1144 b8076a74 bellard
              is_write = (info->si_isr >> 33) & 1;
1145 b8076a74 bellard
          break;
1146 b8076a74 bellard
1147 b8076a74 bellard
      default:
1148 b8076a74 bellard
          break;
1149 b8076a74 bellard
    }
1150 b8076a74 bellard
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1151 b8076a74 bellard
                             is_write,
1152 b8076a74 bellard
                             &uc->uc_sigmask, puc);
1153 b8076a74 bellard
}
1154 b8076a74 bellard
1155 90cb9493 bellard
#elif defined(__s390__)
1156 90cb9493 bellard
1157 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1158 90cb9493 bellard
                       void *puc)
1159 90cb9493 bellard
{
1160 5a7b542b ths
    siginfo_t *info = pinfo;
1161 90cb9493 bellard
    struct ucontext *uc = puc;
1162 90cb9493 bellard
    unsigned long pc;
1163 90cb9493 bellard
    int is_write;
1164 3b46e624 ths
1165 90cb9493 bellard
    pc = uc->uc_mcontext.psw.addr;
1166 90cb9493 bellard
    /* XXX: compute is_write */
1167 90cb9493 bellard
    is_write = 0;
1168 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1169 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1170 c4b89d18 ths
}
1171 c4b89d18 ths
1172 c4b89d18 ths
#elif defined(__mips__)
1173 c4b89d18 ths
1174 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1175 c4b89d18 ths
                       void *puc)
1176 c4b89d18 ths
{
1177 9617efe8 ths
    siginfo_t *info = pinfo;
1178 c4b89d18 ths
    struct ucontext *uc = puc;
1179 c4b89d18 ths
    greg_t pc = uc->uc_mcontext.pc;
1180 c4b89d18 ths
    int is_write;
1181 3b46e624 ths
1182 c4b89d18 ths
    /* XXX: compute is_write */
1183 c4b89d18 ths
    is_write = 0;
1184 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1185 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1186 90cb9493 bellard
}
1187 90cb9493 bellard
1188 f54b3f92 aurel32
#elif defined(__hppa__)
1189 f54b3f92 aurel32
1190 f54b3f92 aurel32
int cpu_signal_handler(int host_signum, void *pinfo,
1191 f54b3f92 aurel32
                       void *puc)
1192 f54b3f92 aurel32
{
1193 f54b3f92 aurel32
    struct siginfo *info = pinfo;
1194 f54b3f92 aurel32
    struct ucontext *uc = puc;
1195 f54b3f92 aurel32
    unsigned long pc;
1196 f54b3f92 aurel32
    int is_write;
1197 f54b3f92 aurel32
1198 f54b3f92 aurel32
    pc = uc->uc_mcontext.sc_iaoq[0];
1199 f54b3f92 aurel32
    /* FIXME: compute is_write */
1200 f54b3f92 aurel32
    is_write = 0;
1201 f54b3f92 aurel32
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1202 f54b3f92 aurel32
                             is_write,
1203 f54b3f92 aurel32
                             &uc->uc_sigmask, puc);
1204 f54b3f92 aurel32
}
1205 f54b3f92 aurel32
1206 9de5e440 bellard
#else
1207 2b413144 bellard
1208 3fb2ded1 bellard
#error host CPU specific signal handler needed
1209 2b413144 bellard
1210 9de5e440 bellard
#endif
1211 67b915a5 bellard
1212 67b915a5 bellard
#endif /* !defined(CONFIG_SOFTMMU) */