1
2
3
4
5
6
7
8#include <linux/mm.h>
9#include <linux/cpu.h>
10#include <linux/sched/mm.h>
11
12#include <asm/mmu_context.h>
13#include <asm/pgalloc.h>
14
15#if defined(CONFIG_PPC32)
16static inline void switch_mm_pgdir(struct task_struct *tsk,
17 struct mm_struct *mm)
18{
19
20 tsk->thread.pgdir = mm->pgd;
21}
22#elif defined(CONFIG_PPC_BOOK3E_64)
23static inline void switch_mm_pgdir(struct task_struct *tsk,
24 struct mm_struct *mm)
25{
26
27 get_paca()->pgd = mm->pgd;
28}
29#else
30static inline void switch_mm_pgdir(struct task_struct *tsk,
31 struct mm_struct *mm) { }
32#endif
33
34void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
35 struct task_struct *tsk)
36{
37 bool new_on_cpu = false;
38
39
40 if (!cpumask_test_cpu(smp_processor_id(), mm_cpumask(next))) {
41 cpumask_set_cpu(smp_processor_id(), mm_cpumask(next));
42 inc_mm_active_cpus(next);
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 smp_mb();
66
67 new_on_cpu = true;
68 }
69
70
71 switch_mm_pgdir(tsk, next);
72
73
74 if (prev == next)
75 return;
76
77
78
79
80
81 if (cpu_has_feature(CPU_FTR_ALTIVEC))
82 asm volatile ("dssall");
83
84 if (new_on_cpu)
85 radix_kvm_prefetch_workaround(next);
86 else
87 membarrier_arch_switch_mm(prev, next, tsk);
88
89
90
91
92
93 switch_mmu_context(prev, next, tsk);
94}
95
96#ifndef CONFIG_PPC_BOOK3S_64
97void arch_exit_mmap(struct mm_struct *mm)
98{
99 void *frag = pte_frag_get(&mm->context);
100
101 if (frag)
102 pte_frag_destroy(frag);
103}
104#endif
105