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