OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [ia64/] [kernel/] [smpboot.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * SMP boot-related support
3
 *
4
 * Copyright (C) 1998-2003 Hewlett-Packard Co
5
 *      David Mosberger-Tang <davidm@hpl.hp.com>
6
 *
7
 * 01/05/16 Rohit Seth <rohit.seth@intel.com>   Moved SMP booting functions from smp.c to here.
8
 * 01/04/27 David Mosberger <davidm@hpl.hp.com> Added ITC synching code.
9
 */
10
 
11
 
12
#define __KERNEL_SYSCALLS__
13
 
14
#include <linux/config.h>
15
 
16
#include <linux/bootmem.h>
17
#include <linux/delay.h>
18
#include <linux/init.h>
19
#include <linux/interrupt.h>
20
#include <linux/irq.h>
21
#include <linux/kernel.h>
22
#include <linux/kernel_stat.h>
23
#include <linux/mm.h>
24
#include <linux/smp.h>
25
#include <linux/smp_lock.h>
26
#include <linux/spinlock.h>
27
#include <linux/efi.h>
28
 
29
#include <asm/atomic.h>
30
#include <asm/bitops.h>
31
#include <asm/cache.h>
32
#include <asm/current.h>
33
#include <asm/delay.h>
34
#include <asm/io.h>
35
#include <asm/irq.h>
36
#include <asm/machvec.h>
37
#include <asm/mca.h>
38
#include <asm/page.h>
39
#include <asm/pgalloc.h>
40
#include <asm/pgtable.h>
41
#include <asm/processor.h>
42
#include <asm/ptrace.h>
43
#include <asm/sal.h>
44
#include <asm/system.h>
45
#include <asm/unistd.h>
46
 
47
#define SMP_DEBUG 0
48
 
49
#if SMP_DEBUG
50
#define Dprintk(x...)  printk(x)
51
#else
52
#define Dprintk(x...)
53
#endif
54
 
55
 
56
/*
57
 * ITC synchronization related stuff:
58
 */
59
#define MASTER  0
60
#define SLAVE   (SMP_CACHE_BYTES/8)
61
 
62
#define NUM_ROUNDS      64      /* magic value */
63
#define NUM_ITERS       5       /* likewise */
64
 
65
static spinlock_t itc_sync_lock = SPIN_LOCK_UNLOCKED;
66
static volatile unsigned long go[SLAVE + 1];
67
 
68
#define DEBUG_ITC_SYNC  0
69
 
70
extern void __init calibrate_delay (void);
71
extern void start_ap (void);
72
extern unsigned long ia64_iobase;
73
 
74
int cpucount;
75
 
76
/* Setup configured maximum number of CPUs to activate */
77
static int max_cpus = -1;
78
 
79
/* Total count of live CPUs */
80
int smp_num_cpus = 1;
81
 
82
/* Bitmask of currently online CPUs */
83
volatile unsigned long cpu_online_map;
84
 
85
/* which logical CPU number maps to which CPU (physical APIC ID) */
86
volatile int ia64_cpu_to_sapicid[NR_CPUS];
87
 
88
static volatile unsigned long cpu_callin_map;
89
 
90
struct smp_boot_data smp_boot_data __initdata;
91
 
92
/* Set when the idlers are all forked */
93
int smp_threads_ready;
94
 
95
unsigned long ap_wakeup_vector = -1; /* External Int use to wakeup APs */
96
 
97
char __initdata no_int_routing;
98
 
99
unsigned char smp_int_redirect; /* are INT and IPI redirectable by the chipset? */
100
 
101
/*
102
 * Setup routine for controlling SMP activation
103
 *
104
 * Command-line option of "nosmp" or "maxcpus=0" will disable SMP
105
 * activation entirely (the MPS table probe still happens, though).
106
 *
107
 * Command-line option of "maxcpus=<NUM>", where <NUM> is an integer
108
 * greater than 0, limits the maximum number of CPUs activated in
109
 * SMP mode to <NUM>.
110
 */
111
 
112
static int __init
113
nosmp (char *str)
114
{
115
        max_cpus = 0;
116
        return 1;
117
}
118
 
119
__setup("nosmp", nosmp);
120
 
121
static int __init
122
maxcpus (char *str)
123
{
124
        get_option(&str, &max_cpus);
125
        return 1;
126
}
127
 
128
__setup("maxcpus=", maxcpus);
129
 
130
static int __init
131
nointroute (char *str)
132
{
133
        no_int_routing = 1;
134
        return 1;
135
}
136
 
137
__setup("nointroute", nointroute);
138
 
139
void
140
sync_master (void *arg)
141
{
142
        unsigned long flags, i;
143
 
144
        go[MASTER] = 0;
145
 
146
        local_irq_save(flags);
147
        {
148
                for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) {
149
                        while (!go[MASTER]);
150
                        go[MASTER] = 0;
151
                        go[SLAVE] = ia64_get_itc();
152
                }
153
        }
154
        local_irq_restore(flags);
155
}
156
 
