aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/cachetlb.txt2
-rw-r--r--arch/x86/kernel/tboot.c1
-rw-r--r--include/linux/mm_types.h9
-rw-r--r--include/linux/sched.h1
-rw-r--r--init/main.c2
-rw-r--r--kernel/fork.c37
-rw-r--r--mm/init-mm.c1
7 files changed, 44 insertions, 9 deletions
diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt
index 9164ae3b83bc..9b728dc17535 100644
--- a/Documentation/cachetlb.txt
+++ b/Documentation/cachetlb.txt
@@ -16,7 +16,7 @@ on all processors in the system. Don't let this scare you into
16thinking SMP cache/tlb flushing must be so inefficient, this is in 16thinking SMP cache/tlb flushing must be so inefficient, this is in
17fact an area where many optimizations are possible. For example, 17fact an area where many optimizations are possible. For example,
18if it can be proven that a user address space has never executed 18if it can be proven that a user address space has never executed
19on a cpu (see vma->cpu_vm_mask), one need not perform a flush 19on a cpu (see mm_cpumask()), one need not perform a flush
20for this address space on that cpu. 20for this address space on that cpu.
21 21
22First, the TLB flushing interfaces, since they are the simplest. The 22First, the TLB flushing interfaces, since they are the simplest. The
diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c
index 998e972f3b1a..30ac65df7d4e 100644
--- a/arch/x86/kernel/tboot.c
+++ b/arch/x86/kernel/tboot.c
@@ -110,7 +110,6 @@ static struct mm_struct tboot_mm = {
110 .mmap_sem = __RWSEM_INITIALIZER(init_mm.mmap_sem), 110 .mmap_sem = __RWSEM_INITIALIZER(init_mm.mmap_sem),
111 .page_table_lock = __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock), 111 .page_table_lock = __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock),
112 .mmlist = LIST_HEAD_INIT(init_mm.mmlist), 112 .mmlist = LIST_HEAD_INIT(init_mm.mmlist),
113 .cpu_vm_mask = CPU_MASK_ALL,
114}; 113};
115 114
116static inline void switch_to_tboot_pt(void) 115static inline void switch_to_tboot_pt(void)
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 201998e5b530..c2f9ea7922f4 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -265,8 +265,6 @@ struct mm_struct {
265 265
266 struct linux_binfmt *binfmt; 266 struct linux_binfmt *binfmt;
267 267
268 cpumask_t cpu_vm_mask;
269
270 /* Architecture-specific MM context */ 268 /* Architecture-specific MM context */
271 mm_context_t context; 269 mm_context_t context;
272 270
@@ -316,9 +314,14 @@ struct mm_struct {
316#ifdef CONFIG_TRANSPARENT_HUGEPAGE 314#ifdef CONFIG_TRANSPARENT_HUGEPAGE
317 pgtable_t pmd_huge_pte; /* protected by page_table_lock */ 315 pgtable_t pmd_huge_pte; /* protected by page_table_lock */
318#endif 316#endif
317
318 cpumask_var_t cpu_vm_mask_var;
319}; 319};
320 320
321/* Future-safe accessor for struct mm_struct's cpu_vm_mask. */ 321/* Future-safe accessor for struct mm_struct's cpu_vm_mask. */
322#define mm_cpumask(mm) (&(mm)->cpu_vm_mask) 322static inline cpumask_t *mm_cpumask(struct mm_struct *mm)
323{
324 return mm->cpu_vm_mask_var;
325}
323 326
324#endif /* _LINUX_MM_TYPES_H */ 327#endif /* _LINUX_MM_TYPES_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 44b8faaac7c0..f18300eddfcb 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2176,6 +2176,7 @@ static inline void mmdrop(struct mm_struct * mm)
2176 if (unlikely(atomic_dec_and_test(&mm->mm_count))) 2176 if (unlikely(atomic_dec_and_test(&mm->mm_count)))
2177 __mmdrop(mm); 2177 __mmdrop(mm);
2178} 2178}
2179extern int mm_init_cpumask(struct mm_struct *mm, struct mm_struct *oldmm);
2179 2180
2180/* mmput gets rid of the mappings and all user-space */ 2181/* mmput gets rid of the mappings and all user-space */
2181extern void mmput(struct mm_struct *); 2182extern void mmput(struct mm_struct *);
diff --git a/init/main.c b/init/main.c
index 48df882d51d2..22da33918aef 100644
--- a/init/main.c
+++ b/init/main.c
@@ -509,6 +509,8 @@ asmlinkage void __init start_kernel(void)
509 sort_main_extable(); 509 sort_main_extable();
510 trap_init(); 510 trap_init();
511 mm_init(); 511 mm_init();
512 BUG_ON(mm_init_cpumask(&init_mm, 0));
513
512 /* 514 /*
513 * Set up the scheduler prior starting any interrupts (such as the 515 * Set up the scheduler prior starting any interrupts (such as the
514 * timer interrupt). Full topology setup happens at smp_init() 516 * timer interrupt). Full topology setup happens at smp_init()
diff --git a/kernel/fork.c b/kernel/fork.c
index 927692734bcf..8e7e135d0817 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -485,6 +485,20 @@ static void mm_init_aio(struct mm_struct *mm)
485#endif 485#endif
486} 486}
487 487
488int mm_init_cpumask(struct mm_struct *mm, struct mm_struct *oldmm)
489{
490#ifdef CONFIG_CPUMASK_OFFSTACK
491 if (!alloc_cpumask_var(&mm->cpu_vm_mask_var, GFP_KERNEL))
492 return -ENOMEM;
493
494 if (oldmm)
495 cpumask_copy(mm_cpumask(mm), mm_cpumask(oldmm));
496 else
497 memset(mm_cpumask(mm), 0, cpumask_size());
498#endif
499 return 0;
500}
501
488static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p) 502static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
489{ 503{
490 atomic_set(&mm->mm_users, 1); 504 atomic_set(&mm->mm_users, 1);
@@ -521,10 +535,20 @@ struct mm_struct * mm_alloc(void)
521 struct mm_struct * mm; 535 struct mm_struct * mm;
522 536
523 mm = allocate_mm(); 537 mm = allocate_mm();
524 if (mm) { 538 if (!mm)
525 memset(mm, 0, sizeof(*mm)); 539 return NULL;
526 mm = mm_init(mm, current); 540
541 memset(mm, 0, sizeof(*mm));
542 mm = mm_init(mm, current);
543 if (!mm)
544 return NULL;
545
546 if (mm_init_cpumask(mm, NULL)) {
547 mm_free_pgd(mm);
548 free_mm(mm);
549 return NULL;
527 } 550 }
551
528 return mm; 552 return mm;
529} 553}
530 554
@@ -536,6 +560,7 @@ struct mm_struct * mm_alloc(void)
536void __mmdrop(struct mm_struct *mm) 560void __mmdrop(struct mm_struct *mm)
537{ 561{
538 BUG_ON(mm == &init_mm); 562 BUG_ON(mm == &init_mm);
563 free_cpumask_var(mm->cpu_vm_mask_var);
539 mm_free_pgd(mm); 564 mm_free_pgd(mm);
540 destroy_context(mm); 565 destroy_context(mm);
541 mmu_notifier_mm_destroy(mm); 566 mmu_notifier_mm_destroy(mm);
@@ -690,6 +715,9 @@ struct mm_struct *dup_mm(struct task_struct *tsk)
690 if (!mm_init(mm, tsk)) 715 if (!mm_init(mm, tsk))
691 goto fail_nomem; 716 goto fail_nomem;
692 717
718 if (mm_init_cpumask(mm, oldmm))
719 goto fail_nocpumask;
720
693 if (init_new_context(tsk, mm)) 721 if (init_new_context(tsk, mm))
694 goto fail_nocontext; 722 goto fail_nocontext;
695 723
@@ -716,6 +744,9 @@ fail_nomem:
716 return NULL; 744 return NULL;
717 745
718fail_nocontext: 746fail_nocontext:
747 free_cpumask_var(mm->cpu_vm_mask_var);
748
749fail_nocpumask:
719 /* 750 /*
720 * If init_new_context() failed, we cannot use mmput() to free the mm 751 * If init_new_context() failed, we cannot use mmput() to free the mm
721 * because it calls destroy_context() 752 * because it calls destroy_context()
diff --git a/mm/init-mm.c b/mm/init-mm.c
index 1d29cdfe8ebb..4019979b2637 100644
--- a/mm/init-mm.c
+++ b/mm/init-mm.c
@@ -21,6 +21,5 @@ struct mm_struct init_mm = {
21 .mmap_sem = __RWSEM_INITIALIZER(init_mm.mmap_sem), 21 .mmap_sem = __RWSEM_INITIALIZER(init_mm.mmap_sem),
22 .page_table_lock = __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock), 22 .page_table_lock = __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock),
23 .mmlist = LIST_HEAD_INIT(init_mm.mmlist), 23 .mmlist = LIST_HEAD_INIT(init_mm.mmlist),
24 .cpu_vm_mask = CPU_MASK_ALL,
25 INIT_MM_CONTEXT(init_mm) 24 INIT_MM_CONTEXT(init_mm)
26}; 25};