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