diff options
Diffstat (limited to 'arch/sparc/mm/tlb.c')
-rw-r--r-- | arch/sparc/mm/tlb.c | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c index ba6ae7ffdc2c..272aa4f7657e 100644 --- a/arch/sparc/mm/tlb.c +++ b/arch/sparc/mm/tlb.c | |||
@@ -24,11 +24,17 @@ static DEFINE_PER_CPU(struct tlb_batch, tlb_batch); | |||
24 | void flush_tlb_pending(void) | 24 | void flush_tlb_pending(void) |
25 | { | 25 | { |
26 | struct tlb_batch *tb = &get_cpu_var(tlb_batch); | 26 | struct tlb_batch *tb = &get_cpu_var(tlb_batch); |
27 | struct mm_struct *mm = tb->mm; | ||
27 | 28 | ||
28 | if (tb->tlb_nr) { | 29 | if (!tb->tlb_nr) |
29 | flush_tsb_user(tb); | 30 | goto out; |
30 | 31 | ||
31 | if (CTX_VALID(tb->mm->context)) { | 32 | flush_tsb_user(tb); |
33 | |||
34 | if (CTX_VALID(mm->context)) { | ||
35 | if (tb->tlb_nr == 1) { | ||
36 | global_flush_tlb_page(mm, tb->vaddrs[0]); | ||
37 | } else { | ||
32 | #ifdef CONFIG_SMP | 38 | #ifdef CONFIG_SMP |
33 | smp_flush_tlb_pending(tb->mm, tb->tlb_nr, | 39 | smp_flush_tlb_pending(tb->mm, tb->tlb_nr, |
34 | &tb->vaddrs[0]); | 40 | &tb->vaddrs[0]); |
@@ -37,12 +43,30 @@ void flush_tlb_pending(void) | |||
37 | tb->tlb_nr, &tb->vaddrs[0]); | 43 | tb->tlb_nr, &tb->vaddrs[0]); |
38 | #endif | 44 | #endif |
39 | } | 45 | } |
40 | tb->tlb_nr = 0; | ||
41 | } | 46 | } |
42 | 47 | ||
48 | tb->tlb_nr = 0; | ||
49 | |||
50 | out: | ||
43 | put_cpu_var(tlb_batch); | 51 | put_cpu_var(tlb_batch); |
44 | } | 52 | } |
45 | 53 | ||
54 | void arch_enter_lazy_mmu_mode(void) | ||
55 | { | ||
56 | struct tlb_batch *tb = &__get_cpu_var(tlb_batch); | ||
57 | |||
58 | tb->active = 1; | ||
59 | } | ||
60 | |||
61 | void arch_leave_lazy_mmu_mode(void) | ||
62 | { | ||
63 | struct tlb_batch *tb = &__get_cpu_var(tlb_batch); | ||
64 | |||
65 | if (tb->tlb_nr) | ||
66 | flush_tlb_pending(); | ||
67 | tb->active = 0; | ||
68 | } | ||
69 | |||
46 | static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr, | 70 | static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr, |
47 | bool exec) | 71 | bool exec) |
48 | { | 72 | { |
@@ -60,6 +84,12 @@ static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr, | |||
60 | nr = 0; | 84 | nr = 0; |
61 | } | 85 | } |
62 | 86 | ||
87 | if (!tb->active) { | ||
88 | global_flush_tlb_page(mm, vaddr); | ||
89 | flush_tsb_user_page(mm, vaddr); | ||
90 | return; | ||
91 | } | ||
92 | |||
63 | if (nr == 0) | 93 | if (nr == 0) |
64 | tb->mm = mm; | 94 | tb->mm = mm; |
65 | 95 | ||