157
/*
158
 * Return the number of cycles by which our itc differs from the itc on the master
159
 * (time-keeper) CPU.  A positive number indicates our itc is ahead of the master,
160
 * negative that it is behind.
161
 */
162
static inline long
163
get_delta (long *rt, long *master)
164
{
165
        unsigned long best_t0 = 0, best_t1 = ~0UL, best_tm = 0;
166
        unsigned long tcenter, t0, t1, tm;
167
        long i;
168
 
169
        for (i = 0; i < NUM_ITERS; ++i) {
170
                t0 = ia64_get_itc();
171
                go[MASTER] = 1;
172
                while (!(tm = go[SLAVE]));
173
                go[SLAVE] = 0;
174
                t1 = ia64_get_itc();
175
 
176
                if (t1 - t0 < best_t1 - best_t0)
177
                        best_t0 = t0, best_t1 = t1, best_tm = tm;
178
        }
179
 
180
        *rt = best_t1 - best_t0;
181
        *master = best_tm - best_t0;
182
 
183
        /* average best_t0 and best_t1 without overflow: */
184
        tcenter = (best_t0/2 + best_t1/2);
185
        if (best_t0 % 2 + best_t1 % 2 == 2)
186
                ++tcenter;
187
        return tcenter - best_tm;
188
}
189
 
190
/*
191
 * Synchronize ar.itc of the current (slave) CPU with the ar.itc of the MASTER CPU
192
 * (normally the time-keeper CPU).  We use a closed loop to eliminate the possibility of
193
 * unaccounted-for errors (such as getting a machine check in the middle of a calibration
194
 * step).  The basic idea is for the slave to ask the master what itc value it has and to
195
 * read its own itc before and after the master responds.  Each iteration gives us three
196
 * timestamps:
197
 *
198
 *      slave           master
199
 *
200
 *      t0 ---\
201
 *             ---\
202
 *                 --->
203
 *                      tm
204
 *                 /---
205
 *             /---
206
 *      t1 <---
207
 *
208
 *
209
 * The goal is to adjust the slave's ar.itc such that tm falls exactly half-way between t0
210
 * and t1.  If we achieve this, the clocks are synchronized provided the interconnect
211
 * between the slave and the master is symmetric.  Even if the interconnect were
212
 * asymmetric, we would still know that the synchronization error is smaller than the
213
 * roundtrip latency (t0 - t1).
214
 *
215
 * When the interconnect is quiet and symmetric, this lets us synchronize the itc to
216
 * within one or two cycles.  However, we can only *guarantee* that the synchronization is
217
 * accurate to within a round-trip time, which is typically in the range of several
218
 * hundred cycles (e.g., ~500 cycles).  In practice, this means that the itc's are usually
219
 * almost perfectly synchronized, but we shouldn't assume that the accuracy is much better
220
 * than half a micro second or so.
221
 */
