Statistics
| Branch: | Revision:

root / cpu-exec.c @ 0f11f25a

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