Commit 2ee4aed86ff2ba38a0e1846de18a9aec38d73015
1 parent
df628ff1
moved invalidate_tlb() to helper.c as a work around for gcc 3.2.2 bug - suppress…
…ed invalid tb_invalidate_page_range() calls git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2287 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
45 additions
and
45 deletions
target-mips/exec.h
| ... | ... | @@ -149,6 +149,7 @@ void dump_sc (void); |
| 149 | 149 | int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, |
| 150 | 150 | int is_user, int is_softmmu); |
| 151 | 151 | void do_interrupt (CPUState *env); |
| 152 | +void invalidate_tlb (CPUState *env, int idx, int use_extra); | |
| 152 | 153 | |
| 153 | 154 | void cpu_loop_exit(void); |
| 154 | 155 | void do_raise_exception_err (uint32_t exception, int error_code); | ... | ... |
target-mips/helper.c
| ... | ... | @@ -416,3 +416,44 @@ void do_interrupt (CPUState *env) |
| 416 | 416 | env->exception_index = EXCP_NONE; |
| 417 | 417 | } |
| 418 | 418 | #endif /* !defined(CONFIG_USER_ONLY) */ |
| 419 | + | |
| 420 | +void invalidate_tlb (CPUState *env, int idx, int use_extra) | |
| 421 | +{ | |
| 422 | + tlb_t *tlb; | |
| 423 | + target_ulong addr; | |
| 424 | + uint8_t ASID; | |
| 425 | + | |
| 426 | + ASID = env->CP0_EntryHi & 0xFF; | |
| 427 | + | |
| 428 | + tlb = &env->tlb[idx]; | |
| 429 | + /* The qemu TLB is flushed then the ASID changes, so no need to | |
| 430 | + flush these entries again. */ | |
| 431 | + if (tlb->G == 0 && tlb->ASID != ASID) { | |
| 432 | + return; | |
| 433 | + } | |
| 434 | + | |
| 435 | + if (use_extra && env->tlb_in_use < MIPS_TLB_MAX) { | |
| 436 | + /* For tlbwr, we can shadow the discarded entry into | |
| 437 | + a new (fake) TLB entry, as long as the guest can not | |
| 438 | + tell that it's there. */ | |
| 439 | + env->tlb[env->tlb_in_use] = *tlb; | |
| 440 | + env->tlb_in_use++; | |
| 441 | + return; | |
| 442 | + } | |
| 443 | + | |
| 444 | + if (tlb->V0) { | |
| 445 | + addr = tlb->VPN; | |
| 446 | + while (addr < tlb->end) { | |
| 447 | + tlb_flush_page (env, addr); | |
| 448 | + addr += TARGET_PAGE_SIZE; | |
| 449 | + } | |
| 450 | + } | |
| 451 | + if (tlb->V1) { | |
| 452 | + addr = tlb->end; | |
| 453 | + while (addr < tlb->end2) { | |
| 454 | + tlb_flush_page (env, addr); | |
| 455 | + addr += TARGET_PAGE_SIZE; | |
| 456 | + } | |
| 457 | + } | |
| 458 | +} | |
| 459 | + | ... | ... |
target-mips/op_helper.c
| ... | ... | @@ -376,53 +376,11 @@ void cpu_mips_tlb_flush (CPUState *env, int flush_global) |
| 376 | 376 | env->tlb_in_use = MIPS_TLB_NB; |
| 377 | 377 | } |
| 378 | 378 | |
| 379 | -static void invalidate_tlb (int idx, int use_extra) | |
| 380 | -{ | |
| 381 | - tlb_t *tlb; | |
| 382 | - target_ulong addr; | |
| 383 | - uint8_t ASID; | |
| 384 | - | |
| 385 | - ASID = env->CP0_EntryHi & 0xFF; | |
| 386 | - | |
| 387 | - tlb = &env->tlb[idx]; | |
| 388 | - /* The qemu TLB is flushed then the ASID changes, so no need to | |
| 389 | - flush these entries again. */ | |
| 390 | - if (tlb->G == 0 && tlb->ASID != ASID) { | |
| 391 | - return; | |
| 392 | - } | |
| 393 | - | |
| 394 | - if (use_extra && env->tlb_in_use < MIPS_TLB_MAX) { | |
| 395 | - /* For tlbwr, we can shadow the discarded entry into | |
| 396 | - a new (fake) TLB entry, as long as the guest can not | |
| 397 | - tell that it's there. */ | |
| 398 | - env->tlb[env->tlb_in_use] = *tlb; | |
| 399 | - env->tlb_in_use++; | |
| 400 | - return; | |
| 401 | - } | |
| 402 | - | |
| 403 | - if (tlb->V0) { | |
| 404 | - tb_invalidate_page_range(tlb->PFN[0], tlb->end - tlb->VPN); | |
| 405 | - addr = tlb->VPN; | |
| 406 | - while (addr < tlb->end) { | |
| 407 | - tlb_flush_page (env, addr); | |
| 408 | - addr += TARGET_PAGE_SIZE; | |
| 409 | - } | |
| 410 | - } | |
| 411 | - if (tlb->V1) { | |
| 412 | - tb_invalidate_page_range(tlb->PFN[1], tlb->end2 - tlb->end); | |
| 413 | - addr = tlb->end; | |
| 414 | - while (addr < tlb->end2) { | |
| 415 | - tlb_flush_page (env, addr); | |
| 416 | - addr += TARGET_PAGE_SIZE; | |
| 417 | - } | |
| 418 | - } | |
| 419 | -} | |
| 420 | - | |
| 421 | 379 | static void mips_tlb_flush_extra (CPUState *env, int first) |
| 422 | 380 | { |
| 423 | 381 | /* Discard entries from env->tlb[first] onwards. */ |
| 424 | 382 | while (env->tlb_in_use > first) { |
| 425 | - invalidate_tlb(--env->tlb_in_use, 0); | |
| 383 | + invalidate_tlb(env, --env->tlb_in_use, 0); | |
| 426 | 384 | } |
| 427 | 385 | } |
| 428 | 386 | |
| ... | ... | @@ -459,7 +417,7 @@ void do_tlbwi (void) |
| 459 | 417 | |
| 460 | 418 | /* Wildly undefined effects for CP0_index containing a too high value and |
| 461 | 419 | MIPS_TLB_NB not being a power of two. But so does real silicon. */ |
| 462 | - invalidate_tlb(env->CP0_index & (MIPS_TLB_NB - 1), 0); | |
| 420 | + invalidate_tlb(env, env->CP0_index & (MIPS_TLB_NB - 1), 0); | |
| 463 | 421 | fill_tlb(env->CP0_index & (MIPS_TLB_NB - 1)); |
| 464 | 422 | } |
| 465 | 423 | |
| ... | ... | @@ -467,7 +425,7 @@ void do_tlbwr (void) |
| 467 | 425 | { |
| 468 | 426 | int r = cpu_mips_get_random(env); |
| 469 | 427 | |
| 470 | - invalidate_tlb(r, 1); | |
| 428 | + invalidate_tlb(env, r, 1); | |
| 471 | 429 | fill_tlb(r); |
| 472 | 430 | } |
| 473 | 431 | ... | ... |