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_ */
|