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