]> Zhao Yanbai Git Server - minix.git/commitdiff
SMP - reduced TLB flushing
authorTomas Hruby <tom@minix3.org>
Mon, 25 Oct 2010 16:21:23 +0000 (16:21 +0000)
committerTomas Hruby <tom@minix3.org>
Mon, 25 Oct 2010 16:21:23 +0000 (16:21 +0000)
- 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
kernel/proc.c
kernel/proc.h
kernel/system/do_vmctl.c

index a2488d2fac31362b1b81873b7a76310bff471ef9..c60046c646d78f9e370a97e246b7f8e115208ece 100644 (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
index 438b43c393a311ca8cc324d83adb826bd4d61853..80c7614c1e886239e4e3129f467ac00193c8a12f 100644 (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();
index 3055a0821dab375b71353a6892e400d4c188769b..dfc3326987f4e7148cb4a74f0730a978da3611d1 100644 (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])
index 37f85333d2867a27e9e841c7e10dfcf4b1baea32..2f10157cdaf4977f9ab92f0f2d6165a57d873aa7 100644 (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));