xref: /openbsd-src/sys/arch/arm64/arm64/process_machdep.c (revision 999a7581f82160625628ebcc08d79b3c296a7d3b)
1 /* $OpenBSD: process_machdep.c,v 1.9 2024/10/14 12:02:16 jsg Exp $ */
2 /*
3  * Copyright (c) 2014 Patrick Wildt <patrick@blueri.se>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /*
19  * This file may seem a bit stylized, but that so that it's easier to port.
20  * Functions to be implemented here are:
21  *
22  * process_read_regs(proc, regs)
23  *	Get the current user-visible register set from the process
24  *	and copy it into the regs structure (<machine/reg.h>).
25  *	The process is stopped at the time read_regs is called.
26  *
27  * process_write_regs(proc, regs)
28  *	Update the current register set from the passed in regs
29  *	structure.  Take care to avoid clobbering special CPU
30  *	registers or privileged bits in the PSL.
31  *	The process is stopped at the time write_regs is called.
32  *
33  * process_sstep(proc, sstep)
34  *	Arrange for the process to trap or not trap depending on sstep
35  *	after executing a single instruction.
36  *
37  * process_set_pc(proc)
38  *	Set the process's program counter.
39  */
40 
41 #include <sys/param.h>
42 
43 #include <sys/proc.h>
44 #include <sys/ptrace.h>
45 #include <sys/systm.h>
46 #include <sys/user.h>
47 
48 #include <machine/fpu.h>
49 #include <machine/pcb.h>
50 #include <machine/reg.h>
51 #include <machine/vmparam.h>
52 
53 #include <arm64/armreg.h>
54 
55 int
56 process_read_regs(struct proc *p, struct reg *regs)
57 {
58 	struct trapframe *tf = p->p_addr->u_pcb.pcb_tf;
59 
60 	memcpy(&regs->r_reg[0], &tf->tf_x[0], sizeof(regs->r_reg));
61 	regs->r_lr = tf->tf_lr;
62 	regs->r_sp = tf->tf_sp;
63 	regs->r_pc = tf->tf_elr;
64 	regs->r_spsr = tf->tf_spsr;
65 	regs->r_tpidr = (uint64_t)p->p_addr->u_pcb.pcb_tcb;
66 
67 	return(0);
68 }
69 
70 int
71 process_read_fpregs(struct proc *p, struct fpreg *regs)
72 {
73 	if (p->p_addr->u_pcb.pcb_flags & PCB_FPU)
74 		fpu_save(p);
75 
76 	if (p->p_addr->u_pcb.pcb_flags & PCB_FPU)
77 		memcpy(regs, &p->p_addr->u_pcb.pcb_fpstate, sizeof(*regs));
78 	else
79 		memset(regs, 0, sizeof(*regs));
80 
81 	return(0);
82 }
83 
84 #ifdef	PTRACE
85 
86 int
87 process_write_regs(struct proc *p, struct reg *regs)
88 {
89 	struct trapframe *tf = p->p_addr->u_pcb.pcb_tf;
90 
91 	memcpy(&tf->tf_x[0], &regs->r_reg[0], sizeof(tf->tf_x));
92 	tf->tf_lr = regs->r_lr;
93 	tf->tf_sp = regs->r_sp;
94 	tf->tf_elr = regs->r_pc;
95 	tf->tf_spsr = (0xff0f0000 & regs->r_spsr) | (tf->tf_spsr & 0x0020ffff);
96 	p->p_addr->u_pcb.pcb_tcb = (void *)regs->r_tpidr;
97 	return(0);
98 }
99 
100 int
101 process_write_fpregs(struct proc *p,  struct fpreg *regs)
102 {
103 	memcpy(&p->p_addr->u_pcb.pcb_fpstate, regs,
104 	    sizeof(p->p_addr->u_pcb.pcb_fpstate));
105 	p->p_addr->u_pcb.pcb_flags |= PCB_FPU;
106 
107 	/* drop FPU state */
108 	fpu_drop();
109 
110 	return(0);
111 }
112 
113 int
114 process_sstep(struct proc *p, int sstep)
115 {
116 	struct trapframe *tf = p->p_addr->u_pcb.pcb_tf;
117 
118 	if (sstep) {
119 		p->p_addr->u_pcb.pcb_flags |= PCB_SINGLESTEP;
120 		tf->tf_spsr |= PSR_SS;
121 	} else {
122 		p->p_addr->u_pcb.pcb_flags &= ~(PCB_SINGLESTEP);
123 		tf->tf_spsr &= ~PSR_SS;
124 	}
125 	return 0;
126 }
127 
128 int
129 process_set_pc(struct proc *p, caddr_t addr)
130 {
131 	struct trapframe *tf = p->p_addr->u_pcb.pcb_tf;
132 
133 	tf->tf_elr = (uint64_t)addr;
134 	tf->tf_spsr &= ~PSR_BTYPE;
135 
136 	return (0);
137 }
138 
139 #endif	/* PTRACE */
140 
141 register_t
142 process_get_pacmask(struct proc *p)
143 {
144 	return (-1ULL << USER_SPACE_BITS);
145 }
146