Statistics
| Branch: | Revision:

root / cpu-exec.c @ aa5fb7b3

History | View | Annotate | Download (43.7 kB)

1 7d13299d bellard
/*
2 7d13299d bellard
 *  i386 emulator main execution loop
3 5fafdf24 ths
 *
4 66321a11 bellard
 *  Copyright (c) 2003-2005 Fabrice Bellard
5 7d13299d bellard
 *
6 3ef693a0 bellard
 * This library is free software; you can redistribute it and/or
7 3ef693a0 bellard
 * modify it under the terms of the GNU Lesser General Public
8 3ef693a0 bellard
 * License as published by the Free Software Foundation; either
9 3ef693a0 bellard
 * version 2 of the License, or (at your option) any later version.
10 7d13299d bellard
 *
11 3ef693a0 bellard
 * This library is distributed in the hope that it will be useful,
12 3ef693a0 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 3ef693a0 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 3ef693a0 bellard
 * Lesser General Public License for more details.
15 7d13299d bellard
 *
16 3ef693a0 bellard
 * You should have received a copy of the GNU Lesser General Public
17 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 7d13299d bellard
 */
19 e4533c7a bellard
#include "config.h"
20 93ac68bc bellard
#include "exec.h"
21 956034d7 bellard
#include "disas.h"
22 7cb69cae bellard
#include "tcg.h"
23 7ba1e619 aliguori
#include "kvm.h"
24 7d13299d bellard
25 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
26 fbf9eeb3 bellard
#undef EAX
27 fbf9eeb3 bellard
#undef ECX
28 fbf9eeb3 bellard
#undef EDX
29 fbf9eeb3 bellard
#undef EBX
30 fbf9eeb3 bellard
#undef ESP
31 fbf9eeb3 bellard
#undef EBP
32 fbf9eeb3 bellard
#undef ESI
33 fbf9eeb3 bellard
#undef EDI
34 fbf9eeb3 bellard
#undef EIP
35 fbf9eeb3 bellard
#include <signal.h>
36 84778508 blueswir1
#ifdef __linux__
37 fbf9eeb3 bellard
#include <sys/ucontext.h>
38 fbf9eeb3 bellard
#endif
39 84778508 blueswir1
#endif
40 fbf9eeb3 bellard
41 dfe5fff3 Juan Quintela
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
42 572a9d4a blueswir1
// Work around ugly bugs in glibc that mangle global register contents
43 572a9d4a blueswir1
#undef env
44 572a9d4a blueswir1
#define env cpu_single_env
45 572a9d4a blueswir1
#endif
46 572a9d4a blueswir1
47 36bdbe54 bellard
int tb_invalidated_flag;
48 36bdbe54 bellard
49 f0667e66 Juan Quintela
//#define CONFIG_DEBUG_EXEC
50 9de5e440 bellard
//#define DEBUG_SIGNAL
51 7d13299d bellard
52 6a4955a8 aliguori
int qemu_cpu_has_work(CPUState *env)
53 6a4955a8 aliguori
{
54 6a4955a8 aliguori
    return cpu_has_work(env);
55 6a4955a8 aliguori
}
56 6a4955a8 aliguori
57 e4533c7a bellard
void cpu_loop_exit(void)
58 e4533c7a bellard
{
59 1c3569fe Paolo Bonzini
    env->current_tb = NULL;
60 e4533c7a bellard
    longjmp(env->jmp_env, 1);
61 e4533c7a bellard
}
62 bfed01fc ths
63 fbf9eeb3 bellard
/* exit the current TB from a signal handler. The host registers are
64 fbf9eeb3 bellard
   restored in a state compatible with the CPU emulator
65 fbf9eeb3 bellard
 */
66 5fafdf24 ths
void cpu_resume_from_signal(CPUState *env1, void *puc)
67 fbf9eeb3 bellard
{
68 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
69 84778508 blueswir1
#ifdef __linux__
70 fbf9eeb3 bellard
    struct ucontext *uc = puc;
71 84778508 blueswir1
#elif defined(__OpenBSD__)
72 84778508 blueswir1
    struct sigcontext *uc = puc;
73 84778508 blueswir1
#endif
74 fbf9eeb3 bellard
#endif
75 fbf9eeb3 bellard
76 fbf9eeb3 bellard
    env = env1;
77 fbf9eeb3 bellard
78 fbf9eeb3 bellard
    /* XXX: restore cpu registers saved in host registers */
79 fbf9eeb3 bellard
80 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
81 fbf9eeb3 bellard
    if (puc) {
82 fbf9eeb3 bellard
        /* XXX: use siglongjmp ? */
83 84778508 blueswir1
#ifdef __linux__
84 60e99246 Aurelien Jarno
#ifdef __ia64
85 60e99246 Aurelien Jarno
        sigprocmask(SIG_SETMASK, (sigset_t *)&uc->uc_sigmask, NULL);
86 60e99246 Aurelien Jarno
#else
87 fbf9eeb3 bellard
        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
88 60e99246 Aurelien Jarno
#endif
89 84778508 blueswir1
#elif defined(__OpenBSD__)
90 84778508 blueswir1
        sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
91 84778508 blueswir1
#endif
92 fbf9eeb3 bellard
    }
93 fbf9eeb3 bellard
#endif
94 9a3ea654 pbrook
    env->exception_index = -1;
95 fbf9eeb3 bellard
    longjmp(env->jmp_env, 1);
96 fbf9eeb3 bellard
}
97 fbf9eeb3 bellard
98 2e70f6ef pbrook
/* Execute the code without caching the generated code. An interpreter
99 2e70f6ef pbrook
   could be used if available. */
100 2e70f6ef pbrook
static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
101 2e70f6ef pbrook
{
102 2e70f6ef pbrook
    unsigned long next_tb;
103 2e70f6ef pbrook
    TranslationBlock *tb;
104 2e70f6ef pbrook
105 2e70f6ef pbrook
    /* Should never happen.
106 2e70f6ef pbrook
       We only end up here when an existing TB is too long.  */
107 2e70f6ef pbrook
    if (max_cycles > CF_COUNT_MASK)
108 2e70f6ef pbrook
        max_cycles = CF_COUNT_MASK;
109 2e70f6ef pbrook
110 2e70f6ef pbrook
    tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
111 2e70f6ef pbrook
                     max_cycles);
112 2e70f6ef pbrook
    env->current_tb = tb;
