xref: /freebsd/sys/arm64/arm64/gdb_machdep.c (revision 16038816)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2020 The FreeBSD Foundation
5  *
6  * This software was developed by Mitchell Horne under sponsorship from
7  * the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kdb.h>
34 #include <sys/kernel.h>
35 #include <sys/proc.h>
36 #include <sys/signal.h>
37 
38 #include <machine/armreg.h>
39 #include <machine/frame.h>
40 #include <machine/gdb_machdep.h>
41 #include <machine/pcb.h>
42 
43 #include <gdb/gdb.h>
44 #include <gdb/gdb_int.h>
45 
46 void *
47 gdb_cpu_getreg(int regnum, size_t *regsz)
48 {
49 
50 	*regsz = gdb_cpu_regsz(regnum);
51 
52 	if (kdb_thread == curthread) {
53 		switch (regnum) {
54 		case GDB_REG_LR:   return (&kdb_frame->tf_lr);
55 		case GDB_REG_SP:   return (&kdb_frame->tf_sp);
56 		case GDB_REG_PC:   return (&kdb_frame->tf_elr);
57 		case GDB_REG_CSPR: return (&kdb_frame->tf_spsr);
58 		}
59 	}
60 	switch (regnum) {
61 	case GDB_REG_SP: return (&kdb_thrctx->pcb_sp);
62 	case GDB_REG_PC: /* FALLTHROUGH */
63 	case GDB_REG_LR: return (&kdb_thrctx->pcb_lr);
64 	default:
65 		if (regnum >= GDB_REG_X0 && regnum <= GDB_REG_X29)
66 			return (&kdb_thrctx->pcb_x[regnum]);
67 		break;
68 	}
69 
70 	return (NULL);
71 }
72 
73 void
74 gdb_cpu_setreg(int regnum, void *val)
75 {
76 	register_t regval = *(register_t *)val;
77 
78 	/* For curthread, keep the pcb and trapframe in sync. */
79 	if (kdb_thread == curthread) {
80 		switch (regnum) {
81 		case GDB_REG_PC: kdb_frame->tf_elr = regval; break;
82 		case GDB_REG_SP: kdb_frame->tf_sp  = regval; break;
83 		default:
84 			if (regnum >= GDB_REG_X0 && regnum <= GDB_REG_X29) {
85 				kdb_frame->tf_x[regnum] = regval;
86 			}
87 			break;
88 		}
89 	}
90 	switch (regnum) {
91 	case GDB_REG_PC: /* FALLTHROUGH */
92 	case GDB_REG_LR: kdb_thrctx->pcb_lr = regval; break;
93 	case GDB_REG_SP: kdb_thrctx->pcb_sp = regval; break;
94 	default:
95 		if (regnum >= GDB_REG_X0 && regnum <= GDB_REG_X29) {
96 			kdb_thrctx->pcb_x[regnum] = regval;
97 		}
98 		break;
99 	}
100 }
101 
102 int
103 gdb_cpu_signal(int type, int code __unused)
104 {
105 
106 	switch (type) {
107 	case EXCP_WATCHPT_EL1:
108 	case EXCP_SOFTSTP_EL1:
109 	case EXCP_BRK:
110 		return (SIGTRAP);
111 	}
112 	return (SIGEMT);
113 }
114 
115 void
116 gdb_cpu_stop_reason(int type, int code __unused)
117 {
118 
119 	if (type == EXCP_WATCHPT_EL1) {
120 		gdb_tx_str("watch:");
121 		gdb_tx_varhex((uintmax_t)READ_SPECIALREG(far_el1));
122 		gdb_tx_char(';');
123 	}
124 }
125