linux-old/arch/alpha/kernel/smp.c
<<
>>
Prefs
   1/*
   2 *      linux/arch/alpha/kernel/smp.c
   3 *
   4 *      2001-07-09 Phil Ezolt (Phillip.Ezolt@compaq.com)
   5 *            Renamed modified smp_call_function to smp_call_function_on_cpu()
   6 *            Created an function that conforms to the old calling convention
   7 *            of smp_call_function().
   8 *
   9 *            This is helpful for DCPI.
  10 *
  11 */
  12
  13#include <linux/errno.h>
  14#include <linux/kernel.h>
  15#include <linux/kernel_stat.h>
  16#include <linux/sched.h>
  17#include <linux/mm.h>
  18#include <linux/threads.h>
  19#include <linux/smp.h>
  20#include <linux/smp_lock.h>
  21#include <linux/interrupt.h>
  22#include <linux/init.h>
  23#include <linux/delay.h>
  24#include <linux/spinlock.h>
  25#include <linux/irq.h>
  26#include <linux/cache.h>
  27
  28#include <asm/hwrpb.h>
  29#include <asm/ptrace.h>
  30#include <asm/atomic.h>
  31
  32#include <asm/io.h>
  33#include <asm/irq.h>
  34#include <asm/bitops.h>
  35#include <asm/pgtable.h>
  36#include <asm/pgalloc.h>
  37#include <asm/hardirq.h>
  38#include <asm/softirq.h>
  39#include <asm/mmu_context.h>
  40
  41#define __KERNEL_SYSCALLS__
  42#include <asm/unistd.h>
  43
  44#include "proto.h"
  45#include "irq_impl.h"
  46
  47
  48#define DEBUG_SMP 0
  49#if DEBUG_SMP
  50#define DBGS(args)      printk args
  51#else
  52#define DBGS(args)
  53#endif
  54
  55/* A collection of per-processor data.  */
  56struct cpuinfo_alpha cpu_data[NR_CPUS];
  57
  58/* A collection of single bit ipi messages.  */
  59static struct {
  60        unsigned long bits ____cacheline_aligned;
  61} ipi_data[NR_CPUS] __cacheline_aligned;
  62
  63enum ipi_message_type {
  64        IPI_RESCHEDULE,
  65        IPI_CALL_FUNC,
  66        IPI_CPU_STOP,
  67};
  68
  69spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
  70
  71/* Set to a secondary's cpuid when it comes online.  */
  72static unsigned long smp_secondary_alive;
  73
  74/* Which cpus ids came online.  */
  75unsigned long cpu_present_mask;
  76
  77/* cpus reported in the hwrpb */
  78static unsigned long hwrpb_cpu_present_mask __initdata = 0;
  79
  80static int max_cpus = -1;       /* Command-line limitation.  */
  81int smp_num_probed;             /* Internal processor count */
  82int smp_num_cpus = 1;           /* Number that came online.  */
  83int smp_threads_ready;          /* True once the per process idle is forked. */
  84cycles_t cacheflush_time;
  85
  86int __cpu_number_map[NR_CPUS];
  87int __cpu_logical_map[NR_CPUS];
  88
  89extern void calibrate_delay(void);
  90extern asmlinkage void entInt(void);
  91
  92
  93static int __init nosmp(char *str)
  94{
  95        max_cpus = 0;
  96        return 1;
  97}
  98
  99__setup("nosmp", nosmp);
 100
 101static int __init maxcpus(char *str)
 102{
 103        get_option(&str, &max_cpus);
 104        return 1;
 105}
 106
 107__setup("maxcpus", maxcpus);
 108
 109
 110/*
 111 * Called by both boot and secondaries to move global data into
 112 *  per-processor storage.
 113 */
 114static inline void __init
 115smp_store_cpu_info(int cpuid)
 116{
 117        cpu_data[cpuid].loops_per_jiffy = loops_per_jiffy;
 118        cpu_data[cpuid].last_asn = ASN_FIRST_VERSION;
 119        cpu_data[cpuid].need_new_asn = 0;
 120        cpu_data[cpuid].asn_lock = 0;
 121        local_irq_count(cpuid) = 0;
 122        local_bh_count(cpuid) = 0;
 123}
 124
 125/*
 126 * Ideally sets up per-cpu profiling hooks.  Doesn't do much now...
 127 */
 128static inline void __init
 129smp_setup_percpu_timer(int cpuid)
 130{
 131        cpu_data[cpuid].prof_counter = 1;
 132        cpu_data[cpuid].prof_multiplier = 1;
 133}
 134
 135static void __init
 136wait_boot_cpu_to_stop(int cpuid)
 137{
 138        long stop = jiffies + 10*HZ;
 139
 140        while (time_before(jiffies, stop)) {
 141                if (!smp_secondary_alive)
 142                        return;
 143                barrier();
 144        }
 145
 146        printk("wait_boot_cpu_to_stop: FAILED on CPU %d, hanging now\n", cpuid);
 147        for (;;)
 148                barrier();
 149}
 150
 151/*
 152 * Where secondaries begin a life of C.
 153 */
 154void __init
 155smp_callin(void)
 156{
 157        int cpuid = hard_smp_processor_id();
 158
 159        if (current != init_tasks[cpu_number_map(cpuid)]) {
 160                printk("BUG: smp_calling: cpu %d current %p init_tasks[cpu_number_map(cpuid)] %p\n",
 161                       cpuid, current, init_tasks[cpu_number_map(cpuid)]);
 162        }
 163
 164        DBGS(("CALLIN %d state 0x%lx\n", cpuid, current->state));
 165
 166        /* Turn on machine checks.  */
 167        wrmces(7);
 168
 169        /* Set trap vectors.  */
 170        trap_init();
 171
 172        /* Set interrupt vector.  */
 173        wrent(entInt, 0);
 174
 175        /* Get our local ticker going. */
 176        smp_setup_percpu_timer(cpuid);
 177
 178        /* Must have completely accurate bogos.  */
 179        __sti();
 180
 181        /*
 182         * Wait boot CPU to stop with irq enabled before
 183         * running calibrate_delay().
 184         */
 185        wait_boot_cpu_to_stop(cpuid);
 186        mb();
 187        calibrate_delay();
 188
 189        smp_store_cpu_info(cpuid);
 190        /*
 191         * Allow master to continue only after we written
 192         * the loops_per_jiffy.
 193         */
 194        wmb();
 195        smp_secondary_alive = 1;
 196
 197        /* Wait for the go code.  */
 198        while (!smp_threads_ready)
 199                barrier();
 200
 201        DBGS(("smp_callin: commencing CPU %d current %p\n",
 202              cpuid, current));
 203
 204        /* Setup the scheduler for this processor.  */
 205        init_idle();
 206
 207        /* ??? This should be in init_idle.  */
 208        atomic_inc(&init_mm.mm_count);
 209        current->active_mm = &init_mm;
 210        /* Do nothing.  */
 211        cpu_idle();
 212}
 213
 214
 215/*
 216 * Rough estimation for SMP scheduling, this is the number of cycles it
 217 * takes for a fully memory-limited process to flush the SMP-local cache.
 218 *
 219 * We are not told how much cache there is, so we have to guess.
 220 */
 221static void __init
 222smp_tune_scheduling (int cpuid)
 223{
 224        struct percpu_struct *cpu;
 225        unsigned long on_chip_cache;
 226        unsigned long freq;
 227
 228        cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset
 229                                      + cpuid * hwrpb->processor_size);
 230        switch (cpu->type)
 231        {
 232        case EV45_CPU:
 233                on_chip_cache = 16 + 16;
 234                break;
 235
 236        case EV5_CPU:
 237        case EV56_CPU:
 238                on_chip_cache = 8 + 8 + 96;
 239                break;
 240
 241        case PCA56_CPU:
 242                on_chip_cache = 16 + 8;
 243                break;
 244
 245        case EV6_CPU:
 246        case EV67_CPU:
 247                on_chip_cache = 64 + 64;
 248                break;
 249
 250        default:
 251                on_chip_cache = 8 + 8;
 252                break;
 253        }
 254
 255        freq = hwrpb->cycle_freq ? : est_cycle_freq;
 256
 257#if 0
 258        /* Magic estimation stolen from x86 port.  */
 259        cacheflush_time = freq / 1024L * on_chip_cache / 5000L;
 260
 261        printk("Using heuristic of %d cycles.\n",
 262               cacheflush_time);
 263#else
 264        /* Magic value to force potential preemption of other CPUs.  */
 265        cacheflush_time = INT_MAX;
 266
 267        printk("Using heuristic of %d cycles.\n",
 268               cacheflush_time);
 269#endif
 270}
 271
 272/*
 273 * Send a message to a secondary's console.  "START" is one such
 274 * interesting message.  ;-)
 275 */
 276static void
 277send_secondary_console_msg(char *str, int cpuid)
 278{
 279        struct percpu_struct *cpu;
 280        register char *cp1, *cp2;
 281        unsigned long cpumask;
 282        size_t len;
 283        long timeout;
 284
 285        cpu = (struct percpu_struct *)
 286                ((char*)hwrpb
 287                 + hwrpb->processor_offset
 288                 + cpuid * hwrpb->processor_size);
 289
 290        cpumask = (1UL << cpuid);
 291        if (hwrpb->txrdy & cpumask)
 292                goto delay1;
 293        ready1:
 294
 295        cp2 = str;
 296        len = strlen(cp2);
 297        *(unsigned int *)&cpu->ipc_buffer[0] = len;
 298        cp1 = (char *) &cpu->ipc_buffer[1];
 299        memcpy(cp1, cp2, len);
 300
 301        /* atomic test and set */
 302        wmb();
 303        set_bit(cpuid, &hwrpb->rxrdy);
 304
 305        if (hwrpb->txrdy & cpumask)
 306                goto delay2;
 307        ready2:
 308        return;
 309
 310delay1:
 311        /* Wait 10 seconds.  Note that jiffies aren't ticking yet.  */
 312        for (timeout = 1000000; timeout > 0; --timeout) {
 313                if (!(hwrpb->txrdy & cpumask))
 314                        goto ready1;
 315                udelay(10);
 316                barrier();
 317        }
 318        goto timeout;
 319
 320delay2:
 321        /* Wait 10 seconds.  */
 322        for (timeout = 1000000; timeout > 0; --timeout) {
 323                if (!(hwrpb->txrdy & cpumask))
 324                        goto ready2;
 325                udelay(10);
 326                barrier();
 327        }
 328        goto timeout;
 329
 330timeout:
 331        printk("Processor %x not ready\n", cpuid);
 332        return;
 333}
 334
 335/*
 336 * A secondary console wants to send a message.  Receive it.
 337 */
 338static void
 339recv_secondary_console_msg(void)
 340{
 341        int mycpu, i, cnt;
 342        unsigned long txrdy = hwrpb->txrdy;
 343        char *cp1, *cp2, buf[80];
 344        struct percpu_struct *cpu;
 345
 346        DBGS(("recv_secondary_console_msg: TXRDY 0x%lx.\n", txrdy));
 347
 348        mycpu = hard_smp_processor_id();
 349
 350        for (i = 0; i < NR_CPUS; i++) {
 351                if (!(txrdy & (1UL << i)))
 352                        continue;
 353
 354                DBGS(("recv_secondary_console_msg: "
 355                      "TXRDY contains CPU %d.\n", i));
 356
 357                cpu = (struct percpu_struct *)
 358                  ((char*)hwrpb
 359                   + hwrpb->processor_offset
 360                   + i * hwrpb->processor_size);
 361
 362                DBGS(("recv_secondary_console_msg: on %d from %d"
 363                      " HALT_REASON 0x%lx FLAGS 0x%lx\n",
 364                      mycpu, i, cpu->halt_reason, cpu->flags));
 365
 366                cnt = cpu->ipc_buffer[0] >> 32;
 367                if (cnt <= 0 || cnt >= 80)
 368                        strcpy(buf, "<<< BOGUS MSG >>>");
 369                else {
 370                        cp1 = (char *) &cpu->ipc_buffer[11];
 371                        cp2 = buf;
 372                        strcpy(cp2, cp1);
 373                        
 374                        while ((cp2 = strchr(cp2, '\r')) != 0) {
 375                                *cp2 = ' ';
 376                                if (cp2[1] == '\n')
 377                                        cp2[1] = ' ';
 378                        }
 379                }
 380
 381                DBGS((KERN_INFO "recv_secondary_console_msg: on %d "
 382                      "message is '%s'\n", mycpu, buf));
 383        }
 384
 385        hwrpb->txrdy = 0;
 386}
 387
 388/*
 389 * Convince the console to have a secondary cpu begin execution.
 390 */
 391static int __init
 392secondary_cpu_start(int cpuid, struct task_struct *idle)
 393{
 394        struct percpu_struct *cpu;
 395        struct pcb_struct *hwpcb;
 396        long timeout;
 397          
 398        cpu = (struct percpu_struct *)
 399                ((char*)hwrpb
 400                 + hwrpb->processor_offset
 401                 + cpuid * hwrpb->processor_size);
 402        hwpcb = (struct pcb_struct *) cpu->hwpcb;
 403
 404        /* Initialize the CPU's HWPCB to something just good enough for
 405           us to get started.  Immediately after starting, we'll swpctx
 406           to the target idle task's ptb.  Reuse the stack in the mean
 407           time.  Precalculate the target PCBB.  */
 408        hwpcb->ksp = (unsigned long) idle + sizeof(union task_union) - 16;
 409        hwpcb->usp = 0;
 410        hwpcb->ptbr = idle->thread.ptbr;
 411        hwpcb->pcc = 0;
 412        hwpcb->asn = 0;
 413        hwpcb->unique = virt_to_phys(&idle->thread);
 414        hwpcb->flags = idle->thread.pal_flags;
 415        hwpcb->res1 = hwpcb->res2 = 0;
 416
 417#if 0
 418        DBGS(("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx UNIQUE 0x%lx\n",
 419              hwpcb->ksp, hwpcb->ptbr, hwrpb->vptb, hwpcb->unique));
 420#endif
 421        DBGS(("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n",
 422              cpuid, idle->state, idle->thread.pal_flags));
 423
 424        /* Setup HWRPB fields that SRM uses to activate secondary CPU */
 425        hwrpb->CPU_restart = __smp_callin;
 426        hwrpb->CPU_restart_data = (unsigned long) __smp_callin;
 427
 428        /* Recalculate and update the HWRPB checksum */
 429        hwrpb_update_checksum(hwrpb);
 430
 431        /*
 432         * Send a "start" command to the specified processor.
 433         */
 434
 435        /* SRM III 3.4.1.3 */
 436        cpu->flags |= 0x22;     /* turn on Context Valid and Restart Capable */
 437        cpu->flags &= ~1;       /* turn off Bootstrap In Progress */
 438        wmb();
 439
 440        send_secondary_console_msg("START\r\n", cpuid);
 441
 442        /* Wait 10 seconds for an ACK from the console.  Note that jiffies 
 443           aren't ticking yet.  */
 444        for (timeout = 1000000; timeout > 0; timeout--) {
 445                if (cpu->flags & 1)
 446                        goto started;
 447                udelay(10);
 448                barrier();
 449        }
 450        printk(KERN_ERR "SMP: Processor %d failed to start.\n", cpuid);
 451        return -1;
 452
 453started:
 454        DBGS(("secondary_cpu_start: SUCCESS for CPU %d!!!\n", cpuid));
 455        return 0;
 456}
 457
 458static int __init fork_by_hand(void)
 459{
 460        struct pt_regs regs;
 461        /*
 462         * don't care about the regs settings since
 463         * we'll never reschedule the forked task.
 464         */
 465        return do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);
 466}
 467
 468/*
 469 * Bring one cpu online.
 470 */
 471static int __init
 472smp_boot_one_cpu(int cpuid, int cpunum)
 473{
 474        struct task_struct *idle;
 475        long timeout;
 476
 477        /* Cook up an idler for this guy.  Note that the address we give
 478           to kernel_thread is irrelevant -- it's going to start where
 479           HWRPB.CPU_restart says to start.  But this gets all the other
 480           task-y sort of data structures set up like we wish.  */
 481        /*
 482         * We can't use kernel_thread since we must avoid to
 483         * reschedule the child.
 484         */
 485        if (fork_by_hand() < 0)
 486                panic("failed fork for CPU %d", cpuid);
 487
 488        idle = init_task.prev_task;
 489        if (!idle)
 490                panic("No idle process for CPU %d", cpuid);
 491        if (idle == &init_task)
 492                panic("idle process is init_task for CPU %d", cpuid);
 493
 494        idle->processor = cpuid;
 495        idle->cpus_runnable = 1 << cpuid; /* we schedule the first task manually */
 496        __cpu_logical_map[cpunum] = cpuid;
 497        __cpu_number_map[cpuid] = cpunum;
 498 
 499        del_from_runqueue(idle);
 500        unhash_process(idle);
 501        init_tasks[cpunum] = idle;
 502
 503        DBGS(("smp_boot_one_cpu: CPU %d state 0x%lx flags 0x%lx\n",
 504              cpuid, idle->state, idle->flags));
 505
 506        /* The secondary will change this once it is happy.  Note that
 507           secondary_cpu_start contains the necessary memory barrier.  */
 508        smp_secondary_alive = -1;
 509
 510        /* Whirrr, whirrr, whirrrrrrrrr... */
 511        if (secondary_cpu_start(cpuid, idle))
 512                return -1;
 513
 514        mb();
 515        /* Notify the secondary CPU it can run calibrate_delay() */
 516        smp_secondary_alive = 0;
 517
 518        /* We've been acked by the console; wait one second for the task
 519           to start up for real.  Note that jiffies aren't ticking yet.  */
 520        for (timeout = 0; timeout < 1000000; timeout++) {
 521                if (smp_secondary_alive == 1)
 522                        goto alive;
 523                udelay(10);
 524                barrier();
 525        }
 526
 527        /* we must invalidate our stuff as we failed to boot the CPU */
 528        __cpu_logical_map[cpunum] = -1;
 529        __cpu_number_map[cpuid] = -1;
 530
 531        /* the idle task is local to us so free it as we don't use it */
 532        free_task_struct(idle);
 533
 534        printk(KERN_ERR "SMP: Processor %d is stuck.\n", cpuid);
 535        return -1;
 536
 537alive:
 538        /* Another "Red Snapper". */
 539        return 0;
 540}
 541
 542/*
 543 * Called from setup_arch.  Detect an SMP system and which processors
 544 * are present.
 545 */
 546void __init
 547setup_smp(void)
 548{
 549        struct percpu_struct *cpubase, *cpu;
 550        int i;
 551
 552        if (boot_cpuid != 0) {
 553                printk(KERN_WARNING "SMP: Booting off cpu %d instead of 0?\n",
 554                       boot_cpuid);
 555        }
 556
 557        if (hwrpb->nr_processors > 1) {
 558                int boot_cpu_palrev;
 559
 560                DBGS(("setup_smp: nr_processors %ld\n",
 561                      hwrpb->nr_processors));
 562
 563                cpubase = (struct percpu_struct *)
 564                        ((char*)hwrpb + hwrpb->processor_offset);
 565                boot_cpu_palrev = cpubase->pal_revision;
 566
 567                for (i = 0; i < hwrpb->nr_processors; i++ ) {
 568                        cpu = (struct percpu_struct *)
 569                                ((char *)cpubase + i*hwrpb->processor_size);
 570                        if ((cpu->flags & 0x1cc) == 0x1cc) {
 571                                smp_num_probed++;
 572                                /* Assume here that "whami" == index */
 573                                hwrpb_cpu_present_mask |= (1UL << i);
 574                                cpu->pal_revision = boot_cpu_palrev;
 575                        }
 576
 577                        DBGS(("setup_smp: CPU %d: flags 0x%lx type 0x%lx\n",
 578                              i, cpu->flags, cpu->type));
 579                        DBGS(("setup_smp: CPU %d: PAL rev 0x%lx\n",
 580                              i, cpu->pal_revision));
 581                }
 582        } else {
 583                smp_num_probed = 1;
 584                hwrpb_cpu_present_mask = (1UL << boot_cpuid);
 585        }
 586        cpu_present_mask = 1UL << boot_cpuid;
 587
 588        printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n",
 589               smp_num_probed, hwrpb_cpu_present_mask);
 590}
 591
 592/*
 593 * Called by smp_init bring all the secondaries online and hold them.
 594 */
 595void __init
 596smp_boot_cpus(void)
 597{
 598        int cpu_count, i;
 599        unsigned long bogosum;
 600
 601        /* Take care of some initial bookkeeping.  */
 602        memset(__cpu_number_map, -1, sizeof(__cpu_number_map));
 603        memset(__cpu_logical_map, -1, sizeof(__cpu_logical_map));
 604        memset(ipi_data, 0, sizeof(ipi_data));
 605
 606        __cpu_number_map[boot_cpuid] = 0;
 607        __cpu_logical_map[0] = boot_cpuid;
 608        current->processor = boot_cpuid;
 609
 610        smp_store_cpu_info(boot_cpuid);
 611        smp_tune_scheduling(boot_cpuid);
 612        smp_setup_percpu_timer(boot_cpuid);
 613
 614        init_idle();
 615
 616        /* ??? This should be in init_idle.  */
 617        atomic_inc(&init_mm.mm_count);
 618        current->active_mm = &init_mm;
 619
 620        /* Nothing to do on a UP box, or when told not to.  */
 621        if (smp_num_probed == 1 || max_cpus == 0) {
 622                printk(KERN_INFO "SMP mode deactivated.\n");
 623                return;
 624        }
 625
 626        printk(KERN_INFO "SMP starting up secondaries.\n");
 627
 628        cpu_count = 1;
 629        for (i = 0; i < NR_CPUS; i++) {
 630                if (i == boot_cpuid)
 631                        continue;
 632
 633                if (((hwrpb_cpu_present_mask >> i) & 1) == 0)
 634                        continue;
 635
 636                if (smp_boot_one_cpu(i, cpu_count))
 637                        continue;
 638
 639                cpu_present_mask |= 1UL << i;
 640                cpu_count++;
 641        }
 642
 643        if (cpu_count == 1) {
 644                printk(KERN_ERR "SMP: Only one lonely processor alive.\n");
 645                return;
 646        }
 647
 648        bogosum = 0;
 649        for (i = 0; i < NR_CPUS; i++) {
 650                if (cpu_present_mask & (1UL << i))
 651                        bogosum += cpu_data[i].loops_per_jiffy;
 652        }
 653        printk(KERN_INFO "SMP: Total of %d processors activated "
 654               "(%lu.%02lu BogoMIPS).\n",
 655               cpu_count, (bogosum + 2500) / (500000/HZ),
 656               ((bogosum + 2500) / (5000/HZ)) % 100);
 657
 658        smp_num_cpus = cpu_count;
 659}
 660
 661/*
 662 * Called by smp_init to release the blocking online cpus once they 
 663 * are all started.
 664 */
 665void __init
 666smp_commence(void)
 667{
 668        /* smp_init sets smp_threads_ready -- that's enough.  */
 669        mb();
 670}
 671
 672
 673void
 674smp_percpu_timer_interrupt(struct pt_regs *regs)
 675{
 676        int cpu = smp_processor_id();
 677        unsigned long user = user_mode(regs);
 678        struct cpuinfo_alpha *data = &cpu_data[cpu];
 679
 680        /* Record kernel PC.  */
 681        if (!user)
 682                alpha_do_profile(regs->pc);
 683
 684        if (!--data->prof_counter) {
 685                /* We need to make like a normal interrupt -- otherwise
 686                   timer interrupts ignore the global interrupt lock,
 687                   which would be a Bad Thing.  */
 688                irq_enter(cpu, RTC_IRQ);
 689
 690                update_process_times(user);
 691
 692                data->prof_counter = data->prof_multiplier;
 693                irq_exit(cpu, RTC_IRQ);
 694
 695                if (softirq_pending(cpu))
 696                        do_softirq();
 697        }
 698}
 699
 700int __init
 701setup_profiling_timer(unsigned int multiplier)
 702{
 703        return -EINVAL;
 704}
 705
 706
 707static void
 708send_ipi_message(unsigned long to_whom, enum ipi_message_type operation)
 709{
 710        long i, j;
 711
 712        /* Reduce the number of memory barriers by doing two loops,
 713           one to set the bits, one to invoke the interrupts.  */
 714
 715        mb();   /* Order out-of-band data and bit setting. */
 716
 717        for (i = 0, j = 1; i < NR_CPUS; ++i, j <<= 1) {
 718                if (to_whom & j)
 719                        set_bit(operation, &ipi_data[i].bits);
 720        }
 721
 722        mb();   /* Order bit setting and interrupt. */
 723
 724        for (i = 0, j = 1; i < NR_CPUS; ++i, j <<= 1) {
 725                if (to_whom & j)
 726                        wripir(i);
 727        }
 728}
 729
 730/* Structure and data for smp_call_function.  This is designed to 
 731   minimize static memory requirements.  Plus it looks cleaner.  */
 732
 733struct smp_call_struct {
 734        void (*func) (void *info);
 735        void *info;
 736        long wait;
 737        atomic_t unstarted_count;
 738        atomic_t unfinished_count;
 739};
 740
 741static struct smp_call_struct *smp_call_function_data;
 742
 743/* Atomicly drop data into a shared pointer.  The pointer is free if
 744   it is initially locked.  If retry, spin until free.  */
 745
 746static inline int
 747pointer_lock (void *lock, void *data, int retry)
 748{
 749        void *old, *tmp;
 750
 751        mb();
 752again:
 753        /* Compare and swap with zero.  */
 754        asm volatile (
 755        "1:     ldq_l   %0,%1\n"
 756        "       mov     %3,%2\n"
 757        "       bne     %0,2f\n"
 758        "       stq_c   %2,%1\n"
 759        "       beq     %2,1b\n"
 760        "2:"
 761        : "=&r"(old), "=m"(*(void **)lock), "=&r"(tmp)
 762        : "r"(data)
 763        : "memory");
 764
 765        if (old == 0)
 766                return 0;
 767        if (! retry)
 768                return -EBUSY;
 769
 770        while (*(void **)lock)
 771                barrier();
 772        goto again;
 773}
 774
 775void
 776handle_ipi(struct pt_regs *regs)
 777{
 778        int this_cpu = smp_processor_id();
 779        unsigned long *pending_ipis = &ipi_data[this_cpu].bits;
 780        unsigned long ops;
 781
 782#if 0
 783        DBGS(("handle_ipi: on CPU %d ops 0x%lx PC 0x%lx\n",
 784              this_cpu, *pending_ipis, regs->pc));
 785#endif
 786
 787        mb();   /* Order interrupt and bit testing. */
 788        while ((ops = xchg(pending_ipis, 0)) != 0) {
 789          mb(); /* Order bit clearing and data access. */
 790          do {
 791                unsigned long which;
 792
 793                which = ops & -ops;
 794                ops &= ~which;
 795                which = ffz(~which);
 796
 797                if (which == IPI_RESCHEDULE) {
 798                        /* Reschedule callback.  Everything to be done
 799                           is done by the interrupt return path.  */
 800                }
 801                else if (which == IPI_CALL_FUNC) {
 802                        struct smp_call_struct *data;
 803                        void (*func)(void *info);
 804                        void *info;
 805                        int wait;
 806
 807                        data = smp_call_function_data;
 808                        func = data->func;
 809                        info = data->info;
 810                        wait = data->wait;
 811
 812                        /* Notify the sending CPU that the data has been
 813                           received, and execution is about to begin.  */
 814                        mb();
 815                        atomic_dec (&data->unstarted_count);
 816
 817                        /* At this point the structure may be gone unless
 818                           wait is true.  */
 819                        (*func)(info);
 820
 821                        /* Notify the sending CPU that the task is done.  */
 822                        mb();
 823                        if (wait) atomic_dec (&data->unfinished_count);
 824                }
 825                else if (which == IPI_CPU_STOP) {
 826                        halt();
 827                }
 828                else {
 829                        printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n",
 830                               this_cpu, which);
 831                }
 832          } while (ops);
 833
 834          mb(); /* Order data access and bit testing. */
 835        }
 836
 837        cpu_data[this_cpu].ipi_count++;
 838
 839        if (hwrpb->txrdy)
 840                recv_secondary_console_msg();
 841}
 842
 843void
 844smp_send_reschedule(int cpu)
 845{
 846#if DEBUG_IPI_MSG
 847        if (cpu == hard_smp_processor_id())
 848                printk(KERN_WARNING
 849                       "smp_send_reschedule: Sending IPI to self.\n");
 850#endif
 851        send_ipi_message(1UL << cpu, IPI_RESCHEDULE);
 852}
 853
 854void
 855smp_send_stop(void)
 856{
 857        unsigned long to_whom = cpu_present_mask ^ (1UL << smp_processor_id());
 858#if DEBUG_IPI_MSG
 859        if (hard_smp_processor_id() != boot_cpu_id)
 860                printk(KERN_WARNING "smp_send_stop: Not on boot cpu.\n");
 861#endif
 862        send_ipi_message(to_whom, IPI_CPU_STOP);
 863}
 864
 865/*
 866 * Run a function on all other CPUs.
 867 *  <func>      The function to run. This must be fast and non-blocking.
 868 *  <info>      An arbitrary pointer to pass to the function.
 869 *  <retry>     If true, keep retrying until ready.
 870 *  <wait>      If true, wait until function has completed on other CPUs.
 871 *  [RETURNS]   0 on success, else a negative status code.
 872 *
 873 * Does not return until remote CPUs are nearly ready to execute <func>
 874 * or are or have executed.
 875 */
 876
 877int
 878smp_call_function_on_cpu (void (*func) (void *info), void *info, int retry,
 879                          int wait, unsigned long to_whom)
 880{
 881        struct smp_call_struct data;
 882        long timeout;
 883        int num_cpus_to_call;
 884        long i,j;
 885        
 886        data.func = func;
 887        data.info = info;
 888        data.wait = wait;
 889
 890        to_whom &= ~(1L << smp_processor_id());
 891        for (i = 0, j = 1, num_cpus_to_call = 0; i < NR_CPUS; ++i, j <<= 1)
 892                if (to_whom & j)
 893                        num_cpus_to_call++;
 894
 895        atomic_set(&data.unstarted_count, num_cpus_to_call);
 896        atomic_set(&data.unfinished_count, num_cpus_to_call);
 897
 898        /* Acquire the smp_call_function_data mutex.  */
 899        if (pointer_lock(&smp_call_function_data, &data, retry))
 900                return -EBUSY;
 901
 902        /* Send a message to the requested CPUs.  */
 903        send_ipi_message(to_whom, IPI_CALL_FUNC);
 904
 905        /* Wait for a minimal response.  */
 906        timeout = jiffies + HZ;
 907        while (atomic_read (&data.unstarted_count) > 0
 908               && time_before (jiffies, timeout))
 909                barrier();
 910
 911        /* We either got one or timed out -- clear the lock.  */
 912        mb();
 913        smp_call_function_data = 0;
 914        if (atomic_read (&data.unstarted_count) > 0)
 915                return -ETIMEDOUT;
 916
 917        /* Wait for a complete response, if needed.  */
 918        if (wait) {
 919                while (atomic_read (&data.unfinished_count) > 0)
 920                        barrier();
 921        }
 922
 923        return 0;
 924}
 925
 926int
 927smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
 928{
 929        return smp_call_function_on_cpu (func, info, retry, wait,
 930                                         cpu_present_mask);
 931}
 932
 933static void
 934ipi_imb(void *ignored)
 935{
 936        imb();
 937}
 938
 939void
 940smp_imb(void)
 941{
 942        /* Must wait other processors to flush their icache before continue. */
 943        if (smp_call_function(ipi_imb, NULL, 1, 1))
 944                printk(KERN_CRIT "smp_imb: timed out\n");
 945
 946        imb();
 947}
 948
 949static void
 950ipi_flush_tlb_all(void *ignored)
 951{
 952        tbia();
 953}
 954
 955void
 956flush_tlb_all(void)
 957{
 958        /* Although we don't have any data to pass, we do want to
 959           synchronize with the other processors.  */
 960        if (smp_call_function(ipi_flush_tlb_all, NULL, 1, 1)) {
 961                printk(KERN_CRIT "flush_tlb_all: timed out\n");
 962        }
 963
 964        tbia();
 965}
 966
 967#define asn_locked() (cpu_data[smp_processor_id()].asn_lock)
 968
 969static void
 970ipi_flush_tlb_mm(void *x)
 971{
 972        struct mm_struct *mm = (struct mm_struct *) x;
 973        if (mm == current->active_mm && !asn_locked())
 974                flush_tlb_current(mm);
 975        else
 976                flush_tlb_other(mm);
 977}
 978
 979void
 980flush_tlb_mm(struct mm_struct *mm)
 981{
 982        if (mm == current->active_mm) {
 983                flush_tlb_current(mm);
 984                if (atomic_read(&mm->mm_users) <= 1) {
 985                        int i, cpu, this_cpu = smp_processor_id();
 986                        for (i = 0; i < smp_num_cpus; i++) {
 987                                cpu = cpu_logical_map(i);
 988                                if (cpu == this_cpu)
 989                                        continue;
 990                                if (mm->context[cpu])
 991                                        mm->context[cpu] = 0;
 992                        }
 993                        return;
 994                }
 995        }
 996
 997        if (smp_call_function(ipi_flush_tlb_mm, mm, 1, 1)) {
 998                printk(KERN_CRIT "flush_tlb_mm: timed out\n");
 999        }
1000}
1001
1002struct flush_tlb_page_struct {
1003        struct vm_area_struct *vma;
1004        struct mm_struct *mm;
1005        unsigned long addr;
1006};
1007
1008static void
1009ipi_flush_tlb_page(void *x)
1010{
1011        struct flush_tlb_page_struct *data = (struct flush_tlb_page_struct *)x;
1012        struct mm_struct * mm = data->mm;
1013
1014        if (mm == current->active_mm && !asn_locked())
1015                flush_tlb_current_page(mm, data->vma, data->addr);
1016        else
1017                flush_tlb_other(mm);
1018}
1019
1020void
1021flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
1022{
1023        struct flush_tlb_page_struct data;
1024        struct mm_struct *mm = vma->vm_mm;
1025
1026        if (mm == current->active_mm) {
1027                flush_tlb_current_page(mm, vma, addr);
1028                if (atomic_read(&mm->mm_users) <= 1) {
1029                        int i, cpu, this_cpu = smp_processor_id();
1030                        for (i = 0; i < smp_num_cpus; i++) {
1031                                cpu = cpu_logical_map(i);
1032                                if (cpu == this_cpu)
1033                                        continue;
1034                                if (mm->context[cpu])
1035                                        mm->context[cpu] = 0;
1036                        }
1037                        return;
1038                }
1039        }
1040
1041        data.vma = vma;
1042        data.mm = mm;
1043        data.addr = addr;
1044
1045        if (smp_call_function(ipi_flush_tlb_page, &data, 1, 1)) {
1046                printk(KERN_CRIT "flush_tlb_page: timed out\n");
1047        }
1048}
1049
1050void
1051flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
1052{
1053        /* On the Alpha we always flush the whole user tlb.  */
1054        flush_tlb_mm(mm);
1055}
1056
1057static void
1058ipi_flush_icache_page(void *x)
1059{
1060        struct mm_struct *mm = (struct mm_struct *) x;
1061        if (mm == current->active_mm && !asn_locked())
1062                __load_new_mm_context(mm);
1063        else
1064                flush_tlb_other(mm);
1065}
1066
1067void
1068flush_icache_page(struct vm_area_struct *vma, struct page *page)
1069{
1070        struct mm_struct *mm = vma->vm_mm;
1071
1072        if ((vma->vm_flags & VM_EXEC) == 0)
1073                return;
1074
1075        if (mm == current->active_mm) {
1076                __load_new_mm_context(mm);
1077                if (atomic_read(&mm->mm_users) <= 1) {
1078                        int i, cpu, this_cpu = smp_processor_id();
1079                        for (i = 0; i < smp_num_cpus; i++) {
1080                                cpu = cpu_logical_map(i);
1081                                if (cpu == this_cpu)
1082                                        continue;
1083                                if (mm->context[cpu])
1084                                        mm->context[cpu] = 0;
1085                        }
1086                        return;
1087                }
1088        }
1089
1090        if (smp_call_function(ipi_flush_icache_page, mm, 1, 1)) {
1091                printk(KERN_CRIT "flush_icache_page: timed out\n");
1092        }
1093}
1094
1095#ifdef CONFIG_DEBUG_SPINLOCK
1096void
1097spin_unlock(spinlock_t * lock)
1098{
1099        mb();
1100        lock->lock = 0;
1101
1102        lock->on_cpu = -1;
1103        lock->previous = NULL;
1104        lock->task = NULL;
1105        lock->base_file = "none";
1106        lock->line_no = 0;
1107}
1108
1109void
1110debug_spin_lock(spinlock_t * lock, const char *base_file, int line_no)
1111{
1112        long tmp;
1113        long stuck;
1114        void *inline_pc = __builtin_return_address(0);
1115        unsigned long started = jiffies;
1116        int printed = 0;
1117        int cpu = smp_processor_id();
1118
1119        stuck = 1L << 30;
1120 try_again:
1121
1122        /* Use sub-sections to put the actual loop at the end
1123           of this object file's text section so as to perfect
1124           branch prediction.  */
1125        __asm__ __volatile__(
1126        "1:     ldl_l   %0,%1\n"
1127        "       subq    %2,1,%2\n"
1128        "       blbs    %0,2f\n"
1129        "       or      %0,1,%0\n"
1130        "       stl_c   %0,%1\n"
1131        "       beq     %0,3f\n"
1132        "4:     mb\n"
1133        ".subsection 2\n"
1134        "2:     ldl     %0,%1\n"
1135        "       subq    %2,1,%2\n"
1136        "3:     blt     %2,4b\n"
1137        "       blbs    %0,2b\n"
1138        "       br      1b\n"
1139        ".previous"
1140        : "=r" (tmp), "=m" (lock->lock), "=r" (stuck)
1141        : "1" (lock->lock), "2" (stuck) : "memory");
1142
1143        if (stuck < 0) {
1144                printk(KERN_WARNING
1145                       "%s:%d spinlock stuck in %s at %p(%d)"
1146                       " owner %s at %p(%d) %s:%d\n",
1147                       base_file, line_no,
1148                       current->comm, inline_pc, cpu,
1149                       lock->task->comm, lock->previous,
1150                       lock->on_cpu, lock->base_file, lock->line_no);
1151                stuck = 1L << 36;
1152                printed = 1;
1153                goto try_again;
1154        }
1155
1156        /* Exiting.  Got the lock.  */
1157        lock->on_cpu = cpu;
1158        lock->previous = inline_pc;
1159        lock->task = current;
1160        lock->base_file = base_file;
1161        lock->line_no = line_no;
1162
1163        if (printed) {
1164                printk(KERN_WARNING
1165                       "%s:%d spinlock grabbed in %s at %p(%d) %ld ticks\n",
1166                       base_file, line_no, current->comm, inline_pc,
1167                       cpu, jiffies - started);
1168        }
1169}
1170
1171int
1172debug_spin_trylock(spinlock_t * lock, const char *base_file, int line_no)
1173{
1174        int ret;
1175        if ((ret = !test_and_set_bit(0, lock))) {
1176                lock->on_cpu = smp_processor_id();
1177                lock->previous = __builtin_return_address(0);
1178                lock->task = current;
1179        } else {
1180                lock->base_file = base_file;
1181                lock->line_no = line_no;
1182        }
1183        return ret;
1184}
1185#endif /* CONFIG_DEBUG_SPINLOCK */
1186
1187#ifdef CONFIG_DEBUG_RWLOCK
1188void write_lock(rwlock_t * lock)
1189{
1190        long regx, regy;
1191        int stuck_lock, stuck_reader;
1192        void *inline_pc = __builtin_return_address(0);
1193
1194 try_again:
1195
1196        stuck_lock = 1<<30;
1197        stuck_reader = 1<<30;
1198
1199        __asm__ __volatile__(
1200        "1:     ldl_l   %1,%0\n"
1201        "       blbs    %1,6f\n"
1202        "       blt     %1,8f\n"
1203        "       mov     1,%1\n"
1204        "       stl_c   %1,%0\n"
1205        "       beq     %1,6f\n"
1206        "4:     mb\n"
1207        ".subsection 2\n"
1208        "6:     blt     %3,4b   # debug\n"
1209        "       subl    %3,1,%3 # debug\n"
1210        "       ldl     %1,%0\n"
1211        "       blbs    %1,6b\n"
1212        "8:     blt     %4,4b   # debug\n"
1213        "       subl    %4,1,%4 # debug\n"
1214        "       ldl     %1,%0\n"
1215        "       blt     %1,8b\n"
1216        "       br      1b\n"
1217        ".previous"
1218        : "=m" (*(volatile int *)lock), "=&r" (regx), "=&r" (regy),
1219          "=&r" (stuck_lock), "=&r" (stuck_reader)
1220        : "0" (*(volatile int *)lock), "3" (stuck_lock), "4" (stuck_reader) : "memory");
1221
1222        if (stuck_lock < 0) {
1223                printk(KERN_WARNING "write_lock stuck at %p\n", inline_pc);
1224                goto try_again;
1225        }
1226        if (stuck_reader < 0) {
1227                printk(KERN_WARNING "write_lock stuck on readers at %p\n",
1228                       inline_pc);
1229                goto try_again;
1230        }
1231}
1232
1233void read_lock(rwlock_t * lock)
1234{
1235        long regx;
1236        int stuck_lock;
1237        void *inline_pc = __builtin_return_address(0);
1238
1239 try_again:
1240
1241        stuck_lock = 1<<30;
1242
1243        __asm__ __volatile__(
1244        "1:     ldl_l   %1,%0;"
1245        "       blbs    %1,6f;"
1246        "       subl    %1,2,%1;"
1247        "       stl_c   %1,%0;"
1248        "       beq     %1,6f;"
1249        "4:     mb\n"
1250        ".subsection 2\n"
1251        "6:     ldl     %1,%0;"
1252        "       blt     %2,4b   # debug\n"
1253        "       subl    %2,1,%2 # debug\n"
1254        "       blbs    %1,6b;"
1255        "       br      1b\n"
1256        ".previous"
1257        : "=m" (*(volatile int *)lock), "=&r" (regx), "=&r" (stuck_lock)
1258        : "0" (*(volatile int *)lock), "2" (stuck_lock) : "memory");
1259
1260        if (stuck_lock < 0) {
1261                printk(KERN_WARNING "read_lock stuck at %p\n", inline_pc);
1262                goto try_again;
1263        }
1264}
1265#endif /* CONFIG_DEBUG_RWLOCK */
1266
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.