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 <linux/slab.h> 16 #include <asm/smp.h> 17 #include <linux/user.h> 18 #include <linux/screen_info.h> 19 #include <linux/delay.h> 20 #include <linux/fs.h> 21 #include <linux/seq_file.h> 22 #include <linux/syscalls.h> 23 #include <linux/kdev_t.h> 24 #include <linux/major.h> 25 #include <linux/string.h> 26 #include <linux/init.h> 27 #include <linux/inet.h> 28 #include <linux/console.h> 29 #include <linux/root_dev.h> 30 #include <linux/interrupt.h> 31 #include <linux/cpu.h> 32 #include <linux/initrd.h> 33 34 #include <asm/system.h> 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 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 register_console(&prom_early_console); 290 291 if (tlb_type == hypervisor) 292 printk("ARCH: SUN4V\n"); 293 else 294 printk("ARCH: SUN4U\n"); 295 296 #ifdef CONFIG_DUMMY_CONSOLE 297 conswitchp = &dummy_con; 298 #elif defined(CONFIG_PROM_CONSOLE) 299 conswitchp = &prom_con; 300 #endif 301 302 idprom_init(); 303 304 if (!root_flags) 305 root_mountflags &= ~MS_RDONLY; 306 ROOT_DEV = old_decode_dev(root_dev); 307 #ifdef CONFIG_BLK_DEV_RAM 308 rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK; 309 rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0); 310 rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0); 311 #endif 312 313 task_thread_info(&init_task)->kregs = &fake_swapper_regs; 314 315 #ifdef CONFIG_IP_PNP 316 if (!ic_set_manually) { 317 int chosen = prom_finddevice ("/chosen"); 318 u32 cl, sv, gw; 319 320 cl = prom_getintdefault (chosen, "client-ip", 0); 321 sv = prom_getintdefault (chosen, "server-ip", 0); 322 gw = prom_getintdefault (chosen, "gateway-ip", 0); 323 if (cl && sv) { 324 ic_myaddr = cl; 325 ic_servaddr = sv; 326 if (gw) 327 ic_gateway = gw; 328 #if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP) 329 ic_proto_enabled = 0; 330 #endif 331 } 332 } 333 #endif 334 335 /* Get boot processor trap_block[] setup. */ 336 init_cur_cpu_trap(current_thread_info()); 337 338 paging_init(); 339 } 340 341 /* BUFFER is PAGE_SIZE bytes long. */ 342 343 extern void smp_info(struct seq_file *); 344 extern void smp_bogo(struct seq_file *); 345 extern void mmu_info(struct seq_file *); 346 347 unsigned int dcache_parity_tl1_occurred; 348 unsigned int icache_parity_tl1_occurred; 349 350 int ncpus_probed; 351 352 static int show_cpuinfo(struct seq_file *m, void *__unused) 353 { 354 seq_printf(m, 355 "cpu\t\t: %s\n" 356 "fpu\t\t: %s\n" 357 "pmu\t\t: %s\n" 358 "prom\t\t: %s\n" 359 "type\t\t: %s\n" 360 "ncpus probed\t: %d\n" 361 "ncpus active\t: %d\n" 362 "D$ parity tl1\t: %u\n" 363 "I$ parity tl1\t: %u\n" 364 #ifndef CONFIG_SMP 365 "Cpu0ClkTck\t: %016lx\n" 366 #endif 367 , 368 sparc_cpu_type, 369 sparc_fpu_type, 370 sparc_pmu_type, 371 prom_version, 372 ((tlb_type == hypervisor) ? 373 "sun4v" : 374 "sun4u"), 375 ncpus_probed, 376 num_online_cpus(), 377 dcache_parity_tl1_occurred, 378 icache_parity_tl1_occurred 379 #ifndef CONFIG_SMP 380 , cpu_data(0).clock_tick 381 #endif 382 ); 383 #ifdef CONFIG_SMP 384 smp_bogo(m); 385 #endif 386 mmu_info(m); 387 #ifdef CONFIG_SMP 388 smp_info(m); 389 #endif 390 return 0; 391 } 392 393 static void *c_start(struct seq_file *m, loff_t *pos) 394 { 395 /* The pointer we are returning is arbitrary, 396 * it just has to be non-NULL and not IS_ERR 397 * in the success case. 398 */ 399 return *pos == 0 ? &c_start : NULL; 400 } 401 402 static void *c_next(struct seq_file *m, void *v, loff_t *pos) 403 { 404 ++*pos; 405 return c_start(m, pos); 406 } 407 408 static void c_stop(struct seq_file *m, void *v) 409 { 410 } 411 412 const struct seq_operations cpuinfo_op = { 413 .start =c_start, 414 .next = c_next, 415 .stop = c_stop, 416 .show = show_cpuinfo, 417 }; 418 419 extern int stop_a_enabled; 420 421 void sun_do_break(void) 422 { 423 if (!stop_a_enabled) 424 return; 425 426 prom_printf("\n"); 427 flush_user_windows(); 428 429 prom_cmdline(); 430 } 431 EXPORT_SYMBOL(sun_do_break); 432 433 int stop_a_enabled = 1; 434 EXPORT_SYMBOL(stop_a_enabled); 435