summaryrefslogtreecommitdiff
path: root/sys/arch/powerpc/include/db_machdep.h
blob: 1edd8ebd4cb4e2bf3d4795b2f5502d7ef6162d87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*	$OpenBSD: db_machdep.h,v 1.2 1997/03/21 00:48:48 niklas Exp $	*/
/*	$NetBSD: db_machdep.h,v 1.30 2021/03/11 08:33:34 simonb Exp $	*/

/* 
 * Mach Operating System
 * Copyright (c) 1992 Carnegie Mellon University
 * All Rights Reserved.
 * 
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 * 
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 * 
 * Carnegie Mellon requests users of this software to return to
 * 
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 * 
 * any improvements or extensions that they make and grant Carnegie Mellon 
 * the rights to redistribute these changes.
 */

/*
 * Machine-dependent defines for new kernel debugger.
 */
#ifndef	_PPC_DB_MACHDEP_H_
#define	_PPC_DB_MACHDEP_H_

#if defined(_KERNEL_OPT)
#include "opt_ppcarch.h"
#endif

#include <uvm/uvm_prot.h>
#include <uvm/uvm_param.h>
#include <machine/trap.h>

#define	DB_ELF_SYMBOLS

typedef	vaddr_t		db_addr_t;	/* address - unsigned */
#define	DDB_EXPR_FMT	"l"		/* expression is long */
typedef	long		db_expr_t;	/* expression - signed */
struct powerpc_saved_state {
	u_int32_t	r[32];		/* data registers */
	u_int32_t	iar;
	u_int32_t	msr;
	u_int32_t	lr;
	u_int32_t	ctr;
	u_int32_t	cr;
	u_int32_t	xer;
	u_int32_t	mq;
	u_int32_t	dear;
	u_int32_t	esr;
	u_int32_t	pid;
};
typedef struct powerpc_saved_state db_regs_t;
extern	db_regs_t	ddb_regs;		/* register state */
#define DDB_REGS	(&ddb_regs)

#define	PC_REGS(regs)	(*(db_addr_t *)&(regs)->iar)

#define	BKPT_ADDR(addr)	(addr)		/* breakpoint address */
#define	BKPT_ASM	"trap"		/* should match BKPT_INST */
#define	BKPT_INST	0x7fe00008	/* breakpoint instruction */
#define	BKPT_SIZE	(4)		/* size of breakpoint inst */
#define	BKPT_SET(inst, addr)	(BKPT_INST)

#if !defined(PPC_BOOKE) && !defined(PPC_IBM4XX)
#define	SR_SINGLESTEP	0x400		/* PSL_SE, available only for oea */
#define	db_clear_single_step(regs)	((regs)->msr &= ~SR_SINGLESTEP)
#define	db_set_single_step(regs)	((regs)->msr |=  SR_SINGLESTEP)
#else
#define	SOFTWARE_SSTEP
#endif

#define T_BREAKPOINT	0xffff
#define	IS_BREAKPOINT_TRAP(type, code)	((type) == T_BREAKPOINT)

#define T_WATCHPOINT	0xeeee
#ifdef T_WATCHPOINT
#define	IS_WATCHPOINT_TRAP(type, code)	((type) == T_WATCHPOINT)
#else
#define	IS_WATCHPOINT_TRAP(type, code)	0
#endif

#define	M_RTS		0xfc0007ff
#define I_RTS		0x4c000020
#define	I_BLRL		0x4c000021
#define M_BC		0xfc000001
#define I_BC		0x40000000
#define I_BCL		0x40000001
#define M_B		0xfc000001
#define I_B		0x48000000
#define I_BL		0x48000001
#define	M_BCTR		0xfc0007ff
#define	I_BCTR		0x4c000420
#define	I_BCTRL		0x4c000421
#define	M_RFI		0xfc0007fe
#define	I_RFI		0x4c000064

#define	inst_trap_return(ins)	(((ins)&M_RFI) == I_RFI)
#define	inst_return(ins)	(((ins)&M_RTS) == I_RTS)
#define	inst_call(ins)		(((ins)&M_BC  ) == I_BCL   || \
				 ((ins)&M_B   ) == I_BL    || \
				 ((ins)&M_BCTR) == I_BCTRL || \
				 ((ins)&M_RTS ) == I_BLRL )
#define	inst_branch(ins)	(((ins)&M_BC  ) == I_BC || \
				 ((ins)&M_B   ) == I_B  || \
				 ((ins)&M_BCTR) == I_BCTR )
#define	inst_unconditional_flow_transfer(ins)	\
				(((ins)&M_B   ) == I_B    || \
				 ((ins)&M_BCTR) == I_BCTR )
#define inst_load(ins)		0
#define inst_store(ins)		0
#if defined(PPC_IBM4XX) || defined(PPC_BOOKE)
#define next_instr_address(v, b) ((db_addr_t) ((b) ? (v) : ((v) + 4)))
extern db_addr_t branch_taken(int, db_addr_t, db_regs_t *);
#endif

/*
 * GDB's register array is:
 *  32 4-byte GPRs
 *  32 8-byte FPRs
 *   7 4-byte UISA special-purpose registers
 *  16 4-byte segment registers
 *  32 4-byte standard OEA special-purpose registers,
 * and up to 64 4-byte non-standard OES special-purpose registers.
 * GDB keeps some extra space, so the total size of the register array
 * they use is 880 bytes (gdb-5.0).
 * KGDB_NUMREGS 220
 */
/*
 * GDB's register array of gdb-6.0 is defined in
 * usr/src/gnu/dist/gdb6/gdb/regformats/reg-ppc.dat
 * GDB's register array is:
 *  32 4-byte GPRs
 *  32 8-byte FPRs
 *   7 4-byte UISA special-purpose registers: pc, ps, cr, lr, ctr, xer, fpscr
 * index of pc in array: 32 + 2*32 = 96
 * size 32 * 4 + 32 * 8 + 7 * 4 = 103 * 4 = 412 bytes
 * KGD_NUMREGS 103
 */
typedef long	kgdb_reg_t;
#define KGDB_PPC_PC_REG		96	/* first UISA SP register */
#define KGDB_PPC_MSR_REG	97
#define KGDB_PPC_CR_REG		98
#define KGDB_PPC_LR_REG		99
#define KGDB_PPC_CTR_REG	100
#define KGDB_PPC_XER_REG	101
#define KGDB_PPC_FPSCR_REG	102
#define KGDB_NUMREGS		103	/* Treat all registers as 4-byte */
#define KGDB_BUFLEN		(2*KGDB_NUMREGS*sizeof(kgdb_reg_t)+1)

#ifdef _KERNEL

void	kdb_kintr(void *);
int	kdb_trap(int, void *);

bool	ddb_running_on_this_cpu_p(void);
bool	ddb_running_on_any_cpu_p(void);
void	db_resume_others(void);

/*
 * We have machine-dependent commands.
 */
#define	DB_MACHINE_COMMANDS

#endif /* _KERNEL */

#endif	/* _PPC_DB_MACHDEP_H_ */