Commit b56dad1c7bde3bdf53895fe6eff13bfb47e3ae9e

Authored by bellard
1 parent 9ba5695c

added raise_exception_err() - added cr2 update


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@126 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 34 additions and 11 deletions
exec-i386.c
@@ -149,7 +149,7 @@ void cpu_unlock(void) @@ -149,7 +149,7 @@ void cpu_unlock(void)
149 149
150 /* exception support */ 150 /* exception support */
151 /* NOTE: not static to force relocation generation by GCC */ 151 /* NOTE: not static to force relocation generation by GCC */
152 -void raise_exception(int exception_index) 152 +void raise_exception_err(int exception_index, int error_code)
153 { 153 {
154 /* NOTE: the register at this point must be saved by hand because 154 /* NOTE: the register at this point must be saved by hand because
155 longjmp restore them */ 155 longjmp restore them */
@@ -178,9 +178,16 @@ void raise_exception(int exception_index) @@ -178,9 +178,16 @@ void raise_exception(int exception_index)
178 env->regs[R_EDI] = EDI; 178 env->regs[R_EDI] = EDI;
179 #endif 179 #endif
180 env->exception_index = exception_index; 180 env->exception_index = exception_index;
  181 + env->error_code = error_code;
181 longjmp(env->jmp_env, 1); 182 longjmp(env->jmp_env, 1);
182 } 183 }
183 184
  185 +/* short cut if error_code is 0 or not present */
  186 +void raise_exception(int exception_index)
  187 +{
  188 + raise_exception_err(exception_index, 0);
  189 +}
  190 +
184 #if defined(DEBUG_EXEC) 191 #if defined(DEBUG_EXEC)
185 static const char *cc_op_str[] = { 192 static const char *cc_op_str[] = {
186 "DYNAMIC", 193 "DYNAMIC",
@@ -218,8 +225,13 @@ static const char *cc_op_str[] = { @@ -218,8 +225,13 @@ static const char *cc_op_str[] = {
218 static void cpu_x86_dump_state(FILE *f) 225 static void cpu_x86_dump_state(FILE *f)
219 { 226 {
220 int eflags; 227 int eflags;
  228 + char cc_op_name[32];
221 eflags = cc_table[CC_OP].compute_all(); 229 eflags = cc_table[CC_OP].compute_all();
222 eflags |= (DF & DF_MASK); 230 eflags |= (DF & DF_MASK);
  231 + if ((unsigned)env->cc_op < CC_OP_NB)
  232 + strcpy(cc_op_name, cc_op_str[env->cc_op]);
  233 + else
  234 + snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
223 fprintf(f, 235 fprintf(f,
224 "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n" 236 "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"
225 "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n" 237 "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"
@@ -227,7 +239,7 @@ static void cpu_x86_dump_state(FILE *f) @@ -227,7 +239,7 @@ static void cpu_x86_dump_state(FILE *f)
227 "EIP=%08x\n", 239 "EIP=%08x\n",
228 env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 240 env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],
229 env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 241 env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP],
230 - env->cc_src, env->cc_dst, cc_op_str[env->cc_op], 242 + env->cc_src, env->cc_dst, cc_op_name,
231 eflags & DF_MASK ? 'D' : '-', 243 eflags & DF_MASK ? 'D' : '-',
232 eflags & CC_O ? 'O' : '-', 244 eflags & CC_O ? 'O' : '-',
233 eflags & CC_S ? 'S' : '-', 245 eflags & CC_S ? 'S' : '-',
@@ -280,14 +292,18 @@ static inline TranslationBlock *tb_find(TranslationBlock ***pptb, @@ -280,14 +292,18 @@ static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
280 292
281 h = pc & (CODE_GEN_HASH_SIZE - 1); 293 h = pc & (CODE_GEN_HASH_SIZE - 1);
282 ptb = &tb_hash[h]; 294 ptb = &tb_hash[h];
283 - for(;;) {  
284 - tb = *ptb;  
285 - if (!tb)  
286 - break;  
287 - if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags) 295 +#if 0
  296 + /* XXX: hack to handle 16 bit modyfing code */
  297 + if (flags & (1 << GEN_FLAG_CODE32_SHIFT))
  298 +#endif
  299 + for(;;) {
  300 + tb = *ptb;
  301 + if (!tb)
  302 + break;
  303 + if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags)
288 return tb; 304 return tb;
289 - ptb = &tb->hash_next;  
290 - } 305 + ptb = &tb->hash_next;
  306 + }
291 *pptb = ptb; 307 *pptb = ptb;
292 return NULL; 308 return NULL;
293 } 309 }
@@ -404,6 +420,8 @@ int cpu_x86_exec(CPUX86State *env1) @@ -404,6 +420,8 @@ int cpu_x86_exec(CPUX86State *env1)
404 (unsigned long)env->seg_cache[R_SS].base) != 0) << 420 (unsigned long)env->seg_cache[R_SS].base) != 0) <<
405 GEN_FLAG_ADDSEG_SHIFT; 421 GEN_FLAG_ADDSEG_SHIFT;
406 flags |= (env->eflags & VM_MASK) >> (17 - GEN_FLAG_VM_SHIFT); 422 flags |= (env->eflags & VM_MASK) >> (17 - GEN_FLAG_VM_SHIFT);
  423 + flags |= (env->eflags & IOPL_MASK) >> (12 - GEN_FLAG_IOPL_SHIFT);
  424 + flags |= (env->segs[R_CS] & 3) << GEN_FLAG_CPL_SHIFT;
