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