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:
commit
7cece14acd
36 changed files with 3222 additions and 3623 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ config SPARC64
|
|||
default y
|
||||
select HAVE_IDE
|
||||
select HAVE_LMB
|
||||
select HAVE_ARCH_KGDB
|
||||
|
||||
config GENERIC_TIME
|
||||
bool
|
||||
|
|
|
@ -29,3 +29,4 @@ obj-$(CONFIG_SUN_LDOMS) += ldc.o vio.o viohs.o ds.o
|
|||
obj-$(CONFIG_AUDIT) += audit.o
|
||||
obj-$(CONFIG_AUDIT)$(CONFIG_COMPAT) += compat_audit.o
|
||||
obj-y += $(obj-yy)
|
||||
obj-$(CONFIG_KGDB) += kgdb.o
|
||||
|
|
579
arch/sparc64/kernel/cherrs.S
Normal file
579
arch/sparc64/kernel/cherrs.S
Normal file
|
@ -0,0 +1,579 @@
|
|||
/* These get patched into the trap table at boot time
|
||||
* once we know we have a cheetah processor.
|
||||
*/
|
||||
.globl cheetah_fecc_trap_vector
|
||||
.type cheetah_fecc_trap_vector,#function
|
||||
cheetah_fecc_trap_vector:
|
||||
membar #Sync
|
||||
ldxa [%g0] ASI_DCU_CONTROL_REG, %g1
|
||||
andn %g1, DCU_DC | DCU_IC, %g1
|
||||
stxa %g1, [%g0] ASI_DCU_CONTROL_REG
|
||||
membar #Sync
|
||||
sethi %hi(cheetah_fast_ecc), %g2
|
||||
jmpl %g2 + %lo(cheetah_fast_ecc), %g0
|
||||
mov 0, %g1
|
||||
.size cheetah_fecc_trap_vector,.-cheetah_fecc_trap_vector
|
||||
|
||||
.globl cheetah_fecc_trap_vector_tl1
|
||||
.type cheetah_fecc_trap_vector_tl1,#function
|
||||
cheetah_fecc_trap_vector_tl1:
|
||||
membar #Sync
|
||||
ldxa [%g0] ASI_DCU_CONTROL_REG, %g1
|
||||
andn %g1, DCU_DC | DCU_IC, %g1
|
||||
stxa %g1, [%g0] ASI_DCU_CONTROL_REG
|
||||
membar #Sync
|
||||
sethi %hi(cheetah_fast_ecc), %g2
|
||||
jmpl %g2 + %lo(cheetah_fast_ecc), %g0
|
||||
mov 1, %g1
|
||||
.size cheetah_fecc_trap_vector_tl1,.-cheetah_fecc_trap_vector_tl1
|
||||
|
||||
.globl cheetah_cee_trap_vector
|
||||
.type cheetah_cee_trap_vector,#function
|
||||
cheetah_cee_trap_vector:
|
||||
membar #Sync
|
||||
ldxa [%g0] ASI_DCU_CONTROL_REG, %g1
|
||||
andn %g1, DCU_IC, %g1
|
||||
stxa %g1, [%g0] ASI_DCU_CONTROL_REG
|
||||
membar #Sync
|
||||
sethi %hi(cheetah_cee), %g2
|
||||
jmpl %g2 + %lo(cheetah_cee), %g0
|
||||
mov 0, %g1
|
||||
.size cheetah_cee_trap_vector,.-cheetah_cee_trap_vector
|
||||
|
||||
.globl cheetah_cee_trap_vector_tl1
|
||||
.type cheetah_cee_trap_vector_tl1,#function
|
||||
cheetah_cee_trap_vector_tl1:
|
||||
membar #Sync
|
||||
ldxa [%g0] ASI_DCU_CONTROL_REG, %g1
|
||||
andn %g1, DCU_IC, %g1
|
||||
stxa %g1, [%g0] ASI_DCU_CONTROL_REG
|
||||
membar #Sync
|
||||
sethi %hi(cheetah_cee), %g2
|
||||
jmpl %g2 + %lo(cheetah_cee), %g0
|
||||
mov 1, %g1
|
||||
.size cheetah_cee_trap_vector_tl1,.-cheetah_cee_trap_vector_tl1
|
||||
|
||||
.globl cheetah_deferred_trap_vector
|
||||
.type cheetah_deferred_trap_vector,#function
|
||||
cheetah_deferred_trap_vector:
|
||||
membar #Sync
|
||||
ldxa [%g0] ASI_DCU_CONTROL_REG, %g1;
|
||||
andn %g1, DCU_DC | DCU_IC, %g1;
|
||||
stxa %g1, [%g0] ASI_DCU_CONTROL_REG;
|
||||
membar #Sync;
|
||||
sethi %hi(cheetah_deferred_trap), %g2
|
||||
jmpl %g2 + %lo(cheetah_deferred_trap), %g0
|
||||
mov 0, %g1
|
||||
.size cheetah_deferred_trap_vector,.-cheetah_deferred_trap_vector
|
||||
|
||||
.globl cheetah_deferred_trap_vector_tl1
|
||||
.type cheetah_deferred_trap_vector_tl1,#function
|
||||
cheetah_deferred_trap_vector_tl1:
|
||||
membar #Sync;
|
||||
ldxa [%g0] ASI_DCU_CONTROL_REG, %g1;
|
||||
andn %g1, DCU_DC | DCU_IC, %g1;
|
||||
stxa %g1, [%g0] ASI_DCU_CONTROL_REG;
|
||||
membar #Sync;
|
||||
sethi %hi(cheetah_deferred_trap), %g2
|
||||
jmpl %g2 + %lo(cheetah_deferred_trap), %g0
|
||||
mov 1, %g1
|
||||
.size cheetah_deferred_trap_vector_tl1,.-cheetah_deferred_trap_vector_tl1
|
||||
|
||||
/* Cheetah+ specific traps. These are for the new I/D cache parity
|
||||
* error traps. The first argument to cheetah_plus_parity_handler
|
||||
* is encoded as follows:
|
||||
*
|
||||
* Bit0: 0=dcache,1=icache
|
||||
* Bit1: 0=recoverable,1=unrecoverable
|
||||
*/
|
||||
.globl cheetah_plus_dcpe_trap_vector
|
||||
.type cheetah_plus_dcpe_trap_vector,#function
|
||||
cheetah_plus_dcpe_trap_vector:
|
||||
membar #Sync
|
||||
sethi %hi(do_cheetah_plus_data_parity), %g7
|
||||
jmpl %g7 + %lo(do_cheetah_plus_data_parity), %g0
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
.size cheetah_plus_dcpe_trap_vector,.-cheetah_plus_dcpe_trap_vector
|
||||
|
||||
.type do_cheetah_plus_data_parity,#function
|
||||
do_cheetah_plus_data_parity:
|
||||
rdpr %pil, %g2
|
||||
wrpr %g0, 15, %pil
|
||||
ba,pt %xcc, etrap_irq
|
||||
rd %pc, %g7
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
call trace_hardirqs_off
|
||||
nop
|
||||
#endif
|
||||
mov 0x0, %o0
|
||||
call cheetah_plus_parity_error
|
||||
add %sp, PTREGS_OFF, %o1
|
||||
ba,a,pt %xcc, rtrap_irq
|
||||
.size do_cheetah_plus_data_parity,.-do_cheetah_plus_data_parity
|
||||
|
||||
.globl cheetah_plus_dcpe_trap_vector_tl1
|
||||
.type cheetah_plus_dcpe_trap_vector_tl1,#function
|
||||
cheetah_plus_dcpe_trap_vector_tl1:
|
||||
membar #Sync
|
||||
wrpr PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate
|
||||
sethi %hi(do_dcpe_tl1), %g3
|
||||
jmpl %g3 + %lo(do_dcpe_tl1), %g0
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
.size cheetah_plus_dcpe_trap_vector_tl1,.-cheetah_plus_dcpe_trap_vector_tl1
|
||||
|
||||
.globl cheetah_plus_icpe_trap_vector
|
||||
.type cheetah_plus_icpe_trap_vector,#function
|
||||
cheetah_plus_icpe_trap_vector:
|
||||
membar #Sync
|
||||
sethi %hi(do_cheetah_plus_insn_parity), %g7
|
||||
jmpl %g7 + %lo(do_cheetah_plus_insn_parity), %g0
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
.size cheetah_plus_icpe_trap_vector,.-cheetah_plus_icpe_trap_vector
|
||||
|
||||
.type do_cheetah_plus_insn_parity,#function
|
||||
do_cheetah_plus_insn_parity:
|
||||
rdpr %pil, %g2
|
||||
wrpr %g0, 15, %pil
|
||||
ba,pt %xcc, etrap_irq
|
||||
rd %pc, %g7
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
call trace_hardirqs_off
|
||||
nop
|
||||
#endif
|
||||
mov 0x1, %o0
|
||||
call cheetah_plus_parity_error
|
||||
add %sp, PTREGS_OFF, %o1
|
||||
ba,a,pt %xcc, rtrap_irq
|
||||
.size do_cheetah_plus_insn_parity,.-do_cheetah_plus_insn_parity
|
||||
|
||||
.globl cheetah_plus_icpe_trap_vector_tl1
|
||||
.type cheetah_plus_icpe_trap_vector_tl1,#function
|
||||
cheetah_plus_icpe_trap_vector_tl1:
|
||||
membar #Sync
|
||||
wrpr PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate
|
||||
sethi %hi(do_icpe_tl1), %g3
|
||||
jmpl %g3 + %lo(do_icpe_tl1), %g0
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
.size cheetah_plus_icpe_trap_vector_tl1,.-cheetah_plus_icpe_trap_vector_tl1
|
||||
|
||||
/* If we take one of these traps when tl >= 1, then we
|
||||
* jump to interrupt globals. If some trap level above us
|
||||
* was also using interrupt globals, we cannot recover.
|
||||
* We may use all interrupt global registers except %g6.
|
||||
*/
|
||||
.globl do_dcpe_tl1
|
||||
.type do_dcpe_tl1,#function
|
||||
do_dcpe_tl1:
|
||||
rdpr %tl, %g1 ! Save original trap level
|
||||
mov 1, %g2 ! Setup TSTATE checking loop
|
||||
sethi %hi(TSTATE_IG), %g3 ! TSTATE mask bit
|
||||
1: wrpr %g2, %tl ! Set trap level to check
|
||||
rdpr %tstate, %g4 ! Read TSTATE for this level
|
||||
andcc %g4, %g3, %g0 ! Interrupt globals in use?
|
||||
bne,a,pn %xcc, do_dcpe_tl1_fatal ! Yep, irrecoverable
|
||||
wrpr %g1, %tl ! Restore original trap level
|
||||
add %g2, 1, %g2 ! Next trap level
|
||||
cmp %g2, %g1 ! Hit them all yet?
|
||||
ble,pt %icc, 1b ! Not yet
|
||||
nop
|
||||
wrpr %g1, %tl ! Restore original trap level
|
||||
do_dcpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */
|
||||
sethi %hi(dcache_parity_tl1_occurred), %g2
|
||||
lduw [%g2 + %lo(dcache_parity_tl1_occurred)], %g1
|
||||
add %g1, 1, %g1
|
||||
stw %g1, [%g2 + %lo(dcache_parity_tl1_occurred)]
|
||||
/* Reset D-cache parity */
|
||||
sethi %hi(1 << 16), %g1 ! D-cache size
|
||||
mov (1 << 5), %g2 ! D-cache line size
|
||||
sub %g1, %g2, %g1 ! Move down 1 cacheline
|
||||
1: srl %g1, 14, %g3 ! Compute UTAG
|
||||
membar #Sync
|
||||
stxa %g3, [%g1] ASI_DCACHE_UTAG
|
||||
membar #Sync
|
||||
sub %g2, 8, %g3 ! 64-bit data word within line
|
||||
2: membar #Sync
|
||||
stxa %g0, [%g1 + %g3] ASI_DCACHE_DATA
|
||||
membar #Sync
|
||||
subcc %g3, 8, %g3 ! Next 64-bit data word
|
||||
bge,pt %icc, 2b
|
||||
nop
|
||||
subcc %g1, %g2, %g1 ! Next cacheline
|
||||
bge,pt %icc, 1b
|
||||
nop
|
||||
ba,pt %xcc, dcpe_icpe_tl1_common
|
||||
nop
|
||||
|
||||
do_dcpe_tl1_fatal:
|
||||
sethi %hi(1f), %g7
|
||||
ba,pt %xcc, etraptl1
|
||||
1: or %g7, %lo(1b), %g7
|
||||
mov 0x2, %o0
|
||||
call cheetah_plus_parity_error
|
||||
add %sp, PTREGS_OFF, %o1
|
||||
ba,pt %xcc, rtrap
|
||||
nop
|
||||
.size do_dcpe_tl1,.-do_dcpe_tl1
|
||||
|
||||
.globl do_icpe_tl1
|
||||
.type do_icpe_tl1,#function
|
||||
do_icpe_tl1:
|
||||
rdpr %tl, %g1 ! Save original trap level
|
||||
mov 1, %g2 ! Setup TSTATE checking loop
|
||||
sethi %hi(TSTATE_IG), %g3 ! TSTATE mask bit
|
||||
1: wrpr %g2, %tl ! Set trap level to check
|
||||
rdpr %tstate, %g4 ! Read TSTATE for this level
|
||||
andcc %g4, %g3, %g0 ! Interrupt globals in use?
|
||||
bne,a,pn %xcc, do_icpe_tl1_fatal ! Yep, irrecoverable
|
||||
wrpr %g1, %tl ! Restore original trap level
|
||||
add %g2, 1, %g2 ! Next trap level
|
||||
cmp %g2, %g1 ! Hit them all yet?
|
||||
ble,pt %icc, 1b ! Not yet
|
||||
nop
|
||||
wrpr %g1, %tl ! Restore original trap level
|
||||
do_icpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */
|
||||
sethi %hi(icache_parity_tl1_occurred), %g2
|
||||
lduw [%g2 + %lo(icache_parity_tl1_occurred)], %g1
|
||||
add %g1, 1, %g1
|
||||
stw %g1, [%g2 + %lo(icache_parity_tl1_occurred)]
|
||||
/* Flush I-cache */
|
||||
sethi %hi(1 << 15), %g1 ! I-cache size
|
||||
mov (1 << 5), %g2 ! I-cache line size
|
||||
sub %g1, %g2, %g1
|
||||
1: or %g1, (2 << 3), %g3
|
||||
stxa %g0, [%g3] ASI_IC_TAG
|
||||
membar #Sync
|
||||
subcc %g1, %g2, %g1
|
||||
bge,pt %icc, 1b
|
||||
nop
|
||||
ba,pt %xcc, dcpe_icpe_tl1_common
|
||||
nop
|
||||
|
||||
do_icpe_tl1_fatal:
|
||||
sethi %hi(1f), %g7
|
||||
ba,pt %xcc, etraptl1
|
||||
1: or %g7, %lo(1b), %g7
|
||||
mov 0x3, %o0
|
||||
call cheetah_plus_parity_error
|
||||
add %sp, PTREGS_OFF, %o1
|
||||
ba,pt %xcc, rtrap
|
||||
nop
|
||||
.size do_icpe_tl1,.-do_icpe_tl1
|
||||
|
||||
.type dcpe_icpe_tl1_common,#function
|
||||
dcpe_icpe_tl1_common:
|
||||
/* Flush D-cache, re-enable D/I caches in DCU and finally
|
||||
* retry the trapping instruction.
|
||||
*/
|
||||
sethi %hi(1 << 16), %g1 ! D-cache size
|
||||
mov (1 << 5), %g2 ! D-cache line size
|
||||
sub %g1, %g2, %g1
|
||||
1: stxa %g0, [%g1] ASI_DCACHE_TAG
|
||||
membar #Sync
|
||||
subcc %g1, %g2, %g1
|
||||
bge,pt %icc, 1b
|
||||
nop
|
||||
ldxa [%g0] ASI_DCU_CONTROL_REG, %g1
|
||||
or %g1, (DCU_DC | DCU_IC), %g1
|
||||
stxa %g1, [%g0] ASI_DCU_CONTROL_REG
|
||||
membar #Sync
|
||||
retry
|
||||
.size dcpe_icpe_tl1_common,.-dcpe_icpe_tl1_common
|
||||
|
||||
/* Capture I/D/E-cache state into per-cpu error scoreboard.
|
||||
*
|
||||
* %g1: (TL>=0) ? 1 : 0
|
||||
* %g2: scratch
|
||||
* %g3: scratch
|
||||
* %g4: AFSR
|
||||
* %g5: AFAR
|
||||
* %g6: unused, will have current thread ptr after etrap
|
||||
* %g7: scratch
|
||||
*/
|
||||
.type __cheetah_log_error,#function
|
||||
__cheetah_log_error:
|
||||
/* Put "TL1" software bit into AFSR. */
|
||||
and %g1, 0x1, %g1
|
||||
sllx %g1, 63, %g2
|
||||
or %g4, %g2, %g4
|
||||
|
||||
/* Get log entry pointer for this cpu at this trap level. */
|
||||
BRANCH_IF_JALAPENO(g2,g3,50f)
|
||||
ldxa [%g0] ASI_SAFARI_CONFIG, %g2
|
||||
srlx %g2, 17, %g2
|
||||
ba,pt %xcc, 60f
|
||||
and %g2, 0x3ff, %g2
|
||||
|
||||
50: ldxa [%g0] ASI_JBUS_CONFIG, %g2
|
||||
srlx %g2, 17, %g2
|
||||
and %g2, 0x1f, %g2
|
||||
|
||||
60: sllx %g2, 9, %g2
|
||||
sethi %hi(cheetah_error_log), %g3
|
||||
ldx [%g3 + %lo(cheetah_error_log)], %g3
|
||||
brz,pn %g3, 80f
|
||||
nop
|
||||
|
||||
add %g3, %g2, %g3
|
||||
sllx %g1, 8, %g1
|
||||
add %g3, %g1, %g1
|
||||
|
||||
/* %g1 holds pointer to the top of the logging scoreboard */
|
||||
ldx [%g1 + 0x0], %g7
|
||||
cmp %g7, -1
|
||||
bne,pn %xcc, 80f
|
||||
nop
|
||||
|
||||
stx %g4, [%g1 + 0x0]
|
||||
stx %g5, [%g1 + 0x8]
|
||||
add %g1, 0x10, %g1
|
||||
|
||||
/* %g1 now points to D-cache logging area */
|
||||
set 0x3ff8, %g2 /* DC_addr mask */
|
||||
and %g5, %g2, %g2 /* DC_addr bits of AFAR */
|
||||
srlx %g5, 12, %g3
|
||||
or %g3, 1, %g3 /* PHYS tag + valid */
|
||||
|
||||
10: ldxa [%g2] ASI_DCACHE_TAG, %g7
|
||||
cmp %g3, %g7 /* TAG match? */
|
||||
bne,pt %xcc, 13f
|
||||
nop
|
||||
|
||||
/* Yep, what we want, capture state. */
|
||||
stx %g2, [%g1 + 0x20]
|
||||
stx %g7, [%g1 + 0x28]
|
||||
|
||||
/* A membar Sync is required before and after utag access. */
|
||||
membar #Sync
|
||||
ldxa [%g2] ASI_DCACHE_UTAG, %g7
|
||||
membar #Sync
|
||||
stx %g7, [%g1 + 0x30]
|
||||
ldxa [%g2] ASI_DCACHE_SNOOP_TAG, %g7
|
||||
stx %g7, [%g1 + 0x38]
|
||||
clr %g3
|
||||
|
||||
12: ldxa [%g2 + %g3] ASI_DCACHE_DATA, %g7
|
||||
stx %g7, [%g1]
|
||||
add %g3, (1 << 5), %g3
|
||||
cmp %g3, (4 << 5)
|
||||
bl,pt %xcc, 12b
|
||||
add %g1, 0x8, %g1
|
||||
|
||||
ba,pt %xcc, 20f
|
||||
add %g1, 0x20, %g1
|
||||
|
||||
13: sethi %hi(1 << 14), %g7
|
||||
add %g2, %g7, %g2
|
||||
srlx %g2, 14, %g7
|
||||
cmp %g7, 4
|
||||
bl,pt %xcc, 10b
|
||||
nop
|
||||
|
||||
add %g1, 0x40, %g1
|
||||
|
||||
/* %g1 now points to I-cache logging area */
|
||||
20: set 0x1fe0, %g2 /* IC_addr mask */
|
||||
and %g5, %g2, %g2 /* IC_addr bits of AFAR */
|
||||
sllx %g2, 1, %g2 /* IC_addr[13:6]==VA[12:5] */
|
||||
srlx %g5, (13 - 8), %g3 /* Make PTAG */
|
||||
andn %g3, 0xff, %g3 /* Mask off undefined bits */
|
||||
|
||||
21: ldxa [%g2] ASI_IC_TAG, %g7
|
||||
andn %g7, 0xff, %g7
|
||||
cmp %g3, %g7
|
||||
bne,pt %xcc, 23f
|
||||
nop
|
||||
|
||||
/* Yep, what we want, capture state. */
|
||||
stx %g2, [%g1 + 0x40]
|
||||
stx %g7, [%g1 + 0x48]
|
||||
add %g2, (1 << 3), %g2
|
||||
ldxa [%g2] ASI_IC_TAG, %g7
|
||||
add %g2, (1 << 3), %g2
|
||||
stx %g7, [%g1 + 0x50]
|
||||
ldxa [%g2] ASI_IC_TAG, %g7
|
||||
add %g2, (1 << 3), %g2
|
||||
stx %g7, [%g1 + 0x60]
|
||||
ldxa [%g2] ASI_IC_TAG, %g7
|
||||
stx %g7, [%g1 + 0x68]
|
||||
sub %g2, (3 << 3), %g2
|
||||
ldxa [%g2] ASI_IC_STAG, %g7
|
||||
stx %g7, [%g1 + 0x58]
|
||||
clr %g3
|
||||
srlx %g2, 2, %g2
|
||||
|
||||
22: ldxa [%g2 + %g3] ASI_IC_INSTR, %g7
|
||||
stx %g7, [%g1]
|
||||
add %g3, (1 << 3), %g3
|
||||
cmp %g3, (8 << 3)
|
||||
bl,pt %xcc, 22b
|
||||
add %g1, 0x8, %g1
|
||||
|
||||
ba,pt %xcc, 30f
|
||||
add %g1, 0x30, %g1
|
||||
|
||||
23: sethi %hi(1 << 14), %g7
|
||||
add %g2, %g7, %g2
|
||||
srlx %g2, 14, %g7
|
||||
cmp %g7, 4
|
||||
bl,pt %xcc, 21b
|
||||
nop
|
||||
|
||||
add %g1, 0x70, %g1
|
||||
|
||||
/* %g1 now points to E-cache logging area */
|
||||
30: andn %g5, (32 - 1), %g2
|
||||
stx %g2, [%g1 + 0x20]
|
||||
ldxa [%g2] ASI_EC_TAG_DATA, %g7
|
||||
stx %g7, [%g1 + 0x28]
|
||||
ldxa [%g2] ASI_EC_R, %g0
|
||||
clr %g3
|
||||
|
||||
31: ldxa [%g3] ASI_EC_DATA, %g7
|
||||
stx %g7, [%g1 + %g3]
|
||||
add %g3, 0x8, %g3
|
||||
cmp %g3, 0x20
|
||||
|
||||
bl,pt %xcc, 31b
|
||||
nop
|
||||
80:
|
||||
rdpr %tt, %g2
|
||||
cmp %g2, 0x70
|
||||
be c_fast_ecc
|
||||
cmp %g2, 0x63
|
||||
be c_cee
|
||||
nop
|
||||
ba,pt %xcc, c_deferred
|
||||
.size __cheetah_log_error,.-__cheetah_log_error
|
||||
|
||||
/* Cheetah FECC trap handling, we get here from tl{0,1}_fecc
|
||||
* in the trap table. That code has done a memory barrier
|
||||
* and has disabled both the I-cache and D-cache in the DCU
|
||||
* control register. The I-cache is disabled so that we may
|
||||
* capture the corrupted cache line, and the D-cache is disabled
|
||||
* because corrupt data may have been placed there and we don't
|
||||
* want to reference it.
|
||||
*
|
||||
* %g1 is one if this trap occurred at %tl >= 1.
|
||||
*
|
||||
* Next, we turn off error reporting so that we don't recurse.
|
||||
*/
|
||||
.globl cheetah_fast_ecc
|
||||
.type cheetah_fast_ecc,#function
|
||||
cheetah_fast_ecc:
|
||||
ldxa [%g0] ASI_ESTATE_ERROR_EN, %g2
|
||||
andn %g2, ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN, %g2
|
||||
stxa %g2, [%g0] ASI_ESTATE_ERROR_EN
|
||||
membar #Sync
|
||||
|
||||
/* Fetch and clear AFSR/AFAR */
|
||||
ldxa [%g0] ASI_AFSR, %g4
|
||||
ldxa [%g0] ASI_AFAR, %g5
|
||||
stxa %g4, [%g0] ASI_AFSR
|
||||
membar #Sync
|
||||
|
||||
ba,pt %xcc, __cheetah_log_error
|
||||
nop
|
||||
.size cheetah_fast_ecc,.-cheetah_fast_ecc
|
||||
|
||||
.type c_fast_ecc,#function
|
||||
c_fast_ecc:
|
||||
rdpr %pil, %g2
|
||||
wrpr %g0, 15, %pil
|
||||
ba,pt %xcc, etrap_irq
|
||||
rd %pc, %g7
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
call trace_hardirqs_off
|
||||
nop
|
||||
#endif
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call cheetah_fecc_handler
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,a,pt %xcc, rtrap_irq
|
||||
.size c_fast_ecc,.-c_fast_ecc
|
||||
|
||||
/* Our caller has disabled I-cache and performed membar Sync. */
|
||||
.globl cheetah_cee
|
||||
.type cheetah_cee,#function
|
||||
cheetah_cee:
|
||||
ldxa [%g0] ASI_ESTATE_ERROR_EN, %g2
|
||||
andn %g2, ESTATE_ERROR_CEEN, %g2
|
||||
stxa %g2, [%g0] ASI_ESTATE_ERROR_EN
|
||||
membar #Sync
|
||||
|
||||
/* Fetch and clear AFSR/AFAR */
|
||||
ldxa [%g0] ASI_AFSR, %g4
|
||||
ldxa [%g0] ASI_AFAR, %g5
|
||||
stxa %g4, [%g0] ASI_AFSR
|
||||
membar #Sync
|
||||
|
||||
ba,pt %xcc, __cheetah_log_error
|
||||
nop
|
||||
.size cheetah_cee,.-cheetah_cee
|
||||
|
||||
.type c_cee,#function
|
||||
c_cee:
|
||||
rdpr %pil, %g2
|
||||
wrpr %g0, 15, %pil
|
||||
ba,pt %xcc, etrap_irq
|
||||
rd %pc, %g7
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
call trace_hardirqs_off
|
||||
nop
|
||||
#endif
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call cheetah_cee_handler
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,a,pt %xcc, rtrap_irq
|
||||
.size c_cee,.-c_cee
|
||||
|
||||
/* Our caller has disabled I-cache+D-cache and performed membar Sync. */
|
||||
.globl cheetah_deferred_trap
|
||||
.type cheetah_deferred_trap,#function
|
||||
cheetah_deferred_trap:
|
||||
ldxa [%g0] ASI_ESTATE_ERROR_EN, %g2
|
||||
andn %g2, ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN, %g2
|
||||
stxa %g2, [%g0] ASI_ESTATE_ERROR_EN
|
||||
membar #Sync
|
||||
|
||||
/* Fetch and clear AFSR/AFAR */
|
||||
ldxa [%g0] ASI_AFSR, %g4
|
||||
ldxa [%g0] ASI_AFAR, %g5
|
||||
stxa %g4, [%g0] ASI_AFSR
|
||||
membar #Sync
|
||||
|
||||
ba,pt %xcc, __cheetah_log_error
|
||||
nop
|
||||
.size cheetah_deferred_trap,.-cheetah_deferred_trap
|
||||
|
||||
.type c_deferred,#function
|
||||
c_deferred:
|
||||
rdpr %pil, %g2
|
||||
wrpr %g0, 15, %pil
|
||||
ba,pt %xcc, etrap_irq
|
||||
rd %pc, %g7
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
call trace_hardirqs_off
|
||||
nop
|
||||
#endif
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call cheetah_deferred_handler
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,a,pt %xcc, rtrap_irq
|
||||
.size c_deferred,.-c_deferred
|
File diff suppressed because it is too large
Load diff
384
arch/sparc64/kernel/fpu_traps.S
Normal file
384
arch/sparc64/kernel/fpu_traps.S
Normal file
|
@ -0,0 +1,384 @@
|
|||
/* This is trivial with the new code... */
|
||||
.globl do_fpdis
|
||||
.type do_fpdis,#function
|
||||
do_fpdis:
|
||||
sethi %hi(TSTATE_PEF), %g4
|
||||
rdpr %tstate, %g5
|
||||
andcc %g5, %g4, %g0
|
||||
be,pt %xcc, 1f
|
||||
nop
|
||||
rd %fprs, %g5
|
||||
andcc %g5, FPRS_FEF, %g0
|
||||
be,pt %xcc, 1f
|
||||
nop
|
||||
|
||||
/* Legal state when DCR_IFPOE is set in Cheetah %dcr. */
|
||||
sethi %hi(109f), %g7
|
||||
ba,pt %xcc, etrap
|
||||
109: or %g7, %lo(109b), %g7
|
||||
add %g0, %g0, %g0
|
||||
ba,a,pt %xcc, rtrap
|
||||
|
||||
1: TRAP_LOAD_THREAD_REG(%g6, %g1)
|
||||
ldub [%g6 + TI_FPSAVED], %g5
|
||||
wr %g0, FPRS_FEF, %fprs
|
||||
andcc %g5, FPRS_FEF, %g0
|
||||
be,a,pt %icc, 1f
|
||||
clr %g7
|
||||
ldx [%g6 + TI_GSR], %g7
|
||||
1: andcc %g5, FPRS_DL, %g0
|
||||
bne,pn %icc, 2f
|
||||
fzero %f0
|
||||
andcc %g5, FPRS_DU, %g0
|
||||
bne,pn %icc, 1f
|
||||
fzero %f2
|
||||
faddd %f0, %f2, %f4
|
||||
fmuld %f0, %f2, %f6
|
||||
faddd %f0, %f2, %f8
|
||||
fmuld %f0, %f2, %f10
|
||||
faddd %f0, %f2, %f12
|
||||
fmuld %f0, %f2, %f14
|
||||
faddd %f0, %f2, %f16
|
||||
fmuld %f0, %f2, %f18
|
||||
faddd %f0, %f2, %f20
|
||||
fmuld %f0, %f2, %f22
|
||||
faddd %f0, %f2, %f24
|
||||
fmuld %f0, %f2, %f26
|
||||
faddd %f0, %f2, %f28
|
||||
fmuld %f0, %f2, %f30
|
||||
faddd %f0, %f2, %f32
|
||||
fmuld %f0, %f2, %f34
|
||||
faddd %f0, %f2, %f36
|
||||
fmuld %f0, %f2, %f38
|
||||
faddd %f0, %f2, %f40
|
||||
fmuld %f0, %f2, %f42
|
||||
faddd %f0, %f2, %f44
|
||||
fmuld %f0, %f2, %f46
|
||||
faddd %f0, %f2, %f48
|
||||
fmuld %f0, %f2, %f50
|
||||
faddd %f0, %f2, %f52
|
||||
fmuld %f0, %f2, %f54
|
||||
faddd %f0, %f2, %f56
|
||||
fmuld %f0, %f2, %f58
|
||||
b,pt %xcc, fpdis_exit2
|
||||
faddd %f0, %f2, %f60
|
||||
1: mov SECONDARY_CONTEXT, %g3
|
||||
add %g6, TI_FPREGS + 0x80, %g1
|
||||
faddd %f0, %f2, %f4
|
||||
fmuld %f0, %f2, %f6
|
||||
|
||||
661: ldxa [%g3] ASI_DMMU, %g5
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
ldxa [%g3] ASI_MMU, %g5
|
||||
.previous
|
||||
|
||||
sethi %hi(sparc64_kern_sec_context), %g2
|
||||
ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
|
||||
|
||||
661: stxa %g2, [%g3] ASI_DMMU
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
stxa %g2, [%g3] ASI_MMU
|
||||
.previous
|
||||
|
||||
membar #Sync
|
||||
add %g6, TI_FPREGS + 0xc0, %g2
|
||||
faddd %f0, %f2, %f8
|
||||
fmuld %f0, %f2, %f10
|
||||
membar #Sync
|
||||
ldda [%g1] ASI_BLK_S, %f32
|
||||
ldda [%g2] ASI_BLK_S, %f48
|
||||
membar #Sync
|
||||
faddd %f0, %f2, %f12
|
||||
fmuld %f0, %f2, %f14
|
||||
faddd %f0, %f2, %f16
|
||||
fmuld %f0, %f2, %f18
|
||||
faddd %f0, %f2, %f20
|
||||
fmuld %f0, %f2, %f22
|
||||
faddd %f0, %f2, %f24
|
||||
fmuld %f0, %f2, %f26
|
||||
faddd %f0, %f2, %f28
|
||||
fmuld %f0, %f2, %f30
|
||||
b,pt %xcc, fpdis_exit
|
||||
nop
|
||||
2: andcc %g5, FPRS_DU, %g0
|
||||
bne,pt %icc, 3f
|
||||
fzero %f32
|
||||
mov SECONDARY_CONTEXT, %g3
|
||||
fzero %f34
|
||||
|
||||
661: ldxa [%g3] ASI_DMMU, %g5
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
ldxa [%g3] ASI_MMU, %g5
|
||||
.previous
|
||||
|
||||
add %g6, TI_FPREGS, %g1
|
||||
sethi %hi(sparc64_kern_sec_context), %g2
|
||||
ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
|
||||
|
||||
661: stxa %g2, [%g3] ASI_DMMU
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
stxa %g2, [%g3] ASI_MMU
|
||||
.previous
|
||||
|
||||
membar #Sync
|
||||
add %g6, TI_FPREGS + 0x40, %g2
|
||||
faddd %f32, %f34, %f36
|
||||
fmuld %f32, %f34, %f38
|
||||
membar #Sync
|
||||
ldda [%g1] ASI_BLK_S, %f0
|
||||
ldda [%g2] ASI_BLK_S, %f16
|
||||
membar #Sync
|
||||
faddd %f32, %f34, %f40
|
||||
fmuld %f32, %f34, %f42
|
||||
faddd %f32, %f34, %f44
|
||||
fmuld %f32, %f34, %f46
|
||||
faddd %f32, %f34, %f48
|
||||
fmuld %f32, %f34, %f50
|
||||
faddd %f32, %f34, %f52
|
||||
fmuld %f32, %f34, %f54
|
||||
faddd %f32, %f34, %f56
|
||||
fmuld %f32, %f34, %f58
|
||||
faddd %f32, %f34, %f60
|
||||
fmuld %f32, %f34, %f62
|
||||
ba,pt %xcc, fpdis_exit
|
||||
nop
|
||||
3: mov SECONDARY_CONTEXT, %g3
|
||||
add %g6, TI_FPREGS, %g1
|
||||
|
||||
661: ldxa [%g3] ASI_DMMU, %g5
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
ldxa [%g3] ASI_MMU, %g5
|
||||
.previous
|
||||
|
||||
sethi %hi(sparc64_kern_sec_context), %g2
|
||||
ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
|
||||
|
||||
661: stxa %g2, [%g3] ASI_DMMU
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
stxa %g2, [%g3] ASI_MMU
|
||||
.previous
|
||||
|
||||
membar #Sync
|
||||
mov 0x40, %g2
|
||||
membar #Sync
|
||||
ldda [%g1] ASI_BLK_S, %f0
|
||||
ldda [%g1 + %g2] ASI_BLK_S, %f16
|
||||
add %g1, 0x80, %g1
|
||||
ldda [%g1] ASI_BLK_S, %f32
|
||||
ldda [%g1 + %g2] ASI_BLK_S, %f48
|
||||
membar #Sync
|
||||
fpdis_exit:
|
||||
|
||||
661: stxa %g5, [%g3] ASI_DMMU
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
stxa %g5, [%g3] ASI_MMU
|
||||
.previous
|
||||
|
||||
membar #Sync
|
||||
fpdis_exit2:
|
||||
wr %g7, 0, %gsr
|
||||
ldx [%g6 + TI_XFSR], %fsr
|
||||
rdpr %tstate, %g3
|
||||
or %g3, %g4, %g3 ! anal...
|
||||
wrpr %g3, %tstate
|
||||
wr %g0, FPRS_FEF, %fprs ! clean DU/DL bits
|
||||
retry
|
||||
.size do_fpdis,.-do_fpdis
|
||||
|
||||
.align 32
|
||||
.type fp_other_bounce,#function
|
||||
fp_other_bounce:
|
||||
call do_fpother
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
nop
|
||||
.size fp_other_bounce,.-fp_other_bounce
|
||||
|
||||
.align 32
|
||||
.globl do_fpother_check_fitos
|
||||
.type do_fpother_check_fitos,#function
|
||||
do_fpother_check_fitos:
|
||||
TRAP_LOAD_THREAD_REG(%g6, %g1)
|
||||
sethi %hi(fp_other_bounce - 4), %g7
|
||||
or %g7, %lo(fp_other_bounce - 4), %g7
|
||||
|
||||
/* NOTE: Need to preserve %g7 until we fully commit
|
||||
* to the fitos fixup.
|
||||
*/
|
||||
stx %fsr, [%g6 + TI_XFSR]
|
||||
rdpr %tstate, %g3
|
||||
andcc %g3, TSTATE_PRIV, %g0
|
||||
bne,pn %xcc, do_fptrap_after_fsr
|
||||
nop
|
||||
ldx [%g6 + TI_XFSR], %g3
|
||||
srlx %g3, 14, %g1
|
||||
and %g1, 7, %g1
|
||||
cmp %g1, 2 ! Unfinished FP-OP
|
||||
bne,pn %xcc, do_fptrap_after_fsr
|
||||
sethi %hi(1 << 23), %g1 ! Inexact
|
||||
andcc %g3, %g1, %g0
|
||||
bne,pn %xcc, do_fptrap_after_fsr
|
||||
rdpr %tpc, %g1
|
||||
lduwa [%g1] ASI_AIUP, %g3 ! This cannot ever fail
|
||||
#define FITOS_MASK 0xc1f83fe0
|
||||
#define FITOS_COMPARE 0x81a01880
|
||||
sethi %hi(FITOS_MASK), %g1
|
||||
or %g1, %lo(FITOS_MASK), %g1
|
||||
and %g3, %g1, %g1
|
||||
sethi %hi(FITOS_COMPARE), %g2
|
||||
or %g2, %lo(FITOS_COMPARE), %g2
|
||||
cmp %g1, %g2
|
||||
bne,pn %xcc, do_fptrap_after_fsr
|
||||
nop
|
||||
std %f62, [%g6 + TI_FPREGS + (62 * 4)]
|
||||
sethi %hi(fitos_table_1), %g1
|
||||
and %g3, 0x1f, %g2
|
||||
or %g1, %lo(fitos_table_1), %g1
|
||||
sllx %g2, 2, %g2
|
||||
jmpl %g1 + %g2, %g0
|
||||
ba,pt %xcc, fitos_emul_continue
|
||||
|
||||
fitos_table_1:
|
||||
fitod %f0, %f62
|
||||
fitod %f1, %f62
|
||||
fitod %f2, %f62
|
||||
fitod %f3, %f62
|
||||
fitod %f4, %f62
|
||||
fitod %f5, %f62
|
||||
fitod %f6, %f62
|
||||
fitod %f7, %f62
|
||||
fitod %f8, %f62
|
||||
fitod %f9, %f62
|
||||
fitod %f10, %f62
|
||||
fitod %f11, %f62
|
||||
fitod %f12, %f62
|
||||
fitod %f13, %f62
|
||||
fitod %f14, %f62
|
||||
fitod %f15, %f62
|
||||
fitod %f16, %f62
|
||||
fitod %f17, %f62
|
||||
fitod %f18, %f62
|
||||
fitod %f19, %f62
|
||||
fitod %f20, %f62
|
||||
fitod %f21, %f62
|
||||
fitod %f22, %f62
|
||||
fitod %f23, %f62
|
||||
fitod %f24, %f62
|
||||
fitod %f25, %f62
|
||||
fitod %f26, %f62
|
||||
fitod %f27, %f62
|
||||
fitod %f28, %f62
|
||||
fitod %f29, %f62
|
||||
fitod %f30, %f62
|
||||
fitod %f31, %f62
|
||||
|
||||
fitos_emul_continue:
|
||||
sethi %hi(fitos_table_2), %g1
|
||||
srl %g3, 25, %g2
|
||||
or %g1, %lo(fitos_table_2), %g1
|
||||
and %g2, 0x1f, %g2
|
||||
sllx %g2, 2, %g2
|
||||
jmpl %g1 + %g2, %g0
|
||||
ba,pt %xcc, fitos_emul_fini
|
||||
|
||||
fitos_table_2:
|
||||
fdtos %f62, %f0
|
||||
fdtos %f62, %f1
|
||||
fdtos %f62, %f2
|
||||
fdtos %f62, %f3
|
||||
fdtos %f62, %f4
|
||||
fdtos %f62, %f5
|
||||
fdtos %f62, %f6
|
||||
fdtos %f62, %f7
|
||||
fdtos %f62, %f8
|
||||
fdtos %f62, %f9
|
||||
fdtos %f62, %f10
|
||||
fdtos %f62, %f11
|
||||
fdtos %f62, %f12
|
||||
fdtos %f62, %f13
|
||||
fdtos %f62, %f14
|
||||
fdtos %f62, %f15
|
||||
fdtos %f62, %f16
|
||||
fdtos %f62, %f17
|
||||
fdtos %f62, %f18
|
||||
fdtos %f62, %f19
|
||||
fdtos %f62, %f20
|
||||
fdtos %f62, %f21
|
||||
fdtos %f62, %f22
|
||||
fdtos %f62, %f23
|
||||
fdtos %f62, %f24
|
||||
fdtos %f62, %f25
|
||||
fdtos %f62, %f26
|
||||
fdtos %f62, %f27
|
||||
fdtos %f62, %f28
|
||||
fdtos %f62, %f29
|
||||
fdtos %f62, %f30
|
||||
fdtos %f62, %f31
|
||||
|
||||
fitos_emul_fini:
|
||||
ldd [%g6 + TI_FPREGS + (62 * 4)], %f62
|
||||
done
|
||||
.size do_fpother_check_fitos,.-do_fpother_check_fitos
|
||||
|
||||
.align 32
|
||||
.globl do_fptrap
|
||||
.type do_fptrap,#function
|
||||
do_fptrap:
|
||||
TRAP_LOAD_THREAD_REG(%g6, %g1)
|
||||
stx %fsr, [%g6 + TI_XFSR]
|
||||
do_fptrap_after_fsr:
|
||||
ldub [%g6 + TI_FPSAVED], %g3
|
||||
rd %fprs, %g1
|
||||
or %g3, %g1, %g3
|
||||
stb %g3, [%g6 + TI_FPSAVED]
|
||||
rd %gsr, %g3
|
||||
stx %g3, [%g6 + TI_GSR]
|
||||
mov SECONDARY_CONTEXT, %g3
|
||||
|
||||
661: ldxa [%g3] ASI_DMMU, %g5
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
ldxa [%g3] ASI_MMU, %g5
|
||||
.previous
|
||||
|
||||
sethi %hi(sparc64_kern_sec_context), %g2
|
||||
ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
|
||||
|
||||
661: stxa %g2, [%g3] ASI_DMMU
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
stxa %g2, [%g3] ASI_MMU
|
||||
.previous
|
||||
|
||||
membar #Sync
|
||||
add %g6, TI_FPREGS, %g2
|
||||
andcc %g1, FPRS_DL, %g0
|
||||
be,pn %icc, 4f
|
||||
mov 0x40, %g3
|
||||
stda %f0, [%g2] ASI_BLK_S
|
||||
stda %f16, [%g2 + %g3] ASI_BLK_S
|
||||
andcc %g1, FPRS_DU, %g0
|
||||
be,pn %icc, 5f
|
||||
4: add %g2, 128, %g2
|
||||
stda %f32, [%g2] ASI_BLK_S
|
||||
stda %f48, [%g2 + %g3] ASI_BLK_S
|
||||
5: mov SECONDARY_CONTEXT, %g1
|
||||
membar #Sync
|
||||
|
||||
661: stxa %g5, [%g1] ASI_DMMU
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
stxa %g5, [%g1] ASI_MMU
|
||||
.previous
|
||||
|
||||
membar #Sync
|
||||
ba,pt %xcc, etrap
|
||||
wr %g0, 0, %fprs
|
||||
.size do_fptrap,.-do_fptrap
|
24
arch/sparc64/kernel/getsetcc.S
Normal file
24
arch/sparc64/kernel/getsetcc.S
Normal file
|
@ -0,0 +1,24 @@
|
|||
.globl getcc
|
||||
.type getcc,#function
|
||||
getcc:
|
||||
ldx [%o0 + PT_V9_TSTATE], %o1
|
||||
srlx %o1, 32, %o1
|
||||
and %o1, 0xf, %o1
|
||||
retl
|
||||
stx %o1, [%o0 + PT_V9_G1]
|
||||
.size getcc,.-getcc
|
||||
|
||||
.globl setcc
|
||||
.type setcc,#function
|
||||
setcc:
|
||||
ldx [%o0 + PT_V9_TSTATE], %o1
|
||||
ldx [%o0 + PT_V9_G1], %o2
|
||||
or %g0, %ulo(TSTATE_ICC), %o3
|
||||
sllx %o3, 32, %o3
|
||||
andn %o1, %o3, %o1
|
||||
sllx %o2, 32, %o2
|
||||
and %o2, %o3, %o2
|
||||
or %o1, %o2, %o1
|
||||
retl
|
||||
stx %o1, [%o0 + PT_V9_TSTATE]
|
||||
.size setcc,.-setcc
|
|
@ -27,6 +27,10 @@
|
|||
#include <asm/ttable.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/cpudata.h>
|
||||
#include <asm/pil.h>
|
||||
#include <asm/estate.h>
|
||||
#include <asm/sfafsr.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
/* This section from from _start to sparc64_boot_end should fit into
|
||||
* 0x0000000000404000 to 0x0000000000408000.
|
||||
|
@ -823,7 +827,16 @@ sparc64_boot_end:
|
|||
#include "etrap.S"
|
||||
#include "rtrap.S"
|
||||
#include "winfixup.S"
|
||||
#include "entry.S"
|
||||
#include "fpu_traps.S"
|
||||
#include "ivec.S"
|
||||
#include "getsetcc.S"
|
||||
#include "utrap.S"
|
||||
#include "spiterrs.S"
|
||||
#include "cherrs.S"
|
||||
#include "misctrap.S"
|
||||
#include "syscalls.S"
|
||||
#include "helpers.S"
|
||||
#include "hvcalls.S"
|
||||
#include "sun4v_tlb_miss.S"
|
||||
#include "sun4v_ivec.S"
|
||||
#include "ktlb.S"
|
||||
|
|
63
arch/sparc64/kernel/helpers.S
Normal file
63
arch/sparc64/kernel/helpers.S
Normal file
|
@ -0,0 +1,63 @@
|
|||
.align 32
|
||||
.globl __flushw_user
|
||||
.type __flushw_user,#function
|
||||
__flushw_user:
|
||||
rdpr %otherwin, %g1
|
||||
brz,pn %g1, 2f
|
||||
clr %g2
|
||||
1: save %sp, -128, %sp
|
||||
rdpr %otherwin, %g1
|
||||
brnz,pt %g1, 1b
|
||||
add %g2, 1, %g2
|
||||
1: sub %g2, 1, %g2
|
||||
brnz,pt %g2, 1b
|
||||
restore %g0, %g0, %g0
|
||||
2: retl
|
||||
nop
|
||||
.size __flushw_user,.-__flushw_user
|
||||
|
||||
/* Flush %fp and %i7 to the stack for all register
|
||||
* windows active inside of the cpu. This allows
|
||||
* show_stack_trace() to avoid using an expensive
|
||||
* 'flushw'.
|
||||
*/
|
||||
.globl stack_trace_flush
|
||||
.type stack_trace_flush,#function
|
||||
stack_trace_flush:
|
||||
rdpr %pstate, %o0
|
||||
wrpr %o0, PSTATE_IE, %pstate
|
||||
|
||||
rdpr %cwp, %g1
|
||||
rdpr %canrestore, %g2
|
||||
sub %g1, 1, %g3
|
||||
|
||||
1: brz,pn %g2, 2f
|
||||
sub %g2, 1, %g2
|
||||
wrpr %g3, %cwp
|
||||
stx %fp, [%sp + STACK_BIAS + RW_V9_I6]
|
||||
stx %i7, [%sp + STACK_BIAS + RW_V9_I7]
|
||||
ba,pt %xcc, 1b
|
||||
sub %g3, 1, %g3
|
||||
|
||||
2: wrpr %g1, %cwp
|
||||
wrpr %o0, %pstate
|
||||
|
||||
retl
|
||||
nop
|
||||
.size stack_trace_flush,.-stack_trace_flush
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
.globl hard_smp_processor_id
|
||||
.type hard_smp_processor_id,#function
|
||||
hard_smp_processor_id:
|
||||
#endif
|
||||
.globl real_hard_smp_processor_id
|
||||
.type real_hard_smp_processor_id,#function
|
||||
real_hard_smp_processor_id:
|
||||
__GET_CPUID(%o0)
|
||||
retl
|
||||
nop
|
||||
#ifdef CONFIG_SMP
|
||||
.size hard_smp_processor_id,.-hard_smp_processor_id
|
||||
#endif
|
||||
.size real_hard_smp_processor_id,.-real_hard_smp_processor_id
|
886
arch/sparc64/kernel/hvcalls.S
Normal file
886
arch/sparc64/kernel/hvcalls.S
Normal file
|
@ -0,0 +1,886 @@
|
|||
/* %o0: devhandle
|
||||
* %o1: devino
|
||||
*
|
||||
* returns %o0: sysino
|
||||
*/
|
||||
.globl sun4v_devino_to_sysino
|
||||
.type sun4v_devino_to_sysino,#function
|
||||
sun4v_devino_to_sysino:
|
||||
mov HV_FAST_INTR_DEVINO2SYSINO, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
mov %o1, %o0
|
||||
.size sun4v_devino_to_sysino, .-sun4v_devino_to_sysino
|
||||
|
||||
/* %o0: sysino
|
||||
*
|
||||
* returns %o0: intr_enabled (HV_INTR_{DISABLED,ENABLED})
|
||||
*/
|
||||
.globl sun4v_intr_getenabled
|
||||
.type sun4v_intr_getenabled,#function
|
||||
sun4v_intr_getenabled:
|
||||
mov HV_FAST_INTR_GETENABLED, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
mov %o1, %o0
|
||||
.size sun4v_intr_getenabled, .-sun4v_intr_getenabled
|
||||
|
||||
/* %o0: sysino
|
||||
* %o1: intr_enabled (HV_INTR_{DISABLED,ENABLED})
|
||||
*/
|
||||
.globl sun4v_intr_setenabled
|
||||
.type sun4v_intr_setenabled,#function
|
||||
sun4v_intr_setenabled:
|
||||
mov HV_FAST_INTR_SETENABLED, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_intr_setenabled, .-sun4v_intr_setenabled
|
||||
|
||||
/* %o0: sysino
|
||||
*
|
||||
* returns %o0: intr_state (HV_INTR_STATE_*)
|
||||
*/
|
||||
.globl sun4v_intr_getstate
|
||||
.type sun4v_intr_getstate,#function
|
||||
sun4v_intr_getstate:
|
||||
mov HV_FAST_INTR_GETSTATE, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
mov %o1, %o0
|
||||
.size sun4v_intr_getstate, .-sun4v_intr_getstate
|
||||
|
||||
/* %o0: sysino
|
||||
* %o1: intr_state (HV_INTR_STATE_*)
|
||||
*/
|
||||
.globl sun4v_intr_setstate
|
||||
.type sun4v_intr_setstate,#function
|
||||
sun4v_intr_setstate:
|
||||
mov HV_FAST_INTR_SETSTATE, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_intr_setstate, .-sun4v_intr_setstate
|
||||
|
||||
/* %o0: sysino
|
||||
*
|
||||
* returns %o0: cpuid
|
||||
*/
|
||||
.globl sun4v_intr_gettarget
|
||||
.type sun4v_intr_gettarget,#function
|
||||
sun4v_intr_gettarget:
|
||||
mov HV_FAST_INTR_GETTARGET, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
mov %o1, %o0
|
||||
.size sun4v_intr_gettarget, .-sun4v_intr_gettarget
|
||||
|
||||
/* %o0: sysino
|
||||
* %o1: cpuid
|
||||
*/
|
||||
.globl sun4v_intr_settarget
|
||||
.type sun4v_intr_settarget,#function
|
||||
sun4v_intr_settarget:
|
||||
mov HV_FAST_INTR_SETTARGET, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_intr_settarget, .-sun4v_intr_settarget
|
||||
|
||||
/* %o0: cpuid
|
||||
* %o1: pc
|
||||
* %o2: rtba
|
||||
* %o3: arg0
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_cpu_start
|
||||
.type sun4v_cpu_start,#function
|
||||
sun4v_cpu_start:
|
||||
mov HV_FAST_CPU_START, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_cpu_start, .-sun4v_cpu_start
|
||||
|
||||
/* %o0: cpuid
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_cpu_stop
|
||||
.type sun4v_cpu_stop,#function
|
||||
sun4v_cpu_stop:
|
||||
mov HV_FAST_CPU_STOP, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_cpu_stop, .-sun4v_cpu_stop
|
||||
|
||||
/* returns %o0: status */
|
||||
.globl sun4v_cpu_yield
|
||||
.type sun4v_cpu_yield, #function
|
||||
sun4v_cpu_yield:
|
||||
mov HV_FAST_CPU_YIELD, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_cpu_yield, .-sun4v_cpu_yield
|
||||
|
||||
/* %o0: type
|
||||
* %o1: queue paddr
|
||||
* %o2: num queue entries
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_cpu_qconf
|
||||
.type sun4v_cpu_qconf,#function
|
||||
sun4v_cpu_qconf:
|
||||
mov HV_FAST_CPU_QCONF, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_cpu_qconf, .-sun4v_cpu_qconf
|
||||
|
||||
/* %o0: num cpus in cpu list
|
||||
* %o1: cpu list paddr
|
||||
* %o2: mondo block paddr
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_cpu_mondo_send
|
||||
.type sun4v_cpu_mondo_send,#function
|
||||
sun4v_cpu_mondo_send:
|
||||
mov HV_FAST_CPU_MONDO_SEND, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_cpu_mondo_send, .-sun4v_cpu_mondo_send
|
||||
|
||||
/* %o0: CPU ID
|
||||
*
|
||||
* returns %o0: -status if status non-zero, else
|
||||
* %o0: cpu state as HV_CPU_STATE_*
|
||||
*/
|
||||
.globl sun4v_cpu_state
|
||||
.type sun4v_cpu_state,#function
|
||||
sun4v_cpu_state:
|
||||
mov HV_FAST_CPU_STATE, %o5
|
||||
ta HV_FAST_TRAP
|
||||
brnz,pn %o0, 1f
|
||||
sub %g0, %o0, %o0
|
||||
mov %o1, %o0
|
||||
1: retl
|
||||
nop
|
||||
.size sun4v_cpu_state, .-sun4v_cpu_state
|
||||
|
||||
/* %o0: virtual address
|
||||
* %o1: must be zero
|
||||
* %o2: TTE
|
||||
* %o3: HV_MMU_* flags
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_mmu_map_perm_addr
|
||||
.type sun4v_mmu_map_perm_addr,#function
|
||||
sun4v_mmu_map_perm_addr:
|
||||
mov HV_FAST_MMU_MAP_PERM_ADDR, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_mmu_map_perm_addr, .-sun4v_mmu_map_perm_addr
|
||||
|
||||
/* %o0: number of TSB descriptions
|
||||
* %o1: TSB descriptions real address
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_mmu_tsb_ctx0
|
||||
.type sun4v_mmu_tsb_ctx0,#function
|
||||
sun4v_mmu_tsb_ctx0:
|
||||
mov HV_FAST_MMU_TSB_CTX0, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_mmu_tsb_ctx0, .-sun4v_mmu_tsb_ctx0
|
||||
|
||||
/* %o0: API group number
|
||||
* %o1: pointer to unsigned long major number storage
|
||||
* %o2: pointer to unsigned long minor number storage
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_get_version
|
||||
.type sun4v_get_version,#function
|
||||
sun4v_get_version:
|
||||
mov HV_CORE_GET_VER, %o5
|
||||
mov %o1, %o3
|
||||
mov %o2, %o4
|
||||
ta HV_CORE_TRAP
|
||||
stx %o1, [%o3]
|
||||
retl
|
||||
stx %o2, [%o4]
|
||||
.size sun4v_get_version, .-sun4v_get_version
|
||||
|
||||
/* %o0: API group number
|
||||
* %o1: desired major number
|
||||
* %o2: desired minor number
|
||||
* %o3: pointer to unsigned long actual minor number storage
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_set_version
|
||||
.type sun4v_set_version,#function
|
||||
sun4v_set_version:
|
||||
mov HV_CORE_SET_VER, %o5
|
||||
mov %o3, %o4
|
||||
ta HV_CORE_TRAP
|
||||
retl
|
||||
stx %o1, [%o4]
|
||||
.size sun4v_set_version, .-sun4v_set_version
|
||||
|
||||
/* %o0: pointer to unsigned long time
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_tod_get
|
||||
.type sun4v_tod_get,#function
|
||||
sun4v_tod_get:
|
||||
mov %o0, %o4
|
||||
mov HV_FAST_TOD_GET, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%o4]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_tod_get, .-sun4v_tod_get
|
||||
|
||||
/* %o0: time
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_tod_set
|
||||
.type sun4v_tod_set,#function
|
||||
sun4v_tod_set:
|
||||
mov HV_FAST_TOD_SET, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_tod_set, .-sun4v_tod_set
|
||||
|
||||
/* %o0: pointer to unsigned long status
|
||||
*
|
||||
* returns %o0: signed character
|
||||
*/
|
||||
.globl sun4v_con_getchar
|
||||
.type sun4v_con_getchar,#function
|
||||
sun4v_con_getchar:
|
||||
mov %o0, %o4
|
||||
mov HV_FAST_CONS_GETCHAR, %o5
|
||||
clr %o0
|
||||
clr %o1
|
||||
ta HV_FAST_TRAP
|
||||
stx %o0, [%o4]
|
||||
retl
|
||||
sra %o1, 0, %o0
|
||||
.size sun4v_con_getchar, .-sun4v_con_getchar
|
||||
|
||||
/* %o0: signed long character
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_con_putchar
|
||||
.type sun4v_con_putchar,#function
|
||||
sun4v_con_putchar:
|
||||
mov HV_FAST_CONS_PUTCHAR, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
sra %o0, 0, %o0
|
||||
.size sun4v_con_putchar, .-sun4v_con_putchar
|
||||
|
||||
/* %o0: buffer real address
|
||||
* %o1: buffer size
|
||||
* %o2: pointer to unsigned long bytes_read
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_con_read
|
||||
.type sun4v_con_read,#function
|
||||
sun4v_con_read:
|
||||
mov %o2, %o4
|
||||
mov HV_FAST_CONS_READ, %o5
|
||||
ta HV_FAST_TRAP
|
||||
brnz %o0, 1f
|
||||
cmp %o1, -1 /* break */
|
||||
be,a,pn %icc, 1f
|
||||
mov %o1, %o0
|
||||
cmp %o1, -2 /* hup */
|
||||
be,a,pn %icc, 1f
|
||||
mov %o1, %o0
|
||||
stx %o1, [%o4]
|
||||
1: retl
|
||||
nop
|
||||
.size sun4v_con_read, .-sun4v_con_read
|
||||
|
||||
/* %o0: buffer real address
|
||||
* %o1: buffer size
|
||||
* %o2: pointer to unsigned long bytes_written
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_con_write
|
||||
.type sun4v_con_write,#function
|
||||
sun4v_con_write:
|
||||
mov %o2, %o4
|
||||
mov HV_FAST_CONS_WRITE, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%o4]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_con_write, .-sun4v_con_write
|
||||
|
||||
/* %o0: soft state
|
||||
* %o1: address of description string
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_mach_set_soft_state
|
||||
.type sun4v_mach_set_soft_state,#function
|
||||
sun4v_mach_set_soft_state:
|
||||
mov HV_FAST_MACH_SET_SOFT_STATE, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_mach_set_soft_state, .-sun4v_mach_set_soft_state
|
||||
|
||||
/* %o0: exit code
|
||||
*
|
||||
* Does not return.
|
||||
*/
|
||||
.globl sun4v_mach_exit
|
||||
.type sun4v_mach_exit,#function
|
||||
sun4v_mach_exit:
|
||||
mov HV_FAST_MACH_EXIT, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_mach_exit, .-sun4v_mach_exit
|
||||
|
||||
/* %o0: buffer real address
|
||||
* %o1: buffer length
|
||||
* %o2: pointer to unsigned long real_buf_len
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_mach_desc
|
||||
.type sun4v_mach_desc,#function
|
||||
sun4v_mach_desc:
|
||||
mov %o2, %o4
|
||||
mov HV_FAST_MACH_DESC, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%o4]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_mach_desc, .-sun4v_mach_desc
|
||||
|
||||
/* %o0: new timeout in milliseconds
|
||||
* %o1: pointer to unsigned long orig_timeout
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_mach_set_watchdog
|
||||
.type sun4v_mach_set_watchdog,#function
|
||||
sun4v_mach_set_watchdog:
|
||||
mov %o1, %o4
|
||||
mov HV_FAST_MACH_SET_WATCHDOG, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%o4]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_mach_set_watchdog, .-sun4v_mach_set_watchdog
|
||||
|
||||
/* No inputs and does not return. */
|
||||
.globl sun4v_mach_sir
|
||||
.type sun4v_mach_sir,#function
|
||||
sun4v_mach_sir:
|
||||
mov %o1, %o4
|
||||
mov HV_FAST_MACH_SIR, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%o4]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_mach_sir, .-sun4v_mach_sir
|
||||
|
||||
/* %o0: channel
|
||||
* %o1: ra
|
||||
* %o2: num_entries
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_ldc_tx_qconf
|
||||
.type sun4v_ldc_tx_qconf,#function
|
||||
sun4v_ldc_tx_qconf:
|
||||
mov HV_FAST_LDC_TX_QCONF, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_ldc_tx_qconf, .-sun4v_ldc_tx_qconf
|
||||
|
||||
/* %o0: channel
|
||||
* %o1: pointer to unsigned long ra
|
||||
* %o2: pointer to unsigned long num_entries
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_ldc_tx_qinfo
|
||||
.type sun4v_ldc_tx_qinfo,#function
|
||||
sun4v_ldc_tx_qinfo:
|
||||
mov %o1, %g1
|
||||
mov %o2, %g2
|
||||
mov HV_FAST_LDC_TX_QINFO, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%g1]
|
||||
stx %o2, [%g2]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_ldc_tx_qinfo, .-sun4v_ldc_tx_qinfo
|
||||
|
||||
/* %o0: channel
|
||||
* %o1: pointer to unsigned long head_off
|
||||
* %o2: pointer to unsigned long tail_off
|
||||
* %o2: pointer to unsigned long chan_state
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_ldc_tx_get_state
|
||||
.type sun4v_ldc_tx_get_state,#function
|
||||
sun4v_ldc_tx_get_state:
|
||||
mov %o1, %g1
|
||||
mov %o2, %g2
|
||||
mov %o3, %g3
|
||||
mov HV_FAST_LDC_TX_GET_STATE, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%g1]
|
||||
stx %o2, [%g2]
|
||||
stx %o3, [%g3]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_ldc_tx_get_state, .-sun4v_ldc_tx_get_state
|
||||
|
||||
/* %o0: channel
|
||||
* %o1: tail_off
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_ldc_tx_set_qtail
|
||||
.type sun4v_ldc_tx_set_qtail,#function
|
||||
sun4v_ldc_tx_set_qtail:
|
||||
mov HV_FAST_LDC_TX_SET_QTAIL, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_ldc_tx_set_qtail, .-sun4v_ldc_tx_set_qtail
|
||||
|
||||
/* %o0: channel
|
||||
* %o1: ra
|
||||
* %o2: num_entries
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_ldc_rx_qconf
|
||||
.type sun4v_ldc_rx_qconf,#function
|
||||
sun4v_ldc_rx_qconf:
|
||||
mov HV_FAST_LDC_RX_QCONF, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_ldc_rx_qconf, .-sun4v_ldc_rx_qconf
|
||||
|
||||
/* %o0: channel
|
||||
* %o1: pointer to unsigned long ra
|
||||
* %o2: pointer to unsigned long num_entries
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_ldc_rx_qinfo
|
||||
.type sun4v_ldc_rx_qinfo,#function
|
||||
sun4v_ldc_rx_qinfo:
|
||||
mov %o1, %g1
|
||||
mov %o2, %g2
|
||||
mov HV_FAST_LDC_RX_QINFO, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%g1]
|
||||
stx %o2, [%g2]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_ldc_rx_qinfo, .-sun4v_ldc_rx_qinfo
|
||||
|
||||
/* %o0: channel
|
||||
* %o1: pointer to unsigned long head_off
|
||||
* %o2: pointer to unsigned long tail_off
|
||||
* %o2: pointer to unsigned long chan_state
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_ldc_rx_get_state
|
||||
.type sun4v_ldc_rx_get_state,#function
|
||||
sun4v_ldc_rx_get_state:
|
||||
mov %o1, %g1
|
||||
mov %o2, %g2
|
||||
mov %o3, %g3
|
||||
mov HV_FAST_LDC_RX_GET_STATE, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%g1]
|
||||
stx %o2, [%g2]
|
||||
stx %o3, [%g3]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_ldc_rx_get_state, .-sun4v_ldc_rx_get_state
|
||||
|
||||
/* %o0: channel
|
||||
* %o1: head_off
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_ldc_rx_set_qhead
|
||||
.type sun4v_ldc_rx_set_qhead,#function
|
||||
sun4v_ldc_rx_set_qhead:
|
||||
mov HV_FAST_LDC_RX_SET_QHEAD, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_ldc_rx_set_qhead, .-sun4v_ldc_rx_set_qhead
|
||||
|
||||
/* %o0: channel
|
||||
* %o1: ra
|
||||
* %o2: num_entries
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_ldc_set_map_table
|
||||
.type sun4v_ldc_set_map_table,#function
|
||||
sun4v_ldc_set_map_table:
|
||||
mov HV_FAST_LDC_SET_MAP_TABLE, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_ldc_set_map_table, .-sun4v_ldc_set_map_table
|
||||
|
||||
/* %o0: channel
|
||||
* %o1: pointer to unsigned long ra
|
||||
* %o2: pointer to unsigned long num_entries
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_ldc_get_map_table
|
||||
.type sun4v_ldc_get_map_table,#function
|
||||
sun4v_ldc_get_map_table:
|
||||
mov %o1, %g1
|
||||
mov %o2, %g2
|
||||
mov HV_FAST_LDC_GET_MAP_TABLE, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%g1]
|
||||
stx %o2, [%g2]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_ldc_get_map_table, .-sun4v_ldc_get_map_table
|
||||
|
||||
/* %o0: channel
|
||||
* %o1: dir_code
|
||||
* %o2: tgt_raddr
|
||||
* %o3: lcl_raddr
|
||||
* %o4: len
|
||||
* %o5: pointer to unsigned long actual_len
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_ldc_copy
|
||||
.type sun4v_ldc_copy,#function
|
||||
sun4v_ldc_copy:
|
||||
mov %o5, %g1
|
||||
mov HV_FAST_LDC_COPY, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%g1]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_ldc_copy, .-sun4v_ldc_copy
|
||||
|
||||
/* %o0: channel
|
||||
* %o1: cookie
|
||||
* %o2: pointer to unsigned long ra
|
||||
* %o3: pointer to unsigned long perm
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_ldc_mapin
|
||||
.type sun4v_ldc_mapin,#function
|
||||
sun4v_ldc_mapin:
|
||||
mov %o2, %g1
|
||||
mov %o3, %g2
|
||||
mov HV_FAST_LDC_MAPIN, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%g1]
|
||||
stx %o2, [%g2]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_ldc_mapin, .-sun4v_ldc_mapin
|
||||
|
||||
/* %o0: ra
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_ldc_unmap
|
||||
.type sun4v_ldc_unmap,#function
|
||||
sun4v_ldc_unmap:
|
||||
mov HV_FAST_LDC_UNMAP, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_ldc_unmap, .-sun4v_ldc_unmap
|
||||
|
||||
/* %o0: channel
|
||||
* %o1: cookie
|
||||
* %o2: mte_cookie
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_ldc_revoke
|
||||
.type sun4v_ldc_revoke,#function
|
||||
sun4v_ldc_revoke:
|
||||
mov HV_FAST_LDC_REVOKE, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_ldc_revoke, .-sun4v_ldc_revoke
|
||||
|
||||
/* %o0: device handle
|
||||
* %o1: device INO
|
||||
* %o2: pointer to unsigned long cookie
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_vintr_get_cookie
|
||||
.type sun4v_vintr_get_cookie,#function
|
||||
sun4v_vintr_get_cookie:
|
||||
mov %o2, %g1
|
||||
mov HV_FAST_VINTR_GET_COOKIE, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%g1]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_vintr_get_cookie, .-sun4v_vintr_get_cookie
|
||||
|
||||
/* %o0: device handle
|
||||
* %o1: device INO
|
||||
* %o2: cookie
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_vintr_set_cookie
|
||||
.type sun4v_vintr_set_cookie,#function
|
||||
sun4v_vintr_set_cookie:
|
||||
mov HV_FAST_VINTR_SET_COOKIE, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_vintr_set_cookie, .-sun4v_vintr_set_cookie
|
||||
|
||||
/* %o0: device handle
|
||||
* %o1: device INO
|
||||
* %o2: pointer to unsigned long valid_state
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_vintr_get_valid
|
||||
.type sun4v_vintr_get_valid,#function
|
||||
sun4v_vintr_get_valid:
|
||||
mov %o2, %g1
|
||||
mov HV_FAST_VINTR_GET_VALID, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%g1]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_vintr_get_valid, .-sun4v_vintr_get_valid
|
||||
|
||||
/* %o0: device handle
|
||||
* %o1: device INO
|
||||
* %o2: valid_state
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_vintr_set_valid
|
||||
.type sun4v_vintr_set_valid,#function
|
||||
sun4v_vintr_set_valid:
|
||||
mov HV_FAST_VINTR_SET_VALID, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_vintr_set_valid, .-sun4v_vintr_set_valid
|
||||
|
||||
/* %o0: device handle
|
||||
* %o1: device INO
|
||||
* %o2: pointer to unsigned long state
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_vintr_get_state
|
||||
.type sun4v_vintr_get_state,#function
|
||||
sun4v_vintr_get_state:
|
||||
mov %o2, %g1
|
||||
mov HV_FAST_VINTR_GET_STATE, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%g1]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_vintr_get_state, .-sun4v_vintr_get_state
|
||||
|
||||
/* %o0: device handle
|
||||
* %o1: device INO
|
||||
* %o2: state
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_vintr_set_state
|
||||
.type sun4v_vintr_set_state,#function
|
||||
sun4v_vintr_set_state:
|
||||
mov HV_FAST_VINTR_SET_STATE, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_vintr_set_state, .-sun4v_vintr_set_state
|
||||
|
||||
/* %o0: device handle
|
||||
* %o1: device INO
|
||||
* %o2: pointer to unsigned long cpuid
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_vintr_get_target
|
||||
.type sun4v_vintr_get_target,#function
|
||||
sun4v_vintr_get_target:
|
||||
mov %o2, %g1
|
||||
mov HV_FAST_VINTR_GET_TARGET, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%g1]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_vintr_get_target, .-sun4v_vintr_get_target
|
||||
|
||||
/* %o0: device handle
|
||||
* %o1: device INO
|
||||
* %o2: cpuid
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_vintr_set_target
|
||||
.type sun4v_vintr_set_target,#function
|
||||
sun4v_vintr_set_target:
|
||||
mov HV_FAST_VINTR_SET_TARGET, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_vintr_set_target, .-sun4v_vintr_set_target
|
||||
|
||||
/* %o0: NCS sub-function
|
||||
* %o1: sub-function arg real-address
|
||||
* %o2: sub-function arg size
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_ncs_request
|
||||
.type sun4v_ncs_request,#function
|
||||
sun4v_ncs_request:
|
||||
mov HV_FAST_NCS_REQUEST, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_ncs_request, .-sun4v_ncs_request
|
||||
|
||||
.globl sun4v_svc_send
|
||||
.type sun4v_svc_send,#function
|
||||
sun4v_svc_send:
|
||||
save %sp, -192, %sp
|
||||
mov %i0, %o0
|
||||
mov %i1, %o1
|
||||
mov %i2, %o2
|
||||
mov HV_FAST_SVC_SEND, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%i3]
|
||||
ret
|
||||
restore
|
||||
.size sun4v_svc_send, .-sun4v_svc_send
|
||||
|
||||
.globl sun4v_svc_recv
|
||||
.type sun4v_svc_recv,#function
|
||||
sun4v_svc_recv:
|
||||
save %sp, -192, %sp
|
||||
mov %i0, %o0
|
||||
mov %i1, %o1
|
||||
mov %i2, %o2
|
||||
mov HV_FAST_SVC_RECV, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%i3]
|
||||
ret
|
||||
restore
|
||||
.size sun4v_svc_recv, .-sun4v_svc_recv
|
||||
|
||||
.globl sun4v_svc_getstatus
|
||||
.type sun4v_svc_getstatus,#function
|
||||
sun4v_svc_getstatus:
|
||||
mov HV_FAST_SVC_GETSTATUS, %o5
|
||||
mov %o1, %o4
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%o4]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_svc_getstatus, .-sun4v_svc_getstatus
|
||||
|
||||
.globl sun4v_svc_setstatus
|
||||
.type sun4v_svc_setstatus,#function
|
||||
sun4v_svc_setstatus:
|
||||
mov HV_FAST_SVC_SETSTATUS, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_svc_setstatus, .-sun4v_svc_setstatus
|
||||
|
||||
.globl sun4v_svc_clrstatus
|
||||
.type sun4v_svc_clrstatus,#function
|
||||
sun4v_svc_clrstatus:
|
||||
mov HV_FAST_SVC_CLRSTATUS, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_svc_clrstatus, .-sun4v_svc_clrstatus
|
||||
|
||||
.globl sun4v_mmustat_conf
|
||||
.type sun4v_mmustat_conf,#function
|
||||
sun4v_mmustat_conf:
|
||||
mov %o1, %o4
|
||||
mov HV_FAST_MMUSTAT_CONF, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%o4]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_mmustat_conf, .-sun4v_mmustat_conf
|
||||
|
||||
.globl sun4v_mmustat_info
|
||||
.type sun4v_mmustat_info,#function
|
||||
sun4v_mmustat_info:
|
||||
mov %o0, %o4
|
||||
mov HV_FAST_MMUSTAT_INFO, %o5
|
||||
ta HV_FAST_TRAP
|
||||
stx %o1, [%o4]
|
||||
retl
|
||||
nop
|
||||
.size sun4v_mmustat_info, .-sun4v_mmustat_info
|
||||
|
||||
.globl sun4v_mmu_demap_all
|
||||
.type sun4v_mmu_demap_all,#function
|
||||
sun4v_mmu_demap_all:
|
||||
clr %o0
|
||||
clr %o1
|
||||
mov HV_MMU_ALL, %o2
|
||||
mov HV_FAST_MMU_DEMAP_ALL, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
.size sun4v_mmu_demap_all, .-sun4v_mmu_demap_all
|
51
arch/sparc64/kernel/ivec.S
Normal file
51
arch/sparc64/kernel/ivec.S
Normal file
|
@ -0,0 +1,51 @@
|
|||
/* The registers for cross calls will be:
|
||||
*
|
||||
* DATA 0: [low 32-bits] Address of function to call, jmp to this
|
||||
* [high 32-bits] MMU Context Argument 0, place in %g5
|
||||
* DATA 1: Address Argument 1, place in %g1
|
||||
* DATA 2: Address Argument 2, place in %g7
|
||||
*
|
||||
* With this method we can do most of the cross-call tlb/cache
|
||||
* flushing very quickly.
|
||||
*/
|
||||
.align 32
|
||||
.globl do_ivec
|
||||
.type do_ivec,#function
|
||||
do_ivec:
|
||||
mov 0x40, %g3
|
||||
ldxa [%g3 + %g0] ASI_INTR_R, %g3
|
||||
sethi %hi(KERNBASE), %g4
|
||||
cmp %g3, %g4
|
||||
bgeu,pn %xcc, do_ivec_xcall
|
||||
srlx %g3, 32, %g5
|
||||
stxa %g0, [%g0] ASI_INTR_RECEIVE
|
||||
membar #Sync
|
||||
|
||||
sethi %hi(ivector_table_pa), %g2
|
||||
ldx [%g2 + %lo(ivector_table_pa)], %g2
|
||||
sllx %g3, 4, %g3
|
||||
add %g2, %g3, %g3
|
||||
|
||||
TRAP_LOAD_IRQ_WORK_PA(%g6, %g1)
|
||||
|
||||
ldx [%g6], %g5
|
||||
stxa %g5, [%g3] ASI_PHYS_USE_EC
|
||||
stx %g3, [%g6]
|
||||
wr %g0, 1 << PIL_DEVICE_IRQ, %set_softint
|
||||
retry
|
||||
do_ivec_xcall:
|
||||
mov 0x50, %g1
|
||||
ldxa [%g1 + %g0] ASI_INTR_R, %g1
|
||||
srl %g3, 0, %g3
|
||||
|
||||
mov 0x60, %g7
|
||||
ldxa [%g7 + %g0] ASI_INTR_R, %g7
|
||||
stxa %g0, [%g0] ASI_INTR_RECEIVE
|
||||
membar #Sync
|
||||
ba,pt %xcc, 1f
|
||||
nop
|
||||
|
||||
.align 32
|
||||
1: jmpl %g3, %g0
|
||||
nop
|
||||
.size do_ivec,.-do_ivec
|
186
arch/sparc64/kernel/kgdb.c
Normal file
186
arch/sparc64/kernel/kgdb.c
Normal file
|
@ -0,0 +1,186 @@
|
|||
/* kgdb.c: KGDB support for 64-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>
|
||||
|
||||
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] + STACK_BIAS);
|
||||
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_F62; i++)
|
||||
gdb_regs[i] = 0;
|
||||
|
||||
gdb_regs[GDB_PC] = regs->tpc;
|
||||
gdb_regs[GDB_NPC] = regs->tnpc;
|
||||
gdb_regs[GDB_STATE] = regs->tstate;
|
||||
gdb_regs[GDB_FSR] = 0;
|
||||
gdb_regs[GDB_FPRS] = 0;
|
||||
gdb_regs[GDB_Y] = regs->y;
|
||||
}
|
||||
|
||||
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
|
||||
{
|
||||
struct thread_info *t = task_thread_info(p);
|
||||
extern unsigned int switch_to_pc;
|
||||
extern unsigned int ret_from_syscall;
|
||||
struct reg_window *win;
|
||||
unsigned long pc, cwp;
|
||||
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] = (unsigned long) p;
|
||||
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 + STACK_BIAS);
|
||||
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_F62; i++)
|
||||
gdb_regs[i] = 0;
|
||||
|
||||
if (t->new_child)
|
||||
pc = (unsigned long) &ret_from_syscall;
|
||||
else
|
||||
pc = (unsigned long) &switch_to_pc;
|
||||
|
||||
gdb_regs[GDB_PC] = pc;
|
||||
gdb_regs[GDB_NPC] = pc + 4;
|
||||
|
||||
cwp = __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP];
|
||||
|
||||
gdb_regs[GDB_STATE] = (TSTATE_PRIV | TSTATE_IE | cwp);
|
||||
gdb_regs[GDB_FSR] = 0;
|
||||
gdb_regs[GDB_FPRS] = 0;
|
||||
gdb_regs[GDB_Y] = 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 TSTATE register is changing, we have to preserve
|
||||
* the CWP field, otherwise window save/restore explodes.
|
||||
*/
|
||||
if (regs->tstate != gdb_regs[GDB_STATE]) {
|
||||
unsigned long cwp = regs->tstate & TSTATE_CWP;
|
||||
|
||||
regs->tstate = (gdb_regs[GDB_STATE] & ~TSTATE_CWP) | cwp;
|
||||
}
|
||||
|
||||
regs->tpc = gdb_regs[GDB_PC];
|
||||
regs->tnpc = gdb_regs[GDB_NPC];
|
||||
regs->y = gdb_regs[GDB_Y];
|
||||
|
||||
win = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS);
|
||||
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];
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void smp_kgdb_capture_client(struct pt_regs *regs)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
__asm__ __volatile__("rdpr %%pstate, %0\n\t"
|
||||
"wrpr %0, %1, %%pstate"
|
||||
: "=r" (flags)
|
||||
: "i" (PSTATE_IE));
|
||||
|
||||
flushw_all();
|
||||
|
||||
if (atomic_read(&kgdb_active) != -1)
|
||||
kgdb_nmicallback(raw_smp_processor_id(), regs);
|
||||
|
||||
__asm__ __volatile__("wrpr %0, 0, %%pstate"
|
||||
: : "r" (flags));
|
||||
}
|
||||
#endif
|
||||
|
||||
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->tpc = addr;
|
||||
linux_regs->tnpc = addr + 4;
|
||||
}
|
||||
/* fallthru */
|
||||
|
||||
case 'D':
|
||||
case 'k':
|
||||
if (linux_regs->tpc == (unsigned long) arch_kgdb_breakpoint) {
|
||||
linux_regs->tpc = linux_regs->tnpc;
|
||||
linux_regs->tnpc += 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (user_mode(regs)) {
|
||||
bad_trap(regs, trap_level);
|
||||
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 0x72 */
|
||||
.gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x72 },
|
||||
};
|
97
arch/sparc64/kernel/misctrap.S
Normal file
97
arch/sparc64/kernel/misctrap.S
Normal file
|
@ -0,0 +1,97 @@
|
|||
#ifdef CONFIG_KGDB
|
||||
.globl arch_kgdb_breakpoint
|
||||
.type arch_kgdb_breakpoint,#function
|
||||
arch_kgdb_breakpoint:
|
||||
ta 0x72
|
||||
retl
|
||||
nop
|
||||
.size arch_kgdb_breakpoint,.-arch_kgdb_breakpoint
|
||||
#endif
|
||||
|
||||
.type __do_privact,#function
|
||||
__do_privact:
|
||||
mov TLB_SFSR, %g3
|
||||
stxa %g0, [%g3] ASI_DMMU ! Clear FaultValid bit
|
||||
membar #Sync
|
||||
sethi %hi(109f), %g7
|
||||
ba,pt %xcc, etrap
|
||||
109: or %g7, %lo(109b), %g7
|
||||
call do_privact
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
nop
|
||||
.size __do_privact,.-__do_privact
|
||||
|
||||
.type do_mna,#function
|
||||
do_mna:
|
||||
rdpr %tl, %g3
|
||||
cmp %g3, 1
|
||||
|
||||
/* Setup %g4/%g5 now as they are used in the
|
||||
* winfixup code.
|
||||
*/
|
||||
mov TLB_SFSR, %g3
|
||||
mov DMMU_SFAR, %g4
|
||||
ldxa [%g4] ASI_DMMU, %g4
|
||||
ldxa [%g3] ASI_DMMU, %g5
|
||||
stxa %g0, [%g3] ASI_DMMU ! Clear FaultValid bit
|
||||
membar #Sync
|
||||
bgu,pn %icc, winfix_mna
|
||||
rdpr %tpc, %g3
|
||||
|
||||
1: sethi %hi(109f), %g7
|
||||
ba,pt %xcc, etrap
|
||||
109: or %g7, %lo(109b), %g7
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call mem_address_unaligned
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
nop
|
||||
.size do_mna,.-do_mna
|
||||
|
||||
.type do_lddfmna,#function
|
||||
do_lddfmna:
|
||||
sethi %hi(109f), %g7
|
||||
mov TLB_SFSR, %g4
|
||||
ldxa [%g4] ASI_DMMU, %g5
|
||||
stxa %g0, [%g4] ASI_DMMU ! Clear FaultValid bit
|
||||
membar #Sync
|
||||
mov DMMU_SFAR, %g4
|
||||
ldxa [%g4] ASI_DMMU, %g4
|
||||
ba,pt %xcc, etrap
|
||||
109: or %g7, %lo(109b), %g7
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call handle_lddfmna
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
nop
|
||||
.size do_lddfmna,.-do_lddfmna
|
||||
|
||||
.type do_stdfmna,#function
|
||||
do_stdfmna:
|
||||
sethi %hi(109f), %g7
|
||||
mov TLB_SFSR, %g4
|
||||
ldxa [%g4] ASI_DMMU, %g5
|
||||
stxa %g0, [%g4] ASI_DMMU ! Clear FaultValid bit
|
||||
membar #Sync
|
||||
mov DMMU_SFAR, %g4
|
||||
ldxa [%g4] ASI_DMMU, %g4
|
||||
ba,pt %xcc, etrap
|
||||
109: or %g7, %lo(109b), %g7
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call handle_stdfmna
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
nop
|
||||
.size do_stdfmna,.-do_stdfmna
|
||||
|
||||
.type breakpoint_trap,#function
|
||||
breakpoint_trap:
|
||||
call sparc_breakpoint
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
nop
|
||||
.size breakpoint_trap,.-breakpoint_trap
|
|
@ -38,7 +38,6 @@
|
|||
#include <asm/pgtable.h>
|
||||
#include <asm/oplib.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/timer.h>
|
||||
#include <asm/starfire.h>
|
||||
#include <asm/tlb.h>
|
||||
#include <asm/sections.h>
|
||||
|
@ -910,6 +909,9 @@ extern unsigned long xcall_flush_tlb_kernel_range;
|
|||
extern unsigned long xcall_report_regs;
|
||||
extern unsigned long xcall_receive_signal;
|
||||
extern unsigned long xcall_new_mmu_context_version;
|
||||
#ifdef CONFIG_KGDB
|
||||
extern unsigned long xcall_kgdb_capture;
|
||||
#endif
|
||||
|
||||
#ifdef DCACHE_ALIASING_POSSIBLE
|
||||
extern unsigned long xcall_flush_dcache_page_cheetah;
|
||||
|
@ -1079,6 +1081,13 @@ void smp_new_mmu_context_version(void)
|
|||
smp_cross_call(&xcall_new_mmu_context_version, 0, 0, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KGDB
|
||||
void kgdb_roundup_cpus(unsigned long flags)
|
||||
{
|
||||
smp_cross_call(&xcall_kgdb_capture, 0, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void smp_report_regs(void)
|
||||
{
|
||||
smp_cross_call(&xcall_report_regs, 0, 0, 0);
|
||||
|
|
245
arch/sparc64/kernel/spiterrs.S
Normal file
245
arch/sparc64/kernel/spiterrs.S
Normal file
|
@ -0,0 +1,245 @@
|
|||
/* We need to carefully read the error status, ACK the errors,
|
||||
* prevent recursive traps, and pass the information on to C
|
||||
* code for logging.
|
||||
*
|
||||
* We pass the AFAR in as-is, and we encode the status
|
||||
* information as described in asm-sparc64/sfafsr.h
|
||||
*/
|
||||
.type __spitfire_access_error,#function
|
||||
__spitfire_access_error:
|
||||
/* Disable ESTATE error reporting so that we do not take
|
||||
* recursive traps and RED state the processor.
|
||||
*/
|
||||
stxa %g0, [%g0] ASI_ESTATE_ERROR_EN
|
||||
membar #Sync
|
||||
|
||||
mov UDBE_UE, %g1
|
||||
ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
|
||||
|
||||
/* __spitfire_cee_trap branches here with AFSR in %g4 and
|
||||
* UDBE_CE in %g1. It only clears ESTATE_ERR_CE in the ESTATE
|
||||
* Error Enable register.
|
||||
*/
|
||||
__spitfire_cee_trap_continue:
|
||||
ldxa [%g0] ASI_AFAR, %g5 ! Get AFAR
|
||||
|
||||
rdpr %tt, %g3
|
||||
and %g3, 0x1ff, %g3 ! Paranoia
|
||||
sllx %g3, SFSTAT_TRAP_TYPE_SHIFT, %g3
|
||||
or %g4, %g3, %g4
|
||||
rdpr %tl, %g3
|
||||
cmp %g3, 1
|
||||
mov 1, %g3
|
||||
bleu %xcc, 1f
|
||||
sllx %g3, SFSTAT_TL_GT_ONE_SHIFT, %g3
|
||||
|
||||
or %g4, %g3, %g4
|
||||
|
||||
/* Read in the UDB error register state, clearing the sticky
|
||||
* error bits as-needed. We only clear them if the UE bit is
|
||||
* set. Likewise, __spitfire_cee_trap below will only do so
|
||||
* if the CE bit is set.
|
||||
*
|
||||
* NOTE: UltraSparc-I/II have high and low UDB error
|
||||
* registers, corresponding to the two UDB units
|
||||
* present on those chips. UltraSparc-IIi only
|
||||
* has a single UDB, called "SDB" in the manual.
|
||||
* For IIi the upper UDB register always reads
|
||||
* as zero so for our purposes things will just
|
||||
* work with the checks below.
|
||||
*/
|
||||
1: ldxa [%g0] ASI_UDBH_ERROR_R, %g3
|
||||
and %g3, 0x3ff, %g7 ! Paranoia
|
||||
sllx %g7, SFSTAT_UDBH_SHIFT, %g7
|
||||
or %g4, %g7, %g4
|
||||
andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
|
||||
be,pn %xcc, 1f
|
||||
nop
|
||||
stxa %g3, [%g0] ASI_UDB_ERROR_W
|
||||
membar #Sync
|
||||
|
||||
1: mov 0x18, %g3
|
||||
ldxa [%g3] ASI_UDBL_ERROR_R, %g3
|
||||
and %g3, 0x3ff, %g7 ! Paranoia
|
||||
sllx %g7, SFSTAT_UDBL_SHIFT, %g7
|
||||
or %g4, %g7, %g4
|
||||
andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
|
||||
be,pn %xcc, 1f
|
||||
nop
|
||||
mov 0x18, %g7
|
||||
stxa %g3, [%g7] ASI_UDB_ERROR_W
|
||||
membar #Sync
|
||||
|
||||
1: /* Ok, now that we've latched the error state, clear the
|
||||
* sticky bits in the AFSR.
|
||||
*/
|
||||
stxa %g4, [%g0] ASI_AFSR
|
||||
membar #Sync
|
||||
|
||||
rdpr %tl, %g2
|
||||
cmp %g2, 1
|
||||
rdpr %pil, %g2
|
||||
bleu,pt %xcc, 1f
|
||||
wrpr %g0, 15, %pil
|
||||
|
||||
ba,pt %xcc, etraptl1
|
||||
rd %pc, %g7
|
||||
|
||||
ba,pt %xcc, 2f
|
||||
nop
|
||||
|
||||
1: ba,pt %xcc, etrap_irq
|
||||
rd %pc, %g7
|
||||
|
||||
2:
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
call trace_hardirqs_off
|
||||
nop
|
||||
#endif
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call spitfire_access_error
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
nop
|
||||
.size __spitfire_access_error,.-__spitfire_access_error
|
||||
|
||||
/* This is the trap handler entry point for ECC correctable
|
||||
* errors. They are corrected, but we listen for the trap so
|
||||
* that the event can be logged.
|
||||
*
|
||||
* Disrupting errors are either:
|
||||
* 1) single-bit ECC errors during UDB reads to system
|
||||
* memory
|
||||
* 2) data parity errors during write-back events
|
||||
*
|
||||
* As far as I can make out from the manual, the CEE trap is
|
||||
* only for correctable errors during memory read accesses by
|
||||
* the front-end of the processor.
|
||||
*
|
||||
* The code below is only for trap level 1 CEE events, as it
|
||||
* is the only situation where we can safely record and log.
|
||||
* For trap level >1 we just clear the CE bit in the AFSR and
|
||||
* return.
|
||||
*
|
||||
* This is just like __spiftire_access_error above, but it
|
||||
* specifically handles correctable errors. If an
|
||||
* uncorrectable error is indicated in the AFSR we will branch
|
||||
* directly above to __spitfire_access_error to handle it
|
||||
* instead. Uncorrectable therefore takes priority over
|
||||
* correctable, and the error logging C code will notice this
|
||||
* case by inspecting the trap type.
|
||||
*/
|
||||
.type __spitfire_cee_trap,#function
|
||||
__spitfire_cee_trap:
|
||||
ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
|
||||
mov 1, %g3
|
||||
sllx %g3, SFAFSR_UE_SHIFT, %g3
|
||||
andcc %g4, %g3, %g0 ! Check for UE
|
||||
bne,pn %xcc, __spitfire_access_error
|
||||
nop
|
||||
|
||||
/* Ok, in this case we only have a correctable error.
|
||||
* Indicate we only wish to capture that state in register
|
||||
* %g1, and we only disable CE error reporting unlike UE
|
||||
* handling which disables all errors.
|
||||
*/
|
||||
ldxa [%g0] ASI_ESTATE_ERROR_EN, %g3
|
||||
andn %g3, ESTATE_ERR_CE, %g3
|
||||
stxa %g3, [%g0] ASI_ESTATE_ERROR_EN
|
||||
membar #Sync
|
||||
|
||||
/* Preserve AFSR in %g4, indicate UDB state to capture in %g1 */
|
||||
ba,pt %xcc, __spitfire_cee_trap_continue
|
||||
mov UDBE_CE, %g1
|
||||
.size __spitfire_cee_trap,.-__spitfire_cee_trap
|
||||
|
||||
.type __spitfire_data_access_exception_tl1,#function
|
||||
__spitfire_data_access_exception_tl1:
|
||||
rdpr %pstate, %g4
|
||||
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
|
||||
mov TLB_SFSR, %g3
|
||||
mov DMMU_SFAR, %g5
|
||||
ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
|
||||
ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
|
||||
stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit
|
||||
membar #Sync
|
||||
rdpr %tt, %g3
|
||||
cmp %g3, 0x80 ! first win spill/fill trap
|
||||
blu,pn %xcc, 1f
|
||||
cmp %g3, 0xff ! last win spill/fill trap
|
||||
bgu,pn %xcc, 1f
|
||||
nop
|
||||
ba,pt %xcc, winfix_dax
|
||||
rdpr %tpc, %g3
|
||||
1: sethi %hi(109f), %g7
|
||||
ba,pt %xcc, etraptl1
|
||||
109: or %g7, %lo(109b), %g7
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call spitfire_data_access_exception_tl1
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
nop
|
||||
.size __spitfire_data_access_exception_tl1,.-__spitfire_data_access_exception_tl1
|
||||
|
||||
.type __spitfire_data_access_exception,#function
|
||||
__spitfire_data_access_exception:
|
||||
rdpr %pstate, %g4
|
||||
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
|
||||
mov TLB_SFSR, %g3
|
||||
mov DMMU_SFAR, %g5
|
||||
ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR
|
||||
ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
|
||||
stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit
|
||||
membar #Sync
|
||||
sethi %hi(109f), %g7
|
||||
ba,pt %xcc, etrap
|
||||
109: or %g7, %lo(109b), %g7
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call spitfire_data_access_exception
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
nop
|
||||
.size __spitfire_data_access_exception,.-__spitfire_data_access_exception
|
||||
|
||||
.type __spitfire_insn_access_exception_tl1,#function
|
||||
__spitfire_insn_access_exception_tl1:
|
||||
rdpr %pstate, %g4
|
||||
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
|
||||
mov TLB_SFSR, %g3
|
||||
ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR
|
||||
rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC
|
||||
stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
|
||||
membar #Sync
|
||||
sethi %hi(109f), %g7
|
||||
ba,pt %xcc, etraptl1
|
||||
109: or %g7, %lo(109b), %g7
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call spitfire_insn_access_exception_tl1
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
nop
|
||||
.size __spitfire_insn_access_exception_tl1,.-__spitfire_insn_access_exception_tl1
|
||||
|
||||
.type __spitfire_insn_access_exception,#function
|
||||
__spitfire_insn_access_exception:
|
||||
rdpr %pstate, %g4
|
||||
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
|
||||
mov TLB_SFSR, %g3
|
||||
ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR
|
||||
rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC
|
||||
stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
|
||||
membar #Sync
|
||||
sethi %hi(109f), %g7
|
||||
ba,pt %xcc, etrap
|
||||
109: or %g7, %lo(109b), %g7
|
||||
mov %l4, %o1
|
||||
mov %l5, %o2
|
||||
call spitfire_insn_access_exception
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
nop
|
||||
.size __spitfire_insn_access_exception,.-__spitfire_insn_access_exception
|
279
arch/sparc64/kernel/syscalls.S
Normal file
279
arch/sparc64/kernel/syscalls.S
Normal file
|
@ -0,0 +1,279 @@
|
|||
/* SunOS's execv() call only specifies the argv argument, the
|
||||
* environment settings are the same as the calling processes.
|
||||
*/
|
||||
sys_execve:
|
||||
sethi %hi(sparc_execve), %g1
|
||||
ba,pt %xcc, execve_merge
|
||||
or %g1, %lo(sparc_execve), %g1
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
sunos_execv:
|
||||
stx %g0, [%sp + PTREGS_OFF + PT_V9_I2]
|
||||
sys32_execve:
|
||||
sethi %hi(sparc32_execve), %g1
|
||||
or %g1, %lo(sparc32_execve), %g1
|
||||
#endif
|
||||
|
||||
execve_merge:
|
||||
flushw
|
||||
jmpl %g1, %g0
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
|
||||
.align 32
|
||||
sys_pipe:
|
||||
ba,pt %xcc, sparc_pipe
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
sys_nis_syscall:
|
||||
ba,pt %xcc, c_sys_nis_syscall
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
sys_memory_ordering:
|
||||
ba,pt %xcc, sparc_memory_ordering
|
||||
add %sp, PTREGS_OFF, %o1
|
||||
sys_sigaltstack:
|
||||
ba,pt %xcc, do_sigaltstack
|
||||
add %i6, STACK_BIAS, %o2
|
||||
#ifdef CONFIG_COMPAT
|
||||
sys32_sigstack:
|
||||
ba,pt %xcc, do_sys32_sigstack
|
||||
mov %i6, %o2
|
||||
sys32_sigaltstack:
|
||||
ba,pt %xcc, do_sys32_sigaltstack
|
||||
mov %i6, %o2
|
||||
#endif
|
||||
.align 32
|
||||
#ifdef CONFIG_COMPAT
|
||||
sys32_sigreturn:
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
call do_sigreturn32
|
||||
add %o7, 1f-.-4, %o7
|
||||
nop
|
||||
#endif
|
||||
sys_rt_sigreturn:
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
call do_rt_sigreturn
|
||||
add %o7, 1f-.-4, %o7
|
||||
nop
|
||||
#ifdef CONFIG_COMPAT
|
||||
sys32_rt_sigreturn:
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
call do_rt_sigreturn32
|
||||
add %o7, 1f-.-4, %o7
|
||||
nop
|
||||
#endif
|
||||
.align 32
|
||||
1: ldx [%g6 + TI_FLAGS], %l5
|
||||
andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
|
||||
be,pt %icc, rtrap
|
||||
nop
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
call syscall_trace
|
||||
mov 1, %o1
|
||||
ba,pt %xcc, rtrap
|
||||
nop
|
||||
|
||||
/* This is how fork() was meant to be done, 8 instruction entry.
|
||||
*
|
||||
* I questioned the following code briefly, let me clear things
|
||||
* up so you must not reason on it like I did.
|
||||
*
|
||||
* Know the fork_kpsr etc. we use in the sparc32 port? We don't
|
||||
* need it here because the only piece of window state we copy to
|
||||
* the child is the CWP register. Even if the parent sleeps,
|
||||
* we are safe because we stuck it into pt_regs of the parent
|
||||
* so it will not change.
|
||||
*
|
||||
* XXX This raises the question, whether we can do the same on
|
||||
* XXX sparc32 to get rid of fork_kpsr _and_ fork_kwim. The
|
||||
* XXX answer is yes. We stick fork_kpsr in UREG_G0 and
|
||||
* XXX fork_kwim in UREG_G1 (global registers are considered
|
||||
* XXX volatile across a system call in the sparc ABI I think
|
||||
* XXX if it isn't we can use regs->y instead, anyone who depends
|
||||
* XXX upon the Y register being preserved across a fork deserves
|
||||
* XXX to lose).
|
||||
*
|
||||
* In fact we should take advantage of that fact for other things
|
||||
* during system calls...
|
||||
*/
|
||||
.align 32
|
||||
sys_vfork: /* Under Linux, vfork and fork are just special cases of clone. */
|
||||
sethi %hi(0x4000 | 0x0100 | SIGCHLD), %o0
|
||||
or %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
|
||||
ba,pt %xcc, sys_clone
|
||||
sys_fork:
|
||||
clr %o1
|
||||
mov SIGCHLD, %o0
|
||||
sys_clone:
|
||||
flushw
|
||||
movrz %o1, %fp, %o1
|
||||
mov 0, %o3
|
||||
ba,pt %xcc, sparc_do_fork
|
||||
add %sp, PTREGS_OFF, %o2
|
||||
|
||||
.globl ret_from_syscall
|
||||
ret_from_syscall:
|
||||
/* Clear current_thread_info()->new_child, and
|
||||
* check performance counter stuff too.
|
||||
*/
|
||||
stb %g0, [%g6 + TI_NEW_CHILD]
|
||||
ldx [%g6 + TI_FLAGS], %l0
|
||||
call schedule_tail
|
||||
mov %g7, %o0
|
||||
andcc %l0, _TIF_PERFCTR, %g0
|
||||
be,pt %icc, 1f
|
||||
nop
|
||||
ldx [%g6 + TI_PCR], %o7
|
||||
wr %g0, %o7, %pcr
|
||||
|
||||
/* Blackbird errata workaround. See commentary in
|
||||
* smp.c:smp_percpu_timer_interrupt() for more
|
||||
* information.
|
||||
*/
|
||||
ba,pt %xcc, 99f
|
||||
nop
|
||||
|
||||
.align 64
|
||||
99: wr %g0, %g0, %pic
|
||||
rd %pic, %g0
|
||||
|
||||
1: ba,pt %xcc, ret_sys_call
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_I0], %o0
|
||||
|
||||
.globl sparc_exit
|
||||
.type sparc_exit,#function
|
||||
sparc_exit:
|
||||
rdpr %pstate, %g2
|
||||
wrpr %g2, PSTATE_IE, %pstate
|
||||
rdpr %otherwin, %g1
|
||||
rdpr %cansave, %g3
|
||||
add %g3, %g1, %g3
|
||||
wrpr %g3, 0x0, %cansave
|
||||
wrpr %g0, 0x0, %otherwin
|
||||
wrpr %g2, 0x0, %pstate
|
||||
ba,pt %xcc, sys_exit
|
||||
stb %g0, [%g6 + TI_WSAVED]
|
||||
.size sparc_exit,.-sparc_exit
|
||||
|
||||
linux_sparc_ni_syscall:
|
||||
sethi %hi(sys_ni_syscall), %l7
|
||||
ba,pt %xcc, 4f
|
||||
or %l7, %lo(sys_ni_syscall), %l7
|
||||
|
||||
linux_syscall_trace32:
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
call syscall_trace
|
||||
clr %o1
|
||||
srl %i0, 0, %o0
|
||||
srl %i4, 0, %o4
|
||||
srl %i1, 0, %o1
|
||||
srl %i2, 0, %o2
|
||||
ba,pt %xcc, 2f
|
||||
srl %i3, 0, %o3
|
||||
|
||||
linux_syscall_trace:
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
call syscall_trace
|
||||
clr %o1
|
||||
mov %i0, %o0
|
||||
mov %i1, %o1
|
||||
mov %i2, %o2
|
||||
mov %i3, %o3
|
||||
b,pt %xcc, 2f
|
||||
mov %i4, %o4
|
||||
|
||||
|
||||
/* Linux 32-bit system calls enter here... */
|
||||
.align 32
|
||||
.globl linux_sparc_syscall32
|
||||
linux_sparc_syscall32:
|
||||
/* Direct access to user regs, much faster. */
|
||||
cmp %g1, NR_SYSCALLS ! IEU1 Group
|
||||
bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI
|
||||
srl %i0, 0, %o0 ! IEU0
|
||||
sll %g1, 2, %l4 ! IEU0 Group
|
||||
srl %i4, 0, %o4 ! IEU1
|
||||
lduw [%l7 + %l4], %l7 ! Load
|
||||
srl %i1, 0, %o1 ! IEU0 Group
|
||||
ldx [%g6 + TI_FLAGS], %l0 ! Load
|
||||
|
||||
srl %i5, 0, %o5 ! IEU1
|
||||
srl %i2, 0, %o2 ! IEU0 Group
|
||||
andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
|
||||
bne,pn %icc, linux_syscall_trace32 ! CTI
|
||||
mov %i0, %l5 ! IEU1
|
||||
call %l7 ! CTI Group brk forced
|
||||
srl %i3, 0, %o3 ! IEU0
|
||||
ba,a,pt %xcc, 3f
|
||||
|
||||
/* Linux native system calls enter here... */
|
||||
.align 32
|
||||
.globl linux_sparc_syscall
|
||||
linux_sparc_syscall:
|
||||
/* Direct access to user regs, much faster. */
|
||||
cmp %g1, NR_SYSCALLS ! IEU1 Group
|
||||
bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI
|
||||
mov %i0, %o0 ! IEU0
|
||||
sll %g1, 2, %l4 ! IEU0 Group
|
||||
mov %i1, %o1 ! IEU1
|
||||
lduw [%l7 + %l4], %l7 ! Load
|
||||
4: mov %i2, %o2 ! IEU0 Group
|
||||
ldx [%g6 + TI_FLAGS], %l0 ! Load
|
||||
|
||||
mov %i3, %o3 ! IEU1
|
||||
mov %i4, %o4 ! IEU0 Group
|
||||
andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
|
||||
bne,pn %icc, linux_syscall_trace ! CTI Group
|
||||
mov %i0, %l5 ! IEU0
|
||||
2: call %l7 ! CTI Group brk forced
|
||||
mov %i5, %o5 ! IEU0
|
||||
nop
|
||||
|
||||
3: stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
|
||||
ret_sys_call:
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
|
||||
sra %o0, 0, %o0
|
||||
mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
|
||||
sllx %g2, 32, %g2
|
||||
|
||||
/* Check if force_successful_syscall_return()
|
||||
* was invoked.
|
||||
*/
|
||||
ldub [%g6 + TI_SYS_NOERROR], %l2
|
||||
brnz,a,pn %l2, 80f
|
||||
stb %g0, [%g6 + TI_SYS_NOERROR]
|
||||
|
||||
cmp %o0, -ERESTART_RESTARTBLOCK
|
||||
bgeu,pn %xcc, 1f
|
||||
andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6
|
||||
80:
|
||||
/* System call success, clear Carry condition code. */
|
||||
andn %g3, %g2, %g3
|
||||
stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
|
||||
bne,pn %icc, linux_syscall_trace2
|
||||
add %l1, 0x4, %l2 ! npc = npc+4
|
||||
stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
|
||||
ba,pt %xcc, rtrap
|
||||
stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
|
||||
|
||||
1:
|
||||
/* System call failure, set Carry condition code.
|
||||
* Also, get abs(errno) to return to the process.
|
||||
*/
|
||||
andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6
|
||||
sub %g0, %o0, %o0
|
||||
or %g3, %g2, %g3
|
||||
stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
|
||||
stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
|
||||
bne,pn %icc, linux_syscall_trace2
|
||||
add %l1, 0x4, %l2 ! npc = npc+4
|
||||
stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
|
||||
|
||||
b,pt %xcc, rtrap
|
||||
stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
|
||||
linux_syscall_trace2:
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
call syscall_trace
|
||||
mov 1, %o1
|
||||
stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
|
||||
ba,pt %xcc, rtrap
|
||||
stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
|
|
@ -153,7 +153,7 @@ tl0_resv164: BTRAP(0x164) BTRAP(0x165) BTRAP(0x166) BTRAP(0x167) BTRAP(0x168)
|
|||
tl0_resv169: BTRAP(0x169) BTRAP(0x16a) BTRAP(0x16b) BTRAP(0x16c)
|
||||
tl0_linux64: LINUX_64BIT_SYSCALL_TRAP
|
||||
tl0_gsctx: TRAP(sparc64_get_context) TRAP(sparc64_set_context)
|
||||
tl0_resv170: KPROBES_TRAP(0x170) KPROBES_TRAP(0x171) BTRAP(0x172)
|
||||
tl0_resv170: KPROBES_TRAP(0x170) KPROBES_TRAP(0x171) KGDB_TRAP(0x172)
|
||||
tl0_resv173: BTRAP(0x173) BTRAP(0x174) BTRAP(0x175) BTRAP(0x176) BTRAP(0x177)
|
||||
tl0_resv178: BTRAP(0x178) BTRAP(0x179) BTRAP(0x17a) BTRAP(0x17b) BTRAP(0x17c)
|
||||
tl0_resv17d: BTRAP(0x17d) BTRAP(0x17e) BTRAP(0x17f)
|
||||
|
|
29
arch/sparc64/kernel/utrap.S
Normal file
29
arch/sparc64/kernel/utrap.S
Normal file
|
@ -0,0 +1,29 @@
|
|||
.globl utrap_trap
|
||||
.type utrap_trap,#function
|
||||
utrap_trap: /* %g3=handler,%g4=level */
|
||||
TRAP_LOAD_THREAD_REG(%g6, %g1)
|
||||
ldx [%g6 + TI_UTRAPS], %g1
|
||||
brnz,pt %g1, invoke_utrap
|
||||
nop
|
||||
|
||||
ba,pt %xcc, etrap
|
||||
rd %pc, %g7
|
||||
mov %l4, %o1
|
||||
call bad_trap
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
nop
|
||||
|
||||
invoke_utrap:
|
||||
sllx %g3, 3, %g3
|
||||
ldx [%g1 + %g3], %g1
|
||||
save %sp, -128, %sp
|
||||
rdpr %tstate, %l6
|
||||
rdpr %cwp, %l7
|
||||
andn %l6, TSTATE_CWP, %l6
|
||||
wrpr %l6, %l7, %tstate
|
||||
rdpr %tpc, %l6
|
||||
rdpr %tnpc, %l7
|
||||
wrpr %g1, 0, %tnpc
|
||||
done
|
||||
.size utrap_trap,.-utrap_trap
|
|
@ -676,6 +676,33 @@ xcall_new_mmu_context_version:
|
|||
wr %g0, (1 << PIL_SMP_CTX_NEW_VERSION), %set_softint
|
||||
retry
|
||||
|
||||
#ifdef CONFIG_KGDB
|
||||
.globl xcall_kgdb_capture
|
||||
xcall_kgdb_capture:
|
||||
661: rdpr %pstate, %g2
|
||||
wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate
|
||||
.section .sun4v_2insn_patch, "ax"
|
||||
.word 661b
|
||||
nop
|
||||
nop
|
||||
.previous
|
||||
|
||||
rdpr %pil, %g2
|
||||
wrpr %g0, 15, %pil
|
||||
sethi %hi(109f), %g7
|
||||
ba,pt %xcc, etrap_irq
|
||||
109: or %g7, %lo(109b), %g7
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
call trace_hardirqs_off
|
||||
nop
|
||||
#endif
|
||||
call smp_kgdb_capture_client
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
/* Has to be a non-v9 branch due to the large distance. */
|
||||
ba rtrap_xcall
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ static int send_ack;
|
|||
static int final_ack;
|
||||
static int hw_break_val;
|
||||
static int hw_break_val2;
|
||||
#if defined(CONFIG_ARM) || defined(CONFIG_MIPS)
|
||||
#if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_SPARC)
|
||||
static int arch_needs_sstep_emulation = 1;
|
||||
#else
|
||||
static int arch_needs_sstep_emulation;
|
||||
|
|
|
@ -52,6 +52,17 @@
|
|||
nop; \
|
||||
nop;
|
||||
|
||||
#ifdef CONFIG_KGDB
|
||||
#define KGDB_TRAP(num) \
|
||||
b kgdb_trap_low; \
|
||||
rd %psr,%l0; \
|
||||
nop; \
|
||||
nop;
|
||||
#else
|
||||
#define KGDB_TRAP(num) \
|
||||
BAD_TRAP(num)
|
||||
#endif
|
||||
|
||||
/* The Get Condition Codes software trap for userland. */
|
||||
#define GETCC_TRAP \
|
||||
b getcc_trap_handler; mov %psr, %l0; nop; nop;
|
||||
|
|
|
@ -1,94 +1,38 @@
|
|||
/* $Id: kgdb.h,v 1.8 1998/01/07 06:33:44 baccala Exp $
|
||||
* kgdb.h: Defines and declarations for serial line source level
|
||||
* remote debugging of the Linux kernel using gdb.
|
||||
*
|
||||
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
||||
*/
|
||||
#ifndef _SPARC_KGDB_H
|
||||
#define _SPARC_KGDB_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
/* To init the kgdb engine. */
|
||||
extern void set_debug_traps(void);
|
||||
#ifdef CONFIG_SPARC32
|
||||
#define BUFMAX 2048
|
||||
#else
|
||||
#define BUFMAX 4096
|
||||
#endif
|
||||
|
||||
/* To enter the debugger explicitly. */
|
||||
extern void breakpoint(void);
|
||||
|
||||
/* For convenience we define the format of a kgdb trap breakpoint
|
||||
* frame here also.
|
||||
*/
|
||||
struct kgdb_frame {
|
||||
unsigned long globals[8];
|
||||
unsigned long outs[8];
|
||||
unsigned long locals[8];
|
||||
unsigned long ins[8];
|
||||
unsigned long fpregs[32];
|
||||
unsigned long y;
|
||||
unsigned long psr;
|
||||
unsigned long wim;
|
||||
unsigned long tbr;
|
||||
unsigned long pc;
|
||||
unsigned long npc;
|
||||
unsigned long fpsr;
|
||||
unsigned long cpsr;
|
||||
enum regnames {
|
||||
GDB_G0, GDB_G1, GDB_G2, GDB_G3, GDB_G4, GDB_G5, GDB_G6, GDB_G7,
|
||||
GDB_O0, GDB_O1, GDB_O2, GDB_O3, GDB_O4, GDB_O5, GDB_SP, GDB_O7,
|
||||
GDB_L0, GDB_L1, GDB_L2, GDB_L3, GDB_L4, GDB_L5, GDB_L6, GDB_L7,
|
||||
GDB_I0, GDB_I1, GDB_I2, GDB_I3, GDB_I4, GDB_I5, GDB_FP, GDB_I7,
|
||||
GDB_F0,
|
||||
GDB_F31 = GDB_F0 + 31,
|
||||
#ifdef CONFIG_SPARC32
|
||||
GDB_Y, GDB_PSR, GDB_WIM, GDB_TBR, GDB_PC, GDB_NPC,
|
||||
GDB_FSR, GDB_CSR,
|
||||
#else
|
||||
GDB_F32 = GDB_F0 + 32,
|
||||
GDB_F62 = GDB_F32 + 15,
|
||||
GDB_PC, GDB_NPC, GDB_STATE, GDB_FSR, GDB_FPRS, GDB_Y,
|
||||
#endif
|
||||
};
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
|
||||
/* Macros for assembly usage of the kgdb breakpoint frame. */
|
||||
#define KGDB_G0 0x000
|
||||
#define KGDB_G1 0x004
|
||||
#define KGDB_G2 0x008
|
||||
#define KGDB_G4 0x010
|
||||
#define KGDB_G6 0x018
|
||||
#define KGDB_I0 0x020
|
||||
#define KGDB_I2 0x028
|
||||
#define KGDB_I4 0x030
|
||||
#define KGDB_I6 0x038
|
||||
#define KGDB_Y 0x100
|
||||
#define KGDB_PSR 0x104
|
||||
#define KGDB_WIM 0x108
|
||||
#define KGDB_TBR 0x10c
|
||||
#define KGDB_PC 0x110
|
||||
#define KGDB_NPC 0x114
|
||||
#ifdef CONFIG_SPARC32
|
||||
#define NUMREGBYTES ((GDB_CSR + 1) * 4)
|
||||
#else
|
||||
#define NUMREGBYTES ((GDB_Y + 1) * 8)
|
||||
#endif
|
||||
|
||||
#define SAVE_KGDB_GLOBALS(reg) \
|
||||
std %g0, [%reg + STACKFRAME_SZ + KGDB_G0]; \
|
||||
std %g2, [%reg + STACKFRAME_SZ + KGDB_G2]; \
|
||||
std %g4, [%reg + STACKFRAME_SZ + KGDB_G4]; \
|
||||
std %g6, [%reg + STACKFRAME_SZ + KGDB_G6];
|
||||
extern void arch_kgdb_breakpoint(void);
|
||||
|
||||
#define SAVE_KGDB_INS(reg) \
|
||||
std %i0, [%reg + STACKFRAME_SZ + KGDB_I0]; \
|
||||
std %i2, [%reg + STACKFRAME_SZ + KGDB_I2]; \
|
||||
std %i4, [%reg + STACKFRAME_SZ + KGDB_I4]; \
|
||||
std %i6, [%reg + STACKFRAME_SZ + KGDB_I6];
|
||||
#define BREAK_INSTR_SIZE 4
|
||||
#define CACHE_FLUSH_IS_SAFE 1
|
||||
|
||||
#define SAVE_KGDB_SREGS(reg, reg_y, reg_psr, reg_wim, reg_tbr, reg_pc, reg_npc) \
|
||||
st %reg_y, [%reg + STACKFRAME_SZ + KGDB_Y]; \
|
||||
st %reg_psr, [%reg + STACKFRAME_SZ + KGDB_PSR]; \
|
||||
st %reg_wim, [%reg + STACKFRAME_SZ + KGDB_WIM]; \
|
||||
st %reg_tbr, [%reg + STACKFRAME_SZ + KGDB_TBR]; \
|
||||
st %reg_pc, [%reg + STACKFRAME_SZ + KGDB_PC]; \
|
||||
st %reg_npc, [%reg + STACKFRAME_SZ + KGDB_NPC];
|
||||
|
||||
#define LOAD_KGDB_GLOBALS(reg) \
|
||||
ld [%reg + STACKFRAME_SZ + KGDB_G1], %g1; \
|
||||
ldd [%reg + STACKFRAME_SZ + KGDB_G2], %g2; \
|
||||
ldd [%reg + STACKFRAME_SZ + KGDB_G4], %g4; \
|
||||
ldd [%reg + STACKFRAME_SZ + KGDB_G6], %g6;
|
||||
|
||||
#define LOAD_KGDB_INS(reg) \
|
||||
ldd [%reg + STACKFRAME_SZ + KGDB_I0], %i0; \
|
||||
ldd [%reg + STACKFRAME_SZ + KGDB_I2], %i2; \
|
||||
ldd [%reg + STACKFRAME_SZ + KGDB_I4], %i4; \
|
||||
ldd [%reg + STACKFRAME_SZ + KGDB_I6], %i6;
|
||||
|
||||
#define LOAD_KGDB_SREGS(reg, reg_y, reg_psr, reg_wim, reg_tbr, reg_pc, reg_npc) \
|
||||
ld [%reg + STACKFRAME_SZ + KGDB_Y], %reg_y; \
|
||||
ld [%reg + STACKFRAME_SZ + KGDB_PSR], %reg_psr; \
|
||||
ld [%reg + STACKFRAME_SZ + KGDB_WIM], %reg_wim; \
|
||||
ld [%reg + STACKFRAME_SZ + KGDB_TBR], %reg_tbr; \
|
||||
ld [%reg + STACKFRAME_SZ + KGDB_PC], %reg_pc; \
|
||||
ld [%reg + STACKFRAME_SZ + KGDB_NPC], %reg_npc;
|
||||
|
||||
#endif /* !(_SPARC_KGDB_H) */
|
||||
#endif /* _SPARC_KGDB_H */
|
||||
|
|
|
@ -51,13 +51,11 @@ void smp_bogo(struct seq_file *);
|
|||
void smp_info(struct seq_file *);
|
||||
|
||||
BTFIXUPDEF_CALL(void, smp_cross_call, smpfunc_t, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
|
||||
BTFIXUPDEF_CALL(void, smp_message_pass, int, int, unsigned long, int)
|
||||
BTFIXUPDEF_CALL(int, __hard_smp_processor_id, void)
|
||||
BTFIXUPDEF_BLACKBOX(hard_smp_processor_id)
|
||||
BTFIXUPDEF_BLACKBOX(load_current)
|
||||
|
||||
#define smp_cross_call(func,arg1,arg2,arg3,arg4,arg5) BTFIXUP_CALL(smp_cross_call)(func,arg1,arg2,arg3,arg4,arg5)
|
||||
#define smp_message_pass(target,msg,data,wait) BTFIXUP_CALL(smp_message_pass)(target,msg,data,wait)
|
||||
|
||||
static inline void xc0(smpfunc_t func) { smp_cross_call(func, 0, 0, 0, 0, 0); }
|
||||
static inline void xc1(smpfunc_t func, unsigned long arg1)
|
||||
|
|
|
@ -94,6 +94,8 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
|
|||
} while(0)
|
||||
#endif
|
||||
|
||||
extern void flushw_all(void);
|
||||
|
||||
/*
|
||||
* Flush windows so that the VM switch which follows
|
||||
* would not pull the stack from under us.
|
||||
|
|
1
include/asm-sparc64/kgdb.h
Normal file
1
include/asm-sparc64/kgdb.h
Normal file
|
@ -0,0 +1 @@
|
|||
#include <asm-sparc/kgdb.h>
|
|
@ -19,11 +19,4 @@
|
|||
#define PIL_SMP_CTX_NEW_VERSION 4
|
||||
#define PIL_DEVICE_IRQ 5
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#define PIL_RESERVED(PIL) ((PIL) == PIL_SMP_CALL_FUNC || \
|
||||
(PIL) == PIL_SMP_RECEIVE_SIGNAL || \
|
||||
(PIL) == PIL_SMP_CAPTURE || \
|
||||
(PIL) == PIL_SMP_CTX_NEW_VERSION)
|
||||
#endif
|
||||
|
||||
#endif /* !(_SPARC64_PIL_H) */
|
||||
|
|
|
@ -180,12 +180,13 @@ do { if (test_thread_flag(TIF_PERFCTR)) { \
|
|||
"ldx [%%sp + 2047 + 0x70], %%i6\n\t" \
|
||||
"ldx [%%sp + 2047 + 0x78], %%i7\n\t" \
|
||||
"ldx [%%g6 + %9], %%g4\n\t" \
|
||||
"brz,pt %%o7, 1f\n\t" \
|
||||
"brz,pt %%o7, switch_to_pc\n\t" \
|
||||
" mov %%g7, %0\n\t" \
|
||||
"sethi %%hi(ret_from_syscall), %%g1\n\t" \
|
||||
"jmpl %%g1 + %%lo(ret_from_syscall), %%g0\n\t" \
|
||||
" nop\n\t" \
|
||||
"1:\n\t" \
|
||||
".globl switch_to_pc\n\t" \
|
||||
"switch_to_pc:\n\t" \
|
||||
: "=&r" (last), "=r" (current), "=r" (current_thread_info_reg), \
|
||||
"=r" (__local_per_cpu_offset) \
|
||||
: "0" (task_thread_info(next)), \
|
||||
|
|
|
@ -175,6 +175,12 @@
|
|||
#define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KGDB
|
||||
#define KGDB_TRAP(lvl) TRAP_IRQ(kgdb_trap, lvl)
|
||||
#else
|
||||
#define KGDB_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
|
||||
#endif
|
||||
|
||||
#define SUN4V_ITSB_MISS \
|
||||
ldxa [%g0] ASI_SCRATCHPAD, %g2; \
|
||||
ldx [%g2 + HV_FAULT_I_ADDR_OFFSET], %g4; \
|
||||
|
|
Loading…
Reference in a new issue