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