1 /* $NetBSD: process_machdep.c,v 1.31 2020/08/10 09:38:48 rin Exp $ */ 2 3 /* 4 * Copyright (c) 1993 Christopher G. Demetriou 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Christopher G. Demetriou. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * This file may seem a bit stylized, but that so that it's easier to port. 35 * Functions to be implemented here are: 36 * 37 * process_read_regs(proc, regs) 38 * Get the current user-visible register set from the process 39 * and copy it into the regs structure (<machine/reg.h>). 40 * The process is stopped at the time read_regs is called. 41 * 42 * process_write_regs(proc, regs) 43 * Update the current register set from the passed in regs 44 * structure. Take care to avoid clobbering special CPU 45 * registers or privileged bits in the PSL. 46 * The process is stopped at the time write_regs is called. 47 * 48 * process_sstep(proc) 49 * Arrange for the process to trap after executing a single instruction. 50 * 51 * process_set_pc(proc) 52 * Set the process's program counter. 53 */ 54 55 #include <sys/cdefs.h> 56 __KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.31 2020/08/10 09:38:48 rin Exp $"); 57 58 #include <sys/param.h> 59 #include <sys/systm.h> 60 #include <sys/kernel.h> 61 #include <sys/proc.h> 62 #include <sys/vnode.h> 63 #include <sys/ptrace.h> 64 65 #include <machine/frame.h> 66 #include <machine/pcb.h> 67 #include <machine/psl.h> 68 69 static inline struct frame * 70 process_frame(struct lwp *l) 71 { 72 void *ptr; 73 74 ptr = l->l_md.md_regs; 75 return ptr; 76 } 77 78 static inline struct fpframe * 79 process_fpframe(struct lwp *l) 80 { 81 struct pcb *pcb = lwp_getpcb(l); 82 83 return &pcb->pcb_fpregs; 84 } 85 86 int 87 process_read_regs(struct lwp *l, struct reg *regs) 88 { 89 struct frame *frame = process_frame(l); 90 91 memcpy(regs->r_regs, frame->f_regs, sizeof(frame->f_regs)); 92 regs->r_sr = frame->f_sr; 93 regs->r_pc = frame->f_pc; 94 95 return 0; 96 } 97 98 int 99 process_read_fpregs(struct lwp *l, struct fpreg *regs, size_t *sz) 100 { 101 struct fpframe *frame = process_fpframe(l); 102 103 memcpy(regs->r_regs, frame->fpf_regs, sizeof(frame->fpf_regs)); 104 regs->r_fpcr = frame->fpf_fpcr; 105 regs->r_fpsr = frame->fpf_fpsr; 106 regs->r_fpiar = frame->fpf_fpiar; 107 108 return 0; 109 } 110 111 int 112 process_write_regs(struct lwp *l, const struct reg *regs) 113 { 114 struct frame *frame = process_frame(l); 115 116 /* 117 * Avoid kernel address error at rte instruction. 118 */ 119 if (regs->r_pc & 1) 120 return EINVAL; 121 122 /* 123 * XXX 124 * in hp300 machdep.c, it just cleared/set these bits 125 * automatically. here, we barf. well-written programs 126 * shouldn't munge them. 127 */ 128 if ((regs->r_sr & PSL_USERCLR) != 0 || 129 (regs->r_sr & PSL_USERSET) != PSL_USERSET) 130 return EPERM; 131 132 memcpy(frame->f_regs, regs->r_regs, sizeof(frame->f_regs)); 133 frame->f_sr = regs->r_sr; 134 frame->f_pc = regs->r_pc; 135 136 return 0; 137 } 138 139 int 140 process_write_fpregs(struct lwp *l, const struct fpreg *regs, size_t sz) 141 { 142 struct fpframe *frame = process_fpframe(l); 143 144 memcpy(frame->fpf_regs, regs->r_regs, sizeof(frame->fpf_regs)); 145 frame->fpf_fpcr = regs->r_fpcr; 146 frame->fpf_fpsr = regs->r_fpsr; 147 frame->fpf_fpiar = regs->r_fpiar; 148 149 return 0; 150 } 151 152 int 153 process_sstep(struct lwp *l, int sstep) 154 { 155 struct frame *frame = process_frame(l); 156 157 if (sstep) 158 frame->f_sr |= PSL_T; 159 else 160 frame->f_sr &= ~PSL_T; 161 162 return 0; 163 } 164 165 int 166 process_set_pc(struct lwp *l, void *addr) 167 { 168 struct frame *frame = process_frame(l); 169 170 /* 171 * Avoid kernel address error at rte instruction. 172 */ 173 if ((u_int)addr & 1) 174 return EINVAL; 175 frame->f_pc = (u_int)addr; 176 177 return 0; 178 } 179