/[qemu]/qemu/cpu-exec.c
ViewVC logotype

Diff of /qemu/cpu-exec.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.2 by bellard, Sat Jun 21 13:09:25 2003 UTC revision 1.3 by bellard, Tue Jun 24 13:22:59 2003 UTC
# Line 29  Line 29 
29    
30  //#define DEBUG_EXEC  //#define DEBUG_EXEC
31  //#define DEBUG_SIGNAL  //#define DEBUG_SIGNAL
32    /* enable it to have a fully working x86 emulator for ring 0 */
33    //#define RING0_HACKS
34    
35  #if defined(TARGET_ARM)  #if defined(TARGET_ARM)
36  /* XXX: unify with i386 target */  /* XXX: unify with i386 target */
# Line 140  int cpu_exec(CPUState *env1) Line 142  int cpu_exec(CPUState *env1)
142  #error unsupported target CPU  #error unsupported target CPU
143  #endif  #endif
144      env->interrupt_request = 0;      env->interrupt_request = 0;
145        env->exception_index = -1;
146    
147      /* prepare setjmp context for exception handling */      /* prepare setjmp context for exception handling */
148      if (setjmp(env->jmp_env) == 0) {      for(;;) {
149          T0 = 0; /* force lookup of first TB */          if (setjmp(env->jmp_env) == 0) {
150          for(;;) {              /* if an exception is pending, we execute it here */
151                if (env->exception_index >= 0) {
152                    if (env->exception_index >= EXCP_INTERRUPT) {
153                        /* exit request from the cpu execution loop */
154                        ret = env->exception_index;
155                        break;
156                    } else if (env->user_mode_only) {
157                        /* if user mode only, we simulate a fake exception
158                           which will be hanlded outside the cpu execution
159                           loop */
160                        do_interrupt_user(env->exception_index,
161                                          env->exception_is_int,
162                                          env->error_code,
163                                          env->exception_next_eip);
164                        ret = env->exception_index;
165                        break;
166                    } else {
167                        /* simulate a real cpu exception. On i386, it can
168                           trigger new exceptions, but we do not handle
169                           double or triple faults yet. */
170                        do_interrupt(env->exception_index,
171                                     env->exception_is_int,
172                                     env->error_code,
173                                     env->exception_next_eip);
174                    }
175                    env->exception_index = -1;
176                }
177    #if defined(TARGET_I386)
178                /* if hardware interrupt pending, we execute it */
179                if (env->hard_interrupt_request &&
180                    (env->eflags & IF_MASK)) {
181                    int intno;
182                    intno = cpu_x86_get_pic_interrupt(env);
183                    if (loglevel) {
184                        fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
185                    }
186                    do_interrupt(intno, 0, 0, 0);
187                    env->hard_interrupt_request = 0;
188                }
189    #endif
190                T0 = 0; /* force lookup of first TB */
191                for(;;) {
192  #ifdef __sparc__  #ifdef __sparc__
193            /* g1 can be modified by some libc? functions */                  /* g1 can be modified by some libc? functions */
194              tmp_T0 = T0;                  tmp_T0 = T0;
195  #endif        #endif      
196              if (env->interrupt_request) {                  if (env->interrupt_request) {
197                  env->exception_index = EXCP_INTERRUPT;                      env->exception_index = EXCP_INTERRUPT;
198                  cpu_loop_exit();                      cpu_loop_exit();
199              }                  }
200  #ifdef DEBUG_EXEC  #ifdef DEBUG_EXEC
201              if (loglevel) {                  if (loglevel) {
202  #if defined(TARGET_I386)  #if defined(TARGET_I386)
203                  /* restore flags in standard format */                      /* restore flags in standard format */
204                  env->regs[R_EAX] = EAX;                      env->regs[R_EAX] = EAX;
205                  env->regs[R_EBX] = EBX;                      env->regs[R_EBX] = EBX;
206                  env->regs[R_ECX] = ECX;                      env->regs[R_ECX] = ECX;
207                  env->regs[R_EDX] = EDX;                      env->regs[R_EDX] = EDX;
208                  env->regs[R_ESI] = ESI;                      env->regs[R_ESI] = ESI;
209                  env->regs[R_EDI] = EDI;                      env->regs[R_EDI] = EDI;
210                  env->regs[R_EBP] = EBP;                      env->regs[R_EBP] = EBP;
211                  env->regs[R_ESP] = ESP;                      env->regs[R_ESP] = ESP;
212                  env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);                      env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
213                  cpu_x86_dump_state(env, logfile, 0);                      cpu_x86_dump_state(env, logfile, 0);
214                  env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);                      env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
215  #elif defined(TARGET_ARM)  #elif defined(TARGET_ARM)
216                  cpu_arm_dump_state(env, logfile, 0);                      cpu_arm_dump_state(env, logfile, 0);
217  #else  #else
218  #error unsupported target CPU  #error unsupported target CPU
219  #endif  #endif
220              }                  }
221  #endif  #endif
222              /* we compute the CPU state. We assume it will not                  /* we compute the CPU state. We assume it will not
223                 change during the whole generated block. */                     change during the whole generated block. */
224  #if defined(TARGET_I386)  #if defined(TARGET_I386)
225              flags = env->segs[R_CS].seg_32bit << GEN_FLAG_CODE32_SHIFT;                  flags = (env->segs[R_CS].flags & DESC_B_MASK)
226              flags |= env->segs[R_SS].seg_32bit << GEN_FLAG_SS32_SHIFT;                      >> (DESC_B_SHIFT - GEN_FLAG_CODE32_SHIFT);
227              flags |= (((unsigned long)env->segs[R_DS].base |                  flags |= (env->segs[R_SS].flags & DESC_B_MASK)
228                         (unsigned long)env->segs[R_ES].base |                      >> (DESC_B_SHIFT - GEN_FLAG_SS32_SHIFT);
229                         (unsigned long)env->segs[R_SS].base) != 0) <<                  flags |= (((unsigned long)env->segs[R_DS].base |
230                  GEN_FLAG_ADDSEG_SHIFT;                             (unsigned long)env->segs[R_ES].base |
231              if (!(env->eflags & VM_MASK)) {                             (unsigned long)env->segs[R_SS].base) != 0) <<
232                  flags |= (env->segs[R_CS].selector & 3) << GEN_FLAG_CPL_SHIFT;                      GEN_FLAG_ADDSEG_SHIFT;
233              } else {                  if (!(env->eflags & VM_MASK)) {
234                  /* NOTE: a dummy CPL is kept */                      flags |= (env->segs[R_CS].selector & 3) << GEN_FLAG_CPL_SHIFT;
235                  flags |= (1 << GEN_FLAG_VM_SHIFT);                  } else {
236                  flags |= (3 << GEN_FLAG_CPL_SHIFT);                      /* NOTE: a dummy CPL is kept */
237              }                      flags |= (1 << GEN_FLAG_VM_SHIFT);
238              flags |= (env->eflags & (IOPL_MASK | TF_MASK));                      flags |= (3 << GEN_FLAG_CPL_SHIFT);
239              cs_base = env->segs[R_CS].base;                  }
240              pc = cs_base + env->eip;                  flags |= (env->eflags & (IOPL_MASK | TF_MASK));
241                    cs_base = env->segs[R_CS].base;
242                    pc = cs_base + env->eip;
243  #elif defined(TARGET_ARM)  #elif defined(TARGET_ARM)
244              flags = 0;                  flags = 0;
245              cs_base = 0;                  cs_base = 0;
246              pc = (uint8_t *)env->regs[15];                  pc = (uint8_t *)env->regs[15];
247  #else  #else
248  #error unsupported CPU  #error unsupported CPU
249  #endif  #endif
250              tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base,                  tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base,
251                           flags);                               flags);
             if (!tb) {  
                 spin_lock(&tb_lock);  
                 /* if no translated code available, then translate it now */  
                 tb = tb_alloc((unsigned long)pc);  
252                  if (!tb) {                  if (!tb) {
253                      /* flush must be done */                      spin_lock(&tb_lock);
254                      tb_flush();                      /* if no translated code available, then translate it now */
                     /* cannot fail at this point */  
255                      tb = tb_alloc((unsigned long)pc);                      tb = tb_alloc((unsigned long)pc);
256                      /* don't forget to invalidate previous TB info */                      if (!tb) {
257                      ptb = &tb_hash[tb_hash_func((unsigned long)pc)];                          /* flush must be done */
258                      T0 = 0;                          tb_flush();
259                  }                          /* cannot fail at this point */
260                  tc_ptr = code_gen_ptr;                          tb = tb_alloc((unsigned long)pc);
261                  tb->tc_ptr = tc_ptr;                          /* don't forget to invalidate previous TB info */
262                  tb->cs_base = (unsigned long)cs_base;                          ptb = &tb_hash[tb_hash_func((unsigned long)pc)];
263                  tb->flags = flags;                          T0 = 0;
264                  ret = cpu_gen_code(tb, CODE_GEN_MAX_SIZE, &code_gen_size);                      }
265                        tc_ptr = code_gen_ptr;
266                        tb->tc_ptr = tc_ptr;
267                        tb->cs_base = (unsigned long)cs_base;
268                        tb->flags = flags;
269                        ret = cpu_gen_code(tb, CODE_GEN_MAX_SIZE, &code_gen_size);
270  #if defined(TARGET_I386)  #if defined(TARGET_I386)
271                  /* XXX: suppress that, this is incorrect */                      /* XXX: suppress that, this is incorrect */
272                  /* if invalid instruction, signal it */                      /* if invalid instruction, signal it */
273                  if (ret != 0) {                      if (ret != 0) {
274                      /* NOTE: the tb is allocated but not linked, so we                          /* NOTE: the tb is allocated but not linked, so we
275                         can leave it */                             can leave it */
276                            spin_unlock(&tb_lock);
277                            raise_exception(EXCP06_ILLOP);
278                        }
279    #endif
280                        *ptb = tb;
281                        tb->hash_next = NULL;
282                        tb_link(tb);
283                        code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
284                      spin_unlock(&tb_lock);                      spin_unlock(&tb_lock);
                     raise_exception(EXCP06_ILLOP);  
285                  }                  }
 #endif  
                 *ptb = tb;  
                 tb->hash_next = NULL;  
                 tb_link(tb);  
                 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));  
                 spin_unlock(&tb_lock);  
             }  
