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 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 sun_m7_patch_2insn_range(&__sun_m7_2insn_patch,
290 &__sun_m7_2insn_patch_end);
291
292 sun4v_hvapi_init();
293}
294
295static void __init popc_patch(void)
296{
297 struct popc_3insn_patch_entry *p3;
298 struct popc_6insn_patch_entry *p6;
299
300 p3 = &__popc_3insn_patch;
301 while (p3 < &__popc_3insn_patch_end) {
302 unsigned long i, addr = p3->addr;
303
304 for (i = 0; i < 3; i++) {
305 *(unsigned int *) (addr + (i * 4)) = p3->insns[i];
306 wmb();
307 __asm__ __volatile__("flush %0"
308 : : "r" (addr + (i * 4)));
309 }
310
311 p3++;
312 }
313
314 p6 = &__popc_6insn_patch;
315 while (p6 < &__popc_6insn_patch_end) {
316 unsigned long i, addr = p6->addr;
317
318 for (i = 0; i < 6; i++) {
319 *(unsigned int *) (addr + (i * 4)) = p6->insns[i];
320 wmb();
321 __asm__ __volatile__("flush %0"
322 : : "r" (addr + (i * 4)));
323 }
324
325 p6++;
326 }
327}
328
329static void __init pause_patch(void)
330{
331 struct pause_patch_entry *p;
332
333 p = &__pause_3insn_patch;
334 while (p < &__pause_3insn_patch_end) {
335 unsigned long i, addr = p->addr;
336
337 for (i = 0; i < 3; i++) {
338 *(unsigned int *) (addr + (i * 4)) = p->insns[i];
339 wmb();
340 __asm__ __volatile__("flush %0"
341 : : "r" (addr + (i * 4)));
342 }
343
344 p++;
345 }
346}
347
348void __init start_early_boot(void)
349{
350 int cpu;
351
352 check_if_starfire();
353 per_cpu_patch();
354 sun4v_patch();
355
356 cpu = hard_smp_processor_id();
357 if (cpu >= NR_CPUS) {
358 prom_printf("Serious problem, boot cpu id (%d) >= NR_CPUS (%d)\n",
359 cpu, NR_CPUS);
360 prom_halt();
361 }
362 current_thread_info()->cpu = cpu;
363
364 prom_init_report();
365 start_kernel();
366}
367
368
369unsigned long sparc64_elf_hwcap = (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR |
370 HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV |
371 HWCAP_SPARC_V9);
372EXPORT_SYMBOL(sparc64_elf_hwcap);
373
374static const char *hwcaps[] = {
375 "flush", "stbar", "swap", "muldiv", "v9",
376 "ultra3", "blkinit", "n2",
377
378
379
380
381 "mul32", "div32", "fsmuld", "v8plus", "popc", "vis", "vis2",
382 "ASIBlkInit", "fmaf", "vis3", "hpc", "random", "trans", "fjfmau",
383 "ima", "cspare", "pause", "cbcond",
384};
385
386static const char *crypto_hwcaps[] = {
387 "aes", "des", "kasumi", "camellia", "md5", "sha1", "sha256",
388 "sha512", "mpmul", "montmul", "montsqr", "crc32c",
389};
390
391void cpucap_info(struct seq_file *m)
392{
393 unsigned long caps = sparc64_elf_hwcap;
394 int i, printed = 0;
395
396 seq_puts(m, "cpucaps\t\t: ");
397 for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
398 unsigned long bit = 1UL << i;
399 if (caps & bit) {
400 seq_printf(m, "%s%s",
401 printed ? "," : "", hwcaps[i]);
402 printed++;
403 }
404 }
405 if (caps & HWCAP_SPARC_CRYPTO) {
406 unsigned long cfr;
407
408 __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
409 for (i = 0; i < ARRAY_SIZE(crypto_hwcaps); i++) {
410 unsigned long bit = 1UL << i;
411 if (cfr & bit) {
412 seq_printf(m, "%s%s",
413 printed ? "," : "", crypto_hwcaps[i]);
414 printed++;
415 }
416 }
417 }
418 seq_putc(m, '\n');
419}
420
421static void __init report_one_hwcap(int *printed, const char *name)
422{
423 if ((*printed) == 0)
424 printk(KERN_INFO "CPU CAPS: [");
425 printk(KERN_CONT "%s%s",
426 (*printed) ? "," : "", name);
427 if (++(*printed) == 8) {
428 printk(KERN_CONT "]\n");
429 *printed = 0;
430 }
431}
432
433static void __init report_crypto_hwcaps(int *printed)
434{
435 unsigned long cfr;
436 int i;
437
438 __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
439
440 for (i = 0; i < ARRAY_SIZE(crypto_hwcaps); i++) {
441 unsigned long bit = 1UL << i;
442 if (cfr & bit)
443 report_one_hwcap(printed, crypto_hwcaps[i]);
444 }
445}
446
447static void __init report_hwcaps(unsigned long caps)
448{
449 int i, printed = 0;
450
451 for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
452 unsigned long bit = 1UL << i;
453 if (caps & bit)
454 report_one_hwcap(&printed, hwcaps[i]);
455 }
456 if (caps & HWCAP_SPARC_CRYPTO)
457 report_crypto_hwcaps(&printed);
458 if (printed != 0)
459 printk(KERN_CONT "]\n");
460}
461
462static unsigned long __init mdesc_cpu_hwcap_list(void)
463{
464 struct mdesc_handle *hp;
465 unsigned long caps = 0;
466 const char *prop;
467 int len;
468 u64 pn;
469
470 hp = mdesc_grab();
471 if (!hp)
472 return 0;
473
474 pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "cpu");
475 if (pn == MDESC_NODE_NULL)
476 goto out;
477
478 prop = mdesc_get_property(hp, pn, "hwcap-list", &len);
479 if (!prop)
480 goto out;
481
482 while (len) {
483 int i, plen;
484
485 for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
486 unsigned long bit = 1UL << i;
487
488 if (!strcmp(prop, hwcaps[i])) {
489 caps |= bit;
490 break;
491 }
492 }
493 for (i = 0; i < ARRAY_SIZE(crypto_hwcaps); i++) {
494 if (!strcmp(prop, crypto_hwcaps[i]))
495 caps |= HWCAP_SPARC_CRYPTO;
496 }
497
498 plen = strlen(prop) + 1;
499 prop += plen;
500 len -= plen;
501 }
502
503out:
504 mdesc_release(hp);
505 return caps;
506}
507
508
509
510
511static void __init init_sparc64_elf_hwcap(void)
512{
513 unsigned long cap = sparc64_elf_hwcap;
514 unsigned long mdesc_caps;
515
516 if (tlb_type == cheetah || tlb_type == cheetah_plus)
517 cap |= HWCAP_SPARC_ULTRA3;
518 else if (tlb_type == hypervisor) {
519 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 ||
520 sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
521 sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
522 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
523 sun4v_chip_type == SUN4V_CHIP_NIAGARA5 ||
524 sun4v_chip_type == SUN4V_CHIP_SPARC_M6 ||
525 sun4v_chip_type == SUN4V_CHIP_SPARC_M7 ||
526 sun4v_chip_type == SUN4V_CHIP_SPARC64X)
527 cap |= HWCAP_SPARC_BLKINIT;
528 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
529 sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
530 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
531 sun4v_chip_type == SUN4V_CHIP_NIAGARA5 ||
532 sun4v_chip_type == SUN4V_CHIP_SPARC_M6 ||
533 sun4v_chip_type == SUN4V_CHIP_SPARC_M7 ||
534 sun4v_chip_type == SUN4V_CHIP_SPARC64X)
535 cap |= HWCAP_SPARC_N2;
536 }
537
538 cap |= (AV_SPARC_MUL32 | AV_SPARC_DIV32 | AV_SPARC_V8PLUS);
539
540 mdesc_caps = mdesc_cpu_hwcap_list();
541 if (!mdesc_caps) {
542 if (tlb_type == spitfire)
543 cap |= AV_SPARC_VIS;
544 if (tlb_type == cheetah || tlb_type == cheetah_plus)
545 cap |= AV_SPARC_VIS | AV_SPARC_VIS2;
546 if (tlb_type == cheetah_plus) {
547 unsigned long impl, ver;
548
549 __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver));
550 impl = ((ver >> 32) & 0xffff);
551 if (impl == PANTHER_IMPL)
552 cap |= AV_SPARC_POPC;
553 }
554 if (tlb_type == hypervisor) {
555 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1)
556 cap |= AV_SPARC_ASI_BLK_INIT;
557 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
558 sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
559 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
560 sun4v_chip_type == SUN4V_CHIP_NIAGARA5 ||
561 sun4v_chip_type == SUN4V_CHIP_SPARC_M6 ||
562 sun4v_chip_type == SUN4V_CHIP_SPARC_M7 ||
563 sun4v_chip_type == SUN4V_CHIP_SPARC64X)
564 cap |= (AV_SPARC_VIS | AV_SPARC_VIS2 |
565 AV_SPARC_ASI_BLK_INIT |
566 AV_SPARC_POPC);
567 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
568 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
569 sun4v_chip_type == SUN4V_CHIP_NIAGARA5 ||
570 sun4v_chip_type == SUN4V_CHIP_SPARC_M6 ||
571 sun4v_chip_type == SUN4V_CHIP_SPARC_M7 ||
572 sun4v_chip_type == SUN4V_CHIP_SPARC64X)
573 cap |= (AV_SPARC_VIS3 | AV_SPARC_HPC |
574 AV_SPARC_FMAF);
575 }
576 }
577 sparc64_elf_hwcap = cap | mdesc_caps;
578
579 report_hwcaps(sparc64_elf_hwcap);
580
581 if (sparc64_elf_hwcap & AV_SPARC_POPC)
582 popc_patch();
583 if (sparc64_elf_hwcap & AV_SPARC_PAUSE)
584 pause_patch();
585}
586
587void __init setup_arch(char **cmdline_p)
588{
589
590 *cmdline_p = prom_getbootargs();
591 strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE);
592 parse_early_param();
593
594 boot_flags_init(*cmdline_p);
595#ifdef CONFIG_EARLYFB
596 if (btext_find_display())
597#endif
598 register_console(&prom_early_console);
599
600 if (tlb_type == hypervisor)
601 printk("ARCH: SUN4V\n");
602 else
603 printk("ARCH: SUN4U\n");
604
605#ifdef CONFIG_DUMMY_CONSOLE
606 conswitchp = &dummy_con;
607#endif
608
609 idprom_init();
610
611 if (!root_flags)
612 root_mountflags &= ~MS_RDONLY;
613 ROOT_DEV = old_decode_dev(root_dev);
614#ifdef CONFIG_BLK_DEV_RAM
615 rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
616 rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
617 rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);
618#endif
619
620 task_thread_info(&init_task)->kregs = &fake_swapper_regs;
621
622#ifdef CONFIG_IP_PNP
623 if (!ic_set_manually) {
624 phandle chosen = prom_finddevice("/chosen");
625 u32 cl, sv, gw;
626
627 cl = prom_getintdefault (chosen, "client-ip", 0);
628 sv = prom_getintdefault (chosen, "server-ip", 0);
629 gw = prom_getintdefault (chosen, "gateway-ip", 0);
630 if (cl && sv) {
631 ic_myaddr = cl;
632 ic_servaddr = sv;
633 if (gw)
634 ic_gateway = gw;
635#if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP)
636 ic_proto_enabled = 0;
637#endif
638 }
639 }
640#endif
641
642
643 init_cur_cpu_trap(current_thread_info());
644
645 paging_init();
646 init_sparc64_elf_hwcap();
647}
648
649extern int stop_a_enabled;
650
651void sun_do_break(void)
652{
653 if (!stop_a_enabled)
654 return;
655
656 prom_printf("\n");
657 flush_user_windows();
658
659 prom_cmdline();
660}
661EXPORT_SYMBOL(sun_do_break);
662
663int stop_a_enabled = 1;
664EXPORT_SYMBOL(stop_a_enabled);
665