113 2e70f6ef pbrook
    /* execute the generated code */
114 2e70f6ef pbrook
    next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
115 1c3569fe Paolo Bonzini
    env->current_tb = NULL;
116 2e70f6ef pbrook
117 2e70f6ef pbrook
    if ((next_tb & 3) == 2) {
118 2e70f6ef pbrook
        /* Restore PC.  This may happen if async event occurs before
119 2e70f6ef pbrook
           the TB starts executing.  */
120 622ed360 aliguori
        cpu_pc_from_tb(env, tb);
121 2e70f6ef pbrook
    }
122 2e70f6ef pbrook
    tb_phys_invalidate(tb, -1);
123 2e70f6ef pbrook
    tb_free(tb);
124 2e70f6ef pbrook
}
125 2e70f6ef pbrook
126 8a40a180 bellard
static TranslationBlock *tb_find_slow(target_ulong pc,
127 8a40a180 bellard
                                      target_ulong cs_base,
128 c068688b j_mayer
                                      uint64_t flags)
129 8a40a180 bellard
{
130 8a40a180 bellard
    TranslationBlock *tb, **ptb1;
131 8a40a180 bellard
    unsigned int h;
132 41c1b1c9 Paul Brook
    tb_page_addr_t phys_pc, phys_page1, phys_page2;
133 41c1b1c9 Paul Brook
    target_ulong virt_page2;
134 3b46e624 ths
135 8a40a180 bellard
    tb_invalidated_flag = 0;
136 3b46e624 ths
137 8a40a180 bellard
    /* find translated block using physical mappings */
138 41c1b1c9 Paul Brook
    phys_pc = get_page_addr_code(env, pc);
139 8a40a180 bellard
    phys_page1 = phys_pc & TARGET_PAGE_MASK;
140 8a40a180 bellard
    phys_page2 = -1;
141 8a40a180 bellard
    h = tb_phys_hash_func(phys_pc);
142 8a40a180 bellard
    ptb1 = &tb_phys_hash[h];
143 8a40a180 bellard
    for(;;) {
144 8a40a180 bellard
        tb = *ptb1;
145 8a40a180 bellard
        if (!tb)
146 8a40a180 bellard
            goto not_found;
147 5fafdf24 ths
        if (tb->pc == pc &&
148 8a40a180 bellard
            tb->page_addr[0] == phys_page1 &&
149 5fafdf24 ths
            tb->cs_base == cs_base &&
150 8a40a180 bellard
            tb->flags == flags) {
151 8a40a180 bellard
            /* check next page if needed */
152 8a40a180 bellard
            if (tb->page_addr[1] != -1) {
153 5fafdf24 ths
                virt_page2 = (pc & TARGET_PAGE_MASK) +
154 8a40a180 bellard
                    TARGET_PAGE_SIZE;
155 41c1b1c9 Paul Brook
                phys_page2 = get_page_addr_code(env, virt_page2);
156 8a40a180 bellard
                if (tb->page_addr[1] == phys_page2)
157 8a40a180 bellard
                    goto found;
158 8a40a180 bellard
            } else {
159 8a40a180 bellard
                goto found;
160 8a40a180 bellard
            }
161 8a40a180 bellard
        }
162 8a40a180 bellard
        ptb1 = &tb->phys_hash_next;
163 8a40a180 bellard
    }
164 8a40a180 bellard
 not_found:
165 2e70f6ef pbrook
   /* if no translated code available, then translate it now */
166 2e70f6ef pbrook
    tb = tb_gen_code(env, pc, cs_base, flags, 0);
167 3b46e624 ths
168 8a40a180 bellard
 found:
169 8a40a180 bellard
    /* we add the TB in the virtual pc hash table */
170 8a40a180 bellard
    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
171 8a40a180 bellard
    return tb;
172 8a40a180 bellard
}
173 8a40a180 bellard
174 8a40a180 bellard
static inline TranslationBlock *tb_find_fast(void)
175 8a40a180 bellard
{
176 8a40a180 bellard
    TranslationBlock *tb;
177 8a40a180 bellard
    target_ulong cs_base, pc;
178 6b917547 aliguori
    int flags;
179 8a40a180 bellard
180 8a40a180 bellard
    /* we record a subset of the CPU state. It will
181 8a40a180 bellard
       always be the same before a given translated block
182 8a40a180 bellard
       is executed. */
183 6b917547 aliguori
    cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
184 bce61846 bellard
    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
185 551bd27f ths
    if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
186 551bd27f ths
                 tb->flags != flags)) {
187 8a40a180 bellard
        tb = tb_find_slow(pc, cs_base, flags);
188 8a40a180 bellard
    }
189 8a40a180 bellard
    return tb;