222
void
223
ia64_sync_itc (unsigned int master)
224
{
225
        long i, delta, adj, adjust_latency = 0, done = 0;
226
        unsigned long flags, rt, master_time_stamp, bound;
227
#if DEBUG_ITC_SYNC
228
        struct {
229
                long rt;        /* roundtrip time */
230
                long master;    /* master's timestamp */
231
                long diff;      /* difference between midpoint and master's timestamp */
232
                long lat;       /* estimate of itc adjustment latency */
233
        } t[NUM_ROUNDS];
234
#endif
235
 
236
        go[MASTER] = 1;
237
 
238
        if (smp_call_function_single(master, sync_master, NULL, 1, 0) < 0) {
239
                printk(KERN_ERR "sync_itc: failed to get attention of CPU %u!\n", master);
240
                return;
241
        }
242
 
243
        while (go[MASTER]);     /* wait for master to be ready */
244
 
245
        spin_lock_irqsave(&itc_sync_lock, flags);
246
        {
247
                for (i = 0; i < NUM_ROUNDS; ++i) {
248
                        delta = get_delta(&rt, &master_time_stamp);
249
                        if (delta == 0) {
250
                                done = 1;       /* let's lock on to this... */
251
                                bound = rt;
252
                        }
253
 
254
                        if (!done) {
255
                                if (i > 0) {
256
                                        adjust_latency += -delta;
257
                                        adj = -delta + adjust_latency/4;
258
                                } else
259
                                        adj = -delta;
260
 
261
                                ia64_set_itc(ia64_get_itc() + adj);
262
                        }
263
#if DEBUG_ITC_SYNC
264
                        t[i].rt = rt;
265
                        t[i].master = master_time_stamp;
266
                        t[i].diff = delta;
267
                        t[i].lat = adjust_latency/4;
268
#endif
269
                }
270
        }
271
        spin_unlock_irqrestore(&itc_sync_lock, flags);
272
 
273
#if DEBUG_ITC_SYNC
274
        for (i = 0; i < NUM_ROUNDS; ++i)
275
                printk("rt=%5ld master=%5ld diff=%5ld adjlat=%5ld\n",
276
                       t[i].rt, t[i].master, t[i].diff, t[i].lat);
277
#endif
278
 
279
        printk(KERN_INFO "CPU %d: synchronized ITC with CPU %u (last diff %ld cycles, "
280
               "maxerr %lu cycles)\n", smp_processor_id(), master, delta, rt);
281
}
282
 
283
/*
284
 * Ideally sets up per-cpu profiling hooks.  Doesn't do much now...
285
 */
286
static inline void __init
287
smp_setup_percpu_timer (void)
288
{
289
        local_cpu_data->prof_counter = 1;
290
        local_cpu_data->prof_multiplier = 1;
291
}
292
 
293
/*
294
 * Architecture specific routine called by the kernel just before init is
295
 * fired off. This allows the BP to have everything in order [we hope].
296
 * At the end of this all the APs will hit the system scheduling and off
297
 * we go. Each AP will jump through the kernel
298
 * init into idle(). At this point the scheduler will one day take over
299
 * and give them jobs to do. smp_callin is a standard routine
300
 * we use to track CPUs as they power up.
301
 */
302
 
303
static volatile atomic_t smp_commenced = ATOMIC_INIT(0);
304
 
305
void __init
306
smp_commence (void)
307
{
308
        /*
309
         * Lets the callins below out of their loop.
310
         */
311
        Dprintk("Setting commenced=1, go go go\n");
312
 
313
        wmb();
314
        atomic_set(&smp_commenced,1);
315
}
316
 
317
 
318
static void __init
319
smp_callin (void)
320
{
321
        int cpuid, phys_id;
322
        extern void ia64_init_itm(void);
323
        extern void ia64_cpu_local_tick(void);
324
 
325
#ifdef CONFIG_PERFMON
326
        extern void pfm_init_percpu(void);
327
#endif
328
 
329
        cpuid = smp_processor_id();
330
        phys_id = hard_smp_processor_id();
331
 
332
        if (test_and_set_bit(cpuid, &cpu_online_map)) {
333
                printk(KERN_ERR "huh, phys CPU#0x%x, CPU#0x%x already present??\n",
334
                       phys_id, cpuid);
335
                BUG();
336
        }
337
 
338
        smp_setup_percpu_timer();
339
 
340
        /*
341
         * Get our bogomips.
342
         */
343
        ia64_init_itm();
344
 
345
        /*
346
         * Set I/O port base per CPU
347
         */
348
        ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
349
 
350
#ifdef CONFIG_IA64_MCA
351
        ia64_mca_cmc_vector_setup();    /* Setup vector on AP & enable */
352
#endif
353
 
354
#ifdef CONFIG_PERFMON
355
        pfm_init_percpu();
356
#endif
357
 
358
        local_irq_enable();
359
        calibrate_delay();
360
        local_cpu_data->loops_per_jiffy = loops_per_jiffy;
361
 
362
        if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) {
363
                /*
364
                 * Synchronize the ITC with the BP.  Need to do this after irqs are
365
                 * enabled because ia64_sync_itc() calls smp_call_function_single(), which
366
                 * calls spin_unlock_bh(), which calls spin_unlock_bh(), which calls
367
                 * local_bh_enable(), which bugs out if irqs are not enabled...
368
                 */
369
                Dprintk("Going to syncup ITC with BP.\n");
370
                ia64_sync_itc(0);
371
 
372
                /*
373
                 * Make sure we didn't sync the itc ahead of the next
374
                 * timer interrupt, if so, just reset it.
375
                 */
376
                if (time_after(ia64_get_itc(),local_cpu_data->itm_next)) {
377
                        Dprintk("oops, jumped a timer.\n");
378
                        ia64_cpu_local_tick();
379
                }
380
        }
