root/arch/sparc/kernel/head.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 /* boot.S: The initial boot code for the Sparc port of Linux.
   2 
   3    Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
   4 
   5            This file has to serve three purposes.
   6 
   7            1) determine the prom-version and cpu/architecture
   8            2) print enough useful info before we start to execute
   9               c-code that I can possibly begin to debug things
  10            3) Hold the vector of trap entry points
  11 
  12    The Sparc offers many challenges to kernel design. Here I will
  13    document those I have come across thus far. Upon bootup the boot
  14    prom loads your a.out image into memory. This memory the prom has
  15    already mapped for you in two places, however as far as I can tell
  16    the virtual address cache is not turned on although the MMU is
  17    translating things. You get loaded at 0x4000 exactly and you are
  18    aliased to 0xf8004000 with the appropriate mmu entries. So, when
  19    you link a boot-loadable object you want to do something like:
  20 
  21         ld -e start -Ttext 4000 -o mykernel myobj1.o myobj2.o ....
  22 
  23    to produce a proper image.
  24 
  25    At boot time you are given (as far as I can tell at this time)
  26    one key to figure out what machine you are one and what devices
  27    are available. The prom when it loads you leaves a pointer to
  28    the 'rom vector' in register %o0 right before it jumps to your
  29    starting address. This is a pointer to a struct that is full of
  30    pointer to functions (ie. printf, halt, reboot), pointers to
  31    linked lists (ie. memory mappings), and pointer to empirical
  32    constants (ie. stdin and stdout magic cookies + rom version).
  33    Starting with this piece of information you can figure out 
  34    just about anything you want about the machine you are on.
  35 
  36    Although I don't use it now, if you are on a Multiprocessor and
  37    therefore a v3 or above prom, register %o2 at boot contains a
  38    function pointer you must call before you proceed to invoke the
  39    other cpu's on the machine. I have no idea what kind of magic this
  40    is, give me time.
  41 */
  42 
  43 #include <asm/head.h>
  44 #include <asm/version.h>
  45 #include <asm/asi.h>
  46 #include <asm/contregs.h>
  47 #include <asm/psr.h>
  48 #include <asm/page.h>
  49 
  50         .data
  51 
  52 /* First thing to go in the data segment is the interrupt stack. */
  53 
  54         .globl  _intstack
  55         .globl  _eintstack
  56 _intstack:
  57         .skip   4 * PAGE_SIZE                ! 16k = 128 128-byte stack frames
  58 _eintstack:
  59 
  60 
  61 
  62 /* 
  63    The following are used with the prom_vector node-ops to figure out
  64    the cpu-type 
  65 */
  66 
  67         .globl  _cputyp
  68 
  69 _cputyp:
  70         .word   1
  71 
  72 _cputypval:
  73         .asciz "sun4c"
  74         .ascii "     "
  75 
  76         .align 4
  77 /*
  78  * Sun people can't spell worth damn. "compatability" indeed.
  79  * At least we *know* we can't spell, and use a spell-checker.
  80  */
  81 
  82 /* Uh, actually Linus it is I who cannot spell. Too much murky
  83  * Sparc assembly will do this to ya.
  84  */
  85 _cputypvar:
  86         .asciz "compatability"
  87 
  88 _cputypvallen = _cputypvar - _cputypval
  89 
  90 /* This hold the prom-interface-version number for either v0 or v2. */
  91 
  92         .align 4
  93         .globl  _prom_iface_vers
  94 
  95 _prom_iface_vers:       .skip 4
  96 
  97 /* WARNING: evil messages follow */
  98 
  99         .align 4
 100 
 101 sun4_notsup:
 102         .asciz  "Sparc-Linux: sun4 support not implemented yet\n\n"
 103         .align 4
 104 
 105 sun4m_notsup:
 106         .asciz  "Sparc-Linux: sun4m support does not exist\n\n"
 107         .align 4
 108 
 109 sun4d_notsup:
 110         .asciz  "Sparc-Linux: sun4d support does not exist\n\n"
 111         .align 4
 112 
 113 you_lose:
 114         .asciz  "You lose..... Thanks for playing...\n"
 115         .align 4
 116 
 117 
 118         .globl boot_msg
 119 
 120 /* memory descriptor property strings, v2 = yuk yuk yuk  */
 121 /* XXX how to figure out vm mapped by prom? May have to scan magic addresses */
 122 
 123 mem_prop_physavail:     .asciz "available"
 124         
 125                         .align 4
 126 mem_prop_phystot:       .asciz "reg"
 127 
 128 /* v2_memory descriptor struct kludged here for assembly, if it ain't broke */
 129 
 130                 .align 4
 131 v2_mem_struct:  .skip 0xff
 132 
 133                         .align 4
 134 v2_printf_physavail:    .asciz "Physical Memory Available: 0x%x bytes"
 135         
 136                         .align 4
 137 v2_printf_phystot:      .asciz "Physical Memory: 0x%x bytes"
 138 
 139 /* A place to store property strings returned from the prom 'node' funcs */
 140 
 141                         .align 4
 142 prop_string_buf:        .skip 32
 143 
 144                 .align 4
 145 prop_name:      .asciz "name"
 146         
 147                 .align 4
 148 current_node:   .skip 4
 149 
 150 
 151 /* nice little boot message */
 152 
 153                 .align 4
 154 boot_msg:       
 155         .ascii "Booting Sparc-Linux V0.00PRE-ALPHA "
 156         .ascii WHO_COMPILED_ME 
 157         .asciz " \n"
 158         .align 4
 159 
 160         .globl boot_msg2
 161 
 162 boot_msg2:
 163         .asciz "Booting Sparclinux V0.00 PRE-ALPHA on a (SUN4C)\n\n"
 164 
 165         .align 4
 166 
 167 pstring1:
 168         .asciz "Prom Magic Cookie: 0x%x  "
 169         .align 4
 170 
 171 pstring2:
 172         .asciz "Interface Version: v%d\n"
 173         .align 4
 174 
 175 pstring3:
 176         .asciz "Prom Revision: V%d\n\n"
 177         .align 4
 178 
 179 pstring4:
 180         .ascii "Total Physical Memory: %d bytes\nVM mapped by Prom: %d bytes\n"
 181         .asciz "Available Physical Memory: %d bytes\n"
 182         .align 4
 183 
 184 
 185 newline:
 186         .asciz "\n"
 187         .align 4
 188 
 189         .text
 190 
 191         .globl  _msgbuf
 192 msgbufsize = PAGE_SIZE                       ! 1 page for msg buffer
 193 _msgbuf =  PAGE_SIZE
 194 
 195 
 196 IE_reg_addr = _msgbuf + msgbufsize      ! this page not used; points to IEreg
 197 
 198         
 199 /* Ok, things start to get interesting. We get linked such that 'start'
 200    is the entry symbol. However, it is real low in kernel address space
 201    and as such a nifty place to place the trap table. We achieve this goal
 202    by just jumping to 'gokernel' for the first trap's entry as the sparc
 203    never receives the zero trap as it is real special (hw reset).
 204 
 205    Each trap entry point is the size of 4 sparc instructions (or 4 bytes
 206    * 4 insns = 16 bytes). There are 128 hardware traps (some undefined
 207    or unimplemented) and 128 software traps (sys-calls, etc.).
 208 
 209    One of the instructions must be a branch. More often than not this
 210    will be to a trap handler entry point because it is completely
 211    impossible to handle any trap in 4 insns. I welcome anyone to 
 212    challenge this theory. :-)
 213 
 214    On entry into this table the hardware has loaded the program counter
 215    at which the trap occurred into register %l1 and the next program
 216    counter into %l2, this way we can return from the trap with a simple
 217 
 218            jmp %l1; rett %l2  ! poof...
 219 
 220    after properly servicing the trap. It wouldn't be a bad idea to load
 221    some more information into the local regs since we have technically
 222    2 or 3 instructions to play with besides the jmp to the 'real' trap
 223    handler (one can even go in the delay slot). For now I am going to put
 224    the %psr (processor status register) and the trap-type value in %l0
 225    and %l3 respectively. Also, for IRQ's I'll put the level in %l4.
 226 
 227 */
 228 
 229         .globl  start
 230         .globl  _trapbase
 231 start:
 232 _trapbase:
 233         b gokernel; WRITE_PAUSE         ! we never get trap #0 it is special
 234 
 235         TRAP_ENTRY(0x1, my_trap_handler) /* Instruction Access Exception */
 236         TRAP_ENTRY(0x2, my_trap_handler) /* Illegal Instruction */
 237         TRAP_ENTRY(0x3, my_trap_handler) /* Privileged Instruction */
 238         TRAP_ENTRY(0x4, my_trap_handler) /* Floating Point Disabled */
 239         TRAP_ENTRY(0x5, spill_window_entry) /* Window Overflow */
 240         TRAP_ENTRY(0x6, fill_window_entry)  /* Window Underflow */
 241         TRAP_ENTRY(0x7, my_trap_handler) /* Memory Address Not Aligned */
 242         TRAP_ENTRY(0x8, my_trap_handler) /* Floating Point Exception */
 243         TRAP_ENTRY(0x9, my_trap_handler) /* Data Miss Exception */
 244         TRAP_ENTRY(0xa, my_trap_handler) /* Tagged Instruction Overflow */
 245         TRAP_ENTRY(0xb, my_trap_handler) /* Watchpoint Detected */
 246         TRAP_ENTRY(0xc, my_trap_handler) /* Undefined... */
 247         TRAP_ENTRY(0xd, my_trap_handler) /* Undefined... */
 248         TRAP_ENTRY(0xe, my_trap_handler) /* Undefined... */
 249         TRAP_ENTRY(0xf, my_trap_handler) /* Undefined... */
 250         TRAP_ENTRY(0x10, my_trap_handler) /* Undefined... */
 251 
 252 /* Level'd interrupt entry points, see macro defs above */
 253 
 254         TRAP_ENTRY_INTERRUPT_SOFT(1, 0x101) /* Interrupt Level 1  */
 255         TRAP_ENTRY_INTERRUPT(2)             /* Interrupt Level 2  */
 256         TRAP_ENTRY_INTERRUPT(3)             /* Interrupt Level 3  */
 257         TRAP_ENTRY_INTERRUPT_SOFT(4, 0x104) /* Interrupt Level 4  */
 258         TRAP_ENTRY_INTERRUPT(5)             /* Interrupt Level 5  */
 259         TRAP_ENTRY_INTERRUPT_SOFT(6, 0x106) /* Interrupt Level 6  */
 260         TRAP_ENTRY_INTERRUPT(7)             /* Interrupt Level 7  */
 261         TRAP_ENTRY_INTERRUPT(8)             /* Interrupt Level 8  */
 262         TRAP_ENTRY_INTERRUPT(9)             /* Interrupt Level 9  */
 263         TRAP_ENTRY_INTERRUPT(10)            /* Interrupt Level 10 */
 264         TRAP_ENTRY_INTERRUPT(11)            /* Interrupt Level 11 */
 265         TRAP_ENTRY_INTERRUPT(12)            /* Interrupt Level 12 */
 266         TRAP_ENTRY_INTERRUPT(13)            /* Interrupt Level 13 */
 267         TRAP_ENTRY_INTERRUPT(14)            /* Interrupt Level 14 */
 268         TRAP_ENTRY_INTERRUPT_NMI(15, linux_trap_nmi) /* Level 15 (nmi) */
 269 
 270         TRAP_ENTRY(0x20, my_trap_handler)   /* General Register Access Error */
 271         TRAP_ENTRY(0x21, my_trap_handler)   /* Instruction Access Error      */
 272         TRAP_ENTRY(0x22, my_trap_handler)   /* Undefined...                  */
 273         TRAP_ENTRY(0x23, my_trap_handler)   /* Undefined...                  */
 274         TRAP_ENTRY(0x24, my_trap_handler)   /* Co-Processor Disabled         */
 275         TRAP_ENTRY(0x25, my_trap_handler)   /* Unimplemented FLUSH inst.     */
 276         TRAP_ENTRY(0x26, my_trap_handler)   /* Undefined...                  */
 277         TRAP_ENTRY(0x27, my_trap_handler)   /* Undefined...                  */
 278         TRAP_ENTRY(0x28, my_trap_handler)   /* Co-Processor Exception        */
 279         TRAP_ENTRY(0x29, my_trap_handler)   /* Data Access Error             */
 280         TRAP_ENTRY(0x2a, my_trap_handler)   /* Division by zero, you lose... */
 281         TRAP_ENTRY(0x2b, my_trap_handler)   /* Data Store Error              */
 282         TRAP_ENTRY(0x2c, my_trap_handler)   /* Data Access MMU-Miss          */
 283         TRAP_ENTRY(0x2d, my_trap_handler)   /* Undefined...                  */
 284         TRAP_ENTRY(0x2e, my_trap_handler)   /* Undefined...                  */
 285         TRAP_ENTRY(0x2f, my_trap_handler)   /* Undefined...                  */
 286         TRAP_ENTRY(0x30, my_trap_handler)   /* Undefined...                  */
 287         TRAP_ENTRY(0x31, my_trap_handler)   /* Undefined...                  */
 288         TRAP_ENTRY(0x32, my_trap_handler)   /* Undefined...                  */
 289         TRAP_ENTRY(0x33, my_trap_handler)   /* Undefined...                  */
 290         TRAP_ENTRY(0x34, my_trap_handler)   /* Undefined...                  */
 291         TRAP_ENTRY(0x35, my_trap_handler)   /* Undefined...                  */
 292         TRAP_ENTRY(0x36, my_trap_handler)   /* Undefined...                  */
 293         TRAP_ENTRY(0x37, my_trap_handler)   /* Undefined...                  */
 294         TRAP_ENTRY(0x38, my_trap_handler)   /* Undefined...                  */
 295         TRAP_ENTRY(0x39, my_trap_handler)   /* Undefined...                  */
 296         TRAP_ENTRY(0x3a, my_trap_handler)   /* Undefined...                  */
 297         TRAP_ENTRY(0x3b, my_trap_handler)   /* Undefined...                  */
 298         TRAP_ENTRY(0x3c, my_trap_handler)   /* Instruction Access MMU-Miss   */
 299         TRAP_ENTRY(0x3d, my_trap_handler)   /* Undefined...                  */
 300         TRAP_ENTRY(0x3e, my_trap_handler)   /* Undefined...                  */
 301         TRAP_ENTRY(0x3f, my_trap_handler)   /* Undefined...                  */
 302         TRAP_ENTRY(0x40, my_trap_handler)   /* Undefined...                  */
 303         TRAP_ENTRY(0x41, my_trap_handler)   /* Undefined...                  */
 304         TRAP_ENTRY(0x42, my_trap_handler)   /* Undefined...                  */
 305         TRAP_ENTRY(0x43, my_trap_handler)   /* Undefined...                  */
 306         TRAP_ENTRY(0x44, my_trap_handler)   /* Undefined...                  */
 307         TRAP_ENTRY(0x45, my_trap_handler)   /* Undefined...                  */
 308         TRAP_ENTRY(0x46, my_trap_handler)   /* Undefined...                  */
 309         TRAP_ENTRY(0x47, my_trap_handler)   /* Undefined...                  */
 310         TRAP_ENTRY(0x48, my_trap_handler)   /* Undefined...                  */
 311         TRAP_ENTRY(0x49, my_trap_handler)   /* Undefined...                  */
 312         TRAP_ENTRY(0x4a, my_trap_handler)   /* Undefined...                  */
 313         TRAP_ENTRY(0x4b, my_trap_handler)   /* Undefined...                  */
 314         TRAP_ENTRY(0x4c, my_trap_handler)   /* Undefined...                  */
 315         TRAP_ENTRY(0x4d, my_trap_handler)   /* Undefined...                  */
 316         TRAP_ENTRY(0x4e, my_trap_handler)   /* Undefined...                  */
 317         TRAP_ENTRY(0x4f, my_trap_handler)   /* Undefined...                  */
 318         TRAP_ENTRY(0x50, my_trap_handler)   /* Undefined...                  */
 319         TRAP_ENTRY(0x51, my_trap_handler)   /* Undefined...                  */
 320         TRAP_ENTRY(0x52, my_trap_handler)   /* Undefined...                  */
 321         TRAP_ENTRY(0x53, my_trap_handler)   /* Undefined...                  */
 322         TRAP_ENTRY(0x54, my_trap_handler)   /* Undefined...                  */
 323         TRAP_ENTRY(0x55, my_trap_handler)   /* Undefined...                  */
 324         TRAP_ENTRY(0x56, my_trap_handler)   /* Undefined...                  */
 325         TRAP_ENTRY(0x57, my_trap_handler)   /* Undefined...                  */
 326         TRAP_ENTRY(0x58, my_trap_handler)   /* Undefined...                  */
 327         TRAP_ENTRY(0x59, my_trap_handler)   /* Undefined...                  */
 328         TRAP_ENTRY(0x5a, my_trap_handler)   /* Undefined...                  */
 329         TRAP_ENTRY(0x5b, my_trap_handler)   /* Undefined...                  */
 330         TRAP_ENTRY(0x5c, my_trap_handler)   /* Undefined...                  */
 331         TRAP_ENTRY(0x5d, my_trap_handler)   /* Undefined...                  */
 332         TRAP_ENTRY(0x5e, my_trap_handler)   /* Undefined...                  */
 333         TRAP_ENTRY(0x5f, my_trap_handler)   /* Undefined...                  */
 334         TRAP_ENTRY(0x60, my_trap_handler)   /* Impl-Dep Exception            */
 335         TRAP_ENTRY(0x61, my_trap_handler)   /* Impl-Dep Exception            */
 336         TRAP_ENTRY(0x62, my_trap_handler)   /* Impl-Dep Exception            */
 337         TRAP_ENTRY(0x63, my_trap_handler)   /* Impl-Dep Exception            */
 338         TRAP_ENTRY(0x64, my_trap_handler)   /* Impl-Dep Exception            */
 339         TRAP_ENTRY(0x65, my_trap_handler)   /* Impl-Dep Exception            */
 340         TRAP_ENTRY(0x66, my_trap_handler)   /* Impl-Dep Exception            */
 341         TRAP_ENTRY(0x67, my_trap_handler)   /* Impl-Dep Exception            */
 342         TRAP_ENTRY(0x68, my_trap_handler)   /* Impl-Dep Exception            */
 343         TRAP_ENTRY(0x69, my_trap_handler)   /* Impl-Dep Exception            */
 344         TRAP_ENTRY(0x6a, my_trap_handler)   /* Impl-Dep Exception            */
 345         TRAP_ENTRY(0x6b, my_trap_handler)   /* Impl-Dep Exception            */
 346         TRAP_ENTRY(0x6c, my_trap_handler)   /* Impl-Dep Exception            */
 347         TRAP_ENTRY(0x6d, my_trap_handler)   /* Impl-Dep Exception            */
 348         TRAP_ENTRY(0x6e, my_trap_handler)   /* Impl-Dep Exception            */
 349         TRAP_ENTRY(0x6f, my_trap_handler)   /* Impl-Dep Exception            */
 350         TRAP_ENTRY(0x70, my_trap_handler)   /* Impl-Dep Exception            */
 351         TRAP_ENTRY(0x71, my_trap_handler)   /* Impl-Dep Exception            */
 352         TRAP_ENTRY(0x72, my_trap_handler)   /* Impl-Dep Exception            */
 353         TRAP_ENTRY(0x73, my_trap_handler)   /* Impl-Dep Exception            */
 354         TRAP_ENTRY(0x74, my_trap_handler)   /* Impl-Dep Exception            */
 355         TRAP_ENTRY(0x75, my_trap_handler)   /* Impl-Dep Exception            */
 356         TRAP_ENTRY(0x76, my_trap_handler)   /* Impl-Dep Exception            */
 357         TRAP_ENTRY(0x77, my_trap_handler)   /* Impl-Dep Exception            */
 358         TRAP_ENTRY(0x78, my_trap_handler)   /* Impl-Dep Exception            */
 359         TRAP_ENTRY(0x79, my_trap_handler)   /* Impl-Dep Exception            */
 360         TRAP_ENTRY(0x7a, my_trap_handler)   /* Impl-Dep Exception            */
 361         TRAP_ENTRY(0x7b, my_trap_handler)   /* Impl-Dep Exception            */
 362         TRAP_ENTRY(0x7c, my_trap_handler)   /* Impl-Dep Exception            */
 363         TRAP_ENTRY(0x7d, my_trap_handler)   /* Impl-Dep Exception            */
 364         TRAP_ENTRY(0x7e, my_trap_handler)   /* Impl-Dep Exception            */
 365         TRAP_ENTRY(0x7f, my_trap_handler)   /* Impl-Dep Exception            */
 366         TRAP_ENTRY(0x80, my_trap_handler)   /* SunOS System Call             */
 367         TRAP_ENTRY(0x81, my_trap_handler)   /* Software Trap                 */
 368         TRAP_ENTRY(0x82, my_trap_handler)   /* Divide by zero trap XXX       */
 369         TRAP_ENTRY(0x83, my_trap_handler)   /* Flush Windows Trap XXX        */
 370         TRAP_ENTRY(0x84, my_trap_handler)   /* Clean Windows Trap XXX        */
 371         TRAP_ENTRY(0x85, my_trap_handler)   /* Software Trap                 */
 372         TRAP_ENTRY(0x86, my_trap_handler)   /* Fix Unaligned Access Trap XXX */
 373         TRAP_ENTRY(0x87, my_trap_handler)   /* Integer Overflow Trap XXX     */
 374         TRAP_ENTRY(0x88, my_trap_handler)   /* Software Trap                 */
 375         TRAP_ENTRY(0x89, my_trap_handler)   /* NetBSD System Call            */
 376         TRAP_ENTRY(0x8a, my_trap_handler)   /* Software Trap                 */
 377         TRAP_ENTRY(0x8b, my_trap_handler)   /* Software Trap                 */
 378         TRAP_ENTRY(0x8c, my_trap_handler)   /* Software Trap                 */
 379         TRAP_ENTRY(0x8d, my_trap_handler)   /* Software Trap                 */
 380         TRAP_ENTRY(0x8e, my_trap_handler)   /* Software Trap                 */
 381         TRAP_ENTRY(0x8f, my_trap_handler)   /* Software Trap                 */
 382         TRAP_ENTRY(0x90, my_trap_handler)   /* SparcLinux System Call        */
 383         TRAP_ENTRY(0x91, my_trap_handler)   /* Software Trap                 */
 384         TRAP_ENTRY(0x92, my_trap_handler)   /* Software Trap                 */
 385         TRAP_ENTRY(0x93, my_trap_handler)   /* Software Trap                 */
 386         TRAP_ENTRY(0x94, my_trap_handler)   /* Software Trap                 */
 387         TRAP_ENTRY(0x95, my_trap_handler)   /* Software Trap                 */
 388         TRAP_ENTRY(0x96, my_trap_handler)   /* Software Trap                 */
 389         TRAP_ENTRY(0x97, my_trap_handler)   /* Software Trap                 */
 390         TRAP_ENTRY(0x98, my_trap_handler)   /* Software Trap                 */
 391         TRAP_ENTRY(0x99, my_trap_handler)   /* Software Trap                 */
 392         TRAP_ENTRY(0x9a, my_trap_handler)   /* Software Trap                 */
 393         TRAP_ENTRY(0x9b, my_trap_handler)   /* Software Trap                 */
 394         TRAP_ENTRY(0x9c, my_trap_handler)   /* Software Trap                 */
 395         TRAP_ENTRY(0x9d, my_trap_handler)   /* Software Trap                 */
 396         TRAP_ENTRY(0x9e, my_trap_handler)   /* Software Trap                 */
 397         TRAP_ENTRY(0x9f, my_trap_handler)   /* Software Trap                 */
 398         TRAP_ENTRY(0xa0, my_trap_handler)   /* Software Trap                 */
 399         TRAP_ENTRY(0xa1, my_trap_handler)   /* Software Trap                 */
 400         TRAP_ENTRY(0xa2, my_trap_handler)   /* Software Trap                 */
 401         TRAP_ENTRY(0xa3, my_trap_handler)   /* Software Trap                 */
 402         TRAP_ENTRY(0xa4, my_trap_handler)   /* Software Trap                 */
 403         TRAP_ENTRY(0xa5, my_trap_handler)   /* Software Trap                 */
 404         TRAP_ENTRY(0xa6, my_trap_handler)   /* Software Trap                 */
 405         TRAP_ENTRY(0xa7, my_trap_handler)   /* Software Trap                 */
 406         TRAP_ENTRY(0xa8, my_trap_handler)   /* Software Trap                 */
 407         TRAP_ENTRY(0xa9, my_trap_handler)   /* Software Trap                 */
 408         TRAP_ENTRY(0xaa, my_trap_handler)   /* Software Trap                 */
 409         TRAP_ENTRY(0xab, my_trap_handler)   /* Software Trap                 */
 410         TRAP_ENTRY(0xac, my_trap_handler)   /* Software Trap                 */
 411         TRAP_ENTRY(0xad, my_trap_handler)   /* Software Trap                 */
 412         TRAP_ENTRY(0xae, my_trap_handler)   /* Software Trap                 */
 413         TRAP_ENTRY(0xaf, my_trap_handler)   /* Software Trap                 */
 414         TRAP_ENTRY(0xb0, my_trap_handler)   /* Software Trap                 */
 415         TRAP_ENTRY(0xb1, my_trap_handler)   /* Software Trap                 */
 416         TRAP_ENTRY(0xb2, my_trap_handler)   /* Software Trap                 */
 417         TRAP_ENTRY(0xb3, my_trap_handler)   /* Software Trap                 */
 418         TRAP_ENTRY(0xb4, my_trap_handler)   /* Software Trap                 */
 419         TRAP_ENTRY(0xb5, my_trap_handler)   /* Software Trap                 */
 420         TRAP_ENTRY(0xb6, my_trap_handler)   /* Software Trap                 */
 421         TRAP_ENTRY(0xb7, my_trap_handler)   /* Software Trap                 */
 422         TRAP_ENTRY(0xb8, my_trap_handler)   /* Software Trap                 */
 423         TRAP_ENTRY(0xb9, my_trap_handler)   /* Software Trap                 */
 424         TRAP_ENTRY(0xba, my_trap_handler)   /* Software Trap                 */
 425         TRAP_ENTRY(0xbb, my_trap_handler)   /* Software Trap                 */
 426         TRAP_ENTRY(0xbc, my_trap_handler)   /* Software Trap                 */
 427         TRAP_ENTRY(0xbd, my_trap_handler)   /* Software Trap                 */
 428         TRAP_ENTRY(0xbe, my_trap_handler)   /* Software Trap                 */
 429         TRAP_ENTRY(0xbf, my_trap_handler)   /* Software Trap                 */
 430         TRAP_ENTRY(0xc0, my_trap_handler)   /* Software Trap                 */
 431         TRAP_ENTRY(0xc1, my_trap_handler)   /* Software Trap                 */
 432         TRAP_ENTRY(0xc2, my_trap_handler)   /* Software Trap                 */
 433         TRAP_ENTRY(0xc3, my_trap_handler)   /* Software Trap                 */
 434         TRAP_ENTRY(0xc4, my_trap_handler)   /* Software Trap                 */
 435         TRAP_ENTRY(0xc5, my_trap_handler)   /* Software Trap                 */
 436         TRAP_ENTRY(0xc6, my_trap_handler)   /* Software Trap                 */
 437         TRAP_ENTRY(0xc7, my_trap_handler)   /* Software Trap                 */
 438         TRAP_ENTRY(0xc8, my_trap_handler)   /* Software Trap                 */
 439         TRAP_ENTRY(0xc9, my_trap_handler)   /* Software Trap                 */
 440         TRAP_ENTRY(0xca, my_trap_handler)   /* Software Trap                 */
 441         TRAP_ENTRY(0xcb, my_trap_handler)   /* Software Trap                 */
 442         TRAP_ENTRY(0xcc, my_trap_handler)   /* Software Trap                 */
 443         TRAP_ENTRY(0xcd, my_trap_handler)   /* Software Trap                 */
 444         TRAP_ENTRY(0xce, my_trap_handler)   /* Software Trap                 */
 445         TRAP_ENTRY(0xcf, my_trap_handler)   /* Software Trap                 */
 446         TRAP_ENTRY(0xd0, my_trap_handler)   /* Software Trap                 */
 447         TRAP_ENTRY(0xd1, my_trap_handler)   /* Software Trap                 */
 448         TRAP_ENTRY(0xd2, my_trap_handler)   /* Software Trap                 */
 449         TRAP_ENTRY(0xd3, my_trap_handler)   /* Software Trap                 */
 450         TRAP_ENTRY(0xd4, my_trap_handler)   /* Software Trap                 */
 451         TRAP_ENTRY(0xd5, my_trap_handler)   /* Software Trap                 */
 452         TRAP_ENTRY(0xd6, my_trap_handler)   /* Software Trap                 */
 453         TRAP_ENTRY(0xd7, my_trap_handler)   /* Software Trap                 */
 454         TRAP_ENTRY(0xd8, my_trap_handler)   /* Software Trap                 */
 455         TRAP_ENTRY(0xd9, my_trap_handler)   /* Software Trap                 */
 456         TRAP_ENTRY(0xda, my_trap_handler)   /* Software Trap                 */
 457         TRAP_ENTRY(0xdb, my_trap_handler)   /* Software Trap                 */
 458         TRAP_ENTRY(0xdc, my_trap_handler)   /* Software Trap                 */
 459         TRAP_ENTRY(0xdd, my_trap_handler)   /* Software Trap                 */
 460         TRAP_ENTRY(0xde, my_trap_handler)   /* Software Trap                 */
 461         TRAP_ENTRY(0xdf, my_trap_handler)   /* Software Trap                 */
 462         TRAP_ENTRY(0xe0, my_trap_handler)   /* Software Trap                 */
 463         TRAP_ENTRY(0xe1, my_trap_handler)   /* Software Trap                 */
 464         TRAP_ENTRY(0xe2, my_trap_handler)   /* Software Trap                 */
 465         TRAP_ENTRY(0xe3, my_trap_handler)   /* Software Trap                 */
 466         TRAP_ENTRY(0xe4, my_trap_handler)   /* Software Trap                 */
 467         TRAP_ENTRY(0xe5, my_trap_handler)   /* Software Trap                 */
 468         TRAP_ENTRY(0xe6, my_trap_handler)   /* Software Trap                 */
 469         TRAP_ENTRY(0xe7, my_trap_handler)   /* Software Trap                 */
 470         TRAP_ENTRY(0xe8, my_trap_handler)   /* Software Trap                 */
 471         TRAP_ENTRY(0xe9, my_trap_handler)   /* Software Trap                 */
 472         TRAP_ENTRY(0xea, my_trap_handler)   /* Software Trap                 */
 473         TRAP_ENTRY(0xeb, my_trap_handler)   /* Software Trap                 */
 474         TRAP_ENTRY(0xec, my_trap_handler)   /* Software Trap                 */
 475         TRAP_ENTRY(0xed, my_trap_handler)   /* Software Trap                 */
 476         TRAP_ENTRY(0xee, my_trap_handler)   /* Software Trap                 */
 477         TRAP_ENTRY(0xef, my_trap_handler)   /* Software Trap                 */
 478         TRAP_ENTRY(0xf0, my_trap_handler)   /* Software Trap                 */
 479         TRAP_ENTRY(0xf1, my_trap_handler)   /* Software Trap                 */
 480         TRAP_ENTRY(0xf2, my_trap_handler)   /* Software Trap                 */
 481         TRAP_ENTRY(0xf3, my_trap_handler)   /* Software Trap                 */
 482         TRAP_ENTRY(0xf4, my_trap_handler)   /* Software Trap                 */
 483         TRAP_ENTRY(0xf5, my_trap_handler)   /* Software Trap                 */
 484         TRAP_ENTRY(0xf6, my_trap_handler)   /* Software Trap                 */
 485         TRAP_ENTRY(0xf7, my_trap_handler)   /* Software Trap                 */
 486         TRAP_ENTRY(0xf8, my_trap_handler)   /* Software Trap                 */
 487         TRAP_ENTRY(0xf9, my_trap_handler)   /* Software Trap                 */
 488         TRAP_ENTRY(0xfa, my_trap_handler)   /* Software Trap                 */
 489         TRAP_ENTRY(0xfb, my_trap_handler)   /* Software Trap                 */
 490         TRAP_ENTRY(0xfc, my_trap_handler)   /* Software Trap                 */
 491         TRAP_ENTRY(0xfd, my_trap_handler)   /* Software Trap                 */
 492         TRAP_ENTRY(0xfe, my_trap_handler)   /* Software Trap                 */
 493         TRAP_ENTRY(0xff, my_trap_handler)   /* Software Trap                 */ 
 494 
 495 _msgbufmapped:
 496         .word   1
 497 
 498 
 499 
 500 /* Cool, here we go. Pick up the romvec pointer in %o0 and stash it in
 501    %g7 and at _prom_vector_p. And also quickly check whether we are on
 502    a v0 or v2 prom.
 503 */
 504 
 505 gokernel:       or      %g0, %o0, %g7
 506                 sethi   %hi(_prom_vector_p), %g1
 507                 st      %o0, [%g1 + %lo(_prom_vector_p)]   ! we will need it later
 508                 rd      %psr, %l2
 509                 rd      %wim, %l3
 510                 rd      %tbr, %l4
 511                 or      %g0, %o2, %l5           ! could be prom magic value...
 512         
 513 #if 0 /* You think I'm nutz? */
 514                 subcc   %l5, 0x0, %g0           ! check for magic SMP pointer
 515                 bne     nosmp   
 516                 nop
 517                 call    %o2                     ! call smp prom setup 
 518                 nop
 519 #endif /* I will be soon... */
 520 
 521 /* Acquire boot time privileged register values, this will help debugging.
 522  * I figure out and store nwindows later on.
 523  */
 524 
 525 nosmp:          sethi   %hi(_boot_psr), %l1
 526                 st      %l2, [%l1 + %lo(_boot_psr)]
 527                 sethi   %hi(_boot_wim), %l1
 528                 st      %l3, [%l1 + %lo(_boot_wim)]
 529                 sethi   %hi(_boot_tbr), %l1
 530                 st      %l4, [%l1 + %lo(_boot_tbr)]
 531                 sethi   %hi(_boot_smp_ptr), %l1
 532                 st      %l5, [%l1 + %lo(_boot_smp_ptr)]
 533 
 534                 or      %g0, %o0, %g7
 535                 sethi   %hi(_prom_vector_p), %g5
 536                 st      %o0, [%g5 + %lo(_prom_vector_p)]   ! we will need it later
 537 
 538                 ld      [%g7 + 0x4], %o3
 539                 subcc   %o3, 0x2, %g0                   ! a v2 prom?
 540                 be      found_v2
 541                 nop
 542 
 543 /* Old sun4's pass our load address into %o0 instead of the prom
 544    pointer. On sun4's you have to hard code the romvec pointer into
 545    your code. Sun probably still does that because they don't even
 546    trust their own "OpenBoot" specifications.
 547 */
 548 
 549                 sethi   %hi(LOAD_ADDR), %g6
 550                 subcc   %o0, %g6, %g0           ! an old sun4?
 551                 be      no_sun4_here
 552                 nop
 553 
 554                 sethi   %hi(_prom_iface_vers), %g1
 555                 st      %g0, [%g1 + %lo(_prom_iface_vers)]
 556                 b       not_v2
 557                 nop
 558 
 559 found_v2:
 560                 or      %g0, 0x2, %o5
 561                 sethi   %hi(_prom_iface_vers), %g1
 562                 st      %o5, [%g1 + %lo(_prom_iface_vers)]
 563 
 564 not_v2:
 565 
 566 /* Get the machine type via the mysterious romvec node operations.
 567  * Here we can find out whether we are on a sun4 sun4c, sun4m, or
 568  * a sun4m. The "nodes" are set up as a bunch of n-ary trees which
 569  * you can traverse to get information about devices and such. The
 570  * information acquisition happens via the node-ops which are defined
 571  * in the linux_openprom.h header file. Of particular interest is the
 572  * 'nextnode(int node)' function as it does the smart thing when
 573  * presented with a value of '0', it gives you the first node in the
 574  * tree. These node integers probably offset into some internal prom
 575  * pointer table the openboot has. It's completely undocumented, so
 576  * I'm not about to go sifting through the prom address space, but may
 577  * do so if I get suspicious enough. :-)
 578  */
 579 
 580                 or      %g0, %g7, %l1
 581                 add     %l1, 0x1c, %l1          
 582                 ld      [%l1], %l0
 583                 ld      [%l0], %l0
 584                 call    %l0
 585                 or      %g0, %g0, %o0           ! next_node(0) = first_node
 586 
 587                 sethi   %hi(_cputypvar), %o1    ! first node has cpu-arch
 588                 or      %o1, %lo(_cputypvar), %o1
 589                 sethi   %hi(_cputypval), %o2    ! information, the string
 590                 or      %o2, %lo(_cputypval), %o2
 591                 ld      [%l1], %l0              ! 'compatibility' tells
 592                 ld      [%l0 + 0xc], %l0        ! that we want 'sun4x' where
 593                 call    %l0                     ! x is one of '', 'c', 'm',
 594                 nop                             ! 'd' or 'e'. %o2 holds pointer
 595                                                 ! to a buf where above string
 596                                                 ! will get stored by the prom.
 597 
 598                 sethi   %hi(_cputypval), %o2    ! better safe than sorry
 599                 or      %o2, %lo(_cputypval), %o2
 600                 ldub    [%o2 + 0x4], %o0
 601                 subcc   %o0, 'c', %g0           ! we already know we are not
 602                 be      is_sun4c                ! on a plain sun4 because of
 603                 nop                             ! the check for 0x4000 in %o0
 604                 subcc   %o0, 'm', %g0           ! at start:
 605                 be      is_sun4m
 606                 nop
 607                 b       no_sun4d_here           ! god bless the person who
 608                 nop                             ! tried to run this on sun4d
 609 
 610 is_sun4m:
 611 is_sun4c:                                       ! OK, this is a sun4c, yippie
 612                 or      %g0, %g7, %g6           ! load up the promvec offsets
 613                 sethi   %hi(prom_magic), %g5    ! magic mushroom :>
 614                 st      %g6, [%g5 + %lo(prom_magic)]
 615                 add     %g7, 0x4, %g6
 616                 sethi   %hi(prom_rom_vers), %g5
 617                 st      %g6, [%g5 + %lo(prom_rom_vers)]
 618                 add     %g7, 0x8, %g6
 619                 sethi   %hi(prom_pluginvers), %g5
 620                 st      %g6, [%g5 + %lo(prom_pluginvers)]
 621                 add     %g7, 0xc, %g6
 622                 sethi   %hi(prom_revision), %g5
 623                 st      %g6, [%g5 + %lo(prom_revision)]
 624                 add     %g7, 0x10, %g6
 625                 sethi   %hi(prom_v0mem_desc), %g5
 626                 st      %g6, [%g5 + %lo(prom_v0mem_desc)]
 627                 add     %g7, 0x1c, %g6
 628                 sethi   %hi(prom_nodefuncs), %g5
 629                 st      %g6, [%g5 + %lo(prom_nodefuncs)]
 630                 add     %g7, 0x68, %g6
 631                 sethi   %hi(prom_printf), %g5
 632                 st      %g6, [%g5 + %lo(prom_printf)]
 633                 add     %g7, 0x6c, %g6
 634                 sethi   %hi(prom_abort), %g5
 635                 st      %g6, [%g5 + %lo(prom_abort)]
 636                 add     %g7, 0x74, %g6
 637                 sethi   %hi(prom_halt), %g5
 638                 st      %g6, [%g5 + %lo(prom_halt)]
 639                 add     %g7, 0x78, %g6
 640                 sethi   %hi(prom_sync), %g5
 641                 st      %g6, [%g5 + %lo(prom_sync)]
 642                 add     %g7, 0x7c, %g6
 643                 sethi   %hi(prom_eval), %g5
 644                 st      %g6, [%g5 + %lo(prom_eval)]
 645                 add     %g7, 0x80, %g6
 646                 sethi   %hi(prom_v0bootline), %g6
 647                 st      %g6, [%g5 + %lo(prom_v0bootline)]
 648 
 649 
 650 /* That was easy, now lets try to print some message on the screen.
 651  * We don't have to worry about bad address translations when the prom
 652  * addresses our pointers because our pointers are at 0x0-kern_size
 653  * as the prom expects.
 654  */
 655 
 656                 sethi   %hi(boot_msg), %o0      
 657                 or      %o0, %lo(boot_msg), %o0
 658                 sethi   %hi(prom_printf), %o1
 659                 ld      [%o1 + %lo(prom_printf)], %o1
 660                 ld      [%o1], %o1
 661                 call    %o1                     ! print boot message #1
 662                 nop
 663 
 664 _newline:       sethi   %hi(newline), %o0
 665                 or      %o0, %lo(newline), %o0
 666                 sethi   %hi(prom_printf), %o1
 667                 ld      [%o1 + %lo(prom_printf)], %o1
 668                 ld      [%o1], %o1
 669                 call    %o1
 670                 nop
 671 
 672                 sethi   %hi(pstring1), %o0
 673                 or      %o0, %lo(pstring1), %o0
 674                 sethi   %hi(prom_printf), %o2
 675                 ld      [%o2 + %lo(prom_printf)], %o2
 676                 ld      [%o2], %o2
 677                 sethi   %hi(prom_magic), %o1
 678                 ld      [%o1 + %lo(prom_magic)], %o1
 679                 ld      [%o1], %o1
 680                 call    %o2
 681 
 682                 sethi   %hi(pstring2), %o0
 683                 or      %o0, %lo(pstring2), %o0
 684                 sethi   %hi(prom_printf), %o2
 685                 ld      [%o2 + %lo(prom_printf)], %o2
 686                 ld      [%o2], %o2
 687                 sethi   %hi(_prom_iface_vers), %o1
 688                 ld      [%o1 + %lo(_prom_iface_vers)], %o1
 689                 ld      [%o1], %o1
 690                 call    %o2
 691 
 692                 b       halt_me
 693                 nop
 694 
 695 no_sun4_here:
 696                 ld      [%g7 + 0x68], %o1
 697                 set     sun4_notsup, %o0
 698                 call    %o1
 699                 nop
 700 
 701 rest_of_boot:
 702                 or      %g0, PAGE_SHIFT, %g5
 703 
 704                 sethi   %hi(AC_CONTEXT), %g1    ! kernel context, safe now
 705                                                 ! the only valid context
 706                                                 ! until we call paging_init()
 707                 stba    %g0, [%g1] ASI_CONTROL
 708 
 709 
 710 /* I make the kernel image sit in memory relative to 0x0 with the text 
 711  * starting at 0x4000. Now it looks like the way memory is set in Linux
 712  * on an ix86.
 713  */
 714 
 715 /* Uh, oh, interrupt time. This crap is real confusing. What I want to do is
 716  * clear all interrupts, map the interrupt enable register which in effect
 717  * enables non-maskable interrupts (or NMI's). Actually we take no interrupts
 718  * until we frob with the %tbr (trap base register) which the prom has set 
 719  * to all its routines which allows some sanity during bootup.
 720  */
 721 
 722 #if 0 /* paranoid, need to fix this routine now */
 723                 sethi   %hi(IE_reg_addr), %l0
 724                 or      %l0, %lo(IE_reg_addr), %l0
 725                 sethi   %hi(INT_ENABLE_REG_PHYSADR), %l2
 726                 or      %l2, %lo(INT_ENABLE_REG_PHYSADR), %l2
 727                 srl     %l2, %g5, %l1
 728 
 729                 sta     %l1, [%l0] ASI_PTE
 730                 mov     INTS_ALL_ENAB, %l1
 731                 stb     %l1, [%l0]
 732 #endif /* paranoid, see above */
 733         
 734 /* Aieee, now set PC and nPC, enable traps, give ourselves a stack and it's
 735  * show-time!
 736  */
 737 
 738                 sethi   %hi(1f), %g1
 739                 or      %g1, %lo(1f), %g1
 740                 jmp     %g1
 741                 nop
 742 
 743                 .align 4
 744 1:              sethi   %hi(_cputyp), %o0
 745                 st      %g4, [%o0 + %lo(_cputyp)]
 746 
 747                 sethi   %hi(_pgshift), %o0
 748                 st      %g5, [%o0 + %lo(_pgshift)]
 749 
 750                 mov     1, %o0
 751                 sll     %o0, %g5, %g5
 752                 sethi   %hi(_nbpg), %o0
 753                 st      %g5, [%o0 + %lo(_nbpg)]
 754 
 755                 sub     %g5, 1, %g5
 756                 sethi   %hi(_pgofset), %o0
 757                 st      %g5, [%o0 + %lo(_pgofset)]
 758 
 759 
 760                 rd      %psr, %g3
 761                 andn    %g3, PSR_ET, %g3
 762                 wr      %g3, 0x0, %psr          ! make sure traps are off
 763                                                 ! before we play around
 764                 WRITE_PAUSE                     ! no guarantees until 3 insns
 765 
 766 
 767                 wr      %g0, 0x0, %wim          ! magical invalid window reg
 768                 WRITE_PAUSE                     ! see above
 769 
 770         
 771 /* I keep the timer interrupt on so that BogoMIPS works and the prom
 772  * keeps updating it's "jiffies" counter. 100HZ clock on sparcstations.
 773  */     
 774 
 775 /* If gas wasn't so dumb, I could use or'd macros in this next
 776  * write. ;-( like this (PSR_PS | PSR_S | PSR_PIL)...
 777  */
 778 
 779                 wr      %g0, (0xfc0), %psr
 780                 WRITE_PAUSE
 781 
 782                 wr      %g0, 0x2, %wim          ! window 1 invalid
 783                 WRITE_PAUSE
 784                 or      %g0, 0x1, %g1
 785                 sethi   %hi(_current + THREAD_WIM), %g2
 786                 st      %g1, [%g2 + %lo(_current + THREAD_WIM)]
 787 
 788 /* I want a kernel stack NOW! */
 789 
 790                 set     USRSTACK - C_STACK, %fp 
 791                 set     USRSTACK - C_STACK + 80, %sp
 792                 rd      %psr, %l0
 793                 wr      %l0, PSR_ET, %psr
 794                 WRITE_PAUSE
 795 
 796 
 797 /*
 798  * Maybe the prom zeroes out our BSS section, maybe it doesn't. I certainly 
 799  * don't know, do you?
 800  */
 801 
 802                 set     _edata, %o0
 803                 set     _end, %o1
 804                 sub     %o1, %o0, %g2
 805                 sethi   %hi(_kernel_bss_len), %g3
 806                 st      %g2, [%g3 + %lo(_kernel_bss_len)]
 807                 sethi   %hi(_trapbase), %g3
 808                 or      %g3, %lo(_trapbase), %g3
 809                 sethi   %hi(_etext), %g4
 810                 or      %g4, %lo(_etext), %g4                   
 811                 sub     %g4, %g3, %g2
 812                 sethi   %hi(_kernel_text_len), %g3
 813                 st      %g2, [%g3 + %lo(_kernel_text_len)]
 814                 sethi   %hi(_etext), %g4
 815                 or      %g4, %lo(_etext), %g4
 816                 sethi   %hi(_edata), %g3
 817                 or      %g3, %lo(_edata), %g3
 818                 sub     %g3, %g4, %g2
 819                 sethi   %hi(_kernel_data_len), %g3
 820                 st      %g2, [%g3 + %lo(_kernel_data_len)]
 821                 or      %g0, %g0, %g1
 822 
 823 1:      
 824                 st      %g0, [%o0]
 825                 add     %o0, 0x4, %o0
 826                 subcc   %o0, %o1, %g0
 827                 bl      1b
 828                 nop
 829 
 830 /* Compute NWINDOWS and stash it away. Now uses %wim trick explained
 831  * in the V8 manual. Ok, this method seems to work, sparc is cool...
 832  */
 833 
 834                 sethi   %hi(0xffffffff), %g1
 835                 rd      %wim, %g2                       ! save current value
 836                 or      %g1, %lo(0xffffffff), %g1
 837                 wr      %g1, 0x0, %wim
 838                 rd      %wim, %g1                       ! get remaining mask
 839                 wr      %g2, 0x0, %wim                  ! restore old value
 840                 WRITE_PAUSE
 841 
 842                 or      %g0, 0x0, %g3
 843 
 844 1:              srl     %g1, 0x1, %g1                   ! shift until highest
 845                 subcc   %g1, 0x0, %g0                   ! bit set
 846                 bne     1b
 847                 add     %g3, 0x1, %g3
 848                 sethi   %hi(_nwindows), %g4
 849                 st      %g3, [%g4 + %lo(_nwindows)]     ! store final value
 850                 sub     %g3, 0x1, %g3
 851                 sethi   %hi(_nwindowsm1), %g4
 852                 st      %g3, [%g4 + %lo(_nwindowsm1)]
 853 
 854 
 855 /* Here we go */
 856 
 857 /* start_kernel() wants the command line args at empty_zero_page, copy
 858  * the boot command line from the prom data struct here...
 859  */
 860 
 861 /* I still haven't gotten this right yet... hack hack hack */
 862         
 863 #if 0
 864                 sethi   %hi(prom_v0bootline), %g6
 865                 ld      [%g6 + %lo(prom_v0bootline)], %g6
 866                 ld      [%g6], %g6
 867                 ld      [%g6], %g6
 868                 sethi   %hi(_empty_zero_page + 2048), %g2
 869                 ld      [%g2 + %lo(_empty_zero_page + 2048)], %g2
 870                 ld      [%g6], %g3      ! argv[0]               
 871                 or      %g0, 0x8, %g1   ! argv counter
 872 1:              ld      [%g3], %g4
 873                 st      %g4, [%g2]
 874                 add     %g3, 0x4, %g3
 875                 cmp     %g4, 0
 876                 bne,a   1b
 877                 add     %g2, 0x4, %g2
 878 
 879                 or      %g0, %lo(' '), %g4
 880                 st      %g4, [%g2]
 881                 sub     %g1, 0x1, %g1
 882                 add     %g3, 0x4, %g3
 883                 cmp     %g1, 0
 884                 bne     1b
 885                 add     %g2, 0x4, %g2
 886 #endif
 887 
 888 /* First we call init_prom() to set up romvec, then off to start_kernel() */
 889 
 890                 sethi   %hi(_prom_vector_p), %g5
 891                 call    _init_prom
 892                 ld      [%g5 + %lo(_prom_vector_p)], %o0   /* delay slot */
 893 
 894                 call    _start_kernel
 895                 nop
 896         
 897                 call    halt_me
 898                 nop
 899 
 900 /* There, happy now adrian? */
 901 
 902 no_sun4d_here:
 903                 ld      [%g7 + 0x68], %o1
 904                 set     sun4d_notsup, %o0
 905                 call    %o1
 906                 nop
 907                 b       halt_me
 908                 nop
 909 
 910 halt_me:
 911                 ld      [%g7 + 0x74], %o0
 912                 call    %o0                     ! get us out of here...
 913                 nop                             ! apparently solaris is better
 914 
 915         .data
 916         .align 4
 917 
 918 /*
 919  * Fill up the prom vector, note in particular the kind first element,
 920  * no joke. I don't need all of them in here as the entire prom vector
 921  * gets initialized in c-code so all routines can use it.
 922  */
 923 
 924                         .globl _prom_vector_p
 925 
 926 _prom_vector_p:         .skip 4
 927 prom_magic:             .skip 4                 ! magic mushroom, beware...
 928 prom_rom_vers:          .skip 4                 ! interface version (v0 or v2)
 929 prom_pluginvers:        .skip 4                 ! XXX help help help ???
 930 prom_revision:          .skip 4                 ! PROM revision (ie. 1.4)
 931 prom_halt:              .skip 4                 ! void halt(void)  solaris friend
 932 prom_eval:              .skip 4                 ! void eval(int len, char* string)
 933 prom_v0bootline:        .skip 4                 ! boot command line
 934 prom_v0mem_desc:        .skip 4                 ! V0 memory descriptor list ptr.
 935 prom_nodefuncs:         .skip 4                 ! Magical Node functions
 936 prom_printf:            .skip 4                 ! minimal printf()
 937 
 938 /* The prom_abort pointer MUST be mapped in all contexts, because if you
 939  * don't then if a user process is running when you press the abort key
 940  * sequence, all sorts of bad things can happen
 941  */
 942 
 943 prom_abort:             .skip 4         ! L1-A magic cookie
 944                                         ! must be mapped in ALL contexts
 945 
 946 /* prom_sync is a place where the kernel should place a pointer to a kernel
 947  * function that when called will sync all pending information to the drives
 948  * and then promptly return. If the kernel gets aborted with 'L1-A' one can
 949  * give the 'sync' command to the boot prompt and this magic cookie gets
 950  * executed. Nice feature eh?
 951  */
 952 
 953 prom_sync:              .skip 4                 ! hook in prom for sync func
 954 
 955         .align 4
 956 
 957 /* We calculate the following at boot time, window fills/spills and trap entry
 958  * code uses these to keep track of the register windows.
 959  */
 960 
 961         .globl _nwindows
 962         .globl _nwindowsm1
 963 _nwindows:      .skip 4
 964 _nwindowsm1:    .skip 4
 965 
 966         .align 4
 967 /* Boot time privileged register values, plus magic %o2 value */
 968 
 969         .globl _boot_wim
 970         .globl _boot_psr
 971         .globl _boot_tbr
 972         .globl _boot_smp_ptr
 973 _boot_wim:              .skip 4
 974 _boot_psr:              .skip 4
 975 _boot_tbr:              .skip 4
 976 _boot_smp_ptr:          .skip 4
 977 
 978 
 979         .align 4
 980 /* Miscellaneous pieces of information saved at kernel startup. */
 981         .globl _kernel_text_len, _kernel_data_len, _kernel_bss_len
 982 _kernel_text_len:       .word 0
 983 _kernel_data_len:       .word 0
 984 _kernel_bss_len:        .word 0
 985 
 986 /* These are for page alignment/offset information as they change from
 987    machine to machine.
 988 */
 989 
 990         .globl  _pgshift, _nbpg, _pgofset
 991 
 992         .align 4
 993 _pgshift:
 994         .word   1
 995 _nbpg:
 996         .word   1
 997 _pgofset:
 998         .word   1
 999 
1000 /* Just to get the kernel through the compiler for now */
1001         .globl _swapper_pg_dir,_pg0
1002         .globl _empty_bad_page
1003         .globl _empty_bad_page_table
1004         .globl _empty_zero_page
1005         .globl _floppy_track_buffer
1006 _floppy_track_buffer:
1007         .fill 512*2*36,1,0
1008 
1009         .align 4
1010 _swapper_pg_dir:        .skip 0x1000
1011 _pg0:                   .skip 0x1000
1012 _empty_bad_page:        .skip 0x1000
1013 _empty_bad_page_table:  .skip 0x1000
1014 _empty_zero_page:       .skip 0x1000
1015 

/* [previous][next][first][last][top][bottom][index][help] */