[U-Boot] [PATCH 0/5] kgdb cleanup and Blackfin kgdb port

I can take care of merging the Blackfin-specific KGDB piece through my tree since it depends on some other Blackfin patches. But all the KGDB common changes can be merged now.
Mike Frysinger (1): kgdb: drop duplicate debugger_exception_handler
Robin Getz (4): kgdb: add default generic stubs kgdb: update mem2hex/hex2mem funcs asm-generic/signal.h: import from linux Blackfin: add support for kgdb
common/Makefile | 2 +- common/kgdb.c | 43 ++- common/kgdb_stubs.c | 64 ++++ cpu/74xx_7xx/traps.c | 4 - cpu/blackfin/interrupt.S | 105 +++++++ cpu/blackfin/traps.c | 57 ++++- cpu/mpc5xx/traps.c | 4 - cpu/mpc5xxx/traps.c | 4 - cpu/mpc8220/traps.c | 4 - cpu/mpc8260/traps.c | 4 - cpu/mpc85xx/traps.c | 4 - cpu/mpc86xx/traps.c | 4 - cpu/mpc8xx/traps.c | 4 - cpu/ppc4xx/traps.c | 4 - include/asm-blackfin/config.h | 7 + include/asm-blackfin/deferred.h | 20 ++ include/asm-blackfin/entry.h | 10 + include/asm-blackfin/mach-common/bits/core.h | 3 + include/asm-blackfin/signal.h | 1 + include/asm-generic/signal.h | 101 ++++++ include/configs/bfin_adi_common.h | 1 + lib_blackfin/Makefile | 2 + lib_blackfin/__kgdb.S | 155 ++++++++++ lib_blackfin/board.c | 6 + lib_blackfin/kgdb.c | 423 ++++++++++++++++++++++++++ lib_blackfin/kgdb.h | 160 ++++++++++ lib_blackfin/string.c | 44 +++- 27 files changed, 1180 insertions(+), 60 deletions(-) create mode 100644 common/kgdb_stubs.c create mode 100644 include/asm-blackfin/deferred.h create mode 100644 include/asm-blackfin/signal.h create mode 100644 include/asm-generic/signal.h create mode 100644 lib_blackfin/__kgdb.S create mode 100644 lib_blackfin/kgdb.c create mode 100644 lib_blackfin/kgdb.h

From: Robin Getz robin.getz@analog.com
The default kgdb functions can be implemented with common U-Boot functions, so rather than force everyone to copy & paste these things, create a set of weak stubs.
Signed-off-by: Robin Getz robin.getz@analog.com Signed-off-by: Mike Frysinger vapier@gentoo.org --- common/Makefile | 2 +- common/kgdb_stubs.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletions(-) create mode 100644 common/kgdb_stubs.c
diff --git a/common/Makefile b/common/Makefile index 44fe687..d054cbe 100644 --- a/common/Makefile +++ b/common/Makefile @@ -149,7 +149,7 @@ COBJS-$(CONFIG_DDR_SPD) += ddr_spd.o COBJS-$(CONFIG_HWCONFIG) += hwconfig.o COBJS-$(CONFIG_CONSOLE_MUX) += iomux.o COBJS-y += flash.o -COBJS-$(CONFIG_CMD_KGDB) += kgdb.o +COBJS-$(CONFIG_CMD_KGDB) += kgdb.o kgdb_stubs.o COBJS-$(CONFIG_KALLSYMS) += kallsyms.o COBJS-$(CONFIG_LCD) += lcd.o COBJS-$(CONFIG_LYNXKDI) += lynxkdi.o diff --git a/common/kgdb_stubs.c b/common/kgdb_stubs.c new file mode 100644 index 0000000..19b0c18 --- /dev/null +++ b/common/kgdb_stubs.c @@ -0,0 +1,64 @@ +/* + * U-boot - stub functions for common kgdb code, + * can be overridden in board specific files + * + * Copyright 2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <common.h> +#include <kgdb.h> + +int (*debugger_exception_handler)(struct pt_regs *); + +__attribute__((weak)) +void kgdb_serial_init(void) +{ + puts("[on serial] "); +} + +__attribute__((weak)) +void putDebugChar(int c) +{ + serial_putc(c); +} + +__attribute__((weak)) +void putDebugStr(const char *str) +{ +#ifdef DEBUG + serial_puts(str); +#endif +} + +__attribute__((weak)) +int getDebugChar(void) +{ + return serial_getc(); +} + +__attribute__((weak)) +void kgdb_interruptible(int yes) +{ + return; +} + +__attribute__((weak)) +void kgdb_flush_cache_range(void *from, void *to) +{ + flush_cache((unsigned long)from, (unsigned long)(to - from)); +} + +__attribute__((weak)) +void kgdb_flush_cache_all(void) +{ + if (dcache_status()) { + dcache_disable(); + dcache_enable(); + } + if (icache_status()) { + icache_disable(); + icache_enable(); + } +}

Dear Mike Frysinger,
In message 1261438846-9675-2-git-send-email-vapier@gentoo.org you wrote:
From: Robin Getz robin.getz@analog.com
The default kgdb functions can be implemented with common U-Boot functions, so rather than force everyone to copy & paste these things, create a set of weak stubs.
Signed-off-by: Robin Getz robin.getz@analog.com Signed-off-by: Mike Frysinger vapier@gentoo.org
common/Makefile | 2 +- common/kgdb_stubs.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletions(-) create mode 100644 common/kgdb_stubs.c
Applied, thanks.
Best regards,
Wolfgang Denk

The debugger_exception_handler definition is the same for everyone, so use the common one now.
Signed-off-by: Mike Frysinger vapier@gentoo.org --- cpu/74xx_7xx/traps.c | 4 ---- cpu/mpc5xx/traps.c | 4 ---- cpu/mpc5xxx/traps.c | 4 ---- cpu/mpc8220/traps.c | 4 ---- cpu/mpc8260/traps.c | 4 ---- cpu/mpc85xx/traps.c | 4 ---- cpu/mpc86xx/traps.c | 4 ---- cpu/mpc8xx/traps.c | 4 ---- cpu/ppc4xx/traps.c | 4 ---- 9 files changed, 0 insertions(+), 36 deletions(-)
diff --git a/cpu/74xx_7xx/traps.c b/cpu/74xx_7xx/traps.c index b066227..24e28e2 100644 --- a/cpu/74xx_7xx/traps.c +++ b/cpu/74xx_7xx/traps.c @@ -40,10 +40,6 @@ DECLARE_GLOBAL_DATA_PTR; #endif
-#if defined(CONFIG_CMD_KGDB) -int (*debugger_exception_handler)(struct pt_regs *) = 0; -#endif - /* Returns 0 if exception not found and fixup otherwise. */ extern unsigned long search_exception_table(unsigned long);
diff --git a/cpu/mpc5xx/traps.c b/cpu/mpc5xx/traps.c index 78c820a..cc8e091 100644 --- a/cpu/mpc5xx/traps.c +++ b/cpu/mpc5xx/traps.c @@ -36,10 +36,6 @@ #include <command.h> #include <asm/processor.h>
-#if defined(CONFIG_CMD_KGDB) -int (*debugger_exception_handler)(struct pt_regs *) = 0; -#endif - #if defined(CONFIG_CMD_BEDBUG) extern void do_bedbug_breakpoint(struct pt_regs *); #endif diff --git a/cpu/mpc5xxx/traps.c b/cpu/mpc5xxx/traps.c index daa1ec6..2a09153 100644 --- a/cpu/mpc5xxx/traps.c +++ b/cpu/mpc5xxx/traps.c @@ -37,10 +37,6 @@ #include <command.h> #include <asm/processor.h>
-#if defined(CONFIG_CMD_KGDB) -int (*debugger_exception_handler)(struct pt_regs *) = 0; -#endif - /* Returns 0 if exception not found and fixup otherwise. */ extern unsigned long search_exception_table(unsigned long);
diff --git a/cpu/mpc8220/traps.c b/cpu/mpc8220/traps.c index 89cca1d..f98d40f 100644 --- a/cpu/mpc8220/traps.c +++ b/cpu/mpc8220/traps.c @@ -37,10 +37,6 @@ #include <command.h> #include <asm/processor.h>
-#if defined(CONFIG_CMD_KGDB) -int (*debugger_exception_handler) (struct pt_regs *) = 0; -#endif - /* Returns 0 if exception not found and fixup otherwise. */ extern unsigned long search_exception_table (unsigned long);
diff --git a/cpu/mpc8260/traps.c b/cpu/mpc8260/traps.c index 6624544..f9f4dea 100644 --- a/cpu/mpc8260/traps.c +++ b/cpu/mpc8260/traps.c @@ -37,10 +37,6 @@ #include <asm/processor.h> #include <asm/m8260_pci.h>
-#if defined(CONFIG_CMD_KGDB) -int (*debugger_exception_handler)(struct pt_regs *) = 0; -#endif - /* Returns 0 if exception not found and fixup otherwise. */ extern unsigned long search_exception_table(unsigned long);
diff --git a/cpu/mpc85xx/traps.c b/cpu/mpc85xx/traps.c index 9d16b9b..241ebd5 100644 --- a/cpu/mpc85xx/traps.c +++ b/cpu/mpc85xx/traps.c @@ -42,10 +42,6 @@
DECLARE_GLOBAL_DATA_PTR;
-#if defined(CONFIG_CMD_KGDB) -int (*debugger_exception_handler)(struct pt_regs *) = 0; -#endif - /* Returns 0 if exception not found and fixup otherwise. */ extern unsigned long search_exception_table(unsigned long);
diff --git a/cpu/mpc86xx/traps.c b/cpu/mpc86xx/traps.c index 13f386d..ad005c3 100644 --- a/cpu/mpc86xx/traps.c +++ b/cpu/mpc86xx/traps.c @@ -36,10 +36,6 @@
DECLARE_GLOBAL_DATA_PTR;
-#if defined(CONFIG_CMD_KGDB) -int (*debugger_exception_handler)(struct pt_regs *) = 0; -#endif - /* Returns 0 if exception not found and fixup otherwise. */ extern unsigned long search_exception_table(unsigned long);
diff --git a/cpu/mpc8xx/traps.c b/cpu/mpc8xx/traps.c index e1ec889..f357c8d 100644 --- a/cpu/mpc8xx/traps.c +++ b/cpu/mpc8xx/traps.c @@ -36,10 +36,6 @@ #include <command.h> #include <asm/processor.h>
-#if defined(CONFIG_CMD_KGDB) -int (*debugger_exception_handler)(struct pt_regs *) = 0; -#endif - #if defined(CONFIG_CMD_BEDBUG) extern void do_bedbug_breakpoint(struct pt_regs *); #endif diff --git a/cpu/ppc4xx/traps.c b/cpu/ppc4xx/traps.c index 55154b6..cb35faf 100644 --- a/cpu/ppc4xx/traps.c +++ b/cpu/ppc4xx/traps.c @@ -38,10 +38,6 @@
DECLARE_GLOBAL_DATA_PTR;
-#if defined(CONFIG_CMD_KGDB) -int (*debugger_exception_handler)(struct pt_regs *) = 0; -#endif - /* Returns 0 if exception not found and fixup otherwise. */ extern unsigned long search_exception_table(unsigned long);

