Statistics
| Branch: | Revision:

root / cpu-exec.c @ 7b6ecf5b

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