1/*- 2 * Copyright (C) 2009-2011 Nathan Whitehorn 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 * $FreeBSD$ 26 */ 27 28#include <sys/syscall.h> 29 30#include <machine/trap.h> 31#include <machine/param.h> 32#include <machine/spr.h> 33#include <machine/asm.h> 34 35#define OFWSTKSZ 4096 /* 4K Open Firmware stack */ 36 37/* 38 * Globals 39 */ 40 .data 41 .align 4 42ofwstk: 43 .space OFWSTKSZ 44rtas_regsave: 45 .space 24 /* 3 * sizeof(register_t) */ 46GLOBAL(ofmsr) 47 .llong 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */ 48GLOBAL(rtasmsr) 49 .llong 0 50GLOBAL(openfirmware_entry) 51 .llong 0 /* Open Firmware entry point */ 52GLOBAL(rtas_entry) 53 .llong 0 /* RTAS entry point */ 54 55/* 56 * Open Firmware Real-mode Entry Point. This is a huge pain. 57 */ 58 59ASENTRY_NOPROF(ofwcall) 60 mflr %r0 61 std %r0,16(%r1) 62 stdu %r1,-208(%r1) 63 64 /* 65 * We need to save the following, because OF's register save/ 66 * restore code assumes that the contents of registers are 67 * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These 68 * get placed in that order in the stack. 69 */ 70 71 mfcr %r4 72 std %r4,48(%r1) 73 std %r13,56(%r1) 74 std %r14,64(%r1) 75 std %r15,72(%r1) 76 std %r16,80(%r1) 77 std %r17,88(%r1) 78 std %r18,96(%r1) 79 std %r19,104(%r1) 80 std %r20,112(%r1) 81 std %r21,120(%r1) 82 std %r22,128(%r1) 83 std %r23,136(%r1) 84 std %r24,144(%r1) 85 std %r25,152(%r1) 86 std %r26,160(%r1) 87 std %r27,168(%r1) 88 std %r28,176(%r1) 89 std %r29,184(%r1) 90 std %r30,192(%r1) 91 std %r31,200(%r1) 92 93 /* Record the old MSR */ 94 mfmsr %r6 95 96 /* read client interface handler */ 97 lis %r4,openfirmware_entry@ha 98 ld %r4,openfirmware_entry@l(%r4) 99 100 /* 101 * Set the MSR to the OF value. This has the side effect of disabling 102 * exceptions, which is important for the next few steps. 103 */ 104 105 lis %r5,ofmsr@ha 106 ld %r5,ofmsr@l(%r5) 107 mtmsrd %r5 108 isync 109 110 /* 111 * Set up OF stack. This needs to be accessible in real mode and 112 * use the 32-bit ABI stack frame format. The pointer to the current 113 * kernel stack is placed at the very top of the stack along with 114 * the old MSR so we can get them back later. 115 */ 116 mr %r5,%r1 117 lis %r1,(ofwstk+OFWSTKSZ-32)@ha 118 addi %r1,%r1,(ofwstk+OFWSTKSZ-32)@l 119 std %r5,8(%r1) /* Save real stack pointer */ 120 std %r2,16(%r1) /* Save old TOC */ 121 std %r6,24(%r1) /* Save old MSR */ 122 li %r5,0 123 stw %r5,4(%r1) 124 stw %r5,0(%r1) 125 126 /* Finally, branch to OF */ 127 mtctr %r4 128 bctrl 129 130 /* Reload stack pointer and MSR from the OFW stack */ 131 ld %r6,24(%r1) 132 ld %r2,16(%r1) 133 ld %r1,8(%r1) 134 135 /* Now set the real MSR */ 136 mtmsrd %r6 137 isync 138 139 /* Sign-extend the return value from OF */ 140 extsw %r3,%r3 141 142 /* Restore all the non-volatile registers */ 143 ld %r5,48(%r1) 144 mtcr %r5 145 ld %r13,56(%r1) 146 ld %r14,64(%r1) 147 ld %r15,72(%r1) 148 ld %r16,80(%r1) 149 ld %r17,88(%r1) 150 ld %r18,96(%r1) 151 ld %r19,104(%r1) 152 ld %r20,112(%r1) 153 ld %r21,120(%r1) 154 ld %r22,128(%r1) 155 ld %r23,136(%r1) 156 ld %r24,144(%r1) 157 ld %r25,152(%r1) 158 ld %r26,160(%r1) 159 ld %r27,168(%r1) 160 ld %r28,176(%r1) 161 ld %r29,184(%r1) 162 ld %r30,192(%r1) 163 ld %r31,200(%r1) 164 165 /* Restore the stack and link register */ 166 ld %r1,0(%r1) 167 ld %r0,16(%r1) 168 mtlr %r0 169 blr 170 171/* 172 * RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate 173 * stack) 174 * 175 * C prototype: int rtascall(void *callbuffer, void *rtas_privdat); 176 */ 177 178ASENTRY_NOPROF(rtascall) 179 mflr %r0 180 std %r0,16(%r1) 181 stdu %r1,-208(%r1) 182 183 /* 184 * We need to save the following, because RTAS's register save/ 185 * restore code assumes that the contents of registers are 186 * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These 187 * get placed in that order in the stack. 188 */ 189 190 mfcr %r5 191 std %r5,48(%r1) 192 std %r13,56(%r1) 193 std %r14,64(%r1) 194 std %r15,72(%r1) 195 std %r16,80(%r1) 196 std %r17,88(%r1) 197 std %r18,96(%r1) 198 std %r19,104(%r1) 199 std %r20,112(%r1) 200 std %r21,120(%r1) 201 std %r22,128(%r1) 202 std %r23,136(%r1) 203 std %r24,144(%r1) 204 std %r25,152(%r1) 205 std %r26,160(%r1) 206 std %r27,168(%r1) 207 std %r28,176(%r1) 208 std %r29,184(%r1) 209 std %r30,192(%r1) 210 std %r31,200(%r1) 211 212 /* Record the old MSR */ 213 mfmsr %r6 214 215 /* read client interface handler */ 216 lis %r5,rtas_entry@ha 217 ld %r5,rtas_entry@l(%r5) 218 219 /* 220 * Set the MSR to the RTAS value. This has the side effect of disabling 221 * exceptions, which is important for the next few steps. 222 */ 223 224 lis %r7,rtasmsr@ha 225 ld %r7,rtasmsr@l(%r7) 226 mtmsrd %r7 227 isync 228 229 /* 230 * Set up RTAS register save area, so that we can get back all of 231 * our 64-bit pointers. Save our stack pointer, the TOC, and the MSR. 232 * Put this in r1, since RTAS is obliged to save it. Kernel globals 233 * are below 4 GB, so this is safe. 234 */ 235 mr %r7,%r1 236 lis %r1,rtas_regsave@ha 237 addi %r1,%r1,rtas_regsave@l 238 std %r7,0(%r1) /* Save 64-bit stack pointer */ 239 std %r2,8(%r1) /* Save TOC */ 240 std %r6,16(%r1) /* Save MSR */ 241 242 /* Finally, branch to RTAS */ 243 mtctr %r5 244 bctrl 245 246 /* 247 * Reload stack pointer and MSR from the reg save area in r1. We are 248 * running in 32-bit mode at this point, so it doesn't matter if r1 249 * has become sign-extended. 250 */ 251 ld %r6,16(%r1) 252 ld %r2,8(%r1) 253 ld %r1,0(%r1) 254 255 /* Now set the real MSR */ 256 mtmsrd %r6 257 isync 258 259 /* Sign-extend the return value from RTAS */ 260 extsw %r3,%r3 261 262 /* Restore all the non-volatile registers */ 263 ld %r5,48(%r1) 264 mtcr %r5 265 ld %r13,56(%r1) 266 ld %r14,64(%r1) 267 ld %r15,72(%r1) 268 ld %r16,80(%r1) 269 ld %r17,88(%r1) 270 ld %r18,96(%r1) 271 ld %r19,104(%r1) 272 ld %r20,112(%r1) 273 ld %r21,120(%r1) 274 ld %r22,128(%r1) 275 ld %r23,136(%r1) 276 ld %r24,144(%r1) 277 ld %r25,152(%r1) 278 ld %r26,160(%r1) 279 ld %r27,168(%r1) 280 ld %r28,176(%r1) 281 ld %r29,184(%r1) 282 ld %r30,192(%r1) 283 ld %r31,200(%r1) 284 285 /* Restore the stack and link register */ 286 ld %r1,0(%r1) 287 ld %r0,16(%r1) 288 mtlr %r0 289 blr 290 291