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