Commit 1376847f9f003a5a1c7f62a1425352d397348ba7
1 parent
17348a7f
support for new TLB handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@513 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
47 additions
and
2 deletions
cpu-exec.c
... | ... | @@ -262,7 +262,42 @@ int cpu_exec(CPUState *env1) |
262 | 262 | tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base, |
263 | 263 | flags); |
264 | 264 | if (!tb) { |
265 | + TranslationBlock **ptb1; | |
266 | + unsigned int h; | |
267 | + target_ulong phys_pc, phys_page1, phys_page2, virt_page2; | |
268 | + | |
269 | + | |
265 | 270 | spin_lock(&tb_lock); |
271 | + | |
272 | + tb_invalidated_flag = 0; | |
273 | + | |
274 | + /* find translated block using physical mappings */ | |
275 | + phys_pc = get_phys_addr_code(env, (unsigned long)pc); | |
276 | + phys_page1 = phys_pc & TARGET_PAGE_MASK; | |
277 | + phys_page2 = -1; | |
278 | + h = tb_phys_hash_func(phys_pc); | |
279 | + ptb1 = &tb_phys_hash[h]; | |
280 | + for(;;) { | |
281 | + tb = *ptb1; | |
282 | + if (!tb) | |
283 | + goto not_found; | |
284 | + if (tb->pc == (unsigned long)pc && | |
285 | + tb->page_addr[0] == phys_page1 && | |
286 | + tb->cs_base == (unsigned long)cs_base && | |
287 | + tb->flags == flags) { | |
288 | + /* check next page if needed */ | |
289 | + virt_page2 = ((unsigned long)pc + tb->size - 1) & TARGET_PAGE_MASK; | |
290 | + if (((unsigned long)pc & TARGET_PAGE_MASK) != virt_page2) { | |
291 | + phys_page2 = get_phys_addr_code(env, virt_page2); | |
292 | + if (tb->page_addr[1] == phys_page2) | |
293 | + goto found; | |
294 | + } else { | |
295 | + goto found; | |
296 | + } | |
297 | + } | |
298 | + ptb1 = &tb->phys_hash_next; | |
299 | + } | |
300 | + not_found: | |
266 | 301 | /* if no translated code available, then translate it now */ |
267 | 302 | tb = tb_alloc((unsigned long)pc); |
268 | 303 | if (!tb) { |
... | ... | @@ -278,8 +313,18 @@ int cpu_exec(CPUState *env1) |
278 | 313 | tb->tc_ptr = tc_ptr; |
279 | 314 | tb->cs_base = (unsigned long)cs_base; |
280 | 315 | tb->flags = flags; |
281 | - tb_invalidated_flag = 0; | |
282 | 316 | cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size); |
317 | + code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); | |
318 | + | |
319 | + /* check next page if needed */ | |
320 | + virt_page2 = ((unsigned long)pc + tb->size - 1) & TARGET_PAGE_MASK; | |
321 | + phys_page2 = -1; | |
322 | + if (((unsigned long)pc & TARGET_PAGE_MASK) != virt_page2) { | |
323 | + phys_page2 = get_phys_addr_code(env, virt_page2); | |
324 | + } | |
325 | + tb_link_phys(tb, phys_pc, phys_page2); | |
326 | + | |
327 | + found: | |
283 | 328 | if (tb_invalidated_flag) { |
284 | 329 | /* as some TB could have been invalidated because |
285 | 330 | of memory exceptions while generating the code, we |
... | ... | @@ -289,10 +334,10 @@ int cpu_exec(CPUState *env1) |
289 | 334 | ptb = &(*ptb)->hash_next; |
290 | 335 | T0 = 0; |
291 | 336 | } |
337 | + /* we add the TB in the virtual pc hash table */ | |
292 | 338 | *ptb = tb; |
293 | 339 | tb->hash_next = NULL; |
294 | 340 | tb_link(tb); |
295 | - code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); | |
296 | 341 | spin_unlock(&tb_lock); |
297 | 342 | } |
298 | 343 | #ifdef DEBUG_EXEC | ... | ... |