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$ 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 41222613SnwhitehornGLOBAL(ofmsr) 42222613Snwhitehorn .long 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */ 43222613SnwhitehornGLOBAL(rtasmsr) 44222613Snwhitehorn .long 0 45222613SnwhitehornGLOBAL(openfirmware_entry) 46222613Snwhitehorn .long 0 /* Open Firmware entry point */ 47222613SnwhitehornGLOBAL(rtas_entry) 48222613Snwhitehorn .long 0 /* RTAS entry point */ 49222613Snwhitehorn 50222613Snwhitehorn .align 4 51222613Snwhitehornofwstk: 52222613Snwhitehorn .space OFWSTKSZ 53222613Snwhitehornrtas_regsave: 54222613Snwhitehorn .space 4 55222613Snwhitehorn 56222613Snwhitehorn/* 57222613Snwhitehorn * Open Firmware Entry Point. May need to enter real mode. 58222613Snwhitehorn * 59222613Snwhitehorn * C prototype: int ofwcall(void *callbuffer); 60222613Snwhitehorn */ 61222613Snwhitehorn 62222613SnwhitehornASENTRY(ofwcall) 63222613Snwhitehorn mflr %r0 64222613Snwhitehorn stw %r0,4(%r1) 65222613Snwhitehorn 66222613Snwhitehorn /* Record the old MSR */ 67222613Snwhitehorn mfmsr %r6 68222613Snwhitehorn 69222613Snwhitehorn /* read client interface handler */ 70222613Snwhitehorn lis %r4,openfirmware_entry@ha 71222613Snwhitehorn lwz %r4,openfirmware_entry@l(%r4) 72222613Snwhitehorn 73222613Snwhitehorn /* 74222613Snwhitehorn * Set the MSR to the OF value. This has the side effect of disabling 75222613Snwhitehorn * exceptions, which prevents preemption later. 76222613Snwhitehorn */ 77222613Snwhitehorn 78222613Snwhitehorn lis %r5,ofmsr@ha 79222613Snwhitehorn lwz %r5,ofmsr@l(%r5) 80222613Snwhitehorn mtmsr %r5 81222613Snwhitehorn isync 82222613Snwhitehorn 83222613Snwhitehorn /* 84222613Snwhitehorn * Set up OF stack. This needs to be potentially accessible in real mode 85222613Snwhitehorn * The pointer to the current kernel stack is placed at the very 86222613Snwhitehorn * top of the stack along with the old MSR so we can get them back 87222613Snwhitehorn * later. 88222613Snwhitehorn */ 89222613Snwhitehorn mr %r5,%r1 90223485Snwhitehorn lis %r1,(ofwstk+OFWSTKSZ-32)@ha 91223485Snwhitehorn addi %r1,%r1,(ofwstk+OFWSTKSZ-32)@l 92223485Snwhitehorn stw %r5,20(%r1) /* Save real stack pointer */ 93223485Snwhitehorn stw %r2,24(%r1) /* Save curthread */ 94223485Snwhitehorn stw %r6,28(%r1) /* Save old MSR */ 95222613Snwhitehorn li %r5,0 96222613Snwhitehorn stw %r5,4(%r1) 97222613Snwhitehorn stw %r5,0(%r1) 98222613Snwhitehorn 99222613Snwhitehorn /* Finally, branch to OF */ 100222613Snwhitehorn mtctr %r4 101222613Snwhitehorn bctrl 102222613Snwhitehorn 103222613Snwhitehorn /* Reload stack pointer and MSR from the OFW stack */ 104223485Snwhitehorn lwz %r6,28(%r1) 105223485Snwhitehorn lwz %r2,24(%r1) 106223485Snwhitehorn lwz %r1,20(%r1) 107222613Snwhitehorn 108222613Snwhitehorn /* Now set the real MSR */ 109222613Snwhitehorn mtmsr %r6 110222613Snwhitehorn isync 111222613Snwhitehorn 112222613Snwhitehorn /* Return */ 113222613Snwhitehorn lwz %r0,4(%r1) 114222613Snwhitehorn mtlr %r0 115222613Snwhitehorn blr 116222613Snwhitehorn 117222613Snwhitehorn/* 118222613Snwhitehorn * RTAS Entry Point. Similar to the OF one, but simpler (no separate stack) 119222613Snwhitehorn * 120222613Snwhitehorn * C prototype: int rtascall(void *callbuffer, void *rtas_privdat); 121222613Snwhitehorn */ 122222613Snwhitehorn 123222613SnwhitehornASENTRY(rtascall) 124222613Snwhitehorn mflr %r0 125222613Snwhitehorn stw %r0,4(%r1) 126222613Snwhitehorn 127222613Snwhitehorn /* Record the old MSR to real-mode-accessible area */ 128222613Snwhitehorn mfmsr %r0 129222613Snwhitehorn lis %r5,rtas_regsave@ha 130222613Snwhitehorn stw %r0,rtas_regsave@l(%r5) 131222613Snwhitehorn 132222613Snwhitehorn /* read client interface handler */ 133222613Snwhitehorn lis %r5,rtas_entry@ha 134222613Snwhitehorn lwz %r5,rtas_entry@l(%r5) 135222613Snwhitehorn 136222613Snwhitehorn /* Set the MSR to the RTAS value */ 137222613Snwhitehorn lis %r6,rtasmsr@ha 138222613Snwhitehorn lwz %r6,rtasmsr@l(%r6) 139222613Snwhitehorn mtmsr %r6 140222613Snwhitehorn isync 141222613Snwhitehorn 142222613Snwhitehorn /* Branch to RTAS */ 143222613Snwhitehorn mtctr %r5 144222613Snwhitehorn bctrl 145222613Snwhitehorn 146222613Snwhitehorn /* Now set the MSR back */ 147222613Snwhitehorn lis %r6,rtas_regsave@ha 148222613Snwhitehorn lwz %r6,rtas_regsave@l(%r6) 149222613Snwhitehorn mtmsr %r6 150222613Snwhitehorn isync 151222613Snwhitehorn 152222613Snwhitehorn /* And return */ 153222613Snwhitehorn lwz %r0,4(%r1) 154222613Snwhitehorn mtlr %r0 155222613Snwhitehorn blr 156222613Snwhitehorn 157