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