setup.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. /* $Id: setup.c,v 1.72 2002/02/09 19:49:30 davem Exp $
  2. * linux/arch/sparc64/kernel/setup.c
  3. *
  4. * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
  5. * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  6. */
  7. #include <linux/errno.h>
  8. #include <linux/sched.h>
  9. #include <linux/kernel.h>
  10. #include <linux/mm.h>
  11. #include <linux/stddef.h>
  12. #include <linux/unistd.h>
  13. #include <linux/ptrace.h>
  14. #include <linux/slab.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 <asm/system.h>
  33. #include <asm/io.h>
  34. #include <asm/processor.h>
  35. #include <asm/oplib.h>
  36. #include <asm/page.h>
  37. #include <asm/pgtable.h>
  38. #include <asm/idprom.h>
  39. #include <asm/head.h>
  40. #include <asm/starfire.h>
  41. #include <asm/mmu_context.h>
  42. #include <asm/timer.h>
  43. #include <asm/sections.h>
  44. #include <asm/setup.h>
  45. #include <asm/mmu.h>
  46. #include <asm/ns87303.h>
  47. #ifdef CONFIG_IP_PNP
  48. #include <net/ipconfig.h>
  49. #endif
  50. /* Used to synchronize accesses to NatSemi SUPER I/O chip configure
  51. * operations in asm/ns87303.h
  52. */
  53. DEFINE_SPINLOCK(ns87303_lock);
  54. struct screen_info screen_info = {
  55. 0, 0, /* orig-x, orig-y */
  56. 0, /* unused */
  57. 0, /* orig-video-page */
  58. 0, /* orig-video-mode */
  59. 128, /* orig-video-cols */
  60. 0, 0, 0, /* unused, ega_bx, unused */
  61. 54, /* orig-video-lines */
  62. 0, /* orig-video-isVGA */
  63. 16 /* orig-video-points */
  64. };
  65. static void
  66. prom_console_write(struct console *con, const char *s, unsigned n)
  67. {
  68. prom_write(s, n);
  69. }
  70. /* Exported for mm/init.c:paging_init. */
  71. unsigned long cmdline_memory_size = 0;
  72. static struct console prom_early_console = {
  73. .name = "earlyprom",
  74. .write = prom_console_write,
  75. .flags = CON_PRINTBUFFER | CON_BOOT,
  76. .index = -1,
  77. };
  78. /*
  79. * Process kernel command line switches that are specific to the
  80. * SPARC or that require special low-level processing.
  81. */
  82. static void __init process_switch(char c)
  83. {
  84. switch (c) {
  85. case 'd':
  86. case 's':
  87. break;
  88. case 'h':
  89. prom_printf("boot_flags_init: Halt!\n");
  90. prom_halt();
  91. break;
  92. case 'p':
  93. /* Just ignore, this behavior is now the default. */
  94. break;
  95. case 'P':
  96. /* Force UltraSPARC-III P-Cache on. */
  97. if (tlb_type != cheetah) {
  98. printk("BOOT: Ignoring P-Cache force option.\n");
  99. break;
  100. }
  101. cheetah_pcache_forced_on = 1;
  102. add_taint(TAINT_MACHINE_CHECK);
  103. cheetah_enable_pcache();
  104. break;
  105. default:
  106. printk("Unknown boot switch (-%c)\n", c);
  107. break;
  108. }
  109. }
  110. static void __init boot_flags_init(char *commands)
  111. {
  112. while (*commands) {
  113. /* Move to the start of the next "argument". */
  114. while (*commands && *commands == ' ')
  115. commands++;
  116. /* Process any command switches, otherwise skip it. */
  117. if (*commands == '\0')
  118. break;
  119. if (*commands == '-') {
  120. commands++;
  121. while (*commands && *commands != ' ')
  122. process_switch(*commands++);
  123. continue;
  124. }
  125. if (!strncmp(commands, "mem=", 4)) {
  126. /*
  127. * "mem=XXX[kKmM]" overrides the PROM-reported
  128. * memory size.
  129. */
  130. cmdline_memory_size = simple_strtoul(commands + 4,
  131. &commands, 0);
  132. if (*commands == 'K' || *commands == 'k') {
  133. cmdline_memory_size <<= 10;
  134. commands++;
  135. } else if (*commands=='M' || *commands=='m') {
  136. cmdline_memory_size <<= 20;
  137. commands++;
  138. }
  139. }
  140. while (*commands && *commands != ' ')
  141. commands++;
  142. }
  143. }
  144. extern unsigned short root_flags;
  145. extern unsigned short root_dev;
  146. extern unsigned short ram_flags;
  147. #define RAMDISK_IMAGE_START_MASK 0x07FF
  148. #define RAMDISK_PROMPT_FLAG 0x8000
  149. #define RAMDISK_LOAD_FLAG 0x4000
  150. extern int root_mountflags;
  151. char reboot_command[COMMAND_LINE_SIZE];
  152. static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 };
  153. void __init per_cpu_patch(void)
  154. {
  155. struct cpuid_patch_entry *p;
  156. unsigned long ver;
  157. int is_jbus;
  158. if (tlb_type == spitfire && !this_is_starfire)
  159. return;
  160. is_jbus = 0;
  161. if (tlb_type != hypervisor) {
  162. __asm__ ("rdpr %%ver, %0" : "=r" (ver));
  163. is_jbus = ((ver >> 32UL) == __JALAPENO_ID ||
  164. (ver >> 32UL) == __SERRANO_ID);
  165. }
  166. p = &__cpuid_patch;
  167. while (p < &__cpuid_patch_end) {
  168. unsigned long addr = p->addr;
  169. unsigned int *insns;
  170. switch (tlb_type) {
  171. case spitfire:
  172. insns = &p->starfire[0];
  173. break;
  174. case cheetah:
  175. case cheetah_plus:
  176. if (is_jbus)
  177. insns = &p->cheetah_jbus[0];
  178. else
  179. insns = &p->cheetah_safari[0];
  180. break;
  181. case hypervisor:
  182. insns = &p->sun4v[0];
  183. break;
  184. default:
  185. prom_printf("Unknown cpu type, halting.\n");
  186. prom_halt();
  187. };
  188. *(unsigned int *) (addr + 0) = insns[0];
  189. wmb();
  190. __asm__ __volatile__("flush %0" : : "r" (addr + 0));
  191. *(unsigned int *) (addr + 4) = insns[1];
  192. wmb();
  193. __asm__ __volatile__("flush %0" : : "r" (addr + 4));
  194. *(unsigned int *) (addr + 8) = insns[2];
  195. wmb();
  196. __asm__ __volatile__("flush %0" : : "r" (addr + 8));
  197. *(unsigned int *) (addr + 12) = insns[3];
  198. wmb();
  199. __asm__ __volatile__("flush %0" : : "r" (addr + 12));
  200. p++;
  201. }
  202. }
  203. void __init sun4v_patch(void)
  204. {
  205. extern void sun4v_hvapi_init(void);
  206. struct sun4v_1insn_patch_entry *p1;
  207. struct sun4v_2insn_patch_entry *p2;
  208. if (tlb_type != hypervisor)
  209. return;
  210. p1 = &__sun4v_1insn_patch;
  211. while (p1 < &__sun4v_1insn_patch_end) {
  212. unsigned long addr = p1->addr;
  213. *(unsigned int *) (addr + 0) = p1->insn;
  214. wmb();
  215. __asm__ __volatile__("flush %0" : : "r" (addr + 0));
  216. p1++;
  217. }
  218. p2 = &__sun4v_2insn_patch;
  219. while (p2 < &__sun4v_2insn_patch_end) {
  220. unsigned long addr = p2->addr;
  221. *(unsigned int *) (addr + 0) = p2->insns[0];
  222. wmb();
  223. __asm__ __volatile__("flush %0" : : "r" (addr + 0));
  224. *(unsigned int *) (addr + 4) = p2->insns[1];
  225. wmb();
  226. __asm__ __volatile__("flush %0" : : "r" (addr + 4));
  227. p2++;
  228. }
  229. sun4v_hvapi_init();
  230. }
  231. #ifdef CONFIG_SMP
  232. void __init boot_cpu_id_too_large(int cpu)
  233. {
  234. prom_printf("Serious problem, boot cpu id (%d) >= NR_CPUS (%d)\n",
  235. cpu, NR_CPUS);
  236. prom_halt();
  237. }
  238. #endif
  239. void __init setup_arch(char **cmdline_p)
  240. {
  241. /* Initialize PROM console and command line. */
  242. *cmdline_p = prom_getbootargs();
  243. strcpy(boot_command_line, *cmdline_p);
  244. boot_flags_init(*cmdline_p);
  245. register_console(&prom_early_console);
  246. if (tlb_type == hypervisor)
  247. printk("ARCH: SUN4V\n");
  248. else
  249. printk("ARCH: SUN4U\n");
  250. #ifdef CONFIG_DUMMY_CONSOLE
  251. conswitchp = &dummy_con;
  252. #elif defined(CONFIG_PROM_CONSOLE)
  253. conswitchp = &prom_con;
  254. #endif
  255. idprom_init();
  256. if (!root_flags)
  257. root_mountflags &= ~MS_RDONLY;
  258. ROOT_DEV = old_decode_dev(root_dev);
  259. #ifdef CONFIG_BLK_DEV_RAM
  260. rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
  261. rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
  262. rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);
  263. #endif
  264. task_thread_info(&init_task)->kregs = &fake_swapper_regs;
  265. #ifdef CONFIG_IP_PNP
  266. if (!ic_set_manually) {
  267. int chosen = prom_finddevice ("/chosen");
  268. u32 cl, sv, gw;
  269. cl = prom_getintdefault (chosen, "client-ip", 0);
  270. sv = prom_getintdefault (chosen, "server-ip", 0);
  271. gw = prom_getintdefault (chosen, "gateway-ip", 0);
  272. if (cl && sv) {
  273. ic_myaddr = cl;
  274. ic_servaddr = sv;
  275. if (gw)
  276. ic_gateway = gw;
  277. #if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP)
  278. ic_proto_enabled = 0;
  279. #endif
  280. }
  281. }
  282. #endif
  283. /* Get boot processor trap_block[] setup. */
  284. init_cur_cpu_trap(current_thread_info());
  285. paging_init();
  286. }
  287. /* BUFFER is PAGE_SIZE bytes long. */
  288. extern char *sparc_cpu_type;
  289. extern char *sparc_fpu_type;
  290. extern void smp_info(struct seq_file *);
  291. extern void smp_bogo(struct seq_file *);
  292. extern void mmu_info(struct seq_file *);
  293. unsigned int dcache_parity_tl1_occurred;
  294. unsigned int icache_parity_tl1_occurred;
  295. int ncpus_probed;
  296. static int show_cpuinfo(struct seq_file *m, void *__unused)
  297. {
  298. seq_printf(m,
  299. "cpu\t\t: %s\n"
  300. "fpu\t\t: %s\n"
  301. "prom\t\t: %s\n"
  302. "type\t\t: %s\n"
  303. "ncpus probed\t: %d\n"
  304. "ncpus active\t: %d\n"
  305. "D$ parity tl1\t: %u\n"
  306. "I$ parity tl1\t: %u\n"
  307. #ifndef CONFIG_SMP
  308. "Cpu0ClkTck\t: %016lx\n"
  309. #endif
  310. ,
  311. sparc_cpu_type,
  312. sparc_fpu_type,
  313. prom_version,
  314. ((tlb_type == hypervisor) ?
  315. "sun4v" :
  316. "sun4u"),
  317. ncpus_probed,
  318. num_online_cpus(),
  319. dcache_parity_tl1_occurred,
  320. icache_parity_tl1_occurred
  321. #ifndef CONFIG_SMP
  322. , cpu_data(0).clock_tick
  323. #endif
  324. );
  325. #ifdef CONFIG_SMP
  326. smp_bogo(m);
  327. #endif
  328. mmu_info(m);
  329. #ifdef CONFIG_SMP
  330. smp_info(m);
  331. #endif
  332. return 0;
  333. }
  334. static void *c_start(struct seq_file *m, loff_t *pos)
  335. {
  336. /* The pointer we are returning is arbitrary,
  337. * it just has to be non-NULL and not IS_ERR
  338. * in the success case.
  339. */
  340. return *pos == 0 ? &c_start : NULL;
  341. }
  342. static void *c_next(struct seq_file *m, void *v, loff_t *pos)
  343. {
  344. ++*pos;
  345. return c_start(m, pos);
  346. }
  347. static void c_stop(struct seq_file *m, void *v)
  348. {
  349. }
  350. const struct seq_operations cpuinfo_op = {
  351. .start =c_start,
  352. .next = c_next,
  353. .stop = c_stop,
  354. .show = show_cpuinfo,
  355. };
  356. extern int stop_a_enabled;
  357. void sun_do_break(void)
  358. {
  359. if (!stop_a_enabled)
  360. return;
  361. prom_printf("\n");
  362. flush_user_windows();
  363. prom_cmdline();
  364. }
  365. int stop_a_enabled = 1;