Statistics
| Branch: | Revision:

root / cpu-exec.c @ 1009d2ed

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