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