1 /*	$OpenBSD: process_machdep.c,v 1.5 2021/01/09 13:14:02 kettenis Exp $	*/
2 
3 /*
4  * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/proc.h>
22 #include <sys/ptrace.h>
23 #include <sys/user.h>
24 
25 #include <machine/fpu.h>
26 #include <machine/pcb.h>
27 #include <machine/psl.h>
28 #include <machine/reg.h>
29 
30 int
process_read_regs(struct proc * p,struct reg * regs)31 process_read_regs(struct proc *p, struct reg *regs)
32 {
33 	struct trapframe *tf = p->p_md.md_regs;
34 
35 	memcpy(regs->r_reg, tf->fixreg, sizeof(regs->r_reg));
36 
37 	regs->r_lr = tf->lr;
38 	regs->r_cr = tf->cr;
39 	regs->r_xer = tf->xer;
40 	regs->r_ctr = tf->ctr;
41 	regs->r_pc = tf->srr0;
42 	regs->r_ps = tf->srr1;
43 
44 	return 0;
45 }
46 
47 int
process_read_fpregs(struct proc * p,struct fpreg * regs)48 process_read_fpregs(struct proc *p, struct fpreg *regs)
49 {
50 	struct trapframe *tf = p->p_md.md_regs;
51 	struct pcb *pcb = &p->p_addr->u_pcb;
52 
53 	if (tf->srr1 & (PSL_FPU|PSL_VEC|PSL_VSX)) {
54 		tf->srr1 &= ~(PSL_FPU|PSL_VEC|PSL_VSX);
55 		save_vsx(p);
56 	}
57 
58 	if (pcb->pcb_flags & (PCB_FPU|PCB_VEC|PCB_VSX))
59 		memcpy(regs, &pcb->pcb_fpstate, sizeof(*regs));
60 	else
61 		memset(regs, 0, sizeof(*regs));
62 
63 	regs->fp_vrsave = tf->vrsave;
64 
65 	return 0;
66 }
67 
68 #ifdef PTRACE
69 
70 /*
71  * Set the process's program counter.
72  */
73 int
process_set_pc(struct proc * p,caddr_t addr)74 process_set_pc(struct proc *p, caddr_t addr)
75 {
76 	struct trapframe *tf = p->p_md.md_regs;
77 
78 	tf->srr0 = (register_t)addr;
79 
80 	return 0;
81 }
82 
83 int
process_sstep(struct proc * p,int sstep)84 process_sstep(struct proc *p, int sstep)
85 {
86 	struct trapframe *tf = p->p_md.md_regs;
87 
88 	if (sstep)
89 		tf->srr1 |= PSL_SE;
90 	else
91 		tf->srr1 &= ~PSL_SE;
92 
93 	return 0;
94 }
95 
96 int
process_write_regs(struct proc * p,struct reg * regs)97 process_write_regs(struct proc *p, struct reg *regs)
98 {
99 	struct trapframe *tf = p->p_md.md_regs;
100 
101 	regs->r_ps &= ~(PSL_FPU|PSL_VEC|PSL_VSX);
102 	regs->r_ps |= (tf->srr1 & (PSL_FPU|PSL_VEC|PSL_VSX));
103 
104 	if (regs->r_ps != tf->srr1)
105 		return EINVAL;
106 
107 	memcpy(tf->fixreg, regs->r_reg, sizeof(regs->r_reg));
108 
109 	tf->lr = regs->r_lr;
110 	tf->cr = regs->r_cr;
111 	tf->xer = regs->r_xer;
112 	tf->ctr = regs->r_ctr;
113 	tf->srr0 = regs->r_pc;
114 	tf->srr1 = regs->r_ps;
115 
116 	return 0;
117 }
118 
119 int
process_write_fpregs(struct proc * p,struct fpreg * regs)120 process_write_fpregs(struct proc *p, struct fpreg *regs)
121 {
122 	struct trapframe *tf = p->p_md.md_regs;
123 	struct pcb *pcb = &p->p_addr->u_pcb;
124 
125 	tf->srr1 &= ~(PSL_FPU|PSL_VEC|PSL_VSX);
126 	memcpy(&pcb->pcb_fpstate, regs, sizeof(*regs));
127 	pcb->pcb_flags |= (PCB_FPU|PCB_VEC|PCB_VSX);
128 
129 	tf->vrsave = regs->fp_vrsave;
130 
131 	return 0;
132 }
133 
134 #endif	/* PTRACE */
135