]> git.proxmox.com Git - qemu.git/blame - cpu-exec.c
Introduce and use cache-utils.[ch]
[qemu.git] / cpu-exec.c
CommitLineData
7d13299d
FB
1/*
2 * i386 emulator main execution loop
5fafdf24 3 *
66321a11 4 * Copyright (c) 2003-2005 Fabrice Bellard
7d13299d 5 *
3ef693a0
FB
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
7d13299d 10 *
3ef693a0
FB
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
7d13299d 15 *
3ef693a0
FB
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
7d13299d 19 */
e4533c7a 20#include "config.h"
7cb69cae 21#define CPU_NO_GLOBAL_REGS
93ac68bc 22#include "exec.h"
956034d7 23#include "disas.h"
7cb69cae 24#include "tcg.h"
7ba1e619 25#include "kvm.h"
7d13299d 26
fbf9eeb3
FB
27#if !defined(CONFIG_SOFTMMU)
28#undef EAX
29#undef ECX
30#undef EDX
31#undef EBX
32#undef ESP
33#undef EBP
34#undef ESI
35#undef EDI
36#undef EIP
37#include <signal.h>
84778508 38#ifdef __linux__
fbf9eeb3
FB
39#include <sys/ucontext.h>
40#endif
84778508 41#endif
fbf9eeb3 42
572a9d4a
BS
43#if defined(__sparc__) && !defined(HOST_SOLARIS)
44// Work around ugly bugs in glibc that mangle global register contents
45#undef env
46#define env cpu_single_env
47#endif
48
36bdbe54
FB
49int tb_invalidated_flag;
50
dc99065b 51//#define DEBUG_EXEC
9de5e440 52//#define DEBUG_SIGNAL
7d13299d 53
e4533c7a
FB
54void cpu_loop_exit(void)
55{
bfed01fc
TS
56 /* NOTE: the register at this point must be saved by hand because
57 longjmp restore them */
58 regs_to_env();
e4533c7a
FB
59 longjmp(env->jmp_env, 1);
60}
bfed01fc 61
fbf9eeb3
FB
62/* exit the current TB from a signal handler. The host registers are
63 restored in a state compatible with the CPU emulator
64 */
5fafdf24 65void cpu_resume_from_signal(CPUState *env1, void *puc)
fbf9eeb3
FB
66{
67#if !defined(CONFIG_SOFTMMU)
84778508 68#ifdef __linux__
fbf9eeb3 69 struct ucontext *uc = puc;
84778508
BS
70#elif defined(__OpenBSD__)
71 struct sigcontext *uc = puc;
72#endif
fbf9eeb3
FB
73#endif
74
75 env = env1;
76
77 /* XXX: restore cpu registers saved in host registers */
78
79#if !defined(CONFIG_SOFTMMU)
80 if (puc) {
81 /* XXX: use siglongjmp ? */
84778508 82#ifdef __linux__
fbf9eeb3 83 sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
84778508
BS
84#elif defined(__OpenBSD__)
85 sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
86#endif
fbf9eeb3
FB
87 }
88#endif
89 longjmp(env->jmp_env, 1);
90}
91
2e70f6ef
PB
92/* Execute the code without caching the generated code. An interpreter
93 could be used if available. */
94static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
95{
96 unsigned long next_tb;
97 TranslationBlock *tb;
98
99 /* Should never happen.
100 We only end up here when an existing TB is too long. */
101 if (max_cycles > CF_COUNT_MASK)
102 max_cycles = CF_COUNT_MASK;
103
104 tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
105 max_cycles);
106 env->current_tb = tb;
107 /* execute the generated code */
108 next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
109
110 if ((next_tb & 3) == 2) {
111 /* Restore PC. This may happen if async event occurs before
112 the TB starts executing. */
622ed360 113 cpu_pc_from_tb(env, tb);
2e70f6ef
PB
114 }
115 tb_phys_invalidate(tb, -1);
116 tb_free(tb);
117}
118
8a40a180
FB
119static TranslationBlock *tb_find_slow(target_ulong pc,
120 target_ulong cs_base,
c068688b 121 uint64_t flags)
8a40a180
FB
122{
123 TranslationBlock *tb, **ptb1;
8a40a180
FB
124 unsigned int h;
125 target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
3b46e624 126
8a40a180 127 tb_invalidated_flag = 0;
3b46e624 128
8a40a180 129 regs_to_env(); /* XXX: do it just before cpu_gen_code() */
3b46e624 130
8a40a180
FB
131 /* find translated block using physical mappings */
132 phys_pc = get_phys_addr_code(env, pc);
133 phys_page1 = phys_pc & TARGET_PAGE_MASK;
134 phys_page2 = -1;
135 h = tb_phys_hash_func(phys_pc);
136 ptb1 = &tb_phys_hash[h];
137 for(;;) {
138 tb = *ptb1;
139 if (!tb)
140 goto not_found;
5fafdf24 141 if (tb->pc == pc &&
8a40a180 142 tb->page_addr[0] == phys_page1 &&
5fafdf24 143 tb->cs_base == cs_base &&
8a40a180
FB
144 tb->flags == flags) {
145 /* check next page if needed */
146 if (tb->page_addr[1] != -1) {
5fafdf24 147 virt_page2 = (pc & TARGET_PAGE_MASK) +
8a40a180
FB
148 TARGET_PAGE_SIZE;
149 phys_page2 = get_phys_addr_code(env, virt_page2);
150 if (tb->page_addr[1] == phys_page2)
151 goto found;
152 } else {
153 goto found;
154 }
155 }
156 ptb1 = &tb->phys_hash_next;
157 }
158 not_found:
2e70f6ef
PB
159 /* if no translated code available, then translate it now */
160 tb = tb_gen_code(env, pc, cs_base, flags, 0);
3b46e624 161
8a40a180 162 found:
8a40a180
FB
163 /* we add the TB in the virtual pc hash table */
164 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
8a40a180
FB
165 return tb;
166}
167
168static inline TranslationBlock *tb_find_fast(void)
169{
170 TranslationBlock *tb;
171 target_ulong cs_base, pc;
6b917547 172 int flags;
8a40a180
FB
173
174 /* we record a subset of the CPU state. It will
175 always be the same before a given translated block
176 is executed. */
6b917547 177 cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
bce61846 178 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
551bd27f
TS
179 if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
180 tb->flags != flags)) {
8a40a180
FB
181 tb = tb_find_slow(pc, cs_base, flags);
182 }
183 return tb;
184}
185
dde2367e
AL
186static CPUDebugExcpHandler *debug_excp_handler;
187
188CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
189{
190 CPUDebugExcpHandler *old_handler = debug_excp_handler;
191
192 debug_excp_handler = handler;
193 return old_handler;
194}
195
6e140f28
AL
196static void cpu_handle_debug_exception(CPUState *env)
197{
198 CPUWatchpoint *wp;
199
200 if (!env->watchpoint_hit)
c0ce998e 201 TAILQ_FOREACH(wp, &env->watchpoints, entry)
6e140f28 202 wp->flags &= ~BP_WATCHPOINT_HIT;
dde2367e
AL
203
204 if (debug_excp_handler)
205 debug_excp_handler(env);
6e140f28
AL
206}
207
7d13299d
FB
208/* main execution loop */
209
e4533c7a 210int cpu_exec(CPUState *env1)
7d13299d 211{
1057eaa7
PB
212#define DECLARE_HOST_REGS 1
213#include "hostregs_helper.h"
8a40a180 214 int ret, interrupt_request;
8a40a180 215 TranslationBlock *tb;
c27004ec 216 uint8_t *tc_ptr;
d5975363 217 unsigned long next_tb;
8c6939c0 218
bfed01fc
TS
219 if (cpu_halted(env1) == EXCP_HALTED)
220 return EXCP_HALTED;
5a1e3cfc 221
5fafdf24 222 cpu_single_env = env1;
6a00d601 223
7d13299d 224 /* first we save global registers */
1057eaa7
PB
225#define SAVE_HOST_REGS 1
226#include "hostregs_helper.h"
c27004ec 227 env = env1;
e4533c7a 228
0d1a29f9 229 env_to_regs();
ecb644f4 230#if defined(TARGET_I386)
9de5e440 231 /* put eflags in CPU temporary format */
fc2b4c48
FB
232 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
233 DF = 1 - (2 * ((env->eflags >> 10) & 1));
9de5e440 234 CC_OP = CC_OP_EFLAGS;
fc2b4c48 235 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
93ac68bc 236#elif defined(TARGET_SPARC)
e6e5906b
PB
237#elif defined(TARGET_M68K)
238 env->cc_op = CC_OP_FLAGS;
239 env->cc_dest = env->sr & 0xf;
240 env->cc_x = (env->sr >> 4) & 1;
ecb644f4
TS
241#elif defined(TARGET_ALPHA)
242#elif defined(TARGET_ARM)
243#elif defined(TARGET_PPC)
6af0bf9c 244#elif defined(TARGET_MIPS)
fdf9b3e8 245#elif defined(TARGET_SH4)
f1ccf904 246#elif defined(TARGET_CRIS)
fdf9b3e8 247 /* XXXXX */
e4533c7a
FB
248#else
249#error unsupported target CPU
250#endif
3fb2ded1 251 env->exception_index = -1;
9d27abd9 252
7d13299d 253 /* prepare setjmp context for exception handling */
3fb2ded1
FB
254 for(;;) {
255 if (setjmp(env->jmp_env) == 0) {
ee8b7021 256 env->current_tb = NULL;
3fb2ded1
FB
257 /* if an exception is pending, we execute it here */
258 if (env->exception_index >= 0) {
259 if (env->exception_index >= EXCP_INTERRUPT) {
260 /* exit request from the cpu execution loop */
261 ret = env->exception_index;
6e140f28
AL
262 if (ret == EXCP_DEBUG)
263 cpu_handle_debug_exception(env);
3fb2ded1
FB
264 break;
265 } else if (env->user_mode_only) {
266 /* if user mode only, we simulate a fake exception
9f083493 267 which will be handled outside the cpu execution
3fb2ded1 268 loop */
83479e77 269#if defined(TARGET_I386)
5fafdf24
TS
270 do_interrupt_user(env->exception_index,
271 env->exception_is_int,
272 env->error_code,
3fb2ded1 273 env->exception_next_eip);
eba01623
FB
274 /* successfully delivered */
275 env->old_exception = -1;
83479e77 276#endif
3fb2ded1
FB
277 ret = env->exception_index;
278 break;
279 } else {
83479e77 280#if defined(TARGET_I386)
3fb2ded1
FB
281 /* simulate a real cpu exception. On i386, it can
282 trigger new exceptions, but we do not handle
283 double or triple faults yet. */
5fafdf24
TS
284 do_interrupt(env->exception_index,
285 env->exception_is_int,
286 env->error_code,
d05e66d2 287 env->exception_next_eip, 0);
678dde13
TS
288 /* successfully delivered */
289 env->old_exception = -1;
ce09776b
FB
290#elif defined(TARGET_PPC)
291 do_interrupt(env);
6af0bf9c
FB
292#elif defined(TARGET_MIPS)
293 do_interrupt(env);
e95c8d51 294#elif defined(TARGET_SPARC)
f2bc7e7f 295 do_interrupt(env);
b5ff1b31
FB
296#elif defined(TARGET_ARM)
297 do_interrupt(env);
fdf9b3e8
FB
298#elif defined(TARGET_SH4)
299 do_interrupt(env);
eddf68a6
JM
300#elif defined(TARGET_ALPHA)
301 do_interrupt(env);
f1ccf904
TS
302#elif defined(TARGET_CRIS)
303 do_interrupt(env);
0633879f
PB
304#elif defined(TARGET_M68K)
305 do_interrupt(0);
83479e77 306#endif
3fb2ded1
FB
307 }
308 env->exception_index = -1;
5fafdf24 309 }
9df217a3
FB
310#ifdef USE_KQEMU
311 if (kqemu_is_ok(env) && env->interrupt_request == 0) {
312 int ret;
a7812ae4 313 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
9df217a3
FB
314 ret = kqemu_cpu_exec(env);
315 /* put eflags in CPU temporary format */
316 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
317 DF = 1 - (2 * ((env->eflags >> 10) & 1));
318 CC_OP = CC_OP_EFLAGS;
319 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
320 if (ret == 1) {
321 /* exception */
322 longjmp(env->jmp_env, 1);
323 } else if (ret == 2) {
324 /* softmmu execution needed */
325 } else {
326 if (env->interrupt_request != 0) {
327 /* hardware interrupt will be executed just after */
328 } else {
329 /* otherwise, we restart */
330 longjmp(env->jmp_env, 1);
331 }
332 }
3fb2ded1 333 }
9df217a3
FB
334#endif
335
7ba1e619 336 if (kvm_enabled()) {
becfc390
AL
337 kvm_cpu_exec(env);
338 longjmp(env->jmp_env, 1);
7ba1e619
AL
339 }
340
b5fc09ae 341 next_tb = 0; /* force lookup of first TB */
3fb2ded1 342 for(;;) {
68a79315 343 interrupt_request = env->interrupt_request;
e1638bd8 344 if (unlikely(interrupt_request)) {
345 if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
346 /* Mask out external interrupts for this step. */
347 interrupt_request &= ~(CPU_INTERRUPT_HARD |
348 CPU_INTERRUPT_FIQ |
349 CPU_INTERRUPT_SMI |
350 CPU_INTERRUPT_NMI);
351 }
6658ffb8
PB
352 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
353 env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
354 env->exception_index = EXCP_DEBUG;
355 cpu_loop_exit();
356 }
a90b7318 357#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
f1ccf904 358 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
a90b7318
AZ
359 if (interrupt_request & CPU_INTERRUPT_HALT) {
360 env->interrupt_request &= ~CPU_INTERRUPT_HALT;
361 env->halted = 1;
362 env->exception_index = EXCP_HLT;
363 cpu_loop_exit();
364 }
365#endif
68a79315 366#if defined(TARGET_I386)
db620f46
FB
367 if (env->hflags2 & HF2_GIF_MASK) {
368 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
369 !(env->hflags & HF_SMM_MASK)) {
370 svm_check_intercept(SVM_EXIT_SMI);
371 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
372 do_smm_enter();
373 next_tb = 0;
374 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
375 !(env->hflags2 & HF2_NMI_MASK)) {
376 env->interrupt_request &= ~CPU_INTERRUPT_NMI;
377 env->hflags2 |= HF2_NMI_MASK;
378 do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
379 next_tb = 0;
380 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
381 (((env->hflags2 & HF2_VINTR_MASK) &&
382 (env->hflags2 & HF2_HIF_MASK)) ||
383 (!(env->hflags2 & HF2_VINTR_MASK) &&
384 (env->eflags & IF_MASK &&
385 !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
386 int intno;
387 svm_check_intercept(SVM_EXIT_INTR);
388 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
389 intno = cpu_get_pic_interrupt(env);
390 if (loglevel & CPU_LOG_TB_IN_ASM) {
391 fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
392 }
393 do_interrupt(intno, 0, 0, 0, 1);
394 /* ensure that no TB jump will be modified as
395 the program flow was changed */
396 next_tb = 0;
0573fbfc 397#if !defined(CONFIG_USER_ONLY)
db620f46
FB
398 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
399 (env->eflags & IF_MASK) &&
400 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
401 int intno;
402 /* FIXME: this should respect TPR */
403 svm_check_intercept(SVM_EXIT_VINTR);
404 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
405 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
406 if (loglevel & CPU_LOG_TB_IN_ASM)
407 fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
408 do_interrupt(intno, 0, 0, 0, 1);
409 next_tb = 0;
907a5b26 410#endif
db620f46 411 }
68a79315 412 }
ce09776b 413#elif defined(TARGET_PPC)
9fddaa0c
FB
414#if 0
415 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
416 cpu_ppc_reset(env);
417 }
418#endif
47103572 419 if (interrupt_request & CPU_INTERRUPT_HARD) {
e9df014c
JM
420 ppc_hw_interrupt(env);
421 if (env->pending_interrupts == 0)
422 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
b5fc09ae 423 next_tb = 0;
ce09776b 424 }
6af0bf9c
FB
425#elif defined(TARGET_MIPS)
426 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
24c7b0e3 427 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
6af0bf9c 428 (env->CP0_Status & (1 << CP0St_IE)) &&
24c7b0e3
TS
429 !(env->CP0_Status & (1 << CP0St_EXL)) &&
430 !(env->CP0_Status & (1 << CP0St_ERL)) &&
6af0bf9c
FB
431 !(env->hflags & MIPS_HFLAG_DM)) {
432 /* Raise it */
433 env->exception_index = EXCP_EXT_INTERRUPT;
434 env->error_code = 0;
435 do_interrupt(env);
b5fc09ae 436 next_tb = 0;
6af0bf9c 437 }
e95c8d51 438#elif defined(TARGET_SPARC)
66321a11
FB
439 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
440 (env->psret != 0)) {
441 int pil = env->interrupt_index & 15;
442 int type = env->interrupt_index & 0xf0;
443
444 if (((type == TT_EXTINT) &&
445 (pil == 15 || pil > env->psrpil)) ||
446 type != TT_EXTINT) {
447 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
f2bc7e7f
BS
448 env->exception_index = env->interrupt_index;
449 do_interrupt(env);
66321a11 450 env->interrupt_index = 0;
327ac2e7
BS
451#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
452 cpu_check_irqs(env);
453#endif
b5fc09ae 454 next_tb = 0;
66321a11 455 }
e95c8d51
FB
456 } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
457 //do_interrupt(0, 0, 0, 0, 0);
458 env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
a90b7318 459 }
b5ff1b31
FB
460#elif defined(TARGET_ARM)
461 if (interrupt_request & CPU_INTERRUPT_FIQ
462 && !(env->uncached_cpsr & CPSR_F)) {
463 env->exception_index = EXCP_FIQ;
464 do_interrupt(env);
b5fc09ae 465 next_tb = 0;
b5ff1b31 466 }
9ee6e8bb
PB
467 /* ARMv7-M interrupt return works by loading a magic value
468 into the PC. On real hardware the load causes the
469 return to occur. The qemu implementation performs the
470 jump normally, then does the exception return when the
471 CPU tries to execute code at the magic address.
472 This will cause the magic PC value to be pushed to
473 the stack if an interrupt occured at the wrong time.
474 We avoid this by disabling interrupts when
475 pc contains a magic address. */
b5ff1b31 476 if (interrupt_request & CPU_INTERRUPT_HARD
9ee6e8bb
PB
477 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
478 || !(env->uncached_cpsr & CPSR_I))) {
b5ff1b31
FB
479 env->exception_index = EXCP_IRQ;
480 do_interrupt(env);
b5fc09ae 481 next_tb = 0;
b5ff1b31 482 }
fdf9b3e8 483#elif defined(TARGET_SH4)
e96e2044
TS
484 if (interrupt_request & CPU_INTERRUPT_HARD) {
485 do_interrupt(env);
b5fc09ae 486 next_tb = 0;
e96e2044 487 }
eddf68a6
JM
488#elif defined(TARGET_ALPHA)
489 if (interrupt_request & CPU_INTERRUPT_HARD) {
490 do_interrupt(env);
b5fc09ae 491 next_tb = 0;
eddf68a6 492 }
f1ccf904 493#elif defined(TARGET_CRIS)
1b1a38b0
EI
494 if (interrupt_request & CPU_INTERRUPT_HARD
495 && (env->pregs[PR_CCS] & I_FLAG)) {
496 env->exception_index = EXCP_IRQ;
497 do_interrupt(env);
498 next_tb = 0;
499 }
500 if (interrupt_request & CPU_INTERRUPT_NMI
501 && (env->pregs[PR_CCS] & M_FLAG)) {
502 env->exception_index = EXCP_NMI;
f1ccf904 503 do_interrupt(env);
b5fc09ae 504 next_tb = 0;
f1ccf904 505 }
0633879f
PB
506#elif defined(TARGET_M68K)
507 if (interrupt_request & CPU_INTERRUPT_HARD
508 && ((env->sr & SR_I) >> SR_I_SHIFT)
509 < env->pending_level) {
510 /* Real hardware gets the interrupt vector via an
511 IACK cycle at this point. Current emulated
512 hardware doesn't rely on this, so we
513 provide/save the vector when the interrupt is
514 first signalled. */
515 env->exception_index = env->pending_vector;
516 do_interrupt(1);
b5fc09ae 517 next_tb = 0;
0633879f 518 }
68a79315 519#endif
9d05095e
FB
520 /* Don't use the cached interupt_request value,
521 do_interrupt may have updated the EXITTB flag. */
b5ff1b31 522 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
bf3e8bf1
FB
523 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
524 /* ensure that no TB jump will be modified as
525 the program flow was changed */
b5fc09ae 526 next_tb = 0;
bf3e8bf1 527 }
68a79315
FB
528 if (interrupt_request & CPU_INTERRUPT_EXIT) {
529 env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
530 env->exception_index = EXCP_INTERRUPT;
531 cpu_loop_exit();
532 }
3fb2ded1 533 }
7d13299d 534#ifdef DEBUG_EXEC
b5ff1b31 535 if ((loglevel & CPU_LOG_TB_CPU)) {
3fb2ded1 536 /* restore flags in standard format */
ecb644f4
TS
537 regs_to_env();
538#if defined(TARGET_I386)
a7812ae4 539 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
7fe48483 540 cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
3fb2ded1 541 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
e4533c7a 542#elif defined(TARGET_ARM)
7fe48483 543 cpu_dump_state(env, logfile, fprintf, 0);
93ac68bc 544#elif defined(TARGET_SPARC)
3475187d 545 cpu_dump_state(env, logfile, fprintf, 0);
67867308 546#elif defined(TARGET_PPC)
7fe48483 547 cpu_dump_state(env, logfile, fprintf, 0);
e6e5906b
PB
548#elif defined(TARGET_M68K)
549 cpu_m68k_flush_flags(env, env->cc_op);
550 env->cc_op = CC_OP_FLAGS;
551 env->sr = (env->sr & 0xffe0)
552 | env->cc_dest | (env->cc_x << 4);
553 cpu_dump_state(env, logfile, fprintf, 0);
6af0bf9c
FB
554#elif defined(TARGET_MIPS)
555 cpu_dump_state(env, logfile, fprintf, 0);
fdf9b3e8
FB
556#elif defined(TARGET_SH4)
557 cpu_dump_state(env, logfile, fprintf, 0);
eddf68a6
JM
558#elif defined(TARGET_ALPHA)
559 cpu_dump_state(env, logfile, fprintf, 0);
f1ccf904
TS
560#elif defined(TARGET_CRIS)
561 cpu_dump_state(env, logfile, fprintf, 0);
e4533c7a 562#else
5fafdf24 563#error unsupported target CPU
e4533c7a 564#endif
3fb2ded1 565 }
7d13299d 566#endif
d5975363 567 spin_lock(&tb_lock);
8a40a180 568 tb = tb_find_fast();
d5975363
PB
569 /* Note: we do it here to avoid a gcc bug on Mac OS X when
570 doing it in tb_find_slow */
571 if (tb_invalidated_flag) {
572 /* as some TB could have been invalidated because
573 of memory exceptions while generating the code, we
574 must recompute the hash index here */
575 next_tb = 0;
2e70f6ef 576 tb_invalidated_flag = 0;
d5975363 577 }
9d27abd9 578#ifdef DEBUG_EXEC
c1135f61 579 if ((loglevel & CPU_LOG_EXEC)) {
c27004ec
FB
580 fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
581 (long)tb->tc_ptr, tb->pc,
582 lookup_symbol(tb->pc));
3fb2ded1 583 }
9d27abd9 584#endif
8a40a180
FB
585 /* see if we can patch the calling TB. When the TB
586 spans two pages, we cannot safely do a direct
587 jump. */
c27004ec 588 {
b5fc09ae 589 if (next_tb != 0 &&
4d7a0880 590#ifdef USE_KQEMU
f32fc648
FB
591 (env->kqemu_enabled != 2) &&
592#endif
ec6338ba 593 tb->page_addr[1] == -1) {
b5fc09ae 594 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
3fb2ded1 595 }
c27004ec 596 }
d5975363 597 spin_unlock(&tb_lock);
83479e77 598 env->current_tb = tb;
55e8b85e 599
600 /* cpu_interrupt might be called while translating the
601 TB, but before it is linked into a potentially
602 infinite loop and becomes env->current_tb. Avoid
603 starting execution if there is a pending interrupt. */
604 if (unlikely (env->interrupt_request & CPU_INTERRUPT_EXIT))
605 env->current_tb = NULL;
606
2e70f6ef
PB
607 while (env->current_tb) {
608 tc_ptr = tb->tc_ptr;
3fb2ded1 609 /* execute the generated code */
572a9d4a
BS
610#if defined(__sparc__) && !defined(HOST_SOLARIS)
611#undef env
2e70f6ef 612 env = cpu_single_env;
572a9d4a
BS
613#define env cpu_single_env
614#endif
2e70f6ef
PB
615 next_tb = tcg_qemu_tb_exec(tc_ptr);
616 env->current_tb = NULL;
617 if ((next_tb & 3) == 2) {
bf20dc07 618 /* Instruction counter expired. */
2e70f6ef
PB
619 int insns_left;
620 tb = (TranslationBlock *)(long)(next_tb & ~3);
621 /* Restore PC. */
622ed360 622 cpu_pc_from_tb(env, tb);
2e70f6ef
PB
623 insns_left = env->icount_decr.u32;
624 if (env->icount_extra && insns_left >= 0) {
625 /* Refill decrementer and continue execution. */
626 env->icount_extra += insns_left;
627 if (env->icount_extra > 0xffff) {
628 insns_left = 0xffff;
629 } else {
630 insns_left = env->icount_extra;
631 }
632 env->icount_extra -= insns_left;
633 env->icount_decr.u16.low = insns_left;
634 } else {
635 if (insns_left > 0) {
636 /* Execute remaining instructions. */
637 cpu_exec_nocache(insns_left, tb);
638 }
639 env->exception_index = EXCP_INTERRUPT;
640 next_tb = 0;
641 cpu_loop_exit();
642 }
643 }
644 }
4cbf74b6
FB
645 /* reset soft MMU for next block (it can currently
646 only be set by a memory fault) */
f32fc648
FB
647#if defined(USE_KQEMU)
648#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
649 if (kqemu_is_ok(env) &&
650 (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
651 cpu_loop_exit();
652 }
4cbf74b6 653#endif
50a518e3 654 } /* for(;;) */
3fb2ded1 655 } else {
0d1a29f9 656 env_to_regs();
7d13299d 657 }
3fb2ded1
FB
658 } /* for(;;) */
659
7d13299d 660
e4533c7a 661#if defined(TARGET_I386)
9de5e440 662 /* restore flags in standard format */
a7812ae4 663 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
e4533c7a 664#elif defined(TARGET_ARM)
b7bcbe95 665 /* XXX: Save/restore host fpu exception state?. */
93ac68bc 666#elif defined(TARGET_SPARC)
67867308 667#elif defined(TARGET_PPC)
e6e5906b
PB
668#elif defined(TARGET_M68K)
669 cpu_m68k_flush_flags(env, env->cc_op);
670 env->cc_op = CC_OP_FLAGS;
671 env->sr = (env->sr & 0xffe0)
672 | env->cc_dest | (env->cc_x << 4);
6af0bf9c 673#elif defined(TARGET_MIPS)
fdf9b3e8 674#elif defined(TARGET_SH4)
eddf68a6 675#elif defined(TARGET_ALPHA)
f1ccf904 676#elif defined(TARGET_CRIS)
fdf9b3e8 677 /* XXXXX */
e4533c7a
FB
678#else
679#error unsupported target CPU
680#endif
1057eaa7
PB
681
682 /* restore global registers */
1057eaa7
PB
683#include "hostregs_helper.h"
684
6a00d601 685 /* fail safe : never use cpu_single_env outside cpu_exec() */
5fafdf24 686 cpu_single_env = NULL;
7d13299d
FB
687 return ret;
688}
6dbad63e 689
fbf9eeb3
FB
690/* must only be called from the generated code as an exception can be
691 generated */
692void tb_invalidate_page_range(target_ulong start, target_ulong end)
693{
dc5d0b3d
FB
694 /* XXX: cannot enable it yet because it yields to MMU exception
695 where NIP != read address on PowerPC */
696#if 0
fbf9eeb3
FB
697 target_ulong phys_addr;
698 phys_addr = get_phys_addr_code(env, start);
699 tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
dc5d0b3d 700#endif
fbf9eeb3
FB
701}
702
1a18c71b 703#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
e4533c7a 704
6dbad63e
FB
705void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
706{
707 CPUX86State *saved_env;
708
709 saved_env = env;
710 env = s;
a412ac57 711 if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
a513fe19 712 selector &= 0xffff;
5fafdf24 713 cpu_x86_load_seg_cache(env, seg_reg, selector,
c27004ec 714 (selector << 4), 0xffff, 0);
a513fe19 715 } else {
5d97559d 716 helper_load_seg(seg_reg, selector);
a513fe19 717 }
6dbad63e
FB
718 env = saved_env;
719}
9de5e440 720
6f12a2a6 721void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
d0a1ffc9
FB
722{
723 CPUX86State *saved_env;
724
725 saved_env = env;
726 env = s;
3b46e624 727
6f12a2a6 728 helper_fsave(ptr, data32);
d0a1ffc9
FB
729
730 env = saved_env;
731}
732
6f12a2a6 733void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
d0a1ffc9
FB
734{
735 CPUX86State *saved_env;
736
737 saved_env = env;
738 env = s;
3b46e624 739
6f12a2a6 740 helper_frstor(ptr, data32);
d0a1ffc9
FB
741
742 env = saved_env;
743}
744
e4533c7a
FB
745#endif /* TARGET_I386 */
746
67b915a5
FB
747#if !defined(CONFIG_SOFTMMU)
748
3fb2ded1
FB
749#if defined(TARGET_I386)
750
b56dad1c 751/* 'pc' is the host PC at which the exception was raised. 'address' is
fd6ce8f6
FB
752 the effective address of the memory exception. 'is_write' is 1 if a
753 write caused the exception and otherwise 0'. 'old_set' is the
754 signal set which should be restored */
2b413144 755static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
5fafdf24 756 int is_write, sigset_t *old_set,
bf3e8bf1 757 void *puc)
9de5e440 758{
a513fe19
FB
759 TranslationBlock *tb;
760 int ret;
68a79315 761
83479e77
FB
762 if (cpu_single_env)
763 env = cpu_single_env; /* XXX: find a correct solution for multithread */
fd6ce8f6 764#if defined(DEBUG_SIGNAL)
5fafdf24 765 qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bf3e8bf1 766 pc, address, is_write, *(unsigned long *)old_set);
9de5e440 767#endif
25eb4484 768 /* XXX: locking issue */
53a5960a 769 if (is_write && page_unprotect(h2g(address), pc, puc)) {
fd6ce8f6
FB
770 return 1;
771 }
fbf9eeb3 772
3fb2ded1 773 /* see if it is an MMU fault */
6ebbf390 774 ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
3fb2ded1
FB
775 if (ret < 0)
776 return 0; /* not an MMU fault */
777 if (ret == 0)
778 return 1; /* the MMU fault was handled without causing real CPU fault */
779 /* now we have a real cpu fault */
a513fe19
FB
780 tb = tb_find_pc(pc);
781 if (tb) {
9de5e440
FB
782 /* the PC is inside the translated code. It means that we have
783 a virtual CPU fault */
bf3e8bf1 784 cpu_restore_state(tb, env, pc, puc);
3fb2ded1 785 }
4cbf74b6 786 if (ret == 1) {
3fb2ded1 787#if 0
5fafdf24 788 printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
4cbf74b6 789 env->eip, env->cr[2], env->error_code);
3fb2ded1 790#endif
4cbf74b6
FB
791 /* we restore the process signal mask as the sigreturn should
792 do it (XXX: use sigsetjmp) */
793 sigprocmask(SIG_SETMASK, old_set, NULL);
54ca9095 794 raise_exception_err(env->exception_index, env->error_code);
4cbf74b6
FB
795 } else {
796 /* activate soft MMU for this block */
3f337316 797 env->hflags |= HF_SOFTMMU_MASK;
fbf9eeb3 798 cpu_resume_from_signal(env, puc);
4cbf74b6 799 }
3fb2ded1
FB
800 /* never comes here */
801 return 1;
802}
803
e4533c7a 804#elif defined(TARGET_ARM)
3fb2ded1 805static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bf3e8bf1
FB
806 int is_write, sigset_t *old_set,
807 void *puc)
3fb2ded1 808{
68016c62
FB
809 TranslationBlock *tb;
810 int ret;
811
812 if (cpu_single_env)
813 env = cpu_single_env; /* XXX: find a correct solution for multithread */
814#if defined(DEBUG_SIGNAL)
5fafdf24 815 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
68016c62
FB
816 pc, address, is_write, *(unsigned long *)old_set);
817#endif
9f0777ed 818 /* XXX: locking issue */
53a5960a 819 if (is_write && page_unprotect(h2g(address), pc, puc)) {
9f0777ed
FB
820 return 1;
821 }
68016c62 822 /* see if it is an MMU fault */
6ebbf390 823 ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
68016c62
FB
824 if (ret < 0)
825 return 0; /* not an MMU fault */
826 if (ret == 0)
827 return 1; /* the MMU fault was handled without causing real CPU fault */
828 /* now we have a real cpu fault */
829 tb = tb_find_pc(pc);
830 if (tb) {
831 /* the PC is inside the translated code. It means that we have
832 a virtual CPU fault */
833 cpu_restore_state(tb, env, pc, puc);
834 }
835 /* we restore the process signal mask as the sigreturn should
836 do it (XXX: use sigsetjmp) */
837 sigprocmask(SIG_SETMASK, old_set, NULL);
838 cpu_loop_exit();
968c74da
AJ
839 /* never comes here */
840 return 1;
3fb2ded1 841}
93ac68bc
FB
842#elif defined(TARGET_SPARC)
843static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bf3e8bf1
FB
844 int is_write, sigset_t *old_set,
845 void *puc)
93ac68bc 846{
68016c62
FB
847 TranslationBlock *tb;
848 int ret;
849
850 if (cpu_single_env)
851 env = cpu_single_env; /* XXX: find a correct solution for multithread */
852#if defined(DEBUG_SIGNAL)
5fafdf24 853 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
68016c62
FB
854 pc, address, is_write, *(unsigned long *)old_set);
855#endif
b453b70b 856 /* XXX: locking issue */
53a5960a 857 if (is_write && page_unprotect(h2g(address), pc, puc)) {
b453b70b
FB
858 return 1;
859 }
68016c62 860 /* see if it is an MMU fault */
6ebbf390 861 ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
68016c62
FB
862 if (ret < 0)
863 return 0; /* not an MMU fault */
864 if (ret == 0)
865 return 1; /* the MMU fault was handled without causing real CPU fault */
866 /* now we have a real cpu fault */
867 tb = tb_find_pc(pc);
868 if (tb) {
869 /* the PC is inside the translated code. It means that we have
870 a virtual CPU fault */
871 cpu_restore_state(tb, env, pc, puc);
872 }
873 /* we restore the process signal mask as the sigreturn should
874 do it (XXX: use sigsetjmp) */
875 sigprocmask(SIG_SETMASK, old_set, NULL);
876 cpu_loop_exit();
968c74da
AJ
877 /* never comes here */
878 return 1;
93ac68bc 879}
67867308
FB
880#elif defined (TARGET_PPC)
881static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bf3e8bf1
FB
882 int is_write, sigset_t *old_set,
883 void *puc)
67867308
FB
884{
885 TranslationBlock *tb;
ce09776b 886 int ret;
3b46e624 887
67867308
FB
888 if (cpu_single_env)
889 env = cpu_single_env; /* XXX: find a correct solution for multithread */
67867308 890#if defined(DEBUG_SIGNAL)
5fafdf24 891 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
67867308
FB
892 pc, address, is_write, *(unsigned long *)old_set);
893#endif
894 /* XXX: locking issue */
53a5960a 895 if (is_write && page_unprotect(h2g(address), pc, puc)) {
67867308
FB
896 return 1;
897 }
898
ce09776b 899 /* see if it is an MMU fault */
6ebbf390 900 ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
ce09776b
FB
901 if (ret < 0)
902 return 0; /* not an MMU fault */
903 if (ret == 0)
904 return 1; /* the MMU fault was handled without causing real CPU fault */
905
67867308
FB
906 /* now we have a real cpu fault */
907 tb = tb_find_pc(pc);
908 if (tb) {
909 /* the PC is inside the translated code. It means that we have
910 a virtual CPU fault */
bf3e8bf1 911 cpu_restore_state(tb, env, pc, puc);
67867308 912 }
ce09776b 913 if (ret == 1) {
67867308 914#if 0
5fafdf24 915 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
ce09776b 916 env->nip, env->error_code, tb);
67867308
FB
917#endif
918 /* we restore the process signal mask as the sigreturn should
919 do it (XXX: use sigsetjmp) */
bf3e8bf1 920 sigprocmask(SIG_SETMASK, old_set, NULL);
64adab3f 921 raise_exception_err(env, env->exception_index, env->error_code);
ce09776b
FB
922 } else {
923 /* activate soft MMU for this block */
fbf9eeb3 924 cpu_resume_from_signal(env, puc);
ce09776b 925 }
67867308 926 /* never comes here */
e6e5906b
PB
927 return 1;
928}
929
930#elif defined(TARGET_M68K)
931static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
932 int is_write, sigset_t *old_set,
933 void *puc)
934{
935 TranslationBlock *tb;
936 int ret;
937
938 if (cpu_single_env)
939 env = cpu_single_env; /* XXX: find a correct solution for multithread */
940#if defined(DEBUG_SIGNAL)
5fafdf24 941 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
e6e5906b
PB
942 pc, address, is_write, *(unsigned long *)old_set);
943#endif
944 /* XXX: locking issue */
945 if (is_write && page_unprotect(address, pc, puc)) {
946 return 1;
947 }
948 /* see if it is an MMU fault */
6ebbf390 949 ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
e6e5906b
PB
950 if (ret < 0)
951 return 0; /* not an MMU fault */
952 if (ret == 0)
953 return 1; /* the MMU fault was handled without causing real CPU fault */
954 /* now we have a real cpu fault */
955 tb = tb_find_pc(pc);
956 if (tb) {
957 /* the PC is inside the translated code. It means that we have
958 a virtual CPU fault */
959 cpu_restore_state(tb, env, pc, puc);
960 }
961 /* we restore the process signal mask as the sigreturn should
962 do it (XXX: use sigsetjmp) */
963 sigprocmask(SIG_SETMASK, old_set, NULL);
964 cpu_loop_exit();
965 /* never comes here */
67867308
FB
966 return 1;
967}
6af0bf9c
FB
968
969#elif defined (TARGET_MIPS)
970static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
971 int is_write, sigset_t *old_set,
972 void *puc)
973{
974 TranslationBlock *tb;
975 int ret;
3b46e624 976
6af0bf9c
FB
977 if (cpu_single_env)
978 env = cpu_single_env; /* XXX: find a correct solution for multithread */
979#if defined(DEBUG_SIGNAL)
5fafdf24 980 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
6af0bf9c
FB
981 pc, address, is_write, *(unsigned long *)old_set);
982#endif
983 /* XXX: locking issue */
53a5960a 984 if (is_write && page_unprotect(h2g(address), pc, puc)) {
6af0bf9c
FB
985 return 1;
986 }
987
988 /* see if it is an MMU fault */
6ebbf390 989 ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
6af0bf9c
FB
990 if (ret < 0)
991 return 0; /* not an MMU fault */
992 if (ret == 0)
993 return 1; /* the MMU fault was handled without causing real CPU fault */
994
995 /* now we have a real cpu fault */
996 tb = tb_find_pc(pc);
997 if (tb) {
998 /* the PC is inside the translated code. It means that we have
999 a virtual CPU fault */
1000 cpu_restore_state(tb, env, pc, puc);
1001 }
1002 if (ret == 1) {
1003#if 0
5fafdf24 1004 printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1eb5207b 1005 env->PC, env->error_code, tb);
6af0bf9c
FB
1006#endif
1007 /* we restore the process signal mask as the sigreturn should
1008 do it (XXX: use sigsetjmp) */
1009 sigprocmask(SIG_SETMASK, old_set, NULL);
1010 do_raise_exception_err(env->exception_index, env->error_code);
1011 } else {
1012 /* activate soft MMU for this block */
1013 cpu_resume_from_signal(env, puc);
1014 }
1015 /* never comes here */
1016 return 1;
1017}
1018
fdf9b3e8
FB
1019#elif defined (TARGET_SH4)
1020static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1021 int is_write, sigset_t *old_set,
1022 void *puc)
1023{
1024 TranslationBlock *tb;
1025 int ret;
3b46e624 1026
fdf9b3e8
FB
1027 if (cpu_single_env)
1028 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1029#if defined(DEBUG_SIGNAL)
5fafdf24 1030 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
fdf9b3e8
FB
1031 pc, address, is_write, *(unsigned long *)old_set);
1032#endif
1033 /* XXX: locking issue */
1034 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1035 return 1;
1036 }
1037
1038 /* see if it is an MMU fault */
6ebbf390 1039 ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
fdf9b3e8
FB
1040 if (ret < 0)
1041 return 0; /* not an MMU fault */
1042 if (ret == 0)
1043 return 1; /* the MMU fault was handled without causing real CPU fault */
1044
1045 /* now we have a real cpu fault */
eddf68a6
JM
1046 tb = tb_find_pc(pc);
1047 if (tb) {
1048 /* the PC is inside the translated code. It means that we have
1049 a virtual CPU fault */
1050 cpu_restore_state(tb, env, pc, puc);
1051 }
1052#if 0
5fafdf24 1053 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
eddf68a6
JM
1054 env->nip, env->error_code, tb);
1055#endif
1056 /* we restore the process signal mask as the sigreturn should
1057 do it (XXX: use sigsetjmp) */
1058 sigprocmask(SIG_SETMASK, old_set, NULL);
1059 cpu_loop_exit();
1060 /* never comes here */
1061 return 1;
1062}
1063
1064#elif defined (TARGET_ALPHA)
1065static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1066 int is_write, sigset_t *old_set,
1067 void *puc)
1068{
1069 TranslationBlock *tb;
1070 int ret;
3b46e624 1071
eddf68a6
JM
1072 if (cpu_single_env)
1073 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1074#if defined(DEBUG_SIGNAL)
5fafdf24 1075 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
eddf68a6
JM
1076 pc, address, is_write, *(unsigned long *)old_set);
1077#endif
1078 /* XXX: locking issue */
1079 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1080 return 1;
1081 }
1082
1083 /* see if it is an MMU fault */
6ebbf390 1084 ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
eddf68a6
JM
1085 if (ret < 0)
1086 return 0; /* not an MMU fault */
1087 if (ret == 0)
1088 return 1; /* the MMU fault was handled without causing real CPU fault */
1089
1090 /* now we have a real cpu fault */
fdf9b3e8
FB
1091 tb = tb_find_pc(pc);
1092 if (tb) {
1093 /* the PC is inside the translated code. It means that we have
1094 a virtual CPU fault */
1095 cpu_restore_state(tb, env, pc, puc);
1096 }
fdf9b3e8 1097#if 0
5fafdf24 1098 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
fdf9b3e8
FB
1099 env->nip, env->error_code, tb);
1100#endif
1101 /* we restore the process signal mask as the sigreturn should
1102 do it (XXX: use sigsetjmp) */
355fb23d
PB
1103 sigprocmask(SIG_SETMASK, old_set, NULL);
1104 cpu_loop_exit();
fdf9b3e8
FB
1105 /* never comes here */
1106 return 1;
1107}
f1ccf904
TS
1108#elif defined (TARGET_CRIS)
1109static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1110 int is_write, sigset_t *old_set,
1111 void *puc)
1112{
1113 TranslationBlock *tb;
1114 int ret;
1115
1116 if (cpu_single_env)
1117 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1118#if defined(DEBUG_SIGNAL)
1119 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1120 pc, address, is_write, *(unsigned long *)old_set);
1121#endif
1122 /* XXX: locking issue */
1123 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1124 return 1;
1125 }
1126
1127 /* see if it is an MMU fault */
6ebbf390 1128 ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
f1ccf904
TS
1129 if (ret < 0)
1130 return 0; /* not an MMU fault */
1131 if (ret == 0)
1132 return 1; /* the MMU fault was handled without causing real CPU fault */
1133
1134 /* now we have a real cpu fault */
1135 tb = tb_find_pc(pc);
1136 if (tb) {
1137 /* the PC is inside the translated code. It means that we have
1138 a virtual CPU fault */
1139 cpu_restore_state(tb, env, pc, puc);
1140 }
f1ccf904
TS
1141 /* we restore the process signal mask as the sigreturn should
1142 do it (XXX: use sigsetjmp) */
1143 sigprocmask(SIG_SETMASK, old_set, NULL);
1144 cpu_loop_exit();
1145 /* never comes here */
1146 return 1;
1147}
1148
e4533c7a
FB
1149#else
1150#error unsupported target CPU
1151#endif
9de5e440 1152
2b413144
FB
1153#if defined(__i386__)
1154
d8ecc0b9
FB
1155#if defined(__APPLE__)
1156# include <sys/ucontext.h>
1157
1158# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1159# define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
1160# define ERROR_sig(context) ((context)->uc_mcontext->es.err)
1161#else
1162# define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
1163# define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
1164# define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
1165#endif
1166
5fafdf24 1167int cpu_signal_handler(int host_signum, void *pinfo,
e4533c7a 1168 void *puc)
9de5e440 1169{
5a7b542b 1170 siginfo_t *info = pinfo;
9de5e440
FB
1171 struct ucontext *uc = puc;
1172 unsigned long pc;
bf3e8bf1 1173 int trapno;
97eb5b14 1174
d691f669
FB
1175#ifndef REG_EIP
1176/* for glibc 2.1 */
fd6ce8f6
FB
1177#define REG_EIP EIP
1178#define REG_ERR ERR
1179#define REG_TRAPNO TRAPNO
d691f669 1180#endif
d8ecc0b9
FB
1181 pc = EIP_sig(uc);
1182 trapno = TRAP_sig(uc);
ec6338ba
FB
1183 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1184 trapno == 0xe ?
1185 (ERROR_sig(uc) >> 1) & 1 : 0,
1186 &uc->uc_sigmask, puc);
2b413144
FB
1187}
1188
bc51c5c9
FB
1189#elif defined(__x86_64__)
1190
b3efe5c8
BS
1191#ifdef __NetBSD__
1192#define REG_ERR _REG_ERR
1193#define REG_TRAPNO _REG_TRAPNO
1194
1195#define QEMU_UC_MCONTEXT_GREGS(uc, reg) (uc)->uc_mcontext.__gregs[(reg)]
1196#define QEMU_UC_MACHINE_PC(uc) _UC_MACHINE_PC(uc)
1197#else
1198#define QEMU_UC_MCONTEXT_GREGS(uc, reg) (uc)->uc_mcontext.gregs[(reg)]
1199#define QEMU_UC_MACHINE_PC(uc) QEMU_UC_MCONTEXT_GREGS(uc, REG_RIP)
1200#endif
1201
5a7b542b 1202int cpu_signal_handler(int host_signum, void *pinfo,
bc51c5c9
FB
1203 void *puc)
1204{
5a7b542b 1205 siginfo_t *info = pinfo;
bc51c5c9 1206 unsigned long pc;
b3efe5c8
BS
1207#ifdef __NetBSD__
1208 ucontext_t *uc = puc;
1209#else
1210 struct ucontext *uc = puc;
1211#endif
bc51c5c9 1212
b3efe5c8 1213 pc = QEMU_UC_MACHINE_PC(uc);
5fafdf24 1214 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
b3efe5c8
BS
1215 QEMU_UC_MCONTEXT_GREGS(uc, REG_TRAPNO) == 0xe ?
1216 (QEMU_UC_MCONTEXT_GREGS(uc, REG_ERR) >> 1) & 1 : 0,
bc51c5c9
FB
1217 &uc->uc_sigmask, puc);
1218}
1219
83fb7adf 1220#elif defined(__powerpc__)
2b413144 1221
83fb7adf
FB
1222/***********************************************************************
1223 * signal context platform-specific definitions
1224 * From Wine
1225 */
1226#ifdef linux
1227/* All Registers access - only for local access */
1228# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
1229/* Gpr Registers access */
1230# define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
1231# define IAR_sig(context) REG_sig(nip, context) /* Program counter */
1232# define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
1233# define CTR_sig(context) REG_sig(ctr, context) /* Count register */
1234# define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
1235# define LR_sig(context) REG_sig(link, context) /* Link register */
1236# define CR_sig(context) REG_sig(ccr, context) /* Condition register */
1237/* Float Registers access */
1238# define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1239# define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1240/* Exception Registers access */
1241# define DAR_sig(context) REG_sig(dar, context)
1242# define DSISR_sig(context) REG_sig(dsisr, context)
1243# define TRAP_sig(context) REG_sig(trap, context)
1244#endif /* linux */
1245
1246#ifdef __APPLE__
1247# include <sys/ucontext.h>
1248typedef struct ucontext SIGCONTEXT;
1249/* All Registers access - only for local access */
1250# define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
1251# define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
1252# define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
1253# define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
1254/* Gpr Registers access */
1255# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
1256# define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
1257# define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
1258# define CTR_sig(context) REG_sig(ctr, context)
1259# define XER_sig(context) REG_sig(xer, context) /* Link register */
1260# define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
1261# define CR_sig(context) REG_sig(cr, context) /* Condition register */
1262/* Float Registers access */
1263# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
1264# define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
1265/* Exception Registers access */
1266# define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
1267# define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
1268# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1269#endif /* __APPLE__ */
1270
5fafdf24 1271int cpu_signal_handler(int host_signum, void *pinfo,
e4533c7a 1272 void *puc)
2b413144 1273{
5a7b542b 1274 siginfo_t *info = pinfo;
25eb4484 1275 struct ucontext *uc = puc;
25eb4484 1276 unsigned long pc;
25eb4484
FB
1277 int is_write;
1278
83fb7adf 1279 pc = IAR_sig(uc);
25eb4484
FB
1280 is_write = 0;
1281#if 0
1282 /* ppc 4xx case */
83fb7adf 1283 if (DSISR_sig(uc) & 0x00800000)
25eb4484
FB
1284 is_write = 1;
1285#else
83fb7adf 1286 if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
25eb4484
FB
1287 is_write = 1;
1288#endif
5fafdf24 1289 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bf3e8bf1 1290 is_write, &uc->uc_sigmask, puc);
2b413144
FB
1291}
1292
2f87c607
FB
1293#elif defined(__alpha__)
1294
5fafdf24 1295int cpu_signal_handler(int host_signum, void *pinfo,
2f87c607
FB
1296 void *puc)
1297{
5a7b542b 1298 siginfo_t *info = pinfo;
2f87c607
FB
1299 struct ucontext *uc = puc;
1300 uint32_t *pc = uc->uc_mcontext.sc_pc;
1301 uint32_t insn = *pc;
1302 int is_write = 0;
1303
8c6939c0 1304 /* XXX: need kernel patch to get write flag faster */
2f87c607
FB
1305 switch (insn >> 26) {
1306 case 0x0d: // stw
1307 case 0x0e: // stb
1308 case 0x0f: // stq_u
1309 case 0x24: // stf
1310 case 0x25: // stg
1311 case 0x26: // sts
1312 case 0x27: // stt
1313 case 0x2c: // stl
1314 case 0x2d: // stq
1315 case 0x2e: // stl_c
1316 case 0x2f: // stq_c
1317 is_write = 1;
1318 }
1319
5fafdf24 1320 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bf3e8bf1 1321 is_write, &uc->uc_sigmask, puc);
2f87c607 1322}
8c6939c0
FB
1323#elif defined(__sparc__)
1324
5fafdf24 1325int cpu_signal_handler(int host_signum, void *pinfo,
e4533c7a 1326 void *puc)
8c6939c0 1327{
5a7b542b 1328 siginfo_t *info = pinfo;
8c6939c0
FB
1329 int is_write;
1330 uint32_t insn;
6b4c11cd 1331#if !defined(__arch64__) || defined(HOST_SOLARIS)
c9e1e2b0
BS
1332 uint32_t *regs = (uint32_t *)(info + 1);
1333 void *sigmask = (regs + 20);
8c6939c0 1334 /* XXX: is there a standard glibc define ? */
c9e1e2b0
BS
1335 unsigned long pc = regs[1];
1336#else
84778508 1337#ifdef __linux__
c9e1e2b0
BS
1338 struct sigcontext *sc = puc;
1339 unsigned long pc = sc->sigc_regs.tpc;
1340 void *sigmask = (void *)sc->sigc_mask;
84778508
BS
1341#elif defined(__OpenBSD__)
1342 struct sigcontext *uc = puc;
1343 unsigned long pc = uc->sc_pc;
1344 void *sigmask = (void *)(long)uc->sc_mask;
1345#endif
c9e1e2b0
BS
1346#endif
1347
8c6939c0
FB
1348 /* XXX: need kernel patch to get write flag faster */
1349 is_write = 0;
1350 insn = *(uint32_t *)pc;
1351 if ((insn >> 30) == 3) {
1352 switch((insn >> 19) & 0x3f) {
1353 case 0x05: // stb
1354 case 0x06: // sth
1355 case 0x04: // st
1356 case 0x07: // std
1357 case 0x24: // stf
1358 case 0x27: // stdf
1359 case 0x25: // stfsr
1360 is_write = 1;
1361 break;
1362 }
1363 }
5fafdf24 1364 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bf3e8bf1 1365 is_write, sigmask, NULL);
8c6939c0
FB
1366}
1367
1368#elif defined(__arm__)
1369
5fafdf24 1370int cpu_signal_handler(int host_signum, void *pinfo,
e4533c7a 1371 void *puc)
8c6939c0 1372{
5a7b542b 1373 siginfo_t *info = pinfo;
8c6939c0
FB
1374 struct ucontext *uc = puc;
1375 unsigned long pc;
1376 int is_write;
3b46e624 1377
48bbf11b 1378#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
5c49b363
AZ
1379 pc = uc->uc_mcontext.gregs[R15];
1380#else
4eee57f5 1381 pc = uc->uc_mcontext.arm_pc;
5c49b363 1382#endif
8c6939c0
FB
1383 /* XXX: compute is_write */
1384 is_write = 0;
5fafdf24 1385 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
8c6939c0 1386 is_write,
f3a9676a 1387 &uc->uc_sigmask, puc);
8c6939c0
FB
1388}
1389
38e584a0
FB
1390#elif defined(__mc68000)
1391
5fafdf24 1392int cpu_signal_handler(int host_signum, void *pinfo,
38e584a0
FB
1393 void *puc)
1394{
5a7b542b 1395 siginfo_t *info = pinfo;
38e584a0
FB
1396 struct ucontext *uc = puc;
1397 unsigned long pc;
1398 int is_write;
3b46e624 1399
38e584a0
FB
1400 pc = uc->uc_mcontext.gregs[16];
1401 /* XXX: compute is_write */
1402 is_write = 0;
5fafdf24 1403 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
38e584a0 1404 is_write,
bf3e8bf1 1405 &uc->uc_sigmask, puc);
38e584a0
FB
1406}
1407
b8076a74
FB
1408#elif defined(__ia64)
1409
1410#ifndef __ISR_VALID
1411 /* This ought to be in <bits/siginfo.h>... */
1412# define __ISR_VALID 1
b8076a74
FB
1413#endif
1414
5a7b542b 1415int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
b8076a74 1416{
5a7b542b 1417 siginfo_t *info = pinfo;
b8076a74
FB
1418 struct ucontext *uc = puc;
1419 unsigned long ip;
1420 int is_write = 0;
1421
1422 ip = uc->uc_mcontext.sc_ip;
1423 switch (host_signum) {
1424 case SIGILL:
1425 case SIGFPE:
1426 case SIGSEGV:
1427 case SIGBUS:
1428 case SIGTRAP:
fd4a43e4 1429 if (info->si_code && (info->si_segvflags & __ISR_VALID))
b8076a74
FB
1430 /* ISR.W (write-access) is bit 33: */
1431 is_write = (info->si_isr >> 33) & 1;
1432 break;
1433
1434 default:
1435 break;
1436 }
1437 return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1438 is_write,
1439 &uc->uc_sigmask, puc);
1440}
1441
90cb9493
FB
1442#elif defined(__s390__)
1443
5fafdf24 1444int cpu_signal_handler(int host_signum, void *pinfo,
90cb9493
FB
1445 void *puc)
1446{
5a7b542b 1447 siginfo_t *info = pinfo;
90cb9493
FB
1448 struct ucontext *uc = puc;
1449 unsigned long pc;
1450 int is_write;
3b46e624 1451
90cb9493
FB
1452 pc = uc->uc_mcontext.psw.addr;
1453 /* XXX: compute is_write */
1454 is_write = 0;
5fafdf24 1455 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
c4b89d18
TS
1456 is_write, &uc->uc_sigmask, puc);
1457}
1458
1459#elif defined(__mips__)
1460
5fafdf24 1461int cpu_signal_handler(int host_signum, void *pinfo,
c4b89d18
TS
1462 void *puc)
1463{
9617efe8 1464 siginfo_t *info = pinfo;
c4b89d18
TS
1465 struct ucontext *uc = puc;
1466 greg_t pc = uc->uc_mcontext.pc;
1467 int is_write;
3b46e624 1468
c4b89d18
TS
1469 /* XXX: compute is_write */
1470 is_write = 0;
5fafdf24 1471 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
c4b89d18 1472 is_write, &uc->uc_sigmask, puc);
90cb9493
FB
1473}
1474
f54b3f92
AJ
1475#elif defined(__hppa__)
1476
1477int cpu_signal_handler(int host_signum, void *pinfo,
1478 void *puc)
1479{
1480 struct siginfo *info = pinfo;
1481 struct ucontext *uc = puc;
1482 unsigned long pc;
1483 int is_write;
1484
1485 pc = uc->uc_mcontext.sc_iaoq[0];
1486 /* FIXME: compute is_write */
1487 is_write = 0;
1488 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1489 is_write,
1490 &uc->uc_sigmask, puc);
1491}
1492
9de5e440 1493#else
2b413144 1494
3fb2ded1 1495#error host CPU specific signal handler needed
2b413144 1496
9de5e440 1497#endif
67b915a5
FB
1498
1499#endif /* !defined(CONFIG_SOFTMMU) */