1 /* $OpenBSD: process_machdep.c,v 1.13 2007/09/09 20:49:18 kettenis Exp $ */
2 /* $NetBSD: process_machdep.c,v 1.1 1996/09/30 16:34:53 ws Exp $ */
3
4 /*
5 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
6 * Copyright (C) 1995, 1996 TooLs GmbH.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by TooLs GmbH.
20 * 4. The name of TooLs GmbH may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/proc.h>
37 #include <sys/ptrace.h>
38 #include <sys/user.h>
39
40 #include <machine/fpu.h>
41 #include <machine/pcb.h>
42 #include <machine/psl.h>
43 #include <machine/reg.h>
44
45 int
process_read_regs(struct proc * p,struct reg * regs)46 process_read_regs(struct proc *p, struct reg *regs)
47 {
48 struct cpu_info *ci = curcpu();
49 struct trapframe *tf = trapframe(p);
50 struct pcb *pcb = &p->p_addr->u_pcb;
51
52 bcopy(tf->fixreg, regs->gpr, sizeof(regs->gpr));
53
54 if (!(pcb->pcb_flags & PCB_FPU)) {
55 bzero(regs->fpr, sizeof(regs->fpr));
56 } else {
57 /* XXX What if the state is on the other cpu? */
58 if (p == ci->ci_fpuproc)
59 save_fpu();
60 bcopy(pcb->pcb_fpu.fpr, regs->fpr, sizeof(regs->fpr));
61 }
62
63 regs->pc = tf->srr0;
64 regs->ps = tf->srr1; /* is this the correct value for this ? */
65 regs->cnd = tf->cr;
66 regs->lr = tf->lr;
67 regs->cnt = tf->ctr;
68 regs->xer = tf->xer;
69 regs->mq = 0; /* what should this really be? */
70
71 return (0);
72 }
73
74 int
process_read_fpregs(struct proc * p,struct fpreg * regs)75 process_read_fpregs(struct proc *p, struct fpreg *regs)
76 {
77 struct cpu_info *ci = curcpu();
78 struct pcb *pcb = &p->p_addr->u_pcb;
79
80 if (!(pcb->pcb_flags & PCB_FPU)) {
81 bzero(regs->fpr, sizeof(regs->fpr));
82 regs->fpscr = 0;
83 } else {
84 /* XXX What if the state is on the other cpu? */
85 if (p == ci->ci_fpuproc)
86 save_fpu();
87 bcopy(pcb->pcb_fpu.fpr, regs->fpr, sizeof(regs->fpr));
88 regs->fpscr = *(u_int64_t *)&pcb->pcb_fpu.fpcsr;
89 }
90
91 return (0);
92 }
93
94 #ifdef PTRACE
95
96 /*
97 * Set the process's program counter.
98 */
99 int
process_set_pc(struct proc * p,caddr_t addr)100 process_set_pc(struct proc *p, caddr_t addr)
101 {
102 struct trapframe *tf = trapframe(p);
103
104 tf->srr0 = (u_int32_t)addr;
105 return 0;
106 }
107
108 int
process_sstep(struct proc * p,int sstep)109 process_sstep(struct proc *p, int sstep)
110 {
111 struct trapframe *tf = trapframe(p);
112
113 if (sstep)
114 tf->srr1 |= PSL_SE;
115 else
116 tf->srr1 &= ~PSL_SE;
117 return 0;
118 }
119
120 int
process_write_regs(struct proc * p,struct reg * regs)121 process_write_regs(struct proc *p, struct reg *regs)
122 {
123 struct cpu_info *ci = curcpu();
124 struct trapframe *tf = trapframe(p);
125 struct pcb *pcb = &p->p_addr->u_pcb;
126
127 if ((regs->ps ^ tf->srr1) & PSL_USERSTATIC)
128 return EINVAL;
129
130 bcopy(regs->gpr, tf->fixreg, sizeof(regs->gpr));
131
132 /* XXX What if the state is on the other cpu? */
133 if (p == ci->ci_fpuproc) { /* release the fpu */
134 save_fpu();
135 ci->ci_fpuproc = NULL;
136 }
137
138 bcopy(regs->fpr, pcb->pcb_fpu.fpr, sizeof(regs->fpr));
139 if (!(pcb->pcb_flags & PCB_FPU)) {
140 pcb->pcb_fpu.fpcsr = 0;
141 pcb->pcb_flags |= PCB_FPU;
142 }
143
144 tf->srr0 = regs->pc;
145 tf->srr1 = regs->ps; /* is this the correct value for this ? */
146 tf->cr = regs->cnd;
147 tf->lr = regs->lr;
148 tf->ctr = regs->cnt;
149 tf->xer = regs->xer;
150 /* regs->mq = 0; what should this really be? */
151
152 return (0);
153 }
154
155 int
process_write_fpregs(struct proc * p,struct fpreg * regs)156 process_write_fpregs(struct proc *p, struct fpreg *regs)
157 {
158 struct cpu_info *ci = curcpu();
159 struct pcb *pcb = &p->p_addr->u_pcb;
160 u_int64_t fpscr = regs->fpscr;
161
162 /* XXX What if the state is on the other cpu? */
163 if (p == ci->ci_fpuproc) { /* release the fpu */
164 save_fpu();
165 ci->ci_fpuproc = NULL;
166 }
167
168 bcopy(regs->fpr, pcb->pcb_fpu.fpr, sizeof(regs->fpr));
169 pcb->pcb_fpu.fpcsr = *(double *)&fpscr;
170 pcb->pcb_flags |= PCB_FPU;
171
172 return (0);
173 }
174
175 #endif /* PTRACE */
176