![Paul Mundt](/assets/img/avatar_default.png)
This rips out most of the needlessly complicated sh_bios and kgdb trap handling, and forces it all through a common fast dispatch path. As more debug traps are inserted, it's important to keep them in sync for all of the parts, not just SH-3/4. As the SH-2 parts are unable to do traps in the >= 0x40 range, we restrict the debug traps to the 0x30-0x3f range on all parts, and also bump the kgdb breakpoint trap down in to this range (from 0xff to 0x3c) so it's possible to use for nommu. Optionally, this table can be padded out to catch spurious traps for SH-3/4, but we don't do that yet.. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
147 lines
4.1 KiB
C
147 lines
4.1 KiB
C
/*
|
|
* 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 #0x3c"); \
|
|
} 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
|
|
|
|
/* Taken from sh-stub.c of GDB 4.18 */
|
|
static const char hexchars[] = "0123456789abcdef";
|
|
|
|
/* Get high hex bits */
|
|
static inline char highhex(const int x)
|
|
{
|
|
return hexchars[(x >> 4) & 0xf];
|
|
}
|
|
|
|
/* Get low hex bits */
|
|
static inline char lowhex(const int x)
|
|
{
|
|
return hexchars[x & 0xf];
|
|
}
|
|
|
|
#endif
|