1/*	$NetBSD: kgdb_machdep.c,v 1.22 2023/10/25 06:02:14 skrll Exp $	*/
2
3/*-
4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 1996 Matthias Pfaller.
35 * All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 *    notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 *    notice, this list of conditions and the following disclaimer in the
44 *    documentation and/or other materials provided with the distribution.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
50 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
51 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
52 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
53 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
54 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
55 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 */
57
58#include <sys/cdefs.h>
59__KERNEL_RCSID(0, "$NetBSD: kgdb_machdep.c,v 1.22 2023/10/25 06:02:14 skrll Exp $");
60
61#include "opt_ddb.h"
62
63#if defined(DDB)
64#error "Can't build DDB and KGDB together."
65#endif
66
67/*
68 * Machine-dependent functions for remote KGDB.  Originally written
69 * for NetBSD/pc532 by Matthias Pfaller.  Modified for NetBSD/i386
70 * by Jason R. Thorpe.  Modified for NetBSD/mips by Ethan Solomita
71 */
72
73#include "opt_cputype.h"	/* which mips CPUs do we support? */
74
75#include <sys/types.h>
76#include <sys/systm.h>
77#include <sys/param.h>
78#include <sys/proc.h>
79#include <sys/reboot.h>
80#include <sys/kgdb.h>
81
82#include <uvm/uvm_extern.h>
83
84#include <mips/locore.h>
85#include <mips/pte.h>
86#include <mips/cpu.h>
87#include <mips/mips_opcode.h>
88#include <mips/reg.h>
89#include <mips/trap.h>
90#include <dev/cons.h>
91
92#include <machine/db_machdep.h>
93#include <ddb/db_access.h>
94
95/*
96 * Is kva a valid address to access?  This is used by KGDB.
97 */
98static int
99kvacc(vaddr_t kva)
100{
101	if (pmap_md_direct_mapped_vaddr_p(kva))
102		return 1;
103
104	if (kva < VM_MIN_KERNEL_ADDRESS || kva >= VM_MAX_KERNEL_ADDRESS)
105		return 0;
106
107	const pt_entry_t * const ptep = pmap_pte_lookup(pmap_kernel(), kva);
108	return ptep != NULL && pte_valid_p(*ptep);
109}
110
111/*
112 * Determine if the memory at va..(va+len) is valid.
113 */
114int
115kgdb_acc(vaddr_t va, size_t len)
116{
117	vaddr_t last_va;
118
119	last_va = va + len + PAGE_SIZE - 1;
120	va  &= ~PGOFSET;
121	last_va &= ~PGOFSET;
122
123	for (; va < last_va; va += PAGE_SIZE) {
124		if (kvacc(va) == 0)
125			return 0;
126	}
127
128	return (1);
129}
130
131/*
132 * Translate a trap number into a unix compatible signal value.
133 * (gdb only understands unix signal numbers).
134 */
135int
136kgdb_signal(int type)
137{
138	switch (type) {
139	case T_TLB_MOD:
140	case T_TLB_MOD+T_USER:
141	case T_TLB_LD_MISS:
142	case T_TLB_ST_MISS:
143	case T_TLB_LD_MISS+T_USER:
144	case T_TLB_ST_MISS+T_USER:
145	case T_ADDR_ERR_LD:	/* misaligned access */
146	case T_ADDR_ERR_ST:	/* misaligned access */
147	case T_BUS_ERR_LD_ST:	/* BERR asserted to CPU */
148	case T_ADDR_ERR_LD+T_USER:	/* misaligned or kseg access */
149	case T_ADDR_ERR_ST+T_USER:	/* misaligned or kseg access */
150	case T_BUS_ERR_IFETCH+T_USER:	/* BERR asserted to CPU */
151	case T_BUS_ERR_LD_ST+T_USER:	/* BERR asserted to CPU */
152		return (SIGSEGV);
153
154	case T_BREAK:
155	case T_BREAK+T_USER:
156		return (SIGTRAP);
157
158	case T_RES_INST+T_USER:
159	case T_COP_UNUSABLE+T_USER:
160		return (SIGILL);
161
162	case T_FPE+T_USER:
163	case T_OVFLOW+T_USER:
164		return (SIGFPE);
165
166	default:
167		return (SIGEMT);
168	}
169}
170
171mips_reg_t kgdb_cause, kgdb_vaddr; /* set by trap() */
172
173/*
174 * Translate the values stored in the db_regs_t struct to the format
175 * understood by gdb.
176 */
177void
178kgdb_getregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
179{
180	memset(gdb_regs, 0, KGDB_NUMREGS * sizeof(kgdb_reg_t));
181	gdb_regs[ 1] = regs->r_regs[_R_AST];	/* AT */
182	gdb_regs[ 2] = regs->r_regs[_R_V0];	/* V0 */
183	gdb_regs[ 3] = regs->r_regs[_R_V1];	/* V1 */
184	gdb_regs[ 4] = regs->r_regs[_R_A0];	/* A0 */
185	gdb_regs[ 5] = regs->r_regs[_R_A1];	/* A1 */
186	gdb_regs[ 6] = regs->r_regs[_R_A2];	/* A2 */
187	gdb_regs[ 7] = regs->r_regs[_R_A3];	/* A3 */
188#if defined(__mips_n32) || defined(__mips_n64)
189	gdb_regs[ 8] = regs->r_regs[_R_A4];	/* A4 */
190	gdb_regs[ 9] = regs->r_regs[_R_A5];	/* A5 */
191	gdb_regs[10] = regs->r_regs[_R_A6];	/* A6 */
192	gdb_regs[11] = regs->r_regs[_R_A7];	/* A7 */
193	gdb_regs[12] = regs->r_regs[_R_T0];	/* T0 */
194	gdb_regs[13] = regs->r_regs[_R_T1];	/* T1 */
195	gdb_regs[14] = regs->r_regs[_R_T2];	/* T2 */
196	gdb_regs[15] = regs->r_regs[_R_T3];	/* T3 */
197#else
198	gdb_regs[ 8] = regs->r_regs[_R_T0];	/* T0 */
199	gdb_regs[ 9] = regs->r_regs[_R_T1];	/* T1 */
200	gdb_regs[10] = regs->r_regs[_R_T2];	/* T2 */
201	gdb_regs[11] = regs->r_regs[_R_T3];	/* T3 */
202	gdb_regs[12] = regs->r_regs[_R_T4];	/* T4 */
203	gdb_regs[13] = regs->r_regs[_R_T5];	/* T5 */
204	gdb_regs[14] = regs->r_regs[_R_T6];	/* T6 */
205	gdb_regs[15] = regs->r_regs[_R_T7];	/* T7 */
206#endif /* __mips_n32 || __mips_n64 */
207	gdb_regs[16] = regs->r_regs[_R_S0];	/* S0 */
208	gdb_regs[17] = regs->r_regs[_R_S1];	/* S1 */
209	gdb_regs[18] = regs->r_regs[_R_S2];	/* S2 */
210	gdb_regs[19] = regs->r_regs[_R_S3];	/* S3 */
211	gdb_regs[20] = regs->r_regs[_R_S4];	/* S4 */
212	gdb_regs[21] = regs->r_regs[_R_S5];	/* S5 */
213	gdb_regs[22] = regs->r_regs[_R_S6];	/* S6 */
214	gdb_regs[23] = regs->r_regs[_R_S7];	/* S7 */
215	gdb_regs[24] = regs->r_regs[_R_T8];	/* T8 */
216	gdb_regs[25] = regs->r_regs[_R_T9];	/* T9 */
217	gdb_regs[28] = regs->r_regs[_R_GP];	/* GP */
218	gdb_regs[29] = regs->r_regs[_R_SP];	/* SP */
219	gdb_regs[30] = regs->r_regs[_R_S8];	/* S8 */
220	gdb_regs[31] = regs->r_regs[_R_RA];	/* RA */
221	gdb_regs[32] = regs->r_regs[_R_SR];	/* SR */
222	gdb_regs[33] = regs->r_regs[_R_MULLO];	/* MULLO */
223	gdb_regs[34] = regs->r_regs[_R_MULHI];	/* MULHI */
224	gdb_regs[35] = kgdb_vaddr;		/* BAD VADDR */
225	gdb_regs[36] = kgdb_cause;		/* CAUSE */
226	gdb_regs[37] = regs->r_regs[_R_PC];	/* PC */
227}
228
229/*
230 * Reverse the above.
231 */
232void
233kgdb_setregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
234{
235	regs->r_regs[_R_PC] = gdb_regs[37];   /* PC */
236}
237
238/*
239 * Trap into kgdb to wait for debugger to connect,
240 * noting on the console why nothing else is going on.
241 */
242void
243kgdb_connect(int verbose)
244{
245	if (kgdb_dev < 0)
246		return;
247
248	if (verbose)
249		printf("kgdb waiting...");
250
251	__asm("break");
252
253	if (verbose)
254		printf("connected.\n");
255
256	kgdb_debug_panic = 1;
257}
258
259/*
260 * Decide what to do on panic.
261 * (This is called by panic, like Debugger())
262 */
263void
264kgdb_panic(void)
265{
266	if (kgdb_dev != NODEV && kgdb_debug_panic) {
267		printf("entering kgdb\n");
268		kgdb_connect(kgdb_active == 0);
269	}
270}
271