Commit b56dad1c7bde3bdf53895fe6eff13bfb47e3ae9e
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; |