190 8a40a180 bellard
}
191 8a40a180 bellard
192 dde2367e aliguori
static CPUDebugExcpHandler *debug_excp_handler;
193 dde2367e aliguori
194 dde2367e aliguori
CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
195 dde2367e aliguori
{
196 dde2367e aliguori
    CPUDebugExcpHandler *old_handler = debug_excp_handler;
197 dde2367e aliguori
198 dde2367e aliguori
    debug_excp_handler = handler;
199 dde2367e aliguori
    return old_handler;
200 dde2367e aliguori
}
201 dde2367e aliguori
202 6e140f28 aliguori
static void cpu_handle_debug_exception(CPUState *env)
203 6e140f28 aliguori
{
204 6e140f28 aliguori
    CPUWatchpoint *wp;
205 6e140f28 aliguori
206 6e140f28 aliguori
    if (!env->watchpoint_hit)
207 72cf2d4f Blue Swirl
        QTAILQ_FOREACH(wp, &env->watchpoints, entry)
208 6e140f28 aliguori
            wp->flags &= ~BP_WATCHPOINT_HIT;
209 dde2367e aliguori
210 dde2367e aliguori
    if (debug_excp_handler)
211 dde2367e aliguori
        debug_excp_handler(env);
212 6e140f28 aliguori
}
213 6e140f28 aliguori
214 7d13299d bellard
/* main execution loop */
215 7d13299d bellard
216 1a28cac3 Marcelo Tosatti
volatile sig_atomic_t exit_request;
217 1a28cac3 Marcelo Tosatti
218 e4533c7a bellard
int cpu_exec(CPUState *env1)
219 7d13299d bellard
{
220 1d9000e8 Paolo Bonzini
    volatile host_reg_t saved_env_reg;
221 8a40a180 bellard
    int ret, interrupt_request;
222 8a40a180 bellard
    TranslationBlock *tb;
223 c27004ec bellard
    uint8_t *tc_ptr;
224 d5975363 pbrook
    unsigned long next_tb;
225 8c6939c0 bellard
226 bfed01fc ths
    if (cpu_halted(env1) == EXCP_HALTED)
227 bfed01fc ths
        return EXCP_HALTED;
228 5a1e3cfc bellard
229 5fafdf24 ths
    cpu_single_env = env1;
230 6a00d601 bellard
231 24ebf5f3 Paolo Bonzini
    /* the access to env below is actually saving the global register's
232 24ebf5f3 Paolo Bonzini
       value, so that files not including target-xyz/exec.h are free to
233 24ebf5f3 Paolo Bonzini
       use it.  */
234 24ebf5f3 Paolo Bonzini
    QEMU_BUILD_BUG_ON (sizeof (saved_env_reg) != sizeof (env));
235 24ebf5f3 Paolo Bonzini
    saved_env_reg = (host_reg_t) env;
236 24ebf5f3 Paolo Bonzini
    asm("");
237 c27004ec bellard
    env = env1;
238 e4533c7a bellard
239 1a28cac3 Marcelo Tosatti
    if (exit_request) {
240 1a28cac3 Marcelo Tosatti
        env->exit_request = 1;
241 1a28cac3 Marcelo Tosatti
        exit_request = 0;
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 24c7b0e3 ths
                        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
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 6113d6d3 Paolo Bonzini
                if (!unlikely (env->exit_request)) {
603 6113d6d3 Paolo Bonzini
                    env->current_tb = tb;
604 2e70f6ef pbrook
                    tc_ptr = tb->tc_ptr;
605 3fb2ded1 bellard
                /* execute the generated code */
606 dfe5fff3 Juan Quintela
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
607 572a9d4a blueswir1
#undef env
608 2e70f6ef pbrook
                    env = cpu_single_env;
609 572a9d4a blueswir1
#define env cpu_single_env
610 572a9d4a blueswir1
#endif
611 2e70f6ef pbrook
                    next_tb = tcg_qemu_tb_exec(tc_ptr);
612 2e70f6ef pbrook
                    env->current_tb = NULL;
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 4cbf74b6 bellard
                /* reset soft MMU for next block (it can currently
642 4cbf74b6 bellard
                   only be set by a memory fault) */
643 50a518e3 ths
            } /* for(;;) */
644 7d13299d bellard
        }
645 3fb2ded1 bellard
    } /* for(;;) */
646 3fb2ded1 bellard
647 7d13299d bellard
648 e4533c7a bellard
#if defined(TARGET_I386)
649 9de5e440 bellard
    /* restore flags in standard format */
650 a7812ae4 pbrook
    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
651 e4533c7a bellard
#elif defined(TARGET_ARM)
652 b7bcbe95 bellard
    /* XXX: Save/restore host fpu exception state?.  */
653 93ac68bc bellard
#elif defined(TARGET_SPARC)
654 67867308 bellard
#elif defined(TARGET_PPC)
655 e6e5906b pbrook
#elif defined(TARGET_M68K)
656 e6e5906b pbrook
    cpu_m68k_flush_flags(env, env->cc_op);
657 e6e5906b pbrook
    env->cc_op = CC_OP_FLAGS;
658 e6e5906b pbrook
    env->sr = (env->sr & 0xffe0)
659 e6e5906b pbrook
              | env->cc_dest | (env->cc_x << 4);
660 b779e29e Edgar E. Iglesias
#elif defined(TARGET_MICROBLAZE)
661 6af0bf9c bellard
#elif defined(TARGET_MIPS)
662 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
663 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
664 f1ccf904 ths
#elif defined(TARGET_CRIS)
665 10ec5117 Alexander Graf
#elif defined(TARGET_S390X)
666 fdf9b3e8 bellard
    /* XXXXX */
667 e4533c7a bellard
#else
668 e4533c7a bellard
#error unsupported target CPU
669 e4533c7a bellard
#endif
670 1057eaa7 pbrook
671 1057eaa7 pbrook
    /* restore global registers */
672 24ebf5f3 Paolo Bonzini
    asm("");
673 24ebf5f3 Paolo Bonzini
    env = (void *) saved_env_reg;
674 1057eaa7 pbrook
675 6a00d601 bellard
    /* fail safe : never use cpu_single_env outside cpu_exec() */
676 5fafdf24 ths
    cpu_single_env = NULL;
677 7d13299d bellard
    return ret;
678 7d13299d bellard
}
679 6dbad63e bellard
680 fbf9eeb3 bellard
/* must only be called from the generated code as an exception can be
681 fbf9eeb3 bellard
   generated */
682 fbf9eeb3 bellard
void tb_invalidate_page_range(target_ulong start, target_ulong end)
683 fbf9eeb3 bellard
{
684 dc5d0b3d bellard
    /* XXX: cannot enable it yet because it yields to MMU exception
685 dc5d0b3d bellard
       where NIP != read address on PowerPC */
686 dc5d0b3d bellard
#if 0
687 fbf9eeb3 bellard
    target_ulong phys_addr;
688 fbf9eeb3 bellard
    phys_addr = get_phys_addr_code(env, start);
689 fbf9eeb3 bellard
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
690 dc5d0b3d bellard
#endif
691 fbf9eeb3 bellard
}
692 fbf9eeb3 bellard
693 1a18c71b bellard
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
694 e4533c7a bellard
695 6dbad63e bellard
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
696 6dbad63e bellard
{
697 6dbad63e bellard
    CPUX86State *saved_env;
698 6dbad63e bellard
699 6dbad63e bellard
    saved_env = env;
700 6dbad63e bellard
    env = s;
701 a412ac57 bellard
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
702 a513fe19 bellard
        selector &= 0xffff;
703 5fafdf24 ths
        cpu_x86_load_seg_cache(env, seg_reg, selector,
704 c27004ec bellard
                               (selector << 4), 0xffff, 0);
705 a513fe19 bellard
    } else {
706 5d97559d bellard
        helper_load_seg(seg_reg, selector);
707 a513fe19 bellard
    }
708 6dbad63e bellard
    env = saved_env;
