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