2 * linux/arch/arm/kernel/smp_tlb.c
4 * Copyright (C) 2002 ARM Limited, All Rights Reserved.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 #include <linux/preempt.h>
11 #include <linux/smp.h>
13 #include <asm/smp_plat.h>
14 #include <asm/tlbflush.h>
16 static void on_each_cpu_mask(void (*func
)(void *), void *info
, int wait
,
17 const struct cpumask
*mask
)
21 smp_call_function_many(mask
, func
, info
, wait
);
22 if (cpumask_test_cpu(smp_processor_id(), mask
))
28 /**********************************************************************/
34 struct vm_area_struct
*ta_vma
;
35 unsigned long ta_start
;
39 static inline void ipi_flush_tlb_all(void *ignored
)
41 local_flush_tlb_all();
44 static inline void ipi_flush_tlb_mm(void *arg
)
46 struct mm_struct
*mm
= (struct mm_struct
*)arg
;
48 local_flush_tlb_mm(mm
);
51 static inline void ipi_flush_tlb_page(void *arg
)
53 struct tlb_args
*ta
= (struct tlb_args
*)arg
;
55 local_flush_tlb_page(ta
->ta_vma
, ta
->ta_start
);
58 static inline void ipi_flush_tlb_kernel_page(void *arg
)
60 struct tlb_args
*ta
= (struct tlb_args
*)arg
;
62 local_flush_tlb_kernel_page(ta
->ta_start
);
65 static inline void ipi_flush_tlb_range(void *arg
)
67 struct tlb_args
*ta
= (struct tlb_args
*)arg
;
69 local_flush_tlb_range(ta
->ta_vma
, ta
->ta_start
, ta
->ta_end
);
72 static inline void ipi_flush_tlb_kernel_range(void *arg
)
74 struct tlb_args
*ta
= (struct tlb_args
*)arg
;
76 local_flush_tlb_kernel_range(ta
->ta_start
, ta
->ta_end
);
79 void flush_tlb_all(void)
81 if (tlb_ops_need_broadcast())
82 on_each_cpu(ipi_flush_tlb_all
, NULL
, 1);
84 local_flush_tlb_all();
87 void flush_tlb_mm(struct mm_struct
*mm
)
89 if (tlb_ops_need_broadcast())
90 on_each_cpu_mask(ipi_flush_tlb_mm
, mm
, 1, mm_cpumask(mm
));
92 local_flush_tlb_mm(mm
);
95 void flush_tlb_page(struct vm_area_struct
*vma
, unsigned long uaddr
)
97 if (tlb_ops_need_broadcast()) {
101 on_each_cpu_mask(ipi_flush_tlb_page
, &ta
, 1, mm_cpumask(vma
->vm_mm
));
103 local_flush_tlb_page(vma
, uaddr
);
106 void flush_tlb_kernel_page(unsigned long kaddr
)
108 if (tlb_ops_need_broadcast()) {
111 on_each_cpu(ipi_flush_tlb_kernel_page
, &ta
, 1);
113 local_flush_tlb_kernel_page(kaddr
);
116 void flush_tlb_range(struct vm_area_struct
*vma
,
117 unsigned long start
, unsigned long end
)
119 if (tlb_ops_need_broadcast()) {
124 on_each_cpu_mask(ipi_flush_tlb_range
, &ta
, 1, mm_cpumask(vma
->vm_mm
));
126 local_flush_tlb_range(vma
, start
, end
);
129 void flush_tlb_kernel_range(unsigned long start
, unsigned long end
)
131 if (tlb_ops_need_broadcast()) {
135 on_each_cpu(ipi_flush_tlb_kernel_range
, &ta
, 1);
137 local_flush_tlb_kernel_range(start
, end
);