root/arch/sparc/kernel/setup_32.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. prom_sync_me
  2. prom_console_write
  3. process_switch
  4. boot_flags_init
  5. per_cpu_patch
  6. leon_patch
  7. sparc32_start_kernel
  8. setup_arch
  9. sun_do_break
  10. topology_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  *  linux/arch/sparc/kernel/setup.c
   4  *
   5  *  Copyright (C) 1995  David S. Miller (davem@caip.rutgers.edu)
   6  *  Copyright (C) 2000  Anton Blanchard (anton@samba.org)
   7  */
   8 
   9 #include <linux/errno.h>
  10 #include <linux/sched.h>
  11 #include <linux/kernel.h>
  12 #include <linux/mm.h>
  13 #include <linux/stddef.h>
  14 #include <linux/unistd.h>
  15 #include <linux/ptrace.h>
  16 #include <linux/slab.h>
  17 #include <linux/initrd.h>
  18 #include <asm/smp.h>
  19 #include <linux/user.h>
  20 #include <linux/screen_info.h>
  21 #include <linux/delay.h>
  22 #include <linux/fs.h>
  23 #include <linux/seq_file.h>
  24 #include <linux/syscalls.h>
  25 #include <linux/kdev_t.h>
  26 #include <linux/major.h>
  27 #include <linux/string.h>
  28 #include <linux/init.h>
  29 #include <linux/interrupt.h>
  30 #include <linux/console.h>
  31 #include <linux/spinlock.h>
  32 #include <linux/root_dev.h>
  33 #include <linux/cpu.h>
  34 #include <linux/kdebug.h>
  35 #include <linux/export.h>
  36 #include <linux/start_kernel.h>
  37 #include <uapi/linux/mount.h>
  38 
  39 #include <asm/io.h>
  40 #include <asm/processor.h>
  41 #include <asm/oplib.h>
  42 #include <asm/page.h>
  43 #include <asm/pgtable.h>
  44 #include <asm/traps.h>
  45 #include <asm/vaddrs.h>
  46 #include <asm/mbus.h>
  47 #include <asm/idprom.h>
  48 #include <asm/cpudata.h>
  49 #include <asm/setup.h>
  50 #include <asm/cacheflush.h>
  51 #include <asm/sections.h>
  52 
  53 #include "kernel.h"
  54 
  55 struct screen_info screen_info = {
  56         0, 0,                   /* orig-x, orig-y */
  57         0,                      /* unused */
  58         0,                      /* orig-video-page */
  59         0,                      /* orig-video-mode */
  60         128,                    /* orig-video-cols */
  61         0,0,0,                  /* ega_ax, ega_bx, ega_cx */
  62         54,                     /* orig-video-lines */
  63         0,                      /* orig-video-isVGA */
  64         16                      /* orig-video-points */
  65 };
  66 
  67 /* Typing sync at the prom prompt calls the function pointed to by
  68  * romvec->pv_synchook which I set to the following function.
  69  * This should sync all filesystems and return, for now it just
  70  * prints out pretty messages and returns.
  71  */
  72 
  73 /* Pretty sick eh? */
  74 static void prom_sync_me(void)
  75 {
  76         unsigned long prom_tbr, flags;
  77 
  78         /* XXX Badly broken. FIX! - Anton */
  79         local_irq_save(flags);
  80         __asm__ __volatile__("rd %%tbr, %0\n\t" : "=r" (prom_tbr));
  81         __asm__ __volatile__("wr %0, 0x0, %%tbr\n\t"
  82                              "nop\n\t"
  83                              "nop\n\t"
  84                              "nop\n\t" : : "r" (&trapbase));
  85 
  86         prom_printf("PROM SYNC COMMAND...\n");
  87         show_free_areas(0, NULL);
  88         if (!is_idle_task(current)) {
  89                 local_irq_enable();
  90                 ksys_sync();
  91                 local_irq_disable();
  92         }
  93         prom_printf("Returning to prom\n");
  94 
  95         __asm__ __volatile__("wr %0, 0x0, %%tbr\n\t"
  96                              "nop\n\t"
  97                              "nop\n\t"
  98                              "nop\n\t" : : "r" (prom_tbr));
  99         local_irq_restore(flags);
 100 }
 101 
 102 static unsigned int boot_flags __initdata = 0;
 103 #define BOOTME_DEBUG  0x1
 104 
 105 /* Exported for mm/init.c:paging_init. */
 106 unsigned long cmdline_memory_size __initdata = 0;
 107 
 108 /* which CPU booted us (0xff = not set) */
 109 unsigned char boot_cpu_id = 0xff; /* 0xff will make it into DATA section... */
 110 
 111 static void
 112 prom_console_write(struct console *con, const char *s, unsigned int n)
 113 {
 114         prom_write(s, n);
 115 }
 116 
 117 static struct console prom_early_console = {
 118         .name =         "earlyprom",
 119         .write =        prom_console_write,
 120         .flags =        CON_PRINTBUFFER | CON_BOOT,
 121         .index =        -1,
 122 };
 123 
 124 /* 
 125  * Process kernel command line switches that are specific to the
 126  * SPARC or that require special low-level processing.
 127  */
 128 static void __init process_switch(char c)
 129 {
 130         switch (c) {
 131         case 'd':
 132                 boot_flags |= BOOTME_DEBUG;
 133                 break;
 134         case 's':
 135                 break;
 136         case 'h':
 137                 prom_printf("boot_flags_init: Halt!\n");
 138                 prom_halt();
 139                 break;
 140         case 'p':
 141                 prom_early_console.flags &= ~CON_BOOT;
 142                 break;
 143         default:
 144                 printk("Unknown boot switch (-%c)\n", c);
 145                 break;
 146         }
 147 }
 148 
 149 static void __init boot_flags_init(char *commands)
 150 {
 151         while (*commands) {
 152                 /* Move to the start of the next "argument". */
 153                 while (*commands == ' ')
 154                         commands++;
 155 
 156                 /* Process any command switches, otherwise skip it. */
 157                 if (*commands == '\0')
 158                         break;
 159                 if (*commands == '-') {
 160                         commands++;
 161                         while (*commands && *commands != ' ')
 162                                 process_switch(*commands++);
 163                         continue;
 164                 }
 165                 if (!strncmp(commands, "mem=", 4)) {
 166                         /*
 167                          * "mem=XXX[kKmM] overrides the PROM-reported
 168                          * memory size.
 169                          */
 170                         cmdline_memory_size = simple_strtoul(commands + 4,
 171                                                      &commands, 0);
 172                         if (*commands == 'K' || *commands == 'k') {
 173                                 cmdline_memory_size <<= 10;
 174                                 commands++;
 175                         } else if (*commands=='M' || *commands=='m') {
 176                                 cmdline_memory_size <<= 20;
 177                                 commands++;
 178                         }
 179                 }
 180                 while (*commands && *commands != ' ')
 181                         commands++;
 182         }
 183 }
 184 
 185 extern unsigned short root_flags;
 186 extern unsigned short root_dev;
 187 extern unsigned short ram_flags;
 188 #define RAMDISK_IMAGE_START_MASK        0x07FF
 189 #define RAMDISK_PROMPT_FLAG             0x8000
 190 #define RAMDISK_LOAD_FLAG               0x4000
 191 
 192 extern int root_mountflags;
 193 
 194 char reboot_command[COMMAND_LINE_SIZE];
 195 
 196 struct cpuid_patch_entry {
 197         unsigned int    addr;
 198         unsigned int    sun4d[3];
 199         unsigned int    leon[3];
 200 };
 201 extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
 202 
 203 static void __init per_cpu_patch(void)
 204 {
 205         struct cpuid_patch_entry *p;
 206 
 207         if (sparc_cpu_model == sun4m) {
 208                 /* Nothing to do, this is what the unpatched code
 209                  * targets.
 210                  */
 211                 return;
 212         }
 213 
 214         p = &__cpuid_patch;
 215         while (p < &__cpuid_patch_end) {
 216                 unsigned long addr = p->addr;
 217                 unsigned int *insns;
 218 
 219                 switch (sparc_cpu_model) {
 220                 case sun4d:
 221                         insns = &p->sun4d[0];
 222                         break;
 223 
 224                 case sparc_leon:
 225                         insns = &p->leon[0];
 226                         break;
 227                 default:
 228                         prom_printf("Unknown cpu type, halting.\n");
 229                         prom_halt();
 230                 }
 231                 *(unsigned int *) (addr + 0) = insns[0];
 232                 flushi(addr + 0);
 233                 *(unsigned int *) (addr + 4) = insns[1];
 234                 flushi(addr + 4);
 235                 *(unsigned int *) (addr + 8) = insns[2];
 236                 flushi(addr + 8);
 237 
 238                 p++;
 239         }
 240 }
 241 
 242 struct leon_1insn_patch_entry {
 243         unsigned int addr;
 244         unsigned int insn;
 245 };
 246 
 247 enum sparc_cpu sparc_cpu_model;
 248 EXPORT_SYMBOL(sparc_cpu_model);
 249 
 250 static __init void leon_patch(void)
 251 {
 252         struct leon_1insn_patch_entry *start = (void *)__leon_1insn_patch;
 253         struct leon_1insn_patch_entry *end = (void *)__leon_1insn_patch_end;
 254 
 255         /* Default instruction is leon - no patching */
 256         if (sparc_cpu_model == sparc_leon)
 257                 return;
 258 
 259         while (start < end) {
 260                 unsigned long addr = start->addr;
 261 
 262                 *(unsigned int *)(addr) = start->insn;
 263                 flushi(addr);
 264 
 265                 start++;
 266         }
 267 }
 268 
 269 struct tt_entry *sparc_ttable;
 270 static struct pt_regs fake_swapper_regs;
 271 
 272 /* Called from head_32.S - before we have setup anything
 273  * in the kernel. Be very careful with what you do here.
 274  */
 275 void __init sparc32_start_kernel(struct linux_romvec *rp)
 276 {
 277         prom_init(rp);
 278 
 279         /* Set sparc_cpu_model */
 280         sparc_cpu_model = sun_unknown;
 281         if (!strcmp(&cputypval[0], "sun4m"))
 282                 sparc_cpu_model = sun4m;
 283         if (!strcmp(&cputypval[0], "sun4s"))
 284                 sparc_cpu_model = sun4m; /* CP-1200 with PROM 2.30 -E */
 285         if (!strcmp(&cputypval[0], "sun4d"))
 286                 sparc_cpu_model = sun4d;
 287         if (!strcmp(&cputypval[0], "sun4e"))
 288                 sparc_cpu_model = sun4e;
 289         if (!strcmp(&cputypval[0], "sun4u"))
 290                 sparc_cpu_model = sun4u;
 291         if (!strncmp(&cputypval[0], "leon" , 4))
 292                 sparc_cpu_model = sparc_leon;
 293 
 294         leon_patch();
 295         start_kernel();
 296 }
 297 
 298 void __init setup_arch(char **cmdline_p)
 299 {
 300         int i;
 301         unsigned long highest_paddr;
 302 
 303         sparc_ttable = &trapbase;
 304 
 305         /* Initialize PROM console and command line. */
 306         *cmdline_p = prom_getbootargs();
 307         strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE);
 308         parse_early_param();
 309 
 310         boot_flags_init(*cmdline_p);
 311 
 312         register_console(&prom_early_console);
 313 
 314         switch(sparc_cpu_model) {
 315         case sun4m:
 316                 pr_info("ARCH: SUN4M\n");
 317                 break;
 318         case sun4d:
 319                 pr_info("ARCH: SUN4D\n");
 320                 break;
 321         case sun4e:
 322                 pr_info("ARCH: SUN4E\n");
 323                 break;
 324         case sun4u:
 325                 pr_info("ARCH: SUN4U\n");
 326                 break;
 327         case sparc_leon:
 328                 pr_info("ARCH: LEON\n");
 329                 break;
 330         default:
 331                 pr_info("ARCH: UNKNOWN!\n");
 332                 break;
 333         }
 334 
 335 #ifdef CONFIG_DUMMY_CONSOLE
 336         conswitchp = &dummy_con;
 337 #endif
 338 
 339         idprom_init();
 340         load_mmu();
 341 
 342         phys_base = 0xffffffffUL;
 343         highest_paddr = 0UL;
 344         for (i = 0; sp_banks[i].num_bytes != 0; i++) {
 345                 unsigned long top;
 346 
 347                 if (sp_banks[i].base_addr < phys_base)
 348                         phys_base = sp_banks[i].base_addr;
 349                 top = sp_banks[i].base_addr +
 350                         sp_banks[i].num_bytes;
 351                 if (highest_paddr < top)
 352                         highest_paddr = top;
 353         }
 354         pfn_base = phys_base >> PAGE_SHIFT;
 355 
 356         if (!root_flags)
 357                 root_mountflags &= ~MS_RDONLY;
 358         ROOT_DEV = old_decode_dev(root_dev);
 359 #ifdef CONFIG_BLK_DEV_RAM
 360         rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
 361         rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
 362         rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);     
 363 #endif
 364 
 365         prom_setsync(prom_sync_me);
 366 
 367         if((boot_flags & BOOTME_DEBUG) && (linux_dbvec != NULL) &&
 368            ((*(short *)linux_dbvec) != -1)) {
 369                 printk("Booted under KADB. Syncing trap table.\n");
 370                 (*(linux_dbvec->teach_debugger))();
 371         }
 372 
 373         init_task.thread.kregs = &fake_swapper_regs;
 374 
 375         /* Run-time patch instructions to match the cpu model */
 376         per_cpu_patch();
 377 
 378         paging_init();
 379 
 380         smp_setup_cpu_possible_map();
 381 }
 382 
 383 extern int stop_a_enabled;
 384 
 385 void sun_do_break(void)
 386 {
 387         if (!stop_a_enabled)
 388                 return;
 389 
 390         printk("\n");
 391         flush_user_windows();
 392 
 393         prom_cmdline();
 394 }
 395 EXPORT_SYMBOL(sun_do_break);
 396 
 397 int stop_a_enabled = 1;
 398 
 399 static int __init topology_init(void)
 400 {
 401         int i, ncpus, err;
 402 
 403         /* Count the number of physically present processors in
 404          * the machine, even on uniprocessor, so that /proc/cpuinfo
 405          * output is consistent with 2.4.x
 406          */
 407         ncpus = 0;
 408         while (!cpu_find_by_instance(ncpus, NULL, NULL))
 409                 ncpus++;
 410         ncpus_probed = ncpus;
 411 
 412         err = 0;
 413         for_each_online_cpu(i) {
 414                 struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
 415                 if (!p)
 416                         err = -ENOMEM;
 417                 else
 418                         register_cpu(p, i);
 419         }
 420 
 421         return err;
 422 }
 423 
 424 subsys_initcall(topology_init);

/* [<][>][^][v][top][bottom][index][help] */