381
 
382
        /*
383
         * Allow the master to continue.
384
         */
385
        set_bit(cpuid, &cpu_callin_map);
386
        Dprintk("Stack on CPU %d at about %p\n",cpuid, &cpuid);
387
}
388
 
389
 
390
/*
391
 * Activate a secondary processor.  head.S calls this.
392
 */
393
int __init
394
start_secondary (void *unused)
395
{
396
        extern int cpu_idle (void);
397
 
398
        Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id());
399
        efi_map_pal_code();
400
        cpu_init();
401
        smp_callin();
402
        Dprintk("CPU %d is set to go.\n", smp_processor_id());
403
        while (!atomic_read(&smp_commenced))
404
                ;
405
 
406
        Dprintk("CPU %d is starting idle.\n", smp_processor_id());
407
        return cpu_idle();
408
}
409
 
410
static int __init
411
fork_by_hand (void)
412
{
413
        /*
414
         * don't care about the eip and regs settings since we'll never reschedule the
415
         * forked task.
416
         */
417
        return do_fork(CLONE_VM|CLONE_PID, 0, 0, 0);
418
}
419
 
420
static void __init
421
do_boot_cpu (int sapicid)
422
{
423
        struct task_struct *idle;
424
        int timeout, cpu;
425
 
426
        cpu = ++cpucount;
427
        /*
428
         * We can't use kernel_thread since we must avoid to
429
         * reschedule the child.
430
         */
431
        if (fork_by_hand() < 0)
432
                panic("failed fork for CPU %d", cpu);
433
 
434
        /*
435
         * We remove it from the pidhash and the runqueue
436
         * once we got the process:
437
         */
438
        idle = init_task.prev_task;
439
        if (!idle)
440
                panic("No idle process for CPU %d", cpu);
441
 
442
        task_set_cpu(idle, cpu);        /* we schedule the first task manually */
443
 
444
        ia64_cpu_to_sapicid[cpu] = sapicid;
445
 
446
        del_from_runqueue(idle);
447
        unhash_process(idle);
448
        init_tasks[cpu] = idle;
449
 
450
        Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
451
 
452
        platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0);
453
 
454
        /*
455
         * Wait 10s total for the AP to start
456
         */
457
        Dprintk("Waiting on callin_map ...");
458
        for (timeout = 0; timeout < 100000; timeout++) {
459
                if (test_bit(cpu, &cpu_callin_map))
460
                        break;  /* It has booted */
461
                udelay(100);
462
        }
463
        Dprintk("\n");
464
 
465
        if (test_bit(cpu, &cpu_callin_map)) {
466
                /* number CPUs logically, starting from 1 (BSP is 0) */
467
                printk(KERN_INFO "CPU%d: CPU has booted.\n", cpu);
468
        } else {
469
                printk(KERN_ERR "Processor 0x%x/0x%x is stuck.\n", cpu, sapicid);
470
                ia64_cpu_to_sapicid[cpu] = -1;
471
                cpucount--;
472
        }
473
}
474
 
475
/*
476
 * Cycle through the APs sending Wakeup IPIs to boot each.
477
 */
