Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
setup_64.c
Go to the documentation of this file.
1 /*
2  * linux/arch/sparc64/kernel/setup.c
3  *
4  * Copyright (C) 1995,1996 David S. Miller ([email protected])
5  * Copyright (C) 1997 Jakub Jelinek ([email protected])
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 
34 #include <asm/io.h>
35 #include <asm/processor.h>
36 #include <asm/oplib.h>
37 #include <asm/page.h>
38 #include <asm/pgtable.h>
39 #include <asm/idprom.h>
40 #include <asm/head.h>
41 #include <asm/starfire.h>
42 #include <asm/mmu_context.h>
43 #include <asm/timer.h>
44 #include <asm/sections.h>
45 #include <asm/setup.h>
46 #include <asm/mmu.h>
47 #include <asm/ns87303.h>
48 #include <asm/btext.h>
49 #include <asm/elf.h>
50 #include <asm/mdesc.h>
51 #include <asm/cacheflush.h>
52 
53 #ifdef CONFIG_IP_PNP
54 #include <net/ipconfig.h>
55 #endif
56 
57 #include "entry.h"
58 #include "kernel.h"
59 
60 /* Used to synchronize accesses to NatSemi SUPER I/O chip configure
61  * operations in asm/ns87303.h
62  */
63 DEFINE_SPINLOCK(ns87303_lock);
64 EXPORT_SYMBOL(ns87303_lock);
65 
67  0, 0, /* orig-x, orig-y */
68  0, /* unused */
69  0, /* orig-video-page */
70  0, /* orig-video-mode */
71  128, /* orig-video-cols */
72  0, 0, 0, /* unused, ega_bx, unused */
73  54, /* orig-video-lines */
74  0, /* orig-video-isVGA */
75  16 /* orig-video-points */
76 };
77 
78 static void
79 prom_console_write(struct console *con, const char *s, unsigned n)
80 {
81  prom_write(s, n);
82 }
83 
84 /* Exported for mm/init.c:paging_init. */
85 unsigned long cmdline_memory_size = 0;
86 
87 static struct console prom_early_console = {
88  .name = "earlyprom",
89  .write = prom_console_write,
91  .index = -1,
92 };
93 
94 /*
95  * Process kernel command line switches that are specific to the
96  * SPARC or that require special low-level processing.
97  */
98 static void __init process_switch(char c)
99 {
100  switch (c) {
101  case 'd':
102  case 's':
103  break;
104  case 'h':
105  prom_printf("boot_flags_init: Halt!\n");
106  prom_halt();
107  break;
108  case 'p':
109  prom_early_console.flags &= ~CON_BOOT;
110  break;
111  case 'P':
112  /* Force UltraSPARC-III P-Cache on. */
113  if (tlb_type != cheetah) {
114  printk("BOOT: Ignoring P-Cache force option.\n");
115  break;
116  }
120  break;
121 
122  default:
123  printk("Unknown boot switch (-%c)\n", c);
124  break;
125  }
126 }
127 
128 static void __init boot_flags_init(char *commands)
129 {
130  while (*commands) {
131  /* Move to the start of the next "argument". */
132  while (*commands && *commands == ' ')
133  commands++;
134 
135  /* Process any command switches, otherwise skip it. */
136  if (*commands == '\0')
137  break;
138  if (*commands == '-') {
139  commands++;
140  while (*commands && *commands != ' ')
141  process_switch(*commands++);
142  continue;
143  }
144  if (!strncmp(commands, "mem=", 4)) {
145  /*
146  * "mem=XXX[kKmM]" overrides the PROM-reported
147  * memory size.
148  */
149  cmdline_memory_size = simple_strtoul(commands + 4,
150  &commands, 0);
151  if (*commands == 'K' || *commands == 'k') {
152  cmdline_memory_size <<= 10;
153  commands++;
154  } else if (*commands=='M' || *commands=='m') {
155  cmdline_memory_size <<= 20;
156  commands++;
157  }
158  }
159  while (*commands && *commands != ' ')
160  commands++;
161  }
162 }
163 
164 extern unsigned short root_flags;
165 extern unsigned short root_dev;
166 extern unsigned short ram_flags;
167 #define RAMDISK_IMAGE_START_MASK 0x07FF
168 #define RAMDISK_PROMPT_FLAG 0x8000
169 #define RAMDISK_LOAD_FLAG 0x4000
170 
171 extern int root_mountflags;
172 
174 
175 static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 };
176 
178 {
179  struct cpuid_patch_entry *p;
180  unsigned long ver;
181  int is_jbus;
182 
183  if (tlb_type == spitfire && !this_is_starfire)
184  return;
185 
186  is_jbus = 0;
187  if (tlb_type != hypervisor) {
188  __asm__ ("rdpr %%ver, %0" : "=r" (ver));
189  is_jbus = ((ver >> 32UL) == __JALAPENO_ID ||
190  (ver >> 32UL) == __SERRANO_ID);
191  }
192 
193  p = &__cpuid_patch;
194  while (p < &__cpuid_patch_end) {
195  unsigned long addr = p->addr;
196  unsigned int *insns;
197 
198  switch (tlb_type) {
199  case spitfire:
200  insns = &p->starfire[0];
201  break;
202  case cheetah:
203  case cheetah_plus:
204  if (is_jbus)
205  insns = &p->cheetah_jbus[0];
206  else
207  insns = &p->cheetah_safari[0];
208  break;
209  case hypervisor:
210  insns = &p->sun4v[0];
211  break;
212  default:
213  prom_printf("Unknown cpu type, halting.\n");
214  prom_halt();
215  }
216 
217  *(unsigned int *) (addr + 0) = insns[0];
218  wmb();
219  __asm__ __volatile__("flush %0" : : "r" (addr + 0));
220 
221  *(unsigned int *) (addr + 4) = insns[1];
222  wmb();
223  __asm__ __volatile__("flush %0" : : "r" (addr + 4));
224 
225  *(unsigned int *) (addr + 8) = insns[2];
226  wmb();
227  __asm__ __volatile__("flush %0" : : "r" (addr + 8));
228 
229  *(unsigned int *) (addr + 12) = insns[3];
230  wmb();
231  __asm__ __volatile__("flush %0" : : "r" (addr + 12));
232 
233  p++;
234  }
235 }
236 
239 {
240  while (start < end) {
241  unsigned long addr = start->addr;
242 
243  *(unsigned int *) (addr + 0) = start->insn;
244  wmb();
245  __asm__ __volatile__("flush %0" : : "r" (addr + 0));
246 
247  start++;
248  }
249 }
250 
253 {
254  while (start < end) {
255  unsigned long addr = start->addr;
256 
257  *(unsigned int *) (addr + 0) = start->insns[0];
258  wmb();
259  __asm__ __volatile__("flush %0" : : "r" (addr + 0));
260 
261  *(unsigned int *) (addr + 4) = start->insns[1];
262  wmb();
263  __asm__ __volatile__("flush %0" : : "r" (addr + 4));
264 
265  start++;
266  }
267 }
268 
269 void __init sun4v_patch(void)
270 {
271  extern void sun4v_hvapi_init(void);
272 
273  if (tlb_type != hypervisor)
274  return;
275 
276  sun4v_patch_1insn_range(&__sun4v_1insn_patch,
278 
279  sun4v_patch_2insn_range(&__sun4v_2insn_patch,
281 
283 }
284 
285 static void __init popc_patch(void)
286 {
287  struct popc_3insn_patch_entry *p3;
288  struct popc_6insn_patch_entry *p6;
289 
290  p3 = &__popc_3insn_patch;
291  while (p3 < &__popc_3insn_patch_end) {
292  unsigned long i, addr = p3->addr;
293 
294  for (i = 0; i < 3; i++) {
295  *(unsigned int *) (addr + (i * 4)) = p3->insns[i];
296  wmb();
297  __asm__ __volatile__("flush %0"
298  : : "r" (addr + (i * 4)));
299  }
300 
301  p3++;
302  }
303 
304  p6 = &__popc_6insn_patch;
305  while (p6 < &__popc_6insn_patch_end) {
306  unsigned long i, addr = p6->addr;
307 
308  for (i = 0; i < 6; i++) {
309  *(unsigned int *) (addr + (i * 4)) = p6->insns[i];
310  wmb();
311  __asm__ __volatile__("flush %0"
312  : : "r" (addr + (i * 4)));
313  }
314 
315  p6++;
316  }
317 }
318 
319 static void __init pause_patch(void)
320 {
321  struct pause_patch_entry *p;
322 
323  p = &__pause_3insn_patch;
324  while (p < &__pause_3insn_patch_end) {
325  unsigned long i, addr = p->addr;
326 
327  for (i = 0; i < 3; i++) {
328  *(unsigned int *) (addr + (i * 4)) = p->insns[i];
329  wmb();
330  __asm__ __volatile__("flush %0"
331  : : "r" (addr + (i * 4)));
332  }
333 
334  p++;
335  }
336 }
337 
338 #ifdef CONFIG_SMP
340 {
341  prom_printf("Serious problem, boot cpu id (%d) >= NR_CPUS (%d)\n",
342  cpu, NR_CPUS);
343  prom_halt();
344 }
345 #endif
346 
347 /* On Ultra, we support all of the v8 capabilities. */
351 EXPORT_SYMBOL(sparc64_elf_hwcap);
352 
353 static const char *hwcaps[] = {
354  "flush", "stbar", "swap", "muldiv", "v9",
355  "ultra3", "blkinit", "n2",
356 
357  /* These strings are as they appear in the machine description
358  * 'hwcap-list' property for cpu nodes.
359  */
360  "mul32", "div32", "fsmuld", "v8plus", "popc", "vis", "vis2",
361  "ASIBlkInit", "fmaf", "vis3", "hpc", "random", "trans", "fjfmau",
362  "ima", "cspare", "pause", "cbcond",
363 };
364 
365 static const char *crypto_hwcaps[] = {
366  "aes", "des", "kasumi", "camellia", "md5", "sha1", "sha256",
367  "sha512", "mpmul", "montmul", "montsqr", "crc32c",
368 };
369 
370 void cpucap_info(struct seq_file *m)
371 {
372  unsigned long caps = sparc64_elf_hwcap;
373  int i, printed = 0;
374 
375  seq_puts(m, "cpucaps\t\t: ");
376  for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
377  unsigned long bit = 1UL << i;
378  if (caps & bit) {
379  seq_printf(m, "%s%s",
380  printed ? "," : "", hwcaps[i]);
381  printed++;
382  }
383  }
384  if (caps & HWCAP_SPARC_CRYPTO) {
385  unsigned long cfr;
386 
387  __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
388  for (i = 0; i < ARRAY_SIZE(crypto_hwcaps); i++) {
389  unsigned long bit = 1UL << i;
390  if (cfr & bit) {
391  seq_printf(m, "%s%s",
392  printed ? "," : "", crypto_hwcaps[i]);
393  printed++;
394  }
395  }
396  }
397  seq_putc(m, '\n');
398 }
399 
400 static void __init report_one_hwcap(int *printed, const char *name)
401 {
402  if ((*printed) == 0)
403  printk(KERN_INFO "CPU CAPS: [");
404  printk(KERN_CONT "%s%s",
405  (*printed) ? "," : "", name);
406  if (++(*printed) == 8) {
407  printk(KERN_CONT "]\n");
408  *printed = 0;
409  }
410 }
411 
412 static void __init report_crypto_hwcaps(int *printed)
413 {
414  unsigned long cfr;
415  int i;
416 
417  __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
418 
419  for (i = 0; i < ARRAY_SIZE(crypto_hwcaps); i++) {
420  unsigned long bit = 1UL << i;
421  if (cfr & bit)
422  report_one_hwcap(printed, crypto_hwcaps[i]);
423  }
424 }
425 
426 static void __init report_hwcaps(unsigned long caps)
427 {
428  int i, printed = 0;
429 
430  for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
431  unsigned long bit = 1UL << i;
432  if (caps & bit)
433  report_one_hwcap(&printed, hwcaps[i]);
434  }
435  if (caps & HWCAP_SPARC_CRYPTO)
436  report_crypto_hwcaps(&printed);
437  if (printed != 0)
438  printk(KERN_CONT "]\n");
439 }
440 
441 static unsigned long __init mdesc_cpu_hwcap_list(void)
442 {
443  struct mdesc_handle *hp;
444  unsigned long caps = 0;
445  const char *prop;
446  int len;
447  u64 pn;
448 
449  hp = mdesc_grab();
450  if (!hp)
451  return 0;
452 
453  pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "cpu");
454  if (pn == MDESC_NODE_NULL)
455  goto out;
456 
457  prop = mdesc_get_property(hp, pn, "hwcap-list", &len);
458  if (!prop)
459  goto out;
460 
461  while (len) {
462  int i, plen;
463 
464  for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
465  unsigned long bit = 1UL << i;
466 
467  if (!strcmp(prop, hwcaps[i])) {
468  caps |= bit;
469  break;
470  }
471  }
472  for (i = 0; i < ARRAY_SIZE(crypto_hwcaps); i++) {
473  if (!strcmp(prop, crypto_hwcaps[i]))
474  caps |= HWCAP_SPARC_CRYPTO;
475  }
476 
477  plen = strlen(prop) + 1;
478  prop += plen;
479  len -= plen;
480  }
481 
482 out:
483  mdesc_release(hp);
484  return caps;
485 }
486 
487 /* This yields a mask that user programs can use to figure out what
488  * instruction set this cpu supports.
489  */
490 static void __init init_sparc64_elf_hwcap(void)
491 {
492  unsigned long cap = sparc64_elf_hwcap;
493  unsigned long mdesc_caps;
494 
495  if (tlb_type == cheetah || tlb_type == cheetah_plus)
496  cap |= HWCAP_SPARC_ULTRA3;
497  else if (tlb_type == hypervisor) {
498  if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 ||
499  sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
500  sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
501  sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
502  sun4v_chip_type == SUN4V_CHIP_NIAGARA5)
503  cap |= HWCAP_SPARC_BLKINIT;
504  if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
505  sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
506  sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
507  sun4v_chip_type == SUN4V_CHIP_NIAGARA5)
508  cap |= HWCAP_SPARC_N2;
509  }
510 
512 
513  mdesc_caps = mdesc_cpu_hwcap_list();
514  if (!mdesc_caps) {
515  if (tlb_type == spitfire)
516  cap |= AV_SPARC_VIS;
517  if (tlb_type == cheetah || tlb_type == cheetah_plus)
518  cap |= AV_SPARC_VIS | AV_SPARC_VIS2;
519  if (tlb_type == cheetah_plus) {
520  unsigned long impl, ver;
521 
522  __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver));
523  impl = ((ver >> 32) & 0xffff);
524  if (impl == PANTHER_IMPL)
525  cap |= AV_SPARC_POPC;
526  }
527  if (tlb_type == hypervisor) {
528  if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1)
529  cap |= AV_SPARC_ASI_BLK_INIT;
530  if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
531  sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
532  sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
533  sun4v_chip_type == SUN4V_CHIP_NIAGARA5)
534  cap |= (AV_SPARC_VIS | AV_SPARC_VIS2 |
536  AV_SPARC_POPC);
537  if (sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
538  sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
539  sun4v_chip_type == SUN4V_CHIP_NIAGARA5)
540  cap |= (AV_SPARC_VIS3 | AV_SPARC_HPC |
541  AV_SPARC_FMAF);
542  }
543  }
544  sparc64_elf_hwcap = cap | mdesc_caps;
545 
546  report_hwcaps(sparc64_elf_hwcap);
547 
548  if (sparc64_elf_hwcap & AV_SPARC_POPC)
549  popc_patch();
550  if (sparc64_elf_hwcap & AV_SPARC_PAUSE)
551  pause_patch();
552 }
553 
554 void __init setup_arch(char **cmdline_p)
555 {
556  /* Initialize PROM console and command line. */
557  *cmdline_p = prom_getbootargs();
558  strcpy(boot_command_line, *cmdline_p);
560 
561  boot_flags_init(*cmdline_p);
562 #ifdef CONFIG_EARLYFB
563  if (btext_find_display())
564 #endif
565  register_console(&prom_early_console);
566 
567  if (tlb_type == hypervisor)
568  printk("ARCH: SUN4V\n");
569  else
570  printk("ARCH: SUN4U\n");
571 
572 #ifdef CONFIG_DUMMY_CONSOLE
574 #endif
575 
576  idprom_init();
577 
578  if (!root_flags)
579  root_mountflags &= ~MS_RDONLY;
580  ROOT_DEV = old_decode_dev(root_dev);
581 #ifdef CONFIG_BLK_DEV_RAM
583  rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
584  rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);
585 #endif
586 
588 
589 #ifdef CONFIG_IP_PNP
590  if (!ic_set_manually) {
591  phandle chosen = prom_finddevice("/chosen");
592  u32 cl, sv, gw;
593 
594  cl = prom_getintdefault (chosen, "client-ip", 0);
595  sv = prom_getintdefault (chosen, "server-ip", 0);
596  gw = prom_getintdefault (chosen, "gateway-ip", 0);
597  if (cl && sv) {
598  ic_myaddr = cl;
599  ic_servaddr = sv;
600  if (gw)
601  ic_gateway = gw;
602 #if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP)
603  ic_proto_enabled = 0;
604 #endif
605  }
606  }
607 #endif
608 
609  /* Get boot processor trap_block[] setup. */
611 
612  paging_init();
613  init_sparc64_elf_hwcap();
614 }
615 
616 extern int stop_a_enabled;
617 
618 void sun_do_break(void)
619 {
620  if (!stop_a_enabled)
621  return;
622 
623  prom_printf("\n");
625 
626  prom_cmdline();
627 }
629 
630 int stop_a_enabled = 1;
631 EXPORT_SYMBOL(stop_a_enabled);