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