709 6dbad63e bellard
}
710 9de5e440 bellard
711 6f12a2a6 bellard
void cpu_x86_fsave(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_fsave(ptr, data32);
719 d0a1ffc9 bellard
720 d0a1ffc9 bellard
    env = saved_env;
721 d0a1ffc9 bellard
}
722 d0a1ffc9 bellard
723 6f12a2a6 bellard
void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
724 d0a1ffc9 bellard
{
725 d0a1ffc9 bellard
    CPUX86State *saved_env;
726 d0a1ffc9 bellard
727 d0a1ffc9 bellard
    saved_env = env;
728 d0a1ffc9 bellard
    env = s;
729 3b46e624 ths
730 6f12a2a6 bellard
    helper_frstor(ptr, data32);
731 d0a1ffc9 bellard
732 d0a1ffc9 bellard
    env = saved_env;
733 d0a1ffc9 bellard
}
734 d0a1ffc9 bellard
735 e4533c7a bellard
#endif /* TARGET_I386 */
736 e4533c7a bellard
737 67b915a5 bellard
#if !defined(CONFIG_SOFTMMU)
738 67b915a5 bellard
739 3fb2ded1 bellard
#if defined(TARGET_I386)
740 0b5c1ce8 Nathan Froyd
#define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code)
741 0b5c1ce8 Nathan Froyd
#else
742 0b5c1ce8 Nathan Froyd
#define EXCEPTION_ACTION cpu_loop_exit()
743 0b5c1ce8 Nathan Froyd
#endif
744 3fb2ded1 bellard
745 b56dad1c bellard
/* 'pc' is the host PC at which the exception was raised. 'address' is
746 fd6ce8f6 bellard
   the effective address of the memory exception. 'is_write' is 1 if a
747 fd6ce8f6 bellard
   write caused the exception and otherwise 0'. 'old_set' is the
748 fd6ce8f6 bellard
   signal set which should be restored */
749 2b413144 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
750 5fafdf24 ths
                                    int is_write, sigset_t *old_set,
751 bf3e8bf1 bellard
                                    void *puc)
752 9de5e440 bellard
{
753 a513fe19 bellard
    TranslationBlock *tb;
754 a513fe19 bellard
    int ret;
755 68a79315 bellard
756 83479e77 bellard
    if (cpu_single_env)
757 83479e77 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
758 fd6ce8f6 bellard
#if defined(DEBUG_SIGNAL)
759 5fafdf24 ths
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
760 bf3e8bf1 bellard
                pc, address, is_write, *(unsigned long *)old_set);
761 9de5e440 bellard
#endif
762 25eb4484 bellard
    /* XXX: locking issue */
763 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
764 fd6ce8f6 bellard
        return 1;
765 fd6ce8f6 bellard
    }
766 fbf9eeb3 bellard
767 3fb2ded1 bellard
    /* see if it is an MMU fault */
768 0b5c1ce8 Nathan Froyd
    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
769 68016c62 bellard
    if (ret < 0)
770 68016c62 bellard
        return 0; /* not an MMU fault */
771 68016c62 bellard
    if (ret == 0)
772 68016c62 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
773 68016c62 bellard
    /* now we have a real cpu fault */
774 68016c62 bellard
    tb = tb_find_pc(pc);
775 68016c62 bellard
    if (tb) {
776 68016c62 bellard
        /* the PC is inside the translated code. It means that we have
777 68016c62 bellard
           a virtual CPU fault */
778 68016c62 bellard
        cpu_restore_state(tb, env, pc, puc);
779 68016c62 bellard
    }
780 68016c62 bellard
781 68016c62 bellard
    /* we restore the process signal mask as the sigreturn should
782 68016c62 bellard
       do it (XXX: use sigsetjmp) */
783 68016c62 bellard
    sigprocmask(SIG_SETMASK, old_set, NULL);
784 0b5c1ce8 Nathan Froyd
    EXCEPTION_ACTION;
785 e6e5906b pbrook
786 e6e5906b pbrook
    /* never comes here */
787 67867308 bellard
    return 1;
788 67867308 bellard
}
789 6af0bf9c bellard
790 2b413144 bellard
#if defined(__i386__)
791 2b413144 bellard
792 d8ecc0b9 bellard
#if defined(__APPLE__)
793 d8ecc0b9 bellard
# include <sys/ucontext.h>
794 d8ecc0b9 bellard
795 d8ecc0b9 bellard
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
796 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
797 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
798 d39bb24a blueswir1
# define MASK_sig(context)    ((context)->uc_sigmask)
799 78cfb07f Juergen Lock
#elif defined (__NetBSD__)
800 78cfb07f Juergen Lock
# include <ucontext.h>
801 78cfb07f Juergen Lock
802 78cfb07f Juergen Lock
# define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
803 78cfb07f Juergen Lock
# define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
804 78cfb07f Juergen Lock
# define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
805 78cfb07f Juergen Lock
# define MASK_sig(context)    ((context)->uc_sigmask)
806 78cfb07f Juergen Lock
#elif defined (__FreeBSD__) || defined(__DragonFly__)
807 78cfb07f Juergen Lock
# include <ucontext.h>
808 78cfb07f Juergen Lock
809 78cfb07f Juergen Lock
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
810 78cfb07f Juergen Lock
# define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
811 78cfb07f Juergen Lock
# define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
812 78cfb07f Juergen Lock
# define MASK_sig(context)    ((context)->uc_sigmask)
813 d39bb24a blueswir1
#elif defined(__OpenBSD__)
814 d39bb24a blueswir1
# define EIP_sig(context)     ((context)->sc_eip)
815 d39bb24a blueswir1
# define TRAP_sig(context)    ((context)->sc_trapno)
816 d39bb24a blueswir1
# define ERROR_sig(context)   ((context)->sc_err)
817 d39bb24a blueswir1
# define MASK_sig(context)    ((context)->sc_mask)
818 d8ecc0b9 bellard
#else
819 d8ecc0b9 bellard
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
820 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
821 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
822 d39bb24a blueswir1
# define MASK_sig(context)    ((context)->uc_sigmask)
823 d8ecc0b9 bellard
#endif
824 d8ecc0b9 bellard
825 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
826 e4533c7a bellard
                       void *puc)
