1
2
3
4
5
6
7
8#include <linux/errno.h>
9#include <linux/sched.h>
10#include <linux/kernel.h>
11#include <linux/mm.h>
12#include <linux/stddef.h>
13#include <linux/unistd.h>
14#include <linux/ptrace.h>
15#include <asm/smp.h>
16#include <linux/user.h>
17#include <linux/screen_info.h>
18#include <linux/delay.h>
19#include <linux/fs.h>
20#include <linux/seq_file.h>
21#include <linux/syscalls.h>
22#include <linux/kdev_t.h>
23#include <linux/major.h>
24#include <linux/string.h>
25#include <linux/init.h>
26#include <linux/inet.h>
27#include <linux/console.h>
28#include <linux/root_dev.h>
29#include <linux/interrupt.h>
30#include <linux/cpu.h>
31#include <linux/initrd.h>
32#include <linux/module.h>
33#include <linux/start_kernel.h>
34
35#include <asm/io.h>
36#include <asm/processor.h>
37#include <asm/oplib.h>
38#include <asm/page.h>
39#include <asm/pgtable.h>
40#include <asm/idprom.h>
41#include <asm/head.h>
42#include <asm/starfire.h>
43#include <asm/mmu_context.h>
44#include <asm/timer.h>
45#include <asm/sections.h>
46#include <asm/setup.h>
47#include <asm/mmu.h>
48#include <asm/ns87303.h>
49#include <asm/btext.h>
50#include <asm/elf.h>
51#include <asm/mdesc.h>
52#include <asm/cacheflush.h>
53
54#ifdef CONFIG_IP_PNP
55#include <net/ipconfig.h>
56#endif
57
58#include "entry.h"
59#include "kernel.h"
60
61
62
63
64DEFINE_SPINLOCK(ns87303_lock);
65EXPORT_SYMBOL(ns87303_lock);
66
67struct screen_info screen_info = {
68 0, 0,
69 0,
70 0,
71 0,
72 128,
73 0, 0, 0,
74 54,
75 0,
76 16
77};
78
79static void
80prom_console_write(struct console *con, const char *s, unsigned int n)
81{
82 prom_write(s, n);
83}
84
85
86unsigned long cmdline_memory_size = 0;
87
88static struct console prom_early_console = {
89 .name = "earlyprom",
90 .write = prom_console_write,
91 .flags = CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME,
92 .index = -1,
93};
94
95
96
97
98
99static void __init process_switch(char c)
100{
101 switch (c) {
102 case 'd':
103 case 's':
104 break;
105 case 'h':
106 prom_printf("boot_flags_init: Halt!\n");
107 prom_halt();
108 break;
109 case 'p':
110 prom_early_console.flags &= ~CON_BOOT;
111 break;
112 case 'P':
113
114 if (tlb_type != cheetah) {
115 printk("BOOT: Ignoring P-Cache force option.\n");
116 break;
117 }
118 cheetah_pcache_forced_on = 1;
119 add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);
120 cheetah_enable_pcache();
121 break;
122
123 default:
124 printk("Unknown boot switch (-%c)\n", c);
125 break;
126 }
127}
128
129static void __init boot_flags_init(char *commands)
130{
131 while (*commands) {
132
133 while (*commands && *commands == ' ')
134 commands++;
135
136
137 if (*commands == '\0')
138 break;
139 if (*commands == '-') {
140 commands++;
141 while (*commands && *commands != ' ')
142 process_switch(*commands++);
143 continue;
144 }
145 if (!strncmp(commands, "mem=", 4))
146 cmdline_memory_size = memparse(commands + 4, &commands);
147
148 while (*commands && *commands != ' ')
149 commands++;
150 }
151}
152
153extern unsigned short root_flags;
154extern unsigned short root_dev;
155extern unsigned short ram_flags;
156#define RAMDISK_IMAGE_START_MASK 0x07FF
157#define RAMDISK_PROMPT_FLAG 0x8000
158#define RAMDISK_LOAD_FLAG 0x4000
159
160extern int root_mountflags;
161
162char reboot_command[COMMAND_LINE_SIZE];
163
164static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 };
165
166static void __init per_cpu_patch(void)
167{
168 struct cpuid_patch_entry *p;
169 unsigned long ver;
170 int is_jbus;
171
172 if (tlb_type == spitfire && !this_is_starfire)
173 return;
174
175 is_jbus = 0;
176 if (tlb_type != hypervisor) {
177 __asm__ ("rdpr %%ver, %0" : "=r" (ver));
178 is_jbus = ((ver >> 32UL) == __JALAPENO_ID ||
179 (ver >> 32UL) == __SERRANO_ID);
180 }
181
182 p = &__cpuid_patch;
183 while (p < &__cpuid_patch_end) {
184 unsigned long addr = p->addr;
185 unsigned int *insns;
186
187 switch (tlb_type) {
188 case spitfire:
189 insns = &p->starfire[0];
190 break;
191 case cheetah:
192 case cheetah_plus:
193 if (is_jbus)
194 insns = &p->cheetah_jbus[0];
195 else
196 insns = &p->cheetah_safari[0];
197 break;
198 case hypervisor:
199 insns = &p->sun4v[0];
200 break;
201 default:
202 prom_printf("Unknown cpu type, halting.\n");
203 prom_halt();
204 }
205
206 *(unsigned int *) (addr + 0) = insns[0];
207 wmb();
208 __asm__ __volatile__("flush %0" : : "r" (addr + 0));
209
210 *(unsigned int *) (addr + 4) = insns[1];
211 wmb();
212 __asm__ __volatile__("flush %0" : : "r" (addr + 4));
213
214 *(unsigned int *) (addr + 8) = insns[2];
215 wmb();
216 __asm__ __volatile__("flush %0" : : "r" (addr + 8));
217
218 *(unsigned int *) (addr + 12) = insns[3];
219 wmb();
220 __asm__ __volatile__("flush %0" : : "r" (addr + 12));
221
222 p++;
223 }
224}
225
226void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *start,
227 struct sun4v_1insn_patch_entry *end)
228{
229 while (start < end) {
230 unsigned long addr = start->addr;
231
232 *(unsigned int *) (addr + 0) = start->insn;
233 wmb();
234 __asm__ __volatile__("flush %0" : : "r" (addr + 0));
235
236 start++;
237 }
238}
239
240void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
241 struct sun4v_2insn_patch_entry *end)
242{
243 while (start < end) {
244 unsigned long addr = start->addr;
245
246 *(unsigned int *) (addr + 0) = start->insns[0];
247 wmb();
248 __asm__ __volatile__("flush %0" : : "r" (addr + 0));
249
250 *(unsigned int *) (addr + 4) = start->insns[1];
251 wmb();
252 __asm__ __volatile__("flush %0" : : "r" (addr + 4));
253
254 start++;
255 }
256}
257
258void sun_m7_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
259 struct sun4v_2insn_patch_entry *end)
260{
261 while (start < end) {
262 unsigned long addr = start->addr;
263
264 *(unsigned int *) (addr + 0) = start->insns[0];
265 wmb();
266 __asm__ __volatile__("flush %0" : : "r" (addr + 0));
267
268 *(unsigned int *) (addr + 4) = start->insns[1];
269 wmb();
270 __asm__ __volatile__("flush %0" : : "r" (addr + 4));
271
272 start++;
273 }
274}
275
276static void __init sun4v_patch(void)
277{
278 extern void sun4v_hvapi_init(void);
279
280 if (tlb_type != hypervisor)
281 return;
282
283 sun4v_patch_1insn_range(&__sun4v_1insn_patch,
284 &__sun4v_1insn_patch_end);
285
286 sun4v_patch_2insn_range(&__sun4v_2insn_patch,
287 &__sun4v_2insn_patch_end);
288 if (sun4v_chip_type == SUN4V_CHIP_SPARC_M7 ||
289 sun4v_chip_type == SUN4V_CHIP_SPARC_SN)
290 sun_m7_patch_2insn_range(&__sun_m7_2insn_patch,
291 &__sun_m7_2insn_patch_end);
292
293 sun4v_hvapi_init();
294}
295
296static void __init popc_patch(void)
297{
298 struct popc_3insn_patch_entry *p3;
299 struct popc_6insn_patch_entry *p6;
300
301 p3 = &__popc_3insn_patch;
302 while (p3 < &__popc_3insn_patch_end) {
303 unsigned long i, addr = p3->addr;
304
305 for (i = 0; i < 3; i++) {
306 *(unsigned int *) (addr + (i * 4)) = p3->insns[i];
307 wmb();
308 __asm__ __volatile__("flush %0"
309 : : "r" (addr + (i * 4)));
310 }
311
312 p3++;
313 }
314
315 p6 = &__popc_6insn_patch;
316 while (p6 < &__popc_6insn_patch_end) {
317 unsigned long i, addr = p6->addr;
318
319 for (i = 0; i < 6; i++) {
320 *(unsigned int *) (addr + (i * 4)) = p6->insns[i];
321 wmb();
322 __asm__ __volatile__("flush %0"
323 : : "r" (addr + (i * 4)));
324 }
325
326 p6++;
327 }
328}
329
330static void __init pause_patch(void)
331{
332 struct pause_patch_entry *p;
333
334 p = &__pause_3insn_patch;
335 while (p < &__pause_3insn_patch_end) {
336 unsigned long i, addr = p->addr;
337
338 for (i = 0; i < 3; i++) {
339 *(unsigned int *) (addr + (i * 4)) = p->insns[i];
340 wmb();
341 __asm__ __volatile__("flush %0"
342 : : "r" (addr + (i * 4)));
343 }
344
345 p++;
346 }
347}
348
349void __init start_early_boot(void)
350{
351 int cpu;
352
353 check_if_starfire();
354 per_cpu_patch();
355 sun4v_patch();
356
357 cpu = hard_smp_processor_id();
358 if (cpu >= NR_CPUS) {
359 prom_printf("Serious problem, boot cpu id (%d) >= NR_CPUS (%d)\n",
360 cpu, NR_CPUS);
361 prom_halt();
362 }
363 current_thread_info()->cpu = cpu;
364
365 prom_init_report();
366 start_kernel();
367}
368
369
370unsigned long sparc64_elf_hwcap = (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR |
371 HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV |
372 HWCAP_SPARC_V9);
373EXPORT_SYMBOL(sparc64_elf_hwcap);
374
375static const char *hwcaps[] = {
376 "flush", "stbar", "swap", "muldiv", "v9",
377 "ultra3", "blkinit", "n2",
378
379
380
381
382 "mul32", "div32", "fsmuld", "v8plus", "popc", "vis", "vis2",
383 "ASIBlkInit", "fmaf", "vis3", "hpc", "random", "trans", "fjfmau",
384 "ima", "cspare", "pause", "cbcond", NULL ,
385 "adp",
386};
387
388static const char *crypto_hwcaps[] = {
389 "aes", "des", "kasumi", "camellia", "md5", "sha1", "sha256",
390 "sha512", "mpmul", "montmul", "montsqr", "crc32c",
391};
392
393void cpucap_info(struct seq_file *m)
394{
395 unsigned long caps = sparc64_elf_hwcap;
396 int i, printed = 0;
397
398 seq_puts(m, "cpucaps\t\t: ");
399 for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
400 unsigned long bit = 1UL << i;
401 if (hwcaps[i] && (caps & bit)) {
402 seq_printf(m, "%s%s",
403 printed ? "," : "", hwcaps[i]);
404 printed++;
405 }
406 }
407 if (caps & HWCAP_SPARC_CRYPTO) {
408 unsigned long cfr;
409
410 __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
411 for (i = 0; i < ARRAY_SIZE(crypto_hwcaps); i++) {
412 unsigned long bit = 1UL << i;
413 if (cfr & bit) {
414 seq_printf(m, "%s%s",
415 printed ? "," : "", crypto_hwcaps[i]);
416 printed++;
417 }
418 }
419 }
420 seq_putc(m, '\n');
421}
422
423static void __init report_one_hwcap(int *printed, const char *name)
424{
425 if ((*printed) == 0)
426 printk(KERN_INFO "CPU CAPS: [");
427 printk(KERN_CONT "%s%s",
428 (*printed) ? "," : "", name);
429 if (++(*printed) == 8) {
430 printk(KERN_CONT "]\n");
431 *printed = 0;
432 }
433}
434
435static void __init report_crypto_hwcaps(int *printed)
436{
437 unsigned long cfr;
438 int i;
439
440 __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
441
442 for (i = 0; i < ARRAY_SIZE(crypto_hwcaps); i++) {
443 unsigned long bit = 1UL << i;
444 if (cfr & bit)
445 report_one_hwcap(printed, crypto_hwcaps[i]);
446 }
447}
448
449static void __init report_hwcaps(unsigned long caps)
450{
451 int i, printed = 0;
452
453 for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
454 unsigned long bit = 1UL << i;
455 if (hwcaps[i] && (caps & bit))
456 report_one_hwcap(&printed, hwcaps[i]);
457 }
458 if (caps & HWCAP_SPARC_CRYPTO)
459 report_crypto_hwcaps(&printed);
460 if (printed != 0)
461 printk(KERN_CONT "]\n");
462}
463
464static unsigned long __init mdesc_cpu_hwcap_list(void)
465{
466 struct mdesc_handle *hp;
467 unsigned long caps = 0;
468 const char *prop;
469 int len;
470 u64 pn;
471
472 hp = mdesc_grab();
473 if (!hp)
474 return 0;
475
476 pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "cpu");
477 if (pn == MDESC_NODE_NULL)
478 goto out;
479
480 prop = mdesc_get_property(hp, pn, "hwcap-list", &len);
481 if (!prop)
482 goto out;
483
484 while (len) {
485 int i, plen;
486
487 for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
488 unsigned long bit = 1UL << i;
489
490 if (hwcaps[i] && !strcmp(prop, hwcaps[i])) {
491 caps |= bit;
492 break;
493 }
494 }
495 for (i = 0; i < ARRAY_SIZE(crypto_hwcaps); i++) {
496 if (!strcmp(prop, crypto_hwcaps[i]))
497 caps |= HWCAP_SPARC_CRYPTO;
498 }
499
500 plen = strlen(prop) + 1;
501 prop += plen;
502 len -= plen;
503 }
504
505out:
506 mdesc_release(hp);
507 return caps;
508}
509
510
511
512
513static void __init init_sparc64_elf_hwcap(void)
514{
515 unsigned long cap = sparc64_elf_hwcap;
516 unsigned long mdesc_caps;
517
518 if (tlb_type == cheetah || tlb_type == cheetah_plus)
519 cap |= HWCAP_SPARC_ULTRA3;
520 else if (tlb_type == hypervisor) {
521 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 ||
522 sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
523 sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
524 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
525 sun4v_chip_type == SUN4V_CHIP_NIAGARA5 ||
526 sun4v_chip_type == SUN4V_CHIP_SPARC_M6 ||
527 sun4v_chip_type == SUN4V_CHIP_SPARC_M7 ||
528 sun4v_chip_type == SUN4V_CHIP_SPARC_SN ||
529 sun4v_chip_type == SUN4V_CHIP_SPARC64X)
530 cap |= HWCAP_SPARC_BLKINIT;
531 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
532 sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
533 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
534 sun4v_chip_type == SUN4V_CHIP_NIAGARA5 ||
535 sun4v_chip_type == SUN4V_CHIP_SPARC_M6 ||
536 sun4v_chip_type == SUN4V_CHIP_SPARC_M7 ||
537 sun4v_chip_type == SUN4V_CHIP_SPARC_SN ||
538 sun4v_chip_type == SUN4V_CHIP_SPARC64X)
539 cap |= HWCAP_SPARC_N2;
540 }
541
542 cap |= (AV_SPARC_MUL32 | AV_SPARC_DIV32 | AV_SPARC_V8PLUS);
543
544 mdesc_caps = mdesc_cpu_hwcap_list();
545 if (!mdesc_caps) {
546 if (tlb_type == spitfire)
547 cap |= AV_SPARC_VIS;
548 if (tlb_type == cheetah || tlb_type == cheetah_plus)
549 cap |= AV_SPARC_VIS | AV_SPARC_VIS2;
550 if (tlb_type == cheetah_plus) {
551 unsigned long impl, ver;
552
553 __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver));
554 impl = ((ver >> 32) & 0xffff);
555 if (impl == PANTHER_IMPL)
556 cap |= AV_SPARC_POPC;
557 }
558 if (tlb_type == hypervisor) {
559 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1)
560 cap |= AV_SPARC_ASI_BLK_INIT;
561 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
562 sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
563 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
564 sun4v_chip_type == SUN4V_CHIP_NIAGARA5 ||
565 sun4v_chip_type == SUN4V_CHIP_SPARC_M6 ||
566 sun4v_chip_type == SUN4V_CHIP_SPARC_M7 ||
567 sun4v_chip_type == SUN4V_CHIP_SPARC_SN ||
568 sun4v_chip_type == SUN4V_CHIP_SPARC64X)
569 cap |= (AV_SPARC_VIS | AV_SPARC_VIS2 |
570 AV_SPARC_ASI_BLK_INIT |
571 AV_SPARC_POPC);
572 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
573 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
574 sun4v_chip_type == SUN4V_CHIP_NIAGARA5 ||
575 sun4v_chip_type == SUN4V_CHIP_SPARC_M6 ||
576 sun4v_chip_type == SUN4V_CHIP_SPARC_M7 ||
577 sun4v_chip_type == SUN4V_CHIP_SPARC_SN ||
578 sun4v_chip_type == SUN4V_CHIP_SPARC64X)
579 cap |= (AV_SPARC_VIS3 | AV_SPARC_HPC |
580 AV_SPARC_FMAF);
581 }
582 }
583 sparc64_elf_hwcap = cap | mdesc_caps;
584
585 report_hwcaps(sparc64_elf_hwcap);
586
587 if (sparc64_elf_hwcap & AV_SPARC_POPC)
588 popc_patch();
589 if (sparc64_elf_hwcap & AV_SPARC_PAUSE)
590 pause_patch();
591}
592
593void __init setup_arch(char **cmdline_p)
594{
595
596 *cmdline_p = prom_getbootargs();
597 strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE);
598 parse_early_param();
599
600 boot_flags_init(*cmdline_p);
601#ifdef CONFIG_EARLYFB
602 if (btext_find_display())
603#endif
604 register_console(&prom_early_console);
605
606 if (tlb_type == hypervisor)
607 printk("ARCH: SUN4V\n");
608 else
609 printk("ARCH: SUN4U\n");
610
611#ifdef CONFIG_DUMMY_CONSOLE
612 conswitchp = &dummy_con;
613#endif
614
615 idprom_init();
616
617 if (!root_flags)
618 root_mountflags &= ~MS_RDONLY;
619 ROOT_DEV = old_decode_dev(root_dev);
620#ifdef CONFIG_BLK_DEV_RAM
621 rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
622 rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
623 rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);
624#endif
625
626 task_thread_info(&init_task)->kregs = &fake_swapper_regs;
627
628#ifdef CONFIG_IP_PNP
629 if (!ic_set_manually) {
630 phandle chosen = prom_finddevice("/chosen");
631 u32 cl, sv, gw;
632
633 cl = prom_getintdefault (chosen, "client-ip", 0);
634 sv = prom_getintdefault (chosen, "server-ip", 0);
635 gw = prom_getintdefault (chosen, "gateway-ip", 0);
636 if (cl && sv) {
637 ic_myaddr = cl;
638 ic_servaddr = sv;
639 if (gw)
640 ic_gateway = gw;
641#if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP)
642 ic_proto_enabled = 0;
643#endif
644 }
645 }
646#endif
647
648
649 init_cur_cpu_trap(current_thread_info());
650
651 paging_init();
652 init_sparc64_elf_hwcap();
653}
654
655extern int stop_a_enabled;
656
657void sun_do_break(void)
658{
659 if (!stop_a_enabled)
660 return;
661
662 prom_printf("\n");
663 flush_user_windows();
664
665 prom_cmdline();
666}
667EXPORT_SYMBOL(sun_do_break);
668
669int stop_a_enabled = 1;
670EXPORT_SYMBOL(stop_a_enabled);
671