VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / arch / ppc64 / kernel / setup.c
1 /*
2  * 
3  * Common boot and setup code.
4  *
5  * Copyright (C) 2001 PPC64 Team, IBM Corp
6  *
7  *      This program is free software; you can redistribute it and/or
8  *      modify it under the terms of the GNU General Public License
9  *      as published by the Free Software Foundation; either version
10  *      2 of the License, or (at your option) any later version.
11  */
12
13 #include <linux/config.h>
14 #include <linux/module.h>
15 #include <linux/string.h>
16 #include <linux/sched.h>
17 #include <linux/init.h>
18 #include <linux/reboot.h>
19 #include <linux/delay.h>
20 #include <linux/initrd.h>
21 #include <linux/ide.h>
22 #include <linux/seq_file.h>
23 #include <linux/ioport.h>
24 #include <linux/console.h>
25 #include <linux/version.h>
26 #include <linux/tty.h>
27 #include <linux/root_dev.h>
28 #include <linux/notifier.h>
29 #include <linux/cpu.h>
30 #include <asm/io.h>
31 #include <asm/prom.h>
32 #include <asm/processor.h>
33 #include <asm/pgtable.h>
34 #include <asm/bootinfo.h>
35 #include <asm/smp.h>
36 #include <asm/elf.h>
37 #include <asm/machdep.h>
38 #include <asm/iSeries/LparData.h>
39 #include <asm/naca.h>
40 #include <asm/paca.h>
41 #include <asm/ppcdebug.h>
42 #include <asm/time.h>
43 #include <asm/cputable.h>
44 #include <asm/sections.h>
45 #include <asm/btext.h>
46 #include <asm/nvram.h>
47 #include <asm/setup.h>
48 #include <asm/system.h>
49 #include <asm/rtas.h>
50
51 extern unsigned long klimit;
52 /* extern void *stab; */
53 extern HTAB htab_data;
54 extern unsigned long loops_per_jiffy;
55
56 int have_of = 1;
57
58 extern void  chrp_init(unsigned long r3,
59                        unsigned long r4,
60                        unsigned long r5,
61                        unsigned long r6,
62                        unsigned long r7);
63
64 extern void  pmac_init(unsigned long r3,
65                        unsigned long r4,
66                        unsigned long r5,
67                        unsigned long r6,
68                        unsigned long r7);
69
70 extern void iSeries_init( void );
71 extern void iSeries_init_early( void );
72 extern void pSeries_init_early( void );
73 extern void pSeriesLP_init_early(void);
74 extern void pmac_init_early(void);
75 extern void mm_init_ppc64( void ); 
76 extern void pseries_secondary_smp_init(unsigned long); 
77 extern int  idle_setup(void);
78 extern void vpa_init(int cpu);
79
80 unsigned long decr_overclock = 1;
81 unsigned long decr_overclock_proc0 = 1;
82 unsigned long decr_overclock_set = 0;
83 unsigned long decr_overclock_proc0_set = 0;
84
85 int powersave_nap;
86
87 unsigned char aux_device_present;
88
89 void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
90                     unsigned long r6, unsigned long r7);
91 int parse_bootinfo(void);
92
93 #ifdef CONFIG_MAGIC_SYSRQ
94 unsigned long SYSRQ_KEY;
95 #endif /* CONFIG_MAGIC_SYSRQ */
96
97 struct machdep_calls ppc_md;
98
99 static int ppc64_panic_event(struct notifier_block *, unsigned long, void *);
100
101 static struct notifier_block ppc64_panic_block = {
102         notifier_call: ppc64_panic_event,
103         priority: INT_MIN /* may not return; must be done last */
104 };
105
106 /*
107  * Perhaps we can put the pmac screen_info[] here
108  * on pmac as well so we don't need the ifdef's.
109  * Until we get multiple-console support in here
110  * that is.  -- Cort
111  * Maybe tie it to serial consoles, since this is really what
112  * these processors use on existing boards.  -- Dan
113  */ 
114 struct screen_info screen_info = {
115         0, 25,                  /* orig-x, orig-y */
116         0,                      /* unused */
117         0,                      /* orig-video-page */
118         0,                      /* orig-video-mode */
119         80,                     /* orig-video-cols */
120         0,0,0,                  /* ega_ax, ega_bx, ega_cx */
121         25,                     /* orig-video-lines */
122         1,                      /* orig-video-isVGA */
123         16                      /* orig-video-points */
124 };
125
126 /*
127  * These are used in binfmt_elf.c to put aux entries on the stack
128  * for each elf executable being started.
129  */
130 int dcache_bsize;
131 int icache_bsize;
132 int ucache_bsize;
133
134 /*
135  * Initialize the PPCDBG state.  Called before relocation has been enabled.
136  */
137 void ppcdbg_initialize(void) {
138         unsigned long offset = reloc_offset();
139         struct naca_struct *_naca = RELOC(naca);
140
141         _naca->debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */;
142 }
143
144 static struct console udbg_console = {
145         .name   = "udbg",
146         .write  = udbg_console_write,
147         .flags  = CON_PRINTBUFFER,
148         .index  = -1,
149 };
150
151 static int early_console_initialized;
152
153 void __init disable_early_printk(void)
154 {
155         if (!early_console_initialized)
156                 return;
157         unregister_console(&udbg_console);
158         early_console_initialized = 0;
159 }
160
161 /*
162  * Do some initial setup of the system.  The parameters are those which 
163  * were passed in from the bootloader.
164  */
165 void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
166                   unsigned long r6, unsigned long r7)
167 {
168 #if defined(CONFIG_SMP) && defined(CONFIG_PPC_PSERIES)
169         int ret, i;
170 #endif
171
172 #ifdef CONFIG_XMON_DEFAULT
173         xmon_init();
174 #endif
175
176 #ifdef CONFIG_PPC_ISERIES
177         /* pSeries systems are identified in prom.c via OF. */
178         if ( itLpNaca.xLparInstalled == 1 )
179                 systemcfg->platform = PLATFORM_ISERIES_LPAR;
180 #endif
181         
182         switch (systemcfg->platform) {
183 #ifdef CONFIG_PPC_ISERIES
184         case PLATFORM_ISERIES_LPAR:
185                 iSeries_init_early();
186                 break;
187 #endif
188
189 #ifdef CONFIG_PPC_PSERIES
190         case PLATFORM_PSERIES:
191                 pSeries_init_early();
192                 parse_bootinfo();
193                 break;
194
195         case PLATFORM_PSERIES_LPAR:
196                 pSeriesLP_init_early();
197                 parse_bootinfo();
198                 break;
199 #endif /* CONFIG_PPC_PSERIES */
200 #ifdef CONFIG_PPC_PMAC
201         case PLATFORM_POWERMAC:
202                 pmac_init_early();
203                 parse_bootinfo();
204 #endif /* CONFIG_PPC_PMAC */
205         }
206
207         /* If we were passed an initrd, set the ROOT_DEV properly if the values
208          * look sensible. If not, clear initrd reference.
209          */
210 #ifdef CONFIG_BLK_DEV_INITRD
211         if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
212             initrd_end > initrd_start)
213                 ROOT_DEV = Root_RAM0;
214         else
215                 initrd_start = initrd_end = 0;
216 #endif /* CONFIG_BLK_DEV_INITRD */
217
218 #ifdef CONFIG_BOOTX_TEXT
219         map_boot_text();
220         if (systemcfg->platform == PLATFORM_POWERMAC) {
221                 early_console_initialized = 1;
222                 register_console(&udbg_console);
223         }
224 #endif /* CONFIG_BOOTX_TEXT */
225
226 #ifdef CONFIG_PPC_PSERIES
227         if (systemcfg->platform & PLATFORM_PSERIES) {
228                 early_console_initialized = 1;
229                 register_console(&udbg_console);
230                 __irq_offset_value = NUM_ISA_INTERRUPTS;
231                 finish_device_tree();
232                 chrp_init(r3, r4, r5, r6, r7);
233
234 #ifdef CONFIG_SMP
235                 /* Start secondary threads on SMT systems */
236                 for (i = 0; i < NR_CPUS; i++) {
237                         if (cpu_available(i) && !cpu_possible(i)) {
238                                 printk("%16.16x : starting thread\n", i);
239                                 rtas_call(rtas_token("start-cpu"), 3, 1, &ret,
240                                           get_hard_smp_processor_id(i), 
241                                           (u32)*((unsigned long *)pseries_secondary_smp_init),
242                                           i);
243                                 cpu_set(i, cpu_possible_map);
244                                 systemcfg->processorCount++;
245                         }
246                 }
247 #endif /* CONFIG_SMP */
248         }
249 #endif /* CONFIG_PPC_PSERIES */
250
251 #ifdef CONFIG_PPC_PMAC
252         if (systemcfg->platform == PLATFORM_POWERMAC) {
253                 finish_device_tree();
254                 pmac_init(r3, r4, r5, r6, r7);
255         }
256 #endif /* CONFIG_PPC_PMAC */
257
258 #if defined(CONFIG_HOTPLUG_CPU) &&  !defined(CONFIG_PPC_PMAC)
259         rtas_stop_self_args.token = rtas_token("stop-self");
260 #endif /* CONFIG_HOTPLUG_CPU && !CONFIG_PPC_PMAC */
261
262         /* Finish initializing the hash table (do the dynamic
263          * patching for the fast-path hashtable.S code)
264          */
265         htab_finish_init();
266
267         printk("Starting Linux PPC64 %s\n", UTS_RELEASE);
268
269         printk("-----------------------------------------------------\n");
270         printk("naca                          = 0x%p\n", naca);
271         printk("naca->pftSize                 = 0x%lx\n", naca->pftSize);
272         printk("naca->debug_switch            = 0x%lx\n", naca->debug_switch);
273         printk("naca->interrupt_controller    = 0x%ld\n", naca->interrupt_controller);
274         printk("systemcfg                     = 0x%p\n", systemcfg);
275         printk("systemcfg->processorCount     = 0x%lx\n", systemcfg->processorCount);
276         printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize);
277         printk("systemcfg->dCacheL1LineSize   = 0x%x\n", systemcfg->dCacheL1LineSize);
278         printk("systemcfg->iCacheL1LineSize   = 0x%x\n", systemcfg->iCacheL1LineSize);
279         printk("htab_data.htab                = 0x%p\n", htab_data.htab);
280         printk("htab_data.num_ptegs           = 0x%lx\n", htab_data.htab_num_ptegs);
281         printk("-----------------------------------------------------\n");
282
283         mm_init_ppc64();
284
285 #if defined(CONFIG_SMP) && defined(CONFIG_PPC_PSERIES)
286         if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
287                 vpa_init(boot_cpuid);
288         }
289 #endif
290
291         /* Select the correct idle loop for the platform. */
292         idle_setup();
293
294         switch (systemcfg->platform) {
295 #ifdef CONFIG_PPC_ISERIES
296         case PLATFORM_ISERIES_LPAR:
297                 iSeries_init();
298                 break;
299 #endif
300         default:
301                 /* The following relies on the device tree being */
302                 /* fully configured.                             */
303                 parse_cmd_line(r3, r4, r5, r6, r7);
304         }
305 }
306
307 void machine_restart(char *cmd)
308 {
309         if (ppc_md.nvram_sync)
310                 ppc_md.nvram_sync();
311         ppc_md.restart(cmd);
312 }
313
314 EXPORT_SYMBOL(machine_restart);
315   
316 void machine_power_off(void)
317 {
318         if (ppc_md.nvram_sync)
319                 ppc_md.nvram_sync();
320         ppc_md.power_off();
321 }
322
323 EXPORT_SYMBOL(machine_power_off);
324   
325 void machine_halt(void)
326 {
327         if (ppc_md.nvram_sync)
328                 ppc_md.nvram_sync();
329         ppc_md.halt();
330 }
331
332 EXPORT_SYMBOL(machine_halt);
333
334 unsigned long ppc_proc_freq;
335 unsigned long ppc_tb_freq;
336
337 static int ppc64_panic_event(struct notifier_block *this,
338                              unsigned long event, void *ptr)
339 {
340         ppc_md.panic((char *)ptr);  /* May not return */
341         return NOTIFY_DONE;
342 }
343
344
345 #ifdef CONFIG_SMP
346 DEFINE_PER_CPU(unsigned int, pvr);
347 #endif
348
349 static int show_cpuinfo(struct seq_file *m, void *v)
350 {
351         unsigned long cpu_id = (unsigned long)v - 1;
352         unsigned int pvr;
353         unsigned short maj;
354         unsigned short min;
355
356         if (cpu_id == NR_CPUS) {
357                 seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
358
359                 if (ppc_md.get_cpuinfo != NULL)
360                         ppc_md.get_cpuinfo(m);
361
362                 return 0;
363         }
364
365         /* We only show online cpus: disable preempt (overzealous, I
366          * knew) to prevent cpu going down. */
367         preempt_disable();
368         if (!cpu_online(cpu_id)) {
369                 preempt_enable();
370                 return 0;
371         }
372
373 #ifdef CONFIG_SMP
374         pvr = per_cpu(pvr, cpu_id);
375 #else
376         pvr = _get_PVR();
377 #endif
378         maj = (pvr >> 8) & 0xFF;
379         min = pvr & 0xFF;
380
381         seq_printf(m, "processor\t: %lu\n", cpu_id);
382         seq_printf(m, "cpu\t\t: ");
383
384         if (cur_cpu_spec->pvr_mask)
385                 seq_printf(m, "%s", cur_cpu_spec->cpu_name);
386         else
387                 seq_printf(m, "unknown (%08x)", pvr);
388
389 #ifdef CONFIG_ALTIVEC
390         if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
391                 seq_printf(m, ", altivec supported");
392 #endif /* CONFIG_ALTIVEC */
393
394         seq_printf(m, "\n");
395
396         /*
397          * Assume here that all clock rates are the same in a
398          * smp system.  -- Cort
399          */
400         seq_printf(m, "clock\t\t: %lu.%06luMHz\n", ppc_proc_freq / 1000000,
401                    ppc_proc_freq % 1000000);
402
403         seq_printf(m, "revision\t: %hd.%hd\n\n", maj, min);
404
405         preempt_enable();
406         return 0;
407 }
408
409 static void *c_start(struct seq_file *m, loff_t *pos)
410 {
411         return *pos <= NR_CPUS ? (void *)((*pos)+1) : NULL;
412 }
413 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
414 {
415         ++*pos;
416         return c_start(m, pos);
417 }
418 static void c_stop(struct seq_file *m, void *v)
419 {
420 }
421 struct seq_operations cpuinfo_op = {
422         .start =c_start,
423         .next = c_next,
424         .stop = c_stop,
425         .show = show_cpuinfo,
426 };
427
428 /*
429  * Fetch the cmd_line from open firmware. 
430  */
431 void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
432                   unsigned long r6, unsigned long r7)
433 {
434         cmd_line[0] = 0;
435
436 #ifdef CONFIG_CMDLINE
437         strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
438 #endif /* CONFIG_CMDLINE */
439
440 #ifdef CONFIG_PPC_PSERIES
441         {
442         struct device_node *chosen;
443
444         chosen = of_find_node_by_name(NULL, "chosen");
445         if (chosen != NULL) {
446                 char *p;
447                 p = get_property(chosen, "bootargs", NULL);
448                 if (p != NULL && p[0] != 0)
449                         strlcpy(cmd_line, p, sizeof(cmd_line));
450                 of_node_put(chosen);
451         }
452         }
453 #endif
454
455         /* Look for mem= option on command line */
456         if (strstr(cmd_line, "mem=")) {
457                 char *p, *q;
458                 unsigned long maxmem = 0;
459                 extern unsigned long __max_memory;
460
461                 for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
462                         q = p + 4;
463                         if (p > cmd_line && p[-1] != ' ')
464                                 continue;
465                         maxmem = simple_strtoul(q, &q, 0);
466                         if (*q == 'k' || *q == 'K') {
467                                 maxmem <<= 10;
468                                 ++q;
469                         } else if (*q == 'm' || *q == 'M') {
470                                 maxmem <<= 20;
471                                 ++q;
472                         }
473                 }
474                 __max_memory = maxmem;
475         }
476 }
477
478 #ifdef CONFIG_PPC_PSERIES
479 static int __init set_preferred_console(void)
480 {
481         struct device_node *prom_stdout;
482         char *name;
483         int offset;
484
485         /* The user has requested a console so this is already set up. */
486         if (strstr(saved_command_line, "console="))
487                 return -EBUSY;
488
489         prom_stdout = find_path_device(of_stdout_device);
490         if (!prom_stdout)
491                 return -ENODEV;
492
493         name = (char *)get_property(prom_stdout, "name", NULL);
494         if (!name)
495                 return -ENODEV;
496
497         if (strcmp(name, "serial") == 0) {
498                 int i;
499                 u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i);
500                 if (i > 8) {
501                         switch (reg[1]) {
502                                 case 0x3f8:
503                                         offset = 0;
504                                         break;
505                                 case 0x2f8:
506                                         offset = 1;
507                                         break;
508                                 case 0x898:
509                                         offset = 2;
510                                         break;
511                                 case 0x890:
512                                         offset = 3;
513                                         break;
514                                 default:
515                                         /* We dont recognise the serial port */
516                                         return -ENODEV;
517                         }
518                 }
519         } else if (strcmp(name, "vty") == 0)
520                 /* pSeries LPAR virtual console */
521                 return add_preferred_console("hvc", 0, NULL);
522         else if (strcmp(name, "ch-a") == 0)
523                 offset = 0;
524         else if (strcmp(name, "ch-b") == 0)
525                 offset = 1;
526         else
527                 return -ENODEV;
528
529         return add_preferred_console("ttyS", offset, NULL);
530
531 }
532 console_initcall(set_preferred_console);
533
534 int parse_bootinfo(void)
535 {
536         struct bi_record *rec;
537
538         rec = prom.bi_recs;
539
540         if ( rec == NULL || rec->tag != BI_FIRST )
541                 return -1;
542
543         for ( ; rec->tag != BI_LAST ; rec = bi_rec_next(rec) ) {
544                 switch (rec->tag) {
545                 case BI_CMD_LINE:
546                         strlcpy(cmd_line, (void *)rec->data, sizeof(cmd_line));
547                         break;
548                 }
549         }
550
551         return 0;
552 }
553 #endif
554
555 int __init ppc_init(void)
556 {
557         /* clear the progress line */
558         ppc_md.progress(" ", 0xffff);
559
560         if (ppc_md.init != NULL) {
561                 ppc_md.init();
562         }
563         return 0;
564 }
565
566 arch_initcall(ppc_init);
567
568 void __init ppc64_calibrate_delay(void)
569 {
570         loops_per_jiffy = tb_ticks_per_jiffy;
571
572         printk("Calibrating delay loop... %lu.%02lu BogoMips\n",
573                                loops_per_jiffy/(500000/HZ),
574                                loops_per_jiffy/(5000/HZ) % 100);
575 }       
576
577 extern void (*calibrate_delay)(void);
578
579 #ifdef CONFIG_IRQSTACKS
580 static void __init irqstack_early_init(void)
581 {
582         int i;
583
584         /* interrupt stacks must be under 256MB, we cannot afford to take SLB misses on them */
585         for (i = 0; i < NR_CPUS; i++) {
586                 softirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
587                                         THREAD_SIZE, 0x10000000));
588                 hardirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
589                                         THREAD_SIZE, 0x10000000));
590         }
591 }
592 #else
593 #define irqstack_early_init()
594 #endif
595
596 /*
597  * Called into from start_kernel, after lock_kernel has been called.
598  * Initializes bootmem, which is unsed to manage page allocation until
599  * mem_init is called.
600  */
601 void __init setup_arch(char **cmdline_p)
602 {
603         extern int panic_timeout;
604         extern void do_init_bootmem(void);
605
606         calibrate_delay = ppc64_calibrate_delay;
607
608         ppc64_boot_msg(0x12, "Setup Arch");
609
610 #ifdef CONFIG_XMON
611         if (strstr(cmd_line, "xmon")) {
612                 /* ensure xmon is enabled */
613                 xmon_init();
614                 debugger(0);
615         }
616 #endif /* CONFIG_XMON */
617
618         /*
619          * Set cache line size based on type of cpu as a default.
620          * Systems with OF can look in the properties on the cpu node(s)
621          * for a possibly more accurate value.
622          */
623         dcache_bsize = systemcfg->dCacheL1LineSize; 
624         icache_bsize = systemcfg->iCacheL1LineSize; 
625
626         /* reboot on panic */
627         panic_timeout = 180;
628
629         if (ppc_md.panic)
630                 notifier_chain_register(&panic_notifier_list, &ppc64_panic_block);
631
632         init_mm.start_code = PAGE_OFFSET;
633         init_mm.end_code = (unsigned long) _etext;
634         init_mm.end_data = (unsigned long) _edata;
635         init_mm.brk = klimit;
636         
637         /* Save unparsed command line copy for /proc/cmdline */
638         strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
639         *cmdline_p = cmd_line;
640
641         irqstack_early_init();
642
643         /* set up the bootmem stuff with available memory */
644         do_init_bootmem();
645
646         ppc_md.setup_arch();
647
648         paging_init();
649         ppc64_boot_msg(0x15, "Setup Done");
650 }
651
652 /* ToDo: do something useful if ppc_md is not yet setup. */
653 #define PPC64_LINUX_FUNCTION 0x0f000000
654 #define PPC64_IPL_MESSAGE 0xc0000000
655 #define PPC64_TERM_MESSAGE 0xb0000000
656 #define PPC64_ATTN_MESSAGE 0xa0000000
657 #define PPC64_DUMP_MESSAGE 0xd0000000
658
659 static void ppc64_do_msg(unsigned int src, const char *msg)
660 {
661         if (ppc_md.progress) {
662                 char buf[32];
663
664                 sprintf(buf, "%08x        \n", src);
665                 ppc_md.progress(buf, 0);
666                 sprintf(buf, "%-16s", msg);
667                 ppc_md.progress(buf, 0);
668         }
669 }
670
671 /* Print a boot progress message. */
672 void ppc64_boot_msg(unsigned int src, const char *msg)
673 {
674         ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_IPL_MESSAGE|src, msg);
675         printk("[boot]%04x %s\n", src, msg);
676 }
677
678 /* Print a termination message (print only -- does not stop the kernel) */
679 void ppc64_terminate_msg(unsigned int src, const char *msg)
680 {
681         ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_TERM_MESSAGE|src, msg);
682         printk("[terminate]%04x %s\n", src, msg);
683 }
684
685 /* Print something that needs attention (device error, etc) */
686 void ppc64_attention_msg(unsigned int src, const char *msg)
687 {
688         ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_ATTN_MESSAGE|src, msg);
689         printk("[attention]%04x %s\n", src, msg);
690 }
691
692 /* Print a dump progress message. */
693 void ppc64_dump_msg(unsigned int src, const char *msg)
694 {
695         ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_DUMP_MESSAGE|src, msg);
696         printk("[dump]%04x %s\n", src, msg);
697 }
698
699 int set_spread_lpevents( char * str )
700 {
701         /* The parameter is the number of processors to share in processing lp events */
702         unsigned long i;
703         unsigned long val = simple_strtoul( str, NULL, 0 );
704         if ( ( val > 0 ) && ( val <= NR_CPUS ) ) {
705                 for ( i=1; i<val; ++i )
706                         paca[i].lpqueue_ptr = paca[0].lpqueue_ptr;
707                 printk("lpevent processing spread over %ld processors\n", val);
708         }
709         else
710                 printk("invalid spreaqd_lpevents %ld\n", val);
711         return 1;
712 }       
713
714 /* This should only be called on processor 0 during calibrate decr */
715 void setup_default_decr(void)
716 {
717         struct paca_struct *lpaca = get_paca();
718
719         if ( decr_overclock_set && !decr_overclock_proc0_set )
720                 decr_overclock_proc0 = decr_overclock;
721
722         lpaca->default_decr = tb_ticks_per_jiffy / decr_overclock_proc0;        
723         lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy;
724 }
725
726 int set_decr_overclock_proc0( char * str )
727 {
728         unsigned long val = simple_strtoul( str, NULL, 0 );
729         if ( ( val >= 1 ) && ( val <= 48 ) ) {
730                 decr_overclock_proc0_set = 1;
731                 decr_overclock_proc0 = val;
732                 printk("proc 0 decrementer overclock factor of %ld\n", val);
733         }
734         else
735                 printk("invalid proc 0 decrementer overclock factor of %ld\n", val);
736         return 1;
737 }
738
739 int set_decr_overclock( char * str )
740 {
741         unsigned long val = simple_strtoul( str, NULL, 0 );
742         if ( ( val >= 1 ) && ( val <= 48 ) ) {
743                 decr_overclock_set = 1;
744                 decr_overclock = val;
745                 printk("decrementer overclock factor of %ld\n", val);
746         }
747         else
748                 printk("invalid decrementer overclock factor of %ld\n", val);
749         return 1;
750
751 }
752
753 __setup("spread_lpevents=", set_spread_lpevents );
754 __setup("decr_overclock_proc0=", set_decr_overclock_proc0 );
755 __setup("decr_overclock=", set_decr_overclock );