827 9de5e440 bellard
{
828 5a7b542b ths
    siginfo_t *info = pinfo;
829 78cfb07f Juergen Lock
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
830 78cfb07f Juergen Lock
    ucontext_t *uc = puc;
831 78cfb07f Juergen Lock
#elif defined(__OpenBSD__)
832 d39bb24a blueswir1
    struct sigcontext *uc = puc;
833 d39bb24a blueswir1
#else
834 9de5e440 bellard
    struct ucontext *uc = puc;
835 d39bb24a blueswir1
#endif
836 9de5e440 bellard
    unsigned long pc;
837 bf3e8bf1 bellard
    int trapno;
838 97eb5b14 bellard
839 d691f669 bellard
#ifndef REG_EIP
840 d691f669 bellard
/* for glibc 2.1 */
841 fd6ce8f6 bellard
#define REG_EIP    EIP
842 fd6ce8f6 bellard
#define REG_ERR    ERR
843 fd6ce8f6 bellard
#define REG_TRAPNO TRAPNO
844 d691f669 bellard
#endif
845 d8ecc0b9 bellard
    pc = EIP_sig(uc);
846 d8ecc0b9 bellard
    trapno = TRAP_sig(uc);
847 ec6338ba bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
848 ec6338ba bellard
                             trapno == 0xe ?
849 ec6338ba bellard
                             (ERROR_sig(uc) >> 1) & 1 : 0,
850 d39bb24a blueswir1
                             &MASK_sig(uc), puc);
851 2b413144 bellard
}
852 2b413144 bellard
853 bc51c5c9 bellard
#elif defined(__x86_64__)
854 bc51c5c9 bellard
855 b3efe5c8 blueswir1
#ifdef __NetBSD__
856 d397abbd blueswir1
#define PC_sig(context)       _UC_MACHINE_PC(context)
857 d397abbd blueswir1
#define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
858 d397abbd blueswir1
#define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
859 d397abbd blueswir1
#define MASK_sig(context)     ((context)->uc_sigmask)
860 d397abbd blueswir1
#elif defined(__OpenBSD__)
861 d397abbd blueswir1
#define PC_sig(context)       ((context)->sc_rip)
862 d397abbd blueswir1
#define TRAP_sig(context)     ((context)->sc_trapno)
863 d397abbd blueswir1
#define ERROR_sig(context)    ((context)->sc_err)
864 d397abbd blueswir1
#define MASK_sig(context)     ((context)->sc_mask)
865 78cfb07f Juergen Lock
#elif defined (__FreeBSD__) || defined(__DragonFly__)
866 78cfb07f Juergen Lock
#include <ucontext.h>
867 78cfb07f Juergen Lock
868 78cfb07f Juergen Lock
#define PC_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
869 78cfb07f Juergen Lock
#define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
870 78cfb07f Juergen Lock
#define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
871 78cfb07f Juergen Lock
#define MASK_sig(context)     ((context)->uc_sigmask)
872 b3efe5c8 blueswir1
#else
873 d397abbd blueswir1
#define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
874 d397abbd blueswir1
#define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
875 d397abbd blueswir1
#define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
876 d397abbd blueswir1
#define MASK_sig(context)     ((context)->uc_sigmask)
877 b3efe5c8 blueswir1
#endif
878 b3efe5c8 blueswir1
879 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo,
880 bc51c5c9 bellard
                       void *puc)
881 bc51c5c9 bellard
{
882 5a7b542b ths
    siginfo_t *info = pinfo;
883 bc51c5c9 bellard
    unsigned long pc;
884 78cfb07f Juergen Lock
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
885 b3efe5c8 blueswir1
    ucontext_t *uc = puc;
886 d397abbd blueswir1
#elif defined(__OpenBSD__)
887 d397abbd blueswir1
    struct sigcontext *uc = puc;
888 b3efe5c8 blueswir1
#else
889 b3efe5c8 blueswir1
    struct ucontext *uc = puc;
890 b3efe5c8 blueswir1
#endif
891 bc51c5c9 bellard
892 d397abbd blueswir1
    pc = PC_sig(uc);
893 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
894 d397abbd blueswir1
                             TRAP_sig(uc) == 0xe ?
895 d397abbd blueswir1
                             (ERROR_sig(uc) >> 1) & 1 : 0,
896 d397abbd blueswir1
                             &MASK_sig(uc), puc);
897 bc51c5c9 bellard
}
898 bc51c5c9 bellard
899 e58ffeb3 malc
#elif defined(_ARCH_PPC)
900 2b413144 bellard
901 83fb7adf bellard
/***********************************************************************
902 83fb7adf bellard
 * signal context platform-specific definitions
903 83fb7adf bellard
 * From Wine
904 83fb7adf bellard
 */
905 83fb7adf bellard
#ifdef linux
906 83fb7adf bellard
/* All Registers access - only for local access */
907 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
908 83fb7adf bellard
/* Gpr Registers access  */
909 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
910 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
911 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
912 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
913 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
914 83fb7adf bellard
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
915 83fb7adf bellard
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
916 83fb7adf bellard
/* Float Registers access  */
917 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
918 83fb7adf bellard
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
919 83fb7adf bellard
/* Exception Registers access */
920 83fb7adf bellard
# define DAR_sig(context)                        REG_sig(dar, context)
921 83fb7adf bellard
# define DSISR_sig(context)                        REG_sig(dsisr, context)
922 83fb7adf bellard
# define TRAP_sig(context)                        REG_sig(trap, context)
923 83fb7adf bellard
#endif /* linux */
924 83fb7adf bellard
925 58d9b1e0 Juergen Lock
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
926 58d9b1e0 Juergen Lock
#include <ucontext.h>
927 58d9b1e0 Juergen Lock
# define IAR_sig(context)                ((context)->uc_mcontext.mc_srr0)
928 58d9b1e0 Juergen Lock
# define MSR_sig(context)                ((context)->uc_mcontext.mc_srr1)
929 58d9b1e0 Juergen Lock
# define CTR_sig(context)                ((context)->uc_mcontext.mc_ctr)
930 58d9b1e0 Juergen Lock
# define XER_sig(context)                ((context)->uc_mcontext.mc_xer)
931 58d9b1e0 Juergen Lock
# define LR_sig(context)                ((context)->uc_mcontext.mc_lr)
932 58d9b1e0 Juergen Lock
# define CR_sig(context)                ((context)->uc_mcontext.mc_cr)
933 58d9b1e0 Juergen Lock
/* Exception Registers access */
934 58d9b1e0 Juergen Lock
# define DAR_sig(context)                ((context)->uc_mcontext.mc_dar)
935 58d9b1e0 Juergen Lock
# define DSISR_sig(context)                ((context)->uc_mcontext.mc_dsisr)
936 58d9b1e0 Juergen Lock
# define TRAP_sig(context)                ((context)->uc_mcontext.mc_exc)
937 58d9b1e0 Juergen Lock
#endif /* __FreeBSD__|| __FreeBSD_kernel__ */
938 58d9b1e0 Juergen Lock
939 83fb7adf bellard
#ifdef __APPLE__
940 83fb7adf bellard
# include <sys/ucontext.h>
941 83fb7adf bellard
typedef struct ucontext SIGCONTEXT;
942 83fb7adf bellard
/* All Registers access - only for local access */
943 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
944 83fb7adf bellard
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
945 83fb7adf bellard
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
946 83fb7adf bellard
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
947 83fb7adf bellard
/* Gpr Registers access */
948 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
949 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
950 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
951 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)
952 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
953 83fb7adf bellard
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
954 83fb7adf bellard
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
955 83fb7adf bellard
/* Float Registers access */
956 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
957 83fb7adf bellard
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
958 83fb7adf bellard
/* Exception Registers access */
959 83fb7adf bellard
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
960 83fb7adf bellard
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
961 83fb7adf bellard
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
962 83fb7adf bellard
#endif /* __APPLE__ */
963 83fb7adf bellard
964 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
965 e4533c7a bellard
                       void *puc)
