1222613Snwhitehorn/*- 2222613Snwhitehorn * Copyright (C) 2009-2011 Nathan Whitehorn 3222613Snwhitehorn * All rights reserved. 4222613Snwhitehorn * 5222613Snwhitehorn * Redistribution and use in source and binary forms, with or without 6222613Snwhitehorn * modification, are permitted provided that the following conditions 7222613Snwhitehorn * are met: 8222613Snwhitehorn * 1. Redistributions of source code must retain the above copyright 9222613Snwhitehorn * notice, this list of conditions and the following disclaimer. 10222613Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 11222613Snwhitehorn * notice, this list of conditions and the following disclaimer in the 12222613Snwhitehorn * documentation and/or other materials provided with the distribution. 13222613Snwhitehorn * 14222613Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15222613Snwhitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16222613Snwhitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17222613Snwhitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18222613Snwhitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19222613Snwhitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20222613Snwhitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21222613Snwhitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22222613Snwhitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23222613Snwhitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24222613Snwhitehorn * 25222613Snwhitehorn * $FreeBSD: releng/10.2/sys/powerpc/ofw/ofwcall64.S 230400 2012-01-20 22:34:19Z andreast $ 26222613Snwhitehorn */ 27222613Snwhitehorn 28222613Snwhitehorn#include <sys/syscall.h> 29222613Snwhitehorn 30222613Snwhitehorn#include <machine/trap.h> 31222613Snwhitehorn#include <machine/param.h> 32222613Snwhitehorn#include <machine/spr.h> 33222613Snwhitehorn#include <machine/asm.h> 34222613Snwhitehorn 35222613Snwhitehorn#define OFWSTKSZ 4096 /* 4K Open Firmware stack */ 36222613Snwhitehorn 37222613Snwhitehorn/* 38222613Snwhitehorn * Globals 39222613Snwhitehorn */ 40222613Snwhitehorn .data 41222613Snwhitehorn .align 4 42222613Snwhitehornofwstk: 43222613Snwhitehorn .space OFWSTKSZ 44222613Snwhitehornrtas_regsave: 45222613Snwhitehorn .space 24 /* 3 * sizeof(register_t) */ 46222613SnwhitehornGLOBAL(ofmsr) 47222613Snwhitehorn .llong 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */ 48222613SnwhitehornGLOBAL(rtasmsr) 49222613Snwhitehorn .llong 0 50222613SnwhitehornGLOBAL(openfirmware_entry) 51222613Snwhitehorn .llong 0 /* Open Firmware entry point */ 52222613SnwhitehornGLOBAL(rtas_entry) 53222613Snwhitehorn .llong 0 /* RTAS entry point */ 54222613Snwhitehorn 55222613Snwhitehorn/* 56222613Snwhitehorn * Open Firmware Real-mode Entry Point. This is a huge pain. 57222613Snwhitehorn */ 58222613Snwhitehorn 59230400SandreastASENTRY_NOPROF(ofwcall) 60222613Snwhitehorn mflr %r0 61222613Snwhitehorn std %r0,16(%r1) 62222613Snwhitehorn stdu %r1,-208(%r1) 63222613Snwhitehorn 64222613Snwhitehorn /* 65222613Snwhitehorn * We need to save the following, because OF's register save/ 66222613Snwhitehorn * restore code assumes that the contents of registers are 67222613Snwhitehorn * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These 68222613Snwhitehorn * get placed in that order in the stack. 69222613Snwhitehorn */ 70222613Snwhitehorn 71222613Snwhitehorn mfcr %r4 72222613Snwhitehorn std %r4,48(%r1) 73222613Snwhitehorn std %r13,56(%r1) 74222613Snwhitehorn std %r14,64(%r1) 75222613Snwhitehorn std %r15,72(%r1) 76222613Snwhitehorn std %r16,80(%r1) 77222613Snwhitehorn std %r17,88(%r1) 78222613Snwhitehorn std %r18,96(%r1) 79222613Snwhitehorn std %r19,104(%r1) 80222613Snwhitehorn std %r20,112(%r1) 81222613Snwhitehorn std %r21,120(%r1) 82222613Snwhitehorn std %r22,128(%r1) 83222613Snwhitehorn std %r23,136(%r1) 84222613Snwhitehorn std %r24,144(%r1) 85222613Snwhitehorn std %r25,152(%r1) 86222613Snwhitehorn std %r26,160(%r1) 87222613Snwhitehorn std %r27,168(%r1) 88222613Snwhitehorn std %r28,176(%r1) 89222613Snwhitehorn std %r29,184(%r1) 90222613Snwhitehorn std %r30,192(%r1) 91222613Snwhitehorn std %r31,200(%r1) 92222613Snwhitehorn 93222613Snwhitehorn /* Record the old MSR */ 94222613Snwhitehorn mfmsr %r6 95222613Snwhitehorn 96222613Snwhitehorn /* read client interface handler */ 97222613Snwhitehorn lis %r4,openfirmware_entry@ha 98222613Snwhitehorn ld %r4,openfirmware_entry@l(%r4) 99222613Snwhitehorn 100222613Snwhitehorn /* 101222613Snwhitehorn * Set the MSR to the OF value. This has the side effect of disabling 102222613Snwhitehorn * exceptions, which is important for the next few steps. 103222613Snwhitehorn */ 104222613Snwhitehorn 105222613Snwhitehorn lis %r5,ofmsr@ha 106222613Snwhitehorn ld %r5,ofmsr@l(%r5) 107222613Snwhitehorn mtmsrd %r5 108222613Snwhitehorn isync 109222613Snwhitehorn 110222613Snwhitehorn /* 111222613Snwhitehorn * Set up OF stack. This needs to be accessible in real mode and 112222613Snwhitehorn * use the 32-bit ABI stack frame format. The pointer to the current 113222613Snwhitehorn * kernel stack is placed at the very top of the stack along with 114222613Snwhitehorn * the old MSR so we can get them back later. 115222613Snwhitehorn */ 116222613Snwhitehorn mr %r5,%r1 117222613Snwhitehorn lis %r1,(ofwstk+OFWSTKSZ-32)@ha 118222613Snwhitehorn addi %r1,%r1,(ofwstk+OFWSTKSZ-32)@l 119222613Snwhitehorn std %r5,8(%r1) /* Save real stack pointer */ 120222613Snwhitehorn std %r2,16(%r1) /* Save old TOC */ 121222613Snwhitehorn std %r6,24(%r1) /* Save old MSR */ 122222613Snwhitehorn li %r5,0 123222613Snwhitehorn stw %r5,4(%r1) 124222613Snwhitehorn stw %r5,0(%r1) 125222613Snwhitehorn 126222613Snwhitehorn /* Finally, branch to OF */ 127222613Snwhitehorn mtctr %r4 128222613Snwhitehorn bctrl 129222613Snwhitehorn 130222613Snwhitehorn /* Reload stack pointer and MSR from the OFW stack */ 131222613Snwhitehorn ld %r6,24(%r1) 132222613Snwhitehorn ld %r2,16(%r1) 133222613Snwhitehorn ld %r1,8(%r1) 134222613Snwhitehorn 135222613Snwhitehorn /* Now set the real MSR */ 136222613Snwhitehorn mtmsrd %r6 137222613Snwhitehorn isync 138222613Snwhitehorn 139222613Snwhitehorn /* Sign-extend the return value from OF */ 140222613Snwhitehorn extsw %r3,%r3 141222613Snwhitehorn 142222613Snwhitehorn /* Restore all the non-volatile registers */ 143222613Snwhitehorn ld %r5,48(%r1) 144222613Snwhitehorn mtcr %r5 145222613Snwhitehorn ld %r13,56(%r1) 146222613Snwhitehorn ld %r14,64(%r1) 147222613Snwhitehorn ld %r15,72(%r1) 148222613Snwhitehorn ld %r16,80(%r1) 149222613Snwhitehorn ld %r17,88(%r1) 150222613Snwhitehorn ld %r18,96(%r1) 151222613Snwhitehorn ld %r19,104(%r1) 152222613Snwhitehorn ld %r20,112(%r1) 153222613Snwhitehorn ld %r21,120(%r1) 154222613Snwhitehorn ld %r22,128(%r1) 155222613Snwhitehorn ld %r23,136(%r1) 156222613Snwhitehorn ld %r24,144(%r1) 157222613Snwhitehorn ld %r25,152(%r1) 158222613Snwhitehorn ld %r26,160(%r1) 159222613Snwhitehorn ld %r27,168(%r1) 160222613Snwhitehorn ld %r28,176(%r1) 161222613Snwhitehorn ld %r29,184(%r1) 162222613Snwhitehorn ld %r30,192(%r1) 163222613Snwhitehorn ld %r31,200(%r1) 164222613Snwhitehorn 165222613Snwhitehorn /* Restore the stack and link register */ 166222613Snwhitehorn ld %r1,0(%r1) 167222613Snwhitehorn ld %r0,16(%r1) 168222613Snwhitehorn mtlr %r0 169222613Snwhitehorn blr 170222613Snwhitehorn 171222613Snwhitehorn/* 172222613Snwhitehorn * RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate 173222613Snwhitehorn * stack) 174222613Snwhitehorn * 175222613Snwhitehorn * C prototype: int rtascall(void *callbuffer, void *rtas_privdat); 176222613Snwhitehorn */ 177222613Snwhitehorn 178230400SandreastASENTRY_NOPROF(rtascall) 179222613Snwhitehorn mflr %r0 180222613Snwhitehorn std %r0,16(%r1) 181222613Snwhitehorn stdu %r1,-208(%r1) 182222613Snwhitehorn 183222613Snwhitehorn /* 184222613Snwhitehorn * We need to save the following, because RTAS's register save/ 185222613Snwhitehorn * restore code assumes that the contents of registers are 186222613Snwhitehorn * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These 187222613Snwhitehorn * get placed in that order in the stack. 188222613Snwhitehorn */ 189222613Snwhitehorn 190222613Snwhitehorn mfcr %r5 191222613Snwhitehorn std %r5,48(%r1) 192222613Snwhitehorn std %r13,56(%r1) 193222613Snwhitehorn std %r14,64(%r1) 194222613Snwhitehorn std %r15,72(%r1) 195222613Snwhitehorn std %r16,80(%r1) 196222613Snwhitehorn std %r17,88(%r1) 197222613Snwhitehorn std %r18,96(%r1) 198222613Snwhitehorn std %r19,104(%r1) 199222613Snwhitehorn std %r20,112(%r1) 200222613Snwhitehorn std %r21,120(%r1) 201222613Snwhitehorn std %r22,128(%r1) 202222613Snwhitehorn std %r23,136(%r1) 203222613Snwhitehorn std %r24,144(%r1) 204222613Snwhitehorn std %r25,152(%r1) 205222613Snwhitehorn std %r26,160(%r1) 206222613Snwhitehorn std %r27,168(%r1) 207222613Snwhitehorn std %r28,176(%r1) 208222613Snwhitehorn std %r29,184(%r1) 209222613Snwhitehorn std %r30,192(%r1) 210222613Snwhitehorn std %r31,200(%r1) 211222613Snwhitehorn 212222613Snwhitehorn /* Record the old MSR */ 213222613Snwhitehorn mfmsr %r6 214222613Snwhitehorn 215222613Snwhitehorn /* read client interface handler */ 216222613Snwhitehorn lis %r5,rtas_entry@ha 217222613Snwhitehorn ld %r5,rtas_entry@l(%r5) 218222613Snwhitehorn 219222613Snwhitehorn /* 220222613Snwhitehorn * Set the MSR to the RTAS value. This has the side effect of disabling 221222613Snwhitehorn * exceptions, which is important for the next few steps. 222222613Snwhitehorn */ 223222613Snwhitehorn 224222613Snwhitehorn lis %r7,rtasmsr@ha 225222613Snwhitehorn ld %r7,rtasmsr@l(%r7) 226222613Snwhitehorn mtmsrd %r7 227222613Snwhitehorn isync 228222613Snwhitehorn 229222613Snwhitehorn /* 230222613Snwhitehorn * Set up RTAS register save area, so that we can get back all of 231222613Snwhitehorn * our 64-bit pointers. Save our stack pointer, the TOC, and the MSR. 232222613Snwhitehorn * Put this in r1, since RTAS is obliged to save it. Kernel globals 233222613Snwhitehorn * are below 4 GB, so this is safe. 234222613Snwhitehorn */ 235222613Snwhitehorn mr %r7,%r1 236222613Snwhitehorn lis %r1,rtas_regsave@ha 237222613Snwhitehorn addi %r1,%r1,rtas_regsave@l 238222613Snwhitehorn std %r7,0(%r1) /* Save 64-bit stack pointer */ 239222613Snwhitehorn std %r2,8(%r1) /* Save TOC */ 240222613Snwhitehorn std %r6,16(%r1) /* Save MSR */ 241222613Snwhitehorn 242222613Snwhitehorn /* Finally, branch to RTAS */ 243222613Snwhitehorn mtctr %r5 244222613Snwhitehorn bctrl 245222613Snwhitehorn 246222613Snwhitehorn /* 247222613Snwhitehorn * Reload stack pointer and MSR from the reg save area in r1. We are 248222613Snwhitehorn * running in 32-bit mode at this point, so it doesn't matter if r1 249222613Snwhitehorn * has become sign-extended. 250222613Snwhitehorn */ 251222613Snwhitehorn ld %r6,16(%r1) 252222613Snwhitehorn ld %r2,8(%r1) 253222613Snwhitehorn ld %r1,0(%r1) 254222613Snwhitehorn 255222613Snwhitehorn /* Now set the real MSR */ 256222613Snwhitehorn mtmsrd %r6 257222613Snwhitehorn isync 258222613Snwhitehorn 259222613Snwhitehorn /* Sign-extend the return value from RTAS */ 260222613Snwhitehorn extsw %r3,%r3 261222613Snwhitehorn 262222613Snwhitehorn /* Restore all the non-volatile registers */ 263222613Snwhitehorn ld %r5,48(%r1) 264222613Snwhitehorn mtcr %r5 265222613Snwhitehorn ld %r13,56(%r1) 266222613Snwhitehorn ld %r14,64(%r1) 267222613Snwhitehorn ld %r15,72(%r1) 268222613Snwhitehorn ld %r16,80(%r1) 269222613Snwhitehorn ld %r17,88(%r1) 270222613Snwhitehorn ld %r18,96(%r1) 271222613Snwhitehorn ld %r19,104(%r1) 272222613Snwhitehorn ld %r20,112(%r1) 273222613Snwhitehorn ld %r21,120(%r1) 274222613Snwhitehorn ld %r22,128(%r1) 275222613Snwhitehorn ld %r23,136(%r1) 276222613Snwhitehorn ld %r24,144(%r1) 277222613Snwhitehorn ld %r25,152(%r1) 278222613Snwhitehorn ld %r26,160(%r1) 279222613Snwhitehorn ld %r27,168(%r1) 280222613Snwhitehorn ld %r28,176(%r1) 281222613Snwhitehorn ld %r29,184(%r1) 282222613Snwhitehorn ld %r30,192(%r1) 283222613Snwhitehorn ld %r31,200(%r1) 284222613Snwhitehorn 285222613Snwhitehorn /* Restore the stack and link register */ 286222613Snwhitehorn ld %r1,0(%r1) 287222613Snwhitehorn ld %r0,16(%r1) 288222613Snwhitehorn mtlr %r0 289222613Snwhitehorn blr 290222613Snwhitehorn 291