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

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