407 cs_base = env->seg_cache[R_CS].base; 425 cs_base = env->seg_cache[R_CS].base;
408 pc = cs_base + env->eip; 426 pc = cs_base + env->eip;
409 tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base, 427 tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base,
@@ -508,7 +526,10 @@ void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector) @@ -508,7 +526,10 @@ void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
508 #include <signal.h> 526 #include <signal.h>
509 #include <sys/ucontext.h> 527 #include <sys/ucontext.h>
510 528
  529 +/* 'pc' is the host PC at which the exception was raised. 'address' is
  530 + the effective address of the memory exception */
511 static inline int handle_cpu_signal(unsigned long pc, 531 static inline int handle_cpu_signal(unsigned long pc,
  532 + unsigned long address,
512 sigset_t *old_set) 533 sigset_t *old_set)
513 { 534 {
514 #ifdef DEBUG_SIGNAL 535 #ifdef DEBUG_SIGNAL
@@ -524,7 +545,9 @@ static inline int handle_cpu_signal(unsigned long pc, @@ -524,7 +545,9 @@ static inline int handle_cpu_signal(unsigned long pc,
524 sigprocmask(SIG_SETMASK, old_set, NULL); 545 sigprocmask(SIG_SETMASK, old_set, NULL);
525 /* XXX: need to compute virtual pc position by retranslating 546 /* XXX: need to compute virtual pc position by retranslating
526 code. The rest of the CPU state should be correct. */ 547 code. The rest of the CPU state should be correct. */
527 - raise_exception(EXCP0D_GPF); 548 + env->cr2 = address;
  549 + /* XXX: more precise exception code */
  550 + raise_exception_err(EXCP0E_PAGE, 4);
528 /* never comes here */ 551 /* never comes here */
529 return 1; 552 return 1;
530 } else { 553 } else {
@@ -546,7 +569,7 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, @@ -546,7 +569,7 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
546 #endif 569 #endif
547 pc = uc->uc_mcontext.gregs[REG_EIP]; 570 pc = uc->uc_mcontext.gregs[REG_EIP];
548 pold_set = &uc->uc_sigmask; 571 pold_set = &uc->uc_sigmask;
549 - return handle_cpu_signal(pc, pold_set); 572 + return handle_cpu_signal(pc, (unsigned long)info->si_addr, pold_set);
550 #else 573 #else
551 #warning No CPU specific signal handler: cannot handle target SIGSEGV events 574 #warning No CPU specific signal handler: cannot handle target SIGSEGV events
552 return 0; 575 return 0;