478
void __init
479
smp_boot_cpus (void)
480
{
481
        int sapicid, cpu;
482
        int boot_cpu_id = hard_smp_processor_id();
483
 
484
        /*
485
         * Initialize the logical to physical CPU number mapping
486
         * and the per-CPU profiling counter/multiplier
487
         */
488
 
489
        for (cpu = 0; cpu < NR_CPUS; cpu++)
490
                ia64_cpu_to_sapicid[cpu] = -1;
491
        smp_setup_percpu_timer();
492
 
493
        /*
494
         * We have the boot CPU online for sure.
495
         */
496
        set_bit(0, &cpu_online_map);
497
        set_bit(0, &cpu_callin_map);
498
 
499
        local_cpu_data->loops_per_jiffy = loops_per_jiffy;
500
        ia64_cpu_to_sapicid[0] = boot_cpu_id;
501
 
502
        printk(KERN_INFO "Boot processor id 0x%x/0x%x\n", 0, boot_cpu_id);
503
 
504
        global_irq_holder = 0;
505
        current->processor = 0;
506
        init_idle();
507
 
508
        /*
509
         * If SMP should be disabled, then really disable it!
510
         */
511
        if (!max_cpus || (max_cpus < -1)) {
512
                printk(KERN_INFO "SMP mode deactivated.\n");
513
                cpu_online_map =  1;
514
                smp_num_cpus = 1;
515
                goto smp_done;
516
        }
517
        if  (max_cpus != -1)
518
                printk(KERN_INFO "Limiting CPUs to %d\n", max_cpus);
519
 
520
        if (smp_boot_data.cpu_count > 1) {
521
 
522
                printk(KERN_INFO "SMP: starting up secondaries.\n");
523
 
524
                for (cpu = 0; cpu < smp_boot_data.cpu_count; cpu++) {
525
                        /*
526
                         * Don't even attempt to start the boot CPU!
527
                         */
528
                        sapicid = smp_boot_data.cpu_phys_id[cpu];
529
                        if ((sapicid == -1) || (sapicid == hard_smp_processor_id()))
530
                                continue;
531
 
532
                        if ((max_cpus > 0) && (cpucount + 1 >= max_cpus))
533
                                break;
534
 
535
                        do_boot_cpu(sapicid);
536
                }
537
 
538
                smp_num_cpus = cpucount + 1;
539
 
540
                /*
541
                 * Allow the user to impress friends.
542
                 */
543
 
544
                printk("Before bogomips.\n");
545
                if (!cpucount) {
546
                        printk(KERN_WARNING "Warning: only one processor found.\n");
547
                } else {
548
                        unsigned long bogosum = 0;
549
                        for (cpu = 0; cpu < NR_CPUS; cpu++)
550
                                if (cpu_online_map & (1UL << cpu))
551
                                        bogosum += cpu_data(cpu)->loops_per_jiffy;
552
 
553
                        printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
554
                               cpucount + 1, bogosum/(500000/HZ), (bogosum/(5000/HZ))%100);
555
                }
556
        }
557
  smp_done:
558
        ;
559
}
560
 
561
/*
562
 * Assume that CPU's have been discovered by some platform-dependent interface.  For
563
 * SoftSDV/Lion, that would be ACPI.
564
 *
565
 * Setup of the IPI irq handler is done in irq.c:init_IRQ_SMP().
566
 */
567
void __init
568
init_smp_config(void)
569
{
570
        struct fptr {
571
                unsigned long fp;
572
                unsigned long gp;
573
        } *ap_startup;
574
        long sal_ret;
575
 
576
        /* Tell SAL where to drop the AP's.  */
577
        ap_startup = (struct fptr *) start_ap;
578
        sal_ret = ia64_sal_set_vectors(SAL_VECTOR_OS_BOOT_RENDEZ,
579
                                      ia64_tpa(ap_startup->fp), ia64_tpa(ap_startup->gp), 0, 0, 0, 0);
580
        if (sal_ret < 0) {
581
                printk(KERN_ERR "SMP: Can't set SAL AP Boot Rendezvous: %s\n     Forcing UP mode\n",
582
                       ia64_sal_strerror(sal_ret));
583
                max_cpus = 0;
584
                smp_num_cpus = 1;
585
        }
586
}
587
 
588
/*
589
 * Initialize the logical CPU number to SAPICID mapping
590
 */
591
void __init
592
smp_build_cpu_map (void)
593
{
594
        int sapicid, cpu, i;
595
        int boot_cpu_id = hard_smp_processor_id();
596
 
597
        for (cpu = 0; cpu < NR_CPUS; cpu++)
598
                ia64_cpu_to_sapicid[cpu] = -1;
599
 
600
        ia64_cpu_to_sapicid[0] = boot_cpu_id;
601
 
602
        for (cpu = 1, i = 0; i < smp_boot_data.cpu_count; i++) {
603
                sapicid = smp_boot_data.cpu_phys_id[i];
604
                if (sapicid == boot_cpu_id)
605
                        continue;
606
                ia64_cpu_to_sapicid[cpu] = sapicid;
607
                cpu++;
608
        }
609
}
610
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.