1178172Simp/*	$OpenBSD: db_machdep.c,v 1.2 1998/09/15 10:50:13 pefo Exp $ */
2178172Simp
3178172Simp/*-
4178172Simp * Copyright (c) 1998 Per Fogelstrom, Opsycon AB
5178172Simp *
6178172Simp * Redistribution and use in source and binary forms, with or without
7178172Simp * modification, are permitted provided that the following conditions
8178172Simp * are met:
9178172Simp * 1. Redistributions of source code must retain the above copyright
10178172Simp *    notice, this list of conditions and the following disclaimer.
11178172Simp * 2. Redistributions in binary form must reproduce the above copyright
12178172Simp *    notice, this list of conditions and the following disclaimer in the
13178172Simp *    documentation and/or other materials provided with the distribution.
14178172Simp * 3. All advertising materials mentioning features or use of this software
15178172Simp *    must display the following acknowledgement:
16178172Simp *	This product includes software developed under OpenBSD by
17178172Simp *	Per Fogelstrom, Opsycon AB, Sweden.
18178172Simp * 4. The name of the author may not be used to endorse or promote products
19178172Simp *    derived from this software without specific prior written permission.
20178172Simp *
21178172Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
22178172Simp * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23178172Simp * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24178172Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
25178172Simp * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26178172Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27178172Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28178172Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29178172Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30178172Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31178172Simp * SUCH DAMAGE.
32178172Simp *
33178172Simp *	JNPR: db_interface.c,v 1.6.2.1 2007/08/29 12:24:49 girish
34178172Simp */
35178172Simp
36178172Simp#include <sys/cdefs.h>
37178172Simp__FBSDID("$FreeBSD$");
38178172Simp
39178172Simp#include <sys/types.h>
40178172Simp#include <sys/param.h>
41178172Simp#include <sys/systm.h>
42178172Simp#include <sys/cons.h>
43178172Simp#include <sys/lock.h>
44178172Simp#include <vm/vm.h>
45178172Simp#include <vm/vm_object.h>
46178172Simp#include <vm/vm_page.h>
47178172Simp#include <vm/pmap.h>
48178172Simp#include <vm/vm_map.h>
49178172Simp#include <sys/user.h>
50178172Simp#include <sys/proc.h>
51178172Simp#include <sys/reboot.h>
52178172Simp
53178172Simp#include <machine/cache.h>
54178172Simp#include <machine/db_machdep.h>
55178172Simp#include <machine/mips_opcode.h>
56178172Simp#include <machine/vmparam.h>
57178172Simp#include <machine/md_var.h>
58178172Simp#define	NO_REG_DEFS	1	/* Prevent asm.h from including regdef.h */
59178172Simp#include <machine/asm.h>
60178172Simp#include <machine/setjmp.h>
61178172Simp
62178172Simp#include <ddb/ddb.h>
63178172Simp#include <ddb/db_sym.h>
64178172Simp#include <ddb/db_access.h>
65178172Simp#include <ddb/db_output.h>
66178172Simp#include <ddb/db_variables.h>
67178172Simp#include <sys/kdb.h>
68178172Simp
69178172Simpstatic db_varfcn_t db_frame;
70178172Simp
71178172Simp#define	DB_OFFSET(x)	(db_expr_t *)offsetof(struct trapframe, x)
72178172Simpstruct db_variable db_regs[] = {
73178172Simp	{ "at",  DB_OFFSET(ast),	db_frame },
74178172Simp	{ "v0",  DB_OFFSET(v0),		db_frame },
75178172Simp	{ "v1",  DB_OFFSET(v1),		db_frame },
76178172Simp	{ "a0",  DB_OFFSET(a0),		db_frame },
77178172Simp	{ "a1",  DB_OFFSET(a1),		db_frame },
78178172Simp	{ "a2",  DB_OFFSET(a2),		db_frame },
79178172Simp	{ "a3",  DB_OFFSET(a3),		db_frame },
80178172Simp	{ "t0",  DB_OFFSET(t0),		db_frame },
81178172Simp	{ "t1",  DB_OFFSET(t1),		db_frame },
82178172Simp	{ "t2",  DB_OFFSET(t2),		db_frame },
83178172Simp	{ "t3",  DB_OFFSET(t3),		db_frame },
84178172Simp	{ "t4",  DB_OFFSET(t4),		db_frame },
85178172Simp	{ "t5",  DB_OFFSET(t5),		db_frame },
86178172Simp	{ "t6",  DB_OFFSET(t6),		db_frame },
87178172Simp	{ "t7",  DB_OFFSET(t7),		db_frame },
88178172Simp	{ "s0",  DB_OFFSET(s0),		db_frame },
89178172Simp	{ "s1",  DB_OFFSET(s1),		db_frame },
90178172Simp	{ "s2",  DB_OFFSET(s2),		db_frame },
91178172Simp	{ "s3",  DB_OFFSET(s3),		db_frame },
92178172Simp	{ "s4",  DB_OFFSET(s4),		db_frame },
93178172Simp	{ "s5",  DB_OFFSET(s5),		db_frame },
94178172Simp	{ "s6",  DB_OFFSET(s6),		db_frame },
95178172Simp	{ "s7",  DB_OFFSET(s7),		db_frame },
96178172Simp	{ "t8",  DB_OFFSET(t8),		db_frame },
97178172Simp	{ "t9",  DB_OFFSET(t9),		db_frame },
98178172Simp	{ "k0",  DB_OFFSET(k0),		db_frame },
99178172Simp	{ "k1",  DB_OFFSET(k1),		db_frame },
100178172Simp	{ "gp",  DB_OFFSET(gp),		db_frame },
101178172Simp	{ "sp",  DB_OFFSET(sp),		db_frame },
102178172Simp	{ "s8",  DB_OFFSET(s8),		db_frame },
103178172Simp	{ "ra",  DB_OFFSET(ra),		db_frame },
104178172Simp	{ "sr",  DB_OFFSET(sr),		db_frame },
105178172Simp	{ "lo",  DB_OFFSET(mullo),	db_frame },
106178172Simp	{ "hi",  DB_OFFSET(mulhi),	db_frame },
107178172Simp	{ "bad", DB_OFFSET(badvaddr),	db_frame },
108178172Simp	{ "cs",  DB_OFFSET(cause),	db_frame },
109178172Simp	{ "pc",  DB_OFFSET(pc),		db_frame },
110178172Simp};
111178172Simpstruct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
112178172Simp
113178172Simpint (*do_db_log_stack_trace_cmd)(char *);
114178172Simp
115178172Simpstatic int
116178172Simpdb_frame(struct db_variable *vp, db_expr_t *valuep, int op)
117178172Simp{
118209935Sjchandra	register_t *reg;
119178172Simp
120178172Simp	if (kdb_frame == NULL)
121178172Simp		return (0);
122178172Simp
123209935Sjchandra	reg = (register_t *)((uintptr_t)kdb_frame + (size_t)(intptr_t)vp->valuep);
124178172Simp	if (op == DB_VAR_GET)
125178172Simp		*valuep = *reg;
126178172Simp	else
127178172Simp		*reg = *valuep;
128178172Simp	return (1);
129178172Simp}
130178172Simp
131178172Simpint
132178172Simpdb_read_bytes(vm_offset_t addr, size_t size, char *data)
133178172Simp{
134178172Simp	jmp_buf jb;
135178172Simp	void *prev_jb;
136178172Simp	int ret;
137178172Simp
138178172Simp	prev_jb = kdb_jmpbuf(jb);
139178172Simp	ret = setjmp(jb);
140178172Simp	if (ret == 0) {
141178172Simp		/*
142178172Simp		 * 'addr' could be a memory-mapped I/O address.  Try to
143178172Simp		 * do atomic load/store in unit of size requested.
144178172Simp		 */
145178172Simp		if ((size == 2 || size == 4 || size == 8) &&
146178172Simp		    ((addr & (size -1)) == 0) &&
147178172Simp		    (((vm_offset_t)data & (size -1)) == 0)) {
148178172Simp			switch (size) {
149178172Simp			case 2:
150178172Simp				*(uint16_t *)data = *(uint16_t *)addr;
151178172Simp				break;
152178172Simp			case 4:
153178172Simp				*(uint32_t *)data = *(uint32_t *)addr;
154178172Simp				break;
155178172Simp			case 8:
156178172Simp				atomic_load_64((volatile u_int64_t *)addr,
157178172Simp				    (u_int64_t *)data);
158178172Simp			break;
159178172Simp			}
160178172Simp		} else {
161178172Simp			char *src;
162178172Simp
163178172Simp			src = (char *)addr;
164178172Simp			while (size-- > 0)
165178172Simp				*data++ = *src++;
166178172Simp		}
167178172Simp	}
168178172Simp
169178172Simp	(void)kdb_jmpbuf(prev_jb);
170178172Simp	return (ret);
171178172Simp}
172178172Simp
173178172Simpint
174178172Simpdb_write_bytes(vm_offset_t addr, size_t size, char *data)
175178172Simp{
176178172Simp	int ret;
177178172Simp	jmp_buf jb;
178178172Simp	void *prev_jb;
179178172Simp
180178172Simp	prev_jb = kdb_jmpbuf(jb);
181178172Simp	ret = setjmp(jb);
182178172Simp
183178172Simp	if (ret == 0) {
184178172Simp		/*
185178172Simp		 * 'addr' could be a memory-mapped I/O address.  Try to
186178172Simp		 * do atomic load/store in unit of size requested.
187178172Simp		 */
188178172Simp		if ((size == 2 || size == 4 || size == 8) &&
189178172Simp		    ((addr & (size -1)) == 0) &&
190178172Simp		    (((vm_offset_t)data & (size -1)) == 0)) {
191178172Simp			switch (size) {
192178172Simp			case 2:
193178172Simp				*(uint16_t *)addr = *(uint16_t *)data;
194178172Simp				break;
195178172Simp			case 4:
196178172Simp				*(uint32_t *)addr = *(uint32_t *)data;
197178172Simp				break;
198178172Simp			case 8:
199178172Simp				atomic_store_64((volatile u_int64_t *)addr,
200178172Simp				    (u_int64_t *)data);
201178172Simp			break;
202178172Simp			}
203178172Simp		} else {
204178172Simp			char *dst;
205178172Simp			size_t len = size;
206178172Simp
207178172Simp			dst = (char *)addr;
208178172Simp			while (len-- > 0)
209178172Simp				*dst++ = *data++;
210178172Simp		}
211178172Simp
212178172Simp		mips_icache_sync_range((db_addr_t) addr, size);
213178172Simp		mips_dcache_wbinv_range((db_addr_t) addr, size);
214178172Simp	}
215178172Simp	(void)kdb_jmpbuf(prev_jb);
216178172Simp	return (ret);
217178172Simp}
218178172Simp
219178172Simp/*
220178172Simp *	To do a single step ddb needs to know the next address
221178172Simp *	that we will get to. It means that we need to find out
222178172Simp *	both the address for a branch taken and for not taken, NOT! :-)
223178172Simp *	MipsEmulateBranch will do the job to find out _exactly_ which
224178172Simp *	address we will end up at so the 'dual bp' method is not
225178172Simp *	requiered.
226178172Simp */
227178172Simpdb_addr_t
228178172Simpnext_instr_address(db_addr_t pc, boolean_t bd)
229178172Simp{
230178172Simp	db_addr_t next;
231178172Simp
232178172Simp	next = (db_addr_t)MipsEmulateBranch(kdb_frame, pc, 0, 0);
233178172Simp	return (next);
234178172Simp}
235178172Simp
236178172Simp
237178172Simp/*
238178172Simp *	Decode instruction and figure out type.
239178172Simp */
240178172Simpint
241178172Simpdb_inst_type(int ins)
242178172Simp{
243178172Simp	InstFmt inst;
244178172Simp	int	ityp = 0;
245178172Simp
246178172Simp	inst.word = ins;
247178172Simp	switch ((int)inst.JType.op) {
248178172Simp	case OP_SPECIAL:
249178172Simp		switch ((int)inst.RType.func) {
250178172Simp		case OP_JR:
251178172Simp			ityp = IT_BRANCH;
252178172Simp			break;
253178172Simp		case OP_JALR:
254178172Simp		case OP_SYSCALL:
255178172Simp			ityp = IT_CALL;
256178172Simp			break;
257178172Simp		}
258178172Simp		break;
259178172Simp
260178172Simp	case OP_BCOND:
261178172Simp		switch ((int)inst.IType.rt) {
262178172Simp		case OP_BLTZ:
263178172Simp		case OP_BLTZL:
264178172Simp		case OP_BGEZ:
265178172Simp		case OP_BGEZL:
266178172Simp			ityp = IT_BRANCH;
267178172Simp			break;
268178172Simp
269178172Simp		case OP_BLTZAL:
270178172Simp		case OP_BLTZALL:
271178172Simp		case OP_BGEZAL:
272178172Simp		case OP_BGEZALL:
273178172Simp			ityp = IT_CALL;
274178172Simp			break;
275178172Simp		}
276178172Simp		break;
277178172Simp
278178172Simp	case OP_JAL:
279178172Simp		ityp = IT_CALL;
280178172Simp		break;
281178172Simp
282178172Simp	case OP_J:
283178172Simp	case OP_BEQ:
284178172Simp	case OP_BEQL:
285178172Simp	case OP_BNE:
286178172Simp	case OP_BNEL:
287178172Simp	case OP_BLEZ:
288178172Simp	case OP_BLEZL:
289178172Simp	case OP_BGTZ:
290178172Simp	case OP_BGTZL:
291178172Simp		ityp = IT_BRANCH;
292178172Simp		break;
293178172Simp
294178172Simp	case OP_COP1:
295178172Simp		switch (inst.RType.rs) {
296178172Simp		case OP_BCx:
297178172Simp		case OP_BCy:
298178172Simp			ityp = IT_BRANCH;
299178172Simp			break;
300178172Simp		}
301178172Simp		break;
302178172Simp
303178172Simp	case OP_LB:
304178172Simp	case OP_LH:
305178172Simp	case OP_LW:
306178172Simp	case OP_LD:
307178172Simp	case OP_LBU:
308178172Simp	case OP_LHU:
309178172Simp	case OP_LWU:
310178172Simp	case OP_LWC1:
311178172Simp		ityp = IT_LOAD;
312178172Simp		break;
313178172Simp
314178172Simp	case OP_SB:
315178172Simp	case OP_SH:
316178172Simp	case OP_SW:
317178172Simp	case OP_SD:
318178172Simp	case OP_SWC1:
319178172Simp		ityp = IT_STORE;
320178172Simp		break;
321178172Simp	}
322178172Simp	return (ityp);
323178172Simp}
324178172Simp
325178172Simp/*
326178172Simp * Return the next pc if the given branch is taken.
327178172Simp * MachEmulateBranch() runs analysis for branch delay slot.
328178172Simp */
329178172Simpdb_addr_t
330178172Simpbranch_taken(int inst, db_addr_t pc)
331178172Simp{
332178172Simp	db_addr_t ra;
333178172Simp	register_t fpucsr;
334178172Simp
335178172Simp	/* TBD: when is fsr set */
336178172Simp	fpucsr = (curthread) ? curthread->td_pcb->pcb_regs.fsr : 0;
337178172Simp	ra = (db_addr_t)MipsEmulateBranch(kdb_frame, pc, fpucsr, 0);
338178172Simp	return (ra);
339178172Simp}
340