0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/errno.h>
0010 #include <linux/sched.h>
0011 #include <linux/kernel.h>
0012 #include <linux/mm.h>
0013 #include <linux/stddef.h>
0014 #include <linux/unistd.h>
0015 #include <linux/ptrace.h>
0016 #include <linux/slab.h>
0017 #include <linux/initrd.h>
0018 #include <asm/smp.h>
0019 #include <linux/user.h>
0020 #include <linux/screen_info.h>
0021 #include <linux/delay.h>
0022 #include <linux/fs.h>
0023 #include <linux/seq_file.h>
0024 #include <linux/syscalls.h>
0025 #include <linux/kdev_t.h>
0026 #include <linux/major.h>
0027 #include <linux/string.h>
0028 #include <linux/init.h>
0029 #include <linux/interrupt.h>
0030 #include <linux/console.h>
0031 #include <linux/spinlock.h>
0032 #include <linux/root_dev.h>
0033 #include <linux/cpu.h>
0034 #include <linux/kdebug.h>
0035 #include <linux/export.h>
0036 #include <linux/start_kernel.h>
0037 #include <uapi/linux/mount.h>
0038
0039 #include <asm/io.h>
0040 #include <asm/processor.h>
0041 #include <asm/oplib.h>
0042 #include <asm/page.h>
0043 #include <asm/traps.h>
0044 #include <asm/vaddrs.h>
0045 #include <asm/mbus.h>
0046 #include <asm/idprom.h>
0047 #include <asm/cpudata.h>
0048 #include <asm/setup.h>
0049 #include <asm/cacheflush.h>
0050 #include <asm/sections.h>
0051
0052 #include "kernel.h"
0053
0054 struct screen_info screen_info = {
0055 0, 0,
0056 0,
0057 0,
0058 0,
0059 128,
0060 0,0,0,
0061 54,
0062 0,
0063 16
0064 };
0065
0066
0067
0068
0069
0070
0071
0072
0073 static void prom_sync_me(void)
0074 {
0075 unsigned long prom_tbr, flags;
0076
0077
0078 local_irq_save(flags);
0079 __asm__ __volatile__("rd %%tbr, %0\n\t" : "=r" (prom_tbr));
0080 __asm__ __volatile__("wr %0, 0x0, %%tbr\n\t"
0081 "nop\n\t"
0082 "nop\n\t"
0083 "nop\n\t" : : "r" (&trapbase));
0084
0085 prom_printf("PROM SYNC COMMAND...\n");
0086 show_free_areas(0, NULL);
0087 if (!is_idle_task(current)) {
0088 local_irq_enable();
0089 ksys_sync();
0090 local_irq_disable();
0091 }
0092 prom_printf("Returning to prom\n");
0093
0094 __asm__ __volatile__("wr %0, 0x0, %%tbr\n\t"
0095 "nop\n\t"
0096 "nop\n\t"
0097 "nop\n\t" : : "r" (prom_tbr));
0098 local_irq_restore(flags);
0099 }
0100
0101 static unsigned int boot_flags __initdata = 0;
0102 #define BOOTME_DEBUG 0x1
0103
0104
0105 unsigned long cmdline_memory_size __initdata = 0;
0106
0107
0108 unsigned char boot_cpu_id = 0xff;
0109
0110 static void
0111 prom_console_write(struct console *con, const char *s, unsigned int n)
0112 {
0113 prom_write(s, n);
0114 }
0115
0116 static struct console prom_early_console = {
0117 .name = "earlyprom",
0118 .write = prom_console_write,
0119 .flags = CON_PRINTBUFFER | CON_BOOT,
0120 .index = -1,
0121 };
0122
0123
0124
0125
0126
0127 static void __init process_switch(char c)
0128 {
0129 switch (c) {
0130 case 'd':
0131 boot_flags |= BOOTME_DEBUG;
0132 break;
0133 case 's':
0134 break;
0135 case 'h':
0136 prom_printf("boot_flags_init: Halt!\n");
0137 prom_halt();
0138 break;
0139 case 'p':
0140 prom_early_console.flags &= ~CON_BOOT;
0141 break;
0142 default:
0143 printk("Unknown boot switch (-%c)\n", c);
0144 break;
0145 }
0146 }
0147
0148 static void __init boot_flags_init(char *commands)
0149 {
0150 while (*commands) {
0151
0152 while (*commands == ' ')
0153 commands++;
0154
0155
0156 if (*commands == '\0')
0157 break;
0158 if (*commands == '-') {
0159 commands++;
0160 while (*commands && *commands != ' ')
0161 process_switch(*commands++);
0162 continue;
0163 }
0164 if (!strncmp(commands, "mem=", 4)) {
0165
0166
0167
0168
0169 cmdline_memory_size = simple_strtoul(commands + 4,
0170 &commands, 0);
0171 if (*commands == 'K' || *commands == 'k') {
0172 cmdline_memory_size <<= 10;
0173 commands++;
0174 } else if (*commands=='M' || *commands=='m') {
0175 cmdline_memory_size <<= 20;
0176 commands++;
0177 }
0178 }
0179 while (*commands && *commands != ' ')
0180 commands++;
0181 }
0182 }
0183
0184 extern unsigned short root_flags;
0185 extern unsigned short root_dev;
0186 extern unsigned short ram_flags;
0187 #define RAMDISK_IMAGE_START_MASK 0x07FF
0188 #define RAMDISK_PROMPT_FLAG 0x8000
0189 #define RAMDISK_LOAD_FLAG 0x4000
0190
0191 extern int root_mountflags;
0192
0193 char reboot_command[COMMAND_LINE_SIZE];
0194
0195 struct cpuid_patch_entry {
0196 unsigned int addr;
0197 unsigned int sun4d[3];
0198 unsigned int leon[3];
0199 };
0200 extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
0201
0202 static void __init per_cpu_patch(void)
0203 {
0204 struct cpuid_patch_entry *p;
0205
0206 if (sparc_cpu_model == sun4m) {
0207
0208
0209
0210 return;
0211 }
0212
0213 p = &__cpuid_patch;
0214 while (p < &__cpuid_patch_end) {
0215 unsigned long addr = p->addr;
0216 unsigned int *insns;
0217
0218 switch (sparc_cpu_model) {
0219 case sun4d:
0220 insns = &p->sun4d[0];
0221 break;
0222
0223 case sparc_leon:
0224 insns = &p->leon[0];
0225 break;
0226 default:
0227 prom_printf("Unknown cpu type, halting.\n");
0228 prom_halt();
0229 }
0230 *(unsigned int *) (addr + 0) = insns[0];
0231 flushi(addr + 0);
0232 *(unsigned int *) (addr + 4) = insns[1];
0233 flushi(addr + 4);
0234 *(unsigned int *) (addr + 8) = insns[2];
0235 flushi(addr + 8);
0236
0237 p++;
0238 }
0239 }
0240
0241 struct leon_1insn_patch_entry {
0242 unsigned int addr;
0243 unsigned int insn;
0244 };
0245
0246 enum sparc_cpu sparc_cpu_model;
0247 EXPORT_SYMBOL(sparc_cpu_model);
0248
0249 static __init void leon_patch(void)
0250 {
0251 struct leon_1insn_patch_entry *start = (void *)__leon_1insn_patch;
0252 struct leon_1insn_patch_entry *end = (void *)__leon_1insn_patch_end;
0253
0254
0255 if (sparc_cpu_model == sparc_leon)
0256 return;
0257
0258 while (start < end) {
0259 unsigned long addr = start->addr;
0260
0261 *(unsigned int *)(addr) = start->insn;
0262 flushi(addr);
0263
0264 start++;
0265 }
0266 }
0267
0268 struct tt_entry *sparc_ttable;
0269
0270
0271
0272
0273 void __init sparc32_start_kernel(struct linux_romvec *rp)
0274 {
0275 prom_init(rp);
0276
0277
0278 sparc_cpu_model = sun_unknown;
0279 if (!strcmp(&cputypval[0], "sun4m"))
0280 sparc_cpu_model = sun4m;
0281 if (!strcmp(&cputypval[0], "sun4s"))
0282 sparc_cpu_model = sun4m;
0283 if (!strcmp(&cputypval[0], "sun4d"))
0284 sparc_cpu_model = sun4d;
0285 if (!strcmp(&cputypval[0], "sun4e"))
0286 sparc_cpu_model = sun4e;
0287 if (!strcmp(&cputypval[0], "sun4u"))
0288 sparc_cpu_model = sun4u;
0289 if (!strncmp(&cputypval[0], "leon" , 4))
0290 sparc_cpu_model = sparc_leon;
0291
0292 leon_patch();
0293 start_kernel();
0294 }
0295
0296 void __init setup_arch(char **cmdline_p)
0297 {
0298 int i;
0299 unsigned long highest_paddr;
0300
0301 sparc_ttable = &trapbase;
0302
0303
0304 *cmdline_p = prom_getbootargs();
0305 strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE);
0306 parse_early_param();
0307
0308 boot_flags_init(*cmdline_p);
0309
0310 register_console(&prom_early_console);
0311
0312 switch(sparc_cpu_model) {
0313 case sun4m:
0314 pr_info("ARCH: SUN4M\n");
0315 break;
0316 case sun4d:
0317 pr_info("ARCH: SUN4D\n");
0318 break;
0319 case sun4e:
0320 pr_info("ARCH: SUN4E\n");
0321 break;
0322 case sun4u:
0323 pr_info("ARCH: SUN4U\n");
0324 break;
0325 case sparc_leon:
0326 pr_info("ARCH: LEON\n");
0327 break;
0328 default:
0329 pr_info("ARCH: UNKNOWN!\n");
0330 break;
0331 }
0332
0333 idprom_init();
0334 load_mmu();
0335
0336 phys_base = 0xffffffffUL;
0337 highest_paddr = 0UL;
0338 for (i = 0; sp_banks[i].num_bytes != 0; i++) {
0339 unsigned long top;
0340
0341 if (sp_banks[i].base_addr < phys_base)
0342 phys_base = sp_banks[i].base_addr;
0343 top = sp_banks[i].base_addr +
0344 sp_banks[i].num_bytes;
0345 if (highest_paddr < top)
0346 highest_paddr = top;
0347 }
0348 pfn_base = phys_base >> PAGE_SHIFT;
0349
0350 if (!root_flags)
0351 root_mountflags &= ~MS_RDONLY;
0352 ROOT_DEV = old_decode_dev(root_dev);
0353 #ifdef CONFIG_BLK_DEV_RAM
0354 rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
0355 #endif
0356
0357 prom_setsync(prom_sync_me);
0358
0359 if((boot_flags & BOOTME_DEBUG) && (linux_dbvec != NULL) &&
0360 ((*(short *)linux_dbvec) != -1)) {
0361 printk("Booted under KADB. Syncing trap table.\n");
0362 (*(linux_dbvec->teach_debugger))();
0363 }
0364
0365
0366 per_cpu_patch();
0367
0368 paging_init();
0369
0370 smp_setup_cpu_possible_map();
0371 }
0372
0373 extern int stop_a_enabled;
0374
0375 void sun_do_break(void)
0376 {
0377 if (!stop_a_enabled)
0378 return;
0379
0380 printk("\n");
0381 flush_user_windows();
0382
0383 prom_cmdline();
0384 }
0385 EXPORT_SYMBOL(sun_do_break);
0386
0387 int stop_a_enabled = 1;
0388
0389 static int __init topology_init(void)
0390 {
0391 int i, ncpus, err;
0392
0393
0394
0395
0396
0397 ncpus = 0;
0398 while (!cpu_find_by_instance(ncpus, NULL, NULL))
0399 ncpus++;
0400 ncpus_probed = ncpus;
0401
0402 err = 0;
0403 for_each_online_cpu(i) {
0404 struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
0405 if (!p)
0406 err = -ENOMEM;
0407 else
0408 register_cpu(p, i);
0409 }
0410
0411 return err;
0412 }
0413
0414 subsys_initcall(topology_init);