1 /* $NetBSD: kgdb_hppa.c,v 1.11 2023/09/03 20:52:13 andvar Exp $ */
2
3 /*
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
10 *
11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement:
13 * This product includes software developed by the University of
14 * California, Lawrence Berkeley Laboratories.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94
41 */
42
43 /*
44 * Machine-dependent (hppa) part of the KGDB remote "stub"
45 */
46
47 #include <sys/cdefs.h>
48 __KERNEL_RCSID(0, "$NetBSD: kgdb_hppa.c,v 1.11 2023/09/03 20:52:13 andvar Exp $");
49
50 #include <sys/param.h>
51 #include <sys/kgdb.h>
52
53 #include <machine/frame.h>
54 #include <machine/trap.h>
55
56 /*
57 * Determine if the memory at va..(va+len) is valid.
58 */
59 int
kgdb_acc(vaddr_t va,size_t ulen)60 kgdb_acc(vaddr_t va, size_t ulen)
61 {
62
63 /* Just let the trap handler deal with it. */
64 return 1;
65 }
66
67 /*
68 * Translate a trap number into a unix compatible signal value.
69 * (gdb only understands unix signal numbers).
70 */
71 int
kgdb_signal(int type)72 kgdb_signal(int type)
73 {
74 int sigval;
75
76 switch (type) {
77
78 case T_HPMC:
79 case T_POWERFAIL:
80 case T_LPMC:
81 case T_INTERRUPT:
82 sigval = SIGINT;
83 break;
84
85 case T_NONEXIST:
86 case T_ILLEGAL:
87 case T_PRIV_OP:
88 case T_PRIV_REG:
89 case T_IPROT:
90 sigval = SIGILL;
91 break;
92
93 case T_IBREAK:
94 case T_DBREAK:
95 case T_TAKENBR:
96 case T_RECOVERY:
97 sigval = SIGTRAP;
98 break;
99
100 case T_EMULATION:
101 sigval = SIGEMT;
102 break;
103
104 case T_DATALIGN:
105 sigval = SIGBUS;
106 break;
107
108 case T_DATACC:
109 case T_DATAPID:
110 case T_ITLBMISS:
111 case T_DTLBMISS:
112 case T_ITLBMISSNA:
113 case T_DTLBMISSNA:
114 case T_DPROT:
115 sigval = SIGSEGV;
116 break;
117
118 #if 0
119 case T_OVERFLOW: /* overflow */
120 case T_CONDITION: /* conditional */
121 case T_EXCEPTION: /* assist exception */
122 case T_TLB_DIRTY: /* TLB dirty bit */
123 case T_PAGEREF: /* page reference */
124 case T_HIGHERPL: /* higher-privilege transfer */
125 case T_LOWERPL: /* lower-privilege transfer */
126 #endif
127 default:
128 sigval = SIGILL;
129 break;
130 }
131 return sigval;
132 }
133
134 /*
135 * Definitions exported from gdb.
136 */
137
138 /*
139 * Translate the values stored in the kernel regs struct to/from
140 * the format understood by gdb.
141 *
142 * When configured for the PA, GDB is set up to expect a buffer
143 * of registers in the HP/UX struct save_state format, described
144 * in HP/UX's machine/save_state.h header. The register order is
145 * very different from our struct trapframe, so we have to do some
146 * moving around of values.
147 *
148 * The constants in the macro below should correspond to the
149 * register numbers in gdb's config/pa/tm-pa.h register macros.
150 */
151 #define KGDB_MOVEREGS \
152 /* 0 is the "save state flags", which gdb doesn't use */ \
153 KGDB_MOVEREG(1, tf_r1); \
154 KGDB_MOVEREG(2, tf_rp); /* r2 */ \
155 KGDB_MOVEREG(3, tf_r3); /* frame pointer when -g */ \
156 KGDB_MOVEREG(4, tf_r4); \
157 KGDB_MOVEREG(5, tf_r5); \
158 KGDB_MOVEREG(6, tf_r6); \
159 KGDB_MOVEREG(7, tf_r7); \
160 KGDB_MOVEREG(8, tf_r8); \
161 KGDB_MOVEREG(9, tf_r9); \
162 KGDB_MOVEREG(10, tf_r10); \
163 KGDB_MOVEREG(11, tf_r11); \
164 KGDB_MOVEREG(12, tf_r12); \
165 KGDB_MOVEREG(13, tf_r13); \
166 KGDB_MOVEREG(14, tf_r14); \
167 KGDB_MOVEREG(15, tf_r15); \
168 KGDB_MOVEREG(16, tf_r16); \
169 KGDB_MOVEREG(17, tf_r17); \
170 KGDB_MOVEREG(18, tf_r18); \
171 KGDB_MOVEREG(19, tf_t4); /* r19 */ \
172 KGDB_MOVEREG(20, tf_t3); /* r20 */ \
173 KGDB_MOVEREG(21, tf_t2); /* r21 */ \
174 KGDB_MOVEREG(22, tf_t1); /* r22 */ \
175 KGDB_MOVEREG(23, tf_arg3); /* r23 */ \
176 KGDB_MOVEREG(24, tf_arg2); /* r24 */ \
177 KGDB_MOVEREG(25, tf_arg1); /* r25 */ \
178 KGDB_MOVEREG(26, tf_arg0); /* r26 */ \
179 KGDB_MOVEREG(27, tf_dp); /* r27 */ \
180 KGDB_MOVEREG(28, tf_ret0); /* r28 */ \
181 KGDB_MOVEREG(29, tf_ret1); /* r29 */ \
182 KGDB_MOVEREG(30, tf_sp); /* r30 */ \
183 KGDB_MOVEREG(31, tf_r31); \
184 KGDB_MOVEREG(32, tf_sar); /* cr11 */ \
185 KGDB_MOVEREG(33, tf_iioq_head); /* cr18 */ \
186 KGDB_MOVEREG(34, tf_iisq_head); /* cr17 */ \
187 KGDB_MOVEREG(35, tf_iioq_tail); \
188 KGDB_MOVEREG(36, tf_iisq_tail); \
189 KGDB_MOVEREG(37, tf_eiem); /* cr15 */ \
190 KGDB_MOVEREG(38, tf_iir); /* cr19 */ \
191 KGDB_MOVEREG(39, tf_isr); /* cr20 */ \
192 KGDB_MOVEREG(40, tf_ior); /* cr21 */ \
193 KGDB_MOVEREG(41, tf_ipsw); /* cr22 */ \
194 /* 42 should be cr31, which we don't have available */ \
195 KGDB_MOVEREG(43, tf_sr4); \
196 KGDB_MOVEREG(44, tf_sr0); \
197 KGDB_MOVEREG(45, tf_sr1); \
198 KGDB_MOVEREG(46, tf_sr2); \
199 KGDB_MOVEREG(47, tf_sr3); \
200 KGDB_MOVEREG(48, tf_sr5); \
201 KGDB_MOVEREG(49, tf_sr6); \
202 KGDB_MOVEREG(50, tf_sr7); \
203 KGDB_MOVEREG(51, tf_rctr); /* cr0 */ \
204 KGDB_MOVEREG(52, tf_pidr1); /* cr8 */ \
205 KGDB_MOVEREG(53, tf_pidr2); /* cr9 */ \
206 KGDB_MOVEREG(54, tf_ccr); /* cr10 */ \
207 KGDB_MOVEREG(55, tf_pidr3); /* cr12 */ \
208 KGDB_MOVEREG(56, tf_pidr4); /* cr13 */ \
209 KGDB_MOVEREG(57, tf_cr24); /* cr24 - DDB */ \
210 KGDB_MOVEREG(58, tf_vtop); /* cr25 - DDB */ \
211 /* 59 should be cr26, which we don't have available */ \
212 KGDB_MOVEREG(60, tf_cr27); /* - DDB */ \
213 KGDB_MOVEREG(61, tf_cr28); /* - DDB */ \
214 /* 62 should be cr29, which we don't have available */ \
215 KGDB_MOVEREG(63, tf_cr30) /* uaddr */
216
217 void
kgdb_getregs(db_regs_t * regs,kgdb_reg_t * gdb_regs)218 kgdb_getregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
219 {
220 #define KGDB_MOVEREG(i, f) gdb_regs[i] = regs->f
221 KGDB_MOVEREGS;
222 #undef KGDB_MOVEREG
223 }
224
225 void
kgdb_setregs(db_regs_t * regs,kgdb_reg_t * gdb_regs)226 kgdb_setregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
227 {
228 #define KGDB_MOVEREG(i, f) regs->f = gdb_regs[i]
229 KGDB_MOVEREGS;
230 #undef KGDB_MOVEREG
231 }
232
233 /*
234 * Trap into kgdb to wait for debugger to connect,
235 * noting on the console why nothing else is going on.
236 */
237 void
kgdb_connect(int verbose)238 kgdb_connect(int verbose)
239 {
240
241 if (kgdb_dev < 0)
242 return;
243
244 if (verbose)
245 printf("kgdb waiting...");
246
247 __asm volatile ("break %0, %1"
248 :: "i" (HPPA_BREAK_KERNEL), "i" (HPPA_BREAK_KGDB));
249
250 if (verbose)
251 printf("connected.\n");
252
253 kgdb_debug_panic = 1;
254 }
255
256 /*
257 * Decide what to do on panic.
258 * (This is called by panic, like Debugger())
259 */
260 void
kgdb_panic(void)261 kgdb_panic(void)
262 {
263 if (kgdb_dev >= 0 && kgdb_debug_panic) {
264 printf("entering kgdb\n");
265 kgdb_connect(kgdb_active == 0);
266 }
267 }
268