Statistics
| Branch: | Revision:

root / cpu-exec.c @ 8ca209ad

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