aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-sh/kgdb.h
blob: 1653ffb75fbe75f857aebee1ad645b69f1d45446 (plain) (blame)
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
/*
 * May be copied or modified under the terms of the GNU General Public
 * License.  See linux/COPYING for more information.
 *
 * Based on original code by Glenn Engel, Jim Kingdon,
 * David Grothe <dave@gcom.com>, Tigran Aivazian, <tigran@sco.com> and
 * Amit S. Kale <akale@veritas.com>
 * 
 * Super-H port based on sh-stub.c (Ben Lee and Steve Chamberlain) by
 * Henry Bell <henry.bell@st.com>
 * 
 * Header file for low-level support for remote debug using GDB. 
 *
 */

#ifndef __KGDB_H
#define __KGDB_H

#include <asm/ptrace.h>

struct console;

/* Same as pt_regs but has vbr in place of syscall_nr */
struct kgdb_regs {
        unsigned long regs[16];
        unsigned long pc;
        unsigned long pr;
        unsigned long sr;
        unsigned long gbr;
        unsigned long mach;
        unsigned long macl;
        unsigned long vbr;
};

/* State info */
extern char kgdb_in_gdb_mode;
extern int kgdb_done_init;
extern int kgdb_enabled;
extern int kgdb_nofault;	/* Ignore bus errors (in gdb mem access) */
extern int kgdb_halt;		/* Execute initial breakpoint at startup */
extern char in_nmi;		/* Debounce flag to prevent NMI reentry*/

/* SCI */
extern int kgdb_portnum;
extern int kgdb_baud;
extern char kgdb_parity;
extern char kgdb_bits;
extern int kgdb_console_setup(struct console *, char *);

/* Init and interface stuff */
extern int kgdb_init(void);
extern int (*kgdb_serial_setup)(void);
extern int (*kgdb_getchar)(void);
extern void (*kgdb_putchar)(int);

struct kgdb_sermap {
	char *name;
	int namelen;
	int (*setup_fn)(struct console *, char *);
	struct kgdb_sermap *next;
};
extern void kgdb_register_sermap(struct kgdb_sermap *map);
extern struct kgdb_sermap *kgdb_porttype;

/* Trap functions */
typedef void (kgdb_debug_hook_t)(struct pt_regs *regs); 
typedef void (kgdb_bus_error_hook_t)(void);
extern kgdb_debug_hook_t  *kgdb_debug_hook;
extern kgdb_bus_error_hook_t *kgdb_bus_err_hook;

extern void breakpoint(void);

/* Console */
struct console;
void kgdb_console_write(struct console *co, const char *s, unsigned count);
void kgdb_console_init(void);

/* Prototypes for jmp fns */
#define _JBLEN 9
typedef        int jmp_buf[_JBLEN];
extern void    longjmp(jmp_buf __jmpb, int __retval);
extern int     setjmp(jmp_buf __jmpb);

/* Variadic macro to print our own message to the console */
#define KGDB_PRINTK(...) printk("KGDB: " __VA_ARGS__)

/* Forced breakpoint */
#define BREAKPOINT() do {                                     \
  if (kgdb_enabled) {                                         \
    asm volatile("trapa   #0xff");                            \
  }                                                           \
} while (0)

/* KGDB should be able to flush all kernel text space */
#if defined(CONFIG_CPU_SH4)
#define kgdb_flush_icache_range(start, end) \
{									\
	extern void __flush_purge_region(void *, int);			\
	__flush_purge_region((void*)(start), (int)(end) - (int)(start));\
	flush_icache_range((start), (end));				\
}
#else
#define kgdb_flush_icache_range(start, end)	do { } while (0)
#endif

/* Kernel assert macros */
#ifdef CONFIG_KGDB_KERNEL_ASSERTS

/* Predefined conditions */
#define KA_VALID_ERRNO(errno) ((errno) > 0 && (errno) <= EMEDIUMTYPE)
#define KA_VALID_PTR_ERR(ptr) KA_VALID_ERRNO(-PTR_ERR(ptr))
#define KA_VALID_KPTR(ptr)  (!(ptr) || \
              ((void *)(ptr) >= (void *)PAGE_OFFSET &&  \
               (void *)(ptr) < ERR_PTR(-EMEDIUMTYPE)))
#define KA_VALID_PTRORERR(errptr) \
               (KA_VALID_KPTR(errptr) || KA_VALID_PTR_ERR(errptr))
#define KA_HELD_GKL()  (current->lock_depth >= 0)

/* The actual assert */
#define KGDB_ASSERT(condition, message) do {                   \
       if (!(condition) && (kgdb_enabled)) {                   \
               KGDB_PRINTK("Assertion failed at %s:%d: %s\n",  \
                                  __FILE__, __LINE__, message);\
               BREAKPOINT();                                   \
       }                                                       \
} while (0)
#else
#define KGDB_ASSERT(condition, message)
#endif

#endif