1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#define __KERNEL_SYSCALLS__
22
23#include <linux/config.h>
24
25#include <linux/kernel.h>
26#include <linux/sched.h>
27#include <linux/init.h>
28#include <linux/interrupt.h>
29#include <linux/smp.h>
30#include <linux/kernel_stat.h>
31#include <linux/mm.h>
32#include <linux/delay.h>
33#include <linux/cache.h>
34#include <linux/efi.h>
35
36#include <asm/atomic.h>
37#include <asm/bitops.h>
38#include <asm/current.h>
39#include <asm/delay.h>
40#include <asm/machvec.h>
41
42#include <asm/io.h>
43#include <asm/irq.h>
44#include <asm/page.h>
45#include <asm/pgalloc.h>
46#include <asm/pgtable.h>
47#include <asm/processor.h>
48#include <asm/ptrace.h>
49#include <asm/sal.h>
50#include <asm/system.h>
51#include <asm/unistd.h>
52#include <asm/mca.h>
53
54
55spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
56
57
58
59
60
61static spinlock_t call_lock = SPIN_LOCK_UNLOCKED;
62
63struct call_data_struct {
64 void (*func) (void *info);
65 void *info;
66 long wait;
67 atomic_t started;
68 atomic_t finished;
69};
70
71static volatile struct call_data_struct *call_data;
72
73#define IPI_CALL_FUNC 0
74#define IPI_CPU_STOP 1
75
76static void
77stop_this_cpu (void)
78{
79 extern void cpu_halt (void);
80
81
82
83 clear_bit(smp_processor_id(), &cpu_online_map);
84 max_xtp();
85 __cli();
86 cpu_halt();
87}
88
89void
90handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
91{
92 int this_cpu = smp_processor_id();
93 unsigned long *pending_ipis = &local_cpu_data->ipi.operation;
94 unsigned long ops;
95
96
97 local_cpu_data->ipi_count++;
98
99 mb();
100 while ((ops = xchg(pending_ipis, 0)) != 0) {
101 mb();
102 do {
103 unsigned long which;
104
105 which = ffz(~ops);
106 ops &= ~(1 << which);
107
108 switch (which) {
109 case IPI_CALL_FUNC:
110 {
111 struct call_data_struct *data;
112 void (*func)(void *info);
113 void *info;
114 int wait;
115
116
117 data = (struct call_data_struct *) call_data;
118 func = data->func;
119 info = data->info;
120 wait = data->wait;
121
122 mb();
123 atomic_inc(&data->started);
124
125
126 (*func)(info);
127
128
129 mb();
130 if (wait)
131 atomic_inc(&data->finished);
132 }
133 break;
134
135 case IPI_CPU_STOP:
136 stop_this_cpu();
137 break;
138
139 default:
140 printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which);
141 break;
142 }
143 } while (ops);
144
145 mb();
146 }
147}
148
149static inline void
150send_IPI_single (int dest_cpu, int op)
151{
152 set_bit(op, &cpu_data(dest_cpu)->ipi.operation);
153 platform_send_ipi(dest_cpu, IA64_IPI_VECTOR, IA64_IPI_DM_INT, 0);
154}
155
156static inline void
157send_IPI_allbutself (int op)
158{
159 int i;
160
161 for (i = 0; i < smp_num_cpus; i++) {
162 if (i != smp_processor_id())
163 send_IPI_single(i, op);
164 }
165}
166
167static inline void
168send_IPI_all (int op)
169{
170 int i;
171
172 for (i = 0; i < smp_num_cpus; i++)
173 send_IPI_single(i, op);
174}
175
176static inline void
177send_IPI_self (int op)
178{
179 send_IPI_single(smp_processor_id(), op);
180}
181
182void
183smp_send_reschedule (int cpu)
184{
185 platform_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0);
186}
187
188void
189smp_flush_tlb_all (void)
190{
191 smp_call_function((void (*)(void *))local_flush_tlb_all, 0, 1, 1);
192 local_flush_tlb_all();
193}
194
195void
196smp_flush_tlb_mm (struct mm_struct *mm)
197{
198 local_flush_tlb_mm(mm);
199
200
201 if (likely(mm == current->active_mm && atomic_read(&mm->mm_users) == 1))
202 return;
203
204 smp_call_function((void (*)(void *))local_flush_tlb_mm, mm, 1, 1);
205}
206
207
208
209
210
211
212
213
214
215
216
217
218
219int
220smp_call_function_single (int cpuid, void (*func) (void *info), void *info, int nonatomic,
221 int wait)
222{
223 struct call_data_struct data;
224 int cpus = 1;
225
226 if (cpuid == smp_processor_id()) {
227 printk("%s: trying to call self\n", __FUNCTION__);
228 return -EBUSY;
229 }
230
231 data.func = func;
232 data.info = info;
233 atomic_set(&data.started, 0);
234 data.wait = wait;
235 if (wait)
236 atomic_set(&data.finished, 0);
237
238 spin_lock_bh(&call_lock);
239
240 call_data = &data;
241 mb();
242 send_IPI_single(cpuid, IPI_CALL_FUNC);
243
244
245 while (atomic_read(&data.started) != cpus)
246 barrier();
247
248 if (wait)
249 while (atomic_read(&data.finished) != cpus)
250 barrier();
251 call_data = NULL;
252
253 spin_unlock_bh(&call_lock);
254 return 0;
255}
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276int
277smp_call_function (void (*func) (void *info), void *info, int nonatomic, int wait)
278{
279 struct call_data_struct data;
280 int cpus = smp_num_cpus-1;
281
282 if (!cpus)
283 return 0;
284
285 data.func = func;
286 data.info = info;
287 atomic_set(&data.started, 0);
288 data.wait = wait;
289 if (wait)
290 atomic_set(&data.finished, 0);
291
292 spin_lock_bh(&call_lock);
293
294 call_data = &data;
295 mb();
296 send_IPI_allbutself(IPI_CALL_FUNC);
297
298
299 while (atomic_read(&data.started) != cpus)
300 barrier();
301
302 if (wait)
303 while (atomic_read(&data.finished) != cpus)
304 barrier();
305 call_data = NULL;
306
307 spin_unlock_bh(&call_lock);
308 return 0;
309}
310
311void
312smp_do_timer (struct pt_regs *regs)
313{
314 int user = user_mode(regs);
315
316 if (--local_cpu_data->prof_counter <= 0) {
317 local_cpu_data->prof_counter = local_cpu_data->prof_multiplier;
318 update_process_times(user);
319 }
320}
321
322
323
324
325void
326smp_send_stop (void)
327{
328 send_IPI_allbutself(IPI_CPU_STOP);
329 smp_num_cpus = 1;
330}
331
332int __init
333setup_profiling_timer (unsigned int multiplier)
334{
335 return -EINVAL;
336}
337