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