966 2b413144 bellard
{
967 5a7b542b ths
    siginfo_t *info = pinfo;
968 58d9b1e0 Juergen Lock
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
969 58d9b1e0 Juergen Lock
    ucontext_t *uc = puc;
970 58d9b1e0 Juergen Lock
#else
971 25eb4484 bellard
    struct ucontext *uc = puc;
972 58d9b1e0 Juergen Lock
#endif
973 25eb4484 bellard
    unsigned long pc;
974 25eb4484 bellard
    int is_write;
975 25eb4484 bellard
976 83fb7adf bellard
    pc = IAR_sig(uc);
977 25eb4484 bellard
    is_write = 0;
978 25eb4484 bellard
#if 0
979 25eb4484 bellard
    /* ppc 4xx case */
980 83fb7adf bellard
    if (DSISR_sig(uc) & 0x00800000)
981 25eb4484 bellard
        is_write = 1;
982 25eb4484 bellard
#else
983 83fb7adf bellard
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
984 25eb4484 bellard
        is_write = 1;
985 25eb4484 bellard
#endif
986 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
987 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
988 2b413144 bellard
}
989 2b413144 bellard
990 2f87c607 bellard
#elif defined(__alpha__)
991 2f87c607 bellard
992 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
993 2f87c607 bellard
                           void *puc)
994 2f87c607 bellard
{
995 5a7b542b ths
    siginfo_t *info = pinfo;
996 2f87c607 bellard
    struct ucontext *uc = puc;
997 2f87c607 bellard
    uint32_t *pc = uc->uc_mcontext.sc_pc;
998 2f87c607 bellard
    uint32_t insn = *pc;
999 2f87c607 bellard
    int is_write = 0;
1000 2f87c607 bellard
1001 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1002 2f87c607 bellard
    switch (insn >> 26) {
1003 2f87c607 bellard
    case 0x0d: // stw
1004 2f87c607 bellard
    case 0x0e: // stb
1005 2f87c607 bellard
    case 0x0f: // stq_u
1006 2f87c607 bellard
    case 0x24: // stf
1007 2f87c607 bellard
    case 0x25: // stg
1008 2f87c607 bellard
    case 0x26: // sts
1009 2f87c607 bellard
    case 0x27: // stt
1010 2f87c607 bellard
    case 0x2c: // stl
1011 2f87c607 bellard
    case 0x2d: // stq
1012 2f87c607 bellard
    case 0x2e: // stl_c
1013 2f87c607 bellard
    case 0x2f: // stq_c
1014 2f87c607 bellard
        is_write = 1;
1015 2f87c607 bellard
    }
1016 2f87c607 bellard
1017 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1018 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
1019 2f87c607 bellard
}
1020 8c6939c0 bellard
#elif defined(__sparc__)
1021 8c6939c0 bellard
1022 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1023 e4533c7a bellard
                       void *puc)
1024 8c6939c0 bellard
{
1025 5a7b542b ths
    siginfo_t *info = pinfo;
1026 8c6939c0 bellard
    int is_write;
1027 8c6939c0 bellard
    uint32_t insn;
1028 dfe5fff3 Juan Quintela
#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
1029 c9e1e2b0 blueswir1
    uint32_t *regs = (uint32_t *)(info + 1);
1030 c9e1e2b0 blueswir1
    void *sigmask = (regs + 20);
1031 8c6939c0 bellard
    /* XXX: is there a standard glibc define ? */
1032 c9e1e2b0 blueswir1
    unsigned long pc = regs[1];
1033 c9e1e2b0 blueswir1
#else
1034 84778508 blueswir1
#ifdef __linux__
1035 c9e1e2b0 blueswir1
    struct sigcontext *sc = puc;
1036 c9e1e2b0 blueswir1
    unsigned long pc = sc->sigc_regs.tpc;
1037 c9e1e2b0 blueswir1
    void *sigmask = (void *)sc->sigc_mask;
1038 84778508 blueswir1
#elif defined(__OpenBSD__)
1039 84778508 blueswir1
    struct sigcontext *uc = puc;
1040 84778508 blueswir1
    unsigned long pc = uc->sc_pc;
1041 84778508 blueswir1
    void *sigmask = (void *)(long)uc->sc_mask;
1042 84778508 blueswir1
#endif
1043 c9e1e2b0 blueswir1
#endif
1044 c9e1e2b0 blueswir1
1045 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1046 8c6939c0 bellard
    is_write = 0;
1047 8c6939c0 bellard
    insn = *(uint32_t *)pc;
1048 8c6939c0 bellard
    if ((insn >> 30) == 3) {
1049 8c6939c0 bellard
      switch((insn >> 19) & 0x3f) {
1050 8c6939c0 bellard
      case 0x05: // stb
1051 d877fa5a Blue Swirl
      case 0x15: // stba
1052 8c6939c0 bellard
      case 0x06: // sth
1053 d877fa5a Blue Swirl
      case 0x16: // stha
1054 8c6939c0 bellard
      case 0x04: // st
1055 d877fa5a Blue Swirl
      case 0x14: // sta
1056 8c6939c0 bellard
      case 0x07: // std
1057 d877fa5a Blue Swirl
      case 0x17: // stda
1058 d877fa5a Blue Swirl
      case 0x0e: // stx
1059 d877fa5a Blue Swirl
      case 0x1e: // stxa
1060 8c6939c0 bellard
      case 0x24: // stf
1061 d877fa5a Blue Swirl
      case 0x34: // stfa
1062 8c6939c0 bellard
      case 0x27: // stdf
1063 d877fa5a Blue Swirl
      case 0x37: // stdfa
1064 d877fa5a Blue Swirl
      case 0x26: // stqf
1065 d877fa5a Blue Swirl
      case 0x36: // stqfa
1066 8c6939c0 bellard
      case 0x25: // stfsr
1067 d877fa5a Blue Swirl
      case 0x3c: // casa
1068 d877fa5a Blue Swirl
      case 0x3e: // casxa
1069 8c6939c0 bellard
        is_write = 1;
1070 8c6939c0 bellard
        break;
1071 8c6939c0 bellard
      }
1072 8c6939c0 bellard
    }
1073 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1074 bf3e8bf1 bellard
                             is_write, sigmask, NULL);
