1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2013 (c) Joyent, Inc. All rights reserved.
  14  */
  15 
  16 #include <sys/asm_linkage.h>
  17 #include <sys/machparam.h>
  18 #include <sys/cpu_asm.h>
  19 
  20 #include "assym.h"
  21 
  22 #if defined(__lint)
  23 
  24 #endif
  25 
  26 /*
  27  * Each of the different machines has its own locore.s to take care of getting
  28  * us into fakebop for the first time. After that, they all return here to a
  29  * generic locore to take us into mlsetup and then to main forever more.
  30  */
  31 
  32         /*
  33          * External globals
  34          */
  35         .globl  _locore_start
  36         .globl  mlsetup
  37         .globl  sysp
  38         .globl  bootops
  39         .globl  bootopsp
  40         .globl  t0
  41 
  42         .data
  43         .comm   t0stack, DEFAULTSTKSZ, 32
  44         .comm   t0, 4094, 32
  45 
  46 #if defined(__lint)
  47 
  48 /* ARGSUSED */
  49 void
  50 _locore_start(struct boot_syscalls *sysp, struct bootops *bop)
  51 {}
  52 
  53 #else   /* __lint */
  54 
  55         /*
  56          * We got here from _kobj_init() via exitto().  We have a few different
  57          * tasks that we need to take care of before we hop into mlsetup and
  58          * then main. We're never going back so we shouldn't feel compelled to
  59          * preserve any registers.
  60          *
  61          *  o Enable unaligned access
  62          *  o Enable our I/D-caches
  63          *  o Save the boot syscalls and bootops for later
  64          *  o Set up our stack to be the real stack of t0stack.
  65          *  o Save t0 as curthread
  66          *  o Set up a struct REGS for mlsetup
  67          *  o Make sure that we're 8 byte aligned for the call
  68          */
  69 
  70         ENTRY(_locore_start)
  71 
  72 
  73         /*
  74          * We've been running in t0stack anyway, up to this point, but
  75          * _locore_start represents what is in effect a fresh start in the
  76          * real kernel -- We'll never return back through here.
  77          *
  78          * So reclaim those few bytes
  79          */
  80         ldr     sp, =t0stack
  81         ldr     r4, =(DEFAULTSTKSZ - REGSIZE)
  82         add     sp, r4
  83         bic     sp, sp, #0xff
  84 
  85         /*
  86          * Save flags and arguments for potential debugging
  87          */
  88         str     r0, [sp, #REGOFF_R0]
  89         str     r1, [sp, #REGOFF_R1]
  90         str     r2, [sp, #REGOFF_R2]
  91         str     r3, [sp, #REGOFF_R3]
  92         mrs     r4, CPSR
  93         str     r4, [sp, #REGOFF_CPSR]
  94 
  95         /*
  96          * Save back the bootops and boot_syscalls.
  97          */
  98         ldr     r2, =sysp
  99         str     r0, [r2]
 100         ldr     r2, =bootops
 101         str     r1, [r2]
 102         ldr     r2, =bootopsp
 103         ldr     r2, [r2]
 104         str     r1, [r2]
 105 
 106         /*
 107          * Set up our curthread pointer
 108          */
 109         ldr     r0, =t0
 110         mcr     p15, 0, r0, c13, c0, 4
 111 
 112         /*
 113          * Go ahead now and enable unaligned access, the L1 I/D caches.
 114          *
 115          * Bit 2 is for the D cache
 116          * Bit 12 is for the I cache
 117          * Bit 22 is for unaligned access
 118          */
 119         mrc     p15, 0, r0, c1, c0, 0
 120         orr     r0, #0x02
 121         orr     r0, #0x1000
 122         orr     r0, #0x400000
 123         mcr     p15, 0, r0, c1, c0, 0
 124 
 125         /*
 126          * mlsetup() takes the struct regs as an argument. main doesn't take
 127          * any and should never return. Currently, we have an 8-byte aligned
 128          * stack.  We want to push a zero frame pointer to terminate any
 129          * stack walking, but that would cause us to end up with only a
 130          * 4-byte aligned stack.  So, to keep things nice and correct, we
 131          * push a zero value twice - it's similar to a typical function
 132          * entry:
 133          *      push { r9, lr }
 134          */
 135         mov     r9,#0
 136         push    { r9 }          /* link register */
 137         push    { r9 }          /* frame pointer */
 138         mov     r0, sp
 139         bl      mlsetup
 140         bl      main
 141         /* NOTREACHED */
 142         ldr     r0,=__return_from_main
 143         ldr     r0,[r0]
 144         bl      panic
 145         SET_SIZE(_locore_start)
 146 
 147 __return_from_main:
 148         .string "main() returned"
 149 #endif  /* __lint */