Statistics
| Branch: | Revision:

root / cpu-exec.c @ eda48c34

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