2 * Copyright (c) 2004 Peter Grehan.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <machine/asm.h>
28 __FBSDID("$FreeBSD$");
33 * int _ppc32_getcontext(mcontext_t *mcp)
35 * Save register state from a voluntary context switch.
36 * Only volatile registers, and those needed to complete
37 * a setcontext call, need to be saved.
44 * Return 0 for this call, and set up the context so it will return
45 * 1 when restored with _ppc32_setcontext().
48 * Floating-point is a big issue. Since there's no way to determine
49 * if the caller has used FP, all volatile register need to be saved.
50 * If FP hasn't been used, this results in a lazy FP exception in
51 * the kernel and from that point on FP is always switched in/out
52 * for the thread, which may be a big performance drag for the system.
53 * An alternative is to use a system call to get the context, which
54 * will do the right thing for floating point, but will save all
55 * registers rather than the caller-saved subset, and has the overhead
57 * Maybe another option would be to give a light-weight way for a
58 * thread to determine if FP is in used: perhaps a syscall that
59 * returns in the asm traphandler, or an OSX-style read-only page
60 * with a flag to indicate FP state.
62 * For now, punt the issue ala Alpha 1:1 model and fix in the future.
64 ENTRY(_ppc32_getcontext)
66 stw %r13, _MC_R13(%r3)
67 stw %r14, _MC_R14(%r3)
68 stw %r15, _MC_R15(%r3)
69 stw %r16, _MC_R16(%r3)
70 stw %r17, _MC_R17(%r3)
71 stw %r18, _MC_R18(%r3)
72 stw %r19, _MC_R19(%r3)
73 stw %r20, _MC_R20(%r3)
74 stw %r21, _MC_R21(%r3)
75 stw %r22, _MC_R22(%r3)
76 stw %r23, _MC_R23(%r3)
77 stw %r24, _MC_R24(%r3)
78 stw %r25, _MC_R25(%r3)
79 stw %r26, _MC_R26(%r3)
80 stw %r27, _MC_R27(%r3)
81 stw %r28, _MC_R28(%r3)
82 stw %r29, _MC_R28(%r3)
83 stw %r30, _MC_R30(%r3)
84 stw %r31, _MC_R31(%r3)
92 li %r4, _MC_VERSION_KSE /* partial ucontext version */
93 stw %r4, _MC_VERS(%r3)
100 * int _ppc32_setcontext(const mcontext_t *mcp, intptr_t val,
103 * Should only be called for partial KSE contexts. The full context
104 * case is handled by kse_switchin() in _thread_switch()
106 * Returns -1 on error and 1 for return from a saved context
109 ENTRY(_ppc32_setcontext)
110 lwz %r6, _MC_VERS(%r3)
111 cmpwi %r6, _MC_VERSION_KSE /* KSE partial context ? */
113 li %r3, -1 /* invalid context type, return -1 */
116 1: /* partial format, callee-saved regs assumed */
118 lwz %r13, _MC_R13(%r3)
119 lwz %r14, _MC_R14(%r3)
120 lwz %r15, _MC_R15(%r3)
121 lwz %r16, _MC_R16(%r3)
122 lwz %r17, _MC_R17(%r3)
123 lwz %r18, _MC_R18(%r3)
124 lwz %r19, _MC_R19(%r3)
125 lwz %r20, _MC_R20(%r3)
126 lwz %r21, _MC_R21(%r3)
127 lwz %r22, _MC_R22(%r3)
128 lwz %r23, _MC_R23(%r3)
129 lwz %r24, _MC_R24(%r3)
130 lwz %r25, _MC_R25(%r3)
131 lwz %r26, _MC_R26(%r3)
132 lwz %r27, _MC_R27(%r3)
133 lwz %r28, _MC_R28(%r3)
134 lwz %r29, _MC_R28(%r3)
135 lwz %r30, _MC_R30(%r3)
136 lwz %r31, _MC_R31(%r3)
144 /* if (loc != NULL) *loc = val */