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