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 extern int stop_a_enabled; 343 344 void sun_do_break(void) 345 { 346 if (!stop_a_enabled) 347 return; 348 349 prom_printf("\n"); 350 flush_user_windows(); 351 352 prom_cmdline(); 353 } 354 EXPORT_SYMBOL(sun_do_break); 355 356 int stop_a_enabled = 1; 357 EXPORT_SYMBOL(stop_a_enabled); 358