aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-04-29 05:38:50 -0400
committerDavid S. Miller <davem@davemloft.net>2008-04-29 05:38:50 -0400
commite2fdd7fd99dd68b77caaf2a2272b75b5da890de7 (patch)
treed2b6d3a9b50e4d2ced793430d2b1414f790666a3
parent4d7ffa49909a830f5f926a3280731d01e29f31fb (diff)
sparc: Add kgdb support.
Current limitations: 1) On SMP single stepping has some fundamental issues, shared with other sw single-step architectures such as mips and arm. 2) On 32-bit sparc we don't support SMP kgdb yet. That requires some reworking of the IPI mechanisms and infrastructure on that platform. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc/Kconfig1
-rw-r--r--arch/sparc/defconfig139
-rw-r--r--arch/sparc/kernel/Makefile1
-rw-r--r--arch/sparc/kernel/entry.S125
-rw-r--r--arch/sparc/kernel/head.S9
-rw-r--r--arch/sparc/kernel/kgdb.c164
-rw-r--r--arch/sparc/kernel/sparc-stub.c724
-rw-r--r--arch/sparc64/Kconfig1
-rw-r--r--arch/sparc64/kernel/Makefile1
-rw-r--r--arch/sparc64/kernel/kgdb.c186
-rw-r--r--arch/sparc64/kernel/misctrap.S10
-rw-r--r--arch/sparc64/kernel/smp.c10
-rw-r--r--arch/sparc64/kernel/ttable.S2
-rw-r--r--arch/sparc64/mm/ultra.S27
-rw-r--r--include/asm-sparc/head.h11
-rw-r--r--include/asm-sparc/kgdb.h116
-rw-r--r--include/asm-sparc/system.h2
-rw-r--r--include/asm-sparc64/kgdb.h1
-rw-r--r--include/asm-sparc64/system.h5
-rw-r--r--include/asm-sparc64/ttable.h6
20 files changed, 581 insertions, 960 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 49590f8fe98c..d211fdb24584 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -68,6 +68,7 @@ config SPARC
68 default y 68 default y
69 select HAVE_IDE 69 select HAVE_IDE
70 select HAVE_OPROFILE 70 select HAVE_OPROFILE
71 select HAVE_ARCH_KGDB if !SMP
71 72
72# Identify this as a Sparc32 build 73# Identify this as a Sparc32 build
73config SPARC32 74config SPARC32
diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig
index 6a2c57a2fe71..2e3a149ea0e7 100644
--- a/arch/sparc/defconfig
+++ b/arch/sparc/defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.25 3# Linux kernel version: 2.6.25
4# Sun Apr 20 01:49:51 2008 4# Tue Apr 29 01:28:58 2008
5# 5#
6CONFIG_MMU=y 6CONFIG_MMU=y
7CONFIG_HIGHMEM=y 7CONFIG_HIGHMEM=y
@@ -217,12 +217,7 @@ CONFIG_IPV6_TUNNEL=m
217# CONFIG_NETWORK_SECMARK is not set 217# CONFIG_NETWORK_SECMARK is not set
218# CONFIG_NETFILTER is not set 218# CONFIG_NETFILTER is not set
219# CONFIG_IP_DCCP is not set 219# CONFIG_IP_DCCP is not set
220CONFIG_IP_SCTP=m 220# CONFIG_IP_SCTP is not set
221# CONFIG_SCTP_DBG_MSG is not set
222CONFIG_SCTP_DBG_OBJCNT=y
223# CONFIG_SCTP_HMAC_NONE is not set
224# CONFIG_SCTP_HMAC_SHA1 is not set
225CONFIG_SCTP_HMAC_MD5=y
226# CONFIG_TIPC is not set 221# CONFIG_TIPC is not set
227# CONFIG_ATM is not set 222# CONFIG_ATM is not set
228# CONFIG_BRIDGE is not set 223# CONFIG_BRIDGE is not set
@@ -245,9 +240,7 @@ CONFIG_NET_PKTGEN=m
245# CONFIG_CAN is not set 240# CONFIG_CAN is not set
246# CONFIG_IRDA is not set 241# CONFIG_IRDA is not set
247# CONFIG_BT is not set 242# CONFIG_BT is not set
248CONFIG_AF_RXRPC=m 243# CONFIG_AF_RXRPC is not set
249# CONFIG_AF_RXRPC_DEBUG is not set
250# CONFIG_RXKAD is not set
251 244
252# 245#
253# Wireless 246# Wireless
@@ -390,7 +383,7 @@ CONFIG_DUMMY=m
390# CONFIG_BONDING is not set 383# CONFIG_BONDING is not set
391# CONFIG_MACVLAN is not set 384# CONFIG_MACVLAN is not set
392# CONFIG_EQUALIZER is not set 385# CONFIG_EQUALIZER is not set
393CONFIG_TUN=m 386# CONFIG_TUN is not set
394# CONFIG_VETH is not set 387# CONFIG_VETH is not set
395# CONFIG_ARCNET is not set 388# CONFIG_ARCNET is not set
396# CONFIG_PHYLIB is not set 389# CONFIG_PHYLIB is not set
@@ -544,6 +537,7 @@ CONFIG_SERIAL_SUNSU_CONSOLE=y
544# CONFIG_SERIAL_SUNSAB is not set 537# CONFIG_SERIAL_SUNSAB is not set
545CONFIG_SERIAL_CORE=y 538CONFIG_SERIAL_CORE=y
546CONFIG_SERIAL_CORE_CONSOLE=y 539CONFIG_SERIAL_CORE_CONSOLE=y
540CONFIG_CONSOLE_POLL=y
547# CONFIG_SERIAL_JSM is not set 541# CONFIG_SERIAL_JSM is not set
548CONFIG_UNIX98_PTYS=y 542CONFIG_UNIX98_PTYS=y
549CONFIG_LEGACY_PTYS=y 543CONFIG_LEGACY_PTYS=y
@@ -595,6 +589,7 @@ CONFIG_SSB_POSSIBLE=y
595# Multifunction device drivers 589# Multifunction device drivers
596# 590#
597# CONFIG_MFD_SM501 is not set 591# CONFIG_MFD_SM501 is not set
592# CONFIG_HTC_PASIC3 is not set
598 593
599# 594#
600# Multimedia devices 595# Multimedia devices
@@ -645,10 +640,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
645# CONFIG_NEW_LEDS is not set 640# CONFIG_NEW_LEDS is not set
646# CONFIG_INFINIBAND is not set 641# CONFIG_INFINIBAND is not set
647# CONFIG_RTC_CLASS is not set 642# CONFIG_RTC_CLASS is not set
648
649#
650# Userspace I/O
651#
652# CONFIG_UIO is not set 643# CONFIG_UIO is not set
653 644
654# 645#
@@ -680,16 +671,12 @@ CONFIG_FS_MBCACHE=y
680# CONFIG_REISERFS_FS is not set 671# CONFIG_REISERFS_FS is not set
681# CONFIG_JFS_FS is not set 672# CONFIG_JFS_FS is not set
682CONFIG_FS_POSIX_ACL=y 673CONFIG_FS_POSIX_ACL=y
683CONFIG_XFS_FS=m 674# CONFIG_XFS_FS is not set
684CONFIG_XFS_QUOTA=y
685CONFIG_XFS_POSIX_ACL=y
686CONFIG_XFS_RT=y
687# CONFIG_OCFS2_FS is not set 675# CONFIG_OCFS2_FS is not set
688CONFIG_DNOTIFY=y 676CONFIG_DNOTIFY=y
689CONFIG_INOTIFY=y 677CONFIG_INOTIFY=y
690CONFIG_INOTIFY_USER=y 678CONFIG_INOTIFY_USER=y
691# CONFIG_QUOTA is not set 679# CONFIG_QUOTA is not set
692CONFIG_QUOTACTL=y
693CONFIG_AUTOFS_FS=m 680CONFIG_AUTOFS_FS=m
694CONFIG_AUTOFS4_FS=m 681CONFIG_AUTOFS4_FS=m
695# CONFIG_FUSE_FS is not set 682# CONFIG_FUSE_FS is not set
@@ -725,11 +712,9 @@ CONFIG_SYSFS=y
725# 712#
726# CONFIG_ADFS_FS is not set 713# CONFIG_ADFS_FS is not set
727# CONFIG_AFFS_FS is not set 714# CONFIG_AFFS_FS is not set
728# CONFIG_ECRYPT_FS is not set
729# CONFIG_HFS_FS is not set 715# CONFIG_HFS_FS is not set
730# CONFIG_HFSPLUS_FS is not set 716# CONFIG_HFSPLUS_FS is not set
731CONFIG_BEFS_FS=m 717# CONFIG_BEFS_FS is not set
732# CONFIG_BEFS_DEBUG is not set
733# CONFIG_BFS_FS is not set 718# CONFIG_BFS_FS is not set
734# CONFIG_EFS_FS is not set 719# CONFIG_EFS_FS is not set
735# CONFIG_CRAMFS is not set 720# CONFIG_CRAMFS is not set
@@ -744,7 +729,6 @@ CONFIG_NETWORK_FILESYSTEMS=y
744CONFIG_NFS_FS=y 729CONFIG_NFS_FS=y
745# CONFIG_NFS_V3 is not set 730# CONFIG_NFS_V3 is not set
746# CONFIG_NFS_V4 is not set 731# CONFIG_NFS_V4 is not set
747# CONFIG_NFS_DIRECTIO is not set
748# CONFIG_NFSD is not set 732# CONFIG_NFSD is not set
749CONFIG_ROOT_NFS=y 733CONFIG_ROOT_NFS=y
750CONFIG_LOCKD=y 734CONFIG_LOCKD=y
@@ -755,16 +739,10 @@ CONFIG_SUNRPC_GSS=m
755CONFIG_RPCSEC_GSS_KRB5=m 739CONFIG_RPCSEC_GSS_KRB5=m
756# CONFIG_RPCSEC_GSS_SPKM3 is not set 740# CONFIG_RPCSEC_GSS_SPKM3 is not set
757# CONFIG_SMB_FS is not set 741# CONFIG_SMB_FS is not set
758CONFIG_CIFS=m 742# CONFIG_CIFS is not set
759# CONFIG_CIFS_STATS is not set
760# CONFIG_CIFS_WEAK_PW_HASH is not set
761# CONFIG_CIFS_XATTR is not set
762# CONFIG_CIFS_DEBUG2 is not set
763# CONFIG_CIFS_EXPERIMENTAL is not set
764# CONFIG_NCP_FS is not set 743# CONFIG_NCP_FS is not set
765# CONFIG_CODA_FS is not set 744# CONFIG_CODA_FS is not set
766CONFIG_AFS_FS=m 745# CONFIG_AFS_FS is not set
767# CONFIG_AFS_DEBUG is not set
768 746
769# 747#
770# Partition Types 748# Partition Types
@@ -821,6 +799,7 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
821# CONFIG_PRINTK_TIME is not set 799# CONFIG_PRINTK_TIME is not set
822# CONFIG_ENABLE_WARN_DEPRECATED is not set 800# CONFIG_ENABLE_WARN_DEPRECATED is not set
823CONFIG_ENABLE_MUST_CHECK=y 801CONFIG_ENABLE_MUST_CHECK=y
802CONFIG_FRAME_WARN=1024
824CONFIG_MAGIC_SYSRQ=y 803CONFIG_MAGIC_SYSRQ=y
825# CONFIG_UNUSED_SYMBOLS is not set 804# CONFIG_UNUSED_SYMBOLS is not set
826# CONFIG_DEBUG_FS is not set 805# CONFIG_DEBUG_FS is not set
@@ -842,70 +821,105 @@ CONFIG_DETECT_SOFTLOCKUP=y
842CONFIG_DEBUG_BUGVERBOSE=y 821CONFIG_DEBUG_BUGVERBOSE=y
843# CONFIG_DEBUG_INFO is not set 822# CONFIG_DEBUG_INFO is not set
844# CONFIG_DEBUG_VM is not set 823# CONFIG_DEBUG_VM is not set
824# CONFIG_DEBUG_WRITECOUNT is not set
845# CONFIG_DEBUG_LIST is not set 825# CONFIG_DEBUG_LIST is not set
846# CONFIG_DEBUG_SG is not set 826# CONFIG_DEBUG_SG is not set
827CONFIG_FRAME_POINTER=y
847# CONFIG_BOOT_PRINTK_DELAY is not set 828# CONFIG_BOOT_PRINTK_DELAY is not set
848# CONFIG_RCU_TORTURE_TEST is not set 829# CONFIG_RCU_TORTURE_TEST is not set
849# CONFIG_BACKTRACE_SELF_TEST is not set 830# CONFIG_BACKTRACE_SELF_TEST is not set
850# CONFIG_FAULT_INJECTION is not set 831# CONFIG_FAULT_INJECTION is not set
851# CONFIG_SAMPLES is not set 832# CONFIG_SAMPLES is not set
833CONFIG_KGDB=y
834CONFIG_HAVE_ARCH_KGDB=y
835CONFIG_KGDB_SERIAL_CONSOLE=y
836CONFIG_KGDB_TESTS=y
837# CONFIG_KGDB_TESTS_ON_BOOT is not set
852# CONFIG_DEBUG_STACK_USAGE is not set 838# CONFIG_DEBUG_STACK_USAGE is not set
853 839
854# 840#
855# Security options 841# Security options
856# 842#
857CONFIG_KEYS=y 843# CONFIG_KEYS is not set
858# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
859# CONFIG_SECURITY is not set 844# CONFIG_SECURITY is not set
860# CONFIG_SECURITY_FILE_CAPABILITIES is not set 845# CONFIG_SECURITY_FILE_CAPABILITIES is not set
861CONFIG_CRYPTO=y 846CONFIG_CRYPTO=y
847
848#
849# Crypto core or helper
850#
862CONFIG_CRYPTO_ALGAPI=y 851CONFIG_CRYPTO_ALGAPI=y
863CONFIG_CRYPTO_AEAD=y 852CONFIG_CRYPTO_AEAD=y
864CONFIG_CRYPTO_BLKCIPHER=y 853CONFIG_CRYPTO_BLKCIPHER=y
865# CONFIG_CRYPTO_SEQIV is not set
866CONFIG_CRYPTO_HASH=y 854CONFIG_CRYPTO_HASH=y
867CONFIG_CRYPTO_MANAGER=y 855CONFIG_CRYPTO_MANAGER=y
856# CONFIG_CRYPTO_GF128MUL is not set
857CONFIG_CRYPTO_NULL=m
858# CONFIG_CRYPTO_CRYPTD is not set
859CONFIG_CRYPTO_AUTHENC=y
860# CONFIG_CRYPTO_TEST is not set
861
862#
863# Authenticated Encryption with Associated Data
864#
865# CONFIG_CRYPTO_CCM is not set
866# CONFIG_CRYPTO_GCM is not set
867# CONFIG_CRYPTO_SEQIV is not set
868
869#
870# Block modes
871#
872CONFIG_CRYPTO_CBC=y
873# CONFIG_CRYPTO_CTR is not set
874# CONFIG_CRYPTO_CTS is not set
875CONFIG_CRYPTO_ECB=m
876# CONFIG_CRYPTO_LRW is not set
877CONFIG_CRYPTO_PCBC=m
878# CONFIG_CRYPTO_XTS is not set
879
880#
881# Hash modes
882#
868CONFIG_CRYPTO_HMAC=y 883CONFIG_CRYPTO_HMAC=y
869# CONFIG_CRYPTO_XCBC is not set 884# CONFIG_CRYPTO_XCBC is not set
870CONFIG_CRYPTO_NULL=m 885
886#
887# Digest
888#
889CONFIG_CRYPTO_CRC32C=m
871CONFIG_CRYPTO_MD4=y 890CONFIG_CRYPTO_MD4=y
872CONFIG_CRYPTO_MD5=y 891CONFIG_CRYPTO_MD5=y
892CONFIG_CRYPTO_MICHAEL_MIC=m
873CONFIG_CRYPTO_SHA1=y 893CONFIG_CRYPTO_SHA1=y
874CONFIG_CRYPTO_SHA256=m 894CONFIG_CRYPTO_SHA256=m
875CONFIG_CRYPTO_SHA512=m 895CONFIG_CRYPTO_SHA512=m
876# CONFIG_CRYPTO_WP512 is not set
877# CONFIG_CRYPTO_TGR192 is not set 896# CONFIG_CRYPTO_TGR192 is not set
878# CONFIG_CRYPTO_GF128MUL is not set 897# CONFIG_CRYPTO_WP512 is not set
879CONFIG_CRYPTO_ECB=m 898
880CONFIG_CRYPTO_CBC=y 899#
881CONFIG_CRYPTO_PCBC=m 900# Ciphers
882# CONFIG_CRYPTO_LRW is not set 901#
883# CONFIG_CRYPTO_XTS is not set
884# CONFIG_CRYPTO_CTR is not set
885# CONFIG_CRYPTO_GCM is not set
886# CONFIG_CRYPTO_CCM is not set
887# CONFIG_CRYPTO_CRYPTD is not set
888CONFIG_CRYPTO_DES=y
889# CONFIG_CRYPTO_FCRYPT is not set
890CONFIG_CRYPTO_BLOWFISH=m
891CONFIG_CRYPTO_TWOFISH=m
892CONFIG_CRYPTO_TWOFISH_COMMON=m
893CONFIG_CRYPTO_SERPENT=m
894CONFIG_CRYPTO_AES=m 902CONFIG_CRYPTO_AES=m
903# CONFIG_CRYPTO_ANUBIS is not set
904CONFIG_CRYPTO_ARC4=m
905CONFIG_CRYPTO_BLOWFISH=m
906# CONFIG_CRYPTO_CAMELLIA is not set
895CONFIG_CRYPTO_CAST5=m 907CONFIG_CRYPTO_CAST5=m
896CONFIG_CRYPTO_CAST6=m 908CONFIG_CRYPTO_CAST6=m
897# CONFIG_CRYPTO_TEA is not set 909CONFIG_CRYPTO_DES=y
898CONFIG_CRYPTO_ARC4=m 910# CONFIG_CRYPTO_FCRYPT is not set
899# CONFIG_CRYPTO_KHAZAD is not set 911# CONFIG_CRYPTO_KHAZAD is not set
900# CONFIG_CRYPTO_ANUBIS is not set
901# CONFIG_CRYPTO_SEED is not set
902# CONFIG_CRYPTO_SALSA20 is not set 912# CONFIG_CRYPTO_SALSA20 is not set
913# CONFIG_CRYPTO_SEED is not set
914CONFIG_CRYPTO_SERPENT=m
915# CONFIG_CRYPTO_TEA is not set
916CONFIG_CRYPTO_TWOFISH=m
917CONFIG_CRYPTO_TWOFISH_COMMON=m
918
919#
920# Compression
921#
903CONFIG_CRYPTO_DEFLATE=y 922CONFIG_CRYPTO_DEFLATE=y
904CONFIG_CRYPTO_MICHAEL_MIC=m
905CONFIG_CRYPTO_CRC32C=m
906# CONFIG_CRYPTO_CAMELLIA is not set
907# CONFIG_CRYPTO_TEST is not set
908CONFIG_CRYPTO_AUTHENC=y
909# CONFIG_CRYPTO_LZO is not set 923# CONFIG_CRYPTO_LZO is not set
910# CONFIG_CRYPTO_HW is not set 924# CONFIG_CRYPTO_HW is not set
911 925
@@ -913,6 +927,7 @@ CONFIG_CRYPTO_AUTHENC=y
913# Library routines 927# Library routines
914# 928#
915CONFIG_BITREVERSE=y 929CONFIG_BITREVERSE=y
930# CONFIG_GENERIC_FIND_FIRST_BIT is not set
916# CONFIG_CRC_CCITT is not set 931# CONFIG_CRC_CCITT is not set
917# CONFIG_CRC16 is not set 932# CONFIG_CRC16 is not set
918# CONFIG_CRC_ITU_T is not set 933# CONFIG_CRC_ITU_T is not set
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 59700aaaae93..6e03a2a7863c 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_PCI) += ebus.o
25obj-$(CONFIG_SUN_PM) += apc.o pmc.o 25obj-$(CONFIG_SUN_PM) += apc.o pmc.o
26obj-$(CONFIG_MODULES) += module.o sparc_ksyms.o 26obj-$(CONFIG_MODULES) += module.o sparc_ksyms.o
27obj-$(CONFIG_SPARC_LED) += led.o 27obj-$(CONFIG_SPARC_LED) += led.o
28obj-$(CONFIG_KGDB) += kgdb.o
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index 484c83d23eef..57d1bbdd0bd2 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -12,7 +12,6 @@
12#include <asm/head.h> 12#include <asm/head.h>
13#include <asm/asi.h> 13#include <asm/asi.h>
14#include <asm/smp.h> 14#include <asm/smp.h>
15#include <asm/kgdb.h>
16#include <asm/contregs.h> 15#include <asm/contregs.h>
17#include <asm/ptrace.h> 16#include <asm/ptrace.h>
18#include <asm/asm-offsets.h> 17#include <asm/asm-offsets.h>
@@ -45,91 +44,20 @@
45 _SV; _SV; _SV; _SV; _SV; _SV; _SV; \ 44 _SV; _SV; _SV; _SV; _SV; _SV; _SV; \
46 _RS; _RS; _RS; _RS; _RS; _RS; _RS; 45 _RS; _RS; _RS; _RS; _RS; _RS; _RS;
47 46
48/* First, KGDB low level things. This is a rewrite
49 * of the routines found in the sparc-stub.c asm() statement
50 * from the gdb distribution. This is also dual-purpose
51 * as a software trap for userlevel programs.
52 */
53 .data
54 .align 4
55
56in_trap_handler:
57 .word 0
58
59 .text 47 .text
60 .align 4
61 48
62#if 0 /* kgdb is dropped from 2.5.33 */ 49#ifdef CONFIG_KGDB
63! This function is called when any SPARC trap (except window overflow or 50 .align 4
64! underflow) occurs. It makes sure that the invalid register window is still 51 .globl arch_kgdb_breakpoint
65! available before jumping into C code. It will also restore the world if you 52 .type arch_kgdb_breakpoint,#function
66! return from handle_exception. 53arch_kgdb_breakpoint:
67 54 ta 0x7d
68 .globl trap_low 55 retl
69trap_low: 56 nop
70 rd %wim, %l3 57 .size arch_kgdb_breakpoint,.-arch_kgdb_breakpoint
71 SAVE_ALL
72
73 sethi %hi(in_trap_handler), %l4
74 ld [%lo(in_trap_handler) + %l4], %l5
75 inc %l5
76 st %l5, [%lo(in_trap_handler) + %l4]
77
78 /* Make sure kgdb sees the same state we just saved. */
79 LOAD_PT_GLOBALS(sp)
80 LOAD_PT_INS(sp)
81 ld [%sp + STACKFRAME_SZ + PT_Y], %l4
82 ld [%sp + STACKFRAME_SZ + PT_WIM], %l3
83 ld [%sp + STACKFRAME_SZ + PT_PSR], %l0
84 ld [%sp + STACKFRAME_SZ + PT_PC], %l1
85 ld [%sp + STACKFRAME_SZ + PT_NPC], %l2
86 rd %tbr, %l5 /* Never changes... */
87
88 /* Make kgdb exception frame. */
89 sub %sp,(16+1+6+1+72)*4,%sp ! Make room for input & locals
90 ! + hidden arg + arg spill
91 ! + doubleword alignment
92 ! + registers[72] local var
93 SAVE_KGDB_GLOBALS(sp)
94 SAVE_KGDB_INS(sp)
95 SAVE_KGDB_SREGS(sp, l4, l0, l3, l5, l1, l2)
96
97 /* We are increasing PIL, so two writes. */
98 or %l0, PSR_PIL, %l0
99 wr %l0, 0, %psr
100 WRITE_PAUSE
101 wr %l0, PSR_ET, %psr
102 WRITE_PAUSE
103
104 call handle_exception
105 add %sp, STACKFRAME_SZ, %o0 ! Pass address of registers
106
107 /* Load new kgdb register set. */
108 LOAD_KGDB_GLOBALS(sp)
109 LOAD_KGDB_INS(sp)
110 LOAD_KGDB_SREGS(sp, l4, l0, l3, l5, l1, l2)
111 wr %l4, 0x0, %y
112
113 sethi %hi(in_trap_handler), %l4
114 ld [%lo(in_trap_handler) + %l4], %l5
115 dec %l5
116 st %l5, [%lo(in_trap_handler) + %l4]
117
118 add %sp,(16+1+6+1+72)*4,%sp ! Undo the kgdb trap frame.
119
120 /* Now take what kgdb did and place it into the pt_regs
121 * frame which SparcLinux RESTORE_ALL understands.,
122 */
123 STORE_PT_INS(sp)
124 STORE_PT_GLOBALS(sp)
125 STORE_PT_YREG(sp, g2)
126 STORE_PT_PRIV(sp, l0, l1, l2)
127
128 RESTORE_ALL
129#endif 58#endif
130 59
131#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE) 60#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
132 .text
133 .align 4 61 .align 4
134 .globl floppy_hardint 62 .globl floppy_hardint
135floppy_hardint: 63floppy_hardint:
@@ -1596,6 +1524,23 @@ breakpoint_trap:
1596 1524
1597 RESTORE_ALL 1525 RESTORE_ALL
1598 1526
1527#ifdef CONFIG_KGDB
1528 .align 4
1529 .globl kgdb_trap_low
1530 .type kgdb_trap_low,#function
1531kgdb_trap_low:
1532 rd %wim,%l3
1533 SAVE_ALL
1534 wr %l0, PSR_ET, %psr
1535 WRITE_PAUSE
1536
1537 call kgdb_trap
1538 add %sp, STACKFRAME_SZ, %o0
1539
1540 RESTORE_ALL
1541 .size kgdb_trap_low,.-kgdb_trap_low
1542#endif
1543
1599 .align 4 1544 .align 4
1600 .globl __handle_exception, flush_patch_exception 1545 .globl __handle_exception, flush_patch_exception
1601__handle_exception: 1546__handle_exception:
@@ -1698,4 +1643,22 @@ pcic_nmi_trap_patch:
1698 1643
1699#endif /* CONFIG_PCI */ 1644#endif /* CONFIG_PCI */
1700 1645
1646 .globl flushw_all
1647flushw_all:
1648 save %sp, -0x40, %sp
1649 save %sp, -0x40, %sp
1650 save %sp, -0x40, %sp
1651 save %sp, -0x40, %sp
1652 save %sp, -0x40, %sp
1653 save %sp, -0x40, %sp
1654 save %sp, -0x40, %sp
1655 restore
1656 restore
1657 restore
1658 restore
1659 restore
1660 restore
1661 ret
1662 restore
1663
1701/* End of entry.S */ 1664/* End of entry.S */
diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S
index b7f1e81c8ff2..8bec05fa5795 100644
--- a/arch/sparc/kernel/head.S
+++ b/arch/sparc/kernel/head.S
@@ -191,7 +191,8 @@ t_bade8:BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xe
191t_baded:BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1) 191t_baded:BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
192t_badf2:BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6) 192t_badf2:BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
193t_badf7:BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb) 193t_badf7:BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
194t_badfc:BAD_TRAP(0xfc) BAD_TRAP(0xfd) 194t_badfc:BAD_TRAP(0xfc)
195t_kgdb: KGDB_TRAP(0xfd)
195dbtrap: BAD_TRAP(0xfe) /* Debugger/PROM breakpoint #1 */ 196dbtrap: BAD_TRAP(0xfe) /* Debugger/PROM breakpoint #1 */
196dbtrap2:BAD_TRAP(0xff) /* Debugger/PROM breakpoint #2 */ 197dbtrap2:BAD_TRAP(0xff) /* Debugger/PROM breakpoint #2 */
197 198
@@ -267,7 +268,7 @@ trapbase_cpu1:
267 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1) 268 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
268 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6) 269 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
269 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb) 270 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
270 BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff) 271 BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
271 272
272trapbase_cpu2: 273trapbase_cpu2:
273 BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction) 274 BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
@@ -335,7 +336,7 @@ trapbase_cpu2:
335 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1) 336 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
336 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6) 337 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
337 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb) 338 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
338 BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff) 339 BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
339 340
340trapbase_cpu3: 341trapbase_cpu3:
341 BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction) 342 BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
@@ -403,7 +404,7 @@ trapbase_cpu3:
403 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1) 404 BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
404 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6) 405 BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
405 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb) 406 BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
406 BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff) 407 BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
407 408
408#endif 409#endif
409 .align PAGE_SIZE 410 .align PAGE_SIZE
diff --git a/arch/sparc/kernel/kgdb.c b/arch/sparc/kernel/kgdb.c
new file mode 100644
index 000000000000..757805ce02ee
--- /dev/null
+++ b/arch/sparc/kernel/kgdb.c
@@ -0,0 +1,164 @@
1/* kgdb.c: KGDB support for 32-bit sparc.
2 *
3 * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
4 */
5
6#include <linux/kgdb.h>
7#include <linux/kdebug.h>
8
9#include <asm/kdebug.h>
10#include <asm/ptrace.h>
11#include <asm/irq.h>
12
13extern unsigned long trapbase;
14
15void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
16{
17 struct reg_window *win;
18 int i;
19
20 gdb_regs[GDB_G0] = 0;
21 for (i = 0; i < 15; i++)
22 gdb_regs[GDB_G1 + i] = regs->u_regs[UREG_G1 + i];
23
24 win = (struct reg_window *) regs->u_regs[UREG_FP];
25 for (i = 0; i < 8; i++)
26 gdb_regs[GDB_L0 + i] = win->locals[i];
27 for (i = 0; i < 8; i++)
28 gdb_regs[GDB_I0 + i] = win->ins[i];
29
30 for (i = GDB_F0; i <= GDB_F31; i++)
31 gdb_regs[i] = 0;
32
33 gdb_regs[GDB_Y] = regs->y;
34 gdb_regs[GDB_PSR] = regs->psr;
35 gdb_regs[GDB_WIM] = 0;
36 gdb_regs[GDB_TBR] = (unsigned long) &trapbase;
37 gdb_regs[GDB_PC] = regs->pc;
38 gdb_regs[GDB_NPC] = regs->npc;
39 gdb_regs[GDB_FSR] = 0;
40 gdb_regs[GDB_CSR] = 0;
41}
42
43void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
44{
45 struct thread_info *t = task_thread_info(p);
46 struct reg_window *win;
47 int i;
48
49 for (i = GDB_G0; i < GDB_G6; i++)
50 gdb_regs[i] = 0;
51 gdb_regs[GDB_G6] = (unsigned long) t;
52 gdb_regs[GDB_G7] = 0;
53 for (i = GDB_O0; i < GDB_SP; i++)
54 gdb_regs[i] = 0;
55 gdb_regs[GDB_SP] = t->ksp;
56 gdb_regs[GDB_O7] = 0;
57
58 win = (struct reg_window *) t->ksp;
59 for (i = 0; i < 8; i++)
60 gdb_regs[GDB_L0 + i] = win->locals[i];
61 for (i = 0; i < 8; i++)
62 gdb_regs[GDB_I0 + i] = win->ins[i];
63
64 for (i = GDB_F0; i <= GDB_F31; i++)
65 gdb_regs[i] = 0;
66
67 gdb_regs[GDB_Y] = 0;
68
69 gdb_regs[GDB_PSR] = t->kpsr;
70 gdb_regs[GDB_WIM] = t->kwim;
71 gdb_regs[GDB_TBR] = (unsigned long) &trapbase;
72 gdb_regs[GDB_PC] = t->kpc;
73 gdb_regs[GDB_NPC] = t->kpc + 4;
74 gdb_regs[GDB_FSR] = 0;
75 gdb_regs[GDB_CSR] = 0;
76}
77
78void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
79{
80 struct reg_window *win;
81 int i;
82
83 for (i = 0; i < 15; i++)
84 regs->u_regs[UREG_G1 + i] = gdb_regs[GDB_G1 + i];
85
86 /* If the PSR register is changing, we have to preserve
87 * the CWP field, otherwise window save/restore explodes.
88 */
89 if (regs->psr != gdb_regs[GDB_PSR]) {
90 unsigned long cwp = regs->psr & PSR_CWP;
91
92 regs->psr = (gdb_regs[GDB_PSR] & ~PSR_CWP) | cwp;
93 }
94
95 regs->pc = gdb_regs[GDB_PC];
96 regs->npc = gdb_regs[GDB_NPC];
97 regs->y = gdb_regs[GDB_Y];
98
99 win = (struct reg_window *) regs->u_regs[UREG_FP];
100 for (i = 0; i < 8; i++)
101 win->locals[i] = gdb_regs[GDB_L0 + i];
102 for (i = 0; i < 8; i++)
103 win->ins[i] = gdb_regs[GDB_I0 + i];
104}
105
106int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
107 char *remcomInBuffer, char *remcomOutBuffer,
108 struct pt_regs *linux_regs)
109{
110 unsigned long addr;
111 char *ptr;
112
113 switch (remcomInBuffer[0]) {
114 case 'c':
115 /* try to read optional parameter, pc unchanged if no parm */
116 ptr = &remcomInBuffer[1];
117 if (kgdb_hex2long(&ptr, &addr)) {
118 linux_regs->pc = addr;
119 linux_regs->npc = addr + 4;
120 }
121 /* fallthru */
122
123 case 'D':
124 case 'k':
125 if (linux_regs->pc == (unsigned long) arch_kgdb_breakpoint) {
126 linux_regs->pc = linux_regs->npc;
127 linux_regs->npc += 4;
128 }
129 return 0;
130 }
131 return -1;
132}
133
134extern void do_hw_interrupt(struct pt_regs *regs, unsigned long type);
135
136asmlinkage void kgdb_trap(struct pt_regs *regs)
137{
138 unsigned long flags;
139
140 if (user_mode(regs)) {
141 do_hw_interrupt(regs, 0xfd);
142 return;
143 }
144
145 flushw_all();
146
147 local_irq_save(flags);
148 kgdb_handle_exception(0x172, SIGTRAP, 0, regs);
149 local_irq_restore(flags);
150}
151
152int kgdb_arch_init(void)
153{
154 return 0;
155}
156
157void kgdb_arch_exit(void)
158{
159}
160
161struct kgdb_arch arch_kgdb_ops = {
162 /* Breakpoint instruction: ta 0x7d */
163 .gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x7d },
164};
diff --git a/arch/sparc/kernel/sparc-stub.c b/arch/sparc/kernel/sparc-stub.c
deleted file mode 100644
index e84f815e6903..000000000000
--- a/arch/sparc/kernel/sparc-stub.c
+++ /dev/null
@@ -1,724 +0,0 @@
1/* $Id: sparc-stub.c,v 1.28 2001/10/30 04:54:21 davem Exp $
2 * sparc-stub.c: KGDB support for the Linux kernel.
3 *
4 * Modifications to run under Linux
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 *
7 * This file originally came from the gdb sources, and the
8 * copyright notices have been retained below.
9 */
10
11/****************************************************************************
12
13 THIS SOFTWARE IS NOT COPYRIGHTED
14
15 HP offers the following for use in the public domain. HP makes no
16 warranty with regard to the software or its performance and the
17 user accepts the software "AS IS" with all faults.
18
19 HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
20 TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22
23****************************************************************************/
24
25/****************************************************************************
26 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
27 *
28 * Module name: remcom.c $
29 * Revision: 1.34 $
30 * Date: 91/03/09 12:29:49 $
31 * Contributor: Lake Stevens Instrument Division$
32 *
33 * Description: low level support for gdb debugger. $
34 *
35 * Considerations: only works on target hardware $
36 *
37 * Written by: Glenn Engel $
38 * ModuleState: Experimental $
39 *
40 * NOTES: See Below $
41 *
42 * Modified for SPARC by Stu Grossman, Cygnus Support.
43 *
44 * This code has been extensively tested on the Fujitsu SPARClite demo board.
45 *
46 * To enable debugger support, two things need to happen. One, a
47 * call to set_debug_traps() is necessary in order to allow any breakpoints
48 * or error conditions to be properly intercepted and reported to gdb.
49 * Two, a breakpoint needs to be generated to begin communication. This
50 * is most easily accomplished by a call to breakpoint(). Breakpoint()
51 * simulates a breakpoint by executing a trap #1.
52 *
53 *************
54 *
55 * The following gdb commands are supported:
56 *
57 * command function Return value
58 *
59 * g return the value of the CPU registers hex data or ENN
60 * G set the value of the CPU registers OK or ENN
61 *
62 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
63 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
64 *
65 * c Resume at current address SNN ( signal NN)
66 * cAA..AA Continue at address AA..AA SNN
67 *
68 * s Step one instruction SNN
69 * sAA..AA Step one instruction from AA..AA SNN
70 *
71 * k kill
72 *
73 * ? What was the last sigval ? SNN (signal NN)
74 *
75 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
76 * baud rate
77 *
78 * All commands and responses are sent with a packet which includes a
79 * checksum. A packet consists of
80 *
81 * $<packet info>#<checksum>.
82 *
83 * where
84 * <packet info> :: <characters representing the command or response>
85 * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
86 *
87 * When a packet is received, it is first acknowledged with either '+' or '-'.
88 * '+' indicates a successful transfer. '-' indicates a failed transfer.
89 *
90 * Example:
91 *
92 * Host: Reply:
93 * $m0,10#2a +$00010203040506070809101112131415#42
94 *
95 ****************************************************************************/
96
97#include <linux/kernel.h>
98#include <linux/string.h>
99#include <linux/mm.h>
100#include <linux/smp.h>
101#include <linux/smp_lock.h>
102
103#include <asm/system.h>
104#include <asm/signal.h>
105#include <asm/oplib.h>
106#include <asm/head.h>
107#include <asm/traps.h>
108#include <asm/vac-ops.h>
109#include <asm/kgdb.h>
110#include <asm/pgalloc.h>
111#include <asm/pgtable.h>
112#include <asm/cacheflush.h>
113
114/*
115 *
116 * external low-level support routines
117 */
118
119extern void putDebugChar(char); /* write a single character */
120extern char getDebugChar(void); /* read and return a single char */
121
122/*
123 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
124 * at least NUMREGBYTES*2 are needed for register packets
125 */
126#define BUFMAX 2048
127
128static int initialized; /* !0 means we've been initialized */
129
130static const char hexchars[]="0123456789abcdef";
131
132#define NUMREGS 72
133
134/* Number of bytes of registers. */
135#define NUMREGBYTES (NUMREGS * 4)
136enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
137 O0, O1, O2, O3, O4, O5, SP, O7,
138 L0, L1, L2, L3, L4, L5, L6, L7,
139 I0, I1, I2, I3, I4, I5, FP, I7,
140
141 F0, F1, F2, F3, F4, F5, F6, F7,
142 F8, F9, F10, F11, F12, F13, F14, F15,
143 F16, F17, F18, F19, F20, F21, F22, F23,
144 F24, F25, F26, F27, F28, F29, F30, F31,
145 Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR };
146
147
148extern void trap_low(void); /* In arch/sparc/kernel/entry.S */
149
150unsigned long get_sun4cpte(unsigned long addr)
151{
152 unsigned long entry;
153
154 __asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" :
155 "=r" (entry) :
156 "r" (addr), "i" (ASI_PTE));
157 return entry;
158}
159
160unsigned long get_sun4csegmap(unsigned long addr)
161{
162 unsigned long entry;
163
164 __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" :
165 "=r" (entry) :
166 "r" (addr), "i" (ASI_SEGMAP));
167 return entry;
168}
169
170#if 0
171/* Have to sort this out. This cannot be done after initialization. */
172static void flush_cache_all_nop(void) {}
173#endif
174
175/* Place where we save old trap entries for restoration */
176struct tt_entry kgdb_savettable[256];
177typedef void (*trapfunc_t)(void);
178
179/* Helper routine for manipulation of kgdb_savettable */
180static inline void copy_ttentry(struct tt_entry *src, struct tt_entry *dest)
181{
182 dest->inst_one = src->inst_one;
183 dest->inst_two = src->inst_two;
184 dest->inst_three = src->inst_three;
185 dest->inst_four = src->inst_four;
186}
187
188/* Initialize the kgdb_savettable so that debugging can commence */
189static void eh_init(void)
190{
191 int i;
192
193 for(i=0; i < 256; i++)
194 copy_ttentry(&sparc_ttable[i], &kgdb_savettable[i]);
195}
196
197/* Install an exception handler for kgdb */
198static void exceptionHandler(int tnum, trapfunc_t trap_entry)
199{
200 unsigned long te_addr = (unsigned long) trap_entry;
201
202 /* Make new vector */
203 sparc_ttable[tnum].inst_one =
204 SPARC_BRANCH((unsigned long) te_addr,
205 (unsigned long) &sparc_ttable[tnum].inst_one);
206 sparc_ttable[tnum].inst_two = SPARC_RD_PSR_L0;
207 sparc_ttable[tnum].inst_three = SPARC_NOP;
208 sparc_ttable[tnum].inst_four = SPARC_NOP;
209}
210
211/* Convert ch from a hex digit to an int */
212static int
213hex(unsigned char ch)
214{
215 if (ch >= 'a' && ch <= 'f')
216 return ch-'a'+10;
217 if (ch >= '0' && ch <= '9')
218 return ch-'0';
219 if (ch >= 'A' && ch <= 'F')
220 return ch-'A'+10;
221 return -1;
222}
223
224/* scan for the sequence $<data>#<checksum> */
225static void
226getpacket(char *buffer)
227{
228 unsigned char checksum;
229 unsigned char xmitcsum;
230 int i;
231 int count;
232 unsigned char ch;
233
234 do {
235 /* wait around for the start character, ignore all other characters */
236 while ((ch = (getDebugChar() & 0x7f)) != '$') ;
237
238 checksum = 0;
239 xmitcsum = -1;
240
241 count = 0;
242
243 /* now, read until a # or end of buffer is found */
244 while (count < BUFMAX) {
245 ch = getDebugChar() & 0x7f;
246 if (ch == '#')
247 break;
248 checksum = checksum + ch;
249 buffer[count] = ch;
250 count = count + 1;
251 }
252
253 if (count >= BUFMAX)
254 continue;
255
256 buffer[count] = 0;
257
258 if (ch == '#') {
259 xmitcsum = hex(getDebugChar() & 0x7f) << 4;
260 xmitcsum |= hex(getDebugChar() & 0x7f);
261 if (checksum != xmitcsum)
262 putDebugChar('-'); /* failed checksum */
263 else {
264 putDebugChar('+'); /* successful transfer */
265 /* if a sequence char is present, reply the ID */
266 if (buffer[2] == ':') {
267 putDebugChar(buffer[0]);
268 putDebugChar(buffer[1]);
269 /* remove sequence chars from buffer */
270 count = strlen(buffer);
271 for (i=3; i <= count; i++)
272 buffer[i-3] = buffer[i];
273 }
274 }
275 }
276 } while (checksum != xmitcsum);
277}
278
279/* send the packet in buffer. */
280
281static void
282putpacket(unsigned char *buffer)
283{
284 unsigned char checksum;
285 int count;
286 unsigned char ch, recv;
287
288 /* $<packet info>#<checksum>. */
289 do {
290 putDebugChar('$');
291 checksum = 0;
292 count = 0;
293
294 while ((ch = buffer[count])) {
295 putDebugChar(ch);
296 checksum += ch;
297 count += 1;
298 }
299
300 putDebugChar('#');
301 putDebugChar(hexchars[checksum >> 4]);
302 putDebugChar(hexchars[checksum & 0xf]);
303 recv = getDebugChar();
304 } while ((recv & 0x7f) != '+');
305}
306
307static char remcomInBuffer[BUFMAX];
308static char remcomOutBuffer[BUFMAX];
309
310/* Convert the memory pointed to by mem into hex, placing result in buf.
311 * Return a pointer to the last char put in buf (null), in case of mem fault,
312 * return 0.
313 */
314
315static unsigned char *
316mem2hex(char *mem, char *buf, int count)
317{
318 unsigned char ch;
319
320 while (count-- > 0) {
321 /* This assembler code is basically: ch = *mem++;
322 * except that we use the SPARC/Linux exception table
323 * mechanism (see how "fixup" works in kernel_mna_trap_fault)
324 * to arrange for a "return 0" upon a memory fault
325 */
326 __asm__(
327 "\n1:\n\t"
328 "ldub [%0], %1\n\t"
329 "inc %0\n\t"
330 ".section .fixup,#alloc,#execinstr\n\t"
331 ".align 4\n"
332 "2:\n\t"
333 "retl\n\t"
334 " mov 0, %%o0\n\t"
335 ".section __ex_table, #alloc\n\t"
336 ".align 4\n\t"
337 ".word 1b, 2b\n\t"
338 ".text\n"
339 : "=r" (mem), "=r" (ch) : "0" (mem));
340 *buf++ = hexchars[ch >> 4];
341 *buf++ = hexchars[ch & 0xf];
342 }
343
344 *buf = 0;
345 return buf;
346}
347
348/* convert the hex array pointed to by buf into binary to be placed in mem
349 * return a pointer to the character AFTER the last byte written.
350*/
351static char *
352hex2mem(char *buf, char *mem, int count)
353{
354 int i;
355 unsigned char ch;
356
357 for (i=0; i<count; i++) {
358
359 ch = hex(*buf++) << 4;
360 ch |= hex(*buf++);
361 /* Assembler code is *mem++ = ch; with return 0 on fault */
362 __asm__(
363 "\n1:\n\t"
364 "stb %1, [%0]\n\t"
365 "inc %0\n\t"
366 ".section .fixup,#alloc,#execinstr\n\t"
367 ".align 4\n"
368 "2:\n\t"
369 "retl\n\t"
370 " mov 0, %%o0\n\t"
371 ".section __ex_table, #alloc\n\t"
372 ".align 4\n\t"
373 ".word 1b, 2b\n\t"
374 ".text\n"
375 : "=r" (mem) : "r" (ch) , "0" (mem));
376 }
377 return mem;
378}
379
380/* This table contains the mapping between SPARC hardware trap types, and
381 signals, which are primarily what GDB understands. It also indicates
382 which hardware traps we need to commandeer when initializing the stub. */
383
384static struct hard_trap_info
385{
386 unsigned char tt; /* Trap type code for SPARC */
387 unsigned char signo; /* Signal that we map this trap into */
388} hard_trap_info[] = {
389 {SP_TRAP_SBPT, SIGTRAP}, /* ta 1 - Linux/KGDB software breakpoint */
390 {0, 0} /* Must be last */
391};
392
393/* Set up exception handlers for tracing and breakpoints */
394
395void
396set_debug_traps(void)
397{
398 struct hard_trap_info *ht;
399 unsigned long flags;
400
401 local_irq_save(flags);
402#if 0
403/* Have to sort this out. This cannot be done after initialization. */
404 BTFIXUPSET_CALL(flush_cache_all, flush_cache_all_nop, BTFIXUPCALL_NOP);
405#endif
406
407 /* Initialize our copy of the Linux Sparc trap table */
408 eh_init();
409
410 for (ht = hard_trap_info; ht->tt && ht->signo; ht++) {
411 /* Only if it doesn't destroy our fault handlers */
412 if((ht->tt != SP_TRAP_TFLT) &&
413 (ht->tt != SP_TRAP_DFLT))
414 exceptionHandler(ht->tt, trap_low);
415 }
416
417 /* In case GDB is started before us, ack any packets (presumably
418 * "$?#xx") sitting there.
419 *
420 * I've found this code causes more problems than it solves,
421 * so that's why it's commented out. GDB seems to work fine
422 * now starting either before or after the kernel -bwb
423 */
424#if 0
425 while((c = getDebugChar()) != '$');
426 while((c = getDebugChar()) != '#');
427 c = getDebugChar(); /* eat first csum byte */
428 c = getDebugChar(); /* eat second csum byte */
429 putDebugChar('+'); /* ack it */
430#endif
431
432 initialized = 1; /* connect! */
433 local_irq_restore(flags);
434}
435
436/* Convert the SPARC hardware trap type code to a unix signal number. */
437
438static int
439computeSignal(int tt)
440{
441 struct hard_trap_info *ht;
442
443 for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
444 if (ht->tt == tt)
445 return ht->signo;
446
447 return SIGHUP; /* default for things we don't know about */
448}
449
450/*
451 * While we find nice hex chars, build an int.
452 * Return number of chars processed.
453 */
454
455static int
456hexToInt(char **ptr, int *intValue)
457{
458 int numChars = 0;
459 int hexValue;
460
461 *intValue = 0;
462
463 while (**ptr) {
464 hexValue = hex(**ptr);
465 if (hexValue < 0)
466 break;
467
468 *intValue = (*intValue << 4) | hexValue;
469 numChars ++;
470
471 (*ptr)++;
472 }
473
474 return (numChars);
475}
476
477/*
478 * This function does all command processing for interfacing to gdb. It
479 * returns 1 if you should skip the instruction at the trap address, 0
480 * otherwise.
481 */
482
483extern void breakinst(void);
484
485void
486handle_exception (unsigned long *registers)
487{
488 int tt; /* Trap type */
489 int sigval;
490 int addr;
491 int length;
492 char *ptr;
493 unsigned long *sp;
494
495 /* First, we must force all of the windows to be spilled out */
496
497 asm("save %sp, -64, %sp\n\t"
498 "save %sp, -64, %sp\n\t"
499 "save %sp, -64, %sp\n\t"
500 "save %sp, -64, %sp\n\t"
501 "save %sp, -64, %sp\n\t"
502 "save %sp, -64, %sp\n\t"
503 "save %sp, -64, %sp\n\t"
504 "save %sp, -64, %sp\n\t"
505 "restore\n\t"
506 "restore\n\t"
507 "restore\n\t"
508 "restore\n\t"
509 "restore\n\t"
510 "restore\n\t"
511 "restore\n\t"
512 "restore\n\t");
513
514 lock_kernel();
515 if (registers[PC] == (unsigned long)breakinst) {
516 /* Skip over breakpoint trap insn */
517 registers[PC] = registers[NPC];
518 registers[NPC] += 4;
519 }
520
521 sp = (unsigned long *)registers[SP];
522
523 tt = (registers[TBR] >> 4) & 0xff;
524
525 /* reply to host that an exception has occurred */
526 sigval = computeSignal(tt);
527 ptr = remcomOutBuffer;
528
529 *ptr++ = 'T';
530 *ptr++ = hexchars[sigval >> 4];
531 *ptr++ = hexchars[sigval & 0xf];
532
533 *ptr++ = hexchars[PC >> 4];
534 *ptr++ = hexchars[PC & 0xf];
535 *ptr++ = ':';
536 ptr = mem2hex((char *)&registers[PC], ptr, 4);
537 *ptr++ = ';';
538
539 *ptr++ = hexchars[FP >> 4];
540 *ptr++ = hexchars[FP & 0xf];
541 *ptr++ = ':';
542 ptr = mem2hex((char *) (sp + 8 + 6), ptr, 4); /* FP */
543 *ptr++ = ';';
544
545 *ptr++ = hexchars[SP >> 4];
546 *ptr++ = hexchars[SP & 0xf];
547 *ptr++ = ':';
548 ptr = mem2hex((char *)&sp, ptr, 4);
549 *ptr++ = ';';
550
551 *ptr++ = hexchars[NPC >> 4];
552 *ptr++ = hexchars[NPC & 0xf];
553 *ptr++ = ':';
554 ptr = mem2hex((char *)&registers[NPC], ptr, 4);
555 *ptr++ = ';';
556
557 *ptr++ = hexchars[O7 >> 4];
558 *ptr++ = hexchars[O7 & 0xf];
559 *ptr++ = ':';
560 ptr = mem2hex((char *)&registers[O7], ptr, 4);
561 *ptr++ = ';';
562
563 *ptr++ = 0;
564
565 putpacket(remcomOutBuffer);
566
567 /* XXX We may want to add some features dealing with poking the
568 * XXX page tables, the real ones on the srmmu, and what is currently
569 * XXX loaded in the sun4/sun4c tlb at this point in time. But this
570 * XXX also required hacking to the gdb sources directly...
571 */
572
573 while (1) {
574 remcomOutBuffer[0] = 0;
575
576 getpacket(remcomInBuffer);
577 switch (remcomInBuffer[0]) {
578 case '?':
579 remcomOutBuffer[0] = 'S';
580 remcomOutBuffer[1] = hexchars[sigval >> 4];
581 remcomOutBuffer[2] = hexchars[sigval & 0xf];
582 remcomOutBuffer[3] = 0;
583 break;
584
585 case 'd':
586 /* toggle debug flag */
587 break;
588
589 case 'g': /* return the value of the CPU registers */
590 {
591 ptr = remcomOutBuffer;
592 /* G & O regs */
593 ptr = mem2hex((char *)registers, ptr, 16 * 4);
594 /* L & I regs */
595 ptr = mem2hex((char *) (sp + 0), ptr, 16 * 4);
596 /* Floating point */
597 memset(ptr, '0', 32 * 8);
598 /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
599 mem2hex((char *)&registers[Y], (ptr + 32 * 4 * 2), (8 * 4));
600 }
601 break;
602
603 case 'G': /* set the value of the CPU registers - return OK */
604 {
605 unsigned long *newsp, psr;
606
607 psr = registers[PSR];
608
609 ptr = &remcomInBuffer[1];
610 /* G & O regs */
611 hex2mem(ptr, (char *)registers, 16 * 4);
612 /* L & I regs */
613 hex2mem(ptr + 16 * 4 * 2, (char *) (sp + 0), 16 * 4);
614 /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
615 hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y], 8 * 4);
616
617 /* See if the stack pointer has moved. If so,
618 * then copy the saved locals and ins to the
619 * new location. This keeps the window
620 * overflow and underflow routines happy.
621 */
622
623 newsp = (unsigned long *)registers[SP];
624 if (sp != newsp)
625 sp = memcpy(newsp, sp, 16 * 4);
626
627 /* Don't allow CWP to be modified. */
628
629 if (psr != registers[PSR])
630 registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
631
632 strcpy(remcomOutBuffer,"OK");
633 }
634 break;
635
636 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
637 /* Try to read %x,%x. */
638
639 ptr = &remcomInBuffer[1];
640
641 if (hexToInt(&ptr, &addr)
642 && *ptr++ == ','
643 && hexToInt(&ptr, &length)) {
644 if (mem2hex((char *)addr, remcomOutBuffer, length))
645 break;
646
647 strcpy (remcomOutBuffer, "E03");
648 } else {
649 strcpy(remcomOutBuffer,"E01");
650 }
651 break;
652
653 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
654 /* Try to read '%x,%x:'. */
655
656 ptr = &remcomInBuffer[1];
657
658 if (hexToInt(&ptr, &addr)
659 && *ptr++ == ','
660 && hexToInt(&ptr, &length)
661 && *ptr++ == ':') {
662 if (hex2mem(ptr, (char *)addr, length)) {
663 strcpy(remcomOutBuffer, "OK");
664 } else {
665 strcpy(remcomOutBuffer, "E03");
666 }
667 } else {
668 strcpy(remcomOutBuffer, "E02");
669 }
670 break;
671
672 case 'c': /* cAA..AA Continue at address AA..AA(optional) */
673 /* try to read optional parameter, pc unchanged if no parm */
674
675 ptr = &remcomInBuffer[1];
676 if (hexToInt(&ptr, &addr)) {
677 registers[PC] = addr;
678 registers[NPC] = addr + 4;
679 }
680
681/* Need to flush the instruction cache here, as we may have deposited a
682 * breakpoint, and the icache probably has no way of knowing that a data ref to
683 * some location may have changed something that is in the instruction cache.
684 */
685 flush_cache_all();
686 unlock_kernel();
687 return;
688
689 /* kill the program */
690 case 'k' : /* do nothing */
691 break;
692 case 'r': /* Reset */
693 asm ("call 0\n\t"
694 "nop\n\t");
695 break;
696 } /* switch */
697
698 /* reply to the request */
699 putpacket(remcomOutBuffer);
700 } /* while(1) */
701}
702
703/* This function will generate a breakpoint exception. It is used at the
704 beginning of a program to sync up with a debugger and can be used
705 otherwise as a quick means to stop program execution and "break" into
706 the debugger. */
707
708void
709breakpoint(void)
710{
711 if (!initialized)
712 return;
713
714 /* Again, watch those c-prefixes for ELF kernels */
715#if defined(__svr4__) || defined(__ELF__)
716 asm(".globl breakinst\n"
717 "breakinst:\n\t"
718 "ta 1\n");
719#else
720 asm(".globl _breakinst\n"
721 "_breakinst:\n\t"
722 "ta 1\n");
723#endif
724}
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index edbe71e3fab9..eb36f3b746b8 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -13,6 +13,7 @@ config SPARC64
13 default y 13 default y
14 select HAVE_IDE 14 select HAVE_IDE
15 select HAVE_LMB 15 select HAVE_LMB
16 select HAVE_ARCH_KGDB
16 17
17config GENERIC_TIME 18config GENERIC_TIME
18 bool 19 bool
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index 2bd0340b743d..ec4f5ebb1ca6 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -29,3 +29,4 @@ obj-$(CONFIG_SUN_LDOMS) += ldc.o vio.o viohs.o ds.o
29obj-$(CONFIG_AUDIT) += audit.o 29obj-$(CONFIG_AUDIT) += audit.o
30obj-$(CONFIG_AUDIT)$(CONFIG_COMPAT) += compat_audit.o 30obj-$(CONFIG_AUDIT)$(CONFIG_COMPAT) += compat_audit.o
31obj-y += $(obj-yy) 31obj-y += $(obj-yy)
32obj-$(CONFIG_KGDB) += kgdb.o
diff --git a/arch/sparc64/kernel/kgdb.c b/arch/sparc64/kernel/kgdb.c
new file mode 100644
index 000000000000..fefbe6dc51be
--- /dev/null
+++ b/arch/sparc64/kernel/kgdb.c
@@ -0,0 +1,186 @@
1/* kgdb.c: KGDB support for 64-bit sparc.
2 *
3 * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
4 */
5
6#include <linux/kgdb.h>
7#include <linux/kdebug.h>
8
9#include <asm/kdebug.h>
10#include <asm/ptrace.h>
11#include <asm/irq.h>
12
13void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
14{
15 struct reg_window *win;
16 int i;
17
18 gdb_regs[GDB_G0] = 0;
19 for (i = 0; i < 15; i++)
20 gdb_regs[GDB_G1 + i] = regs->u_regs[UREG_G1 + i];
21
22 win = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS);
23 for (i = 0; i < 8; i++)
24 gdb_regs[GDB_L0 + i] = win->locals[i];
25 for (i = 0; i < 8; i++)
26 gdb_regs[GDB_I0 + i] = win->ins[i];
27
28 for (i = GDB_F0; i <= GDB_F62; i++)
29 gdb_regs[i] = 0;
30
31 gdb_regs[GDB_PC] = regs->tpc;
32 gdb_regs[GDB_NPC] = regs->tnpc;
33 gdb_regs[GDB_STATE] = regs->tstate;
34 gdb_regs[GDB_FSR] = 0;
35 gdb_regs[GDB_FPRS] = 0;
36 gdb_regs[GDB_Y] = regs->y;
37}
38
39void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
40{
41 struct thread_info *t = task_thread_info(p);
42 extern unsigned int switch_to_pc;
43 extern unsigned int ret_from_syscall;
44 struct reg_window *win;
45 unsigned long pc, cwp;
46 int i;
47
48 for (i = GDB_G0; i < GDB_G6; i++)
49 gdb_regs[i] = 0;
50 gdb_regs[GDB_G6] = (unsigned long) t;
51 gdb_regs[GDB_G7] = (unsigned long) p;
52 for (i = GDB_O0; i < GDB_SP; i++)
53 gdb_regs[i] = 0;
54 gdb_regs[GDB_SP] = t->ksp;
55 gdb_regs[GDB_O7] = 0;
56
57 win = (struct reg_window *) (t->ksp + STACK_BIAS);
58 for (i = 0; i < 8; i++)
59 gdb_regs[GDB_L0 + i] = win->locals[i];
60 for (i = 0; i < 8; i++)
61 gdb_regs[GDB_I0 + i] = win->ins[i];
62
63 for (i = GDB_F0; i <= GDB_F62; i++)
64 gdb_regs[i] = 0;
65
66 if (t->new_child)
67 pc = (unsigned long) &ret_from_syscall;
68 else
69 pc = (unsigned long) &switch_to_pc;
70
71 gdb_regs[GDB_PC] = pc;
72 gdb_regs[GDB_NPC] = pc + 4;
73
74 cwp = __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP];
75
76 gdb_regs[GDB_STATE] = (TSTATE_PRIV | TSTATE_IE | cwp);
77 gdb_regs[GDB_FSR] = 0;
78 gdb_regs[GDB_FPRS] = 0;
79 gdb_regs[GDB_Y] = 0;
80}
81
82void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
83{
84 struct reg_window *win;
85 int i;
86
87 for (i = 0; i < 15; i++)
88 regs->u_regs[UREG_G1 + i] = gdb_regs[GDB_G1 + i];
89
90 /* If the TSTATE register is changing, we have to preserve
91 * the CWP field, otherwise window save/restore explodes.
92 */
93 if (regs->tstate != gdb_regs[GDB_STATE]) {
94 unsigned long cwp = regs->tstate & TSTATE_CWP;
95
96 regs->tstate = (gdb_regs[GDB_STATE] & ~TSTATE_CWP) | cwp;
97 }
98
99 regs->tpc = gdb_regs[GDB_PC];
100 regs->tnpc = gdb_regs[GDB_NPC];
101 regs->y = gdb_regs[GDB_Y];
102
103 win = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS);
104 for (i = 0; i < 8; i++)
105 win->locals[i] = gdb_regs[GDB_L0 + i];
106 for (i = 0; i < 8; i++)
107 win->ins[i] = gdb_regs[GDB_I0 + i];
108}
109
110#ifdef CONFIG_SMP
111void smp_kgdb_capture_client(struct pt_regs *regs)
112{
113 unsigned long flags;
114
115 __asm__ __volatile__("rdpr %%pstate, %0\n\t"
116 "wrpr %0, %1, %%pstate"
117 : "=r" (flags)
118 : "i" (PSTATE_IE));
119
120 flushw_all();
121
122 if (atomic_read(&kgdb_active) != -1)
123 kgdb_nmicallback(raw_smp_processor_id(), regs);
124
125 __asm__ __volatile__("wrpr %0, 0, %%pstate"
126 : : "r" (flags));
127}
128#endif
129
130int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
131 char *remcomInBuffer, char *remcomOutBuffer,
132 struct pt_regs *linux_regs)
133{
134 unsigned long addr;
135 char *ptr;
136
137 switch (remcomInBuffer[0]) {
138 case 'c':
139 /* try to read optional parameter, pc unchanged if no parm */
140 ptr = &remcomInBuffer[1];
141 if (kgdb_hex2long(&ptr, &addr)) {
142 linux_regs->tpc = addr;
143 linux_regs->tnpc = addr + 4;
144 }
145 /* fallthru */
146
147 case 'D':
148 case 'k':
149 if (linux_regs->tpc == (unsigned long) arch_kgdb_breakpoint) {
150 linux_regs->tpc = linux_regs->tnpc;
151 linux_regs->tnpc += 4;
152 }
153 return 0;
154 }
155 return -1;
156}
157
158asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs)
159{
160 unsigned long flags;
161
162 if (user_mode(regs)) {
163 bad_trap(regs, trap_level);
164 return;
165 }
166
167 flushw_all();
168
169 local_irq_save(flags);
170 kgdb_handle_exception(0x172, SIGTRAP, 0, regs);
171 local_irq_restore(flags);
172}
173
174int kgdb_arch_init(void)
175{
176 return 0;
177}
178
179void kgdb_arch_exit(void)
180{
181}
182
183struct kgdb_arch arch_kgdb_ops = {
184 /* Breakpoint instruction: ta 0x72 */
185 .gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x72 },
186};
diff --git a/arch/sparc64/kernel/misctrap.S b/arch/sparc64/kernel/misctrap.S
index b257497ddde1..753b4f031bfb 100644
--- a/arch/sparc64/kernel/misctrap.S
+++ b/arch/sparc64/kernel/misctrap.S
@@ -1,3 +1,13 @@
1#ifdef CONFIG_KGDB
2 .globl arch_kgdb_breakpoint
3 .type arch_kgdb_breakpoint,#function
4arch_kgdb_breakpoint:
5 ta 0x72
6 retl
7 nop
8 .size arch_kgdb_breakpoint,.-arch_kgdb_breakpoint
9#endif
10
1 .type __do_privact,#function 11 .type __do_privact,#function
2__do_privact: 12__do_privact:
3 mov TLB_SFSR, %g3 13 mov TLB_SFSR, %g3
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 409dd71f2738..8face0c49fef 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -910,6 +910,9 @@ extern unsigned long xcall_flush_tlb_kernel_range;
910extern unsigned long xcall_report_regs; 910extern unsigned long xcall_report_regs;
911extern unsigned long xcall_receive_signal; 911extern unsigned long xcall_receive_signal;
912extern unsigned long xcall_new_mmu_context_version; 912extern unsigned long xcall_new_mmu_context_version;
913#ifdef CONFIG_KGDB
914extern unsigned long xcall_kgdb_capture;
915#endif
913 916
914#ifdef DCACHE_ALIASING_POSSIBLE 917#ifdef DCACHE_ALIASING_POSSIBLE
915extern unsigned long xcall_flush_dcache_page_cheetah; 918extern unsigned long xcall_flush_dcache_page_cheetah;
@@ -1079,6 +1082,13 @@ void smp_new_mmu_context_version(void)
1079 smp_cross_call(&xcall_new_mmu_context_version, 0, 0, 0); 1082 smp_cross_call(&xcall_new_mmu_context_version, 0, 0, 0);
1080} 1083}
1081 1084
1085#ifdef CONFIG_KGDB
1086void kgdb_roundup_cpus(unsigned long flags)
1087{
1088 smp_cross_call(&xcall_kgdb_capture, 0, 0, 0);
1089}
1090#endif
1091
1082void smp_report_regs(void) 1092void smp_report_regs(void)
1083{ 1093{
1084 smp_cross_call(&xcall_report_regs, 0, 0, 0); 1094 smp_cross_call(&xcall_report_regs, 0, 0, 0);
diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
index b0de4c00b11a..450053af039e 100644
--- a/arch/sparc64/kernel/ttable.S
+++ b/arch/sparc64/kernel/ttable.S
@@ -153,7 +153,7 @@ tl0_resv164: BTRAP(0x164) BTRAP(0x165) BTRAP(0x166) BTRAP(0x167) BTRAP(0x168)
153tl0_resv169: BTRAP(0x169) BTRAP(0x16a) BTRAP(0x16b) BTRAP(0x16c) 153tl0_resv169: BTRAP(0x169) BTRAP(0x16a) BTRAP(0x16b) BTRAP(0x16c)
154tl0_linux64: LINUX_64BIT_SYSCALL_TRAP 154tl0_linux64: LINUX_64BIT_SYSCALL_TRAP
155tl0_gsctx: TRAP(sparc64_get_context) TRAP(sparc64_set_context) 155tl0_gsctx: TRAP(sparc64_get_context) TRAP(sparc64_set_context)
156tl0_resv170: KPROBES_TRAP(0x170) KPROBES_TRAP(0x171) BTRAP(0x172) 156tl0_resv170: KPROBES_TRAP(0x170) KPROBES_TRAP(0x171) KGDB_TRAP(0x172)
157tl0_resv173: BTRAP(0x173) BTRAP(0x174) BTRAP(0x175) BTRAP(0x176) BTRAP(0x177) 157tl0_resv173: BTRAP(0x173) BTRAP(0x174) BTRAP(0x175) BTRAP(0x176) BTRAP(0x177)
158tl0_resv178: BTRAP(0x178) BTRAP(0x179) BTRAP(0x17a) BTRAP(0x17b) BTRAP(0x17c) 158tl0_resv178: BTRAP(0x178) BTRAP(0x179) BTRAP(0x17a) BTRAP(0x17b) BTRAP(0x17c)
159tl0_resv17d: BTRAP(0x17d) BTRAP(0x17e) BTRAP(0x17f) 159tl0_resv17d: BTRAP(0x17d) BTRAP(0x17e) BTRAP(0x17f)
diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S
index e686a67561af..796e005dad8b 100644
--- a/arch/sparc64/mm/ultra.S
+++ b/arch/sparc64/mm/ultra.S
@@ -676,6 +676,33 @@ xcall_new_mmu_context_version:
676 wr %g0, (1 << PIL_SMP_CTX_NEW_VERSION), %set_softint 676 wr %g0, (1 << PIL_SMP_CTX_NEW_VERSION), %set_softint
677 retry 677 retry
678 678
679#ifdef CONFIG_KGDB
680 .globl xcall_kgdb_capture
681xcall_kgdb_capture:
682661: rdpr %pstate, %g2
683 wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate
684 .section .sun4v_2insn_patch, "ax"
685 .word 661b
686 nop
687 nop
688 .previous
689
690 rdpr %pil, %g2
691 wrpr %g0, 15, %pil
692 sethi %hi(109f), %g7
693 ba,pt %xcc, etrap_irq
694109: or %g7, %lo(109b), %g7
695#ifdef CONFIG_TRACE_IRQFLAGS
696 call trace_hardirqs_off
697 nop
698#endif
699 call smp_kgdb_capture_client
700 add %sp, PTREGS_OFF, %o0
701 /* Has to be a non-v9 branch due to the large distance. */
702 ba rtrap_xcall
703 ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
704#endif
705
679#endif /* CONFIG_SMP */ 706#endif /* CONFIG_SMP */
680 707
681 708
diff --git a/include/asm-sparc/head.h b/include/asm-sparc/head.h
index fcdba5116339..e6532c3e09c9 100644
--- a/include/asm-sparc/head.h
+++ b/include/asm-sparc/head.h
@@ -52,6 +52,17 @@
52 nop; \ 52 nop; \
53 nop; 53 nop;
54 54
55#ifdef CONFIG_KGDB
56#define KGDB_TRAP(num) \
57 b kgdb_trap_low; \
58 rd %psr,%l0; \
59 nop; \
60 nop;
61#else
62#define KGDB_TRAP(num) \
63 BAD_TRAP(num)
64#endif
65
55/* The Get Condition Codes software trap for userland. */ 66/* The Get Condition Codes software trap for userland. */
56#define GETCC_TRAP \ 67#define GETCC_TRAP \
57 b getcc_trap_handler; mov %psr, %l0; nop; nop; 68 b getcc_trap_handler; mov %psr, %l0; nop; nop;
diff --git a/include/asm-sparc/kgdb.h b/include/asm-sparc/kgdb.h
index d120adfb429f..b6ef301d05bf 100644
--- a/include/asm-sparc/kgdb.h
+++ b/include/asm-sparc/kgdb.h
@@ -1,94 +1,38 @@
1/* $Id: kgdb.h,v 1.8 1998/01/07 06:33:44 baccala Exp $
2 * kgdb.h: Defines and declarations for serial line source level
3 * remote debugging of the Linux kernel using gdb.
4 *
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 */
7#ifndef _SPARC_KGDB_H 1#ifndef _SPARC_KGDB_H
8#define _SPARC_KGDB_H 2#define _SPARC_KGDB_H
9 3
10#ifndef __ASSEMBLY__ 4#ifdef CONFIG_SPARC32
11/* To init the kgdb engine. */ 5#define BUFMAX 2048
12extern void set_debug_traps(void); 6#else
13 7#define BUFMAX 4096
14/* To enter the debugger explicitly. */ 8#endif
15extern void breakpoint(void); 9
16 10enum regnames {
17/* For convenience we define the format of a kgdb trap breakpoint 11 GDB_G0, GDB_G1, GDB_G2, GDB_G3, GDB_G4, GDB_G5, GDB_G6, GDB_G7,
18 * frame here also. 12 GDB_O0, GDB_O1, GDB_O2, GDB_O3, GDB_O4, GDB_O5, GDB_SP, GDB_O7,
19 */ 13 GDB_L0, GDB_L1, GDB_L2, GDB_L3, GDB_L4, GDB_L5, GDB_L6, GDB_L7,
20struct kgdb_frame { 14 GDB_I0, GDB_I1, GDB_I2, GDB_I3, GDB_I4, GDB_I5, GDB_FP, GDB_I7,
21 unsigned long globals[8]; 15 GDB_F0,
22 unsigned long outs[8]; 16 GDB_F31 = GDB_F0 + 31,
23 unsigned long locals[8]; 17#ifdef CONFIG_SPARC32
24 unsigned long ins[8]; 18 GDB_Y, GDB_PSR, GDB_WIM, GDB_TBR, GDB_PC, GDB_NPC,
25 unsigned long fpregs[32]; 19 GDB_FSR, GDB_CSR,
26 unsigned long y; 20#else
27 unsigned long psr; 21 GDB_F32 = GDB_F0 + 32,
28 unsigned long wim; 22 GDB_F62 = GDB_F32 + 15,
29 unsigned long tbr; 23 GDB_PC, GDB_NPC, GDB_STATE, GDB_FSR, GDB_FPRS, GDB_Y,
30 unsigned long pc; 24#endif
31 unsigned long npc;
32 unsigned long fpsr;
33 unsigned long cpsr;
34}; 25};
35#endif /* !(__ASSEMBLY__) */
36
37/* Macros for assembly usage of the kgdb breakpoint frame. */
38#define KGDB_G0 0x000
39#define KGDB_G1 0x004
40#define KGDB_G2 0x008
41#define KGDB_G4 0x010
42#define KGDB_G6 0x018
43#define KGDB_I0 0x020
44#define KGDB_I2 0x028
45#define KGDB_I4 0x030
46#define KGDB_I6 0x038
47#define KGDB_Y 0x100
48#define KGDB_PSR 0x104
49#define KGDB_WIM 0x108
50#define KGDB_TBR 0x10c
51#define KGDB_PC 0x110
52#define KGDB_NPC 0x114
53
54#define SAVE_KGDB_GLOBALS(reg) \
55 std %g0, [%reg + STACKFRAME_SZ + KGDB_G0]; \
56 std %g2, [%reg + STACKFRAME_SZ + KGDB_G2]; \
57 std %g4, [%reg + STACKFRAME_SZ + KGDB_G4]; \
58 std %g6, [%reg + STACKFRAME_SZ + KGDB_G6];
59
60#define SAVE_KGDB_INS(reg) \
61 std %i0, [%reg + STACKFRAME_SZ + KGDB_I0]; \
62 std %i2, [%reg + STACKFRAME_SZ + KGDB_I2]; \
63 std %i4, [%reg + STACKFRAME_SZ + KGDB_I4]; \
64 std %i6, [%reg + STACKFRAME_SZ + KGDB_I6];
65
66#define SAVE_KGDB_SREGS(reg, reg_y, reg_psr, reg_wim, reg_tbr, reg_pc, reg_npc) \
67 st %reg_y, [%reg + STACKFRAME_SZ + KGDB_Y]; \
68 st %reg_psr, [%reg + STACKFRAME_SZ + KGDB_PSR]; \
69 st %reg_wim, [%reg + STACKFRAME_SZ + KGDB_WIM]; \
70 st %reg_tbr, [%reg + STACKFRAME_SZ + KGDB_TBR]; \
71 st %reg_pc, [%reg + STACKFRAME_SZ + KGDB_PC]; \
72 st %reg_npc, [%reg + STACKFRAME_SZ + KGDB_NPC];
73 26
74#define LOAD_KGDB_GLOBALS(reg) \ 27#ifdef CONFIG_SPARC32
75 ld [%reg + STACKFRAME_SZ + KGDB_G1], %g1; \ 28#define NUMREGBYTES ((GDB_CSR + 1) * 4)
76 ldd [%reg + STACKFRAME_SZ + KGDB_G2], %g2; \ 29#else
77 ldd [%reg + STACKFRAME_SZ + KGDB_G4], %g4; \ 30#define NUMREGBYTES ((GDB_Y + 1) * 8)
78 ldd [%reg + STACKFRAME_SZ + KGDB_G6], %g6; 31#endif
79 32
80#define LOAD_KGDB_INS(reg) \ 33extern void arch_kgdb_breakpoint(void);
81 ldd [%reg + STACKFRAME_SZ + KGDB_I0], %i0; \
82 ldd [%reg + STACKFRAME_SZ + KGDB_I2], %i2; \
83 ldd [%reg + STACKFRAME_SZ + KGDB_I4], %i4; \
84 ldd [%reg + STACKFRAME_SZ + KGDB_I6], %i6;
85 34
86#define LOAD_KGDB_SREGS(reg, reg_y, reg_psr, reg_wim, reg_tbr, reg_pc, reg_npc) \ 35#define BREAK_INSTR_SIZE 4
87 ld [%reg + STACKFRAME_SZ + KGDB_Y], %reg_y; \ 36#define CACHE_FLUSH_IS_SAFE 1
88 ld [%reg + STACKFRAME_SZ + KGDB_PSR], %reg_psr; \
89 ld [%reg + STACKFRAME_SZ + KGDB_WIM], %reg_wim; \
90 ld [%reg + STACKFRAME_SZ + KGDB_TBR], %reg_tbr; \
91 ld [%reg + STACKFRAME_SZ + KGDB_PC], %reg_pc; \
92 ld [%reg + STACKFRAME_SZ + KGDB_NPC], %reg_npc;
93 37
94#endif /* !(_SPARC_KGDB_H) */ 38#endif /* _SPARC_KGDB_H */
diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h
index 4e08210cd4c2..b4b024445fc9 100644
--- a/include/asm-sparc/system.h
+++ b/include/asm-sparc/system.h
@@ -94,6 +94,8 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
94 } while(0) 94 } while(0)
95#endif 95#endif
96 96
97extern void flushw_all(void);
98
97/* 99/*
98 * Flush windows so that the VM switch which follows 100 * Flush windows so that the VM switch which follows
99 * would not pull the stack from under us. 101 * would not pull the stack from under us.
diff --git a/include/asm-sparc64/kgdb.h b/include/asm-sparc64/kgdb.h
new file mode 100644
index 000000000000..aa6532fd3a13
--- /dev/null
+++ b/include/asm-sparc64/kgdb.h
@@ -0,0 +1 @@
#include <asm-sparc/kgdb.h>
diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h
index 53eae091a171..6897ac31be41 100644
--- a/include/asm-sparc64/system.h
+++ b/include/asm-sparc64/system.h
@@ -180,12 +180,13 @@ do { if (test_thread_flag(TIF_PERFCTR)) { \
180 "ldx [%%sp + 2047 + 0x70], %%i6\n\t" \ 180 "ldx [%%sp + 2047 + 0x70], %%i6\n\t" \
181 "ldx [%%sp + 2047 + 0x78], %%i7\n\t" \ 181 "ldx [%%sp + 2047 + 0x78], %%i7\n\t" \
182 "ldx [%%g6 + %9], %%g4\n\t" \ 182 "ldx [%%g6 + %9], %%g4\n\t" \
183 "brz,pt %%o7, 1f\n\t" \ 183 "brz,pt %%o7, switch_to_pc\n\t" \
184 " mov %%g7, %0\n\t" \ 184 " mov %%g7, %0\n\t" \
185 "sethi %%hi(ret_from_syscall), %%g1\n\t" \ 185 "sethi %%hi(ret_from_syscall), %%g1\n\t" \
186 "jmpl %%g1 + %%lo(ret_from_syscall), %%g0\n\t" \ 186 "jmpl %%g1 + %%lo(ret_from_syscall), %%g0\n\t" \
187 " nop\n\t" \ 187 " nop\n\t" \
188 "1:\n\t" \ 188 ".globl switch_to_pc\n\t" \
189 "switch_to_pc:\n\t" \
189 : "=&r" (last), "=r" (current), "=r" (current_thread_info_reg), \ 190 : "=&r" (last), "=r" (current), "=r" (current_thread_info_reg), \
190 "=r" (__local_per_cpu_offset) \ 191 "=r" (__local_per_cpu_offset) \
191 : "0" (task_thread_info(next)), \ 192 : "0" (task_thread_info(next)), \
diff --git a/include/asm-sparc64/ttable.h b/include/asm-sparc64/ttable.h
index d3cc4eff39a6..1b55538b944f 100644
--- a/include/asm-sparc64/ttable.h
+++ b/include/asm-sparc64/ttable.h
@@ -175,6 +175,12 @@
175#define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl) 175#define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
176#endif 176#endif
177 177
178#ifdef CONFIG_KGDB
179#define KGDB_TRAP(lvl) TRAP_IRQ(kgdb_trap, lvl)
180#else
181#define KGDB_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
182#endif
183
178#define SUN4V_ITSB_MISS \ 184#define SUN4V_ITSB_MISS \
179 ldxa [%g0] ASI_SCRATCHPAD, %g2; \ 185 ldxa [%g0] ASI_SCRATCHPAD, %g2; \
180 ldx [%g2 + HV_FAULT_I_ADDR_OFFSET], %g4; \ 186 ldx [%g2 + HV_FAULT_I_ADDR_OFFSET], %g4; \