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