From 9e01a8363627fac8dea0023f3fb4194ccefa2945 Mon Sep 17 00:00:00 2001 From: Tomas Hruby Date: Mon, 25 Oct 2010 16:21:23 +0000 Subject: [PATCH] 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. --- kernel/arch/i386/klib.S | 2 -- kernel/proc.c | 13 ++++++++++++- kernel/proc.h | 3 +++ kernel/system/do_vmctl.c | 3 +++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/kernel/arch/i386/klib.S b/kernel/arch/i386/klib.S index a2488d2fa..c60046c64 100644 --- a/kernel/arch/i386/klib.S +++ b/kernel/arch/i386/klib.S @@ -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 diff --git a/kernel/proc.c b/kernel/proc.c index 438b43c39..80c7614c1 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -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(); diff --git a/kernel/proc.h b/kernel/proc.h index 3055a0821..dfc332698 100644 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -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]) diff --git a/kernel/system/do_vmctl.c b/kernel/system/do_vmctl.c index 37f85333d..2f10157cd 100644 --- a/kernel/system/do_vmctl.c +++ b/kernel/system/do_vmctl.c @@ -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)); -- 2.44.0