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 */