On 31 May 2012 10:21, 陳韋任 (Wei-Ren Chen) <che...@iis.sinica.edu.tw> wrote: > void tlb_flush_page(CPUArchState *env, target_ulong addr) > { > if ((addr & env->tlb_flush_mask) == env->tlb_flush_addr) { > tlb_flush(env, 1); --- (1) > return; > }
This case (see the comments) is only for handling "large pages". tlb_flush_addr/tlb_flush_mask track the range covered by large pages, so that if we attempt to flush a page for an address in that region we do a full tlb flush instead. (cf tlb_add_large_page()). However the normal case is for standard sized pages: > ... snip ... > > addr &= TARGET_PAGE_MASK; > i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); > for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) { > tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr); > } > > tb_flush_jmp_cache(env, addr); ...which as you see is only flushing the tlb/tb entries corresponding to the specified page address. > The comment of tlb_flush (1) says, > > QEMU doesn't currently implement a global/not-global flag > for tlb entries, at the moment tlb_flush() will also flush all > tlb entries in the flush_global == false case. This is something different. Most CPUs support some sort of concept of TLB entries which are marked as specific to a particular OS process, so that the OS can avoid having to do a full TLB flush when it does a context switch. The "global" terminology is a reference to the x86 specific flavour of this, and the QEMU API currently reflects that x86ism. However we don't actually implement the global/non-global distinction, hence this comment (it's always safe to flush more entries than you're asked to flush). -- PMM