Merge branch 'exec_rm_compat' of git://git.kernel.org/pub/scm/linux/kernel/git/oleg...
[pandora-kernel.git] / arch / m32r / kernel / smp.c
1 /*
2  *  linux/arch/m32r/kernel/smp.c
3  *
4  *  M32R SMP support routines.
5  *
6  *  Copyright (c) 2001, 2002  Hitoshi Yamamoto
7  *
8  *  Taken from i386 version.
9  *    (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
10  *    (c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
11  *
12  *  This code is released under the GNU General Public License version 2 or
13  *  later.
14  */
15
16 #undef DEBUG_SMP
17
18 #include <linux/irq.h>
19 #include <linux/interrupt.h>
20 #include <linux/sched.h>
21 #include <linux/spinlock.h>
22 #include <linux/mm.h>
23 #include <linux/smp.h>
24 #include <linux/profile.h>
25 #include <linux/cpu.h>
26
27 #include <asm/cacheflush.h>
28 #include <asm/pgalloc.h>
29 #include <asm/atomic.h>
30 #include <asm/io.h>
31 #include <asm/mmu_context.h>
32 #include <asm/m32r.h>
33
34 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
35 /* Data structures and variables                                             */
36 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
37
38 /*
39  * For flush_cache_all()
40  */
41 static DEFINE_SPINLOCK(flushcache_lock);
42 static volatile unsigned long flushcache_cpumask = 0;
43
44 /*
45  * For flush_tlb_others()
46  */
47 static volatile cpumask_t flush_cpumask;
48 static struct mm_struct *flush_mm;
49 static struct vm_area_struct *flush_vma;
50 static volatile unsigned long flush_va;
51 static DEFINE_SPINLOCK(tlbstate_lock);
52 #define FLUSH_ALL 0xffffffff
53
54 DECLARE_PER_CPU(int, prof_multiplier);
55 DECLARE_PER_CPU(int, prof_old_multiplier);
56 DECLARE_PER_CPU(int, prof_counter);
57
58 extern spinlock_t ipi_lock[];
59
60 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
61 /* Function Prototypes                                                       */
62 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
63
64 void smp_send_reschedule(int);
65 void smp_reschedule_interrupt(void);
66
67 void smp_flush_cache_all(void);
68 void smp_flush_cache_all_interrupt(void);
69
70 void smp_flush_tlb_all(void);
71 static void flush_tlb_all_ipi(void *);
72
73 void smp_flush_tlb_mm(struct mm_struct *);
74 void smp_flush_tlb_range(struct vm_area_struct *, unsigned long, \
75         unsigned long);
76 void smp_flush_tlb_page(struct vm_area_struct *, unsigned long);
77 static void flush_tlb_others(cpumask_t, struct mm_struct *,
78         struct vm_area_struct *, unsigned long);
79 void smp_invalidate_interrupt(void);
80
81 void smp_send_stop(void);
82 static void stop_this_cpu(void *);
83
84 void smp_send_timer(void);
85 void smp_ipi_timer_interrupt(struct pt_regs *);
86 void smp_local_timer_interrupt(void);
87
88 static void send_IPI_allbutself(int, int);
89 static void send_IPI_mask(const struct cpumask *, int, int);
90 unsigned long send_IPI_mask_phys(cpumask_t, int, int);
91
92 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
93 /* Rescheduling request Routines                                             */
94 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
95
96 /*==========================================================================*
97  * Name:         smp_send_reschedule
98  *
99  * Description:  This routine requests other CPU to execute rescheduling.
100  *               1.Send 'RESCHEDULE_IPI' to other CPU.
101  *                 Request other CPU to execute 'smp_reschedule_interrupt()'.
102  *
103  * Born on Date: 2002.02.05
104  *
105  * Arguments:    cpu_id - Target CPU ID
106  *
107  * Returns:      void (cannot fail)
108  *
109  * Modification log:
110  * Date       Who Description
111  * ---------- --- --------------------------------------------------------
112  *
113  *==========================================================================*/
114 void smp_send_reschedule(int cpu_id)
115 {
116         WARN_ON(cpu_is_offline(cpu_id));
117         send_IPI_mask(cpumask_of(cpu_id), RESCHEDULE_IPI, 1);
118 }
119
120 /*==========================================================================*
121  * Name:         smp_reschedule_interrupt
122  *
123  * Description:  This routine executes on CPU which received
124  *               'RESCHEDULE_IPI'.
125  *
126  * Born on Date: 2002.02.05
127  *
128  * Arguments:    NONE
129  *
130  * Returns:      void (cannot fail)
131  *
132  * Modification log:
133  * Date       Who Description
134  * ---------- --- --------------------------------------------------------
135  *
136  *==========================================================================*/
137 void smp_reschedule_interrupt(void)
138 {
139         scheduler_ipi();
140 }
141
142 /*==========================================================================*
143  * Name:         smp_flush_cache_all
144  *
145  * Description:  This routine sends a 'INVALIDATE_CACHE_IPI' to all other
146  *               CPUs in the system.
147  *
148  * Born on Date: 2003-05-28
149  *
150  * Arguments:    NONE
151  *
152  * Returns:      void (cannot fail)
153  *
154  * Modification log:
155  * Date       Who Description
156  * ---------- --- --------------------------------------------------------
157  *
158  *==========================================================================*/
159 void smp_flush_cache_all(void)
160 {
161         cpumask_t cpumask;
162         unsigned long *mask;
163
164         preempt_disable();
165         cpumask = cpu_online_map;
166         cpu_clear(smp_processor_id(), cpumask);
167         spin_lock(&flushcache_lock);
168         mask=cpus_addr(cpumask);
169         atomic_set_mask(*mask, (atomic_t *)&flushcache_cpumask);
170         send_IPI_mask(&cpumask, INVALIDATE_CACHE_IPI, 0);
171         _flush_cache_copyback_all();
172         while (flushcache_cpumask)
173                 mb();
174         spin_unlock(&flushcache_lock);
175         preempt_enable();
176 }
177
178 void smp_flush_cache_all_interrupt(void)
179 {
180         _flush_cache_copyback_all();
181         clear_bit(smp_processor_id(), &flushcache_cpumask);
182 }
183
184 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
185 /* TLB flush request Routines                                                */
186 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
187
188 /*==========================================================================*
189  * Name:         smp_flush_tlb_all
190  *
191  * Description:  This routine flushes all processes TLBs.
192  *               1.Request other CPU to execute 'flush_tlb_all_ipi()'.
193  *               2.Execute 'do_flush_tlb_all_local()'.
194  *
195  * Born on Date: 2002.02.05
196  *
197  * Arguments:    NONE
198  *
199  * Returns:      void (cannot fail)
200  *
201  * Modification log:
202  * Date       Who Description
203  * ---------- --- --------------------------------------------------------
204  *
205  *==========================================================================*/
206 void smp_flush_tlb_all(void)
207 {
208         unsigned long flags;
209
210         preempt_disable();
211         local_irq_save(flags);
212         __flush_tlb_all();
213         local_irq_restore(flags);
214         smp_call_function(flush_tlb_all_ipi, NULL, 1);
215         preempt_enable();
216 }
217
218 /*==========================================================================*
219  * Name:         flush_tlb_all_ipi
220  *
221  * Description:  This routine flushes all local TLBs.
222  *               1.Execute 'do_flush_tlb_all_local()'.
223  *
224  * Born on Date: 2002.02.05
225  *
226  * Arguments:    *info - not used
227  *
228  * Returns:      void (cannot fail)
229  *
230  * Modification log:
231  * Date       Who Description
232  * ---------- --- --------------------------------------------------------
233  *
234  *==========================================================================*/
235 static void flush_tlb_all_ipi(void *info)
236 {
237         __flush_tlb_all();
238 }
239
240 /*==========================================================================*
241  * Name:         smp_flush_tlb_mm
242  *
243  * Description:  This routine flushes the specified mm context TLB's.
244  *
245  * Born on Date: 2002.02.05
246  *
247  * Arguments:    *mm - a pointer to the mm struct for flush TLB
248  *
249  * Returns:      void (cannot fail)
250  *
251  * Modification log:
252  * Date       Who Description
253  * ---------- --- --------------------------------------------------------
254  *
255  *==========================================================================*/
256 void smp_flush_tlb_mm(struct mm_struct *mm)
257 {
258         int cpu_id;
259         cpumask_t cpu_mask;
260         unsigned long *mmc;
261         unsigned long flags;
262
263         preempt_disable();
264         cpu_id = smp_processor_id();
265         mmc = &mm->context[cpu_id];
266         cpu_mask = *mm_cpumask(mm);
267         cpu_clear(cpu_id, cpu_mask);
268
269         if (*mmc != NO_CONTEXT) {
270                 local_irq_save(flags);
271                 *mmc = NO_CONTEXT;
272                 if (mm == current->mm)
273                         activate_context(mm);
274                 else
275                         cpumask_clear_cpu(cpu_id, mm_cpumask(mm));
276                 local_irq_restore(flags);
277         }
278         if (!cpus_empty(cpu_mask))
279                 flush_tlb_others(cpu_mask, mm, NULL, FLUSH_ALL);
280
281         preempt_enable();
282 }
283
284 /*==========================================================================*
285  * Name:         smp_flush_tlb_range
286  *
287  * Description:  This routine flushes a range of pages.
288  *
289  * Born on Date: 2002.02.05
290  *
291  * Arguments:    *mm - a pointer to the mm struct for flush TLB
292  *               start - not used
293  *               end - not used
294  *
295  * Returns:      void (cannot fail)
296  *
297  * Modification log:
298  * Date       Who Description
299  * ---------- --- --------------------------------------------------------
300  *
301  *==========================================================================*/
302 void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
303         unsigned long end)
304 {
305         smp_flush_tlb_mm(vma->vm_mm);
306 }
307
308 /*==========================================================================*
309  * Name:         smp_flush_tlb_page
310  *
311  * Description:  This routine flushes one page.
312  *
313  * Born on Date: 2002.02.05
314  *
315  * Arguments:    *vma - a pointer to the vma struct include va
316  *               va - virtual address for flush TLB
317  *
318  * Returns:      void (cannot fail)
319  *
320  * Modification log:
321  * Date       Who Description
322  * ---------- --- --------------------------------------------------------
323  *
324  *==========================================================================*/
325 void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
326 {
327         struct mm_struct *mm = vma->vm_mm;
328         int cpu_id;
329         cpumask_t cpu_mask;
330         unsigned long *mmc;
331         unsigned long flags;
332
333         preempt_disable();
334         cpu_id = smp_processor_id();
335         mmc = &mm->context[cpu_id];
336         cpu_mask = *mm_cpumask(mm);
337         cpu_clear(cpu_id, cpu_mask);
338
339 #ifdef DEBUG_SMP
340         if (!mm)
341                 BUG();
342 #endif
343
344         if (*mmc != NO_CONTEXT) {
345                 local_irq_save(flags);
346                 va &= PAGE_MASK;
347                 va |= (*mmc & MMU_CONTEXT_ASID_MASK);
348                 __flush_tlb_page(va);
349                 local_irq_restore(flags);
350         }
351         if (!cpus_empty(cpu_mask))
352                 flush_tlb_others(cpu_mask, mm, vma, va);
353
354         preempt_enable();
355 }
356
357 /*==========================================================================*
358  * Name:         flush_tlb_others
359  *
360  * Description:  This routine requests other CPU to execute flush TLB.
361  *               1.Setup parameters.
362  *               2.Send 'INVALIDATE_TLB_IPI' to other CPU.
363  *                 Request other CPU to execute 'smp_invalidate_interrupt()'.
364  *               3.Wait for other CPUs operation finished.
365  *
366  * Born on Date: 2002.02.05
367  *
368  * Arguments:    cpumask - bitmap of target CPUs
369  *               *mm -  a pointer to the mm struct for flush TLB
370  *               *vma -  a pointer to the vma struct include va
371  *               va - virtual address for flush TLB
372  *
373  * Returns:      void (cannot fail)
374  *
375  * Modification log:
376  * Date       Who Description
377  * ---------- --- --------------------------------------------------------
378  *
379  *==========================================================================*/
380 static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
381         struct vm_area_struct *vma, unsigned long va)
382 {
383         unsigned long *mask;
384 #ifdef DEBUG_SMP
385         unsigned long flags;
386         __save_flags(flags);
387         if (!(flags & 0x0040))  /* Interrupt Disable NONONO */
388                 BUG();
389 #endif /* DEBUG_SMP */
390
391         /*
392          * A couple of (to be removed) sanity checks:
393          *
394          * - we do not send IPIs to not-yet booted CPUs.
395          * - current CPU must not be in mask
396          * - mask must exist :)
397          */
398         BUG_ON(cpus_empty(cpumask));
399
400         BUG_ON(cpu_isset(smp_processor_id(), cpumask));
401         BUG_ON(!mm);
402
403         /* If a CPU which we ran on has gone down, OK. */
404         cpus_and(cpumask, cpumask, cpu_online_map);
405         if (cpus_empty(cpumask))
406                 return;
407
408         /*
409          * i'm not happy about this global shared spinlock in the
410          * MM hot path, but we'll see how contended it is.
411          * Temporarily this turns IRQs off, so that lockups are
412          * detected by the NMI watchdog.
413          */
414         spin_lock(&tlbstate_lock);
415
416         flush_mm = mm;
417         flush_vma = vma;
418         flush_va = va;
419         mask=cpus_addr(cpumask);
420         atomic_set_mask(*mask, (atomic_t *)&flush_cpumask);
421
422         /*
423          * We have to send the IPI only to
424          * CPUs affected.
425          */
426         send_IPI_mask(&cpumask, INVALIDATE_TLB_IPI, 0);
427
428         while (!cpus_empty(flush_cpumask)) {
429                 /* nothing. lockup detection does not belong here */
430                 mb();
431         }
432
433         flush_mm = NULL;
434         flush_vma = NULL;
435         flush_va = 0;
436         spin_unlock(&tlbstate_lock);
437 }
438
439 /*==========================================================================*
440  * Name:         smp_invalidate_interrupt
441  *
442  * Description:  This routine executes on CPU which received
443  *               'INVALIDATE_TLB_IPI'.
444  *               1.Flush local TLB.
445  *               2.Report flush TLB process was finished.
446  *
447  * Born on Date: 2002.02.05
448  *
449  * Arguments:    NONE
450  *
451  * Returns:      void (cannot fail)
452  *
453  * Modification log:
454  * Date       Who Description
455  * ---------- --- --------------------------------------------------------
456  *
457  *==========================================================================*/
458 void smp_invalidate_interrupt(void)
459 {
460         int cpu_id = smp_processor_id();
461         unsigned long *mmc = &flush_mm->context[cpu_id];
462
463         if (!cpu_isset(cpu_id, flush_cpumask))
464                 return;
465
466         if (flush_va == FLUSH_ALL) {
467                 *mmc = NO_CONTEXT;
468                 if (flush_mm == current->active_mm)
469                         activate_context(flush_mm);
470                 else
471                         cpumask_clear_cpu(cpu_id, mm_cpumask(flush_mm));
472         } else {
473                 unsigned long va = flush_va;
474
475                 if (*mmc != NO_CONTEXT) {
476                         va &= PAGE_MASK;
477                         va |= (*mmc & MMU_CONTEXT_ASID_MASK);
478                         __flush_tlb_page(va);
479                 }
480         }
481         cpu_clear(cpu_id, flush_cpumask);
482 }
483
484 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
485 /* Stop CPU request Routines                                                 */
486 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
487
488 /*==========================================================================*
489  * Name:         smp_send_stop
490  *
491  * Description:  This routine requests stop all CPUs.
492  *               1.Request other CPU to execute 'stop_this_cpu()'.
493  *
494  * Born on Date: 2002.02.05
495  *
496  * Arguments:    NONE
497  *
498  * Returns:      void (cannot fail)
499  *
500  * Modification log:
501  * Date       Who Description
502  * ---------- --- --------------------------------------------------------
503  *
504  *==========================================================================*/
505 void smp_send_stop(void)
506 {
507         smp_call_function(stop_this_cpu, NULL, 0);
508 }
509
510 /*==========================================================================*
511  * Name:         stop_this_cpu
512  *
513  * Description:  This routine halt CPU.
514  *
515  * Born on Date: 2002.02.05
516  *
517  * Arguments:    NONE
518  *
519  * Returns:      void (cannot fail)
520  *
521  * Modification log:
522  * Date       Who Description
523  * ---------- --- --------------------------------------------------------
524  *
525  *==========================================================================*/
526 static void stop_this_cpu(void *dummy)
527 {
528         int cpu_id = smp_processor_id();
529
530         /*
531          * Remove this CPU:
532          */
533         cpu_clear(cpu_id, cpu_online_map);
534
535         /*
536          * PSW IE = 1;
537          * IMASK = 0;
538          * goto SLEEP
539          */
540         local_irq_disable();
541         outl(0, M32R_ICU_IMASK_PORTL);
542         inl(M32R_ICU_IMASK_PORTL);      /* dummy read */
543         local_irq_enable();
544
545         for ( ; ; );
546 }
547
548 void arch_send_call_function_ipi_mask(const struct cpumask *mask)
549 {
550         send_IPI_mask(mask, CALL_FUNCTION_IPI, 0);
551 }
552
553 void arch_send_call_function_single_ipi(int cpu)
554 {
555         send_IPI_mask(cpumask_of(cpu), CALL_FUNC_SINGLE_IPI, 0);
556 }
557
558 /*==========================================================================*
559  * Name:         smp_call_function_interrupt
560  *
561  * Description:  This routine executes on CPU which received
562  *               'CALL_FUNCTION_IPI'.
563  *
564  * Born on Date: 2002.02.05
565  *
566  * Arguments:    NONE
567  *
568  * Returns:      void (cannot fail)
569  *
570  * Modification log:
571  * Date       Who Description
572  * ---------- --- --------------------------------------------------------
573  *
574  *==========================================================================*/
575 void smp_call_function_interrupt(void)
576 {
577         irq_enter();
578         generic_smp_call_function_interrupt();
579         irq_exit();
580 }
581
582 void smp_call_function_single_interrupt(void)
583 {
584         irq_enter();
585         generic_smp_call_function_single_interrupt();
586         irq_exit();
587 }
588
589 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
590 /* Timer Routines                                                            */
591 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
592
593 /*==========================================================================*
594  * Name:         smp_send_timer
595  *
596  * Description:  This routine sends a 'LOCAL_TIMER_IPI' to all other CPUs
597  *               in the system.
598  *
599  * Born on Date: 2002.02.05
600  *
601  * Arguments:    NONE
602  *
603  * Returns:      void (cannot fail)
604  *
605  * Modification log:
606  * Date       Who Description
607  * ---------- --- --------------------------------------------------------
608  *
609  *==========================================================================*/
610 void smp_send_timer(void)
611 {
612         send_IPI_allbutself(LOCAL_TIMER_IPI, 1);
613 }
614
615 /*==========================================================================*
616  * Name:         smp_send_timer
617  *
618  * Description:  This routine executes on CPU which received
619  *               'LOCAL_TIMER_IPI'.
620  *
621  * Born on Date: 2002.02.05
622  *
623  * Arguments:    *regs - a pointer to the saved regster info
624  *
625  * Returns:      void (cannot fail)
626  *
627  * Modification log:
628  * Date       Who Description
629  * ---------- --- --------------------------------------------------------
630  *
631  *==========================================================================*/
632 void smp_ipi_timer_interrupt(struct pt_regs *regs)
633 {
634         struct pt_regs *old_regs;
635         old_regs = set_irq_regs(regs);
636         irq_enter();
637         smp_local_timer_interrupt();
638         irq_exit();
639         set_irq_regs(old_regs);
640 }
641
642 /*==========================================================================*
643  * Name:         smp_local_timer_interrupt
644  *
645  * Description:  Local timer interrupt handler. It does both profiling and
646  *               process statistics/rescheduling.
647  *               We do profiling in every local tick, statistics/rescheduling
648  *               happen only every 'profiling multiplier' ticks. The default
649  *               multiplier is 1 and it can be changed by writing the new
650  *               multiplier value into /proc/profile.
651  *
652  * Born on Date: 2002.02.05
653  *
654  * Arguments:    *regs - a pointer to the saved regster info
655  *
656  * Returns:      void (cannot fail)
657  *
658  * Original:     arch/i386/kernel/apic.c
659  *
660  * Modification log:
661  * Date       Who Description
662  * ---------- --- --------------------------------------------------------
663  * 2003-06-24 hy  use per_cpu structure.
664  *==========================================================================*/
665 void smp_local_timer_interrupt(void)
666 {
667         int user = user_mode(get_irq_regs());
668         int cpu_id = smp_processor_id();
669
670         /*
671          * The profiling function is SMP safe. (nothing can mess
672          * around with "current", and the profiling counters are
673          * updated with atomic operations). This is especially
674          * useful with a profiling multiplier != 1
675          */
676
677         profile_tick(CPU_PROFILING);
678
679         if (--per_cpu(prof_counter, cpu_id) <= 0) {
680                 /*
681                  * The multiplier may have changed since the last time we got
682                  * to this point as a result of the user writing to
683                  * /proc/profile. In this case we need to adjust the APIC
684                  * timer accordingly.
685                  *
686                  * Interrupts are already masked off at this point.
687                  */
688                 per_cpu(prof_counter, cpu_id)
689                         = per_cpu(prof_multiplier, cpu_id);
690                 if (per_cpu(prof_counter, cpu_id)
691                         != per_cpu(prof_old_multiplier, cpu_id))
692                 {
693                         per_cpu(prof_old_multiplier, cpu_id)
694                                 = per_cpu(prof_counter, cpu_id);
695                 }
696
697                 update_process_times(user);
698         }
699 }
700
701 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
702 /* Send IPI Routines                                                         */
703 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
704
705 /*==========================================================================*
706  * Name:         send_IPI_allbutself
707  *
708  * Description:  This routine sends a IPI to all other CPUs in the system.
709  *
710  * Born on Date: 2002.02.05
711  *
712  * Arguments:    ipi_num - Number of IPI
713  *               try -  0 : Send IPI certainly.
714  *                     !0 : The following IPI is not sent when Target CPU
715  *                          has not received the before IPI.
716  *
717  * Returns:      void (cannot fail)
718  *
719  * Modification log:
720  * Date       Who Description
721  * ---------- --- --------------------------------------------------------
722  *
723  *==========================================================================*/
724 static void send_IPI_allbutself(int ipi_num, int try)
725 {
726         cpumask_t cpumask;
727
728         cpumask = cpu_online_map;
729         cpu_clear(smp_processor_id(), cpumask);
730
731         send_IPI_mask(&cpumask, ipi_num, try);
732 }
733
734 /*==========================================================================*
735  * Name:         send_IPI_mask
736  *
737  * Description:  This routine sends a IPI to CPUs in the system.
738  *
739  * Born on Date: 2002.02.05
740  *
741  * Arguments:    cpu_mask - Bitmap of target CPUs logical ID
742  *               ipi_num - Number of IPI
743  *               try -  0 : Send IPI certainly.
744  *                     !0 : The following IPI is not sent when Target CPU
745  *                          has not received the before IPI.
746  *
747  * Returns:      void (cannot fail)
748  *
749  * Modification log:
750  * Date       Who Description
751  * ---------- --- --------------------------------------------------------
752  *
753  *==========================================================================*/
754 static void send_IPI_mask(const struct cpumask *cpumask, int ipi_num, int try)
755 {
756         cpumask_t physid_mask, tmp;
757         int cpu_id, phys_id;
758         int num_cpus = num_online_cpus();
759
760         if (num_cpus <= 1)      /* NO MP */
761                 return;
762
763         cpumask_and(&tmp, cpumask, cpu_online_mask);
764         BUG_ON(!cpumask_equal(cpumask, &tmp));
765
766         physid_mask = CPU_MASK_NONE;
767         for_each_cpu(cpu_id, cpumask) {
768                 if ((phys_id = cpu_to_physid(cpu_id)) != -1)
769                         cpu_set(phys_id, physid_mask);
770         }
771
772         send_IPI_mask_phys(physid_mask, ipi_num, try);
773 }
774
775 /*==========================================================================*
776  * Name:         send_IPI_mask_phys
777  *
778  * Description:  This routine sends a IPI to other CPUs in the system.
779  *
780  * Born on Date: 2002.02.05
781  *
782  * Arguments:    cpu_mask - Bitmap of target CPUs physical ID
783  *               ipi_num - Number of IPI
784  *               try -  0 : Send IPI certainly.
785  *                     !0 : The following IPI is not sent when Target CPU
786  *                          has not received the before IPI.
787  *
788  * Returns:      IPICRi regster value.
789  *
790  * Modification log:
791  * Date       Who Description
792  * ---------- --- --------------------------------------------------------
793  *
794  *==========================================================================*/
795 unsigned long send_IPI_mask_phys(cpumask_t physid_mask, int ipi_num,
796         int try)
797 {
798         spinlock_t *ipilock;
799         volatile unsigned long *ipicr_addr;
800         unsigned long ipicr_val;
801         unsigned long my_physid_mask;
802         unsigned long mask = cpus_addr(physid_mask)[0];
803
804
805         if (mask & ~physids_coerce(phys_cpu_present_map))
806                 BUG();
807         if (ipi_num >= NR_IPIS || ipi_num < 0)
808                 BUG();
809
810         mask <<= IPI_SHIFT;
811         ipilock = &ipi_lock[ipi_num];
812         ipicr_addr = (volatile unsigned long *)(M32R_ICU_IPICR_ADDR
813                 + (ipi_num << 2));
814         my_physid_mask = ~(1 << smp_processor_id());
815
816         /*
817          * lock ipi_lock[i]
818          * check IPICRi == 0
819          * write IPICRi (send IPIi)
820          * unlock ipi_lock[i]
821          */
822         spin_lock(ipilock);
823         __asm__ __volatile__ (
824                 ";; CHECK IPICRi == 0           \n\t"
825                 ".fillinsn                      \n"
826                 "1:                             \n\t"
827                 "ld     %0, @%1                 \n\t"
828                 "and    %0, %4                  \n\t"
829                 "beqz   %0, 2f                  \n\t"
830                 "bnez   %3, 3f                  \n\t"
831                 "bra    1b                      \n\t"
832                 ";; WRITE IPICRi (send IPIi)    \n\t"
833                 ".fillinsn                      \n"
834                 "2:                             \n\t"
835                 "st     %2, @%1                 \n\t"
836                 ".fillinsn                      \n"
837                 "3:                             \n\t"
838                 : "=&r"(ipicr_val)
839                 : "r"(ipicr_addr), "r"(mask), "r"(try), "r"(my_physid_mask)
840                 : "memory"
841         );
842         spin_unlock(ipilock);
843
844         return ipicr_val;
845 }