1075 8c6939c0 bellard
}
1076 8c6939c0 bellard
1077 8c6939c0 bellard
#elif defined(__arm__)
1078 8c6939c0 bellard
1079 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1080 e4533c7a bellard
                       void *puc)
1081 8c6939c0 bellard
{
1082 5a7b542b ths
    siginfo_t *info = pinfo;
1083 8c6939c0 bellard
    struct ucontext *uc = puc;
1084 8c6939c0 bellard
    unsigned long pc;
1085 8c6939c0 bellard
    int is_write;
1086 3b46e624 ths
1087 48bbf11b blueswir1
#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1088 5c49b363 balrog
    pc = uc->uc_mcontext.gregs[R15];
1089 5c49b363 balrog
#else
1090 4eee57f5 balrog
    pc = uc->uc_mcontext.arm_pc;
1091 5c49b363 balrog
#endif
1092 8c6939c0 bellard
    /* XXX: compute is_write */
1093 8c6939c0 bellard
    is_write = 0;
1094 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1095 8c6939c0 bellard
                             is_write,
1096 f3a9676a pbrook
                             &uc->uc_sigmask, puc);
1097 8c6939c0 bellard
}
1098 8c6939c0 bellard
1099 38e584a0 bellard
#elif defined(__mc68000)
1100 38e584a0 bellard
1101 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1102 38e584a0 bellard
                       void *puc)
1103 38e584a0 bellard
{
1104 5a7b542b ths
    siginfo_t *info = pinfo;
1105 38e584a0 bellard
    struct ucontext *uc = puc;
1106 38e584a0 bellard
    unsigned long pc;
1107 38e584a0 bellard
    int is_write;
1108 3b46e624 ths
1109 38e584a0 bellard
    pc = uc->uc_mcontext.gregs[16];
1110 38e584a0 bellard
    /* XXX: compute is_write */
1111 38e584a0 bellard
    is_write = 0;
1112 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1113 38e584a0 bellard
                             is_write,
1114 bf3e8bf1 bellard
                             &uc->uc_sigmask, puc);
1115 38e584a0 bellard
}
1116 38e584a0 bellard
1117 b8076a74 bellard
#elif defined(__ia64)
1118 b8076a74 bellard
1119 b8076a74 bellard
#ifndef __ISR_VALID
1120 b8076a74 bellard
  /* This ought to be in <bits/siginfo.h>... */
1121 b8076a74 bellard
# define __ISR_VALID        1
1122 b8076a74 bellard
#endif
1123 b8076a74 bellard
1124 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1125 b8076a74 bellard
{
1126 5a7b542b ths
    siginfo_t *info = pinfo;
1127 b8076a74 bellard
    struct ucontext *uc = puc;
1128 b8076a74 bellard
    unsigned long ip;
1129 b8076a74 bellard
    int is_write = 0;
1130 b8076a74 bellard
1131 b8076a74 bellard
    ip = uc->uc_mcontext.sc_ip;
1132 b8076a74 bellard
    switch (host_signum) {
1133 b8076a74 bellard
      case SIGILL:
1134 b8076a74 bellard
      case SIGFPE:
1135 b8076a74 bellard
      case SIGSEGV:
1136 b8076a74 bellard
      case SIGBUS:
1137 b8076a74 bellard
      case SIGTRAP:
1138 fd4a43e4 bellard
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1139 b8076a74 bellard
              /* ISR.W (write-access) is bit 33:  */
1140 b8076a74 bellard
              is_write = (info->si_isr >> 33) & 1;
1141 b8076a74 bellard
          break;
1142 b8076a74 bellard
1143 b8076a74 bellard
      default:
1144 b8076a74 bellard
          break;
1145 b8076a74 bellard
    }
1146 b8076a74 bellard
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1147 b8076a74 bellard
                             is_write,
1148 60e99246 Aurelien Jarno
                             (sigset_t *)&uc->uc_sigmask, puc);
1149 b8076a74 bellard
}
1150 b8076a74 bellard
1151 90cb9493 bellard
#elif defined(__s390__)
1152 90cb9493 bellard
1153 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1154 90cb9493 bellard
                       void *puc)
