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