]> git.proxmox.com Git - qemu.git/blob - cpu-exec.c
Always process real timers regardless of singlestep mode (Jason Wessel).
[qemu.git] / cpu-exec.c
1 /*
2 * i386 emulator main execution loop
3 *
4 * Copyright (c) 2003-2005 Fabrice Bellard
5 *
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.
10 *
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.
15 *
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
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 #include "config.h"
21 #define CPU_NO_GLOBAL_REGS
22 #include "exec.h"
23 #include "disas.h"
24 #include "tcg.h"
25
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>
37 #include <sys/ucontext.h>
38 #endif
39
40 int tb_invalidated_flag;
41 static unsigned long next_tb;
42
43 //#define DEBUG_EXEC
44 //#define DEBUG_SIGNAL
45
46 #define SAVE_GLOBALS()
47 #define RESTORE_GLOBALS()
48
49 #if defined(__sparc__) && !defined(HOST_SOLARIS)
50 #include <features.h>
51 #if defined(__GLIBC__) && ((__GLIBC__ < 2) || \
52 ((__GLIBC__ == 2) && (__GLIBC_MINOR__ <= 90)))
53 // Work around ugly bugs in glibc that mangle global register contents
54
55 static volatile void *saved_env;
56 #undef SAVE_GLOBALS
57 #define SAVE_GLOBALS() do { \
58 saved_env = env; \
59 } while(0)
60
61 #undef RESTORE_GLOBALS
62 #define RESTORE_GLOBALS() do { \
63 env = (void *)saved_env; \
64 } while(0)
65
66 static int sparc_setjmp(jmp_buf buf)
67 {
68 int ret;
69
70 SAVE_GLOBALS();
71 ret = setjmp(buf);
72 RESTORE_GLOBALS();
73 return ret;
74 }
75 #undef setjmp
76 #define setjmp(jmp_buf) sparc_setjmp(jmp_buf)
77
78 static void sparc_longjmp(jmp_buf buf, int val)
79 {
80 SAVE_GLOBALS();
81 longjmp(buf, val);
82 }
83 #define longjmp(jmp_buf, val) sparc_longjmp(jmp_buf, val)
84 #endif
85 #endif
86
87 void cpu_loop_exit(void)
88 {
89 /* NOTE: the register at this point must be saved by hand because
90 longjmp restore them */
91 regs_to_env();
92 longjmp(env->jmp_env, 1);
93 }
94
95 #if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
96 #define reg_T2
97 #endif
98
99 /* exit the current TB from a signal handler. The host registers are
100 restored in a state compatible with the CPU emulator
101 */
102 void cpu_resume_from_signal(CPUState *env1, void *puc)
103 {
104 #if !defined(CONFIG_SOFTMMU)
105 struct ucontext *uc = puc;
106 #endif
107
108 env = env1;
109
110 /* XXX: restore cpu registers saved in host registers */
111
112 #if !defined(CONFIG_SOFTMMU)
113 if (puc) {
114 /* XXX: use siglongjmp ? */
115 sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
116 }
117 #endif
118 longjmp(env->jmp_env, 1);
119 }
120
121 static TranslationBlock *tb_find_slow(target_ulong pc,
122 target_ulong cs_base,
123 uint64_t flags)
124 {
125 TranslationBlock *tb, **ptb1;
126 int code_gen_size;
127 unsigned int h;
128 target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
129 uint8_t *tc_ptr;
130
131 spin_lock(&tb_lock);
132
133 tb_invalidated_flag = 0;
134
135 regs_to_env(); /* XXX: do it just before cpu_gen_code() */
136
137 /* find translated block using physical mappings */
138 phys_pc = get_phys_addr_code(env, pc);
139 phys_page1 = phys_pc & TARGET_PAGE_MASK;
140 phys_page2 = -1;
141 h = tb_phys_hash_func(phys_pc);
142 ptb1 = &tb_phys_hash[h];
143 for(;;) {
144 tb = *ptb1;
145 if (!tb)
146 goto not_found;
147 if (tb->pc == pc &&
148 tb->page_addr[0] == phys_page1 &&
149 tb->cs_base == cs_base &&
150 tb->flags == flags) {
151 /* check next page if needed */
152 if (tb->page_addr[1] != -1) {
153 virt_page2 = (pc & TARGET_PAGE_MASK) +
154 TARGET_PAGE_SIZE;
155 phys_page2 = get_phys_addr_code(env, virt_page2);
156 if (tb->page_addr[1] == phys_page2)
157 goto found;
158 } else {
159 goto found;
160 }
161 }
162 ptb1 = &tb->phys_hash_next;
163 }
164 not_found:
165 /* if no translated code available, then translate it now */
166 tb = tb_alloc(pc);
167 if (!tb) {
168 /* flush must be done */
169 tb_flush(env);
170 /* cannot fail at this point */
171 tb = tb_alloc(pc);
172 /* don't forget to invalidate previous TB info */
173 tb_invalidated_flag = 1;
174 }
175 tc_ptr = code_gen_ptr;
176 tb->tc_ptr = tc_ptr;
177 tb->cs_base = cs_base;
178 tb->flags = flags;
179 SAVE_GLOBALS();
180 cpu_gen_code(env, tb, &code_gen_size);
181 RESTORE_GLOBALS();
182 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
183
184 /* check next page if needed */
185 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
186 phys_page2 = -1;
187 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
188 phys_page2 = get_phys_addr_code(env, virt_page2);
189 }
190 tb_link_phys(tb, phys_pc, phys_page2);
191
192 found:
193 /* we add the TB in the virtual pc hash table */
194 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
195 spin_unlock(&tb_lock);
196 return tb;
197 }
198
199 static inline TranslationBlock *tb_find_fast(void)
200 {
201 TranslationBlock *tb;
202 target_ulong cs_base, pc;
203 uint64_t flags;
204
205 /* we record a subset of the CPU state. It will
206 always be the same before a given translated block
207 is executed. */
208 #if defined(TARGET_I386)
209 flags = env->hflags;
210 flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
211 flags |= env->intercept;
212 cs_base = env->segs[R_CS].base;
213 pc = cs_base + env->eip;
214 #elif defined(TARGET_ARM)
215 flags = env->thumb | (env->vfp.vec_len << 1)
216 | (env->vfp.vec_stride << 4);
217 if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
218 flags |= (1 << 6);
219 if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
220 flags |= (1 << 7);
221 flags |= (env->condexec_bits << 8);
222 cs_base = 0;
223 pc = env->regs[15];
224 #elif defined(TARGET_SPARC)
225 #ifdef TARGET_SPARC64
226 // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
227 flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
228 | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
229 #else
230 // FPU enable . Supervisor
231 flags = (env->psref << 4) | env->psrs;
232 #endif
233 cs_base = env->npc;
234 pc = env->pc;
235 #elif defined(TARGET_PPC)
236 flags = env->hflags;
237 cs_base = 0;
238 pc = env->nip;
239 #elif defined(TARGET_MIPS)
240 flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
241 cs_base = 0;
242 pc = env->PC[env->current_tc];
243 #elif defined(TARGET_M68K)
244 flags = (env->fpcr & M68K_FPCR_PREC) /* Bit 6 */
245 | (env->sr & SR_S) /* Bit 13 */
246 | ((env->macsr >> 4) & 0xf); /* Bits 0-3 */
247 cs_base = 0;
248 pc = env->pc;
249 #elif defined(TARGET_SH4)
250 flags = env->flags;
251 cs_base = 0;
252 pc = env->pc;
253 #elif defined(TARGET_ALPHA)
254 flags = env->ps;
255 cs_base = 0;
256 pc = env->pc;
257 #elif defined(TARGET_CRIS)
258 flags = env->pregs[PR_CCS] & U_FLAG;
259 flags |= env->dslot;
260 cs_base = 0;
261 pc = env->pc;
262 #else
263 #error unsupported CPU
264 #endif
265 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
266 if (__builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base ||
267 tb->flags != flags, 0)) {
268 tb = tb_find_slow(pc, cs_base, flags);
269 /* Note: we do it here to avoid a gcc bug on Mac OS X when
270 doing it in tb_find_slow */
271 if (tb_invalidated_flag) {
272 /* as some TB could have been invalidated because
273 of memory exceptions while generating the code, we
274 must recompute the hash index here */
275 next_tb = 0;
276 }
277 }
278 return tb;
279 }
280
281 /* main execution loop */
282
283 int cpu_exec(CPUState *env1)
284 {
285 #define DECLARE_HOST_REGS 1
286 #include "hostregs_helper.h"
287 #if defined(TARGET_SPARC)
288 #if defined(reg_REGWPTR)
289 uint32_t *saved_regwptr;
290 #endif
291 #endif
292 int ret, interrupt_request;
293 TranslationBlock *tb;
294 uint8_t *tc_ptr;
295
296 if (cpu_halted(env1) == EXCP_HALTED)
297 return EXCP_HALTED;
298
299 cpu_single_env = env1;
300
301 /* first we save global registers */
302 #define SAVE_HOST_REGS 1
303 #include "hostregs_helper.h"
304 env = env1;
305 SAVE_GLOBALS();
306
307 env_to_regs();
308 #if defined(TARGET_I386)
309 /* put eflags in CPU temporary format */
310 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
311 DF = 1 - (2 * ((env->eflags >> 10) & 1));
312 CC_OP = CC_OP_EFLAGS;
313 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
314 #elif defined(TARGET_SPARC)
315 #if defined(reg_REGWPTR)
316 saved_regwptr = REGWPTR;
317 #endif
318 #elif defined(TARGET_M68K)
319 env->cc_op = CC_OP_FLAGS;
320 env->cc_dest = env->sr & 0xf;
321 env->cc_x = (env->sr >> 4) & 1;
322 #elif defined(TARGET_ALPHA)
323 #elif defined(TARGET_ARM)
324 #elif defined(TARGET_PPC)
325 #elif defined(TARGET_MIPS)
326 #elif defined(TARGET_SH4)
327 #elif defined(TARGET_CRIS)
328 /* XXXXX */
329 #else
330 #error unsupported target CPU
331 #endif
332 env->exception_index = -1;
333
334 /* prepare setjmp context for exception handling */
335 for(;;) {
336 if (setjmp(env->jmp_env) == 0) {
337 env->current_tb = NULL;
338 /* if an exception is pending, we execute it here */
339 if (env->exception_index >= 0) {
340 if (env->exception_index >= EXCP_INTERRUPT) {
341 /* exit request from the cpu execution loop */
342 ret = env->exception_index;
343 break;
344 } else if (env->user_mode_only) {
345 /* if user mode only, we simulate a fake exception
346 which will be handled outside the cpu execution
347 loop */
348 #if defined(TARGET_I386)
349 do_interrupt_user(env->exception_index,
350 env->exception_is_int,
351 env->error_code,
352 env->exception_next_eip);
353 /* successfully delivered */
354 env->old_exception = -1;
355 #endif
356 ret = env->exception_index;
357 break;
358 } else {
359 #if defined(TARGET_I386)
360 /* simulate a real cpu exception. On i386, it can
361 trigger new exceptions, but we do not handle
362 double or triple faults yet. */
363 do_interrupt(env->exception_index,
364 env->exception_is_int,
365 env->error_code,
366 env->exception_next_eip, 0);
367 /* successfully delivered */
368 env->old_exception = -1;
369 #elif defined(TARGET_PPC)
370 do_interrupt(env);
371 #elif defined(TARGET_MIPS)
372 do_interrupt(env);
373 #elif defined(TARGET_SPARC)
374 do_interrupt(env->exception_index);
375 #elif defined(TARGET_ARM)
376 do_interrupt(env);
377 #elif defined(TARGET_SH4)
378 do_interrupt(env);
379 #elif defined(TARGET_ALPHA)
380 do_interrupt(env);
381 #elif defined(TARGET_CRIS)
382 do_interrupt(env);
383 #elif defined(TARGET_M68K)
384 do_interrupt(0);
385 #endif
386 }
387 env->exception_index = -1;
388 }
389 #ifdef USE_KQEMU
390 if (kqemu_is_ok(env) && env->interrupt_request == 0) {
391 int ret;
392 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
393 ret = kqemu_cpu_exec(env);
394 /* put eflags in CPU temporary format */
395 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
396 DF = 1 - (2 * ((env->eflags >> 10) & 1));
397 CC_OP = CC_OP_EFLAGS;
398 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
399 if (ret == 1) {
400 /* exception */
401 longjmp(env->jmp_env, 1);
402 } else if (ret == 2) {
403 /* softmmu execution needed */
404 } else {
405 if (env->interrupt_request != 0) {
406 /* hardware interrupt will be executed just after */
407 } else {
408 /* otherwise, we restart */
409 longjmp(env->jmp_env, 1);
410 }
411 }
412 }
413 #endif
414
415 next_tb = 0; /* force lookup of first TB */
416 for(;;) {
417 SAVE_GLOBALS();
418 interrupt_request = env->interrupt_request;
419 if (__builtin_expect(interrupt_request, 0)
420 #if defined(TARGET_I386)
421 && env->hflags & HF_GIF_MASK
422 #endif
423 && likely(!(env->singlestep_enabled & SSTEP_NOIRQ))) {
424 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
425 env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
426 env->exception_index = EXCP_DEBUG;
427 cpu_loop_exit();
428 }
429 #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
430 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
431 if (interrupt_request & CPU_INTERRUPT_HALT) {
432 env->interrupt_request &= ~CPU_INTERRUPT_HALT;
433 env->halted = 1;
434 env->exception_index = EXCP_HLT;
435 cpu_loop_exit();
436 }
437 #endif
438 #if defined(TARGET_I386)
439 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
440 !(env->hflags & HF_SMM_MASK)) {
441 svm_check_intercept(SVM_EXIT_SMI);
442 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
443 do_smm_enter();
444 next_tb = 0;
445 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
446 !(env->hflags & HF_NMI_MASK)) {
447 env->interrupt_request &= ~CPU_INTERRUPT_NMI;
448 env->hflags |= HF_NMI_MASK;
449 do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
450 next_tb = 0;
451 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
452 (env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) &&
453 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
454 int intno;
455 svm_check_intercept(SVM_EXIT_INTR);
456 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
457 intno = cpu_get_pic_interrupt(env);
458 if (loglevel & CPU_LOG_TB_IN_ASM) {
459 fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
460 }
461 do_interrupt(intno, 0, 0, 0, 1);
462 /* ensure that no TB jump will be modified as
463 the program flow was changed */
464 next_tb = 0;
465 #if !defined(CONFIG_USER_ONLY)
466 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
467 (env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
468 int intno;
469 /* FIXME: this should respect TPR */
470 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
471 svm_check_intercept(SVM_EXIT_VINTR);
472 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
473 if (loglevel & CPU_LOG_TB_IN_ASM)
474 fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
475 do_interrupt(intno, 0, 0, -1, 1);
476 stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
477 ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
478 next_tb = 0;
479 #endif
480 }
481 #elif defined(TARGET_PPC)
482 #if 0
483 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
484 cpu_ppc_reset(env);
485 }
486 #endif
487 if (interrupt_request & CPU_INTERRUPT_HARD) {
488 ppc_hw_interrupt(env);
489 if (env->pending_interrupts == 0)
490 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
491 next_tb = 0;
492 }
493 #elif defined(TARGET_MIPS)
494 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
495 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
496 (env->CP0_Status & (1 << CP0St_IE)) &&
497 !(env->CP0_Status & (1 << CP0St_EXL)) &&
498 !(env->CP0_Status & (1 << CP0St_ERL)) &&
499 !(env->hflags & MIPS_HFLAG_DM)) {
500 /* Raise it */
501 env->exception_index = EXCP_EXT_INTERRUPT;
502 env->error_code = 0;
503 do_interrupt(env);
504 next_tb = 0;
505 }
506 #elif defined(TARGET_SPARC)
507 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
508 (env->psret != 0)) {
509 int pil = env->interrupt_index & 15;
510 int type = env->interrupt_index & 0xf0;
511
512 if (((type == TT_EXTINT) &&
513 (pil == 15 || pil > env->psrpil)) ||
514 type != TT_EXTINT) {
515 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
516 do_interrupt(env->interrupt_index);
517 env->interrupt_index = 0;
518 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
519 cpu_check_irqs(env);
520 #endif
521 next_tb = 0;
522 }
523 } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
524 //do_interrupt(0, 0, 0, 0, 0);
525 env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
526 }
527 #elif defined(TARGET_ARM)
528 if (interrupt_request & CPU_INTERRUPT_FIQ
529 && !(env->uncached_cpsr & CPSR_F)) {
530 env->exception_index = EXCP_FIQ;
531 do_interrupt(env);
532 next_tb = 0;
533 }
534 /* ARMv7-M interrupt return works by loading a magic value
535 into the PC. On real hardware the load causes the
536 return to occur. The qemu implementation performs the
537 jump normally, then does the exception return when the
538 CPU tries to execute code at the magic address.
539 This will cause the magic PC value to be pushed to
540 the stack if an interrupt occured at the wrong time.
541 We avoid this by disabling interrupts when
542 pc contains a magic address. */
543 if (interrupt_request & CPU_INTERRUPT_HARD
544 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
545 || !(env->uncached_cpsr & CPSR_I))) {
546 env->exception_index = EXCP_IRQ;
547 do_interrupt(env);
548 next_tb = 0;
549 }
550 #elif defined(TARGET_SH4)
551 if (interrupt_request & CPU_INTERRUPT_HARD) {
552 do_interrupt(env);
553 next_tb = 0;
554 }
555 #elif defined(TARGET_ALPHA)
556 if (interrupt_request & CPU_INTERRUPT_HARD) {
557 do_interrupt(env);
558 next_tb = 0;
559 }
560 #elif defined(TARGET_CRIS)
561 if (interrupt_request & CPU_INTERRUPT_HARD) {
562 do_interrupt(env);
563 next_tb = 0;
564 }
565 #elif defined(TARGET_M68K)
566 if (interrupt_request & CPU_INTERRUPT_HARD
567 && ((env->sr & SR_I) >> SR_I_SHIFT)
568 < env->pending_level) {
569 /* Real hardware gets the interrupt vector via an
570 IACK cycle at this point. Current emulated
571 hardware doesn't rely on this, so we
572 provide/save the vector when the interrupt is
573 first signalled. */
574 env->exception_index = env->pending_vector;
575 do_interrupt(1);
576 next_tb = 0;
577 }
578 #endif
579 /* Don't use the cached interupt_request value,
580 do_interrupt may have updated the EXITTB flag. */
581 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
582 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
583 /* ensure that no TB jump will be modified as
584 the program flow was changed */
585 next_tb = 0;
586 }
587 if (interrupt_request & CPU_INTERRUPT_EXIT) {
588 env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
589 env->exception_index = EXCP_INTERRUPT;
590 cpu_loop_exit();
591 }
592 }
593 #ifdef DEBUG_EXEC
594 if ((loglevel & CPU_LOG_TB_CPU)) {
595 /* restore flags in standard format */
596 regs_to_env();
597 #if defined(TARGET_I386)
598 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
599 cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
600 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
601 #elif defined(TARGET_ARM)
602 cpu_dump_state(env, logfile, fprintf, 0);
603 #elif defined(TARGET_SPARC)
604 REGWPTR = env->regbase + (env->cwp * 16);
605 env->regwptr = REGWPTR;
606 cpu_dump_state(env, logfile, fprintf, 0);
607 #elif defined(TARGET_PPC)
608 cpu_dump_state(env, logfile, fprintf, 0);
609 #elif defined(TARGET_M68K)
610 cpu_m68k_flush_flags(env, env->cc_op);
611 env->cc_op = CC_OP_FLAGS;
612 env->sr = (env->sr & 0xffe0)
613 | env->cc_dest | (env->cc_x << 4);
614 cpu_dump_state(env, logfile, fprintf, 0);
615 #elif defined(TARGET_MIPS)
616 cpu_dump_state(env, logfile, fprintf, 0);
617 #elif defined(TARGET_SH4)
618 cpu_dump_state(env, logfile, fprintf, 0);
619 #elif defined(TARGET_ALPHA)
620 cpu_dump_state(env, logfile, fprintf, 0);
621 #elif defined(TARGET_CRIS)
622 cpu_dump_state(env, logfile, fprintf, 0);
623 #else
624 #error unsupported target CPU
625 #endif
626 }
627 #endif
628 tb = tb_find_fast();
629 #ifdef DEBUG_EXEC
630 if ((loglevel & CPU_LOG_EXEC)) {
631 fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
632 (long)tb->tc_ptr, tb->pc,
633 lookup_symbol(tb->pc));
634 }
635 #endif
636 RESTORE_GLOBALS();
637 /* see if we can patch the calling TB. When the TB
638 spans two pages, we cannot safely do a direct
639 jump. */
640 {
641 if (next_tb != 0 &&
642 #ifdef USE_KQEMU
643 (env->kqemu_enabled != 2) &&
644 #endif
645 tb->page_addr[1] == -1) {
646 spin_lock(&tb_lock);
647 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
648 spin_unlock(&tb_lock);
649 }
650 }
651 tc_ptr = tb->tc_ptr;
652 env->current_tb = tb;
653 /* execute the generated code */
654 next_tb = tcg_qemu_tb_exec(tc_ptr);
655 env->current_tb = NULL;
656 /* reset soft MMU for next block (it can currently
657 only be set by a memory fault) */
658 #if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
659 if (env->hflags & HF_SOFTMMU_MASK) {
660 env->hflags &= ~HF_SOFTMMU_MASK;
661 /* do not allow linking to another block */
662 next_tb = 0;
663 }
664 #endif
665 #if defined(USE_KQEMU)
666 #define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
667 if (kqemu_is_ok(env) &&
668 (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
669 cpu_loop_exit();
670 }
671 #endif
672 } /* for(;;) */
673 } else {
674 env_to_regs();
675 }
676 } /* for(;;) */
677
678
679 #if defined(TARGET_I386)
680 /* restore flags in standard format */
681 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
682 #elif defined(TARGET_ARM)
683 /* XXX: Save/restore host fpu exception state?. */
684 #elif defined(TARGET_SPARC)
685 #if defined(reg_REGWPTR)
686 REGWPTR = saved_regwptr;
687 #endif
688 #elif defined(TARGET_PPC)
689 #elif defined(TARGET_M68K)
690 cpu_m68k_flush_flags(env, env->cc_op);
691 env->cc_op = CC_OP_FLAGS;
692 env->sr = (env->sr & 0xffe0)
693 | env->cc_dest | (env->cc_x << 4);
694 #elif defined(TARGET_MIPS)
695 #elif defined(TARGET_SH4)
696 #elif defined(TARGET_ALPHA)
697 #elif defined(TARGET_CRIS)
698 /* XXXXX */
699 #else
700 #error unsupported target CPU
701 #endif
702
703 /* restore global registers */
704 RESTORE_GLOBALS();
705 #include "hostregs_helper.h"
706
707 /* fail safe : never use cpu_single_env outside cpu_exec() */
708 cpu_single_env = NULL;
709 return ret;
710 }
711
712 /* must only be called from the generated code as an exception can be
713 generated */
714 void tb_invalidate_page_range(target_ulong start, target_ulong end)
715 {
716 /* XXX: cannot enable it yet because it yields to MMU exception
717 where NIP != read address on PowerPC */
718 #if 0
719 target_ulong phys_addr;
720 phys_addr = get_phys_addr_code(env, start);
721 tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
722 #endif
723 }
724
725 #if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
726
727 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
728 {
729 CPUX86State *saved_env;
730
731 saved_env = env;
732 env = s;
733 if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
734 selector &= 0xffff;
735 cpu_x86_load_seg_cache(env, seg_reg, selector,
736 (selector << 4), 0xffff, 0);
737 } else {
738 helper_load_seg(seg_reg, selector);
739 }
740 env = saved_env;
741 }
742
743 void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
744 {
745 CPUX86State *saved_env;
746
747 saved_env = env;
748 env = s;
749
750 helper_fsave(ptr, data32);
751
752 env = saved_env;
753 }
754
755 void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
756 {
757 CPUX86State *saved_env;
758
759 saved_env = env;
760 env = s;
761
762 helper_frstor(ptr, data32);
763
764 env = saved_env;
765 }
766
767 #endif /* TARGET_I386 */
768
769 #if !defined(CONFIG_SOFTMMU)
770
771 #if defined(TARGET_I386)
772
773 /* 'pc' is the host PC at which the exception was raised. 'address' is
774 the effective address of the memory exception. 'is_write' is 1 if a
775 write caused the exception and otherwise 0'. 'old_set' is the
776 signal set which should be restored */
777 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
778 int is_write, sigset_t *old_set,
779 void *puc)
780 {
781 TranslationBlock *tb;
782 int ret;
783
784 if (cpu_single_env)
785 env = cpu_single_env; /* XXX: find a correct solution for multithread */
786 #if defined(DEBUG_SIGNAL)
787 qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
788 pc, address, is_write, *(unsigned long *)old_set);
789 #endif
790 /* XXX: locking issue */
791 if (is_write && page_unprotect(h2g(address), pc, puc)) {
792 return 1;
793 }
794
795 /* see if it is an MMU fault */
796 ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
797 if (ret < 0)
798 return 0; /* not an MMU fault */
799 if (ret == 0)
800 return 1; /* the MMU fault was handled without causing real CPU fault */
801 /* now we have a real cpu fault */
802 tb = tb_find_pc(pc);
803 if (tb) {
804 /* the PC is inside the translated code. It means that we have
805 a virtual CPU fault */
806 cpu_restore_state(tb, env, pc, puc);
807 }
808 if (ret == 1) {
809 #if 0
810 printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
811 env->eip, env->cr[2], env->error_code);
812 #endif
813 /* we restore the process signal mask as the sigreturn should
814 do it (XXX: use sigsetjmp) */
815 sigprocmask(SIG_SETMASK, old_set, NULL);
816 raise_exception_err(env->exception_index, env->error_code);
817 } else {
818 /* activate soft MMU for this block */
819 env->hflags |= HF_SOFTMMU_MASK;
820 cpu_resume_from_signal(env, puc);
821 }
822 /* never comes here */
823 return 1;
824 }
825
826 #elif defined(TARGET_ARM)
827 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
828 int is_write, sigset_t *old_set,
829 void *puc)
830 {
831 TranslationBlock *tb;
832 int ret;
833
834 if (cpu_single_env)
835 env = cpu_single_env; /* XXX: find a correct solution for multithread */
836 #if defined(DEBUG_SIGNAL)
837 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
838 pc, address, is_write, *(unsigned long *)old_set);
839 #endif
840 /* XXX: locking issue */
841 if (is_write && page_unprotect(h2g(address), pc, puc)) {
842 return 1;
843 }
844 /* see if it is an MMU fault */
845 ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
846 if (ret < 0)
847 return 0; /* not an MMU fault */
848 if (ret == 0)
849 return 1; /* the MMU fault was handled without causing real CPU fault */
850 /* now we have a real cpu fault */
851 tb = tb_find_pc(pc);
852 if (tb) {
853 /* the PC is inside the translated code. It means that we have
854 a virtual CPU fault */
855 cpu_restore_state(tb, env, pc, puc);
856 }
857 /* we restore the process signal mask as the sigreturn should
858 do it (XXX: use sigsetjmp) */
859 sigprocmask(SIG_SETMASK, old_set, NULL);
860 cpu_loop_exit();
861 /* never comes here */
862 return 1;
863 }
864 #elif defined(TARGET_SPARC)
865 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
866 int is_write, sigset_t *old_set,
867 void *puc)
868 {
869 TranslationBlock *tb;
870 int ret;
871
872 if (cpu_single_env)
873 env = cpu_single_env; /* XXX: find a correct solution for multithread */
874 #if defined(DEBUG_SIGNAL)
875 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
876 pc, address, is_write, *(unsigned long *)old_set);
877 #endif
878 /* XXX: locking issue */
879 if (is_write && page_unprotect(h2g(address), pc, puc)) {
880 return 1;
881 }
882 /* see if it is an MMU fault */
883 ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
884 if (ret < 0)
885 return 0; /* not an MMU fault */
886 if (ret == 0)
887 return 1; /* the MMU fault was handled without causing real CPU fault */
888 /* now we have a real cpu fault */
889 tb = tb_find_pc(pc);
890 if (tb) {
891 /* the PC is inside the translated code. It means that we have
892 a virtual CPU fault */
893 cpu_restore_state(tb, env, pc, puc);
894 }
895 /* we restore the process signal mask as the sigreturn should
896 do it (XXX: use sigsetjmp) */
897 sigprocmask(SIG_SETMASK, old_set, NULL);
898 cpu_loop_exit();
899 /* never comes here */
900 return 1;
901 }
902 #elif defined (TARGET_PPC)
903 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
904 int is_write, sigset_t *old_set,
905 void *puc)
906 {
907 TranslationBlock *tb;
908 int ret;
909
910 if (cpu_single_env)
911 env = cpu_single_env; /* XXX: find a correct solution for multithread */
912 #if defined(DEBUG_SIGNAL)
913 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
914 pc, address, is_write, *(unsigned long *)old_set);
915 #endif
916 /* XXX: locking issue */
917 if (is_write && page_unprotect(h2g(address), pc, puc)) {
918 return 1;
919 }
920
921 /* see if it is an MMU fault */
922 ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
923 if (ret < 0)
924 return 0; /* not an MMU fault */
925 if (ret == 0)
926 return 1; /* the MMU fault was handled without causing real CPU fault */
927
928 /* now we have a real cpu fault */
929 tb = tb_find_pc(pc);
930 if (tb) {
931 /* the PC is inside the translated code. It means that we have
932 a virtual CPU fault */
933 cpu_restore_state(tb, env, pc, puc);
934 }
935 if (ret == 1) {
936 #if 0
937 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
938 env->nip, env->error_code, tb);
939 #endif
940 /* we restore the process signal mask as the sigreturn should
941 do it (XXX: use sigsetjmp) */
942 sigprocmask(SIG_SETMASK, old_set, NULL);
943 do_raise_exception_err(env->exception_index, env->error_code);
944 } else {
945 /* activate soft MMU for this block */
946 cpu_resume_from_signal(env, puc);
947 }
948 /* never comes here */
949 return 1;
950 }
951
952 #elif defined(TARGET_M68K)
953 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
954 int is_write, sigset_t *old_set,
955 void *puc)
956 {
957 TranslationBlock *tb;
958 int ret;
959
960 if (cpu_single_env)
961 env = cpu_single_env; /* XXX: find a correct solution for multithread */
962 #if defined(DEBUG_SIGNAL)
963 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
964 pc, address, is_write, *(unsigned long *)old_set);
965 #endif
966 /* XXX: locking issue */
967 if (is_write && page_unprotect(address, pc, puc)) {
968 return 1;
969 }
970 /* see if it is an MMU fault */
971 ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
972 if (ret < 0)
973 return 0; /* not an MMU fault */
974 if (ret == 0)
975 return 1; /* the MMU fault was handled without causing real CPU fault */
976 /* now we have a real cpu fault */
977 tb = tb_find_pc(pc);
978 if (tb) {
979 /* the PC is inside the translated code. It means that we have
980 a virtual CPU fault */
981 cpu_restore_state(tb, env, pc, puc);
982 }
983 /* we restore the process signal mask as the sigreturn should
984 do it (XXX: use sigsetjmp) */
985 sigprocmask(SIG_SETMASK, old_set, NULL);
986 cpu_loop_exit();
987 /* never comes here */
988 return 1;
989 }
990
991 #elif defined (TARGET_MIPS)
992 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
993 int is_write, sigset_t *old_set,
994 void *puc)
995 {
996 TranslationBlock *tb;
997 int ret;
998
999 if (cpu_single_env)
1000 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1001 #if defined(DEBUG_SIGNAL)
1002 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1003 pc, address, is_write, *(unsigned long *)old_set);
1004 #endif
1005 /* XXX: locking issue */
1006 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1007 return 1;
1008 }
1009
1010 /* see if it is an MMU fault */
1011 ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1012 if (ret < 0)
1013 return 0; /* not an MMU fault */
1014 if (ret == 0)
1015 return 1; /* the MMU fault was handled without causing real CPU fault */
1016
1017 /* now we have a real cpu fault */
1018 tb = tb_find_pc(pc);
1019 if (tb) {
1020 /* the PC is inside the translated code. It means that we have
1021 a virtual CPU fault */
1022 cpu_restore_state(tb, env, pc, puc);
1023 }
1024 if (ret == 1) {
1025 #if 0
1026 printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1027 env->PC, env->error_code, tb);
1028 #endif
1029 /* we restore the process signal mask as the sigreturn should
1030 do it (XXX: use sigsetjmp) */
1031 sigprocmask(SIG_SETMASK, old_set, NULL);
1032 do_raise_exception_err(env->exception_index, env->error_code);
1033 } else {
1034 /* activate soft MMU for this block */
1035 cpu_resume_from_signal(env, puc);
1036 }
1037 /* never comes here */
1038 return 1;
1039 }
1040
1041 #elif defined (TARGET_SH4)
1042 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1043 int is_write, sigset_t *old_set,
1044 void *puc)
1045 {
1046 TranslationBlock *tb;
1047 int ret;
1048
1049 if (cpu_single_env)
1050 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1051 #if defined(DEBUG_SIGNAL)
1052 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1053 pc, address, is_write, *(unsigned long *)old_set);
1054 #endif
1055 /* XXX: locking issue */
1056 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1057 return 1;
1058 }
1059
1060 /* see if it is an MMU fault */
1061 ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1062 if (ret < 0)
1063 return 0; /* not an MMU fault */
1064 if (ret == 0)
1065 return 1; /* the MMU fault was handled without causing real CPU fault */
1066
1067 /* now we have a real cpu fault */
1068 tb = tb_find_pc(pc);
1069 if (tb) {
1070 /* the PC is inside the translated code. It means that we have
1071 a virtual CPU fault */
1072 cpu_restore_state(tb, env, pc, puc);
1073 }
1074 #if 0
1075 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1076 env->nip, env->error_code, tb);
1077 #endif
1078 /* we restore the process signal mask as the sigreturn should
1079 do it (XXX: use sigsetjmp) */
1080 sigprocmask(SIG_SETMASK, old_set, NULL);
1081 cpu_loop_exit();
1082 /* never comes here */
1083 return 1;
1084 }
1085
1086 #elif defined (TARGET_ALPHA)
1087 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1088 int is_write, sigset_t *old_set,
1089 void *puc)
1090 {
1091 TranslationBlock *tb;
1092 int ret;
1093
1094 if (cpu_single_env)
1095 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1096 #if defined(DEBUG_SIGNAL)
1097 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1098 pc, address, is_write, *(unsigned long *)old_set);
1099 #endif
1100 /* XXX: locking issue */
1101 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1102 return 1;
1103 }
1104
1105 /* see if it is an MMU fault */
1106 ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1107 if (ret < 0)
1108 return 0; /* not an MMU fault */
1109 if (ret == 0)
1110 return 1; /* the MMU fault was handled without causing real CPU fault */
1111
1112 /* now we have a real cpu fault */
1113 tb = tb_find_pc(pc);
1114 if (tb) {
1115 /* the PC is inside the translated code. It means that we have
1116 a virtual CPU fault */
1117 cpu_restore_state(tb, env, pc, puc);
1118 }
1119 #if 0
1120 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1121 env->nip, env->error_code, tb);
1122 #endif
1123 /* we restore the process signal mask as the sigreturn should
1124 do it (XXX: use sigsetjmp) */
1125 sigprocmask(SIG_SETMASK, old_set, NULL);
1126 cpu_loop_exit();
1127 /* never comes here */
1128 return 1;
1129 }
1130 #elif defined (TARGET_CRIS)
1131 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1132 int is_write, sigset_t *old_set,
1133 void *puc)
1134 {
1135 TranslationBlock *tb;
1136 int ret;
1137
1138 if (cpu_single_env)
1139 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1140 #if defined(DEBUG_SIGNAL)
1141 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1142 pc, address, is_write, *(unsigned long *)old_set);
1143 #endif
1144 /* XXX: locking issue */
1145 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1146 return 1;
1147 }
1148
1149 /* see if it is an MMU fault */
1150 ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1151 if (ret < 0)
1152 return 0; /* not an MMU fault */
1153 if (ret == 0)
1154 return 1; /* the MMU fault was handled without causing real CPU fault */
1155
1156 /* now we have a real cpu fault */
1157 tb = tb_find_pc(pc);
1158 if (tb) {
1159 /* the PC is inside the translated code. It means that we have
1160 a virtual CPU fault */
1161 cpu_restore_state(tb, env, pc, puc);
1162 }
1163 /* we restore the process signal mask as the sigreturn should
1164 do it (XXX: use sigsetjmp) */
1165 sigprocmask(SIG_SETMASK, old_set, NULL);
1166 cpu_loop_exit();
1167 /* never comes here */
1168 return 1;
1169 }
1170
1171 #else
1172 #error unsupported target CPU
1173 #endif
1174
1175 #if defined(__i386__)
1176
1177 #if defined(__APPLE__)
1178 # include <sys/ucontext.h>
1179
1180 # define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1181 # define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
1182 # define ERROR_sig(context) ((context)->uc_mcontext->es.err)
1183 #else
1184 # define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
1185 # define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
1186 # define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
1187 #endif
1188
1189 int cpu_signal_handler(int host_signum, void *pinfo,
1190 void *puc)
1191 {
1192 siginfo_t *info = pinfo;
1193 struct ucontext *uc = puc;
1194 unsigned long pc;
1195 int trapno;
1196
1197 #ifndef REG_EIP
1198 /* for glibc 2.1 */
1199 #define REG_EIP EIP
1200 #define REG_ERR ERR
1201 #define REG_TRAPNO TRAPNO
1202 #endif
1203 pc = EIP_sig(uc);
1204 trapno = TRAP_sig(uc);
1205 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1206 trapno == 0xe ?
1207 (ERROR_sig(uc) >> 1) & 1 : 0,
1208 &uc->uc_sigmask, puc);
1209 }
1210
1211 #elif defined(__x86_64__)
1212
1213 int cpu_signal_handler(int host_signum, void *pinfo,
1214 void *puc)
1215 {
1216 siginfo_t *info = pinfo;
1217 struct ucontext *uc = puc;
1218 unsigned long pc;
1219
1220 pc = uc->uc_mcontext.gregs[REG_RIP];
1221 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1222 uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
1223 (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1224 &uc->uc_sigmask, puc);
1225 }
1226
1227 #elif defined(__powerpc__)
1228
1229 /***********************************************************************
1230 * signal context platform-specific definitions
1231 * From Wine
1232 */
1233 #ifdef linux
1234 /* All Registers access - only for local access */
1235 # define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
1236 /* Gpr Registers access */
1237 # define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
1238 # define IAR_sig(context) REG_sig(nip, context) /* Program counter */
1239 # define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
1240 # define CTR_sig(context) REG_sig(ctr, context) /* Count register */
1241 # define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
1242 # define LR_sig(context) REG_sig(link, context) /* Link register */
1243 # define CR_sig(context) REG_sig(ccr, context) /* Condition register */
1244 /* Float Registers access */
1245 # define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1246 # define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1247 /* Exception Registers access */
1248 # define DAR_sig(context) REG_sig(dar, context)
1249 # define DSISR_sig(context) REG_sig(dsisr, context)
1250 # define TRAP_sig(context) REG_sig(trap, context)
1251 #endif /* linux */
1252
1253 #ifdef __APPLE__
1254 # include <sys/ucontext.h>
1255 typedef struct ucontext SIGCONTEXT;
1256 /* All Registers access - only for local access */
1257 # define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
1258 # define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
1259 # define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
1260 # define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
1261 /* Gpr Registers access */
1262 # define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
1263 # define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
1264 # define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
1265 # define CTR_sig(context) REG_sig(ctr, context)
1266 # define XER_sig(context) REG_sig(xer, context) /* Link register */
1267 # define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
1268 # define CR_sig(context) REG_sig(cr, context) /* Condition register */
1269 /* Float Registers access */
1270 # define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
1271 # define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
1272 /* Exception Registers access */
1273 # define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
1274 # define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
1275 # define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1276 #endif /* __APPLE__ */
1277
1278 int cpu_signal_handler(int host_signum, void *pinfo,
1279 void *puc)
1280 {
1281 siginfo_t *info = pinfo;
1282 struct ucontext *uc = puc;
1283 unsigned long pc;
1284 int is_write;
1285
1286 pc = IAR_sig(uc);
1287 is_write = 0;
1288 #if 0
1289 /* ppc 4xx case */
1290 if (DSISR_sig(uc) & 0x00800000)
1291 is_write = 1;
1292 #else
1293 if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1294 is_write = 1;
1295 #endif
1296 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1297 is_write, &uc->uc_sigmask, puc);
1298 }
1299
1300 #elif defined(__alpha__)
1301
1302 int cpu_signal_handler(int host_signum, void *pinfo,
1303 void *puc)
1304 {
1305 siginfo_t *info = pinfo;
1306 struct ucontext *uc = puc;
1307 uint32_t *pc = uc->uc_mcontext.sc_pc;
1308 uint32_t insn = *pc;
1309 int is_write = 0;
1310
1311 /* XXX: need kernel patch to get write flag faster */
1312 switch (insn >> 26) {
1313 case 0x0d: // stw
1314 case 0x0e: // stb
1315 case 0x0f: // stq_u
1316 case 0x24: // stf
1317 case 0x25: // stg
1318 case 0x26: // sts
1319 case 0x27: // stt
1320 case 0x2c: // stl
1321 case 0x2d: // stq
1322 case 0x2e: // stl_c
1323 case 0x2f: // stq_c
1324 is_write = 1;
1325 }
1326
1327 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1328 is_write, &uc->uc_sigmask, puc);
1329 }
1330 #elif defined(__sparc__)
1331
1332 int cpu_signal_handler(int host_signum, void *pinfo,
1333 void *puc)
1334 {
1335 siginfo_t *info = pinfo;
1336 uint32_t *regs = (uint32_t *)(info + 1);
1337 void *sigmask = (regs + 20);
1338 unsigned long pc;
1339 int is_write;
1340 uint32_t insn;
1341
1342 /* XXX: is there a standard glibc define ? */
1343 pc = regs[1];
1344 /* XXX: need kernel patch to get write flag faster */
1345 is_write = 0;
1346 insn = *(uint32_t *)pc;
1347 if ((insn >> 30) == 3) {
1348 switch((insn >> 19) & 0x3f) {
1349 case 0x05: // stb
1350 case 0x06: // sth
1351 case 0x04: // st
1352 case 0x07: // std
1353 case 0x24: // stf
1354 case 0x27: // stdf
1355 case 0x25: // stfsr
1356 is_write = 1;
1357 break;
1358 }
1359 }
1360 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1361 is_write, sigmask, NULL);
1362 }
1363
1364 #elif defined(__arm__)
1365
1366 int cpu_signal_handler(int host_signum, void *pinfo,
1367 void *puc)
1368 {
1369 siginfo_t *info = pinfo;
1370 struct ucontext *uc = puc;
1371 unsigned long pc;
1372 int is_write;
1373
1374 pc = uc->uc_mcontext.arm_pc;
1375 /* XXX: compute is_write */
1376 is_write = 0;
1377 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1378 is_write,
1379 &uc->uc_sigmask, puc);
1380 }
1381
1382 #elif defined(__mc68000)
1383
1384 int cpu_signal_handler(int host_signum, void *pinfo,
1385 void *puc)
1386 {
1387 siginfo_t *info = pinfo;
1388 struct ucontext *uc = puc;
1389 unsigned long pc;
1390 int is_write;
1391
1392 pc = uc->uc_mcontext.gregs[16];
1393 /* XXX: compute is_write */
1394 is_write = 0;
1395 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1396 is_write,
1397 &uc->uc_sigmask, puc);
1398 }
1399
1400 #elif defined(__ia64)
1401
1402 #ifndef __ISR_VALID
1403 /* This ought to be in <bits/siginfo.h>... */
1404 # define __ISR_VALID 1
1405 #endif
1406
1407 int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1408 {
1409 siginfo_t *info = pinfo;
1410 struct ucontext *uc = puc;
1411 unsigned long ip;
1412 int is_write = 0;
1413
1414 ip = uc->uc_mcontext.sc_ip;
1415 switch (host_signum) {
1416 case SIGILL:
1417 case SIGFPE:
1418 case SIGSEGV:
1419 case SIGBUS:
1420 case SIGTRAP:
1421 if (info->si_code && (info->si_segvflags & __ISR_VALID))
1422 /* ISR.W (write-access) is bit 33: */
1423 is_write = (info->si_isr >> 33) & 1;
1424 break;
1425
1426 default:
1427 break;
1428 }
1429 return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1430 is_write,
1431 &uc->uc_sigmask, puc);
1432 }
1433
1434 #elif defined(__s390__)
1435
1436 int cpu_signal_handler(int host_signum, void *pinfo,
1437 void *puc)
1438 {
1439 siginfo_t *info = pinfo;
1440 struct ucontext *uc = puc;
1441 unsigned long pc;
1442 int is_write;
1443
1444 pc = uc->uc_mcontext.psw.addr;
1445 /* XXX: compute is_write */
1446 is_write = 0;
1447 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1448 is_write, &uc->uc_sigmask, puc);
1449 }
1450
1451 #elif defined(__mips__)
1452
1453 int cpu_signal_handler(int host_signum, void *pinfo,
1454 void *puc)
1455 {
1456 siginfo_t *info = pinfo;
1457 struct ucontext *uc = puc;
1458 greg_t pc = uc->uc_mcontext.pc;
1459 int is_write;
1460
1461 /* XXX: compute is_write */
1462 is_write = 0;
1463 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1464 is_write, &uc->uc_sigmask, puc);
1465 }
1466
1467 #elif defined(__hppa__)
1468
1469 int cpu_signal_handler(int host_signum, void *pinfo,
1470 void *puc)
1471 {
1472 struct siginfo *info = pinfo;
1473 struct ucontext *uc = puc;
1474 unsigned long pc;
1475 int is_write;
1476
1477 pc = uc->uc_mcontext.sc_iaoq[0];
1478 /* FIXME: compute is_write */
1479 is_write = 0;
1480 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1481 is_write,
1482 &uc->uc_sigmask, puc);
1483 }
1484
1485 #else
1486
1487 #error host CPU specific signal handler needed
1488
1489 #endif
1490
1491 #endif /* !defined(CONFIG_SOFTMMU) */