1155 90cb9493 bellard
{
1156 5a7b542b ths
    siginfo_t *info = pinfo;
1157 90cb9493 bellard
    struct ucontext *uc = puc;
1158 90cb9493 bellard
    unsigned long pc;
1159 6a1621b9 Richard Henderson
    uint16_t *pinsn;
1160 6a1621b9 Richard Henderson
    int is_write = 0;
1161 3b46e624 ths
1162 90cb9493 bellard
    pc = uc->uc_mcontext.psw.addr;
1163 6a1621b9 Richard Henderson
1164 6a1621b9 Richard Henderson
    /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
1165 6a1621b9 Richard Henderson
       of the normal 2 arguments.  The 3rd argument contains the "int_code"
1166 6a1621b9 Richard Henderson
       from the hardware which does in fact contain the is_write value.
1167 6a1621b9 Richard Henderson
       The rt signal handler, as far as I can tell, does not give this value
1168 6a1621b9 Richard Henderson
       at all.  Not that we could get to it from here even if it were.  */
1169 6a1621b9 Richard Henderson
    /* ??? This is not even close to complete, since it ignores all
1170 6a1621b9 Richard Henderson
       of the read-modify-write instructions.  */
1171 6a1621b9 Richard Henderson
    pinsn = (uint16_t *)pc;
1172 6a1621b9 Richard Henderson
    switch (pinsn[0] >> 8) {
1173 6a1621b9 Richard Henderson
    case 0x50: /* ST */
1174 6a1621b9 Richard Henderson
    case 0x42: /* STC */
1175 6a1621b9 Richard Henderson
    case 0x40: /* STH */
1176 6a1621b9 Richard Henderson
        is_write = 1;
1177 6a1621b9 Richard Henderson
        break;
1178 6a1621b9 Richard Henderson
    case 0xc4: /* RIL format insns */
1179 6a1621b9 Richard Henderson
        switch (pinsn[0] & 0xf) {
1180 6a1621b9 Richard Henderson
        case 0xf: /* STRL */
1181 6a1621b9 Richard Henderson
        case 0xb: /* STGRL */
1182 6a1621b9 Richard Henderson
        case 0x7: /* STHRL */
1183 6a1621b9 Richard Henderson
            is_write = 1;
1184 6a1621b9 Richard Henderson
        }
1185 6a1621b9 Richard Henderson
        break;
1186 6a1621b9 Richard Henderson
    case 0xe3: /* RXY format insns */
1187 6a1621b9 Richard Henderson
        switch (pinsn[2] & 0xff) {
1188 6a1621b9 Richard Henderson
        case 0x50: /* STY */
1189 6a1621b9 Richard Henderson
        case 0x24: /* STG */
1190 6a1621b9 Richard Henderson
        case 0x72: /* STCY */
1191 6a1621b9 Richard Henderson
        case 0x70: /* STHY */
1192 6a1621b9 Richard Henderson
        case 0x8e: /* STPQ */
1193 6a1621b9 Richard Henderson
        case 0x3f: /* STRVH */
1194 6a1621b9 Richard Henderson
        case 0x3e: /* STRV */
1195 6a1621b9 Richard Henderson
        case 0x2f: /* STRVG */
1196 6a1621b9 Richard Henderson
            is_write = 1;
1197 6a1621b9 Richard Henderson
        }
1198 6a1621b9 Richard Henderson
        break;
1199 6a1621b9 Richard Henderson
    }
1200 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1201 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1202 c4b89d18 ths
}
1203 c4b89d18 ths
1204 c4b89d18 ths
#elif defined(__mips__)
1205 c4b89d18 ths
1206 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1207 c4b89d18 ths
                       void *puc)
1208 c4b89d18 ths
{
1209 9617efe8 ths
    siginfo_t *info = pinfo;
1210 c4b89d18 ths
    struct ucontext *uc = puc;
1211 c4b89d18 ths
    greg_t pc = uc->uc_mcontext.pc;
1212 c4b89d18 ths
    int is_write;
1213 3b46e624 ths
1214 c4b89d18 ths
    /* XXX: compute is_write */
1215 c4b89d18 ths
    is_write = 0;
1216 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1217 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1218 90cb9493 bellard
}
1219 90cb9493 bellard
1220 f54b3f92 aurel32
#elif defined(__hppa__)
1221 f54b3f92 aurel32
1222 f54b3f92 aurel32
int cpu_signal_handler(int host_signum, void *pinfo,
1223 f54b3f92 aurel32
                       void *puc)
1224 f54b3f92 aurel32
{
1225 f54b3f92 aurel32
    struct siginfo *info = pinfo;
1226 f54b3f92 aurel32
    struct ucontext *uc = puc;
1227 f57040be Richard Henderson
    unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
1228 f57040be Richard Henderson
    uint32_t insn = *(uint32_t *)pc;
1229 f57040be Richard Henderson
    int is_write = 0;
1230 f57040be Richard Henderson
1231 f57040be Richard Henderson
    /* XXX: need kernel patch to get write flag faster.  */
1232 f57040be Richard Henderson
    switch (insn >> 26) {
1233 f57040be Richard Henderson
    case 0x1a: /* STW */
1234 f57040be Richard Henderson
    case 0x19: /* STH */
1235 f57040be Richard Henderson
    case 0x18: /* STB */
1236 f57040be Richard Henderson
    case 0x1b: /* STWM */
1237 f57040be Richard Henderson
        is_write = 1;
1238 f57040be Richard Henderson
        break;
1239 f57040be Richard Henderson
1240 f57040be Richard Henderson
    case 0x09: /* CSTWX, FSTWX, FSTWS */
1241 f57040be Richard Henderson
    case 0x0b: /* CSTDX, FSTDX, FSTDS */
1242 f57040be Richard Henderson
        /* Distinguish from coprocessor load ... */
1243 f57040be Richard Henderson
        is_write = (insn >> 9) & 1;
1244 f57040be Richard Henderson
        break;
1245 f57040be Richard Henderson
1246 f57040be Richard Henderson
    case 0x03:
1247 f57040be Richard Henderson
        switch ((insn >> 6) & 15) {
1248 f57040be Richard Henderson
        case 0xa: /* STWS */
1249 f57040be Richard Henderson
        case 0x9: /* STHS */
1250 f57040be Richard Henderson
        case 0x8: /* STBS */
1251 f57040be Richard Henderson
        case 0xe: /* STWAS */
1252 f57040be Richard Henderson
        case 0xc: /* STBYS */
1253 f57040be Richard Henderson
            is_write = 1;
1254 f57040be Richard Henderson
        }
1255 f57040be Richard Henderson
        break;
1256 f57040be Richard Henderson
    }
1257 f54b3f92 aurel32
1258 f54b3f92 aurel32
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1259 f57040be Richard Henderson
                             is_write, &uc->uc_sigmask, puc);
1260 f54b3f92 aurel32
}
1261 f54b3f92 aurel32
1262 9de5e440 bellard
#else
1263 2b413144 bellard
1264 3fb2ded1 bellard
#error host CPU specific signal handler needed
1265 2b413144 bellard
1266 9de5e440 bellard
#endif
1267 67b915a5 bellard
1268 67b915a5 bellard
#endif /* !defined(CONFIG_SOFTMMU) */