blob: bd0300531399e5eeb066a45f3c29b0d897c23b42 [file] [log] [blame]
Russell King03b505e2010-12-20 14:44:32 +00001/*
2 * linux/arch/arm/kernel/smp_tlb.c
3 *
4 * Copyright (C) 2002 ARM Limited, All Rights Reserved.
5 *
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.
9 */
10#include <linux/preempt.h>
11#include <linux/smp.h>
12
13#include <asm/smp_plat.h>
14#include <asm/tlbflush.h>
15
Russell King03b505e2010-12-20 14:44:32 +000016/**********************************************************************/
17
18/*
19 * TLB operations
20 */
21struct tlb_args {
22 struct vm_area_struct *ta_vma;
23 unsigned long ta_start;
24 unsigned long ta_end;
25};
26
27static inline void ipi_flush_tlb_all(void *ignored)
28{
29 local_flush_tlb_all();
30}
31
32static inline void ipi_flush_tlb_mm(void *arg)
33{
34 struct mm_struct *mm = (struct mm_struct *)arg;
35
36 local_flush_tlb_mm(mm);
37}
38
39static inline void ipi_flush_tlb_page(void *arg)
40{
41 struct tlb_args *ta = (struct tlb_args *)arg;
42
43 local_flush_tlb_page(ta->ta_vma, ta->ta_start);
44}
45
46static inline void ipi_flush_tlb_kernel_page(void *arg)
47{
48 struct tlb_args *ta = (struct tlb_args *)arg;
49
50 local_flush_tlb_kernel_page(ta->ta_start);
51}
52
53static inline void ipi_flush_tlb_range(void *arg)
54{
55 struct tlb_args *ta = (struct tlb_args *)arg;
56
57 local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
58}
59
60static inline void ipi_flush_tlb_kernel_range(void *arg)
61{
62 struct tlb_args *ta = (struct tlb_args *)arg;
63
64 local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end);
65}
66
Will Deacon862c5882013-02-28 17:48:11 +010067static inline void ipi_flush_bp_all(void *ignored)
68{
69 local_flush_bp_all();
70}
71
Russell King03b505e2010-12-20 14:44:32 +000072void flush_tlb_all(void)
73{
74 if (tlb_ops_need_broadcast())
75 on_each_cpu(ipi_flush_tlb_all, NULL, 1);
76 else
77 local_flush_tlb_all();
78}
79
80void flush_tlb_mm(struct mm_struct *mm)
81{
82 if (tlb_ops_need_broadcast())
Gilad Ben-Yossef3fc498f2012-03-28 14:42:43 -070083 on_each_cpu_mask(mm_cpumask(mm), ipi_flush_tlb_mm, mm, 1);
Russell King03b505e2010-12-20 14:44:32 +000084 else
85 local_flush_tlb_mm(mm);
86}
87
88void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
89{
90 if (tlb_ops_need_broadcast()) {
91 struct tlb_args ta;
92 ta.ta_vma = vma;
93 ta.ta_start = uaddr;
Gilad Ben-Yossef3fc498f2012-03-28 14:42:43 -070094 on_each_cpu_mask(mm_cpumask(vma->vm_mm), ipi_flush_tlb_page,
95 &ta, 1);
Russell King03b505e2010-12-20 14:44:32 +000096 } else
97 local_flush_tlb_page(vma, uaddr);
98}
99
100void flush_tlb_kernel_page(unsigned long kaddr)
101{
102 if (tlb_ops_need_broadcast()) {
103 struct tlb_args ta;
104 ta.ta_start = kaddr;
105 on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
106 } else
107 local_flush_tlb_kernel_page(kaddr);
108}
109
110void flush_tlb_range(struct vm_area_struct *vma,
111 unsigned long start, unsigned long end)
112{
113 if (tlb_ops_need_broadcast()) {
114 struct tlb_args ta;
115 ta.ta_vma = vma;
116 ta.ta_start = start;
117 ta.ta_end = end;
Gilad Ben-Yossef3fc498f2012-03-28 14:42:43 -0700118 on_each_cpu_mask(mm_cpumask(vma->vm_mm), ipi_flush_tlb_range,
119 &ta, 1);
Russell King03b505e2010-12-20 14:44:32 +0000120 } else
121 local_flush_tlb_range(vma, start, end);
122}
123
124void flush_tlb_kernel_range(unsigned long start, unsigned long end)
125{
126 if (tlb_ops_need_broadcast()) {
127 struct tlb_args ta;
128 ta.ta_start = start;
129 ta.ta_end = end;
130 on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
131 } else
132 local_flush_tlb_kernel_range(start, end);
133}
134
Will Deacon862c5882013-02-28 17:48:11 +0100135void flush_bp_all(void)
136{
137 if (tlb_ops_need_broadcast())
138 on_each_cpu(ipi_flush_bp_all, NULL, 1);
139 else
140 local_flush_bp_all();
141}