286  #ifdef DEBUG_EXEC  #ifdef DEBUG_EXEC
287              if (loglevel) {                  if (loglevel) {
288                  fprintf(logfile, "Trace 0x%08lx [0x%08lx] %s\n",                      fprintf(logfile, "Trace 0x%08lx [0x%08lx] %s\n",
289                          (long)tb->tc_ptr, (long)tb->pc,                              (long)tb->tc_ptr, (long)tb->pc,
290                          lookup_symbol((void *)tb->pc));                              lookup_symbol((void *)tb->pc));
291              }                  }
292  #endif  #endif
293  #ifdef __sparc__  #ifdef __sparc__
294              T0 = tmp_T0;                  T0 = tmp_T0;
295  #endif        #endif      
296              /* see if we can patch the calling TB. XXX: remove TF test */                  /* see if we can patch the calling TB. XXX: remove TF test */
297              if (T0 != 0  #ifndef RING0_HACKS
298    
299                    if (T0 != 0
300  #if defined(TARGET_I386)  #if defined(TARGET_I386)
301                  && !(env->eflags & TF_MASK)                      && !(env->eflags & TF_MASK)
302  #endif  #endif
303                  ) {                      ) {
304                  spin_lock(&tb_lock);                      spin_lock(&tb_lock);
305                  tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb);                      tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb);
306                  spin_unlock(&tb_lock);                      spin_unlock(&tb_lock);
307              }                  }
308              tc_ptr = tb->tc_ptr;  #endif
309                    tc_ptr = tb->tc_ptr;
310              /* execute the generated code */                  
311              gen_func = (void *)tc_ptr;                  /* execute the generated code */
312                    gen_func = (void *)tc_ptr;
313  #if defined(__sparc__)  #if defined(__sparc__)
314              __asm__ __volatile__("call  %0\n\t"                  __asm__ __volatile__("call      %0\n\t"
315                                   "mov   %%o7,%%i0"                                       "mov       %%o7,%%i0"
316                                   : /* no outputs */                                       : /* no outputs */
317                                   : "r" (gen_func)                                       : "r" (gen_func)
318                                   : "i0", "i1", "i2", "i3", "i4", "i5");                                       : "i0", "i1", "i2", "i3", "i4", "i5");
319  #elif defined(__arm__)  #elif defined(__arm__)
320              asm volatile ("mov pc, %0\n\t"                  asm volatile ("mov pc, %0\n\t"
321                            ".global exec_loop\n\t"                                ".global exec_loop\n\t"
322                            "exec_loop:\n\t"                                "exec_loop:\n\t"
323                            : /* no outputs */                                : /* no outputs */
324                            : "r" (gen_func)                                : "r" (gen_func)
325                            : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");                                : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
326  #else  #else
327              gen_func();                  gen_func();
328  #endif  #endif
329                }
330            } else {
331          }          }
332      }      } /* for(;;) */
333      ret = env->exception_index;  
334    
335  #if defined(TARGET_I386)  #if defined(TARGET_I386)
336      /* restore flags in standard format */      /* restore flags in standard format */
# Line 348  void cpu_x86_load_seg(CPUX86State *s, in Line 399  void cpu_x86_load_seg(CPUX86State *s, in
399          SegmentCache *sc;          SegmentCache *sc;
400          selector &= 0xffff;          selector &= 0xffff;
401          sc = &env->segs[seg_reg];          sc = &env->segs[seg_reg];
402          /* NOTE: in VM86 mode, limit and seg_32bit are never reloaded,          /* NOTE: in VM86 mode, limit and flags are never reloaded,
403             so we must load them here */             so we must load them here */
404          sc->base = (void *)(selector << 4);          sc->base = (void *)(selector << 4);
405          sc->limit = 0xffff;          sc->limit = 0xffff;
406          sc->seg_32bit = 0;          sc->flags = 0;
407          sc->selector = selector;          sc->selector = selector;
408      } else {      } else {
409          load_seg(seg_reg, selector, 0);          load_seg(seg_reg, selector, 0);
# Line 398  void cpu_x86_frstor(CPUX86State *s, uint Line 449  void cpu_x86_frstor(CPUX86State *s, uint
449  #include <signal.h>  #include <signal.h>
450  #include <sys/ucontext.h>  #include <sys/ucontext.h>
451    
452    #if defined(TARGET_I386)
453    
454  /* 'pc' is the host PC at which the exception was raised. 'address' is  /* 'pc' is the host PC at which the exception was raised. 'address' is
455     the effective address of the memory exception. 'is_write' is 1 if a     the effective address of the memory exception. 'is_write' is 1 if a
456     write caused the exception and otherwise 0'. 'old_set' is the     write caused the exception and otherwise 0'. 'old_set' is the
# Line 407  static inline int handle_cpu_signal(unsi Line 460  static inline int handle_cpu_signal(unsi
460  {  {
461      TranslationBlock *tb;      TranslationBlock *tb;
462      int ret;      int ret;
     uint32_t found_pc;  
463            
464    #ifdef RING0_HACKS
465        env = global_env; /* XXX: find a better solution */
466    #endif
467  #if defined(DEBUG_SIGNAL)  #if defined(DEBUG_SIGNAL)
468      printf("qemu: SIGSEGV pc=0x%08lx address=%08lx wr=%d oldset=0x%08lx\n",      printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
469             pc, address, is_write, *(unsigned long *)old_set);             pc, address, is_write, *(unsigned long *)old_set);
470  #endif  #endif
471      /* XXX: locking issue */      /* XXX: locking issue */
472      if (is_write && page_unprotect(address)) {      if (is_write && page_unprotect(address)) {
473          return 1;          return 1;
474      }      }
475        /* see if it is an MMU fault */
476        ret = cpu_x86_handle_mmu_fault(env, address, is_write);
477        if (ret < 0)
478            return 0; /* not an MMU fault */
479        if (ret == 0)
480            return 1; /* the MMU fault was handled without causing real CPU fault */
481        /* now we have a real cpu fault */
482      tb = tb_find_pc(pc);      tb = tb_find_pc(pc);
483      if (tb) {      if (tb) {
484          /* the PC is inside the translated code. It means that we have          /* the PC is inside the translated code. It means that we have
485             a virtual CPU fault */             a virtual CPU fault */
486          ret = cpu_search_pc(tb, &found_pc, pc);          cpu_restore_state(tb, env, pc);
487          if (ret < 0)      }
488              return 0;  #if 0
489  #if defined(TARGET_I386)      printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
490          env->eip = found_pc - tb->cs_base;             env->eip, env->cr[2], env->error_code);
491          env->cr[2] = address;  #endif
492          /* we restore the process signal mask as the sigreturn should      /* we restore the process signal mask as the sigreturn should
493             do it (XXX: use sigsetjmp) */         do it (XXX: use sigsetjmp) */
494          sigprocmask(SIG_SETMASK, old_set, NULL);      sigprocmask(SIG_SETMASK, old_set, NULL);
495          raise_exception_err(EXCP0E_PAGE, 4 | (is_write << 1));      raise_exception_err(EXCP0E_PAGE, env->error_code);
496        /* never comes here */
497        return 1;
498    }
499    
500  #elif defined(TARGET_ARM)  #elif defined(TARGET_ARM)
501          env->regs[15] = found_pc;  static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
502          /* XXX: do more */                                      int is_write, sigset_t *old_set)
503    {
504        /* XXX: do more */
505        return 0;
506    }
507  #else  #else
508  #error unsupported target CPU  #error unsupported target CPU
509  #endif  #endif
         /* never comes here */  
         return 1;  
     } else {  
         return 0;  
     }  
 }  
510    
511  #if defined(__i386__)  #if defined(__i386__)
512    
# Line 570  int cpu_signal_handler(int host_signum, Line 634  int cpu_signal_handler(int host_signum,
634    
635  #else  #else
636    
637  #error CPU specific signal handler needed  #error host CPU specific signal handler needed
638    
639  #endif  #endif

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.3

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26