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