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 26#include <sys/syscall.h> 27 28#include <machine/trap.h> 29#include <machine/param.h> 30#include <machine/spr.h> 31#include <machine/asm.h> 32 33#define OFWSTKSZ 4096 /* 4K Open Firmware stack */ 34 35/* 36 * Globals 37 */ 38 .data 39GLOBAL(ofmsr) 40 .long 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */ 41GLOBAL(rtasmsr) 42 .long 0 43GLOBAL(openfirmware_entry) 44 .long 0 /* Open Firmware entry point */ 45GLOBAL(rtas_entry) 46 .long 0 /* RTAS entry point */ 47 48 .align 4 49ofwstk: 50 .space OFWSTKSZ 51rtas_regsave: 52 .space 4 53 54/* 55 * Open Firmware Entry Point. May need to enter real mode. 56 * 57 * C prototype: int ofwcall(void *callbuffer); 58 */ 59 60ASENTRY(ofwcall) 61 mflr %r0 62 stw %r0,4(%r1) 63 64 /* Record the old MSR */ 65 mfmsr %r6 66 67 /* GOT pointer in r7 */ 68 bl 1f 691: 70 mflr %r7 71 addis %r7,%r7,(_GLOBAL_OFFSET_TABLE_-1b)@ha 72 addi %r7,%r7,(_GLOBAL_OFFSET_TABLE_-1b)@l 73 74 /* read client interface handler */ 75 lwz %r4,openfirmware_entry@got(%r7) 76 lwz %r4,0(%r4) 77 78 /* 79 * Set the MSR to the OF value. This has the side effect of disabling 80 * exceptions, which prevents preemption later. 81 */ 82 83 lwz %r5,ofmsr@got(%r7) 84 lwz %r5,0(%r5) 85 mtmsr %r5 86 isync 87 88 /* 89 * Set up OF stack. This needs to be potentially accessible in real mode 90 * The pointer to the current kernel stack is placed at the very 91 * top of the stack along with the old MSR so we can get them back 92 * later. 93 */ 94 mr %r5,%r1 95 lwz %r1,ofwstk@got(%r7) 96 addi %r1,%r1,(OFWSTKSZ-32) 97 stw %r5,20(%r1) /* Save real stack pointer */ 98 stw %r2,24(%r1) /* Save curthread */ 99 stw %r6,28(%r1) /* Save old MSR */ 100 li %r5,0 101 stw %r5,4(%r1) 102 stw %r5,0(%r1) 103 104 /* Finally, branch to OF */ 105 mtctr %r4 106 bctrl 107 108 /* Reload stack pointer and MSR from the OFW stack */ 109 lwz %r6,28(%r1) 110 lwz %r2,24(%r1) 111 lwz %r1,20(%r1) 112 113 /* Now set the real MSR */ 114 mtmsr %r6 115 isync 116 117 /* Return */ 118 lwz %r0,4(%r1) 119 mtlr %r0 120 blr 121ASEND(ofwcall) 122 123/* 124 * RTAS Entry Point. Similar to the OF one, but simpler (no separate stack) 125 * 126 * C prototype: int rtascall(void *callbuffer, void *rtas_privdat); 127 */ 128 129ASENTRY(rtascall) 130 mflr %r0 131 stw %r0,4(%r1) 132 133 /* GOT pointer in r7 */ 134 bl 1f 1351: 136 mflr %r7 137 addis %r7,%r7,(_GLOBAL_OFFSET_TABLE_-1b)@ha 138 addi %r7,%r7,(_GLOBAL_OFFSET_TABLE_-1b)@l 139 140 /* Record the old MSR to real-mode-accessible area */ 141 mfmsr %r0 142 lwz %r5,rtas_regsave@got(%r7) 143 stw %r0,0(%r5) 144 145 /* read client interface handler */ 146 lwz %r5,rtas_entry@got(%r7) 147 lwz %r5,0(%r5) 148 149 /* Set the MSR to the RTAS value */ 150 lwz %r6,rtasmsr@got(%r7) 151 lwz %r6,0(%r6) 152 mtmsr %r6 153 isync 154 155 /* Branch to RTAS */ 156 mtctr %r5 157 bctrl 158 159 /* GOT pointer in r7 */ 160 bl 1f 1611: 162 mflr %r7 163 addis %r7,%r7,(_GLOBAL_OFFSET_TABLE_-1b)@ha 164 addi %r7,%r7,(_GLOBAL_OFFSET_TABLE_-1b)@l 165 166 /* Now set the MSR back */ 167 lwz %r6,rtas_regsave@got(%r7) 168 lwz %r6,0(%r6) 169 mtmsr %r6 170 isync 171 172 /* And return */ 173 lwz %r0,4(%r1) 174 mtlr %r0 175 blr 176ASEND(rtascall) 177