Revision a513fe19 exec-i386.c
b/exec-i386.c | ||
---|---|---|
39 | 39 |
spin_unlock(&global_cpu_lock); |
40 | 40 |
} |
41 | 41 |
|
42 |
/* exception support */ |
|
43 |
/* NOTE: not static to force relocation generation by GCC */ |
|
44 |
void raise_exception_err(int exception_index, int error_code) |
|
42 |
void cpu_loop_exit(void) |
|
45 | 43 |
{ |
46 | 44 |
/* NOTE: the register at this point must be saved by hand because |
47 | 45 |
longjmp restore them */ |
... | ... | |
76 | 74 |
#ifdef reg_EDI |
77 | 75 |
env->regs[R_EDI] = EDI; |
78 | 76 |
#endif |
79 |
env->exception_index = exception_index; |
|
80 |
env->error_code = error_code; |
|
81 | 77 |
longjmp(env->jmp_env, 1); |
82 | 78 |
} |
83 | 79 |
|
84 |
/* short cut if error_code is 0 or not present */ |
|
85 |
void raise_exception(int exception_index) |
|
86 |
{ |
|
87 |
raise_exception_err(exception_index, 0); |
|
88 |
} |
|
89 |
|
|
90 | 80 |
int cpu_x86_exec(CPUX86State *env1) |
91 | 81 |
{ |
92 | 82 |
int saved_T0, saved_T1, saved_A0; |
... | ... | |
115 | 105 |
#ifdef reg_EDI |
116 | 106 |
int saved_EDI; |
117 | 107 |
#endif |
118 |
int code_gen_size, ret, code_size;
|
|
108 |
int code_gen_size, ret; |
|
119 | 109 |
void (*gen_func)(void); |
120 | 110 |
TranslationBlock *tb, **ptb; |
121 | 111 |
uint8_t *tc_ptr, *cs_base, *pc; |
... | ... | |
172 | 162 |
T0 = 0; /* force lookup of first TB */ |
173 | 163 |
for(;;) { |
174 | 164 |
if (env->interrupt_request) { |
175 |
raise_exception(EXCP_INTERRUPT); |
|
165 |
env->exception_index = EXCP_INTERRUPT; |
|
166 |
cpu_loop_exit(); |
|
176 | 167 |
} |
177 | 168 |
#ifdef DEBUG_EXEC |
178 | 169 |
if (loglevel) { |
... | ... | |
226 | 217 |
} |
227 | 218 |
tc_ptr = code_gen_ptr; |
228 | 219 |
tb->tc_ptr = tc_ptr; |
229 |
ret = cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE,
|
|
230 |
&code_gen_size, pc, cs_base, flags,
|
|
231 |
&code_size, tb);
|
|
220 |
tb->cs_base = (unsigned long)cs_base;
|
|
221 |
tb->flags = flags;
|
|
222 |
ret = cpu_x86_gen_code(tb, CODE_GEN_MAX_SIZE, &code_gen_size);
|
|
232 | 223 |
/* if invalid instruction, signal it */ |
233 | 224 |
if (ret != 0) { |
234 | 225 |
/* NOTE: the tb is allocated but not linked, so we |
... | ... | |
237 | 228 |
raise_exception(EXCP06_ILLOP); |
238 | 229 |
} |
239 | 230 |
*ptb = tb; |
240 |
tb->size = code_size; |
|
241 |
tb->cs_base = (unsigned long)cs_base; |
|
242 |
tb->flags = flags; |
|
243 | 231 |
tb->hash_next = NULL; |
244 | 232 |
tb_link(tb); |
245 | 233 |
code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); |
... | ... | |
323 | 311 |
|
324 | 312 |
saved_env = env; |
325 | 313 |
env = s; |
326 |
load_seg(seg_reg, selector); |
|
314 |
if (env->eflags & VM_MASK) { |
|
315 |
SegmentCache *sc; |
|
316 |
selector &= 0xffff; |
|
317 |
sc = &env->seg_cache[seg_reg]; |
|
318 |
/* NOTE: in VM86 mode, limit and seg_32bit are never reloaded, |
|
319 |
so we must load them here */ |
|
320 |
sc->base = (void *)(selector << 4); |
|
321 |
sc->limit = 0xffff; |
|
322 |
sc->seg_32bit = 0; |
|
323 |
env->segs[seg_reg] = selector; |
|
324 |
} else { |
|
325 |
load_seg(seg_reg, selector, 0); |
|
326 |
} |
|
327 | 327 |
env = saved_env; |
328 | 328 |
} |
329 | 329 |
|
... | ... | |
346 | 346 |
static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
347 | 347 |
int is_write, sigset_t *old_set) |
348 | 348 |
{ |
349 |
TranslationBlock *tb; |
|
350 |
int ret; |
|
351 |
uint32_t found_pc; |
|
352 |
|
|
349 | 353 |
#if defined(DEBUG_SIGNAL) |
350 | 354 |
printf("qemu: SIGSEGV pc=0x%08lx address=%08lx wr=%d oldset=0x%08lx\n", |
351 | 355 |
pc, address, is_write, *(unsigned long *)old_set); |
... | ... | |
354 | 358 |
if (is_write && page_unprotect(address)) { |
355 | 359 |
return 1; |
356 | 360 |
} |
357 |
if (pc >= (unsigned long)code_gen_buffer &&
|
|
358 |
pc < (unsigned long)code_gen_buffer + CODE_GEN_BUFFER_SIZE) {
|
|
361 |
tb = tb_find_pc(pc);
|
|
362 |
if (tb) {
|
|
359 | 363 |
/* the PC is inside the translated code. It means that we have |
360 | 364 |
a virtual CPU fault */ |
365 |
ret = cpu_x86_search_pc(tb, &found_pc, pc); |
|
366 |
if (ret < 0) |
|
367 |
return 0; |
|
368 |
env->eip = found_pc - tb->cs_base; |
|
369 |
env->cr2 = address; |
|
361 | 370 |
/* we restore the process signal mask as the sigreturn should |
362 |
do it */ |
|
371 |
do it (XXX: use sigsetjmp) */
|
|
363 | 372 |
sigprocmask(SIG_SETMASK, old_set, NULL); |
364 |
/* XXX: need to compute virtual pc position by retranslating |
|
365 |
code. The rest of the CPU state should be correct. */ |
|
366 |
env->cr2 = address; |
|
367 | 373 |
raise_exception_err(EXCP0E_PAGE, 4 | (is_write << 1)); |
368 | 374 |
/* never comes here */ |
369 | 375 |
return 1; |
Also available in: Unified diff