xref: /netbsd-src/sys/arch/arm/arm/process_machdep.c (revision 06be8101a16cc95f40783b3cb7afd12112103a9a)
1 /*	$NetBSD: process_machdep.c,v 1.7 2001/10/27 16:48:50 rearnsha Exp $	*/
2 
3 /*
4  * Copyright (c) 1995 Frank Lancaster.  All rights reserved.
5  * Copyright (c) 1995 Tools GmbH.  All rights reserved.
6  * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
7  * Copyright (c) 1993 The Regents of the University of California.
8  * Copyright (c) 1993 Jan-Simon Pendry
9  * All rights reserved.
10  *
11  * This code is derived from software contributed to Berkeley by
12  * Jan-Simon Pendry.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. All advertising materials mentioning features or use of this software
23  *    must display the following acknowledgement:
24  *	This product includes software developed by the University of
25  *	California, Berkeley and its contributors.
26  * 4. Neither the name of the University nor the names of its contributors
27  *    may be used to endorse or promote products derived from this software
28  *    without specific prior written permission.
29  *
30  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40  * SUCH DAMAGE.
41  *
42  * From:
43  *	Id: procfs_i386.c,v 4.1 1993/12/17 10:47:45 jsp Rel
44  */
45 
46 /*
47  * This file may seem a bit stylized, but that so that it's easier to port.
48  * Functions to be implemented here are:
49  *
50  * process_read_regs(proc, regs)
51  *	Get the current user-visible register set from the process
52  *	and copy it into the regs structure (<machine/reg.h>).
53  *	The process is stopped at the time read_regs is called.
54  *
55  * process_write_regs(proc, regs)
56  *	Update the current register set from the passed in regs
57  *	structure.  Take care to avoid clobbering special CPU
58  *	registers or privileged bits in the PSL.
59  *	The process is stopped at the time write_regs is called.
60  *
61  * process_sstep(proc, sstep)
62  *	Arrange for the process to trap or not trap depending on sstep
63  *	after executing a single instruction.
64  *
65  * process_set_pc(proc)
66  *	Set the process's program counter.
67  */
68 
69 #include "opt_armfpe.h"
70 #include "opt_progmode.h"
71 
72 #include <sys/param.h>
73 
74 __KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.7 2001/10/27 16:48:50 rearnsha Exp $");
75 
76 #include <sys/proc.h>
77 #include <sys/ptrace.h>
78 #include <sys/systm.h>
79 #include <sys/user.h>
80 
81 #include <machine/frame.h>
82 #include <machine/pcb.h>
83 #include <machine/reg.h>
84 
85 #include <arm/armreg.h>
86 
87 #ifdef ARMFPE
88 #include <arm32/fpe-arm/armfpe.h>
89 #endif	/* ARMFPE */
90 
91 static __inline struct trapframe *
92 process_frame(struct proc *p)
93 {
94 
95 	return p->p_addr->u_pcb.pcb_tf;
96 }
97 
98 int
99 process_read_regs(struct proc *p, struct reg *regs)
100 {
101 	struct trapframe *tf = process_frame(p);
102 
103 	KASSERT(tf != NULL);
104 	bcopy((caddr_t)&tf->tf_r0, (caddr_t)regs->r, sizeof(regs->r));
105 	regs->r_sp = tf->tf_usr_sp;
106 	regs->r_lr = tf->tf_usr_lr;
107 	regs->r_pc = tf->tf_pc;
108 	regs->r_cpsr = tf->tf_spsr;
109 
110 #ifdef DIAGNOSTIC
111 	if ((tf->tf_spsr & PSR_MODE) == PSR_USR32_MODE
112 	    && tf->tf_spsr & I32_bit)
113 		panic("process_read_regs: Interrupts blocked in user process");
114 #endif
115 
116 	return(0);
117 }
118 
119 int
120 process_read_fpregs(struct proc *p, struct fpreg *regs)
121 {
122 #ifdef ARMFPE
123 	arm_fpe_getcontext(p, regs);
124 	return(0);
125 #else	/* ARMFPE */
126 	/* No hardware FP support */
127 	memset(regs, 0, sizeof(struct fpreg));
128 	return(0);
129 #endif	/* ARMFPE */
130 }
131 
132 int
133 process_write_regs(struct proc *p, struct reg *regs)
134 {
135 	struct trapframe *tf = process_frame(p);
136 
137 	KASSERT(tf != NULL);
138 	bcopy((caddr_t)regs->r, (caddr_t)&tf->tf_r0, sizeof(regs->r));
139 	tf->tf_usr_sp = regs->r_sp;
140 	tf->tf_usr_lr = regs->r_lr;
141 #ifdef PROG32
142 	tf->tf_pc = regs->r_pc;
143 	tf->tf_spsr &=  ~PSR_FLAGS;
144 	tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS;
145 #ifdef DIAGNOSTIC
146 	if ((tf->tf_spsr & PSR_MODE) == PSR_USR32_MODE
147 	    && tf->tf_spsr & I32_bit)
148 		panic("process_write_regs: Interrupts blocked in user process");
149 #endif
150 #else /* PROG26 */
151 	if ((regs->r_pc & (R15_MODE | R15_IRQ_DISABLE | R15_FIQ_DISABLE)) != 0)
152 		return EPERM;
153 
154 	tf->tf_r15 = regs->r_pc;
155 #endif
156 
157 	return(0);
158 }
159 
160 int
161 process_write_fpregs(struct proc *p,  struct fpreg *regs)
162 {
163 #ifdef ARMFPE
164 	arm_fpe_setcontext(p, regs);
165 	return(0);
166 #else	/* ARMFPE */
167 	/* No hardware FP support */
168 	return(0);
169 #endif	/* ARMFPE */
170 }
171 
172 int
173 process_set_pc(struct proc *p, caddr_t addr)
174 {
175 	struct trapframe *tf = process_frame(p);
176 
177 	KASSERT(tf != NULL);
178 #ifdef PROG32
179 	tf->tf_pc = (int)addr;
180 #else /* PROG26 */
181 	/* Only set the PC, not the PSR */
182 	if (((register_t)addr & R15_PC) != (register_t)addr)
183 		return EINVAL;
184 	tf->tf_r15 = (tf->tf_r15 & ~R15_PC) | (register_t)addr;
185 #endif
186 
187 	return (0);
188 }
189