You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
qubes-linux-kernel/patches.xen/xen-x86-exit-mmap

74 lines
2.0 KiB

Subject: be more aggressive about de-activating mm-s under destruction
From: jbeulich@novell.com
Patch-mainline: obsolete
... by not only handling the current task on the CPU arch_exit_mmap()
gets executed on, but also forcing remote CPUs to do so.
--- head-2010-04-15.orig/arch/x86/mm/pgtable-xen.c 2010-04-15 11:47:53.000000000 +0200
+++ head-2010-04-15/arch/x86/mm/pgtable-xen.c 2010-04-15 11:48:29.000000000 +0200
@@ -1,6 +1,7 @@
#include <linux/mm.h>
#include <linux/gfp.h>
#include <linux/module.h>
+#include <linux/smp.h>
#include <xen/features.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
@@ -438,27 +439,44 @@ void arch_dup_mmap(struct mm_struct *old
mm_pin(mm);
}
-void arch_exit_mmap(struct mm_struct *mm)
+/*
+ * We aggressively remove defunct pgd from cr3. We execute unmap_vmas() *much*
+ * faster this way, as no hypercalls are needed for the page table updates.
+ */
+static void leave_active_mm(struct task_struct *tsk, struct mm_struct *mm)
+ __releases(tsk->alloc_lock)
{
- struct task_struct *tsk = current;
-
- task_lock(tsk);
-
- /*
- * We aggressively remove defunct pgd from cr3. We execute unmap_vmas()
- * *much* faster this way, as no tlb flushes means bigger wrpt batches.
- */
if (tsk->active_mm == mm) {
tsk->active_mm = &init_mm;
atomic_inc(&init_mm.mm_count);
switch_mm(mm, &init_mm, tsk);
- atomic_dec(&mm->mm_count);
- BUG_ON(atomic_read(&mm->mm_count) == 0);
+ if (atomic_dec_and_test(&mm->mm_count))
+ BUG();
}
task_unlock(tsk);
+}
+
+static void _leave_active_mm(void *mm)
+{
+ struct task_struct *tsk = current;
+
+ if (spin_trylock(&tsk->alloc_lock))
+ leave_active_mm(tsk, mm);
+}
+
+void arch_exit_mmap(struct mm_struct *mm)
+{
+ struct task_struct *tsk = current;
+
+ task_lock(tsk);
+ leave_active_mm(tsk, mm);
+
+ preempt_disable();
+ smp_call_function_many(mm_cpumask(mm), _leave_active_mm, mm, 1);
+ preempt_enable();
if (PagePinned(virt_to_page(mm->pgd))
&& atomic_read(&mm->mm_count) == 1