Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6: sparc64: remove duplicated include sparc: Add kgdb support. kgdbts: Sparc needs sstep emulation. sparc32: Kill smp_message_pass() and related code. sparc64: Kill PIL_RESERVED, unused. sparc64: Split entry.S up into seperate files.
This commit is contained in:
@ -68,6 +68,7 @@ config SPARC
|
||||
default y
|
||||
select HAVE_IDE
|
||||
select HAVE_OPROFILE
|
||||
select HAVE_ARCH_KGDB if !SMP
|
||||
|
||||
# Identify this as a Sparc32 build
|
||||
config SPARC32
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.25
|
||||
# Sun Apr 20 01:49:51 2008
|
||||
# Tue Apr 29 01:28:58 2008
|
||||
#
|
||||
CONFIG_MMU=y
|
||||
CONFIG_HIGHMEM=y
|
||||
@ -217,12 +217,7 @@ CONFIG_IPV6_TUNNEL=m
|
||||
# CONFIG_NETWORK_SECMARK is not set
|
||||
# CONFIG_NETFILTER is not set
|
||||
# CONFIG_IP_DCCP is not set
|
||||
CONFIG_IP_SCTP=m
|
||||
# CONFIG_SCTP_DBG_MSG is not set
|
||||
CONFIG_SCTP_DBG_OBJCNT=y
|
||||
# CONFIG_SCTP_HMAC_NONE is not set
|
||||
# CONFIG_SCTP_HMAC_SHA1 is not set
|
||||
CONFIG_SCTP_HMAC_MD5=y
|
||||
# CONFIG_IP_SCTP is not set
|
||||
# CONFIG_TIPC is not set
|
||||
# CONFIG_ATM is not set
|
||||
# CONFIG_BRIDGE is not set
|
||||
@ -245,9 +240,7 @@ CONFIG_NET_PKTGEN=m
|
||||
# CONFIG_CAN is not set
|
||||
# CONFIG_IRDA is not set
|
||||
# CONFIG_BT is not set
|
||||
CONFIG_AF_RXRPC=m
|
||||
# CONFIG_AF_RXRPC_DEBUG is not set
|
||||
# CONFIG_RXKAD is not set
|
||||
# CONFIG_AF_RXRPC is not set
|
||||
|
||||
#
|
||||
# Wireless
|
||||
@ -390,7 +383,7 @@ CONFIG_DUMMY=m
|
||||
# CONFIG_BONDING is not set
|
||||
# CONFIG_MACVLAN is not set
|
||||
# CONFIG_EQUALIZER is not set
|
||||
CONFIG_TUN=m
|
||||
# CONFIG_TUN is not set
|
||||
# CONFIG_VETH is not set
|
||||
# CONFIG_ARCNET is not set
|
||||
# CONFIG_PHYLIB is not set
|
||||
@ -544,6 +537,7 @@ CONFIG_SERIAL_SUNSU_CONSOLE=y
|
||||
# CONFIG_SERIAL_SUNSAB is not set
|
||||
CONFIG_SERIAL_CORE=y
|
||||
CONFIG_SERIAL_CORE_CONSOLE=y
|
||||
CONFIG_CONSOLE_POLL=y
|
||||
# CONFIG_SERIAL_JSM is not set
|
||||
CONFIG_UNIX98_PTYS=y
|
||||
CONFIG_LEGACY_PTYS=y
|
||||
@ -595,6 +589,7 @@ CONFIG_SSB_POSSIBLE=y
|
||||
# Multifunction device drivers
|
||||
#
|
||||
# CONFIG_MFD_SM501 is not set
|
||||
# CONFIG_HTC_PASIC3 is not set
|
||||
|
||||
#
|
||||
# Multimedia devices
|
||||
@ -645,10 +640,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
|
||||
# CONFIG_NEW_LEDS is not set
|
||||
# CONFIG_INFINIBAND is not set
|
||||
# CONFIG_RTC_CLASS is not set
|
||||
|
||||
#
|
||||
# Userspace I/O
|
||||
#
|
||||
# CONFIG_UIO is not set
|
||||
|
||||
#
|
||||
@ -680,16 +671,12 @@ CONFIG_FS_MBCACHE=y
|
||||
# CONFIG_REISERFS_FS is not set
|
||||
# CONFIG_JFS_FS is not set
|
||||
CONFIG_FS_POSIX_ACL=y
|
||||
CONFIG_XFS_FS=m
|
||||
CONFIG_XFS_QUOTA=y
|
||||
CONFIG_XFS_POSIX_ACL=y
|
||||
CONFIG_XFS_RT=y
|
||||
# CONFIG_XFS_FS is not set
|
||||
# CONFIG_OCFS2_FS is not set
|
||||
CONFIG_DNOTIFY=y
|
||||
CONFIG_INOTIFY=y
|
||||
CONFIG_INOTIFY_USER=y
|
||||
# CONFIG_QUOTA is not set
|
||||
CONFIG_QUOTACTL=y
|
||||
CONFIG_AUTOFS_FS=m
|
||||
CONFIG_AUTOFS4_FS=m
|
||||
# CONFIG_FUSE_FS is not set
|
||||
@ -725,11 +712,9 @@ CONFIG_SYSFS=y
|
||||
#
|
||||
# CONFIG_ADFS_FS is not set
|
||||
# CONFIG_AFFS_FS is not set
|
||||
# CONFIG_ECRYPT_FS is not set
|
||||
# CONFIG_HFS_FS is not set
|
||||
# CONFIG_HFSPLUS_FS is not set
|
||||
CONFIG_BEFS_FS=m
|
||||
# CONFIG_BEFS_DEBUG is not set
|
||||
# CONFIG_BEFS_FS is not set
|
||||
# CONFIG_BFS_FS is not set
|
||||
# CONFIG_EFS_FS is not set
|
||||
# CONFIG_CRAMFS is not set
|
||||
@ -744,7 +729,6 @@ CONFIG_NETWORK_FILESYSTEMS=y
|
||||
CONFIG_NFS_FS=y
|
||||
# CONFIG_NFS_V3 is not set
|
||||
# CONFIG_NFS_V4 is not set
|
||||
# CONFIG_NFS_DIRECTIO is not set
|
||||
# CONFIG_NFSD is not set
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_LOCKD=y
|
||||
@ -755,16 +739,10 @@ CONFIG_SUNRPC_GSS=m
|
||||
CONFIG_RPCSEC_GSS_KRB5=m
|
||||
# CONFIG_RPCSEC_GSS_SPKM3 is not set
|
||||
# CONFIG_SMB_FS is not set
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS is not set
|
||||
# CONFIG_CIFS_WEAK_PW_HASH is not set
|
||||
# CONFIG_CIFS_XATTR is not set
|
||||
# CONFIG_CIFS_DEBUG2 is not set
|
||||
# CONFIG_CIFS_EXPERIMENTAL is not set
|
||||
# CONFIG_CIFS is not set
|
||||
# CONFIG_NCP_FS is not set
|
||||
# CONFIG_CODA_FS is not set
|
||||
CONFIG_AFS_FS=m
|
||||
# CONFIG_AFS_DEBUG is not set
|
||||
# CONFIG_AFS_FS is not set
|
||||
|
||||
#
|
||||
# Partition Types
|
||||
@ -821,6 +799,7 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
|
||||
# CONFIG_PRINTK_TIME is not set
|
||||
# CONFIG_ENABLE_WARN_DEPRECATED is not set
|
||||
CONFIG_ENABLE_MUST_CHECK=y
|
||||
CONFIG_FRAME_WARN=1024
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
# CONFIG_UNUSED_SYMBOLS is not set
|
||||
# CONFIG_DEBUG_FS is not set
|
||||
@ -842,70 +821,105 @@ CONFIG_DETECT_SOFTLOCKUP=y
|
||||
CONFIG_DEBUG_BUGVERBOSE=y
|
||||
# CONFIG_DEBUG_INFO is not set
|
||||
# CONFIG_DEBUG_VM is not set
|
||||
# CONFIG_DEBUG_WRITECOUNT is not set
|
||||
# CONFIG_DEBUG_LIST is not set
|
||||
# CONFIG_DEBUG_SG is not set
|
||||
CONFIG_FRAME_POINTER=y
|
||||
# CONFIG_BOOT_PRINTK_DELAY is not set
|
||||
# CONFIG_RCU_TORTURE_TEST is not set
|
||||
# CONFIG_BACKTRACE_SELF_TEST is not set
|
||||
# CONFIG_FAULT_INJECTION is not set
|
||||
# CONFIG_SAMPLES is not set
|
||||
CONFIG_KGDB=y
|
||||
CONFIG_HAVE_ARCH_KGDB=y
|
||||
CONFIG_KGDB_SERIAL_CONSOLE=y
|
||||
CONFIG_KGDB_TESTS=y
|
||||
# CONFIG_KGDB_TESTS_ON_BOOT is not set
|
||||
# CONFIG_DEBUG_STACK_USAGE is not set
|
||||
|
||||
#
|
||||
# Security options
|
||||
#
|
||||
CONFIG_KEYS=y
|
||||
# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
|
||||
# CONFIG_KEYS is not set
|
||||
# CONFIG_SECURITY is not set
|
||||
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
|
||||
CONFIG_CRYPTO=y
|
||||
|
||||
#
|
||||
# Crypto core or helper
|
||||
#
|
||||
CONFIG_CRYPTO_ALGAPI=y
|
||||
CONFIG_CRYPTO_AEAD=y
|
||||
CONFIG_CRYPTO_BLKCIPHER=y
|
||||
# CONFIG_CRYPTO_SEQIV is not set
|
||||
CONFIG_CRYPTO_HASH=y
|
||||
CONFIG_CRYPTO_MANAGER=y
|
||||
# CONFIG_CRYPTO_GF128MUL is not set
|
||||
CONFIG_CRYPTO_NULL=m
|
||||
# CONFIG_CRYPTO_CRYPTD is not set
|
||||
CONFIG_CRYPTO_AUTHENC=y
|
||||
# CONFIG_CRYPTO_TEST is not set
|
||||
|
||||
#
|
||||
# Authenticated Encryption with Associated Data
|
||||
#
|
||||
# CONFIG_CRYPTO_CCM is not set
|
||||
# CONFIG_CRYPTO_GCM is not set
|
||||
# CONFIG_CRYPTO_SEQIV is not set
|
||||
|
||||
#
|
||||
# Block modes
|
||||
#
|
||||
CONFIG_CRYPTO_CBC=y
|
||||
# CONFIG_CRYPTO_CTR is not set
|
||||
# CONFIG_CRYPTO_CTS is not set
|
||||
CONFIG_CRYPTO_ECB=m
|
||||
# CONFIG_CRYPTO_LRW is not set
|
||||
CONFIG_CRYPTO_PCBC=m
|
||||
# CONFIG_CRYPTO_XTS is not set
|
||||
|
||||
#
|
||||
# Hash modes
|
||||
#
|
||||
CONFIG_CRYPTO_HMAC=y
|
||||
# CONFIG_CRYPTO_XCBC is not set
|
||||
CONFIG_CRYPTO_NULL=m
|
||||
|
||||
#
|
||||
# Digest
|
||||
#
|
||||
CONFIG_CRYPTO_CRC32C=m
|
||||
CONFIG_CRYPTO_MD4=y
|
||||
CONFIG_CRYPTO_MD5=y
|
||||
CONFIG_CRYPTO_MICHAEL_MIC=m
|
||||
CONFIG_CRYPTO_SHA1=y
|
||||
CONFIG_CRYPTO_SHA256=m
|
||||
CONFIG_CRYPTO_SHA512=m
|
||||
# CONFIG_CRYPTO_WP512 is not set
|
||||
# CONFIG_CRYPTO_TGR192 is not set
|
||||
# CONFIG_CRYPTO_GF128MUL is not set
|
||||
CONFIG_CRYPTO_ECB=m
|
||||
CONFIG_CRYPTO_CBC=y
|
||||
CONFIG_CRYPTO_PCBC=m
|
||||
# CONFIG_CRYPTO_LRW is not set
|
||||
# CONFIG_CRYPTO_XTS is not set
|
||||
# CONFIG_CRYPTO_CTR is not set
|
||||
# CONFIG_CRYPTO_GCM is not set
|
||||
# CONFIG_CRYPTO_CCM is not set
|
||||
# CONFIG_CRYPTO_CRYPTD is not set
|
||||
CONFIG_CRYPTO_DES=y
|
||||
# CONFIG_CRYPTO_FCRYPT is not set
|
||||
CONFIG_CRYPTO_BLOWFISH=m
|
||||
CONFIG_CRYPTO_TWOFISH=m
|
||||
CONFIG_CRYPTO_TWOFISH_COMMON=m
|
||||
CONFIG_CRYPTO_SERPENT=m
|
||||
# CONFIG_CRYPTO_WP512 is not set
|
||||
|
||||
#
|
||||
# Ciphers
|
||||
#
|
||||
CONFIG_CRYPTO_AES=m
|
||||
# CONFIG_CRYPTO_ANUBIS is not set
|
||||
CONFIG_CRYPTO_ARC4=m
|
||||
CONFIG_CRYPTO_BLOWFISH=m
|
||||
# CONFIG_CRYPTO_CAMELLIA is not set
|
||||
CONFIG_CRYPTO_CAST5=m
|
||||
CONFIG_CRYPTO_CAST6=m
|
||||
# CONFIG_CRYPTO_TEA is not set
|
||||
CONFIG_CRYPTO_ARC4=m
|
||||
CONFIG_CRYPTO_DES=y
|
||||
# CONFIG_CRYPTO_FCRYPT is not set
|
||||
# CONFIG_CRYPTO_KHAZAD is not set
|
||||
# CONFIG_CRYPTO_ANUBIS is not set
|
||||
# CONFIG_CRYPTO_SEED is not set
|
||||
# CONFIG_CRYPTO_SALSA20 is not set
|
||||
# CONFIG_CRYPTO_SEED is not set
|
||||
CONFIG_CRYPTO_SERPENT=m
|
||||
# CONFIG_CRYPTO_TEA is not set
|
||||
CONFIG_CRYPTO_TWOFISH=m
|
||||
CONFIG_CRYPTO_TWOFISH_COMMON=m
|
||||
|
||||
#
|
||||
# Compression
|
||||
#
|
||||
CONFIG_CRYPTO_DEFLATE=y
|
||||
CONFIG_CRYPTO_MICHAEL_MIC=m
|
||||
CONFIG_CRYPTO_CRC32C=m
|
||||
# CONFIG_CRYPTO_CAMELLIA is not set
|
||||
# CONFIG_CRYPTO_TEST is not set
|
||||
CONFIG_CRYPTO_AUTHENC=y
|
||||
# CONFIG_CRYPTO_LZO is not set
|
||||
# CONFIG_CRYPTO_HW is not set
|
||||
|
||||
@ -913,6 +927,7 @@ CONFIG_CRYPTO_AUTHENC=y
|
||||
# Library routines
|
||||
#
|
||||
CONFIG_BITREVERSE=y
|
||||
# CONFIG_GENERIC_FIND_FIRST_BIT is not set
|
||||
# CONFIG_CRC_CCITT is not set
|
||||
# CONFIG_CRC16 is not set
|
||||
# CONFIG_CRC_ITU_T is not set
|
||||
|
@ -25,3 +25,4 @@ obj-$(CONFIG_PCI) += ebus.o
|
||||
obj-$(CONFIG_SUN_PM) += apc.o pmc.o
|
||||
obj-$(CONFIG_MODULES) += module.o sparc_ksyms.o
|
||||
obj-$(CONFIG_SPARC_LED) += led.o
|
||||
obj-$(CONFIG_KGDB) += kgdb.o
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include <asm/head.h>
|
||||
#include <asm/asi.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/kgdb.h>
|
||||
#include <asm/contregs.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
@ -45,91 +44,20 @@
|
||||
_SV; _SV; _SV; _SV; _SV; _SV; _SV; \
|
||||
_RS; _RS; _RS; _RS; _RS; _RS; _RS;
|
||||
|
||||
/* First, KGDB low level things. This is a rewrite
|
||||
* of the routines found in the sparc-stub.c asm() statement
|
||||
* from the gdb distribution. This is also dual-purpose
|
||||
* as a software trap for userlevel programs.
|
||||
*/
|
||||
.data
|
||||
.align 4
|
||||
|
||||
in_trap_handler:
|
||||
.word 0
|
||||
|
||||
.text
|
||||
|
||||
#ifdef CONFIG_KGDB
|
||||
.align 4
|
||||
|
||||
#if 0 /* kgdb is dropped from 2.5.33 */
|
||||
! This function is called when any SPARC trap (except window overflow or
|
||||
! underflow) occurs. It makes sure that the invalid register window is still
|
||||
! available before jumping into C code. It will also restore the world if you
|
||||
! return from handle_exception.
|
||||
|
||||
.globl trap_low
|
||||
trap_low:
|
||||
rd %wim, %l3
|
||||
SAVE_ALL
|
||||
|
||||
sethi %hi(in_trap_handler), %l4
|
||||
ld [%lo(in_trap_handler) + %l4], %l5
|
||||
inc %l5
|
||||
st %l5, [%lo(in_trap_handler) + %l4]
|
||||
|
||||
/* Make sure kgdb sees the same state we just saved. */
|
||||
LOAD_PT_GLOBALS(sp)
|
||||
LOAD_PT_INS(sp)
|
||||
ld [%sp + STACKFRAME_SZ + PT_Y], %l4
|
||||
ld [%sp + STACKFRAME_SZ + PT_WIM], %l3
|
||||
ld [%sp + STACKFRAME_SZ + PT_PSR], %l0
|
||||
ld [%sp + STACKFRAME_SZ + PT_PC], %l1
|
||||
ld [%sp + STACKFRAME_SZ + PT_NPC], %l2
|
||||
rd %tbr, %l5 /* Never changes... */
|
||||
|
||||
/* Make kgdb exception frame. */
|
||||
sub %sp,(16+1+6+1+72)*4,%sp ! Make room for input & locals
|
||||
! + hidden arg + arg spill
|
||||
! + doubleword alignment
|
||||
! + registers[72] local var
|
||||
SAVE_KGDB_GLOBALS(sp)
|
||||
SAVE_KGDB_INS(sp)
|
||||
SAVE_KGDB_SREGS(sp, l4, l0, l3, l5, l1, l2)
|
||||
|
||||
/* We are increasing PIL, so two writes. */
|
||||
or %l0, PSR_PIL, %l0
|
||||
wr %l0, 0, %psr
|
||||
WRITE_PAUSE
|
||||
wr %l0, PSR_ET, %psr
|
||||
WRITE_PAUSE
|
||||
|
||||
call handle_exception
|
||||
add %sp, STACKFRAME_SZ, %o0 ! Pass address of registers
|
||||
|
||||
/* Load new kgdb register set. */
|
||||
LOAD_KGDB_GLOBALS(sp)
|
||||
LOAD_KGDB_INS(sp)
|
||||
LOAD_KGDB_SREGS(sp, l4, l0, l3, l5, l1, l2)
|
||||
wr %l4, 0x0, %y
|
||||
|
||||
sethi %hi(in_trap_handler), %l4
|
||||
ld [%lo(in_trap_handler) + %l4], %l5
|
||||
dec %l5
|
||||
st %l5, [%lo(in_trap_handler) + %l4]
|
||||
|
||||
add %sp,(16+1+6+1+72)*4,%sp ! Undo the kgdb trap frame.
|
||||
|
||||
/* Now take what kgdb did and place it into the pt_regs
|
||||
* frame which SparcLinux RESTORE_ALL understands.,
|
||||
*/
|
||||
STORE_PT_INS(sp)
|
||||
STORE_PT_GLOBALS(sp)
|
||||
STORE_PT_YREG(sp, g2)
|
||||
STORE_PT_PRIV(sp, l0, l1, l2)
|
||||
|
||||
RESTORE_ALL
|
||||
.globl arch_kgdb_breakpoint
|
||||
.type arch_kgdb_breakpoint,#function
|
||||
arch_kgdb_breakpoint:
|
||||
ta 0x7d
|
||||
retl
|
||||
nop
|
||||
.size arch_kgdb_breakpoint,.-arch_kgdb_breakpoint
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
|
||||
.text
|
||||
.align 4
|
||||
.globl floppy_hardint
|
||||
floppy_hardint:
|
||||
@ -1596,6 +1524,23 @@ breakpoint_trap:
|
||||
|
||||
RESTORE_ALL
|
||||
|
||||
#ifdef CONFIG_KGDB
|
||||
.align 4
|
||||
.globl kgdb_trap_low
|
||||
.type kgdb_trap_low,#function
|
||||
kgdb_trap_low:
|
||||
rd %wim,%l3
|
||||
SAVE_ALL
|
||||
wr %l0, PSR_ET, %psr
|
||||
WRITE_PAUSE
|
||||
|
||||
call kgdb_trap
|
||||
add %sp, STACKFRAME_SZ, %o0
|
||||
|
||||
RESTORE_ALL
|
||||
.size kgdb_trap_low,.-kgdb_trap_low
|
||||
#endif
|
||||
|
||||
.align 4
|
||||
.globl __handle_exception, flush_patch_exception
|
||||
__handle_exception:
|
||||
@ -1698,4 +1643,22 @@ pcic_nmi_trap_patch:
|
||||
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
.globl flushw_all
|
||||
flushw_all:
|
||||
save %sp, -0x40, %sp
|
||||
save %sp, -0x40, %sp
|
||||
save %sp, -0x40, %sp
|
||||
save %sp, -0x40, %sp
|
||||
save %sp, -0x40, %sp
|
||||
save %sp, -0x40, %sp
|
||||
save %sp, -0x40, %sp
|
||||
restore
|
||||
restore
|
||||
restore
|
||||
restore
|
||||
restore
|
||||
restore
|
||||
ret
|
||||
restore
|
||||
|
||||
/* End of entry.S */
|
||||
|
@ -191,7 +191,8 @@ t_bade8:BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xe
|
||||
t_baded:BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
|
||||
t_badf2:BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
|
||||
t_badf7:BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
|
||||
t_badfc:BAD_TRAP(0xfc) BAD_TRAP(0xfd)
|
||||
t_badfc:BAD_TRAP(0xfc)
|
||||
t_kgdb: KGDB_TRAP(0xfd)
|
||||
dbtrap: BAD_TRAP(0xfe) /* Debugger/PROM breakpoint #1 */
|
||||
dbtrap2:BAD_TRAP(0xff) /* Debugger/PROM breakpoint #2 */
|
||||
|
||||
@ -267,7 +268,7 @@ trapbase_cpu1:
|
||||
BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
|
||||
BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
|
||||
BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
|
||||
BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
|
||||
BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
|
||||
|
||||
trapbase_cpu2:
|
||||
BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
|
||||
@ -335,7 +336,7 @@ trapbase_cpu2:
|
||||
BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
|
||||
BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
|
||||
BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
|
||||
BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
|
||||
BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
|
||||
|
||||
trapbase_cpu3:
|
||||
BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction)
|
||||
@ -403,7 +404,7 @@ trapbase_cpu3:
|
||||
BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
|
||||
BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
|
||||
BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
|
||||
BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
|
||||
BAD_TRAP(0xfc) KGDB_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
|
||||
|
||||
#endif
|
||||
.align PAGE_SIZE
|
||||
|
164
arch/sparc/kernel/kgdb.c
Normal file
164
arch/sparc/kernel/kgdb.c
Normal file
@ -0,0 +1,164 @@
|
||||
/* kgdb.c: KGDB support for 32-bit sparc.
|
||||
*
|
||||
* Copyright (C) 2008 David S. Miller <davem@davemloft.net>
|
||||
*/
|
||||
|
||||
#include <linux/kgdb.h>
|
||||
#include <linux/kdebug.h>
|
||||
|
||||
#include <asm/kdebug.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
extern unsigned long trapbase;
|
||||
|
||||
void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
|
||||
{
|
||||
struct reg_window *win;
|
||||
int i;
|
||||
|
||||
gdb_regs[GDB_G0] = 0;
|
||||
for (i = 0; i < 15; i++)
|
||||
gdb_regs[GDB_G1 + i] = regs->u_regs[UREG_G1 + i];
|
||||
|
||||
win = (struct reg_window *) regs->u_regs[UREG_FP];
|
||||
for (i = 0; i < 8; i++)
|
||||
gdb_regs[GDB_L0 + i] = win->locals[i];
|
||||
for (i = 0; i < 8; i++)
|
||||
gdb_regs[GDB_I0 + i] = win->ins[i];
|
||||
|
||||
for (i = GDB_F0; i <= GDB_F31; i++)
|
||||
gdb_regs[i] = 0;
|
||||
|
||||
gdb_regs[GDB_Y] = regs->y;
|
||||
gdb_regs[GDB_PSR] = regs->psr;
|
||||
gdb_regs[GDB_WIM] = 0;
|
||||
gdb_regs[GDB_TBR] = (unsigned long) &trapbase;
|
||||
gdb_regs[GDB_PC] = regs->pc;
|
||||
gdb_regs[GDB_NPC] = regs->npc;
|
||||
gdb_regs[GDB_FSR] = 0;
|
||||
gdb_regs[GDB_CSR] = 0;
|
||||
}
|
||||
|
||||
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
|
||||
{
|
||||
struct thread_info *t = task_thread_info(p);
|
||||
struct reg_window *win;
|
||||
int i;
|
||||
|
||||
for (i = GDB_G0; i < GDB_G6; i++)
|
||||
gdb_regs[i] = 0;
|
||||
gdb_regs[GDB_G6] = (unsigned long) t;
|
||||
gdb_regs[GDB_G7] = 0;
|
||||
for (i = GDB_O0; i < GDB_SP; i++)
|
||||
gdb_regs[i] = 0;
|
||||
gdb_regs[GDB_SP] = t->ksp;
|
||||
gdb_regs[GDB_O7] = 0;
|
||||
|
||||
win = (struct reg_window *) t->ksp;
|
||||
for (i = 0; i < 8; i++)
|
||||
gdb_regs[GDB_L0 + i] = win->locals[i];
|
||||
for (i = 0; i < 8; i++)
|
||||
gdb_regs[GDB_I0 + i] = win->ins[i];
|
||||
|
||||
for (i = GDB_F0; i <= GDB_F31; i++)
|
||||
gdb_regs[i] = 0;
|
||||
|
||||
gdb_regs[GDB_Y] = 0;
|
||||
|
||||
gdb_regs[GDB_PSR] = t->kpsr;
|
||||
gdb_regs[GDB_WIM] = t->kwim;
|
||||
gdb_regs[GDB_TBR] = (unsigned long) &trapbase;
|
||||
gdb_regs[GDB_PC] = t->kpc;
|
||||
gdb_regs[GDB_NPC] = t->kpc + 4;
|
||||
gdb_regs[GDB_FSR] = 0;
|
||||
gdb_regs[GDB_CSR] = 0;
|
||||
}
|
||||
|
||||
void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
|
||||
{
|
||||
struct reg_window *win;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 15; i++)
|
||||
regs->u_regs[UREG_G1 + i] = gdb_regs[GDB_G1 + i];
|
||||
|
||||
/* If the PSR register is changing, we have to preserve
|
||||
* the CWP field, otherwise window save/restore explodes.
|
||||
*/
|
||||
if (regs->psr != gdb_regs[GDB_PSR]) {
|
||||
unsigned long cwp = regs->psr & PSR_CWP;
|
||||
|
||||
regs->psr = (gdb_regs[GDB_PSR] & ~PSR_CWP) | cwp;
|
||||
}
|
||||
|
||||
regs->pc = gdb_regs[GDB_PC];
|
||||
regs->npc = gdb_regs[GDB_NPC];
|
||||
regs->y = gdb_regs[GDB_Y];
|
||||
|
||||
win = (struct reg_window *) regs->u_regs[UREG_FP];
|
||||
for (i = 0; i < 8; i++)
|
||||
win->locals[i] = gdb_regs[GDB_L0 + i];
|
||||
for (i = 0; i < 8; i++)
|
||||
win->ins[i] = gdb_regs[GDB_I0 + i];
|
||||
}
|
||||
|
||||
int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
|
||||
char *remcomInBuffer, char *remcomOutBuffer,
|
||||
struct pt_regs *linux_regs)
|
||||
{
|
||||
unsigned long addr;
|
||||
char *ptr;
|
||||
|
||||
switch (remcomInBuffer[0]) {
|
||||
case 'c':
|
||||
/* try to read optional parameter, pc unchanged if no parm */
|
||||
ptr = &remcomInBuffer[1];
|
||||
if (kgdb_hex2long(&ptr, &addr)) {
|
||||
linux_regs->pc = addr;
|
||||
linux_regs->npc = addr + 4;
|
||||
}
|
||||
/* fallthru */
|
||||
|
||||
case 'D':
|
||||
case 'k':
|
||||
if (linux_regs->pc == (unsigned long) arch_kgdb_breakpoint) {
|
||||
linux_regs->pc = linux_regs->npc;
|
||||
linux_regs->npc += 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern void do_hw_interrupt(struct pt_regs *regs, unsigned long type);
|
||||
|
||||
asmlinkage void kgdb_trap(struct pt_regs *regs)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (user_mode(regs)) {
|
||||
do_hw_interrupt(regs, 0xfd);
|
||||
return;
|
||||
}
|
||||
|
||||
flushw_all();
|
||||
|
||||
local_irq_save(flags);
|
||||
kgdb_handle_exception(0x172, SIGTRAP, 0, regs);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
int kgdb_arch_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kgdb_arch_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
struct kgdb_arch arch_kgdb_ops = {
|
||||
/* Breakpoint instruction: ta 0x7d */
|
||||
.gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x7d },
|
||||
};
|
@ -1,724 +0,0 @@
|
||||
/* $Id: sparc-stub.c,v 1.28 2001/10/30 04:54:21 davem Exp $
|
||||
* sparc-stub.c: KGDB support for the Linux kernel.
|
||||
*
|
||||
* Modifications to run under Linux
|
||||
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
||||
*
|
||||
* This file originally came from the gdb sources, and the
|
||||
* copyright notices have been retained below.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
THIS SOFTWARE IS NOT COPYRIGHTED
|
||||
|
||||
HP offers the following for use in the public domain. HP makes no
|
||||
warranty with regard to the software or its performance and the
|
||||
user accepts the software "AS IS" with all faults.
|
||||
|
||||
HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
|
||||
*
|
||||
* Module name: remcom.c $
|
||||
* Revision: 1.34 $
|
||||
* Date: 91/03/09 12:29:49 $
|
||||
* Contributor: Lake Stevens Instrument Division$
|
||||
*
|
||||
* Description: low level support for gdb debugger. $
|
||||
*
|
||||
* Considerations: only works on target hardware $
|
||||
*
|
||||
* Written by: Glenn Engel $
|
||||
* ModuleState: Experimental $
|
||||
*
|
||||
* NOTES: See Below $
|
||||
*
|
||||
* Modified for SPARC by Stu Grossman, Cygnus Support.
|
||||
*
|
||||
* This code has been extensively tested on the Fujitsu SPARClite demo board.
|
||||
*
|
||||
* To enable debugger support, two things need to happen. One, a
|
||||
* call to set_debug_traps() is necessary in order to allow any breakpoints
|
||||
* or error conditions to be properly intercepted and reported to gdb.
|
||||
* Two, a breakpoint needs to be generated to begin communication. This
|
||||
* is most easily accomplished by a call to breakpoint(). Breakpoint()
|
||||
* simulates a breakpoint by executing a trap #1.
|
||||
*
|
||||
*************
|
||||
*
|
||||
* The following gdb commands are supported:
|
||||
*
|
||||
* command function Return value
|
||||
*
|
||||
* g return the value of the CPU registers hex data or ENN
|
||||
* G set the value of the CPU registers OK or ENN
|
||||
*
|
||||
* mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
|
||||
* MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
|
||||
*
|
||||
* c Resume at current address SNN ( signal NN)
|
||||
* cAA..AA Continue at address AA..AA SNN
|
||||
*
|
||||
* s Step one instruction SNN
|
||||
* sAA..AA Step one instruction from AA..AA SNN
|
||||
*
|
||||
* k kill
|
||||
*
|
||||
* ? What was the last sigval ? SNN (signal NN)
|
||||
*
|
||||
* bBB..BB Set baud rate to BB..BB OK or BNN, then sets
|
||||
* baud rate
|
||||
*
|
||||
* All commands and responses are sent with a packet which includes a
|
||||
* checksum. A packet consists of
|
||||
*
|
||||
* $<packet info>#<checksum>.
|
||||
*
|
||||
* where
|
||||
* <packet info> :: <characters representing the command or response>
|
||||
* <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
|
||||
*
|
||||
* When a packet is received, it is first acknowledged with either '+' or '-'.
|
||||
* '+' indicates a successful transfer. '-' indicates a failed transfer.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* Host: Reply:
|
||||
* $m0,10#2a +$00010203040506070809101112131415#42
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/smp_lock.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/signal.h>
|
||||
#include <asm/oplib.h>
|
||||
#include <asm/head.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/vac-ops.h>
|
||||
#include <asm/kgdb.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
/*
|
||||
*
|
||||
* external low-level support routines
|
||||
*/
|
||||
|
||||
extern void putDebugChar(char); /* write a single character */
|
||||
extern char getDebugChar(void); /* read and return a single char */
|
||||
|
||||
/*
|
||||
* BUFMAX defines the maximum number of characters in inbound/outbound buffers
|
||||
* at least NUMREGBYTES*2 are needed for register packets
|
||||
*/
|
||||
#define BUFMAX 2048
|
||||
|
||||
static int initialized; /* !0 means we've been initialized */
|
||||
|
||||
static const char hexchars[]="0123456789abcdef";
|
||||
|
||||
#define NUMREGS 72
|
||||
|
||||
/* Number of bytes of registers. */
|
||||
#define NUMREGBYTES (NUMREGS * 4)
|
||||
enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
|
||||
O0, O1, O2, O3, O4, O5, SP, O7,
|
||||
L0, L1, L2, L3, L4, L5, L6, L7,
|
||||
I0, I1, I2, I3, I4, I5, FP, I7,
|
||||
|
||||
F0, F1, F2, F3, F4, F5, F6, F7,
|
||||
F8, F9, F10, F11, F12, F13, F14, F15,
|
||||
F16, F17, F18, F19, F20, F21, F22, F23,
|
||||
F24, F25, F26, F27, F28, F29, F30, F31,
|
||||
Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR };
|
||||
|
||||
|
||||
extern void trap_low(void); /* In arch/sparc/kernel/entry.S */
|
||||
|
||||
unsigned long get_sun4cpte(unsigned long addr)
|
||||
{
|
||||
unsigned long entry;
|
||||
|
||||
__asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" :
|
||||
"=r" (entry) :
|
||||
"r" (addr), "i" (ASI_PTE));
|
||||
return entry;
|
||||
}
|
||||
|
||||
unsigned long get_sun4csegmap(unsigned long addr)
|
||||
{
|
||||
unsigned long entry;
|
||||
|
||||
__asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" :
|
||||
"=r" (entry) :
|
||||
"r" (addr), "i" (ASI_SEGMAP));
|
||||
return entry;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Have to sort this out. This cannot be done after initialization. */
|
||||
static void flush_cache_all_nop(void) {}
|
||||
#endif
|
||||
|
||||
/* Place where we save old trap entries for restoration */
|
||||
struct tt_entry kgdb_savettable[256];
|
||||
typedef void (*trapfunc_t)(void);
|
||||
|
||||
/* Helper routine for manipulation of kgdb_savettable */
|
||||
static inline void copy_ttentry(struct tt_entry *src, struct tt_entry *dest)
|
||||
{
|
||||
dest->inst_one = src->inst_one;
|
||||
dest->inst_two = src->inst_two;
|
||||
dest->inst_three = src->inst_three;
|
||||
dest->inst_four = src->inst_four;
|
||||
}
|
||||
|
||||
/* Initialize the kgdb_savettable so that debugging can commence */
|
||||
static void eh_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i < 256; i++)
|
||||
copy_ttentry(&sparc_ttable[i], &kgdb_savettable[i]);
|
||||
}
|
||||
|
||||
/* Install an exception handler for kgdb */
|
||||
static void exceptionHandler(int tnum, trapfunc_t trap_entry)
|
||||
{
|
||||
unsigned long te_addr = (unsigned long) trap_entry;
|
||||
|
||||
/* Make new vector */
|
||||
sparc_ttable[tnum].inst_one =
|
||||
SPARC_BRANCH((unsigned long) te_addr,
|
||||
(unsigned long) &sparc_ttable[tnum].inst_one);
|
||||
sparc_ttable[tnum].inst_two = SPARC_RD_PSR_L0;
|
||||
sparc_ttable[tnum].inst_three = SPARC_NOP;
|
||||
sparc_ttable[tnum].inst_four = SPARC_NOP;
|
||||
}
|
||||
|
||||
/* Convert ch from a hex digit to an int */
|
||||
static int
|
||||
hex(unsigned char ch)
|
||||
{
|
||||
if (ch >= 'a' && ch <= 'f')
|
||||
return ch-'a'+10;
|
||||
if (ch >= '0' && ch <= '9')
|
||||
return ch-'0';
|
||||
if (ch >= 'A' && ch <= 'F')
|
||||
return ch-'A'+10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* scan for the sequence $<data>#<checksum> */
|
||||
static void
|
||||
getpacket(char *buffer)
|
||||
{
|
||||
unsigned char checksum;
|
||||
unsigned char xmitcsum;
|
||||
int i;
|
||||
int count;
|
||||
unsigned char ch;
|
||||
|
||||
do {
|
||||
/* wait around for the start character, ignore all other characters */
|
||||
while ((ch = (getDebugChar() & 0x7f)) != '$') ;
|
||||
|
||||
checksum = 0;
|
||||
xmitcsum = -1;
|
||||
|
||||
count = 0;
|
||||
|
||||
/* now, read until a # or end of buffer is found */
|
||||
while (count < BUFMAX) {
|
||||
ch = getDebugChar() & 0x7f;
|
||||
if (ch == '#')
|
||||
break;
|
||||
checksum = checksum + ch;
|
||||
buffer[count] = ch;
|
||||
count = count + 1;
|
||||
}
|
||||
|
||||
if (count >= BUFMAX)
|
||||
continue;
|
||||
|
||||
buffer[count] = 0;
|
||||
|
||||
if (ch == '#') {
|
||||
xmitcsum = hex(getDebugChar() & 0x7f) << 4;
|
||||
xmitcsum |= hex(getDebugChar() & 0x7f);
|
||||
if (checksum != xmitcsum)
|
||||
putDebugChar('-'); /* failed checksum */
|
||||
else {
|
||||
putDebugChar('+'); /* successful transfer */
|
||||
/* if a sequence char is present, reply the ID */
|
||||
if (buffer[2] == ':') {
|
||||
putDebugChar(buffer[0]);
|
||||
putDebugChar(buffer[1]);
|
||||
/* remove sequence chars from buffer */
|
||||
count = strlen(buffer);
|
||||
for (i=3; i <= count; i++)
|
||||
buffer[i-3] = buffer[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (checksum != xmitcsum);
|
||||
}
|
||||
|
||||
/* send the packet in buffer. */
|
||||
|
||||
static void
|
||||
putpacket(unsigned char *buffer)
|
||||
{
|
||||
unsigned char checksum;
|
||||
int count;
|
||||
unsigned char ch, recv;
|
||||
|
||||
/* $<packet info>#<checksum>. */
|
||||
do {
|
||||
putDebugChar('$');
|
||||
checksum = 0;
|
||||
count = 0;
|
||||
|
||||
while ((ch = buffer[count])) {
|
||||
putDebugChar(ch);
|
||||
checksum += ch;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
putDebugChar('#');
|
||||
putDebugChar(hexchars[checksum >> 4]);
|
||||
putDebugChar(hexchars[checksum & 0xf]);
|
||||
recv = getDebugChar();
|
||||
} while ((recv & 0x7f) != '+');
|
||||
}
|
||||
|
||||
static char remcomInBuffer[BUFMAX];
|
||||
static char remcomOutBuffer[BUFMAX];
|
||||
|
||||
/* Convert the memory pointed to by mem into hex, placing result in buf.
|
||||
* Return a pointer to the last char put in buf (null), in case of mem fault,
|
||||
* return 0.
|
||||
*/
|
||||
|
||||
static unsigned char *
|
||||
mem2hex(char *mem, char *buf, int count)
|
||||
{
|
||||
unsigned char ch;
|
||||
|
||||
while (count-- > 0) {
|
||||
/* This assembler code is basically: ch = *mem++;
|
||||
* except that we use the SPARC/Linux exception table
|
||||
* mechanism (see how "fixup" works in kernel_mna_trap_fault)
|
||||
* to arrange for a "return 0" upon a memory fault
|
||||
*/
|
||||
__asm__(
|
||||
"\n1:\n\t"
|
||||
"ldub [%0], %1\n\t"
|
||||
"inc %0\n\t"
|
||||
".section .fixup,#alloc,#execinstr\n\t"
|
||||
".align 4\n"
|
||||
"2:\n\t"
|
||||
"retl\n\t"
|
||||
" mov 0, %%o0\n\t"
|
||||
".section __ex_table, #alloc\n\t"
|
||||
".align 4\n\t"
|
||||
".word 1b, 2b\n\t"
|
||||
".text\n"
|
||||
: "=r" (mem), "=r" (ch) : "0" (mem));
|
||||
*buf++ = hexchars[ch >> 4];
|
||||
*buf++ = hexchars[ch & 0xf];
|
||||
}
|
||||
|
||||
*buf = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* convert the hex array pointed to by buf into binary to be placed in mem
|
||||
* return a pointer to the character AFTER the last byte written.
|
||||
*/
|
||||
static char *
|
||||
hex2mem(char *buf, char *mem, int count)
|
||||
{
|
||||
int i;
|
||||
unsigned char ch;
|
||||
|
||||
for (i=0; i<count; i++) {
|
||||
|
||||
ch = hex(*buf++) << 4;
|
||||
ch |= hex(*buf++);
|
||||
/* Assembler code is *mem++ = ch; with return 0 on fault */
|
||||
__asm__(
|
||||
"\n1:\n\t"
|
||||
"stb %1, [%0]\n\t"
|
||||
"inc %0\n\t"
|
||||
".section .fixup,#alloc,#execinstr\n\t"
|
||||
".align 4\n"
|
||||
"2:\n\t"
|
||||
"retl\n\t"
|
||||
" mov 0, %%o0\n\t"
|
||||
".section __ex_table, #alloc\n\t"
|
||||
".align 4\n\t"
|
||||
".word 1b, 2b\n\t"
|
||||
".text\n"
|
||||
: "=r" (mem) : "r" (ch) , "0" (mem));
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
/* This table contains the mapping between SPARC hardware trap types, and
|
||||
signals, which are primarily what GDB understands. It also indicates
|
||||
which hardware traps we need to commandeer when initializing the stub. */
|
||||
|
||||
static struct hard_trap_info
|
||||
{
|
||||
unsigned char tt; /* Trap type code for SPARC */
|
||||
unsigned char signo; /* Signal that we map this trap into */
|
||||
} hard_trap_info[] = {
|
||||
{SP_TRAP_SBPT, SIGTRAP}, /* ta 1 - Linux/KGDB software breakpoint */
|
||||
{0, 0} /* Must be last */
|
||||
};
|
||||
|
||||
/* Set up exception handlers for tracing and breakpoints */
|
||||
|
||||
void
|
||||
set_debug_traps(void)
|
||||
{
|
||||
struct hard_trap_info *ht;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
#if 0
|
||||
/* Have to sort this out. This cannot be done after initialization. */
|
||||
BTFIXUPSET_CALL(flush_cache_all, flush_cache_all_nop, BTFIXUPCALL_NOP);
|
||||
#endif
|
||||
|
||||
/* Initialize our copy of the Linux Sparc trap table */
|
||||
eh_init();
|
||||
|
||||
for (ht = hard_trap_info; ht->tt && ht->signo; ht++) {
|
||||
/* Only if it doesn't destroy our fault handlers */
|
||||
if((ht->tt != SP_TRAP_TFLT) &&
|
||||
(ht->tt != SP_TRAP_DFLT))
|
||||
exceptionHandler(ht->tt, trap_low);
|
||||
}
|
||||
|
||||
/* In case GDB is started before us, ack any packets (presumably
|
||||
* "$?#xx") sitting there.
|
||||
*
|
||||
* I've found this code causes more problems than it solves,
|
||||
* so that's why it's commented out. GDB seems to work fine
|
||||
* now starting either before or after the kernel -bwb
|
||||
*/
|
||||
#if 0
|
||||
while((c = getDebugChar()) != '$');
|
||||
while((c = getDebugChar()) != '#');
|
||||
c = getDebugChar(); /* eat first csum byte */
|
||||
c = getDebugChar(); /* eat second csum byte */
|
||||
putDebugChar('+'); /* ack it */
|
||||
#endif
|
||||
|
||||
initialized = 1; /* connect! */
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/* Convert the SPARC hardware trap type code to a unix signal number. */
|
||||
|
||||
static int
|
||||
computeSignal(int tt)
|
||||
{
|
||||
struct hard_trap_info *ht;
|
||||
|
||||
for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
|
||||
if (ht->tt == tt)
|
||||
return ht->signo;
|
||||
|
||||
return SIGHUP; /* default for things we don't know about */
|
||||
}
|
||||
|
||||
/*
|
||||
* While we find nice hex chars, build an int.
|
||||
* Return number of chars processed.
|
||||
*/
|
||||
|
||||
static int
|
||||
hexToInt(char **ptr, int *intValue)
|
||||
{
|
||||
int numChars = 0;
|
||||
int hexValue;
|
||||
|
||||
*intValue = 0;
|
||||
|
||||
while (**ptr) {
|
||||
hexValue = hex(**ptr);
|
||||
if (hexValue < 0)
|
||||
break;
|
||||
|
||||
*intValue = (*intValue << 4) | hexValue;
|
||||
numChars ++;
|
||||
|
||||
(*ptr)++;
|
||||
}
|
||||
|
||||
return (numChars);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function does all command processing for interfacing to gdb. It
|
||||
* returns 1 if you should skip the instruction at the trap address, 0
|
||||
* otherwise.
|
||||
*/
|
||||
|
||||
extern void breakinst(void);
|
||||
|
||||
void
|
||||
handle_exception (unsigned long *registers)
|
||||
{
|
||||
int tt; /* Trap type */
|
||||
int sigval;
|
||||
int addr;
|
||||
int length;
|
||||
char *ptr;
|
||||
unsigned long *sp;
|
||||
|
||||
/* First, we must force all of the windows to be spilled out */
|
||||
|
||||
asm("save %sp, -64, %sp\n\t"
|
||||
"save %sp, -64, %sp\n\t"
|
||||
"save %sp, -64, %sp\n\t"
|
||||
"save %sp, -64, %sp\n\t"
|
||||
"save %sp, -64, %sp\n\t"
|
||||
"save %sp, -64, %sp\n\t"
|
||||
"save %sp, -64, %sp\n\t"
|
||||
"save %sp, -64, %sp\n\t"
|
||||
"restore\n\t"
|
||||
"restore\n\t"
|
||||
"restore\n\t"
|
||||
"restore\n\t"
|
||||
"restore\n\t"
|
||||
"restore\n\t"
|
||||
"restore\n\t"
|
||||
"restore\n\t");
|
||||
|
||||
lock_kernel();
|
||||
if (registers[PC] == (unsigned long)breakinst) {
|
||||
/* Skip over breakpoint trap insn */
|
||||
registers[PC] = registers[NPC];
|
||||
registers[NPC] += 4;
|
||||
}
|
||||
|
||||
sp = (unsigned long *)registers[SP];
|
||||
|
||||
tt = (registers[TBR] >> 4) & 0xff;
|
||||
|
||||
/* reply to host that an exception has occurred */
|
||||
sigval = computeSignal(tt);
|
||||
ptr = remcomOutBuffer;
|
||||
|
||||
*ptr++ = 'T';
|
||||
*ptr++ = hexchars[sigval >> 4];
|
||||
*ptr++ = hexchars[sigval & 0xf];
|
||||
|
||||
*ptr++ = hexchars[PC >> 4];
|
||||
*ptr++ = hexchars[PC & 0xf];
|
||||
*ptr++ = ':';
|
||||
ptr = mem2hex((char *)®isters[PC], ptr, 4);
|
||||
*ptr++ = ';';
|
||||
|
||||
*ptr++ = hexchars[FP >> 4];
|
||||
*ptr++ = hexchars[FP & 0xf];
|
||||
*ptr++ = ':';
|
||||
ptr = mem2hex((char *) (sp + 8 + 6), ptr, 4); /* FP */
|
||||
*ptr++ = ';';
|
||||
|
||||
*ptr++ = hexchars[SP >> 4];
|
||||
*ptr++ = hexchars[SP & 0xf];
|
||||
*ptr++ = ':';
|
||||
ptr = mem2hex((char *)&sp, ptr, 4);
|
||||
*ptr++ = ';';
|
||||
|
||||
*ptr++ = hexchars[NPC >> 4];
|
||||
*ptr++ = hexchars[NPC & 0xf];
|
||||
*ptr++ = ':';
|
||||
ptr = mem2hex((char *)®isters[NPC], ptr, 4);
|
||||
*ptr++ = ';';
|
||||
|
||||
*ptr++ = hexchars[O7 >> 4];
|
||||
*ptr++ = hexchars[O7 & 0xf];
|
||||
*ptr++ = ':';
|
||||
ptr = mem2hex((char *)®isters[O7], ptr, 4);
|
||||
*ptr++ = ';';
|
||||
|
||||
*ptr++ = 0;
|
||||
|
||||
putpacket(remcomOutBuffer);
|
||||
|
||||
/* XXX We may want to add some features dealing with poking the
|
||||
* XXX page tables, the real ones on the srmmu, and what is currently
|
||||
* XXX loaded in the sun4/sun4c tlb at this point in time. But this
|
||||
* XXX also required hacking to the gdb sources directly...
|
||||
*/
|
||||
|
||||
while (1) {
|
||||
remcomOutBuffer[0] = 0;
|
||||
|
||||
getpacket(remcomInBuffer);
|
||||
switch (remcomInBuffer[0]) {
|
||||
case '?':
|
||||
remcomOutBuffer[0] = 'S';
|
||||
remcomOutBuffer[1] = hexchars[sigval >> 4];
|
||||
remcomOutBuffer[2] = hexchars[sigval & 0xf];
|
||||
remcomOutBuffer[3] = 0;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
/* toggle debug flag */
|
||||
break;
|
||||
|
||||
case 'g': /* return the value of the CPU registers */
|
||||
{
|
||||
ptr = remcomOutBuffer;
|
||||
/* G & O regs */
|
||||
ptr = mem2hex((char *)registers, ptr, 16 * 4);
|
||||
/* L & I regs */
|
||||
ptr = mem2hex((char *) (sp + 0), ptr, 16 * 4);
|
||||
/* Floating point */
|
||||
memset(ptr, '0', 32 * 8);
|
||||
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
|
||||
mem2hex((char *)®isters[Y], (ptr + 32 * 4 * 2), (8 * 4));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'G': /* set the value of the CPU registers - return OK */
|
||||
{
|
||||
unsigned long *newsp, psr;
|
||||
|
||||
psr = registers[PSR];
|
||||
|
||||
ptr = &remcomInBuffer[1];
|
||||
/* G & O regs */
|
||||
hex2mem(ptr, (char *)registers, 16 * 4);
|
||||
/* L & I regs */
|
||||
hex2mem(ptr + 16 * 4 * 2, (char *) (sp + 0), 16 * 4);
|
||||
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
|
||||
hex2mem(ptr + 64 * 4 * 2, (char *)®isters[Y], 8 * 4);
|
||||
|
||||
/* See if the stack pointer has moved. If so,
|
||||
* then copy the saved locals and ins to the
|
||||
* new location. This keeps the window
|
||||
* overflow and underflow routines happy.
|
||||
*/
|
||||
|
||||
newsp = (unsigned long *)registers[SP];
|
||||
if (sp != newsp)
|
||||
sp = memcpy(newsp, sp, 16 * 4);
|
||||
|
||||
/* Don't allow CWP to be modified. */
|
||||
|
||||
if (psr != registers[PSR])
|
||||
registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
|
||||
|
||||
strcpy(remcomOutBuffer,"OK");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
|
||||
/* Try to read %x,%x. */
|
||||
|
||||
ptr = &remcomInBuffer[1];
|
||||
|
||||
if (hexToInt(&ptr, &addr)
|
||||
&& *ptr++ == ','
|
||||
&& hexToInt(&ptr, &length)) {
|
||||
if (mem2hex((char *)addr, remcomOutBuffer, length))
|
||||
break;
|
||||
|
||||
strcpy (remcomOutBuffer, "E03");
|
||||
} else {
|
||||
strcpy(remcomOutBuffer,"E01");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
|
||||
/* Try to read '%x,%x:'. */
|
||||
|
||||
ptr = &remcomInBuffer[1];
|
||||
|
||||
if (hexToInt(&ptr, &addr)
|
||||
&& *ptr++ == ','
|
||||
&& hexToInt(&ptr, &length)
|
||||
&& *ptr++ == ':') {
|
||||
if (hex2mem(ptr, (char *)addr, length)) {
|
||||
strcpy(remcomOutBuffer, "OK");
|
||||
} else {
|
||||
strcpy(remcomOutBuffer, "E03");
|
||||
}
|
||||
} else {
|
||||
strcpy(remcomOutBuffer, "E02");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c': /* cAA..AA Continue at address AA..AA(optional) */
|
||||
/* try to read optional parameter, pc unchanged if no parm */
|
||||
|
||||
ptr = &remcomInBuffer[1];
|
||||
if (hexToInt(&ptr, &addr)) {
|
||||
registers[PC] = addr;
|
||||
registers[NPC] = addr + 4;
|
||||
}
|
||||
|
||||
/* Need to flush the instruction cache here, as we may have deposited a
|
||||
* breakpoint, and the icache probably has no way of knowing that a data ref to
|
||||
* some location may have changed something that is in the instruction cache.
|
||||
*/
|
||||
flush_cache_all();
|
||||
unlock_kernel();
|
||||
return;
|
||||
|
||||
/* kill the program */
|
||||
case 'k' : /* do nothing */
|
||||
break;
|
||||
case 'r': /* Reset */
|
||||
asm ("call 0\n\t"
|
||||
"nop\n\t");
|
||||
break;
|
||||
} /* switch */
|
||||
|
||||
/* reply to the request */
|
||||
putpacket(remcomOutBuffer);
|
||||
} /* while(1) */
|
||||
}
|
||||
|
||||
/* This function will generate a breakpoint exception. It is used at the
|
||||
beginning of a program to sync up with a debugger and can be used
|
||||
otherwise as a quick means to stop program execution and "break" into
|
||||
the debugger. */
|
||||
|
||||
void
|
||||
breakpoint(void)
|
||||
{
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
/* Again, watch those c-prefixes for ELF kernels */
|
||||
#if defined(__svr4__) || defined(__ELF__)
|
||||
asm(".globl breakinst\n"
|
||||
"breakinst:\n\t"
|
||||
"ta 1\n");
|
||||
#else
|
||||
asm(".globl _breakinst\n"
|
||||
"_breakinst:\n\t"
|
||||
"ta 1\n");
|
||||
#endif
|
||||
}
|
@ -335,37 +335,6 @@ void smp4d_cross_call_irq(void)
|
||||
ccall_info.processors_out[i] = 1;
|
||||
}
|
||||
|
||||
static int smp4d_stop_cpu_sender;
|
||||
|
||||
static void smp4d_stop_cpu(void)
|
||||
{
|
||||
int me = hard_smp4d_processor_id();
|
||||
|
||||
if (me != smp4d_stop_cpu_sender)
|
||||
while(1) barrier();
|
||||
}
|
||||
|
||||
/* Cross calls, in order to work efficiently and atomically do all
|
||||
* the message passing work themselves, only stopcpu and reschedule
|
||||
* messages come through here.
|
||||
*/
|
||||
void smp4d_message_pass(int target, int msg, unsigned long data, int wait)
|
||||
{
|
||||
int me = hard_smp4d_processor_id();
|
||||
|
||||
SMP_PRINTK(("smp4d_message_pass %d %d %08lx %d\n", target, msg, data, wait));
|
||||
if (msg == MSG_STOP_CPU && target == MSG_ALL_BUT_SELF) {
|
||||
unsigned long flags;
|
||||
static DEFINE_SPINLOCK(stop_cpu_lock);
|
||||
spin_lock_irqsave(&stop_cpu_lock, flags);
|
||||
smp4d_stop_cpu_sender = me;
|
||||
smp4d_cross_call((smpfunc_t)smp4d_stop_cpu, 0, 0, 0, 0, 0);
|
||||
spin_unlock_irqrestore(&stop_cpu_lock, flags);
|
||||
}
|
||||
printk("Yeeee, trying to send SMP msg(%d) to %d on cpu %d\n", msg, target, me);
|
||||
panic("Bogon SMP message pass.");
|
||||
}
|
||||
|
||||
void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs;
|
||||
@ -439,7 +408,6 @@ void __init sun4d_init_smp(void)
|
||||
BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id);
|
||||
BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current);
|
||||
BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM);
|
||||
BTFIXUPSET_CALL(smp_message_pass, smp4d_message_pass, BTFIXUPCALL_NORM);
|
||||
BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM);
|
||||
|
||||
for (i = 0; i < NR_CPUS; i++) {
|
||||
|
@ -34,8 +34,6 @@
|
||||
|
||||
#include "irq.h"
|
||||
|
||||
#define IRQ_RESCHEDULE 13
|
||||
#define IRQ_STOP_CPU 14
|
||||
#define IRQ_CROSS_CALL 15
|
||||
|
||||
extern ctxd_t *srmmu_ctx_table_phys;
|
||||
@ -232,48 +230,6 @@ void smp4m_irq_rotate(int cpu)
|
||||
set_irq_udt(next);
|
||||
}
|
||||
|
||||
/* Cross calls, in order to work efficiently and atomically do all
|
||||
* the message passing work themselves, only stopcpu and reschedule
|
||||
* messages come through here.
|
||||
*/
|
||||
void smp4m_message_pass(int target, int msg, unsigned long data, int wait)
|
||||
{
|
||||
static unsigned long smp_cpu_in_msg[NR_CPUS];
|
||||
cpumask_t mask;
|
||||
int me = smp_processor_id();
|
||||
int irq, i;
|
||||
|
||||
if(msg == MSG_RESCHEDULE) {
|
||||
irq = IRQ_RESCHEDULE;
|
||||
|
||||
if(smp_cpu_in_msg[me])
|
||||
return;
|
||||
} else if(msg == MSG_STOP_CPU) {
|
||||
irq = IRQ_STOP_CPU;
|
||||
} else {
|
||||
goto barf;
|
||||
}
|
||||
|
||||
smp_cpu_in_msg[me]++;
|
||||
if(target == MSG_ALL_BUT_SELF || target == MSG_ALL) {
|
||||
mask = cpu_online_map;
|
||||
if(target == MSG_ALL_BUT_SELF)
|
||||
cpu_clear(me, mask);
|
||||
for(i = 0; i < 4; i++) {
|
||||
if (cpu_isset(i, mask))
|
||||
set_cpu_int(i, irq);
|
||||
}
|
||||
} else {
|
||||
set_cpu_int(target, irq);
|
||||
}
|
||||
smp_cpu_in_msg[me]--;
|
||||
|
||||
return;
|
||||
barf:
|
||||
printk("Yeeee, trying to send SMP msg(%d) on cpu %d\n", msg, me);
|
||||
panic("Bogon SMP message pass.");
|
||||
}
|
||||
|
||||
static struct smp_funcall {
|
||||
smpfunc_t func;
|
||||
unsigned long arg1;
|
||||
@ -413,6 +369,5 @@ void __init sun4m_init_smp(void)
|
||||
BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4m_blackbox_id);
|
||||
BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current);
|
||||
BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM);
|
||||
BTFIXUPSET_CALL(smp_message_pass, smp4m_message_pass, BTFIXUPCALL_NORM);
|
||||
BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM);
|
||||
}
|
||||
|
Reference in New Issue
Block a user