/*-1* Copyright (C) 2009-2011 Nathan Whitehorn2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR14* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES15* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.16* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,17* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,18* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;19* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,20* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR21* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF22* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.23*/2425#include <sys/syscall.h>2627#include <machine/trap.h>28#include <machine/param.h>29#include <machine/spr.h>30#include <machine/asm.h>3132#define OFWSTKSZ 4096 /* 4K Open Firmware stack */3334/*35* Globals36*/37.data38GLOBAL(ofmsr)39.long 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */40GLOBAL(rtasmsr)41.long 042GLOBAL(openfirmware_entry)43.long 0 /* Open Firmware entry point */44GLOBAL(rtas_entry)45.long 0 /* RTAS entry point */4647.align 448ofwstk:49.space OFWSTKSZ50rtas_regsave:51.space 45253/*54* Open Firmware Entry Point. May need to enter real mode.55*56* C prototype: int ofwcall(void *callbuffer);57*/5859ASENTRY(ofwcall)60mflr %r061stw %r0,4(%r1)6263/* Record the old MSR */64mfmsr %r66566/* GOT pointer in r7 */67bl 1f681:69mflr %r770addis %r7,%r7,(_GLOBAL_OFFSET_TABLE_-1b)@ha71addi %r7,%r7,(_GLOBAL_OFFSET_TABLE_-1b)@l7273/* read client interface handler */74lwz %r4,openfirmware_entry@got(%r7)75lwz %r4,0(%r4)7677/*78* Set the MSR to the OF value. This has the side effect of disabling79* exceptions, which prevents preemption later.80*/8182lwz %r5,ofmsr@got(%r7)83lwz %r5,0(%r5)84mtmsr %r585isync8687/*88* Set up OF stack. This needs to be potentially accessible in real mode89* The pointer to the current kernel stack is placed at the very90* top of the stack along with the old MSR so we can get them back91* later.92*/93mr %r5,%r194lwz %r1,ofwstk@got(%r7)95addi %r1,%r1,(OFWSTKSZ-32)96stw %r5,20(%r1) /* Save real stack pointer */97stw %r2,24(%r1) /* Save curthread */98stw %r6,28(%r1) /* Save old MSR */99li %r5,0100stw %r5,4(%r1)101stw %r5,0(%r1)102103/* Finally, branch to OF */104mtctr %r4105bctrl106107/* Reload stack pointer and MSR from the OFW stack */108lwz %r6,28(%r1)109lwz %r2,24(%r1)110lwz %r1,20(%r1)111112/* Now set the real MSR */113mtmsr %r6114isync115116/* Return */117lwz %r0,4(%r1)118mtlr %r0119blr120ASEND(ofwcall)121122/*123* RTAS Entry Point. Similar to the OF one, but simpler (no separate stack)124*125* C prototype: int rtascall(void *callbuffer, void *rtas_privdat);126*/127128ASENTRY(rtascall)129mflr %r0130stw %r0,4(%r1)131132/* GOT pointer in r7 */133bl 1f1341:135mflr %r7136addis %r7,%r7,(_GLOBAL_OFFSET_TABLE_-1b)@ha137addi %r7,%r7,(_GLOBAL_OFFSET_TABLE_-1b)@l138139/* Record the old MSR to real-mode-accessible area */140mfmsr %r0141lwz %r5,rtas_regsave@got(%r7)142stw %r0,0(%r5)143144/* read client interface handler */145lwz %r5,rtas_entry@got(%r7)146lwz %r5,0(%r5)147148/* Set the MSR to the RTAS value */149lwz %r6,rtasmsr@got(%r7)150lwz %r6,0(%r6)151mtmsr %r6152isync153154/* Branch to RTAS */155mtctr %r5156bctrl157158/* GOT pointer in r7 */159bl 1f1601:161mflr %r7162addis %r7,%r7,(_GLOBAL_OFFSET_TABLE_-1b)@ha163addi %r7,%r7,(_GLOBAL_OFFSET_TABLE_-1b)@l164165/* Now set the MSR back */166lwz %r6,rtas_regsave@got(%r7)167lwz %r6,0(%r6)168mtmsr %r6169isync170171/* And return */172lwz %r0,4(%r1)173mtlr %r0174blr175ASEND(rtascall)176177178