- 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.
* 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
* to be scheduled again.
*/
struct proc * p;
+#ifdef CONFIG_SMP
+ int tlb_must_refresh = 0;
+#endif
p = get_cpulocal_var(proc_ptr);
/*
/* 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:
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();
#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])
} 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));