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