root/arch/sparc/kernel/head.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 /* head.S: The initial boot code for the Sparc port of Linux.
   2  *
   3  * Copyright (C) 1995 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 <linux/version.h>
  46 #include <asm/asi.h>
  47 #include <asm/contregs.h>
  48 #include <asm/psr.h>
  49 #include <asm/page.h>
  50 #include <asm/kdebug.h>
  51 
  52         .data
  53 
  54 /* First thing to go in the data segment is the interrupt stack. */
  55 
  56         .globl  C_LABEL(intstack)
  57         .globl  C_LABEL(eintstack)
  58         .align 4
  59 C_LABEL(intstack):
  60         .skip   4 * PAGE_SIZE                ! 16k = 128 128-byte stack frames
  61 C_LABEL(eintstack):
  62 
  63 
  64 
  65 /* 
  66  * The following are used with the prom_vector node-ops to figure out
  67  * the cpu-type 
  68  */
  69 
  70         .align 4
  71         .globl  C_LABEL(cputyp)
  72 C_LABEL(cputyp):
  73         .word   1
  74 
  75         .align 4
  76         .globl C_LABEL(cputypval)
  77 C_LABEL(cputypval):
  78         .asciz "sun4c"
  79         .ascii "     "
  80 
  81 C_LABEL(cputypvalend):
  82 C_LABEL(cputypvallen) = C_LABEL(cputypvar) - C_LABEL(cputypval)
  83 
  84         .align 4
  85 /*
  86  * Sun people can't spell worth damn. "compatability" indeed.
  87  * At least we *know* we can't spell, and use a spell-checker.
  88  */
  89 
  90 /* Uh, actually Linus it is I who cannot spell. Too much murky
  91  * Sparc assembly will do this to ya.
  92  */
  93 C_LABEL(cputypvar):
  94         .asciz "compatability"
  95 
  96 /* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. --P3 */
  97         .align 4
  98 C_LABEL(cputypvar_sun4m):
  99         .asciz "compatible"
 100 
 101 /* WARNING: evil messages follow */
 102 
 103         .align 4
 104 
 105 sun4_notsup:
 106         .asciz  "Sparc-Linux sun4 support not implemented yet\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 sun4e_notsup:
 114         .asciz  "Sparc-Linux sun4e support does not exist\n\n"
 115         .align 4
 116 
 117 sun4u_notsup:
 118         .asciz  "Sparc-Linux sun4u support does not exist\n\n"
 119         .align 4
 120 
 121 /* Ok, things start to get interesting. We get linked such that 'start'
 122  * is the entry symbol. However, it is real low in kernel address space
 123  * and as such a nifty place to place the trap table. We achieve this goal
 124  * by just jumping to 'gokernel' for the first trap's entry as the sparc
 125  * never receives the zero trap as it is real special (hw reset).
 126  *
 127  * Each trap entry point is the size of 4 sparc instructions (or 4 bytes
 128  * * 4 insns = 16 bytes). There are 128 hardware traps (some undefined
 129  * or unimplemented) and 128 software traps (sys-calls, etc.).
 130  *
 131  * One of the instructions must be a branch. More often than not this
 132  * will be to a trap handler entry point because it is completely
 133  * impossible to handle any trap in 4 insns. I welcome anyone to 
 134  * challenge this theory. :-)
 135  *
 136  * On entry into this table the hardware has loaded the program counter
 137  * at which the trap occurred into register %l1 and the next program
 138  * counter into %l2, this way we can return from the trap with a simple
 139  *
 140  *         jmp %l1; rett %l2  ! poof...
 141  *
 142  * after properly servicing the trap. It wouldn't be a bad idea to load
 143  * some more information into the local regs since we have technically
 144  * 2 or 3 instructions to play with besides the jmp to the 'real' trap
 145  * handler (one can even go in the delay slot). For now I am going to put
 146  * the %psr (processor status register) and the trap-type value in %l0
 147  * and %l3 respectively. Also, for IRQ's I'll put the level in %l4.
 148  */
 149 
 150         .text
 151 
 152         .globl  start
 153         .globl  _start  /* warning, solaris hack */
 154         .globl  C_LABEL(trapbase)
 155 _start:   /* danger danger */
 156 start:
 157 C_LABEL(trapbase):
 158 /* XXX Grrr, this table is basically sun4c specific, sort of... XXX */
 159 /* We get control passed to us here at t_zero. */
 160 t_zero: b gokernel; nop; nop; nop;
 161 
 162 t_tflt: TRAP_ENTRY(0x1, sparc_text_fault)    /* Inst. Access Exception        */
 163 t_bins: TRAP_ENTRY(0x2, bad_instruction)     /* Illegal Instruction           */
 164 t_pins: TRAP_ENTRY(0x3, bad_instruction)     /* Privileged Instruction        */
 165 t_fpd:  TRAP_ENTRY(0x4, fpd_trap_handler)    /* Floating Point Disabled       */
 166 t_wovf: TRAP_ENTRY(0x5, spill_window_entry)  /* Window Overflow               */
 167 t_wunf: TRAP_ENTRY(0x6, fill_window_entry)   /* Window Underflow              */
 168 t_mna:  TRAP_ENTRY(0x7, mna_handler)         /* Memory Address Not Aligned    */
 169 t_fpe:  TRAP_ENTRY(0x8, fpe_trap_handler)    /* Floating Point Exception      */
 170 t_dflt: TRAP_ENTRY(0x9, sparc_data_fault)    /* Data Miss Exception           */
 171 t_tio:  TRAP_ENTRY(0xa, do_tag_overflow)     /* Tagged Instruction Ovrflw     */
 172 t_wpt:  TRAP_ENTRY(0xb, do_watchpoint)       /* Watchpoint Detected           */
 173 t_badc: TRAP_ENTRY(0xc, bad_trap_handler)    /* Undefined...                  */
 174 t_badd: TRAP_ENTRY(0xd, bad_trap_handler)    /* Undefined...                  */
 175 t_bade: TRAP_ENTRY(0xe, bad_trap_handler)    /* Undefined...                  */
 176 t_badf: TRAP_ENTRY(0xf, bad_trap_handler)    /* Undefined...                  */
 177 t_bad10:TRAP_ENTRY(0x10, bad_trap_handler)   /* Undefined...                  */
 178 t_irq1: TRAP_ENTRY_INTERRUPT(1)              /* IRQ Software/SBUS Level 1     */
 179 t_irq2: TRAP_ENTRY_INTERRUPT(2)              /* IRQ SBUS Level 2              */
 180 t_irq3: TRAP_ENTRY_INTERRUPT(3)              /* IRQ SCSI/DMA/SBUS Level 3     */
 181 t_irq4: TRAP_ENTRY_INTERRUPT(4)              /* IRQ Software Level 4          */
 182 t_irq5: TRAP_ENTRY_INTERRUPT(5)              /* IRQ SBUS/Ethernet Level 5     */
 183 t_irq6: TRAP_ENTRY_INTERRUPT(6)              /* IRQ Software Level 6          */
 184 t_irq7: TRAP_ENTRY_INTERRUPT(7)              /* IRQ Video/SBUS Level 5        */
 185 t_irq8: TRAP_ENTRY_INTERRUPT(8)              /* IRQ SBUS Level 6              */
 186 t_irq9: TRAP_ENTRY_INTERRUPT(9)              /* IRQ SBUS Level 7              */
 187 t_irq10:TRAP_ENTRY_TIMER                     /* IRQ Timer #1 (one we use)     */
 188 t_irq11:TRAP_ENTRY_INTERRUPT(11)             /* IRQ Floppy Intr.              */
 189 t_irq12:TRAP_ENTRY_INTERRUPT(12)             /* IRQ Zilog serial chip         */
 190 t_irq13:TRAP_ENTRY_INTERRUPT(13)             /* IRQ Audio Intr.               */
 191 t_irq14:TRAP_ENTRY_INTERRUPT(14)             /* IRQ Timer #2                  */
 192 t_nmi:  NMI_TRAP                             /* Level 15 (NMI)                */
 193 t_racc: TRAP_ENTRY(0x20, do_reg_access)      /* General Register Access Error */
 194 t_iacce:TRAP_ENTRY(0x21, do_iacc_error)      /* Instruction Access Error      */
 195 t_bad22:TRAP_ENTRY(0x22, bad_trap_handler)   /* Undefined...                  */
 196 t_bad23:TRAP_ENTRY(0x23, bad_trap_handler)   /* Undefined...                  */
 197 t_cpdis:TRAP_ENTRY(0x24, do_cp_disabled)     /* Co-Processor Disabled         */
 198 t_uflsh:TRAP_ENTRY(0x25, do_bad_flush)       /* Unimplemented FLUSH inst.     */
 199 t_bad26:TRAP_ENTRY(0x26, bad_trap_handler)   /* Undefined...                  */
 200 t_bad27:TRAP_ENTRY(0x27, bad_trap_handler)   /* Undefined...                  */
 201 t_cpexc:TRAP_ENTRY(0x28, do_cp_exception)    /* Co-Processor Exception        */
 202 t_dacce:TRAP_ENTRY(0x29, do_dacc_error)      /* Data Access Error             */
 203 t_hwdz: TRAP_ENTRY(0x2a, do_hw_divzero)      /* Division by zero, you lose... */
 204 t_dserr:TRAP_ENTRY(0x2b, do_dstore_err)      /* Data Store Error              */
 205 t_daccm:TRAP_ENTRY(0x2c, do_dacc_mmu_miss)   /* Data Access MMU-Miss          */
 206 t_bad2d:TRAP_ENTRY(0x2d, bad_trap_handler)   /* Undefined...                  */
 207 t_bad2e:TRAP_ENTRY(0x2e, bad_trap_handler)   /* Undefined...                  */
 208 t_bad2f:TRAP_ENTRY(0x2f, bad_trap_handler)   /* Undefined...                  */
 209 t_bad30:TRAP_ENTRY(0x30, bad_trap_handler)   /* Undefined...                  */
 210 t_bad31:TRAP_ENTRY(0x31, bad_trap_handler)   /* Undefined...                  */
 211 t_bad32:TRAP_ENTRY(0x32, bad_trap_handler)   /* Undefined...                  */
 212 t_bad33:TRAP_ENTRY(0x33, bad_trap_handler)   /* Undefined...                  */
 213 t_bad34:TRAP_ENTRY(0x34, bad_trap_handler)   /* Undefined...                  */
 214 t_bad35:TRAP_ENTRY(0x35, bad_trap_handler)   /* Undefined...                  */
 215 t_bad36:TRAP_ENTRY(0x36, bad_trap_handler)   /* Undefined...                  */
 216 t_bad37:TRAP_ENTRY(0x37, bad_trap_handler)   /* Undefined...                  */
 217 t_bad38:TRAP_ENTRY(0x38, bad_trap_handler)   /* Undefined...                  */
 218 t_bad39:TRAP_ENTRY(0x39, bad_trap_handler)   /* Undefined...                  */
 219 t_bad3a:TRAP_ENTRY(0x3a, bad_trap_handler)   /* Undefined...                  */
 220 t_bad3b:TRAP_ENTRY(0x3b, bad_trap_handler)   /* Undefined...                  */
 221 t_iaccm:TRAP_ENTRY(0x3c, do_iacc_mmu_miss)   /* Instruction Access MMU-Miss   */
 222 t_bad3d:TRAP_ENTRY(0x3d, bad_trap_handler)   /* Undefined...                  */
 223 t_bad3e:TRAP_ENTRY(0x3e, bad_trap_handler)   /* Undefined...                  */
 224 t_bad3f:TRAP_ENTRY(0x3f, bad_trap_handler)   /* Undefined...                  */
 225 t_bad40:TRAP_ENTRY(0x40, bad_trap_handler)   /* Undefined...                  */
 226 t_bad41:TRAP_ENTRY(0x41, bad_trap_handler)   /* Undefined...                  */
 227 t_bad42:TRAP_ENTRY(0x42, bad_trap_handler)   /* Undefined...                  */
 228 t_bad43:TRAP_ENTRY(0x43, bad_trap_handler)   /* Undefined...                  */
 229 t_bad44:TRAP_ENTRY(0x44, bad_trap_handler)   /* Undefined...                  */
 230 t_bad45:TRAP_ENTRY(0x45, bad_trap_handler)   /* Undefined...                  */
 231 t_bad46:TRAP_ENTRY(0x46, bad_trap_handler)   /* Undefined...                  */
 232 t_bad47:TRAP_ENTRY(0x47, bad_trap_handler)   /* Undefined...                  */
 233 t_bad48:TRAP_ENTRY(0x48, bad_trap_handler)   /* Undefined...                  */
 234 t_bad49:TRAP_ENTRY(0x49, bad_trap_handler)   /* Undefined...                  */
 235 t_bad4a:TRAP_ENTRY(0x4a, bad_trap_handler)   /* Undefined...                  */
 236 t_bad4b:TRAP_ENTRY(0x4b, bad_trap_handler)   /* Undefined...                  */
 237 t_bad4c:TRAP_ENTRY(0x4c, bad_trap_handler)   /* Undefined...                  */
 238 t_bad4d:TRAP_ENTRY(0x4d, bad_trap_handler)   /* Undefined...                  */
 239 t_bad4e:TRAP_ENTRY(0x4e, bad_trap_handler)   /* Undefined...                  */
 240 t_bad4f:TRAP_ENTRY(0x4f, bad_trap_handler)   /* Undefined...                  */
 241 t_bad50:TRAP_ENTRY(0x50, bad_trap_handler)   /* Undefined...                  */
 242 t_bad51:TRAP_ENTRY(0x51, bad_trap_handler)   /* Undefined...                  */
 243 t_bad52:TRAP_ENTRY(0x52, bad_trap_handler)   /* Undefined...                  */
 244 t_bad53:TRAP_ENTRY(0x53, bad_trap_handler)   /* Undefined...                  */
 245 t_bad54:TRAP_ENTRY(0x54, bad_trap_handler)   /* Undefined...                  */
 246 t_bad55:TRAP_ENTRY(0x55, bad_trap_handler)   /* Undefined...                  */
 247 t_bad56:TRAP_ENTRY(0x56, bad_trap_handler)   /* Undefined...                  */
 248 t_bad57:TRAP_ENTRY(0x57, bad_trap_handler)   /* Undefined...                  */
 249 t_bad58:TRAP_ENTRY(0x58, bad_trap_handler)   /* Undefined...                  */
 250 t_bad59:TRAP_ENTRY(0x59, bad_trap_handler)   /* Undefined...                  */
 251 t_bad5a:TRAP_ENTRY(0x5a, bad_trap_handler)   /* Undefined...                  */
 252 t_bad5b:TRAP_ENTRY(0x5b, bad_trap_handler)   /* Undefined...                  */
 253 t_bad5c:TRAP_ENTRY(0x5c, bad_trap_handler)   /* Undefined...                  */
 254 t_bad5d:TRAP_ENTRY(0x5d, bad_trap_handler)   /* Undefined...                  */
 255 t_bad5e:TRAP_ENTRY(0x5e, bad_trap_handler)   /* Undefined...                  */
 256 t_bad5f:TRAP_ENTRY(0x5f, bad_trap_handler)   /* Undefined...                  */
 257 t_bad60:TRAP_ENTRY(0x60, bad_trap_handler)   /* Impl-Dep Exception            */
 258 t_bad61:TRAP_ENTRY(0x61, bad_trap_handler)   /* Impl-Dep Exception            */
 259 t_bad62:TRAP_ENTRY(0x62, bad_trap_handler)   /* Impl-Dep Exception            */
 260 t_bad63:TRAP_ENTRY(0x63, bad_trap_handler)   /* Impl-Dep Exception            */
 261 t_bad64:TRAP_ENTRY(0x64, bad_trap_handler)   /* Impl-Dep Exception            */
 262 t_bad65:TRAP_ENTRY(0x65, bad_trap_handler)   /* Impl-Dep Exception            */
 263 t_bad66:TRAP_ENTRY(0x66, bad_trap_handler)   /* Impl-Dep Exception            */
 264 t_bad67:TRAP_ENTRY(0x67, bad_trap_handler)   /* Impl-Dep Exception            */
 265 t_bad68:TRAP_ENTRY(0x68, bad_trap_handler)   /* Impl-Dep Exception            */
 266 t_bad69:TRAP_ENTRY(0x69, bad_trap_handler)   /* Impl-Dep Exception            */
 267 t_bad6a:TRAP_ENTRY(0x6a, bad_trap_handler)   /* Impl-Dep Exception            */
 268 t_bad6b:TRAP_ENTRY(0x6b, bad_trap_handler)   /* Impl-Dep Exception            */
 269 t_bad6c:TRAP_ENTRY(0x6c, bad_trap_handler)   /* Impl-Dep Exception            */
 270 t_bad6d:TRAP_ENTRY(0x6d, bad_trap_handler)   /* Impl-Dep Exception            */
 271 t_bad6e:TRAP_ENTRY(0x6e, bad_trap_handler)   /* Impl-Dep Exception            */
 272 t_bad6f:TRAP_ENTRY(0x6f, bad_trap_handler)   /* Impl-Dep Exception            */
 273 t_bad70:TRAP_ENTRY(0x70, bad_trap_handler)   /* Impl-Dep Exception            */
 274 t_bad71:TRAP_ENTRY(0x71, bad_trap_handler)   /* Impl-Dep Exception            */
 275 t_bad72:TRAP_ENTRY(0x72, bad_trap_handler)   /* Impl-Dep Exception            */
 276 t_bad73:TRAP_ENTRY(0x73, bad_trap_handler)   /* Impl-Dep Exception            */
 277 t_bad74:TRAP_ENTRY(0x74, bad_trap_handler)   /* Impl-Dep Exception            */
 278 t_bad75:TRAP_ENTRY(0x75, bad_trap_handler)   /* Impl-Dep Exception            */
 279 t_bad76:TRAP_ENTRY(0x76, bad_trap_handler)   /* Impl-Dep Exception            */
 280 t_bad77:TRAP_ENTRY(0x77, bad_trap_handler)   /* Impl-Dep Exception            */
 281 t_bad78:TRAP_ENTRY(0x78, bad_trap_handler)   /* Impl-Dep Exception            */
 282 t_bad79:TRAP_ENTRY(0x79, bad_trap_handler)   /* Impl-Dep Exception            */
 283 t_bad7a:TRAP_ENTRY(0x7a, bad_trap_handler)   /* Impl-Dep Exception            */
 284 t_bad7b:TRAP_ENTRY(0x7b, bad_trap_handler)   /* Impl-Dep Exception            */
 285 t_bad7c:TRAP_ENTRY(0x7c, bad_trap_handler)   /* Impl-Dep Exception            */
 286 t_bad7d:TRAP_ENTRY(0x7d, bad_trap_handler)   /* Impl-Dep Exception            */
 287 t_bad7e:TRAP_ENTRY(0x7e, bad_trap_handler)   /* Impl-Dep Exception            */
 288 t_bad7f:TRAP_ENTRY(0x7f, bad_trap_handler)   /* Impl-Dep Exception            */
 289 t_sunos:SUNOS_SYSCALL_TRAP                   /* SunOS System Call             */
 290 t_sbkpt:TRAP_ENTRY(0x81, bad_trap_handler)   /* Software Breakpoint           */
 291 t_divz: TRAP_ENTRY(0x82, bad_trap_handler)   /* Divide by zero trap           */
 292 t_flwin:TRAP_ENTRY(0x83, bad_trap_handler)   /* Flush Windows Trap            */
 293 t_clwin:TRAP_ENTRY(0x84, bad_trap_handler)   /* Clean Windows Trap            */
 294 t_rchk: TRAP_ENTRY(0x85, bad_trap_handler)   /* Range Check                   */
 295 t_funal:TRAP_ENTRY(0x86, bad_trap_handler)   /* Fix Unaligned Access Trap     */
 296 t_iovf: TRAP_ENTRY(0x87, bad_trap_handler)   /* Integer Overflow Trap         */
 297 t_slowl:SOLARIS_SYSCALL_TRAP                 /* Slowaris System Call          */
 298 t_netbs:NETBSD_SYSCALL_TRAP                  /* Net-B.S. System Call          */
 299 t_bad8a:TRAP_ENTRY(0x8a, bad_trap_handler)   /* Software Trap                 */
 300 t_bad8b:TRAP_ENTRY(0x8b, bad_trap_handler)   /* Software Trap                 */
 301 t_bad8c:TRAP_ENTRY(0x8c, bad_trap_handler)   /* Software Trap                 */
 302 t_bad8d:TRAP_ENTRY(0x8d, bad_trap_handler)   /* Software Trap                 */
 303 t_bad8e:TRAP_ENTRY(0x8e, bad_trap_handler)   /* Software Trap                 */
 304 t_bad8f:TRAP_ENTRY(0x8f, bad_trap_handler)   /* Software Trap                 */
 305 t_linux:LINUX_SYSCALL_TRAP                   /* Linux System Call             */
 306 t_bad91:TRAP_ENTRY(0x91, bad_trap_handler)   /* Software Trap                 */
 307 t_bad92:TRAP_ENTRY(0x92, bad_trap_handler)   /* Software Trap                 */
 308 t_bad93:TRAP_ENTRY(0x93, bad_trap_handler)   /* Software Trap                 */
 309 t_bad94:TRAP_ENTRY(0x94, bad_trap_handler)   /* Software Trap                 */
 310 t_bad95:TRAP_ENTRY(0x95, bad_trap_handler)   /* Software Trap                 */
 311 t_bad96:TRAP_ENTRY(0x96, bad_trap_handler)   /* Software Trap                 */
 312 t_bad97:TRAP_ENTRY(0x97, bad_trap_handler)   /* Software Trap                 */
 313 t_bad98:TRAP_ENTRY(0x98, bad_trap_handler)   /* Software Trap                 */
 314 t_bad99:TRAP_ENTRY(0x99, bad_trap_handler)   /* Software Trap                 */
 315 t_bad9a:TRAP_ENTRY(0x9a, bad_trap_handler)   /* Software Trap                 */
 316 t_bad9b:TRAP_ENTRY(0x9b, bad_trap_handler)   /* Software Trap                 */
 317 t_bad9c:TRAP_ENTRY(0x9c, bad_trap_handler)   /* Software Trap                 */
 318 t_bad9d:TRAP_ENTRY(0x9d, bad_trap_handler)   /* Software Trap                 */
 319 t_bad9e:TRAP_ENTRY(0x9e, bad_trap_handler)   /* Software Trap                 */
 320 t_bad9f:TRAP_ENTRY(0x9f, bad_trap_handler)   /* Software Trap                 */
 321 t_getcc:GETCC_TRAP                           /* Get Condition Codes           */
 322 t_setcc:SETCC_TRAP                           /* Set Condition Codes           */
 323 t_bada2:TRAP_ENTRY(0xa2, bad_trap_handler)   /* Software Trap                 */
 324 t_bada3:TRAP_ENTRY(0xa3, bad_trap_handler)   /* Software Trap                 */
 325 t_bada4:TRAP_ENTRY(0xa4, bad_trap_handler)   /* Software Trap                 */
 326 t_bada5:TRAP_ENTRY(0xa5, bad_trap_handler)   /* Software Trap                 */
 327 t_bada6:TRAP_ENTRY(0xa6, bad_trap_handler)   /* Software Trap                 */
 328 t_bada7:TRAP_ENTRY(0xa7, bad_trap_handler)   /* Software Trap                 */
 329 t_bada8:TRAP_ENTRY(0xa8, bad_trap_handler)   /* Software Trap                 */
 330 t_bada9:TRAP_ENTRY(0xa9, bad_trap_handler)   /* Software Trap                 */
 331 t_badaa:TRAP_ENTRY(0xaa, bad_trap_handler)   /* Software Trap                 */
 332 t_badab:TRAP_ENTRY(0xab, bad_trap_handler)   /* Software Trap                 */
 333 t_badac:TRAP_ENTRY(0xac, bad_trap_handler)   /* Software Trap                 */
 334 t_badad:TRAP_ENTRY(0xad, bad_trap_handler)   /* Software Trap                 */
 335 t_badae:TRAP_ENTRY(0xae, bad_trap_handler)   /* Software Trap                 */
 336 t_badaf:TRAP_ENTRY(0xaf, bad_trap_handler)   /* Software Trap                 */
 337 t_badb0:TRAP_ENTRY(0xb0, bad_trap_handler)   /* Software Trap                 */
 338 t_badb1:TRAP_ENTRY(0xb1, bad_trap_handler)   /* Software Trap                 */
 339 t_badb2:TRAP_ENTRY(0xb2, bad_trap_handler)   /* Software Trap                 */
 340 t_badb3:TRAP_ENTRY(0xb3, bad_trap_handler)   /* Software Trap                 */
 341 t_badb4:TRAP_ENTRY(0xb4, bad_trap_handler)   /* Software Trap                 */
 342 t_badb5:TRAP_ENTRY(0xb5, bad_trap_handler)   /* Software Trap                 */
 343 t_badb6:TRAP_ENTRY(0xb6, bad_trap_handler)   /* Software Trap                 */
 344 t_badb7:TRAP_ENTRY(0xb7, bad_trap_handler)   /* Software Trap                 */
 345 t_badb8:TRAP_ENTRY(0xb8, bad_trap_handler)   /* Software Trap                 */
 346 t_badb9:TRAP_ENTRY(0xb9, bad_trap_handler)   /* Software Trap                 */
 347 t_badba:TRAP_ENTRY(0xba, bad_trap_handler)   /* Software Trap                 */
 348 t_badbb:TRAP_ENTRY(0xbb, bad_trap_handler)   /* Software Trap                 */
 349 t_badbc:TRAP_ENTRY(0xbc, bad_trap_handler)   /* Software Trap                 */
 350 t_badbd:TRAP_ENTRY(0xbd, bad_trap_handler)   /* Software Trap                 */
 351 t_badbe:TRAP_ENTRY(0xbe, bad_trap_handler)   /* Software Trap                 */
 352 t_badbf:TRAP_ENTRY(0xbf, bad_trap_handler)   /* Software Trap                 */
 353 t_badc0:TRAP_ENTRY(0xc0, bad_trap_handler)   /* Software Trap                 */
 354 t_badc1:TRAP_ENTRY(0xc1, bad_trap_handler)   /* Software Trap                 */
 355 t_badc2:TRAP_ENTRY(0xc2, bad_trap_handler)   /* Software Trap                 */
 356 t_badc3:TRAP_ENTRY(0xc3, bad_trap_handler)   /* Software Trap                 */
 357 t_badc4:TRAP_ENTRY(0xc4, bad_trap_handler)   /* Software Trap                 */
 358 t_badc5:TRAP_ENTRY(0xc5, bad_trap_handler)   /* Software Trap                 */
 359 t_badc6:TRAP_ENTRY(0xc6, bad_trap_handler)   /* Software Trap                 */
 360 t_badc7:TRAP_ENTRY(0xc7, bad_trap_handler)   /* Software Trap                 */
 361 t_badc8:TRAP_ENTRY(0xc8, bad_trap_handler)   /* Software Trap                 */
 362 t_badc9:TRAP_ENTRY(0xc9, bad_trap_handler)   /* Software Trap                 */
 363 t_badca:TRAP_ENTRY(0xca, bad_trap_handler)   /* Software Trap                 */
 364 t_badcb:TRAP_ENTRY(0xcb, bad_trap_handler)   /* Software Trap                 */
 365 t_badcc:TRAP_ENTRY(0xcc, bad_trap_handler)   /* Software Trap                 */
 366 t_badcd:TRAP_ENTRY(0xcd, bad_trap_handler)   /* Software Trap                 */
 367 t_badce:TRAP_ENTRY(0xce, bad_trap_handler)   /* Software Trap                 */
 368 t_badcf:TRAP_ENTRY(0xcf, bad_trap_handler)   /* Software Trap                 */
 369 t_badd0:TRAP_ENTRY(0xd0, bad_trap_handler)   /* Software Trap                 */
 370 t_badd1:TRAP_ENTRY(0xd1, bad_trap_handler)   /* Software Trap                 */
 371 t_badd2:TRAP_ENTRY(0xd2, bad_trap_handler)   /* Software Trap                 */
 372 t_badd3:TRAP_ENTRY(0xd3, bad_trap_handler)   /* Software Trap                 */
 373 t_badd4:TRAP_ENTRY(0xd4, bad_trap_handler)   /* Software Trap                 */
 374 t_badd5:TRAP_ENTRY(0xd5, bad_trap_handler)   /* Software Trap                 */
 375 t_badd6:TRAP_ENTRY(0xd6, bad_trap_handler)   /* Software Trap                 */
 376 t_badd7:TRAP_ENTRY(0xd7, bad_trap_handler)   /* Software Trap                 */
 377 t_badd8:TRAP_ENTRY(0xd8, bad_trap_handler)   /* Software Trap                 */
 378 t_badd9:TRAP_ENTRY(0xd9, bad_trap_handler)   /* Software Trap                 */
 379 t_badda:TRAP_ENTRY(0xda, bad_trap_handler)   /* Software Trap                 */
 380 t_baddb:TRAP_ENTRY(0xdb, bad_trap_handler)   /* Software Trap                 */
 381 t_baddc:TRAP_ENTRY(0xdc, bad_trap_handler)   /* Software Trap                 */
 382 t_baddd:TRAP_ENTRY(0xdd, bad_trap_handler)   /* Software Trap                 */
 383 t_badde:TRAP_ENTRY(0xde, bad_trap_handler)   /* Software Trap                 */
 384 t_baddf:TRAP_ENTRY(0xdf, bad_trap_handler)   /* Software Trap                 */
 385 t_bade0:TRAP_ENTRY(0xe0, bad_trap_handler)   /* Software Trap                 */
 386 t_bade1:TRAP_ENTRY(0xe1, bad_trap_handler)   /* Software Trap                 */
 387 t_bade2:TRAP_ENTRY(0xe2, bad_trap_handler)   /* Software Trap                 */
 388 t_bade3:TRAP_ENTRY(0xe3, bad_trap_handler)   /* Software Trap                 */
 389 t_bade4:TRAP_ENTRY(0xe4, bad_trap_handler)   /* Software Trap                 */
 390 t_bade5:TRAP_ENTRY(0xe5, bad_trap_handler)   /* Software Trap                 */
 391 t_bade6:TRAP_ENTRY(0xe6, bad_trap_handler)   /* Software Trap                 */
 392 t_bade7:TRAP_ENTRY(0xe7, bad_trap_handler)   /* Software Trap                 */
 393 t_bade8:TRAP_ENTRY(0xe8, bad_trap_handler)   /* Software Trap                 */
 394 t_bade9:TRAP_ENTRY(0xe9, bad_trap_handler)   /* Software Trap                 */
 395 t_badea:TRAP_ENTRY(0xea, bad_trap_handler)   /* Software Trap                 */
 396 t_badeb:TRAP_ENTRY(0xeb, bad_trap_handler)   /* Software Trap                 */
 397 t_badec:TRAP_ENTRY(0xec, bad_trap_handler)   /* Software Trap                 */
 398 t_baded:TRAP_ENTRY(0xed, bad_trap_handler)   /* Software Trap                 */
 399 t_badee:TRAP_ENTRY(0xee, bad_trap_handler)   /* Software Trap                 */
 400 t_badef:TRAP_ENTRY(0xef, bad_trap_handler)   /* Software Trap                 */
 401 t_badf0:TRAP_ENTRY(0xf0, bad_trap_handler)   /* Software Trap                 */
 402 t_badf1:TRAP_ENTRY(0xf1, bad_trap_handler)   /* Software Trap                 */
 403 t_badf2:TRAP_ENTRY(0xf2, bad_trap_handler)   /* Software Trap                 */
 404 t_badf3:TRAP_ENTRY(0xf3, bad_trap_handler)   /* Software Trap                 */
 405 t_badf4:TRAP_ENTRY(0xf4, bad_trap_handler)   /* Software Trap                 */
 406 t_badf5:TRAP_ENTRY(0xf5, bad_trap_handler)   /* Software Trap                 */
 407 t_badf6:TRAP_ENTRY(0xf6, bad_trap_handler)   /* Software Trap                 */
 408 t_badf7:TRAP_ENTRY(0xf7, bad_trap_handler)   /* Software Trap                 */
 409 t_badf8:TRAP_ENTRY(0xf8, bad_trap_handler)   /* Software Trap                 */
 410 t_badf9:TRAP_ENTRY(0xf9, bad_trap_handler)   /* Software Trap                 */
 411 t_badfa:TRAP_ENTRY(0xfa, bad_trap_handler)   /* Software Trap                 */
 412 t_badfb:TRAP_ENTRY(0xfb, bad_trap_handler)   /* Software Trap                 */
 413 t_badfc:TRAP_ENTRY(0xfc, bad_trap_handler)   /* Software Trap                 */
 414 t_badfd:TRAP_ENTRY(0xfd, bad_trap_handler)   /* Software Trap                 */
 415 dbtrap: TRAP_ENTRY(0xfe, bad_trap_handler)   /* Debugger/PROM breakpoint #1   */
 416 dbtrap2:TRAP_ENTRY(0xff, bad_trap_handler)   /* Debugger/PROM breakpoint #2   */        
 417 
 418         .globl  C_LABEL(end_traptable)
 419 C_LABEL(end_traptable):
 420 
 421         .skip 4096
 422 
 423 /* This was the only reasonable way I could think of to properly align
 424  * these page-table data structures.
 425  *
 426  * XXX swapper_pg_dir is going to have to be 'per-CPU' for SMP support
 427  */
 428 
 429         .globl C_LABEL(auxio_reg_addr)
 430 C_LABEL(auxio_reg_addr):        .skip   (PAGE_SIZE)
 431 
 432         .globl C_LABEL(clock_reg_addr)
 433 C_LABEL(clock_reg_addr):        .skip   (PAGE_SIZE*5)
 434 
 435         .globl C_LABEL(int_reg_addr)
 436 C_LABEL(int_reg_addr):          .skip   (PAGE_SIZE*5)
 437 
 438         .globl C_LABEL(pg0)
 439         .globl C_LABEL(empty_bad_page)
 440         .globl C_LABEL(empty_bad_page_table)
 441         .globl C_LABEL(empty_zero_page)
 442         .globl C_LABEL(swapper_pg_dir)
 443 C_LABEL(swapper_pg_dir):                .skip 0x1000
 444 C_LABEL(pg0):                           .skip 0x1000
 445 C_LABEL(empty_bad_page):                .skip 0x1000
 446 C_LABEL(empty_bad_page_table):          .skip 0x1000
 447 C_LABEL(empty_zero_page):               .skip 0x1000
 448 
 449 
 450 /* Cool, here we go. Pick up the romvec pointer in %o0 and stash it in
 451  * %g7 and at prom_vector_p. And also quickly check whether we are on
 452  * a v0, v2, or v3 prom.  We also get a debug structure of some sort from
 453  * the boot loader (or is it the prom?) in %o1.  Finally a call back vector
 454  * is passed in %o2.  I think this is how you register yourself with a
 455  * debugger.  I do know that it wants my %o7 (return PC - 8) as it's
 456  * first argument.  I will poke around and figure out what the debug
 457  * vector is, it could contain useful stuff.
 458  */
 459 
 460 /* Grrr, in order to be Sparc ABI complient, the kernel has to live in
 461  * an address space above 0xe0000000  ;(  Must remain position independant
 462  * until we 'remap' ourselves from low to high addresses.  We only map the
 463  * first 3MB of addresses into upper ram as that is how much the PROM
 464  * promises to set up for us.
 465  */
 466 gokernel:
 467                 /* Ok, it's nice to know, as early as possible, if we
 468                  * are already mapped where we expect to be in virtual
 469                  * memory.  The Solaris /boot elf format bootloader
 470                  * will peek into our elf header and load us where
 471                  * we want to be, otherwise we have to re-map.
 472                  *
 473                  * Some boot loaders don't place the jmp'rs address
 474                  * in %o7, so we do a pc-relative call to a local
 475                  * label, then see what %o7 has.
 476                  */
 477 
 478                 /* XXX Sparc V9 detection goes here XXX */
 479 
 480                 or      %g0, %o7, %g4           ! Save %o7
 481 
 482                 /* Jump to it, and pray... */
 483 current_pc:
 484                 call    1f
 485                 nop
 486 
 487 1:
 488                 or      %g0, %o7, %g3
 489 
 490 got_pc:
 491                 or      %g0, %g4, %o7   /* Previous %o7. */
 492         
 493                 or      %g0, %o0, %l0           ! stash away romvec
 494                 or      %g0, %o0, %g7           ! put it here too
 495                 or      %g0, %o1, %l1           ! stash away debug_vec too
 496                 rd      %psr, %l2               ! Save psr
 497                 rd      %wim, %l3               ! wim
 498                 rd      %tbr, %l4               ! tbr
 499                 or      %g0, %o2, %l5           ! and the possible magic func
 500 
 501                 /* Ok, let's check out our run time program counter. */
 502                 set     current_pc, %g5
 503                 cmp     %g3, %g5
 504                 be      already_mapped
 505 
 506                 /* %l6 will hold the offset we have to subtract
 507                  * from absolute symbols in order to access areas
 508                  * in our own image.  If already mapped this is
 509                  * just plain zero, else it is PAGE_OFFSET which is
 510                  * also KERNBASE.
 511                  */
 512                 set     PAGE_OFFSET, %l6
 513                 b       copy_prom_lvl14
 514                 nop
 515 
 516 already_mapped:
 517                 or      %g0, %g0, %l6
 518 
 519                 /* Copy over the Prom's level 14 clock handler. */
 520 copy_prom_lvl14:
 521                 rd      %tbr, %g1
 522                 andn    %g1, 0xfff, %g1         ! proms trap table base
 523                 or      %g0, (0x1e<<4), %g2     ! offset to lvl14 intr
 524                 or      %g1, %g2, %g2
 525                 set     t_irq14, %g3
 526                 sub     %g3, %l6, %g3
 527                 ldd     [%g2], %g4
 528                 std     %g4, [%g3]
 529                 ldd     [%g2 + 0x8], %g4
 530                 std     %g4, [%g3 + 0x8]        ! Copy proms handler
 531 
 532                 /* Copy over the Prom/debugger's trap entry points. */
 533 copy_prom_bpoint:
 534                 or      %g0, (0xfe<<4), %g2
 535                 or      %g1, %g2, %g2
 536                 set     dbtrap, %g3
 537                 sub     %g3, %l6, %g3
 538                 ldd     [%g2], %g4
 539                 std     %g4, [%g3]
 540                 ldd     [%g2 + 0x8], %g4
 541                 std     %g4, [%g3 + 0x8]
 542                 ldd     [%g2 + 0x10], %g4
 543                 std     %g4, [%g3 + 0x10]
 544                 ldd     [%g2 + 0x18], %g4
 545                 std     %g4, [%g3 + 0x18]
 546 
 547 copy_prom_done:
 548                 ld      [%o0 + 0x4], %g1
 549                 and     %g1, 0x3, %g1
 550                 subcc   %g1, 0x0, %g0
 551                 be      set_sane_psr            ! Not on v0 proms
 552                 nop
 553 
 554                 subcc   %o2, 0x0, %g0           ! check for boot routine pointer
 555                 bz      set_sane_psr
 556                 nop
 557                 jmpl    %o2, %o7                ! call boot setup func
 558                 add     %o7, 0x8, %o0
 559 
 560 set_sane_psr:
 561                 /* Traps are on, kadb can be tracing through here.  But
 562                  * we have no clue what the PIL is. So we set up a sane
 563                  * %psr, but preserve CWP or our locals could disappear!
 564                  */
 565                 rd      %psr, %g2
 566                 and     %g2, 0x1f, %g2                  ! %g2 has CWP now
 567                 set     (PSR_S|PSR_PIL), %g1            ! Supervisor + PIL high
 568                 or      %g1, %g2, %g1                   ! mix mix mix
 569                 wr      %g1, 0x0, %psr                  ! let PIL set in
 570                 wr      %g1, PSR_ET, %psr               ! now turn on traps
 571 
 572                 /* A note about the last two instructions...
 573                  * If you are going to increase PIL and turn on
 574                  * traps at the same time you are asking for trouble.
 575                  * You MUST set a %psr with traps off containing
 576                  * your new PIL, then turn on the ET bit with the
 577                  * next write.  On certain buggy Sparc chips if you
 578                  * set both at the same time you can get a Watchdog
 579                  * Reset under certain conditions.  This is no fun.
 580                  * Basically the PIL bits get there before the
 581                  * EnableTrap bit does or something like that.
 582                  */
 583 
 584                 /* Insane asylum... */
 585                 WRITE_PAUSE
 586 
 587 /* Must determine whether we are on a sun4c MMU, SRMMU, or SUN4/400 MUTANT
 588  * MMU so we can remap ourselves properly.  DONT TOUCH %l0 thru %l5 in these
 589  * remapping routines, we need their values afterwards!
 590  *
 591  * XXX UGH, need to write some sun4u SpitFire remapping V9 code RSN... XXX
 592  */
 593                 /* Now check whether we are already mapped, if we
 594                  * are we can skip all this garbage coming up.
 595                  */
 596                 subcc   %l6, 0x0, %g0
 597                 bz      go_to_highmem           ! this will be a nop then
 598                 nop
 599 
 600                 sethi   %hi(LOAD_ADDR), %g6
 601                 subcc   %g7, %g6, %g0
 602                 bne     remap_not_a_sun4        ! This is not a Sun4
 603                 nop
 604 
 605                 or      %g0, 0x1, %g1
 606                 lduba   [%g1] ASI_CONTROL, %g1  ! Only safe to try on Sun4.
 607                 subcc   %g1, 0x24, %g0          ! Is this a mutant Sun4/400???
 608                 be      sun4_mutant_remap       ! Ugh, it is...
 609                 nop
 610 
 611 remap_not_a_sun4:
 612                 lda     [%g0] ASI_M_MMUREGS, %g1 ! same as ASI_PTE on sun4c
 613                 and     %g1, 0x1, %g1           ! Test SRMMU Enable bit ;-)
 614                 subcc   %g1, 0x0, %g0
 615                 bz      sun4c_remap             ! A sun4c MMU or normal Sun4
 616                 nop
 617 srmmu_remap:
 618                 /* First, check for a viking (TI) module. */
 619                 set     0x40000000, %g2
 620                 rd      %psr, %g3
 621                 and     %g2, %g3, %g3
 622                 subcc   %g3, 0x0, %g0
 623                 bz      srmmu_nviking
 624                 nop
 625 
 626                 /* Figure out what kind of viking we are on.
 627                  * We need to know if we have to play with the
 628                  * AC bit and disable traps or not.
 629                  */
 630 
 631                 /* I've only seen MicroSparc's on SparcClassics with this
 632                  * bit set.
 633                  */
 634                 set     0x800, %g2
 635                 lda     [%g0] ASI_M_MMUREGS, %g3        ! peek in the control reg
 636                 and     %g2, %g3, %g3
 637                 subcc   %g3, 0x0, %g0
 638                 bnz     srmmu_nviking                   ! is in mbus mode
 639                 nop
 640                 
 641                 rd      %psr, %g3                       ! DONT TOUCH %g3
 642                 andn    %g3, PSR_ET, %g2
 643                 wr      %g2, 0x0, %psr
 644                 WRITE_PAUSE
 645                 
 646                 /* Get context table pointer, then convert to
 647                  * a physical address, which is 36 bits.
 648                  */
 649                 set     AC_M_CTPR, %g4
 650                 lda     [%g4] ASI_M_MMUREGS, %g4
 651                 sll     %g4, 0x4, %g4                   ! We use this below
 652                                                         ! DONT TOUCH %g4
 653 
 654                 /* Set the AC bit in the Viking's MMU control reg. */
 655                 lda     [%g0] ASI_M_MMUREGS, %g5        ! DONT TOUCH %g5
 656                 set     0x8000, %g6                     ! AC bit mask
 657                 or      %g5, %g6, %g6                   ! Or it in...
 658                 sta     %g6, [%g0] ASI_M_MMUREGS        ! Close your eyes...
 659 
 660                 /* Grrr, why does it seem like every other load/store
 661                  * on the sun4m is in some ASI space...
 662                  * Fine with me, let's get the pointer to the level 1
 663                  * page table directory and fetch it's entry.
 664                  */
 665                 lda     [%g4] ASI_M_BYPASS, %o1         ! This is a level 1 ptr
 666                 srl     %o1, 0x4, %o1                   ! Clear low 4 bits
 667                 sll     %o1, 0x8, %o1                   ! Make physical
 668                 
 669                 /* Ok, pull in the PTD. */
 670                 lda     [%o1] ASI_M_BYPASS, %o2         ! This is the 0x0 16MB pgd
 671 
 672                 /* Calculate to KERNBASE entry.
 673                  *
 674                  * XXX Should not use imperical constant, but Gas gets an  XXX
 675                  * XXX upset stomach with the bitshift I would have to use XXX
 676                  */
 677                 add     %o1, 0x3c0, %o3         
 678 
 679                 /* Poke the entry into the calculated address. */
 680                 sta     %o2, [%o3] ASI_M_BYPASS
 681 
 682                 /* I don't get it Sun, if you engineered all these
 683                  * boot loaders and the PROM (thank you for the debugging
 684                  * features btw) why did you not have them load kernel
 685                  * images up in high address space, since this is necessary
 686                  * for ABI compliance anyways?  Does this low-mapping provide
 687                  * enhanced interoperability?
 688                  *
 689                  * "The PROM is the computer."
 690                  */
 691 
 692                 /* Ok, restore the MMU control register we saved in %g5 */
 693                 sta     %g5, [%g0] ASI_M_MMUREGS        ! POW... ouch
 694 
 695                 /* Turn traps back on.  We saved it in %g3 earlier. */
 696                 wr      %g3, 0x0, %psr                  ! tick tock, tick tock
 697 
 698                 /* Now we burn precious CPU cycles due to bad engineering. */
 699                 WRITE_PAUSE
 700 
 701                 /* Wow, all that just to move a 32-bit value from one
 702                  * place to another...  Jump to high memory.
 703                  */
 704                 b       go_to_highmem
 705                 nop
 706 
 707                 /* This works on viking's in Mbus mode and all
 708                  * other MBUS modules.  It is virtually the same as
 709                  * the above madness sans turning traps off and flipping
 710                  * the AC bit.
 711                  */
 712 srmmu_nviking:
 713                 set     AC_M_CTPR, %g1
 714                 lda     [%g1] ASI_M_MMUREGS, %g1        ! get ctx table ptr
 715                 sll     %g1, 0x4, %g1                   ! make physical addr
 716                 lda     [%g1] ASI_M_BYPASS, %g1         ! ptr to level 1 pg_table
 717                 srl     %g1, 0x4, %g1
 718                 sll     %g1, 0x8, %g1                   ! make phys addr for l1 tbl
 719 
 720                 lda     [%g1] ASI_M_BYPASS, %g2         ! get level1 entry for 0x0
 721                 add     %g1, 0x3c0, %g3                 ! XXX AWAY WITH IMPERICALS
 722                 sta     %g2, [%g3] ASI_M_BYPASS         ! place at KERNBASE entry
 723                 b       go_to_highmem
 724                 nop                                     ! wheee....
 725 
 726                 /* This remaps the kernel on Sun4/4xx machines
 727                  * that have the Sun Mutant Three Level MMU.
 728                  * It's like a platypus, Sun didn't have the
 729                  * SRMMU in conception so they kludged the three
 730                  * level logic in the regular Sun4 MMU probably.
 731                  *
 732                  * Basically, you take each entry in the top level
 733                  * directory that maps the low 3MB starting at
 734                  * address zero and put the mapping in the KERNBASE
 735                  * slots.  These top level pgd's are called regmaps.
 736                  */
 737 sun4_mutant_remap:
 738                 or      %g0, %g0, %g3           ! source base
 739                 sethi   %hi(KERNBASE), %g4      ! destination base
 740                 or      %g4, %lo(KERNBASE), %g4
 741                 sethi   %hi(0x300000), %g5
 742                 or      %g5, %lo(0x300000), %g5 ! upper bound 3MB
 743                 or      %g0, 0x1, %l6
 744                 sll     %l6, 24, %l6            ! Regmap mapping size
 745                 add     %g3, 0x2, %g3           ! Base magic
 746                 add     %g4, 0x2, %g4           ! Base magic
 747 
 748                 /* Main remapping loop on Sun4-Mutant-MMU.
 749                  * "I am not an animal..." -Famous Mutant Person
 750                  */
 751 sun4_mutant_loop:
 752                 lduha   [%g3] ASI_REGMAP, %g2   ! Get lower entry
 753                 stha    %g2, [%g4] ASI_REGMAP   ! Store in high entry
 754                 add     %g4, %l6, %g4           ! Move up high memory ptr
 755                 subcc   %g3, %g5, %g0           ! Reached our limit?
 756                 blu     sun4_mutant_loop        ! Nope, loop again
 757                 add     %g3, %l6, %g3           ! delay, Move up low ptr
 758                 b       go_to_highmem           ! Jump to high memory.
 759                 nop
 760 
 761 /* The following works for normal (ie. non Sun4/400) Sun4 MMU's */
 762 sun4c_remap:
 763                 or      %g0, %g0, %g3           ! source base
 764                 sethi   %hi(KERNBASE), %g4      ! destination base
 765                 or      %g4, %lo(KERNBASE), %g4
 766                 sethi   %hi(0x300000), %g5
 767                 or      %g5, %lo(0x300000), %g5 ! upper bound 3MB
 768                 or      %g0, 0x1, %l6
 769                 sll     %l6, 18, %l6            ! sun4c mmu segmap size
 770 sun4c_remap_loop:
 771                 lda     [%g3] ASI_SEGMAP, %g6   ! load phys_seg
 772                 sta     %g6, [%g4] ASI_SEGMAP   ! store new virt mapping
 773                 add     %g3, %l6, %g3           ! Increment source ptr
 774                 subcc   %g3, %g5, %g0           ! Reached limit?
 775                 bl      sun4c_remap_loop        ! Nope, loop again
 776                 add     %g4, %l6, %g4           ! delay, Increment dest ptr
 777 
 778 /* Now do a non-relative jump so that PC is in high-memory */
 779 go_to_highmem:
 780                 set     execute_in_high_mem, %g1
 781                 jmp     %g1
 782                 nop
 783 
 784 /* Acquire boot time privileged register values, this will help debugging.
 785  * I figure out and store nwindows and nwindowsm1 later on.
 786  */
 787 execute_in_high_mem:
 788                 or      %g0, %l0, %o0           ! put back romvec
 789                 or      %g0, %l1, %o1           ! and debug_vec
 790 
 791                 sethi   %hi( C_LABEL(prom_vector_p) ), %g1
 792                 st      %o0, [%g1 + %lo( C_LABEL(prom_vector_p) )]
 793 
 794                 sethi   %hi( C_LABEL(linux_dbvec) ), %g1
 795                 st      %o1, [%g1 + %lo( C_LABEL(linux_dbvec) )]
 796 
 797                 ld      [%o0 + 0x4], %o3
 798                 and     %o3, 0x3, %o5                   ! get the version
 799 
 800                 subcc   %o3, 0x2, %g0                   ! a v2 prom?
 801                 be      found_version
 802                 nop
 803 
 804                 /* paul@sfe.com.au */
 805                 subcc   %o3, 0x3, %g0                   ! a v3 prom?
 806                 be      found_version
 807                 nop
 808 
 809 /* Old sun4's pass our load address into %o0 instead of the prom
 810  * pointer. On sun4's you have to hard code the romvec pointer into
 811  * your code. Sun probably still does that because they don't even
 812  * trust their own "OpenBoot" specifications.
 813  */
 814 
 815                 sethi   %hi(LOAD_ADDR), %g6
 816                 subcc   %o0, %g6, %g0           ! an old sun4?
 817                 be      no_sun4_here
 818                 nop
 819 
 820 found_version:
 821 
 822 /* Get the machine type via the mysterious romvec node operations.
 823  * Here we can find out whether we are on a sun4, sun4c, sun4m, 
 824  * sun4d, or a sun4e. The "nodes" are set up as a bunch of n-ary trees 
 825  * which you can traverse to get information about devices and such.
 826  * The information acquisition happens via the node-ops which are
 827  * defined in the openprom.h header file. Of particular interest
 828  * is the 'nextnode(int node)' function as it does the smart thing when
 829  * presented with a value of '0', it gives you the root node in the
 830  * tree. These node integers probably offset into some internal prom
 831  * pointer table the openboot has. It's completely undocumented, so
 832  * I'm not about to go sifting through the prom address space, but may
 833  * do so if I get suspicious enough. :-)
 834  */
 835 
 836                 or      %g0, %g7, %l1
 837                 add     %l1, 0x1c, %l1          
 838                 ld      [%l1], %l0
 839                 ld      [%l0], %l0
 840                 call    %l0
 841                 or      %g0, %g0, %o0           ! next_node(0) = first_node
 842                 or      %o0, %g0, %g6
 843 
 844                 sethi   %hi( C_LABEL(cputypvar) ), %o1  ! First node has cpu-arch
 845                 or      %o1, %lo( C_LABEL(cputypvar) ), %o1
 846                 sethi   %hi( C_LABEL(cputypval) ), %o2  ! information, the string
 847                 or      %o2, %lo( C_LABEL(cputypval) ), %o2
 848                 ld      [%l1], %l0              ! 'compatibility' tells
 849                 ld      [%l0 + 0xc], %l0        ! that we want 'sun4x' where
 850                 call    %l0                     ! x is one of '', 'c', 'm',
 851                 nop                             ! 'd' or 'e'. %o2 holds pointer
 852                                                 ! to a buf where above string
 853                                                 ! will get stored by the prom.
 854 
 855                 subcc   %o0, %g0, %g0
 856                 bpos    got_prop                ! Got the property
 857                 nop
 858 
 859                 or      %g6, %g0, %o0
 860                 sethi   %hi( C_LABEL(cputypvar_sun4m) ), %o1
 861                 or      %o1, %lo( C_LABEL(cputypvar_sun4m) ), %o1
 862                 sethi   %hi( C_LABEL(cputypval) ), %o2
 863                 or      %o2, %lo( C_LABEL(cputypval) ), %o2
 864                 ld      [%l1], %l0
 865                 ld      [%l0 + 0xc], %l0
 866                 call    %l0
 867                 nop
 868 
 869 got_prop:
 870                 sethi   %hi( C_LABEL(cputypval) ), %o2
 871                 or      %o2, %lo( C_LABEL(cputypval) ), %o2
 872 
 873                 ldub    [%o2 + 0x4], %l1
 874                 subcc   %l1, 'c', %g0           ! We already know we are not
 875                 be      1f                      ! on a plain sun4 because of
 876                 nop                             ! the check for 0x4000 in %o0
 877                 subcc   %l1, 'm', %g0           ! at start
 878                 be      1f
 879                 nop
 880 
 881                 subcc   %l1, 'd', %g0
 882                 be      no_sun4d_here           ! God bless the person who
 883                 nop                             ! tried to run this on sun4d.
 884         
 885                 subcc   %l1, 'e', %g0
 886                 be      no_sun4e_here           ! Could be a sun4e.
 887                 nop
 888 
 889                 b       no_sun4u_here           ! AIEEE, a V9 sun4u...
 890                 nop
 891 
 892 
 893 1:
 894                 or      %g0, PAGE_SHIFT, %g5
 895 
 896                 sethi   %hi( C_LABEL(cputypval) ), %l1
 897                 or      %l1, %lo( C_LABEL(cputypval) ), %l1
 898                 ldub    [%l1 + 0x4], %l1
 899                 subcc   %l1, 'm', %g0           ! Test for sun4d, sun4e ?
 900                 be      sun4m_init
 901                 nop
 902 
 903                 sethi   %hi(AC_CONTEXT), %g1    ! kernel context, safe now
 904                                                 ! the only valid context
 905                                                 ! until we call paging_init()
 906                 stba    %g0, [%g1] ASI_CONTROL
 907 
 908                 b       sun4c_continue_boot
 909                 nop
 910 
 911 sun4m_init:
 912 /* P3: I just do not know what to do here. But I do know that ASI_CONTROL
 913  * will not serve on sun4m. Also I do not want to smash the current MMU
 914  * setup until we call paging_init().
 915  */
 916 
 917 /* Ok, the PROM could have done funny things and apple cider could still
 918  * be sitting in the fault status/address registers.  Read them all to
 919  * clear them so we don't get magic faults later on.
 920  */
 921 /* This sucks, aparently this makes Vikings call prom panic, will fix later */
 922 
 923                 set     (0x40000000), %o1
 924                 rd      %psr, %o0
 925                 andcc   %o0, %o1, %g0
 926                 bne     sun4c_continue_boot     ! quick hack
 927                 nop
 928 
 929 clr_srmmu_fregs:
 930                 set     AC_M_SFSR, %o0
 931                 lda     [%o0] ASI_M_MMUREGS, %g0
 932                 set     AC_M_SFAR, %o0
 933                 lda     [%o0] ASI_M_MMUREGS, %g0
 934                 set     AC_M_AFSR, %o0
 935                 lda     [%o0] ASI_M_MMUREGS, %g0
 936                 set     AC_M_AFAR, %o0
 937                 lda     [%o0] ASI_M_MMUREGS, %g0
 938                 nop
 939 
 940 
 941 sun4c_continue_boot:
 942 
 943 
 944 /* Aieee, now set PC and nPC, enable traps, give ourselves a stack and it's
 945  * show-time!
 946  */
 947 
 948                 sethi   %hi( C_LABEL(cputyp) ), %o0
 949                 st      %g4, [%o0 + %lo( C_LABEL(cputyp) )]
 950 
 951                 /* Turn on PreviousSupervisor, Supervisor, EnableFloating,
 952                  * and all the PIL bits.  Also puts us in register window
 953                  * zero.
 954                  */
 955                 sethi   %hi(PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
 956                 or      %g2, %lo(PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
 957                 wr      %g2, 0x0, %psr
 958                 WRITE_PAUSE
 959 
 960                 wr      %g0, 0x2, %wim          ! Make window 1 invalid.
 961                 WRITE_PAUSE
 962 
 963                 /* Initialize the WIM value for init_task. */
 964                 or      %g0, 0x1, %g1
 965                 sethi   %hi( C_LABEL(current) + THREAD_WIM), %g2
 966                 st      %g1, [%g2 + %lo( C_LABEL(current) + THREAD_WIM)]
 967 
 968 /* I want a kernel stack NOW! */
 969 /* Grrr, gotta be real careful about alignment here */
 970 
 971                 set     ( C_LABEL(init_user_stack) + PAGE_SIZE - 96 - 96 - 80), %g1
 972                 andn    %g1, 0x7, %g1
 973                 or      %g1, 0x0, %fp
 974                 add     %fp, (96+80), %sp
 975 
 976                 /* Enable traps. */
 977                 rd      %psr, %l0
 978                 wr      %l0, PSR_ET, %psr
 979                 WRITE_PAUSE
 980 
 981 /*
 982  * Maybe the prom zeroes out our BSS section, maybe it doesn't. I certainly 
 983  * don't know, do you?
 984  */
 985 
 986                 set     C_LABEL(edata) , %o0    ! First address of BSS
 987                 set     C_LABEL(end) , %o1      ! Last address of BSS
 988 
 989                 /* Argh, ELF gets me again... */
 990                 andn    %o0, 0x3, %o0
 991                 andn    %o1, 0x3, %o1
 992 
 993 /* Friggin' bzero() kludge. */
 994 
 995 1:      
 996                 st      %g0, [%o0]
 997                 add     %o0, 0x4, %o0
 998                 subcc   %o0, %o1, %g0
 999                 bl      1b
1000                 nop
1001 
1002 /* Compute NWINDOWS and stash it away. Now uses %wim trick explained
1003  * in the V8 manual. Ok, this method seems to work, Sparc is cool...
1004  * No, it doesn't work, have to play the save/readCWP/restore trick.
1005  */
1006 
1007                 rd      %wim, %g1
1008                 rd      %psr, %g2
1009                 wr      %g0, 0x0, %wim                  ! so we dont get a trap
1010                 andn    %g2, 0x1f, %g3
1011                 wr      %g3, 0x0, %psr
1012                 WRITE_PAUSE
1013                 save
1014                 rd      %psr, %g3
1015                 restore
1016                 and     %g3, 0x1f, %g3
1017                 add     %g3, 0x1, %g3
1018                 wr      %g2, 0x0, %psr
1019                 wr      %g1, 0x0, %wim
1020 
1021                 cmp     %g3, 0x7
1022                 bne,a   2f
1023                 sethi   %hi( C_LABEL(nwindows) ), %g4
1024 
1025 
1026                 /* Nop out one save and one restore in the save state code
1027                  * and system call entry if this is a seven window Sparc.
1028                  */
1029                 sethi   %hi(nop7), %g5
1030                 or      %g5, %lo(nop7), %g5
1031                 sethi   %hi(NOP_INSN), %g6
1032                 or      %g6, %lo(NOP_INSN), %g6
1033                 /* patch 1 */
1034                 st      %g6, [%g5]
1035                 st      %g6, [%g5 + 0x4]
1036                 sethi   %hi(rnop7), %g5
1037                 or      %g5, %lo(rnop7), %g5
1038                 /* patch 2 */
1039                 st      %g6, [%g5]
1040                 st      %g6, [%g5 + 0x4]
1041 
1042                 sethi   %hi( C_LABEL(nwindows) ), %g4
1043 
1044 2:              
1045                 st      %g3, [%g4 + %lo( C_LABEL(nwindows) )]   ! store final value
1046                 sub     %g3, 0x1, %g3
1047                 sethi   %hi( C_LABEL(nwindowsm1) ), %g4
1048                 st      %g3, [%g4 + %lo( C_LABEL(nwindowsm1) )]
1049 
1050                 /* Initialize lnx_winmask. */
1051                 set     lnx_winmask, %g4
1052                 or      %g0, 0x2, %g5
1053                 or      %g0, 0x0, %g6
1054 msk_loop:
1055                 stb     %g5, [%g4 + %g6]
1056                 add     %g6, 0x1, %g6
1057                 cmp     %g6, %g3
1058                 bl,a    msk_loop
1059                 sll     %g5, 0x1, %g5
1060                 or      %g0, 0x1, %g5
1061                 stb     %g5, [%g4 + %g3]
1062 
1063                 /* Here we go */
1064                 set     C_LABEL(trapbase), %g3
1065                 wr      %g3, 0x0, %tbr
1066                 WRITE_PAUSE
1067 
1068 
1069 /* First we call prom_init() to set up PROMLIB, then off to start_kernel() */
1070 /* XXX put this in setup_arch() */
1071 
1072                 sethi   %hi( C_LABEL(prom_vector_p) ), %g5
1073                 call    C_LABEL(prom_init)
1074                 ld      [%g5 + %lo( C_LABEL(prom_vector_p) )], %o0
1075 
1076                 subcc   %o0, 0x1, %g0
1077                 be      halt_me                 ! promlib init failed
1078                 nop
1079 
1080                 call    C_LABEL(start_kernel)
1081                 nop
1082         
1083                 /* We should not get here. */
1084                 call    halt_me
1085                 nop
1086 
1087 /* There, happy now Adrian? */
1088 
1089                 /* XXX Fix this... XXX */
1090 no_sun4_here:
1091                 sethi   %hi(SUN4_PROM_VECTOR+SUN4_PRINTF), %o1
1092                 ld      [%o1 + %lo(SUN4_PROM_VECTOR+SUN4_PRINTF)], %o1
1093                 set     sun4_notsup, %o0
1094                 call    %o1
1095                 nop
1096 1:
1097                 ba      1b                      ! Cannot exit into KMON
1098                 nop
1099 
1100 no_sun4d_here:
1101                 ld      [%g7 + 0x68], %o1
1102                 set     sun4d_notsup, %o0
1103                 call    %o1
1104                 nop
1105                 b       halt_me
1106                 nop
1107 
1108 no_sun4e_here:
1109                 ld      [%g7 + 0x68], %o1
1110                 set     sun4e_notsup, %o0
1111                 call    %o1
1112                 nop
1113                 b       halt_me
1114                 nop
1115 
1116 no_sun4u_here:
1117                 ld      [%g7 + 0x68], %o1
1118                 set     sun4u_notsup, %o0
1119                 call    %o1
1120                 nop
1121                 b       halt_me
1122                 nop
1123 
1124 halt_me:
1125                 ld      [%g7 + 0x74], %o0
1126                 call    %o0                     ! Get us out of here...
1127                 nop                             ! Apparently Solaris is better.
1128 
1129         .data
1130         .align 4
1131 
1132 /*
1133  * Fill up the prom vector, note in particular the kind first element,
1134  * no joke. I don't need all of them in here as the entire prom vector
1135  * gets initialized in c-code so all routines can use it.
1136  */
1137 
1138                         .globl C_LABEL(prom_vector_p)
1139 C_LABEL(prom_vector_p): .skip 4
1140 
1141         .align 4
1142 
1143 /* We calculate the following at boot time, window fills/spills and trap entry
1144  * code uses these to keep track of the register windows.
1145  */
1146 
1147         .globl C_LABEL(nwindows)
1148         .globl C_LABEL(nwindowsm1)
1149 C_LABEL(nwindows):      .skip 4
1150 C_LABEL(nwindowsm1):    .skip 4
1151 
1152         .align 4
1153 
1154 /* Boot time debugger vector value.  We need this later on. */
1155 
1156         .globl C_LABEL(linux_dbvec)
1157 C_LABEL(linux_dbvec):           .skip 4
1158 
1159         .align 4
1160 
1161 /* Just to get the kernel through the compiler for now */
1162         .globl C_LABEL(floppy_track_buffer)
1163 C_LABEL(floppy_track_buffer):
1164         .fill 512*2*36,1,0

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