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 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 the L1 I/D caches.
114 */
115 mrc p15, 0, r0, c1, c0, 0
116 orr r0, #0x04 /* D-cache */
117 orr r0, #0x1000 /* I-cache */
118 mcr p15, 0, r0, c1, c0, 0
119
120 /*
121 * mlsetup() takes the struct regs as an argument. main doesn't take
122 * any and should never return. Currently, we have an 8-byte aligned
123 * stack. We want to push a zero frame pointer to terminate any
124 * stack walking, but that would cause us to end up with only a
125 * 4-byte aligned stack. So, to keep things nice and correct, we
126 * push a zero value twice - it's similar to a typical function
127 * entry:
128 * push { r9, lr }
129 */
130 mov r9,#0
131 push { r9 } /* link register */
132 push { r9 } /* frame pointer */
133 mov r0, sp
134 bl mlsetup
135 bl main
136 /* NOTREACHED */
137 ldr r0,=__return_from_main
138 ldr r0,[r0]
139 bl panic
140 SET_SIZE(_locore_start)
141
142 __return_from_main:
143 .string "main() returned"
144 #endif /* __lint */