SMP - reduced TLB flushing

- flush TLB of processes only if the page tables has been changed and
  the page tables of this process are already loaded on this cpu which
  means that there might be stale entries in TLB. Until now SMP was
  always flushing TLB to make sure everything is consistent.
This commit is contained in:
Tomas Hruby 2010-10-25 16:21:23 +00:00
parent 7f7822aebd
commit 9e01a83636
4 changed files with 18 additions and 3 deletions

View file

@ -803,11 +803,9 @@ ENTRY(__switch_address_space)
* test if the cr3 is loaded with the current value to avoid unnecessary
* TLB flushes
*/
#ifndef CONFIG_SMP
mov %cr3, %ecx
cmp %ecx, %eax
je 0f
#endif
mov %eax, %cr3
/* get ptproc */
mov 8(%esp), %eax

View file

@ -242,6 +242,9 @@ PUBLIC void switch_to_user(void)
* to be scheduled again.
*/
struct proc * p;
#ifdef CONFIG_SMP
int tlb_must_refresh = 0;
#endif
p = get_cpulocal_var(proc_ptr);
/*
@ -279,6 +282,10 @@ not_runnable_pick_new:
/* update the global variable */
get_cpulocal_var(proc_ptr) = p;
#ifdef CONFIG_SMP
if (p->p_misc_flags & MF_FLUSH_TLB && get_cpulocal_var(ptproc) == p)
tlb_must_refresh = 1;
#endif
switch_address_space(p);
check_misc_flags:
@ -385,7 +392,11 @@ check_misc_flags:
assert(!(p->p_misc_flags & MF_FULLVM) || p->p_seg.p_cr3 != 0);
#ifdef CONFIG_SMP
refresh_tlb();
if (p->p_misc_flags & MF_FLUSH_TLB) {
if (tlb_must_refresh)
refresh_tlb();
p->p_misc_flags &= ~MF_FLUSH_TLB;
}
#endif
restart_local_timer();

View file

@ -242,6 +242,9 @@ struct proc {
#define MF_SENDING_FROM_KERNEL 0x2000 /* message of this process is from kernel */
#define MF_CONTEXT_SET 0x4000 /* don't touch context */
#define MF_SPROF_SEEN 0x8000 /* profiling has seen this process */
#define MF_FLUSH_TLB 0x10000 /* if set, TLB must be flushed before letting
this process run again. Currently it only
applies to SMP */
/* Magic process table addresses. */
#define BEG_PROC_ADDR (&proc[0])

View file

@ -148,6 +148,9 @@ PUBLIC int do_vmctl(struct proc * caller, message * m_ptr)
} else
#endif
RTS_SET(p, RTS_VMINHIBIT);
#if CONFIG_SMP
p->p_misc_flags |= MF_FLUSH_TLB;
#endif
return OK;
case VMCTL_VMINHIBIT_CLEAR:
assert(RTS_ISSET(p, RTS_VMINHIBIT));