1132400Sgrehan/* 2132400Sgrehan * Copyright (c) 2004 Peter Grehan. 3132400Sgrehan * All rights reserved. 4132400Sgrehan * 5132400Sgrehan * Redistribution and use in source and binary forms, with or without 6132400Sgrehan * modification, are permitted provided that the following conditions 7132400Sgrehan * are met: 8132400Sgrehan * 1. Redistributions of source code must retain the above copyright 9132400Sgrehan * notice, this list of conditions and the following disclaimer. 10132400Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 11132400Sgrehan * notice, this list of conditions and the following disclaimer in the 12132400Sgrehan * documentation and/or other materials provided with the distribution. 13132400Sgrehan * 14132400Sgrehan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15132400Sgrehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16132400Sgrehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17132400Sgrehan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18132400Sgrehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19132400Sgrehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20132400Sgrehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21132400Sgrehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22132400Sgrehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23132400Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24132400Sgrehan * SUCH DAMAGE. 25132400Sgrehan */ 26132400Sgrehan 27132400Sgrehan#include <machine/asm.h> 28132400Sgrehan__FBSDID("$FreeBSD$"); 29132400Sgrehan 30132400Sgrehan#include "assym.s" 31132400Sgrehan 32132400Sgrehan/* 33132400Sgrehan * int _ppc32_getcontext(mcontext_t *mcp) 34132400Sgrehan * 35132400Sgrehan * Save register state from a voluntary context switch. 36132400Sgrehan * Only volatile registers, and those needed to complete 37132400Sgrehan * a setcontext call, need to be saved. 38132400Sgrehan * 39132400Sgrehan * r1 40132400Sgrehan * r14-31 41132400Sgrehan * f14-31 XXX 42132400Sgrehan * lr 43132400Sgrehan * 44132400Sgrehan * Return 0 for this call, and set up the context so it will return 45132400Sgrehan * 1 when restored with _ppc32_setcontext(). 46132400Sgrehan * 47132400Sgrehan * XXX XXX 48132400Sgrehan * Floating-point is a big issue. Since there's no way to determine 49132400Sgrehan * if the caller has used FP, all volatile register need to be saved. 50132400Sgrehan * If FP hasn't been used, this results in a lazy FP exception in 51132400Sgrehan * the kernel and from that point on FP is always switched in/out 52132400Sgrehan * for the thread, which may be a big performance drag for the system. 53132400Sgrehan * An alternative is to use a system call to get the context, which 54132400Sgrehan * will do the right thing for floating point, but will save all 55132400Sgrehan * registers rather than the caller-saved subset, and has the overhead 56132400Sgrehan * of a syscall. 57132400Sgrehan * Maybe another option would be to give a light-weight way for a 58132400Sgrehan * thread to determine if FP is in used: perhaps a syscall that 59132400Sgrehan * returns in the asm traphandler, or an OSX-style read-only page 60132400Sgrehan * with a flag to indicate FP state. 61132400Sgrehan * 62132400Sgrehan * For now, punt the issue ala Alpha 1:1 model and fix in the future. 63132400Sgrehan */ 64132400SgrehanENTRY(_ppc32_getcontext) 65132400Sgrehan stw %r1, _MC_R1(%r3) 66132400Sgrehan stw %r13, _MC_R13(%r3) 67132400Sgrehan stw %r14, _MC_R14(%r3) 68132400Sgrehan stw %r15, _MC_R15(%r3) 69132400Sgrehan stw %r16, _MC_R16(%r3) 70132400Sgrehan stw %r17, _MC_R17(%r3) 71132400Sgrehan stw %r18, _MC_R18(%r3) 72132400Sgrehan stw %r19, _MC_R19(%r3) 73132400Sgrehan stw %r20, _MC_R20(%r3) 74132400Sgrehan stw %r21, _MC_R21(%r3) 75132400Sgrehan stw %r22, _MC_R22(%r3) 76132400Sgrehan stw %r23, _MC_R23(%r3) 77132400Sgrehan stw %r24, _MC_R24(%r3) 78132400Sgrehan stw %r25, _MC_R25(%r3) 79132400Sgrehan stw %r26, _MC_R26(%r3) 80132400Sgrehan stw %r27, _MC_R27(%r3) 81132400Sgrehan stw %r28, _MC_R28(%r3) 82132400Sgrehan stw %r29, _MC_R28(%r3) 83132400Sgrehan stw %r30, _MC_R30(%r3) 84132400Sgrehan stw %r31, _MC_R31(%r3) 85132400Sgrehan mflr %r4 86132400Sgrehan stw %r4, _MC_LR(%r3) 87132400Sgrehan mfcr %r4 88132400Sgrehan stw %r4, _MC_CR(%r3) 89132400Sgrehan 90132400Sgrehan /* XXX f14-31 ? */ 91132400Sgrehan 92132400Sgrehan li %r4, _MC_VERSION_KSE /* partial ucontext version */ 93132400Sgrehan stw %r4, _MC_VERS(%r3) 94132400Sgrehan 95132400Sgrehan /* Return 0 */ 96132400Sgrehan li %r3, 0 97132400Sgrehan blr 98132400Sgrehan 99132400Sgrehan/* 100132400Sgrehan * int _ppc32_setcontext(const mcontext_t *mcp, intptr_t val, 101132400Sgrehan * intptr_t *loc); 102132400Sgrehan * 103132400Sgrehan * Should only be called for partial KSE contexts. The full context 104132400Sgrehan * case is handled by kse_switchin() in _thread_switch() 105132400Sgrehan * 106132400Sgrehan * Returns -1 on error and 1 for return from a saved context 107132400Sgrehan */ 108132400Sgrehan 109132400SgrehanENTRY(_ppc32_setcontext) 110132400Sgrehan lwz %r6, _MC_VERS(%r3) 111132400Sgrehan cmpwi %r6, _MC_VERSION_KSE /* KSE partial context ? */ 112132400Sgrehan beq 1f 113132400Sgrehan li %r3, -1 /* invalid context type, return -1 */ 114132400Sgrehan blr 115132400Sgrehan 116132400Sgrehan1: /* partial format, callee-saved regs assumed */ 117132400Sgrehan lwz %r1, _MC_R1(%r3) 118132400Sgrehan lwz %r13, _MC_R13(%r3) 119132400Sgrehan lwz %r14, _MC_R14(%r3) 120132400Sgrehan lwz %r15, _MC_R15(%r3) 121132400Sgrehan lwz %r16, _MC_R16(%r3) 122132400Sgrehan lwz %r17, _MC_R17(%r3) 123132400Sgrehan lwz %r18, _MC_R18(%r3) 124132400Sgrehan lwz %r19, _MC_R19(%r3) 125132400Sgrehan lwz %r20, _MC_R20(%r3) 126132400Sgrehan lwz %r21, _MC_R21(%r3) 127132400Sgrehan lwz %r22, _MC_R22(%r3) 128132400Sgrehan lwz %r23, _MC_R23(%r3) 129132400Sgrehan lwz %r24, _MC_R24(%r3) 130132400Sgrehan lwz %r25, _MC_R25(%r3) 131132400Sgrehan lwz %r26, _MC_R26(%r3) 132132400Sgrehan lwz %r27, _MC_R27(%r3) 133132400Sgrehan lwz %r28, _MC_R28(%r3) 134132400Sgrehan lwz %r29, _MC_R28(%r3) 135132400Sgrehan lwz %r30, _MC_R30(%r3) 136132400Sgrehan lwz %r31, _MC_R31(%r3) 137132400Sgrehan lwz %r6, _MC_LR(%r3) 138132400Sgrehan mtlr %r6 139132400Sgrehan lwz %r6, _MC_CR(%r3) 140132400Sgrehan mtcr %r6 141132400Sgrehan 142132400Sgrehan /* XXX f14-31 ? */ 143132400Sgrehan 144132400Sgrehan /* if (loc != NULL) *loc = val */ 145132400Sgrehan cmpwi %r5, 0 146132400Sgrehan beq 2f 147132400Sgrehan stw %r4, 0(%r5) 148132400Sgrehan 149132400Sgrehan /* Return 1 */ 150132400Sgrehan2: li %r3, 1 151132400Sgrehan blr 152