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