xref: /netbsd/sys/arch/arm/arm/process_machdep.c (revision bf9ec67e)
1 /*	$NetBSD: process_machdep.c,v 1.9 2001/11/24 01:26:23 thorpej 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 
71 #include <sys/param.h>
72 
73 __KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.9 2001/11/24 01:26:23 thorpej Exp $");
74 
75 #include <sys/proc.h>
76 #include <sys/ptrace.h>
77 #include <sys/systm.h>
78 #include <sys/user.h>
79 
80 #include <machine/frame.h>
81 #include <machine/pcb.h>
82 #include <machine/reg.h>
83 
84 #include <arm/armreg.h>
85 
86 #ifdef ARMFPE
87 #include <arm/fpe-arm/armfpe.h>
88 #endif
89 
90 static __inline struct trapframe *
91 process_frame(struct proc *p)
92 {
93 
94 	return p->p_addr->u_pcb.pcb_tf;
95 }
96 
97 int
98 process_read_regs(struct proc *p, struct reg *regs)
99 {
100 	struct trapframe *tf = process_frame(p);
101 
102 	KASSERT(tf != NULL);
103 	bcopy((caddr_t)&tf->tf_r0, (caddr_t)regs->r, sizeof(regs->r));
104 	regs->r_sp = tf->tf_usr_sp;
105 	regs->r_lr = tf->tf_usr_lr;
106 	regs->r_pc = tf->tf_pc;
107 	regs->r_cpsr = tf->tf_spsr;
108 
109 #ifdef DIAGNOSTIC
110 	if ((tf->tf_spsr & PSR_MODE) == PSR_USR32_MODE
111 	    && tf->tf_spsr & I32_bit)
112 		panic("process_read_regs: Interrupts blocked in user process");
113 #endif
114 
115 	return(0);
116 }
117 
118 int
119 process_read_fpregs(struct proc *p, struct fpreg *regs)
120 {
121 #ifdef ARMFPE
122 	arm_fpe_getcontext(p, regs);
123 	return(0);
124 #else	/* ARMFPE */
125 	/* No hardware FP support */
126 	memset(regs, 0, sizeof(struct fpreg));
127 	return(0);
128 #endif	/* ARMFPE */
129 }
130 
131 int
132 process_write_regs(struct proc *p, struct reg *regs)
133 {
134 	struct trapframe *tf = process_frame(p);
135 
136 	KASSERT(tf != NULL);
137 	bcopy((caddr_t)regs->r, (caddr_t)&tf->tf_r0, sizeof(regs->r));
138 	tf->tf_usr_sp = regs->r_sp;
139 	tf->tf_usr_lr = regs->r_lr;
140 #ifdef __PROG32
141 	tf->tf_pc = regs->r_pc;
142 	tf->tf_spsr &=  ~PSR_FLAGS;
143 	tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS;
144 #ifdef DIAGNOSTIC
145 	if ((tf->tf_spsr & PSR_MODE) == PSR_USR32_MODE
146 	    && tf->tf_spsr & I32_bit)
147 		panic("process_write_regs: Interrupts blocked in user process");
148 #endif
149 #else /* __PROG26 */
150 	if ((regs->r_pc & (R15_MODE | R15_IRQ_DISABLE | R15_FIQ_DISABLE)) != 0)
151 		return EPERM;
152 
153 	tf->tf_r15 = regs->r_pc;
154 #endif
155 
156 	return(0);
157 }
158 
159 int
160 process_write_fpregs(struct proc *p,  struct fpreg *regs)
161 {
162 #ifdef ARMFPE
163 	arm_fpe_setcontext(p, regs);
164 	return(0);
165 #else	/* ARMFPE */
166 	/* No hardware FP support */
167 	return(0);
168 #endif	/* ARMFPE */
169 }
170 
171 int
172 process_set_pc(struct proc *p, caddr_t addr)
173 {
174 	struct trapframe *tf = process_frame(p);
175 
176 	KASSERT(tf != NULL);
177 #ifdef __PROG32
178 	tf->tf_pc = (int)addr;
179 #else /* __PROG26 */
180 	/* Only set the PC, not the PSR */
181 	if (((register_t)addr & R15_PC) != (register_t)addr)
182 		return EINVAL;
183 	tf->tf_r15 = (tf->tf_r15 & ~R15_PC) | (register_t)addr;
184 #endif
185 
186 	return (0);
187 }
188