Statistics
| Branch: | Revision:

root / cpu-exec.c @ 58d9b1e0

History | View | Annotate | Download (42.1 kB)

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