Dear Mike Frysinger,
In message 1261438846-9675-3-git-send-email-vapier@gentoo.org you wrote:
The debugger_exception_handler definition is the same for everyone, so use the common one now.
Signed-off-by: Mike Frysinger vapier@gentoo.org
cpu/74xx_7xx/traps.c | 4 ---- cpu/mpc5xx/traps.c | 4 ---- cpu/mpc5xxx/traps.c | 4 ---- cpu/mpc8220/traps.c | 4 ---- cpu/mpc8260/traps.c | 4 ---- cpu/mpc85xx/traps.c | 4 ---- cpu/mpc86xx/traps.c | 4 ---- cpu/mpc8xx/traps.c | 4 ---- cpu/ppc4xx/traps.c | 4 ---- 9 files changed, 0 insertions(+), 36 deletions(-)
Applied, thanks.
Best regards,
Wolfgang Denk

From: Robin Getz robin.getz@analog.com
Convert the funcs to do the conversion inline so that we can do the copy all at once with memcpy. This let's us push out an weird arch-specific issues with accessing different regions of memory to the memcpy function like the MMRs on Blackfin systems, and it should be a bit faster.
Signed-off-by: Robin Getz robin.getz@analog.com Signed-off-by: Mike Frysinger vapier@gentoo.org --- common/kgdb.c | 43 ++++++++++++++++++++++++++++++++----------- 1 files changed, 32 insertions(+), 11 deletions(-)
diff --git a/common/kgdb.c b/common/kgdb.c index 862f368..0531452 100644 --- a/common/kgdb.c +++ b/common/kgdb.c @@ -132,11 +132,20 @@ hex(unsigned char ch) static unsigned char * mem2hex(char *mem, char *buf, int count) { + char *tmp; unsigned char ch;
+ /* + * We use the upper half of buf as an intermediate buffer for the + * raw memory copy. Hex conversion will work against this one. + */ + tmp = buf + count; longjmp_on_fault = 1; + + memcpy(tmp, mem, count); + while (count-- > 0) { - ch = *mem++; + ch = *tmp++; *buf++ = hexchars[ch >> 4]; *buf++ = hexchars[ch & 0xf]; } @@ -151,21 +160,33 @@ mem2hex(char *mem, char *buf, int count) static char * hex2mem(char *buf, char *mem, int count) { - int i, hexValue; - unsigned char ch; - char *mem_start = mem; + int hexValue; + char *tmp_raw, *tmp_hex; + + /* + * We use the upper half of buf as an intermediate buffer for the + * raw memory that is converted from hex. + */ + tmp_raw = buf + count * 2; + tmp_hex = tmp_raw - 1;
longjmp_on_fault = 1; - for (i=0; i<count; i++) { - if ((hexValue = hex(*buf++)) < 0) + while (tmp_hex >= buf) { + tmp_raw--; + hexValue = hex(*tmp_hex--); + if (hexValue < 0) kgdb_error(KGDBERR_NOTHEXDIG); - ch = hexValue << 4; - if ((hexValue = hex(*buf++)) < 0) + *tmp_raw = hexValue; + hexValue = hex(*tmp_hex--); + if (hexValue < 0) kgdb_error(KGDBERR_NOTHEXDIG); - ch |= hexValue; - *mem++ = ch; + *tmp_raw |= hexValue << 4; + } - kgdb_flush_cache_range((void *)mem_start, (void *)(mem - 1)); + + memcpy(mem, tmp_raw, count); + + kgdb_flush_cache_range((void *)mem, (void *)(mem+count)); longjmp_on_fault = 0;
return buf;

Dear Mike Frysinger,
In message 1261438846-9675-4-git-send-email-vapier@gentoo.org you wrote:
From: Robin Getz robin.getz@analog.com
Convert the funcs to do the conversion inline so that we can do the copy all at once with memcpy. This let's us push out an weird arch-specific issues with accessing different regions of memory to the memcpy function like the MMRs on Blackfin systems, and it should be a bit faster.
Signed-off-by: Robin Getz robin.getz@analog.com Signed-off-by: Mike Frysinger vapier@gentoo.org
common/kgdb.c | 43 ++++++++++++++++++++++++++++++++----------- 1 files changed, 32 insertions(+), 11 deletions(-)
Applied, thanks.
Best regards,
Wolfgang Denk

Dear All,
Greetings!
I am having the following boot requirements:
Boot software will be flashed in to PROM, which should start from PROM and copy the application software which is flahsed in other flash device in different address space. The processor is LEON3FT.
is current release of U-Boot supports LEON3FT architecture, please provide with details and link to get start
Regards, Balaji

Hi Balaji,
I am having the following boot requirements:
Boot software will be flashed in to PROM, which should start from PROM and copy the application software which is flahsed in other flash device in different address space. The processor is LEON3FT.
is current release of U-Boot supports LEON3FT architecture, please provide with details and link to get start
Actually I don't know much about the Leon line of CPUs, but I see that we have three configurations using a Leon CPU: gr_cpci_ax2000, gr_ep2s60, grsim and gr_xc3s_1500. I put the maintainer of these boards on CC, so maybe he can answer that.
Cheers Detlev

Hi,
Detlev Zundel wrote:
Hi Balaji,
I am having the following boot requirements:
Boot software will be flashed in to PROM, which should start from PROM and copy the application software which is flahsed in other flash device in different address space. The processor is LEON3FT.
is current release of U-Boot supports LEON3FT architecture, please provide with details and link to get start
Actually I don't know much about the Leon line of CPUs, but I see that we have three configurations using a Leon CPU: gr_cpci_ax2000, gr_ep2s60, grsim and gr_xc3s_1500. I put the maintainer of these boards on CC, so maybe he can answer that.
Cheers Detlev
As Detlev points out there are three BSPs available. Since the LEON3 is a SOC it is hard to support all different configurations on a board, so the boards supported are though to support the template design of GRLIB.
The LEON3FT is not supported in the current u-boot available in the sparc git repository at denx.de. Some extra steps must be taken when running the fault-tolerant LEON3, one must clear memory and registered for example so that the CRCs of the registers are correct.
I have a version that supports LEON3FT available at ftp://ftp.gaisler.com/u-boot/u-boot-sparc-vxworks-1.0.0.tar.gz, currently I'm working with generating patches for the LEON3 CPU/boards, I have reworked some parts of the current LEON port. I suggest you wait one day or so until I push the patches onto the SPARC-u-boot git repo, after that I will also add the LEON3FT patches. In the meanwhile you can try the FTP link.
Regards, Daniel

Thanks Daniel,
it will be veryhelpful for me to start exploring. pleas do let me know once you have updated for LEON3FT.
have nice weekend.
Regards, Balaji KUPPUSAMY, PMP®
----- Original Message ---- From: Daniel Hellstrom daniel@gaisler.com To: K Balaji krb_balaji@yahoo.com Cc: u-boot@lists.denx.de Sent: Thu, January 21, 2010 3:02:22 PM Subject: Re: [U-Boot] U-Boot for LENO3 processor board
Hi,
Detlev Zundel wrote:
Hi Balaji,
I am having the following boot requirements:
Boot software will be flashed in to PROM, which should start from PROM and copy the application software which is flahsed in other flash device in different address space. The processor is LEON3FT.
is current release of U-Boot supports LEON3FT architecture, please provide with details and link to get start
Actually I don't know much about the Leon line of CPUs, but I see that we have three configurations using a Leon CPU: gr_cpci_ax2000, gr_ep2s60, grsim and gr_xc3s_1500. I put the maintainer of these boards on CC, so maybe he can answer that.
Cheers Detlev
As Detlev points out there are three BSPs available. Since the LEON3 is a SOC it is hard to support all different configurations on a board, so the boards supported are though to support the template design of GRLIB.
The LEON3FT is not supported in the current u-boot available in the sparc git repository at denx.de. Some extra steps must be taken when running the fault-tolerant LEON3, one must clear memory and registered for example so that the CRCs of the registers are correct.
I have a version that supports LEON3FT available at ftp://ftp.gaisler.com/u-boot/u-boot-sparc-vxworks-1.0.0.tar.gz, currently I'm working with generating patches for the LEON3 CPU/boards, I have reworked some parts of the current LEON port. I suggest you wait one day or so until I push the patches onto the SPARC-u-boot git repo, after that I will also add the LEON3FT patches. In the meanwhile you can try the FTP link.
Regards, Daniel

Hi,
Detlev Zundel wrote:
Hi Balaji,
I am having the following boot requirements:
Boot software will be flashed in to PROM, which should start from PROM and copy the application software which is flahsed in other flash device in different address space. The processor is LEON3FT.
is current release of U-Boot supports LEON3FT architecture, please provide with details and link to get start
Actually I don't know much about the Leon line of CPUs, but I see that we have three configurations using a Leon CPU: gr_cpci_ax2000, gr_ep2s60, grsim and gr_xc3s_1500. I put the maintainer of these boards on CC, so maybe he can answer that.
Cheers Detlev
Thank you for CC:ing me Detlev.
As Detlev points out there are three BSPs available. Since the LEON3 is a SOC it is hard to support all different configurations on a board, so the BSPs intention is to support the template design of GRLIB.
The LEON3FT is not supported in the current u-boot available in the sparc git repository at denx.de. Some extra steps must be taken when running the fault-tolerant LEON3, one must clear memory and registered for example so that the CRCs of the registers are correct.
I have a version that supports LEON3FT available at ftp://ftp.gaisler.com/u-boot/u-boot-sparc-vxworks-1.0.0.tar.gz, currently I'm working with generating patches for the LEON3 CPU/boards, I have reworked some parts of the current LEON port. I suggest you wait one day or so until I push the patches onto the SPARC-u-boot git repo, after that I will also add the LEON3FT patches. In the meanwhile you can try the FTP link.
Regards, Daniel

Hallo Detlev,
thanks for prompt reply and the input.
Regards, Balaji KUPPUSAMY, PMP®
----- Original Message ---- From: Detlev Zundel dzu@denx.de To: K Balaji krb_balaji@yahoo.com Cc: u-boot@lists.denx.de; Daniel Hellstrom daniel@gaisler.com Sent: Thu, January 21, 2010 2:14:52 PM Subject: Re: [U-Boot] U-Boot for LENO3 processor board
Hi Balaji,
I am having the following boot requirements:
Boot software will be flashed in to PROM, which should start from PROM and copy the application software which is flahsed in other flash device in different address space. The processor is LEON3FT.
is current release of U-Boot supports LEON3FT architecture, please provide with details and link to get start
Actually I don't know much about the Leon line of CPUs, but I see that we have three configurations using a Leon CPU: gr_cpci_ax2000, gr_ep2s60, grsim and gr_xc3s_1500. I put the maintainer of these boards on CC, so maybe he can answer that.
Cheers Detlev

From: Robin Getz robin.getz@analog.com
We need signal.h for Blackfin/KGDB, so import the asm-generic/signal.h for people to leverage.
Signed-off-by: Robin Getz robin.getz@analog.com Signed-off-by: Mike Frysinger vapier@gentoo.org --- include/asm-generic/signal.h | 101 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 101 insertions(+), 0 deletions(-) create mode 100644 include/asm-generic/signal.h
diff --git a/include/asm-generic/signal.h b/include/asm-generic/signal.h new file mode 100644 index 0000000..af93947 --- /dev/null +++ b/include/asm-generic/signal.h @@ -0,0 +1,101 @@ +#ifndef __ASM_GENERIC_SIGNAL_H +#define __ASM_GENERIC_SIGNAL_H + +#include <linux/types.h> + +#define _NSIG 64 +#define _NSIG_BPW BITS_PER_LONG +#define _NSIG_WORDS (_NSIG / _NSIG_BPW) + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGIOT 6 +#define SIGBUS 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGUSR1 10 +#define SIGSEGV 11 +#define SIGUSR2 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGSTKFLT 16 +#define SIGCHLD 17 +#define SIGCONT 18 +#define SIGSTOP 19 +#define SIGTSTP 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGURG 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGIO 29 +#define SIGPOLL SIGIO +/* +#define SIGLOST 29 +*/ +#define SIGPWR 30 +#define SIGSYS 31 +#define SIGUNUSED 31 + +/* These should not be considered constants from userland. */ +#define SIGRTMIN 32 +#ifndef SIGRTMAX +#define SIGRTMAX _NSIG +#endif + +/* + * SA_FLAGS values: + * + * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_RESTART flag to get restarting signals (which were the default long ago) + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. + * SA_RESETHAND clears the handler when the signal is delivered. + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. + * SA_NODEFER prevents the current signal from being masked in the handler. + * + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single + * Unix names RESETHAND and NODEFER respectively. + */ +#define SA_NOCLDSTOP 0x00000001 +#define SA_NOCLDWAIT 0x00000002 +#define SA_SIGINFO 0x00000004 +#define SA_ONSTACK 0x08000000 +#define SA_RESTART 0x10000000 +#define SA_NODEFER 0x40000000 +#define SA_RESETHAND 0x80000000 + +#define SA_NOMASK SA_NODEFER +#define SA_ONESHOT SA_RESETHAND + +/* + * New architectures should not define the obsolete + * SA_RESTORER 0x04000000 + */ + +/* + * sigaltstack controls + */ +#define SS_ONSTACK 1 +#define SS_DISABLE 2 + +#define MINSIGSTKSZ 2048 +#define SIGSTKSZ 8192 + +#ifndef __ASSEMBLY__ +typedef struct { + unsigned long sig[_NSIG_WORDS]; +} sigset_t; + +/* not actually used, but required for linux/syscalls.h */ + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_GENERIC_SIGNAL_H */

From: Robin Getz robin.getz@analog.com
Signed-off-by: Robin Getz robin.getz@analog.com Signed-off-by: Mike Frysinger vapier@gentoo.org --- cpu/blackfin/interrupt.S | 105 +++++++ cpu/blackfin/traps.c | 57 ++++- include/asm-blackfin/config.h | 7 + include/asm-blackfin/deferred.h | 20 ++ include/asm-blackfin/entry.h | 10 + include/asm-blackfin/mach-common/bits/core.h | 3 + include/asm-blackfin/signal.h | 1 + include/configs/bfin_adi_common.h | 1 + lib_blackfin/Makefile | 2 + lib_blackfin/__kgdb.S | 155 ++++++++++ lib_blackfin/board.c | 6 + lib_blackfin/kgdb.c | 423 ++++++++++++++++++++++++++ lib_blackfin/kgdb.h | 160 ++++++++++ lib_blackfin/string.c | 44 +++- 14 files changed, 982 insertions(+), 12 deletions(-) create mode 100644 include/asm-blackfin/deferred.h create mode 100644 include/asm-blackfin/signal.h create mode 100644 lib_blackfin/__kgdb.S create mode 100644 lib_blackfin/kgdb.c create mode 100644 lib_blackfin/kgdb.h
diff --git a/cpu/blackfin/interrupt.S b/cpu/blackfin/interrupt.S index 8c7a262..69bba3f 100644 --- a/cpu/blackfin/interrupt.S +++ b/cpu/blackfin/interrupt.S @@ -8,6 +8,9 @@ #include <config.h> #include <asm/blackfin.h> #include <asm/entry.h> +#include <asm/ptrace.h> +#include <asm/deferred.h> +#include <asm/mach-common/bits/core.h>
.text
@@ -19,10 +22,75 @@ ENTRY(_trap) SAVE_ALL_SYS
r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ + r1 = 3; /* EVT3 space */ sp += -12; call _trap_c; sp += 12;
+#ifdef CONFIG_EXCEPTION_DEFER + CC = R0 == 0; + IF CC JUMP .Lexit_trap; + + /* To avoid double faults, lower our priority to IRQ5 */ + p4.l = lo(COREMMR_BASE); + p4.h = hi(COREMMR_BASE); + + r7.h = _exception_to_level5; + r7.l = _exception_to_level5; + [p4 + (EVT5 - COREMMR_BASE)] = r7; + + /* + * Save these registers, as they are only valid in exception context + * (where we are now - as soon as we defer to IRQ5, they can change) + */ + p5.l = _deferred_regs; + p5.h = _deferred_regs; + r6 = [p4 + (DCPLB_FAULT_ADDR - COREMMR_BASE)]; + [p5 + (deferred_regs_DCPLB_FAULT_ADDR * 4)] = r6; + + r6 = [p4 + (ICPLB_FAULT_ADDR - COREMMR_BASE)]; + [p5 + (deferred_regs_ICPLB_FAULT_ADDR * 4)] = r6; + + /* Save the state of single stepping */ + r6 = SYSCFG; + [p5 + (deferred_regs_SYSCFG * 4)] = r6; + /* Clear it while we handle the exception in IRQ5 mode + * RESTORE_ALL_SYS will load it, so all we need to do is store it + * in the right place + */ + BITCLR(r6, SYSCFG_SSSTEP_P); + [SP + PT_SYSCFG] = r6; + + /* Since we are going to clobber RETX, we need to save it */ + r6 = retx; + [p5 + (deferred_regs_retx * 4)] = r6; + + /* Save the current IMASK, since we change in order to jump to level 5 */ + cli r6; + [p5 + (deferred_regs_IMASK * 4)] = r6; + + /* Disable all interrupts, but make sure level 5 is enabled so + * we can switch to that level. + */ + r6 = 0x3f; + sti r6; + + /* Clobber RETX so we don't end up back at a faulting instruction */ + [sp + PT_RETX] = r7; + + /* In case interrupts are disabled IPEND[4] (global interrupt disable bit) + * clear it (re-enabling interrupts again) by the special sequence of pushing + * RETI onto the stack. This way we can lower ourselves to IVG5 even if the + * exception was taken after the interrupt handler was called but before it + * got a chance to enable global interrupts itself. + */ + [--sp] = reti; + sp += 4; + + RAISE 5; +.Lexit_trap: +#endif + #if ANOMALY_05000257 R7 = LC0; LC0 = R7; @@ -35,6 +103,43 @@ ENTRY(_trap) rtx; ENDPROC(_trap)
+#ifdef CONFIG_EXCEPTION_DEFER +/* Deferred (IRQ5) exceptions */ +ENTRY(_exception_to_level5) + SAVE_ALL_SYS + + /* Now we have to fix things up */ + p4.l = lo(EVT5); + p4.h = hi(EVT5); + r0.l = _evt_default; + r0.h = _evt_default; + [p4] = r0; + csync; + + p4.l = _deferred_regs; + p4.h = _deferred_regs; + r0 = [p4 + (deferred_regs_retx * 4)]; + [sp + PT_PC] = r0; + + r0 = [p4 + (deferred_regs_SYSCFG * 4)]; + [sp + PT_SYSCFG] = r0; + + r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ + r1 = 5; /* EVT5 space */ + sp += -12; + call _trap_c; + sp += 12; + + /* Restore IMASK */ + r0 = [p4 + (deferred_regs_IMASK * 4)]; + sti r0; + + RESTORE_ALL_SYS + + rti; +ENDPROC(_exception_to_level5) +#endif + /* default entry point for interrupts */ ENTRY(_evt_default) SAVE_ALL_SYS diff --git a/cpu/blackfin/traps.c b/cpu/blackfin/traps.c index becc36e..caaea94 100644 --- a/cpu/blackfin/traps.c +++ b/cpu/blackfin/traps.c @@ -18,6 +18,7 @@ */
#include <common.h> +#include <kgdb.h> #include <linux/types.h> #include <asm/traps.h> #include <asm/cplb.h> @@ -25,6 +26,7 @@ #include <asm/mach-common/bits/core.h> #include <asm/mach-common/bits/mpu.h> #include <asm/mach-common/bits/trace.h> +#include <asm/deferred.h> #include "cpu.h"
#define trace_buffer_save(x) \ @@ -69,8 +71,16 @@ const struct memory_map const bfin_memory_map[] = { } };
-void trap_c(struct pt_regs *regs) +#ifdef CONFIG_EXCEPTION_DEFER +unsigned int deferred_regs[deferred_regs_last]; +#endif + +/* + * Handle all exceptions while running in EVT3 or EVT5 + */ +int trap_c(struct pt_regs *regs, uint32_t level) { + uint32_t ret = 0; uint32_t trapnr = (regs->seqstat & EXCAUSE); bool data = false;
@@ -87,7 +97,7 @@ void trap_c(struct pt_regs *regs) */ if (last_cplb_fault_retx != regs->retx) { last_cplb_fault_retx = regs->retx; - return; + return ret; } }
@@ -102,6 +112,12 @@ void trap_c(struct pt_regs *regs) size_t i; unsigned long tflags;
+#ifdef CONFIG_EXCEPTION_DEFER + /* This should never happen */ + if (level == 5) + bfin_panic(regs); +#endif + /* * Keep the trace buffer so that a miss here points people * to the right place (their code). Crashes here rarely @@ -167,11 +183,40 @@ void trap_c(struct pt_regs *regs) trace_buffer_restore(tflags); break; } - +#ifdef CONFIG_CMD_KGDB + /* Single step + * if we are in IRQ5, just ignore, otherwise defer, and handle it in kgdb + */ + case VEC_STEP: + if (level == 3) { + /* If we just returned from an interrupt, the single step + * event is for the RTI instruction. + */ + if (regs->retx == regs->pc) + break; + /* we just return if we are single stepping through IRQ5 */ + if (regs->ipend & 0x20) + break; + /* Otherwise, turn single stepping off & fall through, + * which defers to IRQ5 + */ + regs->syscfg &= ~1; + } + /* fall through */ +#endif default: - /* All traps come here */ +#ifdef CONFIG_CMD_KGDB + if (level == 3) { + /* We need to handle this at EVT5, so try again */ + ret = 1; + break; + } + if (debugger_exception_handler && (*debugger_exception_handler)(regs)) + return 0; +#endif bfin_panic(regs); } + return ret; }
#ifdef CONFIG_DEBUG_DUMP @@ -251,8 +296,10 @@ void dump(struct pt_regs *fp) if (!ENABLE_DUMP) return;
- /* fp->ipend is garbage, so load it ourself */ +#ifndef CONFIG_CMD_KGDB + /* fp->ipend is normally garbage, so load it ourself */ fp->ipend = bfin_read_IPEND(); +#endif
hwerrcause = (fp->seqstat & HWERRCAUSE) >> HWERRCAUSE_P; excause = (fp->seqstat & EXCAUSE) >> EXCAUSE_P; diff --git a/include/asm-blackfin/config.h b/include/asm-blackfin/config.h index 0ae838a..7455685 100644 --- a/include/asm-blackfin/config.h +++ b/include/asm-blackfin/config.h @@ -66,6 +66,11 @@ # error CONFIG_PLL_BYPASS: Invalid value: must be 0 or 1 #endif
+/* If we are using KGDB, make sure we defer exceptions */ +#ifdef CONFIG_CMD_KGDB +# define CONFIG_EXCEPTION_DEFER 1 +#endif + /* Using L1 scratch pad makes sense for everyone by default. */ #ifndef CONFIG_LINUX_CMDLINE_ADDR # define CONFIG_LINUX_CMDLINE_ADDR L1_SRAM_SCRATCH @@ -138,6 +143,8 @@ #endif #ifndef CONFIG_SYS_CBSIZE # define CONFIG_SYS_CBSIZE 1024 +#elif defined(CONFIG_CMD_KGDB) && CONFIG_SYS_CBSIZE < 1024 +# error "kgdb needs cbsize to be >= 1024" #endif #ifndef CONFIG_SYS_BARGSIZE # define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE diff --git a/include/asm-blackfin/deferred.h b/include/asm-blackfin/deferred.h new file mode 100644 index 0000000..82ceda3 --- /dev/null +++ b/include/asm-blackfin/deferred.h @@ -0,0 +1,20 @@ +/* + * U-boot - deferred register layout + * + * Copyright 2004-2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef _BLACKFIN_DEFER_H +#define _BLACKFIN_DEFER_H + +#define deferred_regs_DCPLB_FAULT_ADDR 0 +#define deferred_regs_ICPLB_FAULT_ADDR 1 +#define deferred_regs_retx 2 +#define deferred_regs_SEQSTAT 3 +#define deferred_regs_SYSCFG 4 +#define deferred_regs_IMASK 5 +#define deferred_regs_last 6 + +#endif /* _BLACKFIN_DEFER_H */ diff --git a/include/asm-blackfin/entry.h b/include/asm-blackfin/entry.h index ef74d68..404144f 100644 --- a/include/asm-blackfin/entry.h +++ b/include/asm-blackfin/entry.h @@ -86,6 +86,11 @@ [--sp] = RETE; [--sp] = SEQSTAT; [--sp] = SYSCFG; +#ifdef CONFIG_CMD_KGDB + p0.l = lo(IPEND) + p0.h = hi(IPEND) + r0 = [p0]; +#endif [--sp] = r0; /* Skip IPEND as well. */ .endm
@@ -137,6 +142,11 @@ [--sp] = RETE; [--sp] = SEQSTAT; [--sp] = SYSCFG; +#ifdef CONFIG_CMD_KGDB + p0.l = lo(IPEND) + p0.h = hi(IPEND) + r0 = [p0]; +#endif [--sp] = r0; /* Skip IPEND as well. */ .endm
diff --git a/include/asm-blackfin/mach-common/bits/core.h b/include/asm-blackfin/mach-common/bits/core.h index d8cee10..6db4f81 100644 --- a/include/asm-blackfin/mach-common/bits/core.h +++ b/include/asm-blackfin/mach-common/bits/core.h @@ -105,5 +105,8 @@ #define SSSTEP 0x00000001 /* Supervisor Single Step */ #define CCEN 0x00000002 /* Cycle Counter Enable */ #define SNEN 0x00000004 /* Self-Nesting Interrupt Enable */ +#define SYSCFG_SSSTEP_P 0 +#define SYSCFG_CCEN_P 1 +#define SYSCFG_SCEN_P 2
#endif diff --git a/include/asm-blackfin/signal.h b/include/asm-blackfin/signal.h new file mode 100644 index 0000000..7b1573c --- /dev/null +++ b/include/asm-blackfin/signal.h @@ -0,0 +1 @@ +#include <asm-generic/signal.h> diff --git a/include/configs/bfin_adi_common.h b/include/configs/bfin_adi_common.h index 0da7940..91c5666 100644 --- a/include/configs/bfin_adi_common.h +++ b/include/configs/bfin_adi_common.h @@ -80,6 +80,7 @@ # define CONFIG_CMD_CPLBINFO # define CONFIG_CMD_ELF # define CONFIG_ELF_SIMPLE_LOAD +# define CONFIG_CMD_KGDB # define CONFIG_CMD_REGINFO # define CONFIG_CMD_STRINGS # if defined(__ADSPBF51x__) || defined(__ADSPBF52x__) || defined(__ADSPBF54x__) diff --git a/lib_blackfin/Makefile b/lib_blackfin/Makefile index eebb131..3bdba75 100644 --- a/lib_blackfin/Makefile +++ b/lib_blackfin/Makefile @@ -37,12 +37,14 @@ SOBJS-y += memcpy.o SOBJS-y += memmove.o SOBJS-y += memset.o SOBJS-y += outs.o +SOBJS-$(CONFIG_CMD_KGDB) += __kgdb.o
COBJS-y += board.o COBJS-y += boot.o COBJS-y += cache.o COBJS-y += clocks.o COBJS-$(CONFIG_CMD_CACHE_DUMP) += cmd_cache_dump.o +COBJS-$(CONFIG_CMD_KGDB) += kgdb.o COBJS-y += muldi3.o COBJS-$(CONFIG_POST) += post.o tests.o COBJS-y += string.o diff --git a/lib_blackfin/__kgdb.S b/lib_blackfin/__kgdb.S new file mode 100644 index 0000000..cba4179 --- /dev/null +++ b/lib_blackfin/__kgdb.S @@ -0,0 +1,155 @@ + +#include <asm/linkage.h> + +/* save stack context for non-local goto + * int kgdb_setjmp(long *buf) + */ + +ENTRY(_kgdb_setjmp) + [--SP] = p0; /* Save P0 */ + p0 = r0; + r0 = [SP++]; /* Load P0 into R0 */ + + [p0 + 0x00] = r0; /* GP address registers */ + [p0 + 0x04] = p1; + [p0 + 0x08] = p2; + [p0 + 0x0C] = p3; + [p0 + 0x10] = p4; + [p0 + 0x14] = p5; + [p0 + 0x18] = FP; /* frame pointer */ + [p0 + 0x1C] = SP; /* stack pointer */ + + [p0 + 0x20] = p0; /* data regs */ + [p0 + 0x24] = r1; + [p0 + 0x28] = r2; + [p0 + 0x2C] = r3; + [p0 + 0x30] = r4; + [p0 + 0x34] = r5; + [p0 + 0x38] = r6; + [p0 + 0x3C] = r7; + + r0 = ASTAT; [p0 + 0x40] = r0; + + /* loop counters */ + r0 = LC0; [p0 + 0x44] = r0; + r0 = LC1; [p0 + 0x48] = r0; + + /* Accumulator */ + r0 = A0.w; [p0 + 0x4C] = r0; + r0.l = A0.x; [p0 + 0x50] = r0; + r0 = A1.w; [p0 + 0x54] = r0; + r0.l = A1.x; [p0 + 0x58] = r0; + + /* index registers */ + r0 = i0; [p0 + 0x5C] = r0; + r0 = i1; [p0 + 0x60] = r0; + r0 = i2; [p0 + 0x64] = r0; + r0 = i3; [p0 + 0x68] = r0; + + /* modifier registers */ + r0 = m0; [p0 + 0x6C] = r0; + r0 = m1; [p0 + 0x70] = r0; + r0 = m2; [p0 + 0x74] = r0; + r0 = m3; [p0 + 0x78] = r0; + + /* length registers */ + r0 = l0; [p0 + 0x7C] = r0; + r0 = l1; [p0 + 0x80] = r0; + r0 = l2; [p0 + 0x84] = r0; + r0 = l3; [p0 + 0x88] = r0; + + /* base registers */ + r0 = b0; [p0 + 0x8C] = r0; + r0 = b1; [p0 + 0x90] = r0; + r0 = b2; [p0 + 0x94] = r0; + r0 = b3; [p0 + 0x98] = r0; + + /* store return address */ + r0 = RETS; [p0 + 0x9C] = r0; + + R0 = 0; + RTS; +ENDPROC(_kgdb_setjmp) + +/* + * non-local jump to a saved stack context + * longjmp(long *buf, int val) + */ + +ENTRY(_kgdb_longjmp) + p0 = r0; + r0 = [p0 + 0x00]; + [--sp] = r0; + + /* GP address registers - skip p0 for now*/ + p1 = [p0 + 0x04]; + p2 = [p0 + 0x08]; + p3 = [p0 + 0x0C]; + p4 = [p0 + 0x10]; + p5 = [p0 + 0x14]; + /* frame pointer */ + fp = [p0 + 0x18]; + /* stack pointer */ + r0 = [sp++]; + sp = [p0 + 0x1C]; + [--sp] = r0; + [--sp] = r1; + + /* data regs */ + r0 = [p0 + 0x20]; + r1 = [p0 + 0x24]; + r2 = [p0 + 0x28]; + r3 = [p0 + 0x2C]; + r4 = [p0 + 0x30]; + r5 = [p0 + 0x34]; + r6 = [p0 + 0x38]; + r7 = [p0 + 0x3C]; + + r0 = [p0 + 0x40]; ASTAT = r0; + + /* loop counters */ + r0 = [p0 + 0x44]; LC0 = r0; + r0 = [p0 + 0x48]; LC1 = r0; + + /* Accumulator */ + r0 = [p0 + 0x4C]; A0.w = r0; + r0 = [p0 + 0x50]; A0.x = r0; + r0 = [p0 + 0x54]; A1.w = r0; + r0 = [p0 + 0x58]; A1.x = r0; + + /* index registers */ + r0 = [p0 + 0x5C]; i0 = r0; + r0 = [p0 + 0x60]; i1 = r0; + r0 = [p0 + 0x64]; i2 = r0; + r0 = [p0 + 0x68]; i3 = r0; + + /* modifier registers */ + r0 = [p0 + 0x6C]; m0 = r0; + r0 = [p0 + 0x70]; m1 = r0; + r0 = [p0 + 0x74]; m2 = r0; + r0 = [p0 + 0x78]; m3 = r0; + + /* length registers */ + r0 = [p0 + 0x7C]; l0 = r0; + r0 = [p0 + 0x80]; l1 = r0; + r0 = [p0 + 0x84]; l2 = r0; + r0 = [p0 + 0x88]; l3 = r0; + + /* base registers */ + r0 = [p0 + 0x8C]; b0 = r0; + r0 = [p0 + 0x90]; b1 = r0; + r0 = [p0 + 0x94]; b2 = r0; + r0 = [p0 + 0x98]; b3 = r0; + + /* store return address */ + r0 = [p0 + 0x9C]; RETS = r0; + + /* fixup R0 & P0 */ + r0 = [sp++]; + p0 = [sp++]; + CC = R0 == 0; + IF !CC JUMP .Lfinished; + R0 = 1; +.Lfinished: + RTS; +ENDPROC(_kgdb_longjmp) diff --git a/lib_blackfin/board.c b/lib_blackfin/board.c index 90da2b4..21fff33 100644 --- a/lib_blackfin/board.c +++ b/lib_blackfin/board.c @@ -22,6 +22,7 @@
#include <asm/cplb.h> #include <asm/mach-common/bits/mpu.h> +#include <kgdb.h>
#ifdef CONFIG_CMD_NAND #include <nand.h> /* cannot even include nand.h if it isnt configured */ @@ -356,6 +357,11 @@ void board_init_r(gd_t * id, ulong dest_addr) /* Initialize the console (after the relocation and devices init) */ console_init_r();
+#ifdef CONFIG_CMD_KGDB + puts("KGDB: "); + kgdb_init(); +#endif + #ifdef CONFIG_STATUS_LED status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING); status_led_set(STATUS_LED_CRASH, STATUS_LED_OFF); diff --git a/lib_blackfin/kgdb.c b/lib_blackfin/kgdb.c new file mode 100644 index 0000000..bd62d71 --- /dev/null +++ b/lib_blackfin/kgdb.c @@ -0,0 +1,423 @@ +/* + * U-boot - architecture specific kgdb code + * + * Copyright 2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <common.h> +#include <command.h> + +#include <kgdb.h> +#include <asm/processor.h> +#include <asm/mach-common/bits/core.h> +#include "kgdb.h" +#include <asm/deferred.h> +#include <asm/traps.h> +#include <asm/signal.h> + +void kgdb_enter(struct pt_regs *regs, kgdb_data *kdp) +{ + /* disable interrupts */ + disable_interrupts(); + + /* reply to host that an exception has occurred */ + kdp->sigval = kgdb_trap(regs); + + /* send the PC and the Stack Pointer */ + kdp->nregs = 2; + kdp->regs[0].num = BFIN_PC; + kdp->regs[0].val = regs->pc; + + kdp->regs[1].num = BFIN_SP; + kdp->regs[1].val = (unsigned long)regs; + +} + +void kgdb_exit(struct pt_regs *regs, kgdb_data *kdp) +{ + if (kdp->extype & KGDBEXIT_WITHADDR) + printf("KGDBEXIT_WITHADDR\n"); + + switch (kdp->extype & KGDBEXIT_TYPEMASK) { + case KGDBEXIT_KILL: + printf("KGDBEXIT_KILL:\n"); + break; + case KGDBEXIT_CONTINUE: + /* Make sure the supervisor single step bit is clear */ + regs->syscfg &= ~1; + break; + case KGDBEXIT_SINGLE: + /* set the supervisor single step bit */ + regs->syscfg |= 1; + break; + default: + printf("KGDBEXIT : %d\n", kdp->extype); + } + + /* enable interrupts */ + enable_interrupts(); +} + +int kgdb_trap(struct pt_regs *regs) +{ + /* ipend doesn't get filled in properly */ + switch (regs->seqstat & EXCAUSE) { + case VEC_EXCPT01: + return SIGTRAP; + case VEC_EXCPT03: + return SIGSEGV; + case VEC_EXCPT02: + return SIGTRAP; + case VEC_EXCPT04 ... VEC_EXCPT15: + return SIGILL; + case VEC_STEP: + return SIGTRAP; + case VEC_OVFLOW: + return SIGTRAP; + case VEC_UNDEF_I: + return SIGILL; + case VEC_ILGAL_I: + return SIGILL; + case VEC_CPLB_VL: + return SIGSEGV; + case VEC_MISALI_D: + return SIGBUS; + case VEC_UNCOV: + return SIGILL; + case VEC_CPLB_MHIT: + return SIGSEGV; + case VEC_MISALI_I: + return SIGBUS; + case VEC_CPLB_I_VL: + return SIGBUS; + case VEC_CPLB_I_MHIT: + return SIGSEGV; + default: + return SIGBUS; + } +} + +/* + * getregs - gets the pt_regs, and gives them to kgdb's buffer + */ +int kgdb_getregs(struct pt_regs *regs, char *buf, int max) +{ + unsigned long *gdb_regs = (unsigned long *)buf; + + if (max < NUMREGBYTES) + kgdb_error(KGDBERR_NOSPACE); + + if ((unsigned long)gdb_regs & 3) + kgdb_error(KGDBERR_ALIGNFAULT); + + gdb_regs[BFIN_R0] = regs->r0; + gdb_regs[BFIN_R1] = regs->r1; + gdb_regs[BFIN_R2] = regs->r2; + gdb_regs[BFIN_R3] = regs->r3; + gdb_regs[BFIN_R4] = regs->r4; + gdb_regs[BFIN_R5] = regs->r5; + gdb_regs[BFIN_R6] = regs->r6; + gdb_regs[BFIN_R7] = regs->r7; + gdb_regs[BFIN_P0] = regs->p0; + gdb_regs[BFIN_P1] = regs->p1; + gdb_regs[BFIN_P2] = regs->p2; + gdb_regs[BFIN_P3] = regs->p3; + gdb_regs[BFIN_P4] = regs->p4; + gdb_regs[BFIN_P5] = regs->p5; + gdb_regs[BFIN_SP] = (unsigned long)regs; + gdb_regs[BFIN_FP] = regs->fp; + gdb_regs[BFIN_I0] = regs->i0; + gdb_regs[BFIN_I1] = regs->i1; + gdb_regs[BFIN_I2] = regs->i2; + gdb_regs[BFIN_I3] = regs->i3; + gdb_regs[BFIN_M0] = regs->m0; + gdb_regs[BFIN_M1] = regs->m1; + gdb_regs[BFIN_M2] = regs->m2; + gdb_regs[BFIN_M3] = regs->m3; + gdb_regs[BFIN_B0] = regs->b0; + gdb_regs[BFIN_B1] = regs->b1; + gdb_regs[BFIN_B2] = regs->b2; + gdb_regs[BFIN_B3] = regs->b3; + gdb_regs[BFIN_L0] = regs->l0; + gdb_regs[BFIN_L1] = regs->l1; + gdb_regs[BFIN_L2] = regs->l2; + gdb_regs[BFIN_L3] = regs->l3; + gdb_regs[BFIN_A0_DOT_X] = regs->a0x; + gdb_regs[BFIN_A0_DOT_W] = regs->a0w; + gdb_regs[BFIN_A1_DOT_X] = regs->a1x; + gdb_regs[BFIN_A1_DOT_W] = regs->a1w; + gdb_regs[BFIN_ASTAT] = regs->astat; + gdb_regs[BFIN_RETS] = regs->rets; + gdb_regs[BFIN_LC0] = regs->lc0; + gdb_regs[BFIN_LT0] = regs->lt0; + gdb_regs[BFIN_LB0] = regs->lb0; + gdb_regs[BFIN_LC1] = regs->lc1; + gdb_regs[BFIN_LT1] = regs->lt1; + gdb_regs[BFIN_LB1] = regs->lb1; + gdb_regs[BFIN_CYCLES] = 0; + gdb_regs[BFIN_CYCLES2] = 0; + gdb_regs[BFIN_USP] = regs->usp; + gdb_regs[BFIN_SEQSTAT] = regs->seqstat; + gdb_regs[BFIN_SYSCFG] = regs->syscfg; + gdb_regs[BFIN_RETI] = regs->pc; + gdb_regs[BFIN_RETX] = regs->retx; + gdb_regs[BFIN_RETN] = regs->retn; + gdb_regs[BFIN_RETE] = regs->rete; + gdb_regs[BFIN_PC] = regs->pc; + gdb_regs[BFIN_CC] = 0; + gdb_regs[BFIN_EXTRA1] = 0; + gdb_regs[BFIN_EXTRA2] = 0; + gdb_regs[BFIN_EXTRA3] = 0; + gdb_regs[BFIN_IPEND] = regs->ipend; + + return NUMREGBYTES; +} + +/* + * putreg - put kgdb's reg (regno) into the pt_regs + */ +void kgdb_putreg(struct pt_regs *regs, int regno, char *buf, int length) +{ + unsigned long *ptr = (unsigned long *)buf; + + if (regno < 0 || regno > BFIN_NUM_REGS) + kgdb_error(KGDBERR_BADPARAMS); + + if (length < 4) + kgdb_error(KGDBERR_NOSPACE); + + if ((unsigned long)ptr & 3) + kgdb_error(KGDBERR_ALIGNFAULT); + + switch (regno) { + case BFIN_R0: + regs->r0 = *ptr; + break; + case BFIN_R1: + regs->r1 = *ptr; + break; + case BFIN_R2: + regs->r2 = *ptr; + break; + case BFIN_R3: + regs->r3 = *ptr; + break; + case BFIN_R4: + regs->r4 = *ptr; + break; + case BFIN_R5: + regs->r5 = *ptr; + break; + case BFIN_R6: + regs->r6 = *ptr; + break; + case BFIN_R7: + regs->r7 = *ptr; + break; + case BFIN_P0: + regs->p0 = *ptr; + break; + case BFIN_P1: + regs->p1 = *ptr; + break; + case BFIN_P2: + regs->p2 = *ptr; + break; + case BFIN_P3: + regs->p3 = *ptr; + break; + case BFIN_P4: + regs->p4 = *ptr; + break; + case BFIN_P5: + regs->p5 = *ptr; + break; + case BFIN_SP: + regs->reserved = *ptr; + break; + case BFIN_FP: + regs->fp = *ptr; + break; + case BFIN_I0: + regs->i0 = *ptr; + break; + case BFIN_I1: + regs->i1 = *ptr; + break; + case BFIN_I2: + regs->i2 = *ptr; + break; + case BFIN_I3: + regs->i3 = *ptr; + break; + case BFIN_M0: + regs->m0 = *ptr; + break; + case BFIN_M1: + regs->m1 = *ptr; + break; + case BFIN_M2: + regs->m2 = *ptr; + break; + case BFIN_M3: + regs->m3 = *ptr; + break; + case BFIN_B0: + regs->b0 = *ptr; + break; + case BFIN_B1: + regs->b1 = *ptr; + break; + case BFIN_B2: + regs->b2 = *ptr; + break; + case BFIN_B3: + regs->b3 = *ptr; + break; + case BFIN_L0: + regs->l0 = *ptr; + break; + case BFIN_L1: + regs->l1 = *ptr; + break; + case BFIN_L2: + regs->l2 = *ptr; + break; + case BFIN_L3: + regs->l3 = *ptr; + break; + case BFIN_A0_DOT_X: + regs->a0x = *ptr; + break; + case BFIN_A0_DOT_W: + regs->a0w = *ptr; + break; + case BFIN_A1_DOT_X: + regs->a1x = *ptr; + break; + case BFIN_A1_DOT_W: + regs->a1w = *ptr; + break; + case BFIN_ASTAT: + regs->astat = *ptr; + break; + case BFIN_RETS: + regs->rets = *ptr; + break; + case BFIN_LC0: + regs->lc0 = *ptr; + break; + case BFIN_LT0: + regs->lt0 = *ptr; + break; + case BFIN_LB0: + regs->lb0 = *ptr; + break; + case BFIN_LC1: + regs->lc1 = *ptr; + break; + case BFIN_LT1: + regs->lt1 = *ptr; + break; + case BFIN_LB1: + regs->lb1 = *ptr; + break; +/* + BFIN_CYCLES, + BFIN_CYCLES2, + BFIN_USP, + BFIN_SEQSTAT, + BFIN_SYSCFG, +*/ + case BFIN_RETX: + regs->retx = *ptr; + break; + case BFIN_RETN: + regs->retn = *ptr; + break; + case BFIN_RETE: + regs->rete = *ptr; + break; + case BFIN_PC: + regs->pc = *ptr; + break; + + default: + kgdb_error(KGDBERR_BADPARAMS); + } +} + +void kgdb_putregs(struct pt_regs *regs, char *buf, int length) +{ + unsigned long *gdb_regs = (unsigned long *)buf; + + if (length != BFIN_NUM_REGS) + kgdb_error(KGDBERR_NOSPACE); + + if ((unsigned long)gdb_regs & 3) + kgdb_error(KGDBERR_ALIGNFAULT); + + regs->r0 = gdb_regs[BFIN_R0]; + regs->r1 = gdb_regs[BFIN_R1]; + regs->r2 = gdb_regs[BFIN_R2]; + regs->r3 = gdb_regs[BFIN_R3]; + regs->r4 = gdb_regs[BFIN_R4]; + regs->r5 = gdb_regs[BFIN_R5]; + regs->r6 = gdb_regs[BFIN_R6]; + regs->r7 = gdb_regs[BFIN_R7]; + regs->p0 = gdb_regs[BFIN_P0]; + regs->p1 = gdb_regs[BFIN_P1]; + regs->p2 = gdb_regs[BFIN_P2]; + regs->p3 = gdb_regs[BFIN_P3]; + regs->p4 = gdb_regs[BFIN_P4]; + regs->p5 = gdb_regs[BFIN_P5]; + regs->fp = gdb_regs[BFIN_FP]; +/* regs->sp = gdb_regs[BFIN_ ]; */ + regs->i0 = gdb_regs[BFIN_I0]; + regs->i1 = gdb_regs[BFIN_I1]; + regs->i2 = gdb_regs[BFIN_I2]; + regs->i3 = gdb_regs[BFIN_I3]; + regs->m0 = gdb_regs[BFIN_M0]; + regs->m1 = gdb_regs[BFIN_M1]; + regs->m2 = gdb_regs[BFIN_M2]; + regs->m3 = gdb_regs[BFIN_M3]; + regs->b0 = gdb_regs[BFIN_B0]; + regs->b1 = gdb_regs[BFIN_B1]; + regs->b2 = gdb_regs[BFIN_B2]; + regs->b3 = gdb_regs[BFIN_B3]; + regs->l0 = gdb_regs[BFIN_L0]; + regs->l1 = gdb_regs[BFIN_L1]; + regs->l2 = gdb_regs[BFIN_L2]; + regs->l3 = gdb_regs[BFIN_L3]; + regs->a0x = gdb_regs[BFIN_A0_DOT_X]; + regs->a0w = gdb_regs[BFIN_A0_DOT_W]; + regs->a1x = gdb_regs[BFIN_A1_DOT_X]; + regs->a1w = gdb_regs[BFIN_A1_DOT_W]; + regs->rets = gdb_regs[BFIN_RETS]; + regs->lc0 = gdb_regs[BFIN_LC0]; + regs->lt0 = gdb_regs[BFIN_LT0]; + regs->lb0 = gdb_regs[BFIN_LB0]; + regs->lc1 = gdb_regs[BFIN_LC1]; + regs->lt1 = gdb_regs[BFIN_LT1]; + regs->lb1 = gdb_regs[BFIN_LB1]; + regs->usp = gdb_regs[BFIN_USP]; + regs->syscfg = gdb_regs[BFIN_SYSCFG]; + regs->retx = gdb_regs[BFIN_PC]; + regs->retn = gdb_regs[BFIN_RETN]; + regs->rete = gdb_regs[BFIN_RETE]; + regs->pc = gdb_regs[BFIN_PC]; + +#if 0 /* can't change these */ + regs->astat = gdb_regs[BFIN_ASTAT]; + regs->seqstat = gdb_regs[BFIN_SEQSTAT]; + regs->ipend = gdb_regs[BFIN_IPEND]; +#endif + +} + +void kgdb_breakpoint(int argc, char *argv[]) +{ + asm volatile ("excpt 0x1\n"); +} diff --git a/lib_blackfin/kgdb.h b/lib_blackfin/kgdb.h new file mode 100644 index 0000000..18f1f49 --- /dev/null +++ b/lib_blackfin/kgdb.h @@ -0,0 +1,160 @@ +/* Blackfin KGDB header + * + * Copyright 2005-2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __ASM_BLACKFIN_KGDB_H__ +#define __ASM_BLACKFIN_KGDB_H__ + +/* gdb locks */ +#define KGDB_MAX_NO_CPUS 8 + +/* + * BUFMAX defines the maximum number of characters in inbound/outbound buffers. + * At least NUMREGBYTES*2 are needed for register packets. + * Longer buffer is needed to list all threads. + */ +#define BUFMAX 2048 + +enum regnames { + /* Core Registers */ + BFIN_R0 = 0, + BFIN_R1, + BFIN_R2, + BFIN_R3, + BFIN_R4, + BFIN_R5, + BFIN_R6, + BFIN_R7, + BFIN_P0, + BFIN_P1, + BFIN_P2, + BFIN_P3, + BFIN_P4, + BFIN_P5, + BFIN_SP, + BFIN_FP, + BFIN_I0, + BFIN_I1, + BFIN_I2, + BFIN_I3, + BFIN_M0, + BFIN_M1, + BFIN_M2, + BFIN_M3, + BFIN_B0, + BFIN_B1, + BFIN_B2, + BFIN_B3, + BFIN_L0, + BFIN_L1, + BFIN_L2, + BFIN_L3, + BFIN_A0_DOT_X, + BFIN_A0_DOT_W, + BFIN_A1_DOT_X, + BFIN_A1_DOT_W, + BFIN_ASTAT, + BFIN_RETS, + BFIN_LC0, + BFIN_LT0, + BFIN_LB0, + BFIN_LC1, + BFIN_LT1, + BFIN_LB1, + BFIN_CYCLES, + BFIN_CYCLES2, + BFIN_USP, + BFIN_SEQSTAT, + BFIN_SYSCFG, + BFIN_RETI, + BFIN_RETX, + BFIN_RETN, + BFIN_RETE, + + /* Pseudo Registers */ + BFIN_PC, + BFIN_CC, + BFIN_EXTRA1, /* Address of .text section. */ + BFIN_EXTRA2, /* Address of .data section. */ + BFIN_EXTRA3, /* Address of .bss section. */ + BFIN_FDPIC_EXEC, + BFIN_FDPIC_INTERP, + + /* MMRs */ + BFIN_IPEND, + + /* LAST ENTRY SHOULD NOT BE CHANGED. */ + BFIN_NUM_REGS /* The number of all registers. */ +}; + +/* Number of bytes of registers. */ +#define NUMREGBYTES (BFIN_NUM_REGS * 4) + +static inline void arch_kgdb_breakpoint(void) +{ + asm volatile ("EXCPT 2;"); +} +#define BREAK_INSTR_SIZE 2 +#define CACHE_FLUSH_IS_SAFE 1 +#define GDB_ADJUSTS_BREAK_OFFSET +#define GDB_SKIP_HW_WATCH_TEST +#define HW_INST_WATCHPOINT_NUM 6 +#define HW_WATCHPOINT_NUM 8 +#define TYPE_INST_WATCHPOINT 0 +#define TYPE_DATA_WATCHPOINT 1 + +/* Instruction watchpoint address control register bits mask */ +#define WPPWR 0x1 +#define WPIREN01 0x2 +#define WPIRINV01 0x4 +#define WPIAEN0 0x8 +#define WPIAEN1 0x10 +#define WPICNTEN0 0x20 +#define WPICNTEN1 0x40 +#define EMUSW0 0x80 +#define EMUSW1 0x100 +#define WPIREN23 0x200 +#define WPIRINV23 0x400 +#define WPIAEN2 0x800 +#define WPIAEN3 0x1000 +#define WPICNTEN2 0x2000 +#define WPICNTEN3 0x4000 +#define EMUSW2 0x8000 +#define EMUSW3 0x10000 +#define WPIREN45 0x20000 +#define WPIRINV45 0x40000 +#define WPIAEN4 0x80000 +#define WPIAEN5 0x100000 +#define WPICNTEN4 0x200000 +#define WPICNTEN5 0x400000 +#define EMUSW4 0x800000 +#define EMUSW5 0x1000000 +#define WPAND 0x2000000 + +/* Data watchpoint address control register bits mask */ +#define WPDREN01 0x1 +#define WPDRINV01 0x2 +#define WPDAEN0 0x4 +#define WPDAEN1 0x8 +#define WPDCNTEN0 0x10 +#define WPDCNTEN1 0x20 + +#define WPDSRC0 0xc0 +#define WPDACC0_OFFSET 8 +#define WPDSRC1 0xc00 +#define WPDACC1_OFFSET 12 + +/* Watchpoint status register bits mask */ +#define STATIA0 0x1 +#define STATIA1 0x2 +#define STATIA2 0x4 +#define STATIA3 0x8 +#define STATIA4 0x10 +#define STATIA5 0x20 +#define STATDA0 0x40 +#define STATDA1 0x80 + +#endif diff --git a/lib_blackfin/string.c b/lib_blackfin/string.c index 12b6d24..e344d3b 100644 --- a/lib_blackfin/string.c +++ b/lib_blackfin/string.c @@ -230,15 +230,45 @@ void *memcpy(void *dst, const void *src, size_t count) if (!count) return dst;
- if (addr_bfin_on_chip_mem(dst)) { - /* L1 is the destination */ - return dma_memcpy(dst, src, count); +#ifdef CONFIG_CMD_KGDB + if (src >= (void *)SYSMMR_BASE) { + if (count == 2 && (unsigned long)src % 2 == 0) { + u16 mmr = bfin_read16(src); + memcpy(dst, &mmr, sizeof(mmr)); + return dst; + } + if (count == 4 && (unsigned long)src % 4 == 0) { + u32 mmr = bfin_read32(src); + memcpy(dst, &mmr, sizeof(mmr)); + return dst; + } + /* Failed for some reason */ + memset(dst, 0xad, count); + return dst; + } + if (dst >= (void *)SYSMMR_BASE) { + if (count == 2 && (unsigned long)dst % 2 == 0) { + u16 mmr; + memcpy(&mmr, src, sizeof(mmr)); + bfin_write16(dst, mmr); + return dst; + } + if (count == 4 && (unsigned long)dst % 4 == 0) { + u32 mmr; + memcpy(&mmr, src, sizeof(mmr)); + bfin_write32(dst, mmr); + return dst; + } + /* Failed for some reason */ + memset(dst, 0xad, count); + return dst; + } +#endif
- } else if (addr_bfin_on_chip_mem(src)) { - /* L1 is the source */ + /* if L1 is the source or dst, use DMA */ + if (addr_bfin_on_chip_mem(dst) || addr_bfin_on_chip_mem(src)) return dma_memcpy(dst, src, count); - - } else + else /* No L1 is involved, so just call regular memcpy */ return memcpy_ASM(dst, src, count); }

Dear Mike Frysinger,
In message 1261438846-9675-1-git-send-email-vapier@gentoo.org you wrote:
I can take care of merging the Blackfin-specific KGDB piece through my tree since it depends on some other Blackfin patches. But all the KGDB common changes can be merged now.
Mike Frysinger (1): kgdb: drop duplicate debugger_exception_handler
Robin Getz (4): kgdb: add default generic stubs kgdb: update mem2hex/hex2mem funcs asm-generic/signal.h: import from linux Blackfin: add support for kgdb
I applied patches 1 through 3; can you please run 4 and 5 through the BF tree?
Best regards,
Wolfgang Denk

The following changes since commit 88ffb2665cd066b6b20cfaade13929d4e8428dde: Heiko Schocher (1): CRAMFS: support cramfs in RAM
are available in the git repository at:
git://www.denx.de/git/u-boot-blackfin.git master
Robin Getz (2): asm-generic/signal.h: import from linux Blackfin: add support for kgdb
cpu/blackfin/interrupt.S | 105 +++++++ cpu/blackfin/traps.c | 57 ++++- include/asm-blackfin/config.h | 7 + include/asm-blackfin/deferred.h | 20 ++ include/asm-blackfin/entry.h | 10 + include/asm-blackfin/mach-common/bits/core.h | 3 + include/asm-blackfin/signal.h | 1 + include/asm-generic/signal.h | 101 ++++++ include/configs/bfin_adi_common.h | 1 + lib_blackfin/Makefile | 2 + lib_blackfin/__kgdb.S | 155 ++++++++++ lib_blackfin/board.c | 6 + lib_blackfin/kgdb.c | 423 ++++++++++++++++++++++++++ lib_blackfin/kgdb.h | 160 ++++++++++ lib_blackfin/string.c | 44 +++- 15 files changed, 1083 insertions(+), 12 deletions(-) create mode 100644 include/asm-blackfin/deferred.h create mode 100644 include/asm-blackfin/signal.h create mode 100644 include/asm-generic/signal.h create mode 100644 lib_blackfin/__kgdb.S create mode 100644 lib_blackfin/kgdb.c create mode 100644 lib_blackfin/kgdb.h

Dear Mike Frysinger,
In message 1263778635-4003-1-git-send-email-vapier@gentoo.org you wrote:
The following changes since commit 88ffb2665cd066b6b20cfaade13929d4e8428dde: Heiko Schocher (1): CRAMFS: support cramfs in RAM
are available in the git repository at:
git://www.denx.de/git/u-boot-blackfin.git master
Robin Getz (2): asm-generic/signal.h: import from linux Blackfin: add support for kgdb
Applied, thanks.
Best regards,
Wolfgang Denk
participants (5)
-
Daniel Hellstrom
-
Detlev Zundel
-
K Balaji
-
Mike Frysinger
-
Wolfgang Denk