From: Andreas Dilger Date: Mon, 3 Dec 2012 07:02:26 +0000 (-0700) Subject: LU-20 build: fix confirmpatches, remove old patches X-Git-Tag: 2.3.58~19 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=ea941366d550f8cfefb108ebc3354d08e1bd71bd LU-20 build: fix confirmpatches, remove old patches Update both confirmpatches.sh and clearpatches.sh scripts to take a command line argument of the patch directory to check. Add options "-h" for help, and "-v" for verbose. Update confirmpatches.sh to ignore comment lines in patch series. Update clearpatches.sh to have a "-d" option to delete the patches it found to be unused. Remove unused kernel/ldiskfs patches found from running clearpatches. Signed-off-by: Andreas Dilger Change-Id: Id5a1de13930f1c428a13d6816e68db40ce61cab0 Reviewed-on: http://review.whamcloud.com/4755 Tested-by: Hudson Tested-by: Maloo Reviewed-by: Christopher J. Morrone Reviewed-by: Yang Sheng Reviewed-by: James Simmons Reviewed-by: Oleg Drokin --- diff --git a/build/clearpatches.sh b/build/clearpatches.sh old mode 100644 new mode 100755 index a0f5741..1f287461 --- a/build/clearpatches.sh +++ b/build/clearpatches.sh @@ -1,13 +1,21 @@ +#!/bin/bash +PROG=$(basename $0) +[ "$1" = "-h" -o "$1" = "--help" ] && echo "usage: $PROG [patch dir]" && exit 0 +[ "$1" = "-d" ] && shift && DELETE="git rm" || DELETE="echo" +[ "$1" = "-v" ] && shift && VERBOSE="echo" || VERBOSE=":" + +[ "$1" ] && BASEDIR="$1" BASEDIR=${BASEDIR:-lustre/kernel_patches} SERIESPATH=${SERIESPATH:-$BASEDIR/series} -PATCHESPATH=${PATCHESPATH:-$BASEDIR/patches} -NOUSEPATH=${NOUSEPATH:-$BASEDIR/unused} +PATCHPATH=${PATCHPATH:-$BASEDIR/patches} + +[ ! -d "$BASEDIR" ] && echo "$PROG: missing base directory '$BASEDIR'" && exit 1 +[ ! -d "$SERIESPATH" ] && echo "$PROG: missing series '$SERIESPATH'" && exit 2 +[ ! -d "$PATCHPATH" ] && echo "$PROG: missing patches '$PATCHPATH'" && exit 3 -#mkdir -p $NOUSEPATH -for PATCH in `ls $PATCHESPATH | grep -v CVS` ; do - #echo $PATCH - if ! grep -rq $PATCH $SERIESPATH ; then - echo "$PATCH" - #mv $PATCHESPATH/$PATCH $NOUSEPATH +for PATCH in $(ls $PATCHPATH | egrep -v "CVS|~$|.orig|.rej"); do + $VERBOSE $PATCH + if ! grep -q $PATCH $SERIESPATH/*.series ; then + $DELETE $PATCHPATH/$PATCH fi done diff --git a/build/confirmpatches.sh b/build/confirmpatches.sh old mode 100644 new mode 100755 index 1c160da..7e33291 --- a/build/confirmpatches.sh +++ b/build/confirmpatches.sh @@ -1,12 +1,22 @@ +#!/bin/bash +PROG=$(basename $0) +[ "$1" = "-h" -o "$1" = "--help" ] && echo "usage: $PROG [patch dir]" && exit 0 +[ "$1" = "-v" ] && shift && VERBOSE="echo" || VERBOSE=":" + BASEDIR=${BASEDIR:-lustre/kernel_patches} SERIESPATH=${SERIESPATH:-$BASEDIR/series} -PATCHESPATH=${PATCHESPATH:-$BASEDIR/patches} -for SERIES in `ls $SERIESPATH | egrep -v "CVS|~$|.orig"` ; do - #echo $SERIES - for PATCH in `cat $SERIESPATH/$SERIES`; do - #echo $PATCH - if [ ! `find $PATCHESPATH -name $PATCH` ]; then - echo "$SERIESPATH/$SERIES: patch $PATCH was not found !" +PATCHPATH=${PATCHPATH:-$BASEDIR/patches} + +[ ! -d "$BASEDIR" ] && echo "$PROG: missing base directory '$BASEDIR'" && exit 1 +[ ! -d "$SERIESPATH" ] && echo "$PROG: missing series '$SERIESPATH'" && exit 2 +[ ! -d "$PATCHPATH" ] && echo "$PROG: missing patches '$PATCHPATH'" && exit 3 + +for SERIES in $(ls $SERIESPATH | egrep -v "CVS|~$|.orig") ; do + $VERBOSE "series: $SERIES" + for PATCH in $(grep -v "^#" $SERIESPATH/$SERIES); do + $VERBOSE $PATCH + if [ ! $(find $PATCHPATH -name $PATCH) ]; then + echo "$SERIESPATH/$SERIES: patch '$PATCH' not found!" fi done done diff --git a/ldiskfs/kernel_patches/patches/ext4-claim_inode-free_inode-race.patch b/ldiskfs/kernel_patches/patches/ext4-claim_inode-free_inode-race.patch deleted file mode 100644 index c742b38..0000000 --- a/ldiskfs/kernel_patches/patches/ext4-claim_inode-free_inode-race.patch +++ /dev/null @@ -1,28 +0,0 @@ -Index: linux-stage/fs/ext4/ialloc.c -=================================================================== ---- linux-stage.orig/fs/ext4/ialloc.c -+++ linux-stage/fs/ext4/ialloc.c -@@ -189,7 +189,7 @@ void ext4_free_inode(handle_t *handle, s - struct ext4_group_desc *gdp; - struct ext4_super_block *es; - struct ext4_sb_info *sbi; -- int fatal = 0, err, count; -+ int fatal = 0, err, count, cleared; - ext4_group_t flex_group; - - if (atomic_read(&inode->i_count) > 1) { -@@ -243,9 +243,12 @@ void ext4_free_inode(handle_t *handle, s - if (fatal) - goto error_return; - -+ ext4_lock_group(sb, block_group); -+ cleared = ext4_clear_bit(bit, bitmap_bh->b_data); -+ ext4_unlock_group(sb, block_group); -+ - /* Ok, now we can actually update the inode bitmaps.. */ -- if (!ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group), -- bit, bitmap_bh->b_data)) -+ if (!cleared) - ext4_error(sb, "ext4_free_inode", - "bit already cleared for inode %lu", ino); - else { diff --git a/ldiskfs/kernel_patches/patches/ext4-disable-write-bar-by-default.patch b/ldiskfs/kernel_patches/patches/ext4-disable-write-bar-by-default.patch deleted file mode 100644 index 1a9e9a3..0000000 --- a/ldiskfs/kernel_patches/patches/ext4-disable-write-bar-by-default.patch +++ /dev/null @@ -1,13 +0,0 @@ -Index: linux-stage/fs/ext4/super.c -=================================================================== ---- linux-stage.orig/fs/ext4/super.c -+++ linux-stage/fs/ext4/super.c -@@ -2457,7 +2457,7 @@ static int ext4_fill_super(struct super_ - sbi->s_resgid = le16_to_cpu(es->s_def_resgid); - - set_opt(sbi->s_mount_opt, RESERVATION); -- set_opt(sbi->s_mount_opt, BARRIER); -+ /* set_opt(sbi->s_mount_opt, BARRIER); */ - - /* - * turn on extents feature by default in ext4 filesystem diff --git a/ldiskfs/kernel_patches/patches/ext4-discard-prealloc-after-failed.patch b/ldiskfs/kernel_patches/patches/ext4-discard-prealloc-after-failed.patch deleted file mode 100644 index 59588a2..0000000 --- a/ldiskfs/kernel_patches/patches/ext4-discard-prealloc-after-failed.patch +++ /dev/null @@ -1,76 +0,0 @@ - -[PATCH] discard an inode's preallocated blocks after failed allocation -Date: Tue, 30 Nov 2010 15:22:38 -0800 (PST) -From: jiayingz@google.com (Jiaying Zhang) - -We have seen kernel crashes caused by the BUG_ON in -ext4_mb_return_to_preallocation() that checks whether the inode's -i_prealloc_list is empty. As I understand, the assumption is that -when ext4_mb_return_to_preallocation() is called from ext4_free_blocks(), -the inode's preallocation list should have been already discarded. -However, although we call ext4_discard_preallocations() during ext4 -truncate, we don't always call that function in various failure -cases before calling ext4_free_blocks(). So it is likely to hit this -BUG_ON with disk errors or corrupted fs etc. - -To fix the problem, the following patch adds ext4_discard_preallocation() -before ext4_free_blocks() in failed allocation cases. This will discard -any preallocated block extent attached to the inode, but I think it is -probably what we should be doing with failed allocation. - -I am also curious whether we can drop the ext4_mb_return_to_preallocation() -call from ext4_free_blocks(). From the comments above that function, it -seems to intent to discard the specified blocks only but all it is currently -doing is the BUG_ON check on whether the inode's preallocation list is empty. -Is there any plan to extend this function later? - - -ext4: discard an inode's preallocated blocks after failed allocation so that -we won't hit on the BUG_ON check in ext4_mb_return_to_preallocation() later. - -Signed-off-by: Jiaying Zhang - -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 29a4adf..2164df6 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -1056,6 +1056,7 @@ cleanup: - } - - if (err) { -+ ext4_discard_preallocations(inode); - /* free all allocated blocks in error case */ - for (i = 0; i < depth; i++) { - if (!ablocks[i]) -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index 4f4362c..456cb4a 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -690,6 +690,7 @@ allocated: - *err = 0; - return ret; - failed_out: -+ ext4_discard_preallocations(inode); - for (i = 0; i < index; i++) - ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0); - return ret; -@@ -787,6 +788,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode, - return err; - failed: - /* Allocation failed, free what we already allocated */ -+ ext4_discard_preallocations(inode); - for (i = 1; i <= n ; i++) { - BUFFER_TRACE(branch[i].bh, "call jbd2_journal_forget"); - ext4_journal_forget(handle, branch[i].bh); -@@ -878,6 +880,7 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode, - return err; - - err_out: -+ ext4_discard_preallocations(inode); - for (i = 1; i <= num; i++) { - /* - * branch[i].bh is newly allocated, so there is no --- -To unsubscribe from this list: send the line "unsubscribe linux-ext4" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/ldiskfs/kernel_patches/patches/ext4-extents-mount-option-rhel5.patch b/ldiskfs/kernel_patches/patches/ext4-extents-mount-option-rhel5.patch deleted file mode 100644 index 316fa46..0000000 --- a/ldiskfs/kernel_patches/patches/ext4-extents-mount-option-rhel5.patch +++ /dev/null @@ -1,166 +0,0 @@ -diff -up linux-2.6.18-164/fs/ext4/ext4.h linux-2.6.18-164/fs/ext4/ext4.h ---- linux-2.6.18-164/fs/ext4/ext4.h 2009-10-16 23:26:25.000000000 +0800 -+++ linux-2.6.18-164/fs/ext4/ext4.h 2009-10-16 23:31:41.000000000 +0800 -@@ -539,6 +539,7 @@ do { \ - #define EXT4_MOUNT_QUOTA 0x80000 /* Some quota option set */ - #define EXT4_MOUNT_USRQUOTA 0x100000 /* "old" user quota */ - #define EXT4_MOUNT_GRPQUOTA 0x200000 /* "old" group quota */ -+#define EXT4_MOUNT_EXTENTS 0x400000 /* Extents support */ - #define EXT4_MOUNT_JOURNAL_CHECKSUM 0x800000 /* Journal checksums */ - #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */ - #define EXT4_MOUNT_I_VERSION 0x2000000 /* i_version support */ -diff -up linux-2.6.18-164/fs/ext4/ext4_jbd2.h linux-2.6.18-164/fs/ext4/ext4_jbd2.h ---- linux-2.6.18-164/fs/ext4/ext4_jbd2.h 2009-10-16 23:26:25.000000000 +0800 -+++ linux-2.6.18-164/fs/ext4/ext4_jbd2.h 2009-10-16 23:32:02.000000000 +0800 -@@ -33,7 +33,7 @@ - - #define EXT4_SINGLEDATA_TRANS_BLOCKS(sb) \ - (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS) \ -- ? 27U : 8U) -+ || test_opt(sb, EXTENTS) ? 27U : 8U) - - /* Indicate that EXT4_SINGLEDATA_TRANS_BLOCKS takes the sb as argument */ - #define EXT4_SINGLEDATA_TRANS_BLOCKS_HAS_SB -diff -up linux-2.6.18-164/fs/ext4/extents.c linux-2.6.18-164/fs/ext4/extents.c ---- linux-2.6.18-164/fs/ext4/extents.c 2009-10-16 23:26:25.000000000 +0800 -+++ linux-2.6.18-164/fs/ext4/extents.c 2009-10-16 23:33:36.000000000 +0800 -@@ -2313,7 +2313,7 @@ void ext4_ext_init(struct super_block *s - * possible initialization would be here - */ - -- if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) { -+ if (test_opt(sb, EXTENTS)) { - #if defined(AGGRESSIVE_TEST) || defined(CHECK_BINSEARCH) || defined(EXTENTS_STATS) - printk(KERN_INFO "EXT4-fs: file extents enabled"); - #ifdef AGGRESSIVE_TEST -@@ -2338,7 +2338,7 @@ void ext4_ext_init(struct super_block *s - */ - void ext4_ext_release(struct super_block *sb) - { -- if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) -+ if (!test_opt(sb, EXTENTS)) - return; - - #ifdef EXTENTS_STATS -diff -up linux-2.6.18-164/fs/ext4/ialloc.c linux-2.6.18-164/fs/ext4/ialloc.c ---- linux-2.6.18-164/fs/ext4/ialloc.c 2009-10-16 23:26:25.000000000 +0800 -+++ linux-2.6.18-164/fs/ext4/ialloc.c 2009-10-16 23:34:38.000000000 +0800 -@@ -938,7 +938,7 @@ got: - if (err) - goto fail_free_drop; - -- if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) { -+ if (test_opt(sb, EXTENTS)) { - /* set extent flag only for directory, file and normal symlink*/ - if (S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) { - EXT4_I(inode)->i_flags |= EXT4_EXTENTS_FL; -diff -up linux-2.6.18-164/fs/ext4/migrate.c linux-2.6.18-164/fs/ext4/migrate.c ---- linux-2.6.18-164/fs/ext4/migrate.c 2009-09-28 16:11:26.000000000 +0800 -+++ linux-2.6.18-164/fs/ext4/migrate.c 2009-10-16 23:36:49.000000000 +0800 -@@ -459,13 +459,13 @@ int ext4_ext_migrate(struct inode *inode - struct list_blocks_struct lb; - unsigned long max_entries; - -- /* -- * If the filesystem does not support extents, or the inode -- * already is extent-based, error out. -- */ -- if (!EXT4_HAS_INCOMPAT_FEATURE(inode->i_sb, -- EXT4_FEATURE_INCOMPAT_EXTENTS) || -- (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) -+ if (!test_opt(inode->i_sb, EXTENTS)) -+ /* -+ * if mounted with noextents we don't allow the migrate -+ */ -+ return -EINVAL; -+ -+ if ((EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) - return -EINVAL; - - if (S_ISLNK(inode->i_mode) && inode->i_blocks == 0) -diff -up linux-2.6.18-164/fs/ext4/super.c linux-2.6.18-164/fs/ext4/super.c ---- linux-2.6.18-164/fs/ext4/super.c 2009-10-16 23:26:25.000000000 +0800 -+++ linux-2.6.18-164/fs/ext4/super.c 2009-10-16 23:48:19.000000000 +0800 -@@ -849,6 +849,8 @@ static int ext4_show_options(struct seq_ - seq_puts(seq, ",journal_async_commit"); - if (test_opt(sb, NOBH)) - seq_puts(seq, ",nobh"); -+ if (!test_opt(sb, EXTENTS)) -+ seq_puts(seq, ",noextents"); - if (test_opt(sb, I_VERSION)) - seq_puts(seq, ",i_version"); - if (!test_opt(sb, DELALLOC)) -@@ -1334,6 +1336,7 @@ enum { - Opt_inode_readahead_blks, Opt_journal_ioprio, - Opt_iopen, Opt_noiopen, Opt_iopen_nopriv, Opt_bigendian_extents, - Opt_force_over_128tb, -+ Opt_extents, Opt_noextents, - }; - - static match_table_t tokens = { -@@ -1401,6 +1404,8 @@ static match_table_t tokens = { - {Opt_noauto_da_alloc, "noauto_da_alloc"}, - {Opt_bigendian_extents, "bigendian_extents"}, - {Opt_force_over_128tb, "force_over_128tb"}, -+ {Opt_extents, "extents"}, -+ {Opt_noextents, "noextents"}, - {Opt_err, NULL}, - }; - -@@ -1441,6 +1446,7 @@ static int parse_options(char *options, - int qtype, qfmt; - char *qname; - #endif -+ ext4_fsblk_t last_block; - - if (!options) - return 1; -@@ -1829,6 +1835,33 @@ set_qf_format: - case Opt_force_over_128tb: - force_over_128tb = 1; - break; -+ case Opt_extents: -+ if (!EXT4_HAS_INCOMPAT_FEATURE(sb, -+ EXT4_FEATURE_INCOMPAT_EXTENTS)) { -+ ext4_warning(sb, -+ "extents feature not enabled " -+ "on this filesystem, use tune2fs"); -+ return 0; -+ } -+ set_opt(sbi->s_mount_opt, EXTENTS); -+ break; -+ case Opt_noextents: -+ /* -+ * When e2fsprogs support resizing an already existing -+ * ext3 file system to greater than 2**32 we need to -+ * add support to block allocator to handle growing -+ * already existing block mapped inode so that blocks -+ * allocated for them fall within 2**32 -+ */ -+ last_block = ext4_blocks_count(sbi->s_es) - 1; -+ if (last_block > 0xffffffffULL) { -+ printk(KERN_ERR "EXT4-fs: Filesystem too " -+ "large to mount with " -+ "-o noextents options\n"); -+ return 0; -+ } -+ clear_opt(sbi->s_mount_opt, EXTENTS); -+ break; - default: - printk(KERN_ERR - "EXT4-fs: Unrecognized mount option \"%s\" " -@@ -2501,6 +2534,14 @@ static int ext4_fill_super(struct super_ - set_opt(sbi->s_mount_opt, BARRIER); - - /* -+ * turn on extents feature by default in ext4 filesystem -+ * only if feature flag already set by mkfs or tune2fs. -+ * Use -o noextents to turn it off -+ */ -+ if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) -+ set_opt(sbi->s_mount_opt, EXTENTS); -+ -+ /* - * enable delayed allocation by default - * Use -o nodelalloc to turn it off - */ diff --git a/ldiskfs/kernel_patches/patches/ext4-hash-indexed-dir-dotdot-update.patch b/ldiskfs/kernel_patches/patches/ext4-hash-indexed-dir-dotdot-update.patch deleted file mode 100644 index d354f89..0000000 --- a/ldiskfs/kernel_patches/patches/ext4-hash-indexed-dir-dotdot-update.patch +++ /dev/null @@ -1,87 +0,0 @@ -Index: linux-stage/fs/ext4/namei.c -=================================================================== ---- linux-stage.orig/fs/ext4/namei.c 2009-08-10 22:44:33.000000000 +0800 -+++ linux-stage/fs/ext4/namei.c 2009-08-10 22:48:22.000000000 +0800 -@@ -1493,6 +1493,72 @@ - return add_dirent_to_buf(handle, dentry, inode, de, bh); - } - -+/* update ".." for hash-indexed directory, split the item "." if necessary */ -+static int ext4_update_dotdot(handle_t *handle, struct dentry *dentry, -+ struct inode *inode) -+{ -+ struct inode * dir = dentry->d_parent->d_inode; -+ struct buffer_head * dir_block; -+ struct ext4_dir_entry_2 * de; -+ int len, journal = 0, err = 0; -+ -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ -+ if (IS_DIRSYNC(dir)) -+ handle->h_sync = 1; -+ -+ dir_block = ext4_bread(handle, dir, 0, 0, &err); -+ if (!dir_block) -+ goto out; -+ -+ de = (struct ext4_dir_entry_2 *)dir_block->b_data; -+ /* the first item must be "." */ -+ assert(de->name_len == 1 && de->name[0] == '.'); -+ len = le16_to_cpu(de->rec_len); -+ assert(len >= EXT4_DIR_REC_LEN(1)); -+ if (len > EXT4_DIR_REC_LEN(1)) { -+ BUFFER_TRACE(dir_block, "get_write_access"); -+ err = ext4_journal_get_write_access(handle, dir_block); -+ if (err) -+ goto out_journal; -+ -+ journal = 1; -+ de->rec_len = cpu_to_le16(EXT4_DIR_REC_LEN(1)); -+ } -+ -+ len -= EXT4_DIR_REC_LEN(1); -+ assert(len == 0 || len >= EXT4_DIR_REC_LEN(2)); -+ de = (struct ext4_dir_entry_2 *) -+ ((char *) de + le16_to_cpu(de->rec_len)); -+ if (!journal) { -+ BUFFER_TRACE(dir_block, "get_write_access"); -+ err = ext4_journal_get_write_access(handle, dir_block); -+ if (err) -+ goto out_journal; -+ } -+ -+ de->inode = cpu_to_le32(inode->i_ino); -+ if (len > 0) -+ de->rec_len = cpu_to_le16(len); -+ else -+ assert(le16_to_cpu(de->rec_len) >= EXT4_DIR_REC_LEN(2)); -+ de->name_len = 2; -+ strcpy (de->name, ".."); -+ ext4_set_de_type(dir->i_sb, de, S_IFDIR); -+ -+out_journal: -+ if (journal) { -+ BUFFER_TRACE(dir_block, "call ext4_journal_dirty_metadata"); -+ err = ext4_journal_dirty_metadata(handle, dir_block); -+ ext4_mark_inode_dirty(handle, dir); -+ } -+ brelse (dir_block); -+ -+out: -+ return err; -+} -+ - /* - * ext4_add_entry() - * -@@ -1521,6 +1587,9 @@ - if (!dentry->d_name.len) - return -EINVAL; - if (is_dx(dir)) { -+ if (dentry->d_name.len == 2 && -+ memcmp(dentry->d_name.name, "..", 2) == 0) -+ return ext4_update_dotdot(handle, dentry, inode); - retval = ext4_dx_add_entry(handle, dentry, inode); - if (!retval || (retval != ERR_BAD_DX_DIR)) - return retval; diff --git a/ldiskfs/kernel_patches/patches/ext4-lock-cached_extent.patch b/ldiskfs/kernel_patches/patches/ext4-lock-cached_extent.patch deleted file mode 100644 index 1751057..0000000 --- a/ldiskfs/kernel_patches/patches/ext4-lock-cached_extent.patch +++ /dev/null @@ -1,53 +0,0 @@ -Index: linux-2.6.27.21-0.1/fs/ext4/extents.c -=================================================================== ---- linux-2.6.27.21-0.1.orig/fs/ext4/extents.c 2009-06-19 15:50:57.000000000 +0530 -+++ linux-2.6.27.21-0.1/fs/ext4/extents.c 2009-06-19 15:56:32.000000000 +0530 -@@ -1736,11 +1736,13 @@ - { - struct ext4_ext_cache *cex; - BUG_ON(len == 0); -+ spin_lock(&EXT4_I(inode)->i_block_reservation_lock); - cex = &EXT4_I(inode)->i_cached_extent; - cex->ec_type = type; - cex->ec_block = block; - cex->ec_len = len; - cex->ec_start = start; -+ spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); - } - - /* -@@ -1797,12 +1799,17 @@ - struct ext4_extent *ex) - { - struct ext4_ext_cache *cex; -+ int ret = EXT4_EXT_CACHE_NO; - -+ /* -+ * We borrow i_block_reservation_lock to protect i_cached_extent -+ */ -+ spin_lock(&EXT4_I(inode)->i_block_reservation_lock); - cex = &EXT4_I(inode)->i_cached_extent; - - /* has cache valid data? */ - if (cex->ec_type == EXT4_EXT_CACHE_NO) -- return EXT4_EXT_CACHE_NO; -+ goto errout; - - BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP && - cex->ec_type != EXT4_EXT_CACHE_EXTENT); -@@ -1813,11 +1820,12 @@ - ext_debug("%u cached by %u:%u:%llu\n", - block, - cex->ec_block, cex->ec_len, cex->ec_start); -- return cex->ec_type; -+ ret = cex->ec_type; - } - -- /* not in cache */ -- return EXT4_EXT_CACHE_NO; -+errout: -+ spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); -+ return ret; - } - - /* diff --git a/ldiskfs/kernel_patches/patches/ext4-lustre-i_version.patch b/ldiskfs/kernel_patches/patches/ext4-lustre-i_version.patch deleted file mode 100644 index 7c94e98..0000000 --- a/ldiskfs/kernel_patches/patches/ext4-lustre-i_version.patch +++ /dev/null @@ -1,66 +0,0 @@ -Index: linux-2.6.27.21-0.1/fs/ext4/ext4_i.h -=================================================================== ---- linux-2.6.27.21-0.1.orig/fs/ext4/ext4_i.h 2009-06-15 06:23:34.000000000 -0400 -+++ linux-2.6.27.21-0.1/fs/ext4/ext4_i.h 2009-06-15 17:09:59.000000000 -0400 -@@ -36,6 +36,8 @@ typedef unsigned int ext4_group_t; - #define rsv_start rsv_window._rsv_start - #define rsv_end rsv_window._rsv_end - -+#define USE_I_FS_VERSION -+ - /* - * storage for cached extent - */ -@@ -138,6 +140,8 @@ struct ext4_inode_info { - __u16 i_extra_isize; - - spinlock_t i_block_reservation_lock; -+ -+ __u64 i_fs_version; - }; - - #endif /* _EXT4_I */ -Index: linux-2.6.27.21-0.1/fs/ext4/ialloc.c -=================================================================== ---- linux-2.6.27.21-0.1.orig/fs/ext4/ialloc.c 2009-06-15 06:23:34.000000000 -0400 -+++ linux-2.6.27.21-0.1/fs/ext4/ialloc.c 2009-06-15 16:59:35.000000000 -0400 -@@ -888,6 +888,7 @@ got: - ei->i_file_acl = 0; - ei->i_dtime = 0; - ei->i_block_group = group; -+ ei->i_fs_version = 0; - - ext4_set_inode_flags(inode); - if (IS_DIRSYNC(inode)) -Index: linux-2.6.27.21-0.1/fs/ext4/inode.c -=================================================================== ---- linux-2.6.27.21-0.1.orig/fs/ext4/inode.c 2009-06-15 06:23:34.000000000 -0400 -+++ linux-2.6.27.21-0.1/fs/ext4/inode.c 2009-06-15 17:01:11.000000000 -0400 -@@ -4201,10 +4201,10 @@ struct inode *ext4_iget(struct super_blo - EXT4_INODE_GET_XTIME(i_atime, inode, raw_inode); - EXT4_EINODE_GET_XTIME(i_crtime, ei, raw_inode); - -- inode->i_version = le32_to_cpu(raw_inode->i_disk_version); -+ ei->i_fs_version = le32_to_cpu(raw_inode->i_disk_version); - if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) { - if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi)) -- inode->i_version |= -+ ei->i_fs_version |= - (__u64)(le32_to_cpu(raw_inode->i_version_hi)) << 32; - } - -@@ -4383,11 +4383,11 @@ static int ext4_do_update_inode(handle_t - } else for (block = 0; block < EXT4_N_BLOCKS; block++) - raw_inode->i_block[block] = ei->i_data[block]; - -- raw_inode->i_disk_version = cpu_to_le32(inode->i_version); -+ raw_inode->i_disk_version = cpu_to_le32(ei->i_fs_version); - if (ei->i_extra_isize) { - if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi)) - raw_inode->i_version_hi = -- cpu_to_le32(inode->i_version >> 32); -+ cpu_to_le32(ei->i_fs_version >> 32); - raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize); - } - - diff --git a/ldiskfs/kernel_patches/patches/ext4-pa_lock-typo.patch b/ldiskfs/kernel_patches/patches/ext4-pa_lock-typo.patch deleted file mode 100644 index 6c10882..0000000 --- a/ldiskfs/kernel_patches/patches/ext4-pa_lock-typo.patch +++ /dev/null @@ -1,13 +0,0 @@ -Index: linux-2.6.18-128.1.6/fs/ext4/mballoc.c -=================================================================== ---- linux-2.6.18-128.1.6.orig/fs/ext4/mballoc.c -+++ linux-2.6.18-128.1.6/fs/ext4/mballoc.c -@@ -4507,7 +4507,7 @@ static void ext4_mb_add_n_trim(struct ex - pa_inode_list) { - spin_lock(&tmp_pa->pa_lock); - if (tmp_pa->pa_deleted) { -- spin_unlock(&pa->pa_lock); -+ spin_unlock(&tmp_pa->pa_lock); - continue; - } - if (!added && pa->pa_free < tmp_pa->pa_free) { diff --git a/ldiskfs/kernel_patches/patches/ext4-super-warning.patch b/ldiskfs/kernel_patches/patches/ext4-super-warning.patch deleted file mode 100644 index b82d3bc..0000000 --- a/ldiskfs/kernel_patches/patches/ext4-super-warning.patch +++ /dev/null @@ -1,14 +0,0 @@ -Index: linux-2.6.27.21-0.1/fs/ext4/super.c -=================================================================== ---- linux-2.6.27.21-0.1.orig/fs/ext4/super.c -+++ linux-2.6.27.21-0.1/fs/ext4/super.c -@@ -1299,7 +1299,7 @@ enum { - Opt_mballoc - }; - --static const match_table_t tokens = { -+static match_table_t tokens = { - {Opt_bsd_df, "bsddf"}, - {Opt_minix_df, "minixdf"}, - {Opt_grpid, "grpid"}, - diff --git a/ldiskfs/kernel_patches/patches/ext4_ext_search_right-fix.patch b/ldiskfs/kernel_patches/patches/ext4_ext_search_right-fix.patch deleted file mode 100644 index f505008..0000000 --- a/ldiskfs/kernel_patches/patches/ext4_ext_search_right-fix.patch +++ /dev/null @@ -1,24 +0,0 @@ -Index: linux-2.6.27.21-0.1/fs/ext4/extents.c -=================================================================== ---- linux-2.6.27.21-0.1.orig/fs/ext4/extents.c -+++ linux-2.6.27.21-0.1/fs/ext4/extents.c -@@ -1119,7 +1119,8 @@ ext4_ext_search_right(struct inode *inod - struct ext4_extent_idx *ix; - struct ext4_extent *ex; - ext4_fsblk_t block; -- int depth, ee_len; -+ int depth; /* Note, NOT eh_depth; depth from top of tree */ -+ int ee_len; - - BUG_ON(path == NULL); - depth = path->p_depth; -@@ -1176,7 +1177,8 @@ got_index: - if (bh == NULL) - return -EIO; - eh = ext_block_hdr(bh); -- if (ext4_ext_check_header(inode, eh, depth)) { -+ /* subtract from p_depth to get proper eh_depth */ -+ if (ext4_ext_check_header(inode, eh, path->p_depth - depth)) { - put_bh(bh); - return -EIO; - } diff --git a/lustre/kernel_patches/patches/2.6-rhel5-kgdb-ga.patch b/lustre/kernel_patches/patches/2.6-rhel5-kgdb-ga.patch deleted file mode 100644 index 6e38859..0000000 --- a/lustre/kernel_patches/patches/2.6-rhel5-kgdb-ga.patch +++ /dev/null @@ -1,19200 +0,0 @@ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/Documentation/DocBook/Makefile linux-2.6.18-53.1.14.kgdb/Documentation/DocBook/Makefile ---- linux-2.6.18-53.1.14/Documentation/DocBook/Makefile 2008-03-06 05:54:50.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/Documentation/DocBook/Makefile 2008-06-10 15:37:25.000000000 +0400 -@@ -11,7 +11,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mc - procfs-guide.xml writing_usb_driver.xml \ - kernel-api.xml journal-api.xml lsm.xml utrace.xml usb.xml \ - gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ -- genericirq.xml -+ genericirq.xml kgdb.xml - - ### - # The build process is as follows (targets): -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/Documentation/DocBook/kgdb.tmpl linux-2.6.18-53.1.14.kgdb/Documentation/DocBook/kgdb.tmpl ---- linux-2.6.18-53.1.14/Documentation/DocBook/kgdb.tmpl 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/Documentation/DocBook/kgdb.tmpl 2008-06-10 15:38:50.000000000 +0400 -@@ -0,0 +1,250 @@ -+ -+ -+ -+ -+ -+ KGDB Internals -+ -+ -+ -+ Tom -+ Rini -+ -+
-+ trini@kernel.crashing.org -+
-+
-+
-+
-+ -+ -+ -+ Amit S. -+ Kale -+ -+
-+ amitkale@linsyssoft.com -+
-+
-+
-+
-+ -+ -+ 2004-2005 -+ MontaVista Software, Inc. -+ -+ -+ 2004 -+ Amit S. Kale -+ -+ -+ -+ -+ This file is licensed under the terms of the GNU General Public License -+ version 2. This program is licensed "as is" without any warranty of any -+ kind, whether express or implied. -+ -+ -+ -+
-+ -+ -+ -+ Introduction -+ -+ kgdb is a source level debugger for linux kernel. It is used along -+ with gdb to debug a linux kernel. Kernel developers can debug a kernel -+ similar to application programs with the use of kgdb. It makes it -+ possible to place breakpoints in kernel code, step through the code -+ and observe variables. -+ -+ -+ Two machines are required for using kgdb. One of these machines is a -+ development machine and the other is a test machine. The machines are -+ typically connected through a serial line, a null-modem cable which -+ connects their serial ports. It is also possible however, to use an -+ ethernet connection between the machines. The kernel to be debugged -+ runs on the test machine. gdb runs on the development machine. The -+ serial line or ethernet connection is used by gdb to communicate to -+ the kernel being debugged. -+ -+ -+ -+ Compiling a kernel -+ -+ To enable CONFIG_KGDB, look under the "Kernel debugging" -+ and then select "KGDB: kernel debugging with remote gdb". -+ -+ -+ The first choice for I/O is CONFIG_KGDB_ONLY_MODULES. -+ This means that you will only be able to use KGDB after loading a -+ kernel module that defines how you want to be able to talk with -+ KGDB. There are two other choices (more on some architectures) that -+ can be enabled as modules later, if not picked here. -+ -+ The first of these is CONFIG_KGDB_8250_NOMODULE. -+ This has sub-options such as CONFIG_KGDB_SIMPLE_SERIAL -+ which toggles choosing the serial port by ttyS number or by specifying -+ a port and IRQ number. -+ -+ -+ The second of these choices on most systems for I/O is -+ CONFIG_KGDBOE. This requires that the machine to be -+ debugged has an ethernet card which supports the netpoll API, such as -+ the cards supported by CONFIG_E100. There are no -+ sub-options for this, but a kernel command line option is required. -+ -+ -+ -+ Booting the kernel -+ -+ The Kernel command line option kgdbwait makes kgdb -+ wait for gdb connection during booting of a kernel. If the -+ CONFIG_KGDB_8250 driver is used (or if applicable, -+ another serial driver) this breakpoint will happen very early on, before -+ console output. If you wish to change serial port information and you -+ have enabled both CONFIG_KGDB_8250 and -+ CONFIG_KGDB_SIMPLE_SERIAL then you must pass the option -+ kgdb8250=<io or mmio>,<address>,<baud -+ rate>,<irq> before kgdbwait. -+ The values io or mmio refer to -+ if the address being passed next needs to be memory mapped -+ (mmio) or not. The address must -+ be passed in hex and is the hardware address and will be remapped if -+ passed as mmio. The value -+ baud rate and irq are base-10. -+ The supported values for baud rate are -+ 9600, 19200, -+ 38400, 57600, and -+ 115200. -+ -+ -+ To have KGDB stop the kernel and wait, with the compiled values for the -+ serial driver, pass in: kgdbwait. -+ -+ -+ To specify the values of the SH SCI(F) serial port at boot: -+ kgdbsci=0,115200. -+ -+ -+ To specify the values of the serial port at boot: -+ kgdb8250=io,3f8,115200,3. -+ On IA64 this could also be: -+ kgdb8250=mmio,0xff5e0000,115200,74 -+ And to have KGDB also stop the kernel and wait for GDB to connect, pass in -+ kgdbwait after this arguement. -+ -+ -+ To configure the CONFIG_KGDBOE driver, pass in -+ kgdboe=[src-port]@<src-ip>/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr] -+ where: -+ -+ src-port (optional): source for UDP packets (defaults to 6443) -+ src-ip: source IP to use (interface address) -+ dev (optional): network interface (eth0) -+ tgt-port (optional): port GDB will use (defaults to 6442) -+ tgt-ip: IP address GDB will be connecting from -+ tgt-macaddr (optional): ethernet MAC address for logging agent (default is broadcast) -+ -+ -+ -+ The CONFIG_KGDBOE driver can be reconfigured at run -+ time, if CONFIG_SYSFS and -+ CONFIG_MODULES by echo'ing a new config string to -+ /sys/module/kgdboe/parameter/kgdboe. The -+ driver can be unconfigured with the special string -+ not_configured. -+ -+ -+ -+ Connecting gdb -+ -+ If you have used any of the methods to have KGDB stop and create -+ an initial breakpoint described in the previous chapter, kgdb prints -+ the message "Waiting for connection from remote gdb..." on the console -+ and waits for connection from gdb. At this point you connect gdb to kgdb. -+ -+ -+ Example (serial): -+ -+ -+ % gdb ./vmlinux -+ (gdb) set remotebaud 115200 -+ (gdb) target remote /dev/ttyS0 -+ -+ -+ Example (ethernet): -+ -+ -+ % gdb ./vmlinux -+ (gdb) target remote udp:192.168.2.2:6443 -+ -+ -+ Once connected, you can debug a kernel the way you would debug an -+ application program. -+ -+ -+ -+ Architecture specific notes -+ -+ SuperH: The NMI switch found on some boards can be used to trigger an -+ initial breakpoint. Subsequent triggers do nothing. If console -+ is enabled on the SCI(F) serial port, and that is the port being used -+ for KGDB, then you must trigger a breakpoint via sysrq, NMI, or -+ some other method prior to connecting, or echo a control-c to the -+ serial port. Also, to use the SCI(F) port for KGDB, the -+ CONFIG_SERIAL_SH_SCI driver must be enabled. -+ -+ -+ -+ The common backend (required) -+ -+ There are a few flags which must be set on every architecture in -+ their <asm/kgdb.h> file. These are: -+ -+ -+ -+ NUMREGBYTES: The size in bytes of all of the registers, so -+ that we can ensure they will all fit into a packet. -+ -+ -+ BUFMAX: The size in bytes of the buffer GDB will read into. -+ This must be larger than NUMREGBYTES. -+ -+ -+ CACHE_FLUSH_IS_SAFE: Set to one if it always safe to call -+ flush_cache_range or flush_icache_range. On some architectures, -+ these functions may not be safe to call on SMP since we keep other -+ CPUs in a holding pattern. -+ -+ -+ -+ -+ -+ There are also the following functions for the common backend, -+ found in kernel/kgdb.c that must be supplied by the -+ architecture-specific backend. No weak version of these is provided. -+ -+!Iinclude/linux/kgdb.h -+ -+ -+ The common backend (optional) -+ -+ These functions are part of the common backend, found in kernel/kgdb.c -+ and are optionally implemented. Some functions (with _hw_ in the name) -+ end up being required on arches which use hardware breakpoints. -+ -+!Ikernel/kgdb.c -+ -+ -+ Driver-Specific Functions -+ -+ Some of the I/O drivers have additional functions that can be -+ called, that are specific to the driver. Calls from other places -+ to these functions must be wrapped in #ifdefs for the driver in -+ question. -+ -+!Idrivers/serial/8250_kgdb.c -+ -+
-diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/MAINTAINERS linux-2.6.18-53.1.14.kgdb/MAINTAINERS ---- linux-2.6.18-53.1.14/MAINTAINERS 2008-03-06 05:54:49.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/MAINTAINERS 2008-06-10 15:37:25.000000000 +0400 -@@ -1715,6 +1715,15 @@ L: linux-kernel@vger.kernel.org - L: fastboot@osdl.org - S: Maintained - -+KGDB -+P: Tom Rini -+P: Amit S. Kale -+M: trini@kernel.crashing.org -+M: amitkale@linsyssoft.com -+W: http://sourceforge.net/projects/kgdb -+L: kgdb-bugreport@lists.sourceforge.net -+S: Maintained -+ - KPROBES - P: Prasanna S Panchamukhi - M: prasanna@in.ibm.com -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/Makefile linux-2.6.18-53.1.14.kgdb/Makefile ---- linux-2.6.18-53.1.14/Makefile 2008-03-06 05:55:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/Makefile 2008-06-10 15:39:01.000000000 +0400 -@@ -992,6 +992,7 @@ MRPROPER_DIRS += include/config include - MRPROPER_FILES += .config .config.old include/asm .version .old_version \ - include/linux/autoconf.h include/linux/version.h \ - include/linux/utsrelease.h \ -+ include/linux/dwarf2-defs.h \ - Module.symvers tags TAGS cscope* - - # clean - Delete most, but leave enough to build external modules -@@ -1422,7 +1423,11 @@ clean := -f $(if $(KBUILD_SRC),$(srctree - endif # skip-makefile - - PHONY += FORCE --FORCE: -+include/linux/dwarf2-defs.h: $(srctree)/include/linux/dwarf2.h $(srctree)/scripts/dwarfh.awk -+ mkdir -p include/linux/ -+ awk -f $(srctree)/scripts/dwarfh.awk $(srctree)/include/linux/dwarf2.h > include/linux/dwarf2-defs.h -+ -+FORCE: include/linux/dwarf2-defs.h - - - # Declare the contents of the .PHONY variable as phony. We keep that -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/arm/kernel/Makefile linux-2.6.18-53.1.14.kgdb/arch/arm/kernel/Makefile ---- linux-2.6.18-53.1.14/arch/arm/kernel/Makefile 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/arm/kernel/Makefile 2008-06-10 15:38:56.000000000 +0400 -@@ -20,6 +20,7 @@ obj-$(CONFIG_ISA_DMA) += dma-isa.o - obj-$(CONFIG_PCI) += bios32.o isa.o - obj-$(CONFIG_SMP) += smp.o - obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o -+obj-$(CONFIG_KGDB) += kgdb.o kgdb-jmp.o - - obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o - AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312 -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/arm/kernel/entry-armv.S linux-2.6.18-53.1.14.kgdb/arch/arm/kernel/entry-armv.S ---- linux-2.6.18-53.1.14/arch/arm/kernel/entry-armv.S 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/arm/kernel/entry-armv.S 2008-06-10 15:39:01.000000000 +0400 -@@ -15,6 +15,7 @@ - * it to save wrong values... Be aware! - */ - -+#include - #include - #include - #include -@@ -232,6 +233,7 @@ svc_preempt: - beq preempt_return @ go again - b 1b - #endif -+ CFI_END_FRAME(__irq_svc) - - .align 5 - __und_svc: -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/arm/kernel/kgdb-jmp.S linux-2.6.18-53.1.14.kgdb/arch/arm/kernel/kgdb-jmp.S ---- linux-2.6.18-53.1.14/arch/arm/kernel/kgdb-jmp.S 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/arm/kernel/kgdb-jmp.S 2008-06-10 15:38:56.000000000 +0400 -@@ -0,0 +1,32 @@ -+/* -+ * arch/arm/kernel/kgdb-jmp.S -+ * -+ * Trivial setjmp and longjmp procedures to support bus error recovery -+ * which may occur during kgdb memory read/write operations. -+ * -+ * Author: MontaVista Software, Inc. -+ * source@mvista.com -+ * -+ * 2002-2005 (c) MontaVista Software, Inc. This file is licensed under the -+ * terms of the GNU General Public License version 2. This program as licensed -+ * "as is" without any warranty of any kind, whether express or implied. -+ */ -+#include -+ -+ENTRY (kgdb_fault_setjmp) -+ /* Save registers */ -+ stmia r0, {r0-r14} -+ str lr,[r0, #60] -+ mrs r1,cpsr -+ str r1,[r0,#64] -+ ldr r1,[r0,#4] -+ mov r0, #0 -+ mov pc,lr -+ -+ENTRY (kgdb_fault_longjmp) -+ /* Restore registers */ -+ mov r1,#1 -+ str r1,[r0] -+ ldr r1,[r0, #64] -+ msr spsr,r1 -+ ldmia r0,{r0-pc}^ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/arm/kernel/kgdb.c linux-2.6.18-53.1.14.kgdb/arch/arm/kernel/kgdb.c ---- linux-2.6.18-53.1.14/arch/arm/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/arm/kernel/kgdb.c 2008-06-10 15:38:56.000000000 +0400 -@@ -0,0 +1,208 @@ -+/* -+ * arch/arm/kernel/kgdb.c -+ * -+ * ARM KGDB support -+ * -+ * Copyright (c) 2002-2004 MontaVista Software, Inc -+ * -+ * Authors: George Davis -+ * Deepak Saxena -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Make a local copy of the registers passed into the handler (bletch) */ -+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs) -+{ -+ int regno; -+ -+ /* Initialize all to zero (??) */ -+ for (regno = 0; regno < GDB_MAX_REGS; regno++) -+ gdb_regs[regno] = 0; -+ -+ gdb_regs[_R0] = kernel_regs->ARM_r0; -+ gdb_regs[_R1] = kernel_regs->ARM_r1; -+ gdb_regs[_R2] = kernel_regs->ARM_r2; -+ gdb_regs[_R3] = kernel_regs->ARM_r3; -+ gdb_regs[_R4] = kernel_regs->ARM_r4; -+ gdb_regs[_R5] = kernel_regs->ARM_r5; -+ gdb_regs[_R6] = kernel_regs->ARM_r6; -+ gdb_regs[_R7] = kernel_regs->ARM_r7; -+ gdb_regs[_R8] = kernel_regs->ARM_r8; -+ gdb_regs[_R9] = kernel_regs->ARM_r9; -+ gdb_regs[_R10] = kernel_regs->ARM_r10; -+ gdb_regs[_FP] = kernel_regs->ARM_fp; -+ gdb_regs[_IP] = kernel_regs->ARM_ip; -+ gdb_regs[_SP] = kernel_regs->ARM_sp; -+ gdb_regs[_LR] = kernel_regs->ARM_lr; -+ gdb_regs[_PC] = kernel_regs->ARM_pc; -+ gdb_regs[_CPSR] = kernel_regs->ARM_cpsr; -+} -+ -+/* Copy local gdb registers back to kgdb regs, for later copy to kernel */ -+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs) -+{ -+ kernel_regs->ARM_r0 = gdb_regs[_R0]; -+ kernel_regs->ARM_r1 = gdb_regs[_R1]; -+ kernel_regs->ARM_r2 = gdb_regs[_R2]; -+ kernel_regs->ARM_r3 = gdb_regs[_R3]; -+ kernel_regs->ARM_r4 = gdb_regs[_R4]; -+ kernel_regs->ARM_r5 = gdb_regs[_R5]; -+ kernel_regs->ARM_r6 = gdb_regs[_R6]; -+ kernel_regs->ARM_r7 = gdb_regs[_R7]; -+ kernel_regs->ARM_r8 = gdb_regs[_R8]; -+ kernel_regs->ARM_r9 = gdb_regs[_R9]; -+ kernel_regs->ARM_r10 = gdb_regs[_R10]; -+ kernel_regs->ARM_fp = gdb_regs[_FP]; -+ kernel_regs->ARM_ip = gdb_regs[_IP]; -+ kernel_regs->ARM_sp = gdb_regs[_SP]; -+ kernel_regs->ARM_lr = gdb_regs[_LR]; -+ kernel_regs->ARM_pc = gdb_regs[_PC]; -+ kernel_regs->ARM_cpsr = gdb_regs[GDB_MAX_REGS - 1]; -+} -+ -+static inline struct pt_regs *kgdb_get_user_regs(struct task_struct *task) -+{ -+ return (struct pt_regs *) -+ ((unsigned long)task->thread_info + THREAD_SIZE - -+ 8 - sizeof(struct pt_regs)); -+} -+ -+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, -+ struct task_struct *task) -+{ -+ int regno; -+ struct pt_regs *thread_regs; -+ -+ /* Just making sure... */ -+ if (task == NULL) -+ return; -+ -+ /* Initialize to zero */ -+ for (regno = 0; regno < GDB_MAX_REGS; regno++) -+ gdb_regs[regno] = 0; -+ -+ /* Otherwise, we have only some registers from switch_to() */ -+ thread_regs = kgdb_get_user_regs(task); -+ gdb_regs[_R0] = thread_regs->ARM_r0; /* Not really valid? */ -+ gdb_regs[_R1] = thread_regs->ARM_r1; /* " " */ -+ gdb_regs[_R2] = thread_regs->ARM_r2; /* " " */ -+ gdb_regs[_R3] = thread_regs->ARM_r3; /* " " */ -+ gdb_regs[_R4] = thread_regs->ARM_r4; -+ gdb_regs[_R5] = thread_regs->ARM_r5; -+ gdb_regs[_R6] = thread_regs->ARM_r6; -+ gdb_regs[_R7] = thread_regs->ARM_r7; -+ gdb_regs[_R8] = thread_regs->ARM_r8; -+ gdb_regs[_R9] = thread_regs->ARM_r9; -+ gdb_regs[_R10] = thread_regs->ARM_r10; -+ gdb_regs[_FP] = thread_regs->ARM_fp; -+ gdb_regs[_IP] = thread_regs->ARM_ip; -+ gdb_regs[_SP] = thread_regs->ARM_sp; -+ gdb_regs[_LR] = thread_regs->ARM_lr; -+ gdb_regs[_PC] = thread_regs->ARM_pc; -+ gdb_regs[_CPSR] = thread_regs->ARM_cpsr; -+} -+ -+static int compiled_break; -+ -+int kgdb_arch_handle_exception(int exception_vector, int signo, -+ int err_code, char *remcom_in_buffer, -+ char *remcom_out_buffer, -+ struct pt_regs *linux_regs) -+{ -+ long addr; -+ char *ptr; -+ -+ switch (remcom_in_buffer[0]) { -+ case 'c': -+ kgdb_contthread = NULL; -+ -+ /* -+ * Try to read optional parameter, pc unchanged if no parm. -+ * If this was a compiled breakpoint, we need to move -+ * to the next instruction or we will just breakpoint -+ * over and over again. -+ */ -+ ptr = &remcom_in_buffer[1]; -+ if (kgdb_hex2long(&ptr, &addr)) { -+ linux_regs->ARM_pc = addr; -+ } else if (compiled_break == 1) { -+ linux_regs->ARM_pc += 4; -+ } -+ -+ compiled_break = 0; -+ -+ return 0; -+ } -+ -+ return -1; -+} -+ -+static int kgdb_brk_fn(struct pt_regs *regs, unsigned int instr) -+{ -+ kgdb_handle_exception(1, SIGTRAP, 0, regs); -+ -+ return 0; -+} -+ -+static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr) -+{ -+ compiled_break = 1; -+ kgdb_handle_exception(1, SIGTRAP, 0, regs); -+ -+ return 0; -+} -+ -+static struct undef_hook kgdb_brkpt_hook = { -+ .instr_mask = 0xffffffff, -+ .instr_val = KGDB_BREAKINST, -+ .fn = kgdb_brk_fn -+}; -+ -+static struct undef_hook kgdb_compiled_brkpt_hook = { -+ .instr_mask = 0xffffffff, -+ .instr_val = KGDB_COMPILED_BREAK, -+ .fn = kgdb_compiled_brk_fn -+}; -+ -+/* -+ * Register our undef instruction hooks with ARM undef core. -+ * We regsiter a hook specifically looking for the KGB break inst -+ * and we handle the normal undef case within the do_undefinstr -+ * handler. -+ */ -+int kgdb_arch_init(void) -+{ -+ register_undef_hook(&kgdb_brkpt_hook); -+ register_undef_hook(&kgdb_compiled_brkpt_hook); -+ -+ return 0; -+} -+ -+struct kgdb_arch arch_kgdb_ops = { -+#ifndef __ARMEB__ -+ .gdb_bpt_instr = {0xfe, 0xde, 0xff, 0xe7} -+#else -+ .gdb_bpt_instr = {0xe7, 0xff, 0xde, 0xfe} -+#endif -+}; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/arm/kernel/setup.c linux-2.6.18-53.1.14.kgdb/arch/arm/kernel/setup.c ---- linux-2.6.18-53.1.14/arch/arm/kernel/setup.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/arm/kernel/setup.c 2008-06-10 15:38:56.000000000 +0400 -@@ -829,6 +829,11 @@ void __init setup_arch(char **cmdline_p) - conswitchp = &dummy_con; - #endif - #endif -+ -+#if defined(CONFIG_KGDB) -+ extern void __init early_trap_init(void); -+ early_trap_init(); -+#endif - } - - -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/arm/kernel/traps.c linux-2.6.18-53.1.14.kgdb/arch/arm/kernel/traps.c ---- linux-2.6.18-53.1.14/arch/arm/kernel/traps.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/arm/kernel/traps.c 2008-06-10 15:38:56.000000000 +0400 -@@ -278,6 +278,7 @@ asmlinkage void do_undefinstr(struct pt_ - unsigned int instr; - struct undef_hook *hook; - siginfo_t info; -+ mm_segment_t fs; - void __user *pc; - - /* -@@ -287,12 +288,15 @@ asmlinkage void do_undefinstr(struct pt_ - */ - regs->ARM_pc -= correction; - -+ fs = get_fs(); -+ set_fs(KERNEL_DS); - pc = (void __user *)instruction_pointer(regs); - if (thumb_mode(regs)) { - get_user(instr, (u16 __user *)pc); - } else { - get_user(instr, (u32 __user *)pc); - } -+ set_fs(fs); - - spin_lock_irq(&undef_lock); - list_for_each_entry(hook, &undef_hook, node) { -@@ -684,6 +688,13 @@ EXPORT_SYMBOL(abort); - - void __init trap_init(void) - { -+#if defined(CONFIG_KGDB) -+ return; -+} -+ -+void __init early_trap_init(void) -+{ -+#endif - unsigned long vectors = CONFIG_VECTORS_BASE; - extern char __stubs_start[], __stubs_end[]; - extern char __vectors_start[], __vectors_end[]; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/arm/mach-ixp2000/core.c linux-2.6.18-53.1.14.kgdb/arch/arm/mach-ixp2000/core.c ---- linux-2.6.18-53.1.14/arch/arm/mach-ixp2000/core.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/arm/mach-ixp2000/core.c 2008-06-10 15:38:56.000000000 +0400 -@@ -34,6 +34,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -184,6 +185,9 @@ static struct platform_device ixp2000_se - void __init ixp2000_uart_init(void) - { - platform_device_register(&ixp2000_serial_device); -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_port(0, &ixp2000_serial_port); -+#endif - } - - -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/arm/mach-ixp2000/ixdp2x01.c linux-2.6.18-53.1.14.kgdb/arch/arm/mach-ixp2000/ixdp2x01.c ---- linux-2.6.18-53.1.14/arch/arm/mach-ixp2000/ixdp2x01.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/arm/mach-ixp2000/ixdp2x01.c 2008-06-10 15:38:56.000000000 +0400 -@@ -38,6 +38,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -413,6 +414,11 @@ static void __init ixdp2x01_init_machine - platform_add_devices(ixdp2x01_devices, ARRAY_SIZE(ixdp2x01_devices)); - ixp2000_uart_init(); - ixdp2x01_uart_init(); -+ -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_port(0, &ixdp425_serial_ports[0]); -+ kgdb8250_add_port(1, &ixdp425_serial_ports[1]); -+#endif - } - - -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/arm/mach-ixp4xx/coyote-setup.c linux-2.6.18-53.1.14.kgdb/arch/arm/mach-ixp4xx/coyote-setup.c ---- linux-2.6.18-53.1.14/arch/arm/mach-ixp4xx/coyote-setup.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/arm/mach-ixp4xx/coyote-setup.c 2008-06-10 15:38:56.000000000 +0400 -@@ -96,6 +96,10 @@ static void __init coyote_init(void) - } - - platform_add_devices(coyote_devices, ARRAY_SIZE(coyote_devices)); -+ -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_port(0, &coyote_serial_port); -+#endif - } - - #ifdef CONFIG_ARCH_ADI_COYOTE -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/arm/mach-ixp4xx/ixdp425-setup.c linux-2.6.18-53.1.14.kgdb/arch/arm/mach-ixp4xx/ixdp425-setup.c ---- linux-2.6.18-53.1.14/arch/arm/mach-ixp4xx/ixdp425-setup.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/arm/mach-ixp4xx/ixdp425-setup.c 2008-06-10 15:38:56.000000000 +0400 -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - - static struct flash_platform_data ixdp425_flash_data = { - .map_name = "cfi_probe", -@@ -76,7 +77,8 @@ static struct plat_serial8250_port ixdp4 - .mapbase = IXP4XX_UART1_BASE_PHYS, - .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, - .irq = IRQ_IXP4XX_UART1, -- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | -+ UPF_SHARE_IRQ, - .iotype = UPIO_MEM, - .regshift = 2, - .uartclk = IXP4XX_UART_XTAL, -@@ -85,7 +87,8 @@ static struct plat_serial8250_port ixdp4 - .mapbase = IXP4XX_UART2_BASE_PHYS, - .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, - .irq = IRQ_IXP4XX_UART2, -- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | -+ UPF_SHARE_IRQ, - .iotype = UPIO_MEM, - .regshift = 2, - .uartclk = IXP4XX_UART_XTAL, -@@ -116,6 +119,11 @@ static void __init ixdp425_init(void) - IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; - - platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices)); -+ -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_port(0, &ixdp425_serial_ports[0]); -+ kgdb8250_add_port(1, &ixdp425_serial_ports[1]); -+#endif - } - - #ifdef CONFIG_ARCH_IXDP425 -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/arm/mach-omap1/serial.c linux-2.6.18-53.1.14.kgdb/arch/arm/mach-omap1/serial.c ---- linux-2.6.18-53.1.14/arch/arm/mach-omap1/serial.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/arm/mach-omap1/serial.c 2008-06-10 15:38:56.000000000 +0400 -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -199,6 +200,9 @@ void __init omap_serial_init(void) - break; - } - omap_serial_reset(&serial_platform_data[i]); -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_platform_port(i, &serial_platform_data[i]); -+#endif - } - } - -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/arm/mach-pxa/Makefile linux-2.6.18-53.1.14.kgdb/arch/arm/mach-pxa/Makefile ---- linux-2.6.18-53.1.14/arch/arm/mach-pxa/Makefile 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/arm/mach-pxa/Makefile 2008-06-10 15:38:56.000000000 +0400 -@@ -31,6 +31,7 @@ obj-$(CONFIG_LEDS) += $(led-y) - # Misc features - obj-$(CONFIG_PM) += pm.o sleep.o - obj-$(CONFIG_PXA_SSP) += ssp.o -+obj-$(CONFIG_KGDB_PXA_SERIAL) += kgdb-serial.o - - ifeq ($(CONFIG_PXA27x),y) - obj-$(CONFIG_PM) += standby.o -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/arm/mach-pxa/kgdb-serial.c linux-2.6.18-53.1.14.kgdb/arch/arm/mach-pxa/kgdb-serial.c ---- linux-2.6.18-53.1.14/arch/arm/mach-pxa/kgdb-serial.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/arm/mach-pxa/kgdb-serial.c 2008-06-10 15:38:56.000000000 +0400 -@@ -0,0 +1,98 @@ -+/* -+ * linux/arch/arm/mach-pxa/kgdb-serial.c -+ * -+ * Provides low level kgdb serial support hooks for PXA2xx boards -+ * -+ * Author: Nicolas Pitre -+ * Copyright: (C) 2002-2005 MontaVista Software Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#if defined(CONFIG_KGDB_PXA_FFUART) -+ -+#define UART FFUART -+#define CKEN_UART CKEN6_FFUART -+#define GPIO_RX_MD GPIO34_FFRXD_MD -+#define GPIO_TX_MD GPIO39_FFTXD_MD -+ -+#elif defined(CONFIG_KGDB_PXA_BTUART) -+ -+#define UART BTUART -+#define CKEN_UART CKEN7_BTUART -+#define GPIO_RX_MD GPIO42_BTRXD_MD -+#define GPIO_TX_MD GPIO43_BTTXD_MD -+ -+#elif defined(CONFIG_KGDB_PXA_STUART) -+ -+#define UART STUART -+#define CKEN_UART CKEN5_STUART -+#define GPIO_RX_MD GPIO46_STRXD_MD -+#define GPIO_TX_MD GPIO47_STTXD_MD -+ -+#endif -+ -+#define UART_BAUDRATE (CONFIG_KGDB_BAUDRATE) -+ -+static volatile unsigned long *port = (unsigned long *)&UART; -+ -+static int kgdb_serial_init(void) -+{ -+ pxa_set_cken(CKEN_UART, 1); -+ pxa_gpio_mode(GPIO_RX_MD); -+ pxa_gpio_mode(GPIO_TX_MD); -+ -+ port[UART_IER] = 0; -+ port[UART_LCR] = LCR_DLAB; -+ port[UART_DLL] = ((921600 / UART_BAUDRATE) & 0xff); -+ port[UART_DLM] = ((921600 / UART_BAUDRATE) >> 8); -+ port[UART_LCR] = LCR_WLS1 | LCR_WLS0; -+ port[UART_MCR] = 0; -+ port[UART_IER] = IER_UUE; -+ port[UART_FCR] = FCR_ITL_16; -+ -+ return 0; -+} -+ -+static void kgdb_serial_putchar(int c) -+{ -+ if (!(CKEN & CKEN_UART) || port[UART_IER] != IER_UUE) -+ kgdb_serial_init(); -+ while (!(port[UART_LSR] & LSR_TDRQ)) -+ cpu_relax(); -+ port[UART_TX] = c; -+} -+ -+static void kgdb_serial_flush(void) -+{ -+ if ((CKEN & CKEN_UART) && (port[UART_IER] & IER_UUE)) -+ while (!(port[UART_LSR] & LSR_TEMT)) -+ cpu_relax(); -+} -+ -+static int kgdb_serial_getchar(void) -+{ -+ unsigned char c; -+ if (!(CKEN & CKEN_UART) || port[UART_IER] != IER_UUE) -+ kgdb_serial_init(); -+ while (!(port[UART_LSR] & UART_LSR_DR)) -+ cpu_relax(); -+ c = port[UART_RX]; -+ return c; -+} -+ -+struct kgdb_io kgdb_io_ops = { -+ .init = kgdb_serial_init, -+ .write_char = kgdb_serial_putchar, -+ .flush = kgdb_serial_flush, -+ .read_char = kgdb_serial_getchar, -+}; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/arm/mach-versatile/kgdb_serial.c linux-2.6.18-53.1.14.kgdb/arch/arm/mach-versatile/kgdb_serial.c ---- linux-2.6.18-53.1.14/arch/arm/mach-versatile/kgdb_serial.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/arm/mach-versatile/kgdb_serial.c 2008-06-10 15:38:56.000000000 +0400 -@@ -0,0 +1,121 @@ -+/* -+ * arch/arm/mach-versatile/kgdb_serial.c -+ * -+ * Author: Manish Lachwani, mlachwani@mvista.com -+ * -+ * 2005 (c) MontaVista Software, Inc. This file is licensed under -+ * the terms of the GNU General Public License version 2. This program -+ * is licensed "as is" without any warranty of any kind, whether express -+ * or implied. -+ * -+ * Support for KGDB on ARM Versatile. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define ARM_BAUD_38400 23 -+/* -+ * Functions that will be used later -+ */ -+#define UART_GET_INT_STATUS(p) readb((p) + UART010_IIR) -+#define UART_GET_MIS(p) readw((p) + UART011_MIS) -+#define UART_PUT_ICR(p, c) writel((c), (p) + UART010_ICR) -+#define UART_GET_FR(p) readb((p) + UART01x_FR) -+#define UART_GET_CHAR(p) readb((p) + UART01x_DR) -+#define UART_PUT_CHAR(p, c) writel((c), (p) + UART01x_DR) -+#define UART_GET_RSR(p) readb((p) + UART01x_RSR) -+#define UART_GET_CR(p) readb((p) + UART010_CR) -+#define UART_PUT_CR(p,c) writel((c), (p) + UART010_CR) -+#define UART_GET_LCRL(p) readb((p) + UART010_LCRL) -+#define UART_PUT_LCRL(p,c) writel((c), (p) + UART010_LCRL) -+#define UART_GET_LCRM(p) readb((p) + UART010_LCRM) -+#define UART_PUT_LCRM(p,c) writel((c), (p) + UART010_LCRM) -+#define UART_GET_LCRH(p) readb((p) + UART010_LCRH) -+#define UART_PUT_LCRH(p,c) writel((c), (p) + UART010_LCRH) -+#define UART_RX_DATA(s) (((s) & UART01x_FR_RXFE) == 0) -+#define UART_TX_READY(s) (((s) & UART01x_FR_TXFF) == 0) -+#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART01x_FR_TMSK) == 0) -+ -+/* -+ * KGDB IRQ -+ */ -+static int kgdb_irq = 12; -+static volatile unsigned char *port = NULL; -+ -+static int kgdb_serial_init(void) -+{ -+ int rate = ARM_BAUD_38400; -+ -+ port = IO_ADDRESS(0x101F1000); -+ UART_PUT_CR(port, 0); -+ -+ /* Set baud rate */ -+ UART_PUT_LCRM(port, ((rate & 0xf00) >> 8)); -+ UART_PUT_LCRL(port, (rate & 0xff)); -+ UART_PUT_LCRH(port, UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN); -+ UART_PUT_CR(port, UART01x_CR_UARTEN); -+ -+ return 0; -+} -+ -+static void kgdb_serial_putchar(int ch) -+{ -+ unsigned int status; -+ -+ do { -+ status = UART_GET_FR(port); -+ } while (!UART_TX_READY(status)); -+ -+ UART_PUT_CHAR(port, ch); -+} -+ -+static int kgdb_serial_getchar(void) -+{ -+ unsigned int status; -+ int ch; -+ -+ do { -+ status = UART_GET_FR(port); -+ } while (!UART_RX_DATA(status)); -+ ch = UART_GET_CHAR(port); -+ return ch; -+} -+ -+static struct uart_port kgdb_amba_port = { -+ .irq = 12, -+ .iobase = 0, -+ .iotype = UPIO_MEM, -+ .membase = (unsigned char *)IO_ADDRESS(0x101F1000), -+}; -+ -+static irqreturn_t kgdb_interrupt(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ int status = UART_GET_MIS(port); -+ -+ if (irq != kgdb_irq) -+ return IRQ_NONE; -+ -+ if (status & 0x40) -+ breakpoint(); -+ -+ return IRQ_HANDLED; -+} -+ -+static void __init kgdb_hookup_irq(void) -+{ -+ request_irq(kgdb_irq, kgdb_interrupt, SA_SHIRQ, "GDB-stub", -+ &kgdb_amba_port); -+} -+ -+struct kgdb_io kgdb_io_ops = { -+ .init = kgdb_serial_init, -+ .write_char = kgdb_serial_putchar, -+ .read_char = kgdb_serial_getchar, -+ .late_init = kgdb_hookup_irq, -+}; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/arm/mm/extable.c linux-2.6.18-53.1.14.kgdb/arch/arm/mm/extable.c ---- linux-2.6.18-53.1.14/arch/arm/mm/extable.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/arm/mm/extable.c 2008-06-10 15:38:56.000000000 +0400 -@@ -2,6 +2,7 @@ - * linux/arch/arm/mm/extable.c - */ - #include -+#include - #include - - int fixup_exception(struct pt_regs *regs) -@@ -11,6 +12,12 @@ int fixup_exception(struct pt_regs *regs - fixup = search_exception_tables(instruction_pointer(regs)); - if (fixup) - regs->ARM_pc = fixup->fixup; -+#ifdef CONFIG_KGDB -+ if (atomic_read(&debugger_active) && kgdb_may_fault) -+ /* Restore our previous state. */ -+ kgdb_fault_longjmp(kgdb_fault_jmp_regs); -+ /* Not reached. */ -+#endif - - return fixup != NULL; - } -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/i386/kernel/Makefile linux-2.6.18-53.1.14.kgdb/arch/i386/kernel/Makefile ---- linux-2.6.18-53.1.14/arch/i386/kernel/Makefile 2008-03-06 05:54:14.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/i386/kernel/Makefile 2008-06-10 15:38:03.000000000 +0400 -@@ -39,6 +39,7 @@ obj-$(CONFIG_VM86) += vm86.o - obj-$(CONFIG_EARLY_PRINTK) += early_printk.o - obj-$(CONFIG_HPET_TIMER) += hpet.o - obj-$(CONFIG_K8_NB) += k8.o -+obj-$(CONFIG_KGDB) += kgdb.o kgdb-jmp.o - - EXTRA_AFLAGS := -traditional - -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/i386/kernel/entry.S linux-2.6.18-53.1.14.kgdb/arch/i386/kernel/entry.S ---- linux-2.6.18-53.1.14/arch/i386/kernel/entry.S 2008-03-06 05:55:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/i386/kernel/entry.S 2008-06-10 15:39:01.000000000 +0400 -@@ -201,7 +201,7 @@ VM_MASK = 0x00020000 - CFI_OFFSET ecx, ECX-OLDESP;\ - CFI_OFFSET ebx, EBX-OLDESP - --ENTRY(ret_from_fork) -+KPROBE_ENTRY(ret_from_fork) - CFI_STARTPROC - pushl %eax - CFI_ADJUST_CFA_OFFSET 4 -@@ -659,7 +659,7 @@ ENTRY(simd_coprocessor_error) - jmp error_code - CFI_ENDPROC - --ENTRY(device_not_available) -+KPROBE_ENTRY(device_not_available) - RING0_INT_FRAME - pushl $-1 # mark this as an int - CFI_ADJUST_CFA_OFFSET 4 -@@ -916,7 +916,7 @@ ENTRY(machine_check) - CFI_ENDPROC - #endif - --ENTRY(spurious_interrupt_bug) -+KPROBE_ENTRY(spurious_interrupt_bug) - RING0_INT_FRAME - pushl $0 - CFI_ADJUST_CFA_OFFSET 4 -@@ -942,3 +942,108 @@ ENDPROC(kernel_thread_helper) - #include "syscall_table.S" - - syscall_table_size=(.-sys_call_table) -+ -+# Here we do call frames. We cheat a bit as we only really need -+# correct frames at locations we can actually look at from a -+# debugger. Since the break instruction trap actually goes thru -+# some of this code, we don't really need info on those areas, but -+# only after the fact. I.e. if we can not step or break in a -+# location or end up with a return address pointing at the -+# location, we don't need a correct call frame for it. -+ -+#ifdef CONFIG_KGDB -+ -+#include -+/* -+ * The register numbers as known by gdb -+ */ -+ -+#define _EAX 0 -+#define _ECX 1 -+#define _EDX 2 -+#define _EBX 3 -+#define _ESP 4 -+#define _EBP 5 -+#define _ESI 6 -+#define _EDI 7 -+#define _PC 8 -+#define _EIP 8 -+#define _PS 9 -+#define _EFLAGS 9 -+#define _CS 10 -+#define _SS 11 -+#define _DS 12 -+#define _ES 13 -+#define _FS 14 -+#define _GS 15 -+ /* -+ * This code uses macros defined in linux/dwarf2-lang.h -+ * They attempt to follow the dwarf2 naming conventions... sort of.. -+ */ -+ENTRY(end_of_stack_stop_unwind_function) -+ .long end_of_stack_stop_unwind_function+1 -+ -+ .text -+ -+ CFI_preamble(c1,_PC,1,1) -+ CFA_define_reference(_ESP,OLDESP) /* Stack pointer */ -+ CFA_expression(_EIP) -+ CFA_exp_OP_dup /* copy old esp */ -+ CFA_exp_OP_consts(CS-OLDESP) /* offset to CS address */ -+ CFA_exp_OP_plus /* should be CS address */ -+ CFA_exp_OP_deref /* get the CS */ -+ CFA_exp_OP_const4s(VM_MASK|3) /* prepare to mask it */ -+ CFA_exp_OP_and /* mask it, zero means kernel */ -+ CFA_exp_OP_bra(eip_user_rtn) /* branch if user */ -+ CFA_exp_OP_const4s(EIP-OLDESP) /* offset to return address */ -+ CFA_exp_OP_plus /* add that in */ -+ CFA_exp_OP_skip(eip_end) /* done if kernel, skip out */ -+eip_user_rtn: -+ CFA_exp_OP_addr(end_of_stack_stop_unwind_function)/*dummy function */ -+eip_end: -+ CFA_expression_end -+ CFA_define_offset(_EBX,EBX-OLDESP) -+ CFA_define_offset(_ECX,ECX-OLDESP) -+ CFA_define_offset(_EDX,EDX-OLDESP) -+ CFA_define_offset(_ESI,ESI-OLDESP) -+ CFA_define_offset(_EDI,EDI-OLDESP) -+ CFA_define_offset(_EBP,EBP-OLDESP) -+ CFA_define_offset(_EAX,EAX-OLDESP) -+ CFA_define_offset(_EFLAGS,EFLAGS-OLDESP) -+ CFI_postamble() -+ -+/* -+ * This provides an uwind for our dummy end of unwind function. -+ * Current convention is to provied an undefined return address. -+ */ -+ CFI_preamble(c2,_PC,1,1) -+ CFA_define_reference(_ESP,0) /* Stack pointer */ -+ CFA_undefine_reg(_EIP) -+ CFI_postamble() -+ -+ FDE_preamble(c2,end_of_stack_stop_unwind_function, \ -+ end_of_stack_stop_unwind_function+5) -+ FDE_postamble() -+ /* -+ * This is VERY sloppy. At this point all we want to do is get -+ * the frame right for back tracing. It will not be good if -+ * you try to single step. We use already defined labels. -+ * We want to cover all call outs. -+ * We could also recode this as just one FDE, but this works and -+ * I want to get it out. -+ */ -+ FDE_preamble(c1,ret_from_fork,ret_from_exception) -+ CFA_define_cfa_offset(4) /* one extra word on stack */ -+ FDE_postamble() -+ -+ FDE_preamble(c1,ret_from_exception,device_not_available_emulate) -+ FDE_postamble() -+ -+ FDE_preamble(c1,device_not_available_emulate,debug) -+ CFA_define_cfa_offset(4) /* one extra word on stack */ -+ FDE_postamble() -+ -+ FDE_preamble(c1, debug,spurious_interrupt_bug) -+ FDE_postamble() -+ -+#endif -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/i386/kernel/head.S linux-2.6.18-53.1.14.kgdb/arch/i386/kernel/head.S ---- linux-2.6.18-53.1.14/arch/i386/kernel/head.S 2008-03-06 05:54:34.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/i386/kernel/head.S 2008-06-10 15:39:01.000000000 +0400 -@@ -10,6 +10,7 @@ - .text - #include - #include -+#include - #include - #include - #include -@@ -336,6 +337,10 @@ is386: movl $2,%ecx # set MP - #endif /* CONFIG_SMP */ - jmp start_kernel - -+ /* This dwarf code tells gdb that this is the end of the unwind */ -+ /* This uses the CFA set up for pc=1 located in entry.S */ -+ CFI_END_FRAME(is386) -+ - /* - * We depend on ET to be correct. This checks for 287/387. - */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/i386/kernel/kgdb-jmp.S linux-2.6.18-53.1.14.kgdb/arch/i386/kernel/kgdb-jmp.S ---- linux-2.6.18-53.1.14/arch/i386/kernel/kgdb-jmp.S 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/i386/kernel/kgdb-jmp.S 2008-06-10 15:38:03.000000000 +0400 -@@ -0,0 +1,74 @@ -+/* -+ * arch/i386/kernel/kgdb-jmp.S -+ * -+ * Save and restore system registers so that within a limited frame we -+ * may have a fault and "jump back" to a known safe location. -+ * -+ * Author: George Anzinger -+ * -+ * Cribbed from glibc, which carries the following: -+ * Copyright (C) 1996, 1996, 1997, 2000, 2001 Free Software Foundation, Inc. -+ * Copyright (C) 2005 by MontaVista Software. -+ * -+ * This file is licensed under the terms of the GNU General Public License -+ * version 2. This program as licensed "as is" without any warranty of -+ * any kind, whether express or implied. -+ */ -+ -+#include -+ -+#define PCOFF 0 -+#define LINKAGE 4 /* just the return address */ -+#define PTR_SIZE 4 -+#define PARMS LINKAGE /* no space for saved regs */ -+#define JMPBUF PARMS -+#define VAL JMPBUF+PTR_SIZE -+ -+#define JB_BX 0 -+#define JB_SI 1 -+#define JB_DI 2 -+#define JB_BP 3 -+#define JB_SP 4 -+#define JB_PC 5 -+ -+/* This must be called prior to kgdb_fault_longjmp and -+ * kgdb_fault_longjmp must not be called outside of the context of the -+ * last call to kgdb_fault_setjmp. -+ * kgdb_fault_setjmp(int *jmp_buf[6]) -+ */ -+ENTRY(kgdb_fault_setjmp) -+ movl JMPBUF(%esp), %eax -+ -+ /* Save registers. */ -+ movl %ebx, (JB_BX*4)(%eax) -+ movl %esi, (JB_SI*4)(%eax) -+ movl %edi, (JB_DI*4)(%eax) -+ /* Save SP as it will be after we return. */ -+ leal JMPBUF(%esp), %ecx -+ movl %ecx, (JB_SP*4)(%eax) -+ movl PCOFF(%esp), %ecx /* Save PC we are returning to now. */ -+ movl %ecx, (JB_PC*4)(%eax) -+ movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer. */ -+ -+ /* Restore state so we can now try the access. */ -+ movl JMPBUF(%esp), %ecx /* User's jmp_buf in %ecx. */ -+ /* Save the return address now. */ -+ movl (JB_PC*4)(%ecx), %edx -+ /* Restore registers. */ -+ movl $0, %eax -+ movl (JB_SP*4)(%ecx), %esp -+ jmp *%edx /* Jump to saved PC. */ -+ -+/* kgdb_fault_longjmp(int *jmp_buf[6]) */ -+ENTRY(kgdb_fault_longjmp) -+ movl JMPBUF(%esp), %ecx /* User's jmp_buf in %ecx. */ -+ /* Save the return address now. */ -+ movl (JB_PC*4)(%ecx), %edx -+ /* Restore registers. */ -+ movl (JB_BX*4)(%ecx), %ebx -+ movl (JB_SI*4)(%ecx), %esi -+ movl (JB_DI*4)(%ecx), %edi -+ movl (JB_BP*4)(%ecx), %ebp -+ movl $1, %eax -+ movl (JB_SP*4)(%ecx), %esp -+ jmp *%edx /* Jump to saved PC. */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/i386/kernel/kgdb.c linux-2.6.18-53.1.14.kgdb/arch/i386/kernel/kgdb.c ---- linux-2.6.18-53.1.14/arch/i386/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/i386/kernel/kgdb.c 2008-06-10 15:39:27.000000000 +0400 -@@ -0,0 +1,363 @@ -+/* -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2, or (at your option) any -+ * later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ */ -+ -+/* -+ * Copyright (C) 2000-2001 VERITAS Software Corporation. -+ */ -+/* -+ * Contributor: Lake Stevens Instrument Division$ -+ * Written by: Glenn Engel $ -+ * Updated by: Amit Kale -+ * Updated by: Tom Rini -+ * Modified for 386 by Jim Kingdon, Cygnus Support. -+ * Origianl kgdb, compatibility with 2.1.xx kernel by -+ * David Grothe -+ * Additional support from Tigran Aivazian -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* for linux pt_regs struct */ -+#include -+#include -+#include -+#include -+#include -+ -+#include "mach_ipi.h" -+ -+/* Put the error code here just in case the user cares. */ -+int gdb_i386errcode; -+/* Likewise, the vector number here (since GDB only gets the signal -+ number through the usual means, and that's not very specific). */ -+int gdb_i386vector = -1; -+ -+extern atomic_t cpu_doing_single_step; -+ -+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) -+{ -+ gdb_regs[_EAX] = regs->eax; -+ gdb_regs[_EBX] = regs->ebx; -+ gdb_regs[_ECX] = regs->ecx; -+ gdb_regs[_EDX] = regs->edx; -+ gdb_regs[_ESI] = regs->esi; -+ gdb_regs[_EDI] = regs->edi; -+ gdb_regs[_EBP] = regs->ebp; -+ gdb_regs[_DS] = regs->xds; -+ gdb_regs[_ES] = regs->xes; -+ gdb_regs[_PS] = regs->eflags; -+ gdb_regs[_CS] = regs->xcs; -+ gdb_regs[_PC] = regs->eip; -+ gdb_regs[_ESP] = (int)(®s->esp); -+ gdb_regs[_SS] = __KERNEL_DS; -+ gdb_regs[_FS] = 0xFFFF; -+ gdb_regs[_GS] = 0xFFFF; -+} -+ -+/* -+ * Extracts ebp, esp and eip values understandable by gdb from the values -+ * saved by switch_to. -+ * thread.esp points to ebp. flags and ebp are pushed in switch_to hence esp -+ * prior to entering switch_to is 8 greater then the value that is saved. -+ * If switch_to changes, change following code appropriately. -+ */ -+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) -+{ -+ gdb_regs[_EAX] = 0; -+ gdb_regs[_EBX] = 0; -+ gdb_regs[_ECX] = 0; -+ gdb_regs[_EDX] = 0; -+ gdb_regs[_ESI] = 0; -+ gdb_regs[_EDI] = 0; -+ gdb_regs[_EBP] = *(unsigned long *)p->thread.esp; -+ gdb_regs[_DS] = __KERNEL_DS; -+ gdb_regs[_ES] = __KERNEL_DS; -+ gdb_regs[_PS] = 0; -+ gdb_regs[_CS] = __KERNEL_CS; -+ gdb_regs[_PC] = p->thread.eip; -+ gdb_regs[_ESP] = p->thread.esp; -+ gdb_regs[_SS] = __KERNEL_DS; -+ gdb_regs[_FS] = 0xFFFF; -+ gdb_regs[_GS] = 0xFFFF; -+} -+ -+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs) -+{ -+ regs->eax = gdb_regs[_EAX]; -+ regs->ebx = gdb_regs[_EBX]; -+ regs->ecx = gdb_regs[_ECX]; -+ regs->edx = gdb_regs[_EDX]; -+ regs->esi = gdb_regs[_ESI]; -+ regs->edi = gdb_regs[_EDI]; -+ regs->ebp = gdb_regs[_EBP]; -+ regs->xds = gdb_regs[_DS]; -+ regs->xes = gdb_regs[_ES]; -+ regs->eflags = gdb_regs[_PS]; -+ regs->xcs = gdb_regs[_CS]; -+ regs->eip = gdb_regs[_PC]; -+} -+ -+static struct hw_breakpoint { -+ unsigned enabled; -+ unsigned type; -+ unsigned len; -+ unsigned addr; -+} breakinfo[4] = { -+ { .enabled = 0 }, -+ { .enabled = 0 }, -+ { .enabled = 0 }, -+ { .enabled = 0 }, -+}; -+ -+void kgdb_correct_hw_break(void) -+{ -+ int breakno; -+ int correctit; -+ int breakbit; -+ unsigned dr7; -+ -+ asm volatile ("movl %%db7, %0\n":"=r" (dr7) -+ :); -+ do { -+ unsigned addr0, addr1, addr2, addr3; -+ asm volatile ("movl %%db0, %0\n" -+ "movl %%db1, %1\n" -+ "movl %%db2, %2\n" -+ "movl %%db3, %3\n":"=r" (addr0), "=r"(addr1), -+ "=r"(addr2), "=r"(addr3):); -+ } while (0); -+ correctit = 0; -+ for (breakno = 0; breakno < 3; breakno++) { -+ breakbit = 2 << (breakno << 1); -+ if (!(dr7 & breakbit) && breakinfo[breakno].enabled) { -+ correctit = 1; -+ dr7 |= breakbit; -+ dr7 &= ~(0xf0000 << (breakno << 2)); -+ dr7 |= (((breakinfo[breakno].len << 2) | -+ breakinfo[breakno].type) << 16) << -+ (breakno << 2); -+ switch (breakno) { -+ case 0: -+ asm volatile ("movl %0, %%dr0\n"::"r" -+ (breakinfo[breakno].addr)); -+ break; -+ -+ case 1: -+ asm volatile ("movl %0, %%dr1\n"::"r" -+ (breakinfo[breakno].addr)); -+ break; -+ -+ case 2: -+ asm volatile ("movl %0, %%dr2\n"::"r" -+ (breakinfo[breakno].addr)); -+ break; -+ -+ case 3: -+ asm volatile ("movl %0, %%dr3\n"::"r" -+ (breakinfo[breakno].addr)); -+ break; -+ } -+ } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) { -+ correctit = 1; -+ dr7 &= ~breakbit; -+ dr7 &= ~(0xf0000 << (breakno << 2)); -+ } -+ } -+ if (correctit) -+ asm volatile ("movl %0, %%db7\n"::"r" (dr7)); -+} -+ -+int kgdb_remove_hw_break(unsigned long addr) -+{ -+ int i, idx = -1; -+ for (i = 0; i < 4; i++) { -+ if (breakinfo[i].addr == addr && breakinfo[i].enabled) { -+ idx = i; -+ break; -+ } -+ } -+ if (idx == -1) -+ return -1; -+ -+ breakinfo[idx].enabled = 0; -+ return 0; -+} -+ -+void kgdb_remove_all_hw_break(void) -+{ -+ int i; -+ -+ for (i = 0; i < 4; i++) { -+ if (breakinfo[i].enabled) { -+ /* Do what? */ -+ ; -+ } -+ memset(&breakinfo[i], 0, sizeof(struct hw_breakpoint)); -+ } -+} -+ -+int kgdb_set_hw_break(unsigned long addr) -+{ -+ int i, idx = -1; -+ for (i = 0; i < 4; i++) { -+ if (!breakinfo[i].enabled) { -+ idx = i; -+ break; -+ } -+ } -+ if (idx == -1) -+ return -1; -+ -+ breakinfo[idx].enabled = 1; -+ breakinfo[idx].type = 1; -+ breakinfo[idx].len = 1; -+ breakinfo[idx].addr = addr; -+ return 0; -+} -+ -+void kgdb_disable_hw_debug(struct pt_regs *regs) -+{ -+ /* Disable hardware debugging while we are in kgdb */ -+ asm volatile ("movl %0,%%db7": /* no output */ :"r" (0)); -+} -+ -+void kgdb_post_master_code(struct pt_regs *regs, int e_vector, int err_code) -+{ -+ /* Master processor is completely in the debugger */ -+ gdb_i386vector = e_vector; -+ gdb_i386errcode = err_code; -+} -+ -+void kgdb_roundup_cpus(unsigned long flags) -+{ -+ send_IPI_allbutself(APIC_DM_NMI); -+} -+ -+int kgdb_arch_handle_exception(int e_vector, int signo, -+ int err_code, char *remcom_in_buffer, -+ char *remcom_out_buffer, -+ struct pt_regs *linux_regs) -+{ -+ long addr; -+ char *ptr; -+ int newPC, dr6; -+ -+ switch (remcom_in_buffer[0]) { -+ case 'c': -+ case 's': -+ /* try to read optional parameter, pc unchanged if no parm */ -+ ptr = &remcom_in_buffer[1]; -+ if (kgdb_hex2long(&ptr, &addr)) -+ linux_regs->eip = addr; -+ newPC = linux_regs->eip; -+ -+ /* clear the trace bit */ -+ linux_regs->eflags &= ~TF_MASK; -+ atomic_set(&cpu_doing_single_step, -1); -+ -+ /* set the trace bit if we're stepping */ -+ if (remcom_in_buffer[0] == 's') { -+ linux_regs->eflags |= TF_MASK; -+ debugger_step = 1; -+ atomic_set(&cpu_doing_single_step,smp_processor_id()); -+ } -+ -+ asm volatile ("movl %%db6, %0\n":"=r" (dr6)); -+ if (!(dr6 & 0x4000)) { -+ long breakno; -+ for (breakno = 0; breakno < 4; ++breakno) { -+ if (dr6 & (1 << breakno) && -+ breakinfo[breakno].type == 0) { -+ /* Set restore flag */ -+ linux_regs->eflags |= X86_EFLAGS_RF; -+ break; -+ } -+ } -+ } -+ kgdb_correct_hw_break(); -+ asm volatile ("movl %0, %%db6\n"::"r" (0)); -+ -+ return (0); -+ } /* switch */ -+ /* this means that we do not want to exit from the handler */ -+ return -1; -+} -+ -+/* Register KGDB with the i386die_chain so that we hook into all of the right -+ * spots. */ -+static int kgdb_notify(struct notifier_block *self, unsigned long cmd, -+ void *ptr) -+{ -+ struct die_args *args = ptr; -+ struct pt_regs *regs = args->regs; -+ -+ /* Bad memory access? */ -+ if (cmd == DIE_PAGE_FAULT_NO_CONTEXT && atomic_read(&debugger_active) -+ && kgdb_may_fault) { -+ kgdb_fault_longjmp(kgdb_fault_jmp_regs); -+ return NOTIFY_STOP; -+ } else if (cmd == DIE_PAGE_FAULT) -+ /* A normal page fault, ignore. */ -+ return NOTIFY_DONE; -+ else if ((cmd == DIE_NMI || cmd == DIE_NMI_IPI || -+ cmd == DIE_NMIWATCHDOG) && atomic_read(&debugger_active)) { -+ /* CPU roundup */ -+ kgdb_nmihook(smp_processor_id(), regs); -+ return NOTIFY_STOP; -+ } else if (cmd == DIE_NMI_IPI || cmd == DIE_NMI || user_mode(regs) || -+ (cmd == DIE_DEBUG && atomic_read(&debugger_active))) -+ /* Normal watchdog event or userspace debugging, or spurious -+ * debug exception, ignore. */ -+ return NOTIFY_DONE; -+ -+ kgdb_handle_exception(args->trapnr, args->signr, args->err, regs); -+ -+ return NOTIFY_STOP; -+} -+ -+static struct notifier_block kgdb_notifier = { -+ .notifier_call = kgdb_notify, -+}; -+ -+int kgdb_arch_init(void) -+{ -+ atomic_notifier_chain_register(&i386die_chain, &kgdb_notifier); -+ return 0; -+} -+ -+/* -+ * Skip an int3 exception when it occurs after a breakpoint has been -+ * removed. Backtrack eip by 1 since the int3 would have caused it to -+ * increment by 1. -+ */ -+ -+int kgdb_skipexception(int exception, struct pt_regs *regs) -+{ -+ if (exception == 3 && kgdb_isremovedbreak(regs->eip - 1)) { -+ regs->eip -= 1; -+ return 1; -+ } -+ return 0; -+} -+ -+struct kgdb_arch arch_kgdb_ops = { -+ .gdb_bpt_instr = {0xcc}, -+ .flags = KGDB_HW_BREAKPOINT, -+}; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/i386/kernel/setup.c linux-2.6.18-53.1.14.kgdb/arch/i386/kernel/setup.c ---- linux-2.6.18-53.1.14/arch/i386/kernel/setup.c 2008-03-06 05:54:58.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/i386/kernel/setup.c 2008-06-10 15:38:03.000000000 +0400 -@@ -148,6 +148,7 @@ EXPORT_SYMBOL(ist_info); - struct e820map e820; - - extern void early_cpu_init(void); -+extern void early_trap_init(void); - extern void generic_apic_probe(char *); - extern int root_mountflags; - -@@ -1470,6 +1471,7 @@ void __init setup_arch(char **cmdline_p) - memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data)); - pre_setup_arch_hook(); - early_cpu_init(); -+ early_trap_init(); - - /* - * FIXME: This isn't an official loader_type right -@@ -1526,6 +1528,7 @@ void __init setup_arch(char **cmdline_p) - data_resource.end = virt_to_phys(_edata)-1; - - parse_cmdline_early(cmdline_p); -+ parse_early_param(); - - #ifdef CONFIG_EARLY_PRINTK - { -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/i386/kernel/smpboot.c linux-2.6.18-53.1.14.kgdb/arch/i386/kernel/smpboot.c ---- linux-2.6.18-53.1.14/arch/i386/kernel/smpboot.c 2008-03-06 05:54:34.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/i386/kernel/smpboot.c 2008-06-10 15:39:01.000000000 +0400 -@@ -592,6 +592,9 @@ void __devinit initialize_secondary(void - - asm volatile( - "movl %0,%%esp\n\t" -+#ifdef CONFIG_KGDB -+ "pushl end_of_stack_stop_unwind_function\n\t" -+#endif - "jmp *%1" - : - :"r" (current->thread.esp),"r" (current->thread.eip)); -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/i386/kernel/traps.c linux-2.6.18-53.1.14.kgdb/arch/i386/kernel/traps.c ---- linux-2.6.18-53.1.14/arch/i386/kernel/traps.c 2008-03-06 05:55:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/i386/kernel/traps.c 2008-06-10 15:38:03.000000000 +0400 -@@ -964,6 +964,7 @@ fastcall void __kprobes do_debug(struct - */ - clear_dr7: - set_debugreg(0, 7); -+ notify_die(DIE_DEBUG, "debug2", regs, condition, error_code, SIGTRAP); - return; - - debug_vm86: -@@ -1268,6 +1269,12 @@ static void __init set_task_gate(unsigne - _set_gate(idt_table+n,5,0,0,(gdt_entry<<3)); - } - -+/* Some traps need to be set early. */ -+void __init early_trap_init(void) { -+ set_intr_gate(1,&debug); -+ set_system_intr_gate(3, &int3); /* int3 can be called from all */ -+ set_intr_gate(14,&page_fault); -+} - - void __init trap_init(void) - { -@@ -1284,10 +1291,8 @@ void __init trap_init(void) - #endif - - set_trap_gate(0,÷_error); -- set_intr_gate(1,&debug); - set_intr_gate(2,&nmi); -- set_system_intr_gate(3, &int3); /* int3/4 can be called from all */ -- set_system_gate(4,&overflow); -+ set_system_gate(4,&overflow); /* int4/5 can be called from all */ - set_trap_gate(5,&bounds); - set_trap_gate(6,&invalid_op); - set_trap_gate(7,&device_not_available); -@@ -1297,7 +1302,6 @@ void __init trap_init(void) - set_trap_gate(11,&segment_not_present); - set_trap_gate(12,&stack_segment); - set_trap_gate(13,&general_protection); -- set_intr_gate(14,&page_fault); - set_trap_gate(15,&spurious_interrupt_bug); - set_trap_gate(16,&coprocessor_error); - set_trap_gate(17,&alignment_check); -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/i386/mm/fault.c linux-2.6.18-53.1.14.kgdb/arch/i386/mm/fault.c ---- linux-2.6.18-53.1.14/arch/i386/mm/fault.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/i386/mm/fault.c 2008-06-10 15:38:03.000000000 +0400 -@@ -539,6 +539,10 @@ no_context: - if (is_prefetch(regs, address, error_code)) - return; - -+ if (notify_die(DIE_PAGE_FAULT_NO_CONTEXT, "no context", regs, -+ error_code, 14, SIGSEGV) == NOTIFY_STOP) -+ return; -+ - /* - * Oops. The kernel tried to access some bad page. We'll have to - * terminate things with extreme prejudice. -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ia64/kernel/Makefile linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/Makefile ---- linux-2.6.18-53.1.14/arch/ia64/kernel/Makefile 2008-03-06 05:54:11.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/Makefile 2008-06-10 15:38:32.000000000 +0400 -@@ -32,6 +32,7 @@ obj-$(CONFIG_KEXEC) += machine_kexec.o - obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o - obj-$(CONFIG_AUDIT) += audit.o - mca_recovery-y += mca_drv.o mca_drv_asm.o -+obj-$(CONFIG_KGDB) += kgdb.o kgdb-jmp.o - - # The gate DSO image is built using a special linker script. - targets += gate.so gate-syms.o -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ia64/kernel/entry.S linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/entry.S ---- linux-2.6.18-53.1.14/arch/ia64/kernel/entry.S 2008-03-06 05:54:43.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/entry.S 2008-06-10 15:39:39.000000000 +0400 -@@ -959,9 +959,9 @@ GLOBAL_ENTRY(__ia64_leave_kernel) - shr.u r18=r19,16 // get byte size of existing "dirty" partition - ;; - mov r16=ar.bsp // get existing backing store pointer -- addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0 -+(pUStk) addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0 - ;; -- ld4 r17=[r17] // r17 = cpu_data->phys_stacked_size_p8 -+(pUStk) ld4 r17=[r17] // r17 = cpu_data->phys_stacked_size_p8 - (pKStk) br.cond.dpnt skip_rbs_switch - - /* -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ia64/kernel/ivt.S linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/ivt.S ---- linux-2.6.18-53.1.14/arch/ia64/kernel/ivt.S 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/ivt.S 2008-06-10 15:39:39.000000000 +0400 -@@ -52,6 +52,14 @@ - #include - #include - -+#ifdef CONFIG_KGDB -+#define KGDB_ENABLE_PSR_DB mov r31=psr;; movl r30=IA64_PSR_DB;; \ -+ or r31=r31,r30;; \ -+ mov psr.l=r31;; srlz.i;; -+#else -+#define KGDB_ENABLE_PSR_DB -+#endif -+ - #if 1 - # define PSR_DEFAULT_BITS psr.ac - #else -@@ -519,6 +527,7 @@ ENTRY(page_fault) - movl r14=ia64_leave_kernel - ;; - SAVE_REST -+ KGDB_ENABLE_PSR_DB - mov rp=r14 - ;; - adds out2=16,r12 // out2 = pointer to pt_regs -@@ -863,6 +872,7 @@ ENTRY(interrupt) - srlz.i // ensure everybody knows psr.ic is back on - ;; - SAVE_REST -+ KGDB_ENABLE_PSR_DB - ;; - MCA_RECOVER_RANGE(interrupt) - alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group -@@ -1110,6 +1120,7 @@ ENTRY(non_syscall) - movl r15=ia64_leave_kernel - ;; - SAVE_REST -+ KGDB_ENABLE_PSR_DB - mov rp=r15 - ;; - br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and ignore return addr -@@ -1143,6 +1154,7 @@ ENTRY(dispatch_unaligned_handler) - adds r3=8,r2 // set up second base pointer - ;; - SAVE_REST -+ KGDB_ENABLE_PSR_DB - movl r14=ia64_leave_kernel - ;; - mov rp=r14 -@@ -1185,6 +1197,10 @@ ENTRY(dispatch_to_fault_handler) - adds r3=8,r2 // set up second base pointer for SAVE_REST - ;; - SAVE_REST -+ cmp.eq p6,p0=29,out0 -+(p6) br.cond.spnt 1f;; // debug_vector -+ KGDB_ENABLE_PSR_DB -+1: - movl r14=ia64_leave_kernel - ;; - mov rp=r14 -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ia64/kernel/kgdb-jmp.S linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/kgdb-jmp.S ---- linux-2.6.18-53.1.14/arch/ia64/kernel/kgdb-jmp.S 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/kgdb-jmp.S 2008-06-10 15:38:32.000000000 +0400 -@@ -0,0 +1,238 @@ -+/* setjmp() and longjmp() assembler support for kdb on ia64. -+ -+ This code was copied from glibc CVS as of 2001-06-27 and modified where -+ necessary to fit the kernel. -+ Keith Owens 2001-06-27 -+ */ -+ -+/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. -+ Contributed by David Mosberger-Tang . -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Library General Public License as -+ published by the Free Software Foundation; either version 2 of the -+ License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Library General Public License for more details. -+ -+ You should have received a copy of the GNU Library General Public -+ License along with the GNU C Library; see the file COPYING.LIB. If -+ not, write to the Free Software Foundation, Inc., -+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+*/ -+ -+#include -+GLOBAL_ENTRY(kgdb_fault_setjmp) -+ .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2) -+ alloc loc1=ar.pfs,2,2,2,0 -+ mov r16=ar.unat -+ ;; -+ mov r17=ar.fpsr -+ mov r2=in0 -+ add r3=8,in0 -+ ;; -+.mem.offset 0,0; -+ st8.spill.nta [r2]=sp,16 // r12 (sp) -+.mem.offset 8,0; -+ st8.spill.nta [r3]=gp,16 // r1 (gp) -+ ;; -+ st8.nta [r2]=r16,16 // save caller's unat -+ st8.nta [r3]=r17,16 // save fpsr -+ add r8=0xa0,in0 -+ ;; -+.mem.offset 160,0; -+ st8.spill.nta [r2]=r4,16 // r4 -+.mem.offset 168,0; -+ st8.spill.nta [r3]=r5,16 // r5 -+ add r9=0xb0,in0 -+ ;; -+ stf.spill.nta [r8]=f2,32 -+ stf.spill.nta [r9]=f3,32 -+ mov loc0=rp -+ .body -+ ;; -+ stf.spill.nta [r8]=f4,32 -+ stf.spill.nta [r9]=f5,32 -+ mov r17=b1 -+ ;; -+ stf.spill.nta [r8]=f16,32 -+ stf.spill.nta [r9]=f17,32 -+ mov r18=b2 -+ ;; -+ stf.spill.nta [r8]=f18,32 -+ stf.spill.nta [r9]=f19,32 -+ mov r19=b3 -+ ;; -+ stf.spill.nta [r8]=f20,32 -+ stf.spill.nta [r9]=f21,32 -+ mov r20=b4 -+ ;; -+ stf.spill.nta [r8]=f22,32 -+ stf.spill.nta [r9]=f23,32 -+ mov r21=b5 -+ ;; -+ stf.spill.nta [r8]=f24,32 -+ stf.spill.nta [r9]=f25,32 -+ mov r22=ar.lc -+ ;; -+ stf.spill.nta [r8]=f26,32 -+ stf.spill.nta [r9]=f27,32 -+ mov r24=pr -+ ;; -+ stf.spill.nta [r8]=f28,32 -+ stf.spill.nta [r9]=f29,32 -+ ;; -+ stf.spill.nta [r8]=f30 -+ stf.spill.nta [r9]=f31 -+ -+.mem.offset 0,0; -+ st8.spill.nta [r2]=r6,16 // r6 -+.mem.offset 8,0; -+ st8.spill.nta [r3]=r7,16 // r7 -+ ;; -+ mov r23=ar.bsp -+ mov r25=ar.unat -+ st8.nta [r2]=loc0,16 // b0 -+ st8.nta [r3]=r17,16 // b1 -+ ;; -+ st8.nta [r2]=r18,16 // b2 -+ st8.nta [r3]=r19,16 // b3 -+ ;; -+ st8.nta [r2]=r20,16 // b4 -+ st8.nta [r3]=r21,16 // b5 -+ ;; -+ st8.nta [r2]=loc1,16 // ar.pfs -+ st8.nta [r3]=r22,16 // ar.lc -+ ;; -+ st8.nta [r2]=r24,16 // pr -+ st8.nta [r3]=r23,16 // ar.bsp -+ ;; -+ st8.nta [r2]=r25 // ar.unat -+ st8.nta [r3]=in0 // &__jmp_buf -+ mov r8=0 -+ mov rp=loc0 -+ mov ar.pfs=loc1 -+ br.ret.sptk.few rp -+END(kdba_setjmp) -+#define pPos p6 /* is rotate count positive? */ -+#define pNeg p7 /* is rotate count negative? */ -+GLOBAL_ENTRY(kgdb_fault_longjmp) -+ alloc r8=ar.pfs,2,1,0,0 -+ mov r27=ar.rsc -+ add r2=0x98,in0 // r2 <- &jmpbuf.orig_jmp_buf_addr -+ ;; -+ ld8 r8=[r2],-16 // r8 <- orig_jmp_buf_addr -+ mov r10=ar.bsp -+ and r11=~0x3,r27 // clear ar.rsc.mode -+ ;; -+ flushrs // flush dirty regs to backing store (must be first in insn grp) -+ ld8 r23=[r2],8 // r23 <- jmpbuf.ar_bsp -+ sub r8=r8,in0 // r8 <- &orig_jmpbuf - &jmpbuf -+ ;; -+ ld8 r25=[r2] // r25 <- jmpbuf.ar_unat -+ extr.u r8=r8,3,6 // r8 <- (&orig_jmpbuf - &jmpbuf)/8 & 0x3f -+ ;; -+ cmp.lt pNeg,pPos=r8,r0 -+ mov r2=in0 -+ ;; -+(pPos) mov r16=r8 -+(pNeg) add r16=64,r8 -+(pPos) sub r17=64,r8 -+(pNeg) sub r17=r0,r8 -+ ;; -+ mov ar.rsc=r11 // put RSE in enforced lazy mode -+ shr.u r8=r25,r16 -+ add r3=8,in0 // r3 <- &jmpbuf.r1 -+ shl r9=r25,r17 -+ ;; -+ or r25=r8,r9 -+ ;; -+ mov r26=ar.rnat -+ mov ar.unat=r25 // setup ar.unat (NaT bits for r1, r4-r7, and r12) -+ ;; -+ ld8.fill.nta sp=[r2],16 // r12 (sp) -+ ld8.fill.nta gp=[r3],16 // r1 (gp) -+ dep r11=-1,r23,3,6 // r11 <- ia64_rse_rnat_addr(jmpbuf.ar_bsp) -+ ;; -+ ld8.nta r16=[r2],16 // caller's unat -+ ld8.nta r17=[r3],16 // fpsr -+ ;; -+ ld8.fill.nta r4=[r2],16 // r4 -+ ld8.fill.nta r5=[r3],16 // r5 (gp) -+ cmp.geu p8,p0=r10,r11 // p8 <- (ar.bsp >= jmpbuf.ar_bsp) -+ ;; -+ ld8.fill.nta r6=[r2],16 // r6 -+ ld8.fill.nta r7=[r3],16 // r7 -+ ;; -+ mov ar.unat=r16 // restore caller's unat -+ mov ar.fpsr=r17 // restore fpsr -+ ;; -+ ld8.nta r16=[r2],16 // b0 -+ ld8.nta r17=[r3],16 // b1 -+ ;; -+(p8) ld8 r26=[r11] // r26 <- *ia64_rse_rnat_addr(jmpbuf.ar_bsp) -+ mov ar.bspstore=r23 // restore ar.bspstore -+ ;; -+ ld8.nta r18=[r2],16 // b2 -+ ld8.nta r19=[r3],16 // b3 -+ ;; -+ ld8.nta r20=[r2],16 // b4 -+ ld8.nta r21=[r3],16 // b5 -+ ;; -+ ld8.nta r11=[r2],16 // ar.pfs -+ ld8.nta r22=[r3],56 // ar.lc -+ ;; -+ ld8.nta r24=[r2],32 // pr -+ mov b0=r16 -+ ;; -+ ldf.fill.nta f2=[r2],32 -+ ldf.fill.nta f3=[r3],32 -+ mov b1=r17 -+ ;; -+ ldf.fill.nta f4=[r2],32 -+ ldf.fill.nta f5=[r3],32 -+ mov b2=r18 -+ ;; -+ ldf.fill.nta f16=[r2],32 -+ ldf.fill.nta f17=[r3],32 -+ mov b3=r19 -+ ;; -+ ldf.fill.nta f18=[r2],32 -+ ldf.fill.nta f19=[r3],32 -+ mov b4=r20 -+ ;; -+ ldf.fill.nta f20=[r2],32 -+ ldf.fill.nta f21=[r3],32 -+ mov b5=r21 -+ ;; -+ ldf.fill.nta f22=[r2],32 -+ ldf.fill.nta f23=[r3],32 -+ mov ar.lc=r22 -+ ;; -+ ldf.fill.nta f24=[r2],32 -+ ldf.fill.nta f25=[r3],32 -+ cmp.eq p8,p9=0,in1 -+ ;; -+ ldf.fill.nta f26=[r2],32 -+ ldf.fill.nta f27=[r3],32 -+ mov ar.pfs=r11 -+ ;; -+ ldf.fill.nta f28=[r2],32 -+ ldf.fill.nta f29=[r3],32 -+ ;; -+ ldf.fill.nta f30=[r2] -+ ldf.fill.nta f31=[r3] -+(p8) mov r8=1 -+ -+ mov ar.rnat=r26 // restore ar.rnat -+ ;; -+ mov ar.rsc=r27 // restore ar.rsc -+(p9) mov r8=in1 -+ -+ invala // virt. -> phys. regnum mapping may change -+ mov pr=r24,-1 -+ br.ret.sptk.few rp -+END(kgdb_fault_longjmp) -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ia64/kernel/kgdb.c linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/kgdb.c ---- linux-2.6.18-53.1.14/arch/ia64/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/kgdb.c 2008-06-10 15:38:32.000000000 +0400 -@@ -0,0 +1,1131 @@ -+/* -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2, or (at your option) any -+ * later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ */ -+ -+/* -+ * Copyright (C) 2000-2001 VERITAS Software Corporation. -+ * (c) Copyright 2005 Hewlett-Packard Development Company, L.P. -+ * Bob Picco -+ */ -+/* -+ * Contributor: Lake Stevens Instrument Division$ -+ * Written by: Glenn Engel $ -+ * Updated by: Amit Kale -+ * Modified for 386 by Jim Kingdon, Cygnus Support. -+ * Origianl kgdb, compatibility with 2.1.xx kernel by David Grothe -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* for linux pt_regs struct */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define NUM_REGS 590 -+#define REGISTER_BYTES (NUM_REGS*8+128*8) -+#define REGISTER_BYTE(N) (((N) * 8) \ -+ + ((N) <= IA64_FR0_REGNUM ? \ -+ 0 : 8 * (((N) > IA64_FR127_REGNUM) ? 128 : (N) - IA64_FR0_REGNUM))) -+#define REGISTER_SIZE(N) \ -+ (((N) >= IA64_FR0_REGNUM && (N) <= IA64_FR127_REGNUM) ? 16 : 8) -+#define IA64_GR0_REGNUM 0 -+#define IA64_FR0_REGNUM 128 -+#define IA64_FR127_REGNUM (IA64_FR0_REGNUM+127) -+#define IA64_PR0_REGNUM 256 -+#define IA64_BR0_REGNUM 320 -+#define IA64_VFP_REGNUM 328 -+#define IA64_PR_REGNUM 330 -+#define IA64_IP_REGNUM 331 -+#define IA64_PSR_REGNUM 332 -+#define IA64_CFM_REGNUM 333 -+#define IA64_AR0_REGNUM 334 -+#define IA64_NAT0_REGNUM 462 -+#define IA64_NAT31_REGNUM (IA64_NAT0_REGNUM+31) -+#define IA64_NAT32_REGNUM (IA64_NAT0_REGNUM+32) -+#define IA64_RSC_REGNUM (IA64_AR0_REGNUM+16) -+#define IA64_BSP_REGNUM (IA64_AR0_REGNUM+17) -+#define IA64_BSPSTORE_REGNUM (IA64_AR0_REGNUM+18) -+#define IA64_RNAT_REGNUM (IA64_AR0_REGNUM+19) -+#define IA64_FCR_REGNUM (IA64_AR0_REGNUM+21) -+#define IA64_EFLAG_REGNUM (IA64_AR0_REGNUM+24) -+#define IA64_CSD_REGNUM (IA64_AR0_REGNUM+25) -+#define IA64_SSD_REGNUM (IA64_AR0_REGNUM+26) -+#define IA64_CFLG_REGNUM (IA64_AR0_REGNUM+27) -+#define IA64_FSR_REGNUM (IA64_AR0_REGNUM+28) -+#define IA64_FIR_REGNUM (IA64_AR0_REGNUM+29) -+#define IA64_FDR_REGNUM (IA64_AR0_REGNUM+30) -+#define IA64_CCV_REGNUM (IA64_AR0_REGNUM+32) -+#define IA64_UNAT_REGNUM (IA64_AR0_REGNUM+36) -+#define IA64_FPSR_REGNUM (IA64_AR0_REGNUM+40) -+#define IA64_ITC_REGNUM (IA64_AR0_REGNUM+44) -+#define IA64_PFS_REGNUM (IA64_AR0_REGNUM+64) -+#define IA64_LC_REGNUM (IA64_AR0_REGNUM+65) -+#define IA64_EC_REGNUM (IA64_AR0_REGNUM+66) -+ -+#define REGISTER_INDEX(N) (REGISTER_BYTE(N) / sizeof (unsigned long)) -+#define BREAK_INSTR_ALIGN (~0xfULL) -+ -+#define ptoff(V) ((unsigned int) &((struct pt_regs *)0x0)->V) -+struct reg_to_ptreg_index { -+ unsigned int reg; -+ unsigned int ptregoff; -+}; -+ -+static struct reg_to_ptreg_index gr_reg_to_ptreg_index[] = { -+ {IA64_GR0_REGNUM + 1, ptoff(r1)}, -+ {IA64_GR0_REGNUM + 2, ptoff(r2)}, -+ {IA64_GR0_REGNUM + 3, ptoff(r3)}, -+ {IA64_GR0_REGNUM + 8, ptoff(r8)}, -+ {IA64_GR0_REGNUM + 9, ptoff(r9)}, -+ {IA64_GR0_REGNUM + 10, ptoff(r10)}, -+ {IA64_GR0_REGNUM + 11, ptoff(r11)}, -+ {IA64_GR0_REGNUM + 12, ptoff(r12)}, -+ {IA64_GR0_REGNUM + 13, ptoff(r13)}, -+ {IA64_GR0_REGNUM + 14, ptoff(r14)}, -+ {IA64_GR0_REGNUM + 15, ptoff(r15)}, -+ {IA64_GR0_REGNUM + 16, ptoff(r16)}, -+ {IA64_GR0_REGNUM + 17, ptoff(r17)}, -+ {IA64_GR0_REGNUM + 18, ptoff(r18)}, -+ {IA64_GR0_REGNUM + 19, ptoff(r19)}, -+ {IA64_GR0_REGNUM + 20, ptoff(r20)}, -+ {IA64_GR0_REGNUM + 21, ptoff(r21)}, -+ {IA64_GR0_REGNUM + 22, ptoff(r22)}, -+ {IA64_GR0_REGNUM + 23, ptoff(r23)}, -+ {IA64_GR0_REGNUM + 24, ptoff(r24)}, -+ {IA64_GR0_REGNUM + 25, ptoff(r25)}, -+ {IA64_GR0_REGNUM + 26, ptoff(r26)}, -+ {IA64_GR0_REGNUM + 27, ptoff(r27)}, -+ {IA64_GR0_REGNUM + 28, ptoff(r28)}, -+ {IA64_GR0_REGNUM + 29, ptoff(r29)}, -+ {IA64_GR0_REGNUM + 30, ptoff(r30)}, -+ {IA64_GR0_REGNUM + 31, ptoff(r31)}, -+}; -+ -+static struct reg_to_ptreg_index br_reg_to_ptreg_index[] = { -+ {IA64_BR0_REGNUM, ptoff(b0)}, -+ {IA64_BR0_REGNUM + 6, ptoff(b6)}, -+ {IA64_BR0_REGNUM + 7, ptoff(b7)}, -+}; -+ -+static struct reg_to_ptreg_index ar_reg_to_ptreg_index[] = { -+ {IA64_PFS_REGNUM, ptoff(ar_pfs)}, -+ {IA64_UNAT_REGNUM, ptoff(ar_unat)}, -+ {IA64_RNAT_REGNUM, ptoff(ar_rnat)}, -+ {IA64_BSPSTORE_REGNUM, ptoff(ar_bspstore)}, -+ {IA64_RSC_REGNUM, ptoff(ar_rsc)}, -+ {IA64_CSD_REGNUM, ptoff(ar_csd)}, -+ {IA64_SSD_REGNUM, ptoff(ar_ssd)}, -+ {IA64_FPSR_REGNUM, ptoff(ar_fpsr)}, -+ {IA64_CCV_REGNUM, ptoff(ar_ccv)}, -+}; -+ -+extern atomic_t cpu_doing_single_step; -+ -+static int kgdb_gr_reg(int regnum, struct unw_frame_info *info, -+ unsigned long *reg, int rw) -+{ -+ char nat; -+ -+ if ((regnum >= IA64_GR0_REGNUM && regnum <= (IA64_GR0_REGNUM + 1)) || -+ (regnum >= (IA64_GR0_REGNUM + 4) && -+ regnum <= (IA64_GR0_REGNUM + 7))) -+ return !unw_access_gr(info, regnum - IA64_GR0_REGNUM, -+ reg, &nat, rw); -+ else -+ return 0; -+} -+static int kgdb_gr_ptreg(int regnum, struct pt_regs * ptregs, -+ struct unw_frame_info *info, unsigned long *reg, int rw) -+{ -+ int i, result = 1; -+ char nat; -+ -+ if (!((regnum >= (IA64_GR0_REGNUM + 2) && -+ regnum <= (IA64_GR0_REGNUM + 3)) || -+ (regnum >= (IA64_GR0_REGNUM + 8) && -+ regnum <= (IA64_GR0_REGNUM + 15)) || -+ (regnum >= (IA64_GR0_REGNUM + 16) && -+ regnum <= (IA64_GR0_REGNUM + 31)))) -+ return 0; -+ else if (rw && ptregs) { -+ for (i = 0; i < ARRAY_SIZE(gr_reg_to_ptreg_index); i++) -+ if (gr_reg_to_ptreg_index[i].reg == regnum) { -+ *((unsigned long *)(((void *)ptregs) + -+ gr_reg_to_ptreg_index[i].ptregoff)) = *reg; -+ break; -+ } -+ } else if (!rw && ptregs) { -+ for (i = 0; i < ARRAY_SIZE(gr_reg_to_ptreg_index); i++) -+ if (gr_reg_to_ptreg_index[i].reg == regnum) { -+ *reg = *((unsigned long *) -+ (((void *)ptregs) + -+ gr_reg_to_ptreg_index[i].ptregoff)); -+ break; -+ } -+ } else -+ result = !unw_access_gr(info, regnum - IA64_GR0_REGNUM, -+ reg, &nat, rw); -+ return result; -+} -+ -+static int kgdb_br_reg(int regnum, struct pt_regs * ptregs, -+ struct unw_frame_info *info, unsigned long *reg, int rw) -+{ -+ int i, result = 1; -+ -+ if (!(regnum >= IA64_BR0_REGNUM && regnum <= (IA64_BR0_REGNUM + 7))) -+ return 0; -+ -+ switch (regnum) { -+ case IA64_BR0_REGNUM: -+ case IA64_BR0_REGNUM + 6: -+ case IA64_BR0_REGNUM + 7: -+ if (rw) { -+ for (i = 0; i < ARRAY_SIZE(br_reg_to_ptreg_index); i++) -+ if (br_reg_to_ptreg_index[i].reg == regnum) { -+ *((unsigned long *) -+ (((void *)ptregs) + -+ br_reg_to_ptreg_index[i].ptregoff)) = -+ *reg; -+ break; -+ } -+ } else -+ for (i = 0; i < ARRAY_SIZE(br_reg_to_ptreg_index); i++) -+ if (br_reg_to_ptreg_index[i].reg == regnum) { -+ *reg = *((unsigned long *) -+ (((void *)ptregs) + -+ br_reg_to_ptreg_index[i]. -+ ptregoff)); -+ break; -+ } -+ break; -+ case IA64_BR0_REGNUM + 1: -+ case IA64_BR0_REGNUM + 2: -+ case IA64_BR0_REGNUM + 3: -+ case IA64_BR0_REGNUM + 4: -+ case IA64_BR0_REGNUM + 5: -+ result = !unw_access_br(info, regnum - IA64_BR0_REGNUM, -+ reg, rw); -+ break; -+ } -+ -+ return result; -+} -+ -+static int kgdb_fr_reg(int regnum, char *inbuffer, struct pt_regs * ptregs, -+ struct unw_frame_info *info, unsigned long *reg, -+ struct ia64_fpreg *freg, int rw) -+{ -+ int result = 1; -+ -+ if (!(regnum >= IA64_FR0_REGNUM && regnum <= (IA64_FR0_REGNUM + 127))) -+ return 0; -+ -+ switch (regnum) { -+ case IA64_FR0_REGNUM + 6: -+ case IA64_FR0_REGNUM + 7: -+ case IA64_FR0_REGNUM + 8: -+ case IA64_FR0_REGNUM + 9: -+ case IA64_FR0_REGNUM + 10: -+ case IA64_FR0_REGNUM + 11: -+ case IA64_FR0_REGNUM + 12: -+ if (rw) { -+ char *ptr = inbuffer; -+ -+ freg->u.bits[0] = *reg; -+ kgdb_hex2long(&ptr, &freg->u.bits[1]); -+ *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))) = -+ *freg; -+ break; -+ } else if (!ptregs) -+ result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM, -+ freg, rw); -+ else -+ *freg = -+ *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))); -+ break; -+ default: -+ if (!rw) -+ result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM, -+ freg, rw); -+ else -+ result = 0; -+ break; -+ } -+ -+ return result; -+} -+ -+static int kgdb_ar_reg(int regnum, struct pt_regs * ptregs, -+ struct unw_frame_info *info, unsigned long *reg, int rw) -+{ -+ int result = 0, i; -+ -+ if (!(regnum >= IA64_AR0_REGNUM && regnum <= IA64_EC_REGNUM)) -+ return 0; -+ -+ if (rw && ptregs) { -+ for (i = 0; i < ARRAY_SIZE(ar_reg_to_ptreg_index); i++) -+ if (ar_reg_to_ptreg_index[i].reg == regnum) { -+ *((unsigned long *) (((void *)ptregs) + -+ ar_reg_to_ptreg_index[i].ptregoff)) = -+ *reg; -+ result = 1; -+ break; -+ } -+ } else if (ptregs) { -+ for (i = 0; i < ARRAY_SIZE(ar_reg_to_ptreg_index); i++) -+ if (ar_reg_to_ptreg_index[i].reg == regnum) { -+ *reg = *((unsigned long *) (((void *)ptregs) + -+ ar_reg_to_ptreg_index[i].ptregoff)); -+ result = 1; -+ break; -+ } -+ } -+ -+ if (result) -+ return result; -+ -+ result = 1; -+ -+ switch (regnum) { -+ case IA64_CSD_REGNUM: -+ result = !unw_access_ar(info, UNW_AR_CSD, reg, rw); -+ break; -+ case IA64_SSD_REGNUM: -+ result = !unw_access_ar(info, UNW_AR_SSD, reg, rw); -+ break; -+ case IA64_UNAT_REGNUM: -+ result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw); -+ break; -+ case IA64_RNAT_REGNUM: -+ result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw); -+ break; -+ case IA64_BSPSTORE_REGNUM: -+ result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw); -+ break; -+ case IA64_PFS_REGNUM: -+ result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw); -+ break; -+ case IA64_LC_REGNUM: -+ result = !unw_access_ar(info, UNW_AR_LC, reg, rw); -+ break; -+ case IA64_EC_REGNUM: -+ result = !unw_access_ar(info, UNW_AR_EC, reg, rw); -+ break; -+ case IA64_FPSR_REGNUM: -+ result = !unw_access_ar(info, UNW_AR_FPSR, reg, rw); -+ break; -+ case IA64_RSC_REGNUM: -+ result = !unw_access_ar(info, UNW_AR_RSC, reg, rw); -+ break; -+ case IA64_CCV_REGNUM: -+ result = !unw_access_ar(info, UNW_AR_CCV, reg, rw); -+ break; -+ default: -+ result = 0; -+ } -+ -+ return result; -+} -+ -+void kgdb_get_reg(char *outbuffer, int regnum, struct unw_frame_info *info, -+ struct pt_regs *ptregs) -+{ -+ unsigned long reg, size = 0, *mem = ® -+ struct ia64_fpreg freg; -+ -+ if (kgdb_gr_reg(regnum, info, ®, 0) || -+ kgdb_gr_ptreg(regnum, ptregs, info, ®, 0) || -+ kgdb_br_reg(regnum, ptregs, info, ®, 0) || -+ kgdb_ar_reg(regnum, ptregs, info, ®, 0)) -+ size = sizeof(reg); -+ else if (kgdb_fr_reg(regnum, NULL, ptregs, info, ®, &freg, 0)) { -+ size = sizeof(freg); -+ mem = (unsigned long *)&freg; -+ } else if (regnum == IA64_IP_REGNUM) { -+ if (!ptregs) { -+ unw_get_ip(info, ®); -+ size = sizeof(reg); -+ } else { -+ reg = ptregs->cr_iip; -+ size = sizeof(reg); -+ } -+ } else if (regnum == IA64_CFM_REGNUM) { -+ if (!ptregs) -+ unw_get_cfm(info, ®); -+ else -+ reg = ptregs->cr_ifs; -+ size = sizeof(reg); -+ } else if (regnum == IA64_PSR_REGNUM) { -+ if (!ptregs && kgdb_usethread) -+ ptregs = (struct pt_regs *) -+ ((unsigned long)kgdb_usethread + -+ IA64_STK_OFFSET) - 1; -+ if (ptregs) -+ reg = ptregs->cr_ipsr; -+ size = sizeof(reg); -+ } else if (regnum == IA64_PR_REGNUM) { -+ if (ptregs) -+ reg = ptregs->pr; -+ else -+ unw_access_pr(info, ®, 0); -+ size = sizeof(reg); -+ } else if (regnum == IA64_BSP_REGNUM) { -+ unw_get_bsp(info, ®); -+ size = sizeof(reg); -+ } -+ -+ if (size) { -+ kgdb_mem2hex((char *) mem, outbuffer, size); -+ outbuffer[size*2] = 0; -+ } -+ else -+ strcpy(outbuffer, "E0"); -+ -+ return; -+} -+ -+void kgdb_put_reg(char *inbuffer, char *outbuffer, int regnum, -+ struct unw_frame_info *info, struct pt_regs *ptregs) -+{ -+ unsigned long reg; -+ struct ia64_fpreg freg; -+ char *ptr = inbuffer; -+ -+ kgdb_hex2long(&ptr, ®); -+ strcpy(outbuffer, "OK"); -+ -+ if (kgdb_gr_reg(regnum, info, ®, 1) || -+ kgdb_gr_ptreg(regnum, ptregs, info, ®, 1) || -+ kgdb_br_reg(regnum, ptregs, info, ®, 1) || -+ kgdb_fr_reg(regnum, inbuffer, ptregs, info, ®, &freg, 1) || -+ kgdb_ar_reg(regnum, ptregs, info, ®, 1)) ; -+ else if (regnum == IA64_IP_REGNUM) -+ ptregs->cr_iip = reg; -+ else if (regnum == IA64_CFM_REGNUM) -+ ptregs->cr_ifs = reg; -+ else if (regnum == IA64_PSR_REGNUM) -+ ptregs->cr_ipsr = reg; -+ else if (regnum == IA64_PR_REGNUM) -+ ptregs->pr = reg; -+ else -+ strcpy(outbuffer, "E01"); -+ return; -+} -+ -+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) -+{ -+} -+ -+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) -+{ -+} -+ -+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs) -+{ -+ -+} -+ -+#define MAX_HW_BREAKPOINT (20) -+long hw_break_total_dbr, hw_break_total_ibr; -+#define HW_BREAKPOINT (hw_break_total_dbr + hw_break_total_ibr) -+#define WATCH_INSTRUCTION 0x0 -+#define WATCH_WRITE 0x1 -+#define WATCH_READ 0x2 -+#define WATCH_ACCESS 0x3 -+ -+#define HWCAP_DBR ((1 << WATCH_WRITE) | (1 << WATCH_READ)) -+#define HWCAP_IBR (1 << WATCH_INSTRUCTION) -+struct hw_breakpoint { -+ unsigned enabled; -+ unsigned long capable; -+ unsigned long type; -+ unsigned long mask; -+ unsigned long addr; -+} *breakinfo; -+ -+static struct hw_breakpoint hwbreaks[MAX_HW_BREAKPOINT]; -+ -+enum instruction_type { A, I, M, F, B, L, X, u }; -+ -+static enum instruction_type bundle_encoding[32][3] = { -+ {M, I, I}, /* 00 */ -+ {M, I, I}, /* 01 */ -+ {M, I, I}, /* 02 */ -+ {M, I, I}, /* 03 */ -+ {M, L, X}, /* 04 */ -+ {M, L, X}, /* 05 */ -+ {u, u, u}, /* 06 */ -+ {u, u, u}, /* 07 */ -+ {M, M, I}, /* 08 */ -+ {M, M, I}, /* 09 */ -+ {M, M, I}, /* 0A */ -+ {M, M, I}, /* 0B */ -+ {M, F, I}, /* 0C */ -+ {M, F, I}, /* 0D */ -+ {M, M, F}, /* 0E */ -+ {M, M, F}, /* 0F */ -+ {M, I, B}, /* 10 */ -+ {M, I, B}, /* 11 */ -+ {M, B, B}, /* 12 */ -+ {M, B, B}, /* 13 */ -+ {u, u, u}, /* 14 */ -+ {u, u, u}, /* 15 */ -+ {B, B, B}, /* 16 */ -+ {B, B, B}, /* 17 */ -+ {M, M, B}, /* 18 */ -+ {M, M, B}, /* 19 */ -+ {u, u, u}, /* 1A */ -+ {u, u, u}, /* 1B */ -+ {M, F, B}, /* 1C */ -+ {M, F, B}, /* 1D */ -+ {u, u, u}, /* 1E */ -+ {u, u, u}, /* 1F */ -+}; -+ -+int kgdb_validate_break_address(unsigned long addr) -+{ -+ int error; -+ char tmp_variable[BREAK_INSTR_SIZE]; -+ error = kgdb_get_mem((char *)(addr & BREAK_INSTR_ALIGN), tmp_variable, -+ BREAK_INSTR_SIZE); -+ return error; -+} -+ -+int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) -+{ -+ extern unsigned long _start[]; -+ unsigned long slot = addr & BREAK_INSTR_ALIGN, bundle_addr; -+ unsigned long template; -+ struct bundle { -+ struct { -+ unsigned long long template:5; -+ unsigned long long slot0:41; -+ unsigned long long slot1_p0:64 - 46; -+ } quad0; -+ struct { -+ unsigned long long slot1_p1:41 - (64 - 46); -+ unsigned long long slot2:41; -+ } quad1; -+ } bundle; -+ int ret; -+ -+ bundle_addr = addr & ~0xFULL; -+ -+ if (bundle_addr == (unsigned long)_start) -+ return 0; -+ -+ ret = kgdb_get_mem((char *)bundle_addr, (char *)&bundle, -+ BREAK_INSTR_SIZE); -+ if (ret < 0) -+ return ret; -+ -+ if (slot > 2) -+ slot = 0; -+ -+ memcpy(saved_instr, &bundle, BREAK_INSTR_SIZE); -+ template = bundle.quad0.template; -+ -+ if (slot == 1 && bundle_encoding[template][1] == L) -+ slot = 2; -+ -+ switch (slot) { -+ case 0: -+ bundle.quad0.slot0 = BREAKNUM; -+ break; -+ case 1: -+ bundle.quad0.slot1_p0 = BREAKNUM; -+ bundle.quad1.slot1_p1 = (BREAKNUM >> (64 - 46)); -+ break; -+ case 2: -+ bundle.quad1.slot2 = BREAKNUM; -+ break; -+ } -+ -+ return kgdb_set_mem((char *)bundle_addr, (char *)&bundle, -+ BREAK_INSTR_SIZE); -+} -+ -+int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle) -+{ -+ extern unsigned long _start[]; -+ -+ addr = addr & BREAK_INSTR_ALIGN; -+ if (addr == (unsigned long)_start) -+ return 0; -+ return kgdb_set_mem((char *)addr, (char *)bundle, BREAK_INSTR_SIZE); -+} -+ -+static int hw_breakpoint_init; -+ -+void do_init_hw_break(void) -+{ -+ s64 status; -+ int i; -+ -+ hw_breakpoint_init = 1; -+ -+#ifdef CONFIG_IA64_HP_SIM -+ hw_break_total_ibr = 8; -+ hw_break_total_dbr = 8; -+ status = 0; -+#else -+ status = ia64_pal_debug_info(&hw_break_total_ibr, &hw_break_total_dbr); -+#endif -+ -+ if (status) { -+ printk(KERN_INFO "do_init_hw_break: pal call failed %d\n", -+ (int)status); -+ return; -+ } -+ -+ if (HW_BREAKPOINT > MAX_HW_BREAKPOINT) { -+ printk(KERN_INFO "do_init_hw_break: %d exceeds max %d\n", -+ (int)HW_BREAKPOINT, (int)MAX_HW_BREAKPOINT); -+ -+ while ((HW_BREAKPOINT > MAX_HW_BREAKPOINT) -+ && hw_break_total_ibr != 1) -+ hw_break_total_ibr--; -+ while (HW_BREAKPOINT > MAX_HW_BREAKPOINT) -+ hw_break_total_dbr--; -+ } -+ -+ breakinfo = hwbreaks; -+ -+ memset(breakinfo, 0, HW_BREAKPOINT * sizeof(struct hw_breakpoint)); -+ -+ for (i = 0; i < hw_break_total_dbr; i++) -+ breakinfo[i].capable = HWCAP_DBR; -+ -+ for (; i < HW_BREAKPOINT; i++) -+ breakinfo[i].capable = HWCAP_IBR; -+ -+ return; -+} -+ -+void kgdb_correct_hw_break(void) -+{ -+ int breakno; -+ -+ if (!breakinfo) -+ return; -+ -+ for (breakno = 0; breakno < HW_BREAKPOINT; breakno++) { -+ if (breakinfo[breakno].enabled) { -+ if (breakinfo[breakno].capable & HWCAP_IBR) { -+ int ibreakno = breakno - hw_break_total_dbr; -+ ia64_set_ibr(ibreakno << 1, -+ breakinfo[breakno].addr); -+ ia64_set_ibr((ibreakno << 1) + 1, -+ (~breakinfo[breakno].mask & -+ ((1UL << 56UL) - 1)) | -+ (1UL << 56UL) | (1UL << 63UL)); -+ } else { -+ ia64_set_dbr(breakno << 1, -+ breakinfo[breakno].addr); -+ ia64_set_dbr((breakno << 1) + 1, -+ (~breakinfo[breakno]. -+ mask & ((1UL << 56UL) - 1)) | -+ (1UL << 56UL) | -+ (breakinfo[breakno].type << 62UL)); -+ } -+ } else { -+ if (breakinfo[breakno].capable & HWCAP_IBR) -+ ia64_set_ibr(((breakno - -+ hw_break_total_dbr) << 1) + 1, -+ 0); -+ else -+ ia64_set_dbr((breakno << 1) + 1, 0); -+ } -+ } -+ -+ return; -+} -+ -+int hardware_breakpoint(unsigned long addr, int length, int type, int action) -+{ -+ int breakno, found, watch; -+ unsigned long mask; -+ extern unsigned long _start[]; -+ -+ if (!hw_breakpoint_init) -+ do_init_hw_break(); -+ -+ if (!breakinfo) -+ return 0; -+ else if (addr == (unsigned long)_start) -+ return 1; -+ -+ if (type == WATCH_ACCESS) -+ mask = HWCAP_DBR; -+ else -+ mask = 1UL << type; -+ -+ for (watch = 0, found = 0, breakno = 0; breakno < HW_BREAKPOINT; -+ breakno++) { -+ if (action) { -+ if (breakinfo[breakno].enabled -+ || !(breakinfo[breakno].capable & mask)) -+ continue; -+ breakinfo[breakno].enabled = 1; -+ breakinfo[breakno].type = type; -+ breakinfo[breakno].mask = length - 1; -+ breakinfo[breakno].addr = addr; -+ watch = breakno; -+ } else if (breakinfo[breakno].enabled && -+ ((length < 0 && breakinfo[breakno].addr == addr) || -+ ((breakinfo[breakno].capable & mask) && -+ (breakinfo[breakno].mask == (length - 1)) && -+ (breakinfo[breakno].addr == addr)))) { -+ breakinfo[breakno].enabled = 0; -+ breakinfo[breakno].type = 0UL; -+ } else -+ continue; -+ found++; -+ if (type != WATCH_ACCESS) -+ break; -+ else if (found == 2) -+ break; -+ else -+ mask = HWCAP_IBR; -+ } -+ -+ if (type == WATCH_ACCESS && found == 1) { -+ breakinfo[watch].enabled = 0; -+ found = 0; -+ } -+ -+ mb(); -+ return found; -+} -+ -+int kgdb_arch_set_hw_breakpoint(unsigned long addr, int len, -+ enum kgdb_bptype type) -+{ -+ return hardware_breakpoint(addr, len, type - '1', 1); -+} -+ -+int kgdb_arch_remove_hw_breakpoint(unsigned long addr, int len, -+ enum kgdb_bptype type) -+{ -+ return hardware_breakpoint(addr, len, type - '1', 0); -+} -+ -+int kgdb_remove_hw_break(unsigned long addr) -+{ -+ return hardware_breakpoint(addr, 8, WATCH_INSTRUCTION, 0); -+ -+} -+ -+void kgdb_remove_all_hw_break(void) -+{ -+ int i; -+ -+ for (i = 0; i < HW_BREAKPOINT; i++) -+ memset(&breakinfo[i], 0, sizeof(struct hw_breakpoint)); -+} -+ -+int kgdb_set_hw_break(unsigned long addr) -+{ -+ return hardware_breakpoint(addr, 8, WATCH_INSTRUCTION, 1); -+} -+ -+void kgdb_disable_hw_debug(struct pt_regs *regs) -+{ -+ unsigned long hw_breakpoint_status; -+ -+ hw_breakpoint_status = ia64_getreg(_IA64_REG_PSR); -+ if (hw_breakpoint_status & IA64_PSR_DB) -+ ia64_setreg(_IA64_REG_PSR_L, -+ hw_breakpoint_status ^ IA64_PSR_DB); -+} -+ -+volatile static struct smp_unw { -+ struct unw_frame_info *unw; -+ struct task_struct *task; -+} smp_unw[NR_CPUS]; -+ -+static int inline kgdb_get_blocked_state(struct task_struct *p, -+ struct unw_frame_info *unw) -+{ -+ unsigned long ip; -+ int count = 0; -+ -+ unw_init_from_blocked_task(unw, p); -+ ip = 0UL; -+ do { -+ if (unw_unwind(unw) < 0) -+ return -1; -+ unw_get_ip(unw, &ip); -+ if (!in_sched_functions(ip)) -+ break; -+ } while (count++ < 16); -+ -+ if (!ip) -+ return -1; -+ else -+ return 0; -+} -+ -+static void inline kgdb_wait(struct pt_regs *regs) -+{ -+ unsigned long hw_breakpoint_status = ia64_getreg(_IA64_REG_PSR); -+ if (hw_breakpoint_status & IA64_PSR_DB) -+ ia64_setreg(_IA64_REG_PSR_L, -+ hw_breakpoint_status ^ IA64_PSR_DB); -+ kgdb_nmihook(smp_processor_id(), regs); -+ if (hw_breakpoint_status & IA64_PSR_DB) -+ ia64_setreg(_IA64_REG_PSR_L, hw_breakpoint_status); -+ -+ return; -+} -+ -+static void inline normalize(struct unw_frame_info *running, -+ struct pt_regs *regs) -+{ -+ unsigned long sp; -+ -+ do { -+ unw_get_sp(running, &sp); -+ if ((sp + 0x10) >= (unsigned long)regs) -+ break; -+ } while (unw_unwind(running) >= 0); -+ -+ return; -+} -+ -+static void kgdb_init_running(struct unw_frame_info *unw, void *data) -+{ -+ struct pt_regs *regs; -+ -+ regs = data; -+ normalize(unw, regs); -+ smp_unw[smp_processor_id()].unw = unw; -+ kgdb_wait(regs); -+} -+ -+void kgdb_wait_ipi(struct pt_regs *regs) -+{ -+ struct unw_frame_info unw; -+ -+ smp_unw[smp_processor_id()].task = current; -+ -+ if (user_mode(regs)) { -+ smp_unw[smp_processor_id()].unw = (struct unw_frame_info *)1; -+ kgdb_wait(regs); -+ } else { -+ if (current->state == TASK_RUNNING) -+ unw_init_running(kgdb_init_running, regs); -+ else { -+ if (kgdb_get_blocked_state(current, &unw)) -+ smp_unw[smp_processor_id()].unw = -+ (struct unw_frame_info *)1; -+ else -+ smp_unw[smp_processor_id()].unw = &unw; -+ kgdb_wait(regs); -+ } -+ } -+ -+ smp_unw[smp_processor_id()].unw = NULL; -+ return; -+} -+ -+void kgdb_roundup_cpus(unsigned long flags) -+{ -+ if (num_online_cpus() > 1) -+ smp_send_nmi_allbutself(); -+} -+ -+static volatile int kgdb_hwbreak_sstep[NR_CPUS]; -+ -+static int kgdb_notify(struct notifier_block *self, unsigned long cmd, -+ void *ptr) -+{ -+ struct die_args *args = ptr; -+ struct pt_regs *regs = args->regs; -+ unsigned long err = args->err; -+ -+ switch (cmd) { -+ default: -+ return NOTIFY_DONE; -+ case DIE_PAGE_FAULT_NO_CONTEXT: -+ if (atomic_read(&debugger_active) && kgdb_may_fault) { -+ kgdb_fault_longjmp(kgdb_fault_jmp_regs); -+ return NOTIFY_STOP; -+ } -+ break; -+ case DIE_BREAK: -+ if (user_mode(regs) || err == 0x80001) -+ return NOTIFY_DONE; -+ break; -+ case DIE_FAULT: -+ if (user_mode(regs)) -+ return NOTIFY_DONE; -+ else if (err == 36 && kgdb_hwbreak_sstep[smp_processor_id()]) { -+ kgdb_hwbreak_sstep[smp_processor_id()] = 0; -+ regs->cr_ipsr &= ~IA64_PSR_SS; -+ return NOTIFY_STOP; -+ } -+ case DIE_MCA_MONARCH_PROCESS: -+ case DIE_INIT_MONARCH_PROCESS: -+ break; -+ } -+ -+ kgdb_handle_exception(args->trapnr, args->signr, args->err, regs); -+ return NOTIFY_STOP; -+} -+ -+static struct notifier_block kgdb_notifier = { -+ .notifier_call = kgdb_notify, -+}; -+ -+int kgdb_arch_init(void) -+{ -+ atomic_notifier_chain_register(&ia64die_chain, &kgdb_notifier); -+ return 0; -+} -+ -+static void do_kgdb_handle_exception(struct unw_frame_info *, void *data); -+ -+struct kgdb_state { -+ int e_vector; -+ int signo; -+ unsigned long err_code; -+ struct pt_regs *regs; -+ struct unw_frame_info *unw; -+ char *inbuf; -+ char *outbuf; -+ int unwind; -+ int ret; -+}; -+ -+static void inline kgdb_pc(struct pt_regs *regs, unsigned long pc) -+{ -+ regs->cr_iip = pc & ~0xf; -+ ia64_psr(regs)->ri = pc & 0x3; -+ return; -+} -+ -+int kgdb_arch_handle_exception(int e_vector, int signo, -+ int err_code, char *remcom_in_buffer, -+ char *remcom_out_buffer, -+ struct pt_regs *linux_regs) -+{ -+ struct kgdb_state info; -+ -+ info.e_vector = e_vector; -+ info.signo = signo; -+ info.err_code = err_code; -+ info.unw = (void *)0; -+ info.inbuf = remcom_in_buffer; -+ info.outbuf = remcom_out_buffer; -+ info.unwind = 0; -+ info.ret = -1; -+ -+ if (remcom_in_buffer[0] == 'c' || remcom_in_buffer[0] == 's') { -+ info.regs = linux_regs; -+ do_kgdb_handle_exception(NULL, &info); -+ } else if (kgdb_usethread == current) { -+ info.regs = linux_regs; -+ info.unwind = 1; -+ unw_init_running(do_kgdb_handle_exception, &info); -+ } else if (kgdb_usethread->state != TASK_RUNNING) { -+ struct unw_frame_info unw_info; -+ -+ if (kgdb_get_blocked_state(kgdb_usethread, &unw_info)) { -+ info.ret = 1; -+ goto bad; -+ } -+ info.regs = NULL; -+ do_kgdb_handle_exception(&unw_info, &info); -+ } else { -+ int i; -+ -+ for (i = 0; i < NR_CPUS; i++) -+ if (smp_unw[i].task == kgdb_usethread && smp_unw[i].unw -+ && smp_unw[i].unw != (struct unw_frame_info *)1) { -+ info.regs = NULL; -+ do_kgdb_handle_exception(smp_unw[i].unw, &info); -+ break; -+ } else { -+ info.ret = 1; -+ goto bad; -+ } -+ } -+ -+ bad: -+ if (info.ret != -1 && remcom_in_buffer[0] == 'p') { -+ unsigned long bad = 0xbad4badbadbadbadUL; -+ -+ printk("kgdb_arch_handle_exception: p packet bad (%s)\n", -+ remcom_in_buffer); -+ kgdb_mem2hex((char *)&bad, remcom_out_buffer, sizeof(bad)); -+ remcom_out_buffer[sizeof(bad) * 2] = 0; -+ info.ret = -1; -+ } -+ return info.ret; -+} -+ -+/* -+ * This is done because I evidently made an incorrect 'p' encoding -+ * when my patch for gdb was committed. It was later corrected. This -+ * check supports both my wrong encoding of the register number and -+ * the correct encoding. Eventually this should be eliminated and -+ * kgdb_hex2long should be demarshalling the regnum. -+ */ -+static inline int check_packet(unsigned int regnum, char *packet) -+{ -+ static int check_done, swap; -+ unsigned long reglong; -+ -+ if (likely(check_done)) { -+ if (swap) { -+ kgdb_hex2long(&packet, ®long); -+ regnum = (int) reglong; -+ } -+ -+ } else { -+ if (regnum > NUM_REGS) { -+ kgdb_hex2long(&packet, ®long); -+ regnum = (int) reglong; -+ swap = 1; -+ } -+ check_done = 1; -+ } -+ return regnum; -+} -+ -+static void do_kgdb_handle_exception(struct unw_frame_info *unw_info, -+ void *data) -+{ -+ long addr; -+ char *ptr; -+ unsigned long newPC; -+ int e_vector, signo; -+ unsigned long err_code; -+ struct pt_regs *linux_regs; -+ struct kgdb_state *info; -+ char *remcom_in_buffer, *remcom_out_buffer; -+ -+ info = data; -+ info->unw = unw_info; -+ e_vector = info->e_vector; -+ signo = info->signo; -+ err_code = info->err_code; -+ remcom_in_buffer = info->inbuf; -+ remcom_out_buffer = info->outbuf; -+ linux_regs = info->regs; -+ -+ if (info->unwind) -+ normalize(unw_info, linux_regs); -+ -+ switch (remcom_in_buffer[0]) { -+ case 'p': -+ { -+ unsigned int regnum; -+ -+ kgdb_hex2mem(&remcom_in_buffer[1], (char *)®num, -+ sizeof(regnum)); -+ regnum = check_packet(regnum, &remcom_in_buffer[1]); -+ if (regnum >= NUM_REGS) { -+ remcom_out_buffer[0] = 'E'; -+ remcom_out_buffer[1] = 0; -+ } else -+ kgdb_get_reg(remcom_out_buffer, regnum, -+ unw_info, linux_regs); -+ break; -+ } -+ case 'P': -+ { -+ unsigned int regno; -+ long v; -+ char *ptr; -+ -+ ptr = &remcom_in_buffer[1]; -+ if ((!kgdb_usethread || kgdb_usethread == current) && -+ kgdb_hex2long(&ptr, &v) && -+ *ptr++ == '=' && (v >= 0)) { -+ regno = (unsigned int)v; -+ regno = (regno >= NUM_REGS ? 0 : regno); -+ kgdb_put_reg(ptr, remcom_out_buffer, regno, -+ unw_info, linux_regs); -+ } else -+ strcpy(remcom_out_buffer, "E01"); -+ break; -+ } -+ case 'c': -+ case 's': -+ if (e_vector == TRAP_BRKPT && err_code == KGDBBREAKNUM) { -+ if (ia64_psr(linux_regs)->ri < 2) -+ kgdb_pc(linux_regs, linux_regs->cr_iip + -+ ia64_psr(linux_regs)->ri + 1); -+ else -+ kgdb_pc(linux_regs, linux_regs->cr_iip + 16); -+ } -+ -+ /* try to read optional parameter, pc unchanged if no parm */ -+ ptr = &remcom_in_buffer[1]; -+ if (kgdb_hex2long(&ptr, &addr)) { -+ linux_regs->cr_iip = addr; -+ } -+ newPC = linux_regs->cr_iip; -+ -+ /* clear the trace bit */ -+ linux_regs->cr_ipsr &= ~IA64_PSR_SS; -+ -+ atomic_set(&cpu_doing_single_step, -1); -+ -+ /* set the trace bit if we're stepping or took a hardware break */ -+ if (remcom_in_buffer[0] == 's' || e_vector == TRAP_HWBKPT) { -+ linux_regs->cr_ipsr |= IA64_PSR_SS; -+ debugger_step = 1; -+ if (kgdb_contthread) -+ atomic_set(&cpu_doing_single_step, -+ smp_processor_id()); -+ } -+ -+ kgdb_correct_hw_break(); -+ -+ /* if not hardware breakpoint, then reenable them */ -+ if (e_vector != TRAP_HWBKPT) -+ linux_regs->cr_ipsr |= IA64_PSR_DB; -+ else { -+ kgdb_hwbreak_sstep[smp_processor_id()] = 1; -+ linux_regs->cr_ipsr &= ~IA64_PSR_DB; -+ } -+ -+ info->ret = 0; -+ break; -+ default: -+ break; -+ } -+ -+ return; -+} -+ -+struct kgdb_arch arch_kgdb_ops = { -+ .set_hw_breakpoint = kgdb_arch_set_hw_breakpoint, -+ .remove_hw_breakpoint = kgdb_arch_remove_hw_breakpoint, -+ .gdb_bpt_instr = {0xcc}, -+ .flags = KGDB_HW_BREAKPOINT, -+}; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ia64/kernel/process.c linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/process.c ---- linux-2.6.18-53.1.14/arch/ia64/kernel/process.c 2008-03-06 05:55:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/process.c 2008-06-10 15:39:39.000000000 +0400 -@@ -463,6 +463,9 @@ copy_thread (int nr, unsigned long clone - */ - child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) - & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); -+#ifdef CONFIG_KGDB -+ child_ptregs->cr_ipsr |= IA64_PSR_DB; -+#endif - - /* - * NOTE: The calling convention considers all floating point -@@ -691,6 +694,9 @@ kernel_thread (int (*fn)(void *), void * - regs.pt.r11 = (unsigned long) arg; /* 2nd argument */ - /* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't read. */ - regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN; -+#ifdef CONFIG_KGDB -+ regs.pt.cr_ipsr |= IA64_PSR_DB; -+#endif - regs.pt.cr_ifs = 1UL << 63; /* mark as valid, empty frame */ - regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR); - regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ia64/kernel/smp.c linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/smp.c ---- linux-2.6.18-53.1.14/arch/ia64/kernel/smp.c 2008-03-06 05:54:27.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/smp.c 2008-06-10 15:38:32.000000000 +0400 -@@ -48,6 +48,7 @@ - #include - #include - #include -+#include - - /* - * Structure and data for smp_call_function(). This is designed to minimise static memory -@@ -68,6 +69,9 @@ static volatile struct call_data_struct - #define IPI_CALL_FUNC 0 - #define IPI_CPU_STOP 1 - #define IPI_KDUMP_CPU_STOP 3 -+#ifdef CONFIG_KGDB -+#define IPI_KGDB_INTERRUPT 2 -+#endif - - /* This needs to be cacheline aligned because it is written to by *other* CPUs. */ - static DEFINE_PER_CPU(u64, ipi_operation) ____cacheline_aligned; -@@ -185,6 +189,11 @@ handle_IPI (int irq, void *dev_id, struc - case IPI_CPU_STOP: - stop_this_cpu(); - break; -+#ifdef CONFIG_KGDB -+ case IPI_KGDB_INTERRUPT: -+ kgdb_wait_ipi(regs); -+ break; -+#endif - #ifdef CONFIG_CRASH_DUMP - case IPI_KDUMP_CPU_STOP: - unw_init_running(kdump_cpu_freeze, NULL); -@@ -359,6 +368,14 @@ smp_call_function_single (int cpuid, voi - } - EXPORT_SYMBOL(smp_call_function_single); - -+#ifdef CONFIG_KGDB -+void -+smp_send_nmi_allbutself(void) -+{ -+ send_IPI_allbutself(IPI_KGDB_INTERRUPT); -+} -+#endif -+ - /* - * this function sends a 'generic call function' IPI to all other CPUs - * in the system. -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ia64/kernel/traps.c linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/traps.c ---- linux-2.6.18-53.1.14/arch/ia64/kernel/traps.c 2008-03-06 05:54:44.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/traps.c 2008-06-10 15:38:32.000000000 +0400 -@@ -200,8 +200,12 @@ __kprobes ia64_bad_break (unsigned long - break; - - default: -- if (break_num < 0x40000 || break_num > 0x100000) -+ if (break_num < 0x40000 || break_num > 0x100000) { -+ if (notify_die(DIE_BREAK, "bad break", regs, -+ break_num, TRAP_BRKPT, SIGTRAP) == NOTIFY_STOP) -+ return; - die_if_kernel("Bad break", regs, break_num); -+ } - - if (break_num < 0x80000) { - sig = SIGILL; code = __ILL_BREAK; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ia64/kernel/unwind.c linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/unwind.c ---- linux-2.6.18-53.1.14/arch/ia64/kernel/unwind.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ia64/kernel/unwind.c 2008-06-10 15:39:39.000000000 +0400 -@@ -72,10 +72,68 @@ - # define STAT(x...) - #endif - -+#ifdef CONFIG_KGDB -+#define KGDB_EARLY_SIZE 100 -+static struct unw_reg_state __initdata kgdb_reg_state[KGDB_EARLY_SIZE]; -+static struct unw_labeled_state __initdata kgdb_labeled_state[KGDB_EARLY_SIZE]; -+void __initdata *kgdb_reg_state_free, __initdata *kgdb_labeled_state_free; -+ -+static void __init -+kgdb_malloc_init(void) -+{ -+ int i; -+ -+ kgdb_reg_state_free = kgdb_reg_state; -+ for (i = 1; i < KGDB_EARLY_SIZE; i++) { -+ *((unsigned long *) &kgdb_reg_state[i]) = (unsigned long) kgdb_reg_state_free; -+ kgdb_reg_state_free = &kgdb_reg_state[i]; -+ } -+ -+ kgdb_labeled_state_free = kgdb_labeled_state; -+ for (i = 1; i < KGDB_EARLY_SIZE; i++) { -+ *((unsigned long *) &kgdb_labeled_state[i]) = -+ (unsigned long) kgdb_labeled_state_free; -+ kgdb_labeled_state_free = &kgdb_labeled_state[i]; -+ } -+ -+} -+ -+static void * __init -+kgdb_malloc(void **mem) -+{ -+ void *p; -+ -+ p = *mem; -+ *mem = *((void **) p); -+ return p; -+} -+ -+static void __init -+kgdb_free(void **mem, void *p) -+{ -+ *((void **)p) = *mem; -+ *mem = p; -+} -+ -+#define alloc_reg_state() (!malloc_sizes[0].cs_cachep ? \ -+ kgdb_malloc(&kgdb_reg_state_free) : \ -+ kmalloc(sizeof(struct unw_reg_state), GFP_ATOMIC)) -+#define free_reg_state(usr) (!malloc_sizes[0].cs_cachep ? \ -+ kgdb_free(&kgdb_reg_state_free, usr) : \ -+ kfree(usr)) -+#define alloc_labeled_state() (!malloc_sizes[0].cs_cachep ? \ -+ kgdb_malloc(&kgdb_labeled_state_free) : \ -+ kmalloc(sizeof(struct unw_labeled_state), GFP_ATOMIC)) -+#define free_labeled_state(usr) (!malloc_sizes[0].cs_cachep ? \ -+ kgdb_free(&kgdb_labeled_state_free, usr) : \ -+ kfree(usr)) -+ -+#else - #define alloc_reg_state() kmalloc(sizeof(struct unw_reg_state), GFP_ATOMIC) - #define free_reg_state(usr) kfree(usr) - #define alloc_labeled_state() kmalloc(sizeof(struct unw_labeled_state), GFP_ATOMIC) - #define free_labeled_state(usr) kfree(usr) -+#endif - - typedef unsigned long unw_word; - typedef unsigned char unw_hash_index_t; -@@ -238,6 +296,24 @@ static struct { - #endif - }; - -+#ifdef CONFIG_KGDB -+/* -+ * This makes it safe to call breakpoint() very early -+ * in setup_arch providing: -+ * 1) breakpoint isn't called between lines in cpu_init -+ * where init_mm.mm_count is incremented and ia64_mmu_init -+ * is called. Otherwise the test below is invalid. -+ * 2) the memory examined doesn't result in tlbmiss. -+ */ -+static unsigned long inline kgdb_unimpl_va_mask(void) -+{ -+ if (atomic_read(&init_mm.mm_count) > 1) -+ return local_cpu_data->unimpl_va_mask; -+ else -+ return 0UL; -+} -+#endif -+ - static inline int - read_only (void *addr) - { -@@ -1786,7 +1862,11 @@ run_script (struct unw_script *script, s - - case UNW_INSN_LOAD: - #ifdef UNW_DEBUG -+#ifdef CONFIG_KGDB -+ if ((s[val] & (kgdb_unimpl_va_mask() | 0x7)) != 0 -+#else - if ((s[val] & (local_cpu_data->unimpl_va_mask | 0x7)) != 0 -+#endif - || s[val] < TASK_SIZE) - { - UNW_DPRINT(0, "unwind.%s: rejecting bad psp=0x%lx\n", -@@ -1821,7 +1901,11 @@ find_save_locs (struct unw_frame_info *i - struct unw_script *scr; - unsigned long flags = 0; - -+#ifdef CONFIG_KGDB -+ if ((info->ip & (kgdb_unimpl_va_mask() | 0xf)) || info->ip < TASK_SIZE) { -+#else - if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf)) || info->ip < TASK_SIZE) { -+#endif - /* don't let obviously bad addresses pollute the cache */ - /* FIXME: should really be level 0 but it occurs too often. KAO */ - UNW_DPRINT(1, "unwind.%s: rejecting bad ip=0x%lx\n", __FUNCTION__, info->ip); -@@ -2249,6 +2333,9 @@ unw_init (void) - - init_unwind_table(&unw.kernel_table, "kernel", KERNEL_START, (unsigned long) __gp, - __start_unwind, __end_unwind); -+#ifdef CONFIG_KGDB -+ kgdb_malloc_init(); -+#endif - } - - /* -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ia64/mm/extable.c linux-2.6.18-53.1.14.kgdb/arch/ia64/mm/extable.c ---- linux-2.6.18-53.1.14/arch/ia64/mm/extable.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ia64/mm/extable.c 2008-06-10 15:38:32.000000000 +0400 -@@ -6,6 +6,7 @@ - */ - - #include -+#include - - #include - #include -@@ -73,6 +74,11 @@ search_extable (const struct exception_t - else - last = mid - 1; - } -+#ifdef CONFIG_KGDB -+ if (atomic_read(&debugger_active) && kgdb_may_fault) -+ kgdb_fault_longjmp(kgdb_fault_jmp_regs); -+ /* Not reached. */ -+#endif - return NULL; - } - -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ia64/mm/fault.c linux-2.6.18-53.1.14.kgdb/arch/ia64/mm/fault.c ---- linux-2.6.18-53.1.14/arch/ia64/mm/fault.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ia64/mm/fault.c 2008-06-10 15:38:32.000000000 +0400 -@@ -266,6 +266,10 @@ ia64_do_page_fault (unsigned long addres - */ - bust_spinlocks(1); - -+ if (notify_die(DIE_PAGE_FAULT_NO_CONTEXT, "no context", regs, -+ isr, 14, SIGSEGV) == NOTIFY_STOP) -+ return; -+ - if (address < PAGE_SIZE) - printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference (address %016lx)\n", address); - else -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/Kconfig.debug linux-2.6.18-53.1.14.kgdb/arch/mips/Kconfig.debug ---- linux-2.6.18-53.1.14/arch/mips/Kconfig.debug 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/Kconfig.debug 2008-06-10 15:38:24.000000000 +0400 -@@ -37,25 +37,6 @@ config DEBUG_STACK_USAGE - - This option will slow down process creation somewhat. - --config KGDB -- bool "Remote GDB kernel debugging" -- depends on DEBUG_KERNEL -- select DEBUG_INFO -- help -- If you say Y here, it will be possible to remotely debug the MIPS -- kernel using gdb. This enlarges your kernel image disk size by -- several megabytes and requires a machine with more than 16 MB, -- better 32 MB RAM to avoid excessive linking time. This is only -- useful for kernel hackers. If unsure, say N. -- --config GDB_CONSOLE -- bool "Console output to GDB" -- depends on KGDB -- help -- If you are using GDB for remote debugging over a serial port and -- would like kernel messages to be formatted into GDB $O packets so -- that GDB prints them as program output, say 'Y'. -- - config SB1XXX_CORELIS - bool "Corelis Debugger" - depends on SIBYTE_SB1xxx_SOC -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/kernel/Makefile linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/Makefile ---- linux-2.6.18-53.1.14/arch/mips/kernel/Makefile 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/Makefile 2008-06-10 15:38:24.000000000 +0400 -@@ -59,7 +59,8 @@ obj-$(CONFIG_MIPS32_COMPAT) += linux32.o - obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o - obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o ptrace32.o - --obj-$(CONFIG_KGDB) += gdb-low.o gdb-stub.o -+obj-$(CONFIG_KGDB) += kgdb_handler.o kgdb.o kgdb-jmp.o \ -+ kgdb-setjmp.o - obj-$(CONFIG_PROC_FS) += proc.o - - obj-$(CONFIG_64BIT) += cpu-bugs64.o -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/kernel/gdb-low.S linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/gdb-low.S ---- linux-2.6.18-53.1.14/arch/mips/kernel/gdb-low.S 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/gdb-low.S 1970-01-01 03:00:00.000000000 +0300 -@@ -1,394 +0,0 @@ --/* -- * gdb-low.S contains the low-level trap handler for the GDB stub. -- * -- * Copyright (C) 1995 Andreas Busse -- */ --#include -- --#include --#include --#include --#include --#include --#include --#include -- --#ifdef CONFIG_32BIT --#define DMFC0 mfc0 --#define DMTC0 mtc0 --#define LDC1 lwc1 --#define SDC1 lwc1 --#endif --#ifdef CONFIG_64BIT --#define DMFC0 dmfc0 --#define DMTC0 dmtc0 --#define LDC1 ldc1 --#define SDC1 ldc1 --#endif -- --/* -- * [jsun] We reserves about 2x GDB_FR_SIZE in stack. The lower (addressed) -- * part is used to store registers and passed to exception handler. -- * The upper part is reserved for "call func" feature where gdb client -- * saves some of the regs, setups call frame and passes args. -- * -- * A trace shows about 200 bytes are used to store about half of all regs. -- * The rest should be big enough for frame setup and passing args. -- */ -- --/* -- * The low level trap handler -- */ -- .align 5 -- NESTED(trap_low, GDB_FR_SIZE, sp) -- .set noat -- .set noreorder -- -- mfc0 k0, CP0_STATUS -- sll k0, 3 /* extract cu0 bit */ -- bltz k0, 1f -- move k1, sp -- -- /* -- * Called from user mode, go somewhere else. -- */ -- mfc0 k0, CP0_CAUSE -- andi k0, k0, 0x7c --#ifdef CONFIG_64BIT -- dsll k0, k0, 1 --#endif -- PTR_L k1, saved_vectors(k0) -- jr k1 -- nop --1: -- move k0, sp -- PTR_SUBU sp, k1, GDB_FR_SIZE*2 # see comment above -- LONG_S k0, GDB_FR_REG29(sp) -- LONG_S $2, GDB_FR_REG2(sp) -- --/* -- * First save the CP0 and special registers -- */ -- -- mfc0 v0, CP0_STATUS -- LONG_S v0, GDB_FR_STATUS(sp) -- mfc0 v0, CP0_CAUSE -- LONG_S v0, GDB_FR_CAUSE(sp) -- DMFC0 v0, CP0_EPC -- LONG_S v0, GDB_FR_EPC(sp) -- DMFC0 v0, CP0_BADVADDR -- LONG_S v0, GDB_FR_BADVADDR(sp) -- mfhi v0 -- LONG_S v0, GDB_FR_HI(sp) -- mflo v0 -- LONG_S v0, GDB_FR_LO(sp) -- --/* -- * Now the integer registers -- */ -- -- LONG_S zero, GDB_FR_REG0(sp) /* I know... */ -- LONG_S $1, GDB_FR_REG1(sp) -- /* v0 already saved */ -- LONG_S $3, GDB_FR_REG3(sp) -- LONG_S $4, GDB_FR_REG4(sp) -- LONG_S $5, GDB_FR_REG5(sp) -- LONG_S $6, GDB_FR_REG6(sp) -- LONG_S $7, GDB_FR_REG7(sp) -- LONG_S $8, GDB_FR_REG8(sp) -- LONG_S $9, GDB_FR_REG9(sp) -- LONG_S $10, GDB_FR_REG10(sp) -- LONG_S $11, GDB_FR_REG11(sp) -- LONG_S $12, GDB_FR_REG12(sp) -- LONG_S $13, GDB_FR_REG13(sp) -- LONG_S $14, GDB_FR_REG14(sp) -- LONG_S $15, GDB_FR_REG15(sp) -- LONG_S $16, GDB_FR_REG16(sp) -- LONG_S $17, GDB_FR_REG17(sp) -- LONG_S $18, GDB_FR_REG18(sp) -- LONG_S $19, GDB_FR_REG19(sp) -- LONG_S $20, GDB_FR_REG20(sp) -- LONG_S $21, GDB_FR_REG21(sp) -- LONG_S $22, GDB_FR_REG22(sp) -- LONG_S $23, GDB_FR_REG23(sp) -- LONG_S $24, GDB_FR_REG24(sp) -- LONG_S $25, GDB_FR_REG25(sp) -- LONG_S $26, GDB_FR_REG26(sp) -- LONG_S $27, GDB_FR_REG27(sp) -- LONG_S $28, GDB_FR_REG28(sp) -- /* sp already saved */ -- LONG_S $30, GDB_FR_REG30(sp) -- LONG_S $31, GDB_FR_REG31(sp) -- -- CLI /* disable interrupts */ -- TRACE_IRQS_OFF -- --/* -- * Followed by the floating point registers -- */ -- mfc0 v0, CP0_STATUS /* FPU enabled? */ -- srl v0, v0, 16 -- andi v0, v0, (ST0_CU1 >> 16) -- -- beqz v0,2f /* disabled, skip */ -- nop -- -- SDC1 $0, GDB_FR_FPR0(sp) -- SDC1 $1, GDB_FR_FPR1(sp) -- SDC1 $2, GDB_FR_FPR2(sp) -- SDC1 $3, GDB_FR_FPR3(sp) -- SDC1 $4, GDB_FR_FPR4(sp) -- SDC1 $5, GDB_FR_FPR5(sp) -- SDC1 $6, GDB_FR_FPR6(sp) -- SDC1 $7, GDB_FR_FPR7(sp) -- SDC1 $8, GDB_FR_FPR8(sp) -- SDC1 $9, GDB_FR_FPR9(sp) -- SDC1 $10, GDB_FR_FPR10(sp) -- SDC1 $11, GDB_FR_FPR11(sp) -- SDC1 $12, GDB_FR_FPR12(sp) -- SDC1 $13, GDB_FR_FPR13(sp) -- SDC1 $14, GDB_FR_FPR14(sp) -- SDC1 $15, GDB_FR_FPR15(sp) -- SDC1 $16, GDB_FR_FPR16(sp) -- SDC1 $17, GDB_FR_FPR17(sp) -- SDC1 $18, GDB_FR_FPR18(sp) -- SDC1 $19, GDB_FR_FPR19(sp) -- SDC1 $20, GDB_FR_FPR20(sp) -- SDC1 $21, GDB_FR_FPR21(sp) -- SDC1 $22, GDB_FR_FPR22(sp) -- SDC1 $23, GDB_FR_FPR23(sp) -- SDC1 $24, GDB_FR_FPR24(sp) -- SDC1 $25, GDB_FR_FPR25(sp) -- SDC1 $26, GDB_FR_FPR26(sp) -- SDC1 $27, GDB_FR_FPR27(sp) -- SDC1 $28, GDB_FR_FPR28(sp) -- SDC1 $29, GDB_FR_FPR29(sp) -- SDC1 $30, GDB_FR_FPR30(sp) -- SDC1 $31, GDB_FR_FPR31(sp) -- --/* -- * FPU control registers -- */ -- -- cfc1 v0, CP1_STATUS -- LONG_S v0, GDB_FR_FSR(sp) -- cfc1 v0, CP1_REVISION -- LONG_S v0, GDB_FR_FIR(sp) -- --/* -- * Current stack frame ptr -- */ -- --2: -- LONG_S sp, GDB_FR_FRP(sp) -- --/* -- * CP0 registers (R4000/R4400 unused registers skipped) -- */ -- -- mfc0 v0, CP0_INDEX -- LONG_S v0, GDB_FR_CP0_INDEX(sp) -- mfc0 v0, CP0_RANDOM -- LONG_S v0, GDB_FR_CP0_RANDOM(sp) -- DMFC0 v0, CP0_ENTRYLO0 -- LONG_S v0, GDB_FR_CP0_ENTRYLO0(sp) -- DMFC0 v0, CP0_ENTRYLO1 -- LONG_S v0, GDB_FR_CP0_ENTRYLO1(sp) -- DMFC0 v0, CP0_CONTEXT -- LONG_S v0, GDB_FR_CP0_CONTEXT(sp) -- mfc0 v0, CP0_PAGEMASK -- LONG_S v0, GDB_FR_CP0_PAGEMASK(sp) -- mfc0 v0, CP0_WIRED -- LONG_S v0, GDB_FR_CP0_WIRED(sp) -- DMFC0 v0, CP0_ENTRYHI -- LONG_S v0, GDB_FR_CP0_ENTRYHI(sp) -- mfc0 v0, CP0_PRID -- LONG_S v0, GDB_FR_CP0_PRID(sp) -- -- .set at -- --/* -- * Continue with the higher level handler -- */ -- -- move a0,sp -- -- jal handle_exception -- nop -- --/* -- * Restore all writable registers, in reverse order -- */ -- -- .set noat -- -- LONG_L v0, GDB_FR_CP0_ENTRYHI(sp) -- LONG_L v1, GDB_FR_CP0_WIRED(sp) -- DMTC0 v0, CP0_ENTRYHI -- mtc0 v1, CP0_WIRED -- LONG_L v0, GDB_FR_CP0_PAGEMASK(sp) -- LONG_L v1, GDB_FR_CP0_ENTRYLO1(sp) -- mtc0 v0, CP0_PAGEMASK -- DMTC0 v1, CP0_ENTRYLO1 -- LONG_L v0, GDB_FR_CP0_ENTRYLO0(sp) -- LONG_L v1, GDB_FR_CP0_INDEX(sp) -- DMTC0 v0, CP0_ENTRYLO0 -- LONG_L v0, GDB_FR_CP0_CONTEXT(sp) -- mtc0 v1, CP0_INDEX -- DMTC0 v0, CP0_CONTEXT -- -- --/* -- * Next, the floating point registers -- */ -- mfc0 v0, CP0_STATUS /* check if the FPU is enabled */ -- srl v0, v0, 16 -- andi v0, v0, (ST0_CU1 >> 16) -- -- beqz v0, 3f /* disabled, skip */ -- nop -- -- LDC1 $31, GDB_FR_FPR31(sp) -- LDC1 $30, GDB_FR_FPR30(sp) -- LDC1 $29, GDB_FR_FPR29(sp) -- LDC1 $28, GDB_FR_FPR28(sp) -- LDC1 $27, GDB_FR_FPR27(sp) -- LDC1 $26, GDB_FR_FPR26(sp) -- LDC1 $25, GDB_FR_FPR25(sp) -- LDC1 $24, GDB_FR_FPR24(sp) -- LDC1 $23, GDB_FR_FPR23(sp) -- LDC1 $22, GDB_FR_FPR22(sp) -- LDC1 $21, GDB_FR_FPR21(sp) -- LDC1 $20, GDB_FR_FPR20(sp) -- LDC1 $19, GDB_FR_FPR19(sp) -- LDC1 $18, GDB_FR_FPR18(sp) -- LDC1 $17, GDB_FR_FPR17(sp) -- LDC1 $16, GDB_FR_FPR16(sp) -- LDC1 $15, GDB_FR_FPR15(sp) -- LDC1 $14, GDB_FR_FPR14(sp) -- LDC1 $13, GDB_FR_FPR13(sp) -- LDC1 $12, GDB_FR_FPR12(sp) -- LDC1 $11, GDB_FR_FPR11(sp) -- LDC1 $10, GDB_FR_FPR10(sp) -- LDC1 $9, GDB_FR_FPR9(sp) -- LDC1 $8, GDB_FR_FPR8(sp) -- LDC1 $7, GDB_FR_FPR7(sp) -- LDC1 $6, GDB_FR_FPR6(sp) -- LDC1 $5, GDB_FR_FPR5(sp) -- LDC1 $4, GDB_FR_FPR4(sp) -- LDC1 $3, GDB_FR_FPR3(sp) -- LDC1 $2, GDB_FR_FPR2(sp) -- LDC1 $1, GDB_FR_FPR1(sp) -- LDC1 $0, GDB_FR_FPR0(sp) -- --/* -- * Now the CP0 and integer registers -- */ -- --3: --#ifdef CONFIG_MIPS_MT_SMTC -- /* Read-modify write of Status must be atomic */ -- mfc0 t2, CP0_TCSTATUS -- ori t1, t2, TCSTATUS_IXMT -- mtc0 t1, CP0_TCSTATUS -- andi t2, t2, TCSTATUS_IXMT -- _ehb -- DMT 9 # dmt t1 -- jal mips_ihb -- nop --#endif /* CONFIG_MIPS_MT_SMTC */ -- mfc0 t0, CP0_STATUS -- ori t0, 0x1f -- xori t0, 0x1f -- mtc0 t0, CP0_STATUS --#ifdef CONFIG_MIPS_MT_SMTC -- andi t1, t1, VPECONTROL_TE -- beqz t1, 9f -- nop -- EMT # emt --9: -- mfc0 t1, CP0_TCSTATUS -- xori t1, t1, TCSTATUS_IXMT -- or t1, t1, t2 -- mtc0 t1, CP0_TCSTATUS -- _ehb --#endif /* CONFIG_MIPS_MT_SMTC */ -- LONG_L v0, GDB_FR_STATUS(sp) -- LONG_L v1, GDB_FR_EPC(sp) -- mtc0 v0, CP0_STATUS -- DMTC0 v1, CP0_EPC -- LONG_L v0, GDB_FR_HI(sp) -- LONG_L v1, GDB_FR_LO(sp) -- mthi v0 -- mtlo v1 -- LONG_L $31, GDB_FR_REG31(sp) -- LONG_L $30, GDB_FR_REG30(sp) -- LONG_L $28, GDB_FR_REG28(sp) -- LONG_L $27, GDB_FR_REG27(sp) -- LONG_L $26, GDB_FR_REG26(sp) -- LONG_L $25, GDB_FR_REG25(sp) -- LONG_L $24, GDB_FR_REG24(sp) -- LONG_L $23, GDB_FR_REG23(sp) -- LONG_L $22, GDB_FR_REG22(sp) -- LONG_L $21, GDB_FR_REG21(sp) -- LONG_L $20, GDB_FR_REG20(sp) -- LONG_L $19, GDB_FR_REG19(sp) -- LONG_L $18, GDB_FR_REG18(sp) -- LONG_L $17, GDB_FR_REG17(sp) -- LONG_L $16, GDB_FR_REG16(sp) -- LONG_L $15, GDB_FR_REG15(sp) -- LONG_L $14, GDB_FR_REG14(sp) -- LONG_L $13, GDB_FR_REG13(sp) -- LONG_L $12, GDB_FR_REG12(sp) -- LONG_L $11, GDB_FR_REG11(sp) -- LONG_L $10, GDB_FR_REG10(sp) -- LONG_L $9, GDB_FR_REG9(sp) -- LONG_L $8, GDB_FR_REG8(sp) -- LONG_L $7, GDB_FR_REG7(sp) -- LONG_L $6, GDB_FR_REG6(sp) -- LONG_L $5, GDB_FR_REG5(sp) -- LONG_L $4, GDB_FR_REG4(sp) -- LONG_L $3, GDB_FR_REG3(sp) -- LONG_L $2, GDB_FR_REG2(sp) -- LONG_L $1, GDB_FR_REG1(sp) --#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) -- LONG_L k0, GDB_FR_EPC(sp) -- LONG_L $29, GDB_FR_REG29(sp) /* Deallocate stack */ -- jr k0 -- rfe --#else -- LONG_L sp, GDB_FR_REG29(sp) /* Deallocate stack */ -- -- .set mips3 -- eret -- .set mips0 --#endif -- .set at -- .set reorder -- END(trap_low) -- --LEAF(kgdb_read_byte) --4: lb t0, (a0) -- sb t0, (a1) -- li v0, 0 -- jr ra -- .section __ex_table,"a" -- PTR 4b, kgdbfault -- .previous -- END(kgdb_read_byte) -- --LEAF(kgdb_write_byte) --5: sb a0, (a1) -- li v0, 0 -- jr ra -- .section __ex_table,"a" -- PTR 5b, kgdbfault -- .previous -- END(kgdb_write_byte) -- -- .type kgdbfault@function -- .ent kgdbfault -- --kgdbfault: li v0, -EFAULT -- jr ra -- .end kgdbfault -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/kernel/gdb-stub.c linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/gdb-stub.c ---- linux-2.6.18-53.1.14/arch/mips/kernel/gdb-stub.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/gdb-stub.c 1970-01-01 03:00:00.000000000 +0300 -@@ -1,1154 +0,0 @@ --/* -- * arch/mips/kernel/gdb-stub.c -- * -- * Originally written by Glenn Engel, Lake Stevens Instrument Division -- * -- * Contributed by HP Systems -- * -- * Modified for SPARC by Stu Grossman, Cygnus Support. -- * -- * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse -- * Send complaints, suggestions etc. to -- * -- * Copyright (C) 1995 Andreas Busse -- * -- * Copyright (C) 2003 MontaVista Software Inc. -- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net -- */ -- --/* -- * 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 BREAK instruction. -- * -- * -- * 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 -- * -- * $#. -- * -- * where -- * :: -- * :: < two hex digits computed as modulo 256 sum of > -- * -- * 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 -- * -- * -- * ============== -- * MORE EXAMPLES: -- * ============== -- * -- * For reference -- the following are the steps that one -- * company took (RidgeRun Inc) to get remote gdb debugging -- * going. In this scenario the host machine was a PC and the -- * target platform was a Galileo EVB64120A MIPS evaluation -- * board. -- * -- * Step 1: -- * First download gdb-5.0.tar.gz from the internet. -- * and then build/install the package. -- * -- * Example: -- * $ tar zxf gdb-5.0.tar.gz -- * $ cd gdb-5.0 -- * $ ./configure --target=mips-linux-elf -- * $ make -- * $ install -- * $ which mips-linux-elf-gdb -- * /usr/local/bin/mips-linux-elf-gdb -- * -- * Step 2: -- * Configure linux for remote debugging and build it. -- * -- * Example: -- * $ cd ~/linux -- * $ make menuconfig -- * $ make -- * -- * Step 3: -- * Download the kernel to the remote target and start -- * the kernel running. It will promptly halt and wait -- * for the host gdb session to connect. It does this -- * since the "Kernel Hacking" option has defined -- * CONFIG_KGDB which in turn enables your calls -- * to: -- * set_debug_traps(); -- * breakpoint(); -- * -- * Step 4: -- * Start the gdb session on the host. -- * -- * Example: -- * $ mips-linux-elf-gdb vmlinux -- * (gdb) set remotebaud 115200 -- * (gdb) target remote /dev/ttyS1 -- * ...at this point you are connected to -- * the remote target and can use gdb -- * in the normal fasion. Setting -- * breakpoints, single stepping, -- * printing variables, etc. -- */ --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include --#include --#include --#include --#include --#include --#include --#include -- --/* -- * external low-level support routines -- */ -- --extern int putDebugChar(char c); /* write a single character */ --extern char getDebugChar(void); /* read and return a single char */ --extern void trap_low(void); -- --/* -- * breakpoint and test functions -- */ --extern void breakpoint(void); --extern void breakinst(void); --extern void async_breakpoint(void); --extern void async_breakinst(void); --extern void adel(void); -- --/* -- * local prototypes -- */ -- --static void getpacket(char *buffer); --static void putpacket(char *buffer); --static int computeSignal(int tt); --static int hex(unsigned char ch); --static int hexToInt(char **ptr, int *intValue); --static int hexToLong(char **ptr, long *longValue); --static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault); --void handle_exception(struct gdb_regs *regs); -- --int kgdb_enabled; -- --/* -- * spin locks for smp case -- */ --static DEFINE_SPINLOCK(kgdb_lock); --static raw_spinlock_t kgdb_cpulock[NR_CPUS] = { -- [0 ... NR_CPUS-1] = __RAW_SPIN_LOCK_UNLOCKED, --}; -- --/* -- * BUFMAX defines the maximum number of characters in inbound/outbound buffers -- * at least NUMREGBYTES*2 are needed for register packets -- */ --#define BUFMAX 2048 -- --static char input_buffer[BUFMAX]; --static char output_buffer[BUFMAX]; --static int initialized; /* !0 means we've been initialized */ --static int kgdb_started; --static const char hexchars[]="0123456789abcdef"; -- --/* Used to prevent crashes in memory access. Note that they'll crash anyway if -- we haven't set up fault handlers yet... */ --int kgdb_read_byte(unsigned char *address, unsigned char *dest); --int kgdb_write_byte(unsigned char val, unsigned char *dest); -- --/* -- * 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 $# -- */ --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(); -- 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 sequence 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(char *buffer) --{ -- unsigned char checksum; -- int count; -- unsigned char ch; -- -- /* -- * $#. -- */ -- -- do { -- putDebugChar('$'); -- checksum = 0; -- count = 0; -- -- while ((ch = buffer[count]) != 0) { -- if (!(putDebugChar(ch))) -- return; -- checksum += ch; -- count += 1; -- } -- -- putDebugChar('#'); -- putDebugChar(hexchars[checksum >> 4]); -- putDebugChar(hexchars[checksum & 0xf]); -- -- } -- while ((getDebugChar() & 0x7f) != '+'); --} -- -- --/* -- * 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. -- * may_fault is non-zero if we are reading from arbitrary memory, but is currently -- * not used. -- */ --static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault) --{ -- unsigned char ch; -- -- while (count-- > 0) { -- if (kgdb_read_byte(mem++, &ch) != 0) -- return 0; -- *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 -- * may_fault is non-zero if we are reading from arbitrary memory, but is currently -- * not used. -- */ --static char *hex2mem(char *buf, char *mem, int count, int binary, int may_fault) --{ -- int i; -- unsigned char ch; -- -- for (i=0; itt && ht->signo; ht++) -- saved_vectors[ht->tt] = set_except_vector(ht->tt, trap_low); -- -- putDebugChar('+'); /* 'hello world' */ -- /* -- * In case GDB is started before us, ack any packets -- * (presumably "$?#xx") sitting there. -- */ -- while((c = getDebugChar()) != '$'); -- while((c = getDebugChar()) != '#'); -- c = getDebugChar(); /* eat first csum byte */ -- c = getDebugChar(); /* eat second csum byte */ -- putDebugChar('+'); /* ack it */ -- -- initialized = 1; -- local_irq_restore(flags); --} -- --void restore_debug_traps(void) --{ -- struct hard_trap_info *ht; -- unsigned long flags; -- -- local_irq_save(flags); -- for (ht = hard_trap_info; ht->tt && ht->signo; ht++) -- set_except_vector(ht->tt, saved_vectors[ht->tt]); -- local_irq_restore(flags); --} -- --/* -- * Convert the MIPS 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); --} -- --static int hexToLong(char **ptr, long *longValue) --{ -- int numChars = 0; -- int hexValue; -- -- *longValue = 0; -- -- while (**ptr) { -- hexValue = hex(**ptr); -- if (hexValue < 0) -- break; -- -- *longValue = (*longValue << 4) | hexValue; -- numChars ++; -- -- (*ptr)++; -- } -- -- return numChars; --} -- -- --#if 0 --/* -- * Print registers (on target console) -- * Used only to debug the stub... -- */ --void show_gdbregs(struct gdb_regs * regs) --{ -- /* -- * Saved main processor registers -- */ -- printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", -- regs->reg0, regs->reg1, regs->reg2, regs->reg3, -- regs->reg4, regs->reg5, regs->reg6, regs->reg7); -- printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", -- regs->reg8, regs->reg9, regs->reg10, regs->reg11, -- regs->reg12, regs->reg13, regs->reg14, regs->reg15); -- printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", -- regs->reg16, regs->reg17, regs->reg18, regs->reg19, -- regs->reg20, regs->reg21, regs->reg22, regs->reg23); -- printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", -- regs->reg24, regs->reg25, regs->reg26, regs->reg27, -- regs->reg28, regs->reg29, regs->reg30, regs->reg31); -- -- /* -- * Saved cp0 registers -- */ -- printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\n", -- regs->cp0_epc, regs->cp0_status, regs->cp0_cause); --} --#endif /* dead code */ -- --/* -- * We single-step by setting breakpoints. When an exception -- * is handled, we need to restore the instructions hoisted -- * when the breakpoints were set. -- * -- * This is where we save the original instructions. -- */ --static struct gdb_bp_save { -- unsigned long addr; -- unsigned int val; --} step_bp[2]; -- --#define BP 0x0000000d /* break opcode */ -- --/* -- * Set breakpoint instructions for single stepping. -- */ --static void single_step(struct gdb_regs *regs) --{ -- union mips_instruction insn; -- unsigned long targ; -- int is_branch, is_cond, i; -- -- targ = regs->cp0_epc; -- insn.word = *(unsigned int *)targ; -- is_branch = is_cond = 0; -- -- switch (insn.i_format.opcode) { -- /* -- * jr and jalr are in r_format format. -- */ -- case spec_op: -- switch (insn.r_format.func) { -- case jalr_op: -- case jr_op: -- targ = *(®s->reg0 + insn.r_format.rs); -- is_branch = 1; -- break; -- } -- break; -- -- /* -- * This group contains: -- * bltz_op, bgez_op, bltzl_op, bgezl_op, -- * bltzal_op, bgezal_op, bltzall_op, bgezall_op. -- */ -- case bcond_op: -- is_branch = is_cond = 1; -- targ += 4 + (insn.i_format.simmediate << 2); -- break; -- -- /* -- * These are unconditional and in j_format. -- */ -- case jal_op: -- case j_op: -- is_branch = 1; -- targ += 4; -- targ >>= 28; -- targ <<= 28; -- targ |= (insn.j_format.target << 2); -- break; -- -- /* -- * These are conditional. -- */ -- case beq_op: -- case beql_op: -- case bne_op: -- case bnel_op: -- case blez_op: -- case blezl_op: -- case bgtz_op: -- case bgtzl_op: -- case cop0_op: -- case cop1_op: -- case cop2_op: -- case cop1x_op: -- is_branch = is_cond = 1; -- targ += 4 + (insn.i_format.simmediate << 2); -- break; -- } -- -- if (is_branch) { -- i = 0; -- if (is_cond && targ != (regs->cp0_epc + 8)) { -- step_bp[i].addr = regs->cp0_epc + 8; -- step_bp[i++].val = *(unsigned *)(regs->cp0_epc + 8); -- *(unsigned *)(regs->cp0_epc + 8) = BP; -- } -- step_bp[i].addr = targ; -- step_bp[i].val = *(unsigned *)targ; -- *(unsigned *)targ = BP; -- } else { -- step_bp[0].addr = regs->cp0_epc + 4; -- step_bp[0].val = *(unsigned *)(regs->cp0_epc + 4); -- *(unsigned *)(regs->cp0_epc + 4) = BP; -- } --} -- --/* -- * If asynchronously interrupted by gdb, then we need to set a breakpoint -- * at the interrupted instruction so that we wind up stopped with a -- * reasonable stack frame. -- */ --static struct gdb_bp_save async_bp; -- --/* -- * Swap the interrupted EPC with our asynchronous breakpoint routine. -- * This is safer than stuffing the breakpoint in-place, since no cache -- * flushes (or resulting smp_call_functions) are required. The -- * assumption is that only one CPU will be handling asynchronous bp's, -- * and only one can be active at a time. -- */ --extern spinlock_t smp_call_lock; -- --void set_async_breakpoint(unsigned long *epc) --{ -- /* skip breaking into userland */ -- if ((*epc & 0x80000000) == 0) -- return; -- --#ifdef CONFIG_SMP -- /* avoid deadlock if someone is make IPC */ -- if (spin_is_locked(&smp_call_lock)) -- return; --#endif -- -- async_bp.addr = *epc; -- *epc = (unsigned long)async_breakpoint; --} -- --static void kgdb_wait(void *arg) --{ -- unsigned flags; -- int cpu = smp_processor_id(); -- -- local_irq_save(flags); -- -- __raw_spin_lock(&kgdb_cpulock[cpu]); -- __raw_spin_unlock(&kgdb_cpulock[cpu]); -- -- local_irq_restore(flags); --} -- --/* -- * GDB stub needs to call kgdb_wait on all processor with interrupts -- * disabled, so it uses it's own special variant. -- */ --static int kgdb_smp_call_kgdb_wait(void) --{ --#ifdef CONFIG_SMP -- struct call_data_struct data; -- int i, cpus = num_online_cpus() - 1; -- int cpu = smp_processor_id(); -- -- /* -- * Can die spectacularly if this CPU isn't yet marked online -- */ -- BUG_ON(!cpu_online(cpu)); -- -- if (!cpus) -- return 0; -- -- if (spin_is_locked(&smp_call_lock)) { -- /* -- * Some other processor is trying to make us do something -- * but we're not going to respond... give up -- */ -- return -1; -- } -- -- /* -- * We will continue here, accepting the fact that -- * the kernel may deadlock if another CPU attempts -- * to call smp_call_function now... -- */ -- -- data.func = kgdb_wait; -- data.info = NULL; -- atomic_set(&data.started, 0); -- data.wait = 0; -- -- spin_lock(&smp_call_lock); -- call_data = &data; -- mb(); -- -- /* Send a message to all other CPUs and wait for them to respond */ -- for (i = 0; i < NR_CPUS; i++) -- if (cpu_online(i) && i != cpu) -- core_send_ipi(i, SMP_CALL_FUNCTION); -- -- /* Wait for response */ -- /* FIXME: lock-up detection, backtrace on lock-up */ -- while (atomic_read(&data.started) != cpus) -- barrier(); -- -- call_data = NULL; -- spin_unlock(&smp_call_lock); --#endif -- -- return 0; --} -- --/* -- * 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. -- */ --void handle_exception (struct gdb_regs *regs) --{ -- int trap; /* Trap type */ -- int sigval; -- long addr; -- int length; -- char *ptr; -- unsigned long *stack; -- int i; -- int bflag = 0; -- -- kgdb_started = 1; -- -- /* -- * acquire the big kgdb spinlock -- */ -- if (!spin_trylock(&kgdb_lock)) { -- /* -- * some other CPU has the lock, we should go back to -- * receive the gdb_wait IPC -- */ -- return; -- } -- -- /* -- * If we're in async_breakpoint(), restore the real EPC from -- * the breakpoint. -- */ -- if (regs->cp0_epc == (unsigned long)async_breakinst) { -- regs->cp0_epc = async_bp.addr; -- async_bp.addr = 0; -- } -- -- /* -- * acquire the CPU spinlocks -- */ -- for (i = num_online_cpus()-1; i >= 0; i--) -- if (__raw_spin_trylock(&kgdb_cpulock[i]) == 0) -- panic("kgdb: couldn't get cpulock %d\n", i); -- -- /* -- * force other cpus to enter kgdb -- */ -- kgdb_smp_call_kgdb_wait(); -- -- /* -- * If we're in breakpoint() increment the PC -- */ -- trap = (regs->cp0_cause & 0x7c) >> 2; -- if (trap == 9 && regs->cp0_epc == (unsigned long)breakinst) -- regs->cp0_epc += 4; -- -- /* -- * If we were single_stepping, restore the opcodes hoisted -- * for the breakpoint[s]. -- */ -- if (step_bp[0].addr) { -- *(unsigned *)step_bp[0].addr = step_bp[0].val; -- step_bp[0].addr = 0; -- -- if (step_bp[1].addr) { -- *(unsigned *)step_bp[1].addr = step_bp[1].val; -- step_bp[1].addr = 0; -- } -- } -- -- stack = (long *)regs->reg29; /* stack ptr */ -- sigval = computeSignal(trap); -- -- /* -- * reply to host that an exception has occurred -- */ -- ptr = output_buffer; -- -- /* -- * Send trap type (converted to signal) -- */ -- *ptr++ = 'T'; -- *ptr++ = hexchars[sigval >> 4]; -- *ptr++ = hexchars[sigval & 0xf]; -- -- /* -- * Send Error PC -- */ -- *ptr++ = hexchars[REG_EPC >> 4]; -- *ptr++ = hexchars[REG_EPC & 0xf]; -- *ptr++ = ':'; -- ptr = mem2hex((char *)®s->cp0_epc, ptr, sizeof(long), 0); -- *ptr++ = ';'; -- -- /* -- * Send frame pointer -- */ -- *ptr++ = hexchars[REG_FP >> 4]; -- *ptr++ = hexchars[REG_FP & 0xf]; -- *ptr++ = ':'; -- ptr = mem2hex((char *)®s->reg30, ptr, sizeof(long), 0); -- *ptr++ = ';'; -- -- /* -- * Send stack pointer -- */ -- *ptr++ = hexchars[REG_SP >> 4]; -- *ptr++ = hexchars[REG_SP & 0xf]; -- *ptr++ = ':'; -- ptr = mem2hex((char *)®s->reg29, ptr, sizeof(long), 0); -- *ptr++ = ';'; -- -- *ptr++ = 0; -- putpacket(output_buffer); /* send it off... */ -- -- /* -- * Wait for input from remote GDB -- */ -- while (1) { -- output_buffer[0] = 0; -- getpacket(input_buffer); -- -- switch (input_buffer[0]) -- { -- case '?': -- output_buffer[0] = 'S'; -- output_buffer[1] = hexchars[sigval >> 4]; -- output_buffer[2] = hexchars[sigval & 0xf]; -- output_buffer[3] = 0; -- break; -- -- /* -- * Detach debugger; let CPU run -- */ -- case 'D': -- putpacket(output_buffer); -- goto finish_kgdb; -- break; -- -- case 'd': -- /* toggle debug flag */ -- break; -- -- /* -- * Return the value of the CPU registers -- */ -- case 'g': -- ptr = output_buffer; -- ptr = mem2hex((char *)®s->reg0, ptr, 32*sizeof(long), 0); /* r0...r31 */ -- ptr = mem2hex((char *)®s->cp0_status, ptr, 6*sizeof(long), 0); /* cp0 */ -- ptr = mem2hex((char *)®s->fpr0, ptr, 32*sizeof(long), 0); /* f0...31 */ -- ptr = mem2hex((char *)®s->cp1_fsr, ptr, 2*sizeof(long), 0); /* cp1 */ -- ptr = mem2hex((char *)®s->frame_ptr, ptr, 2*sizeof(long), 0); /* frp */ -- ptr = mem2hex((char *)®s->cp0_index, ptr, 16*sizeof(long), 0); /* cp0 */ -- break; -- -- /* -- * set the value of the CPU registers - return OK -- */ -- case 'G': -- { -- ptr = &input_buffer[1]; -- hex2mem(ptr, (char *)®s->reg0, 32*sizeof(long), 0, 0); -- ptr += 32*(2*sizeof(long)); -- hex2mem(ptr, (char *)®s->cp0_status, 6*sizeof(long), 0, 0); -- ptr += 6*(2*sizeof(long)); -- hex2mem(ptr, (char *)®s->fpr0, 32*sizeof(long), 0, 0); -- ptr += 32*(2*sizeof(long)); -- hex2mem(ptr, (char *)®s->cp1_fsr, 2*sizeof(long), 0, 0); -- ptr += 2*(2*sizeof(long)); -- hex2mem(ptr, (char *)®s->frame_ptr, 2*sizeof(long), 0, 0); -- ptr += 2*(2*sizeof(long)); -- hex2mem(ptr, (char *)®s->cp0_index, 16*sizeof(long), 0, 0); -- strcpy(output_buffer,"OK"); -- } -- break; -- -- /* -- * mAA..AA,LLLL Read LLLL bytes at address AA..AA -- */ -- case 'm': -- ptr = &input_buffer[1]; -- -- if (hexToLong(&ptr, &addr) -- && *ptr++ == ',' -- && hexToInt(&ptr, &length)) { -- if (mem2hex((char *)addr, output_buffer, length, 1)) -- break; -- strcpy (output_buffer, "E03"); -- } else -- strcpy(output_buffer,"E01"); -- break; -- -- /* -- * XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA -- */ -- case 'X': -- bflag = 1; -- /* fall through */ -- -- /* -- * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK -- */ -- case 'M': -- ptr = &input_buffer[1]; -- -- if (hexToLong(&ptr, &addr) -- && *ptr++ == ',' -- && hexToInt(&ptr, &length) -- && *ptr++ == ':') { -- if (hex2mem(ptr, (char *)addr, length, bflag, 1)) -- strcpy(output_buffer, "OK"); -- else -- strcpy(output_buffer, "E03"); -- } -- else -- strcpy(output_buffer, "E02"); -- break; -- -- /* -- * cAA..AA Continue at address AA..AA(optional) -- */ -- case 'c': -- /* try to read optional parameter, pc unchanged if no parm */ -- -- ptr = &input_buffer[1]; -- if (hexToLong(&ptr, &addr)) -- regs->cp0_epc = addr; -- -- goto exit_kgdb_exception; -- break; -- -- /* -- * kill the program; let us try to restart the machine -- * Reset the whole machine. -- */ -- case 'k': -- case 'r': -- machine_restart("kgdb restarts machine"); -- break; -- -- /* -- * Step to next instruction -- */ -- case 's': -- /* -- * There is no single step insn in the MIPS ISA, so we -- * use breakpoints and continue, instead. -- */ -- single_step(regs); -- goto exit_kgdb_exception; -- /* NOTREACHED */ -- break; -- -- /* -- * Set baud rate (bBB) -- * FIXME: Needs to be written -- */ -- case 'b': -- { --#if 0 -- int baudrate; -- extern void set_timer_3(); -- -- ptr = &input_buffer[1]; -- if (!hexToInt(&ptr, &baudrate)) -- { -- strcpy(output_buffer,"B01"); -- break; -- } -- -- /* Convert baud rate to uart clock divider */ -- -- switch (baudrate) -- { -- case 38400: -- baudrate = 16; -- break; -- case 19200: -- baudrate = 33; -- break; -- case 9600: -- baudrate = 65; -- break; -- default: -- baudrate = 0; -- strcpy(output_buffer,"B02"); -- goto x1; -- } -- -- if (baudrate) { -- putpacket("OK"); /* Ack before changing speed */ -- set_timer_3(baudrate); /* Set it */ -- } --#endif -- } -- break; -- -- } /* switch */ -- -- /* -- * reply to the request -- */ -- -- putpacket(output_buffer); -- -- } /* while */ -- -- return; -- --finish_kgdb: -- restore_debug_traps(); -- --exit_kgdb_exception: -- /* release locks so other CPUs can go */ -- for (i = num_online_cpus()-1; i >= 0; i--) -- __raw_spin_unlock(&kgdb_cpulock[i]); -- spin_unlock(&kgdb_lock); -- -- __flush_cache_all(); -- return; --} -- --/* -- * 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; -- -- __asm__ __volatile__( -- ".globl breakinst\n\t" -- ".set\tnoreorder\n\t" -- "nop\n" -- "breakinst:\tbreak\n\t" -- "nop\n\t" -- ".set\treorder" -- ); --} -- --/* Nothing but the break; don't pollute any registers */ --void async_breakpoint(void) --{ -- __asm__ __volatile__( -- ".globl async_breakinst\n\t" -- ".set\tnoreorder\n\t" -- "nop\n" -- "async_breakinst:\tbreak\n\t" -- "nop\n\t" -- ".set\treorder" -- ); --} -- --void adel(void) --{ -- __asm__ __volatile__( -- ".globl\tadel\n\t" -- "lui\t$8,0x8000\n\t" -- "lw\t$9,1($8)\n\t" -- ); --} -- --/* -- * malloc is needed by gdb client in "call func()", even a private one -- * will make gdb happy -- */ --static void * __attribute_used__ malloc(size_t size) --{ -- return kmalloc(size, GFP_ATOMIC); --} -- --static void __attribute_used__ free (void *where) --{ -- kfree(where); --} -- --#ifdef CONFIG_GDB_CONSOLE -- --void gdb_putsn(const char *str, int l) --{ -- char outbuf[18]; -- -- if (!kgdb_started) -- return; -- -- outbuf[0]='O'; -- -- while(l) { -- int i = (l>8)?8:l; -- mem2hex((char *)str, &outbuf[1], i, 0); -- outbuf[(i*2)+1]=0; -- putpacket(outbuf); -- str += i; -- l -= i; -- } --} -- --static void gdb_console_write(struct console *con, const char *s, unsigned n) --{ -- gdb_putsn(s, n); --} -- --static struct console gdb_console = { -- .name = "gdb", -- .write = gdb_console_write, -- .flags = CON_PRINTBUFFER, -- .index = -1 --}; -- --static int __init register_gdb_console(void) --{ -- register_console(&gdb_console); -- -- return 0; --} -- --console_initcall(register_gdb_console); -- --#endif -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/kernel/irq.c linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/irq.c ---- linux-2.6.18-53.1.14/arch/mips/kernel/irq.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/irq.c 2008-06-10 15:38:24.000000000 +0400 -@@ -25,6 +25,10 @@ - #include - #include - #include -+#include -+ -+/* Keep track of if we've done certain initialization already or not. */ -+int kgdb_early_setup; - - /* - * 'what should we do if we get a hw irq event on an illegal vector'. -@@ -115,23 +119,13 @@ asmlinkage void spurious_interrupt(struc - atomic_inc(&irq_err_count); - } - --#ifdef CONFIG_KGDB --extern void breakpoint(void); --extern void set_debug_traps(void); -- --static int kgdb_flag = 1; --static int __init nokgdb(char *str) --{ -- kgdb_flag = 0; -- return 1; --} --__setup("nokgdb", nokgdb); --#endif -- - void __init init_IRQ(void) - { - int i; - -+ if (kgdb_early_setup) -+ return; -+ - for (i = 0; i < NR_IRQS; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; -@@ -144,12 +138,12 @@ void __init init_IRQ(void) - } - - arch_init_irq(); -- - #ifdef CONFIG_KGDB -- if (kgdb_flag) { -- printk("Wait for gdb client connection ...\n"); -- set_debug_traps(); -- breakpoint(); -- } -+ /* -+ * We have been called before kgdb_arch_init(). Hence, -+ * we dont want the traps to be reinitialized -+ */ -+ if (kgdb_early_setup == 0) -+ kgdb_early_setup = 1; - #endif - } -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/kernel/kgdb-jmp.c linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/kgdb-jmp.c ---- linux-2.6.18-53.1.14/arch/mips/kernel/kgdb-jmp.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/kgdb-jmp.c 2008-06-10 15:38:24.000000000 +0400 -@@ -0,0 +1,116 @@ -+/* -+ * arch/mips/kernel/kgdb-jmp.c -+ * -+ * Save and restore system registers so that within a limited frame we -+ * may have a fault and "jump back" to a known safe location. -+ * -+ * Author: Tom Rini -+ * Author: Manish Lachwani -+ * -+ * Cribbed from glibc, which carries the following: -+ * Copyright (C) 1996, 1997, 2000, 2002, 2003 Free Software Foundation, Inc. -+ * Copyright (C) 2005 by MontaVista Software. -+ * -+ * This file is licensed under the terms of the GNU General Public License -+ * version 2. This program as licensed "as is" without any warranty of -+ * any kind, whether express or implied. -+ */ -+ -+#include -+#include -+ -+#ifdef CONFIG_MIPS64 -+/* -+ * MIPS 64-bit -+ */ -+ -+int kgdb_fault_setjmp_aux(unsigned long *curr_context, int sp, int fp) -+{ -+ __asm__ __volatile__ ("sd $gp, %0" : : "m" (curr_context[0])); -+ __asm__ __volatile__ ("sd $16, %0" : : "m" (curr_context[1])); -+ __asm__ __volatile__ ("sd $17, %0" : : "m" (curr_context[2])); -+ __asm__ __volatile__ ("sd $18, %0" : : "m" (curr_context[3])); -+ __asm__ __volatile__ ("sd $19, %0" : : "m" (curr_context[4])); -+ __asm__ __volatile__ ("sd $20, %0" : : "m" (curr_context[5])); -+ __asm__ __volatile__ ("sd $21, %0" : : "m" (curr_context[6])); -+ __asm__ __volatile__ ("sd $22, %0" : : "m" (curr_context[7])); -+ __asm__ __volatile__ ("sd $23, %0" : : "m" (curr_context[8])); -+ __asm__ __volatile__ ("sd $31, %0" : : "m" (curr_context[9])); -+ curr_context[10] = (long *)sp; -+ curr_context[11] = (long *)fp; -+ -+ return 0; -+} -+ -+void kgdb_fault_longjmp(unsigned long *curr_context) -+{ -+ unsigned long sp_val, fp_val; -+ -+ __asm__ __volatile__ ("ld $gp, %0" : : "m" (curr_context[0])); -+ __asm__ __volatile__ ("ld $16, %0" : : "m" (curr_context[1])); -+ __asm__ __volatile__ ("ld $17, %0" : : "m" (curr_context[2])); -+ __asm__ __volatile__ ("ld $18, %0" : : "m" (curr_context[3])); -+ __asm__ __volatile__ ("ld $19, %0" : : "m" (curr_context[4])); -+ __asm__ __volatile__ ("ld $20, %0" : : "m" (curr_context[5])); -+ __asm__ __volatile__ ("ld $21, %0" : : "m" (curr_context[6])); -+ __asm__ __volatile__ ("ld $22, %0" : : "m" (curr_context[7])); -+ __asm__ __volatile__ ("ld $23, %0" : : "m" (curr_context[8])); -+ __asm__ __volatile__ ("ld $25, %0" : : "m" (curr_context[9])); -+ sp_val = curr_context[10]; -+ fp_val = curr_context[11]; -+ __asm__ __volatile__ ("ld $29, %0\n\t" -+ "ld $30, %1\n\t" : : "m" (sp_val), "m" (fp_val)); -+ -+ __asm__ __volatile__ ("dli $2, 1"); -+ __asm__ __volatile__ ("j $25"); -+ -+ for (;;); -+} -+#else -+/* -+ * MIPS 32-bit -+ */ -+ -+int kgdb_fault_setjmp_aux(unsigned long *curr_context, int sp, int fp) -+{ -+ __asm__ __volatile__("sw $gp, %0" : : "m" (curr_context[0])); -+ __asm__ __volatile__("sw $16, %0" : : "m" (curr_context[1])); -+ __asm__ __volatile__("sw $17, %0" : : "m" (curr_context[2])); -+ __asm__ __volatile__("sw $18, %0" : : "m" (curr_context[3])); -+ __asm__ __volatile__("sw $19, %0" : : "m" (curr_context[4])); -+ __asm__ __volatile__("sw $20, %0" : : "m" (curr_context[5])); -+ __asm__ __volatile__("sw $21, %0" : : "m" (curr_context[6])); -+ __asm__ __volatile__("sw $22, %0" : : "m" (curr_context[7])); -+ __asm__ __volatile__("sw $23, %0" : : "m" (curr_context[8])); -+ __asm__ __volatile__("sw $31, %0" : : "m" (curr_context[9])); -+ curr_context[10] = (long *)sp; -+ curr_context[11] = (long *)fp; -+ -+ return 0; -+} -+ -+void kgdb_fault_longjmp(unsigned long *curr_context) -+{ -+ unsigned long sp_val, fp_val; -+ -+ __asm__ __volatile__("lw $gp, %0" : : "m" (curr_context[0])); -+ __asm__ __volatile__("lw $16, %0" : : "m" (curr_context[1])); -+ __asm__ __volatile__("lw $17, %0" : : "m" (curr_context[2])); -+ __asm__ __volatile__("lw $18, %0" : : "m" (curr_context[3])); -+ __asm__ __volatile__("lw $19, %0" : : "m" (curr_context[4])); -+ __asm__ __volatile__("lw $20, %0" : : "m" (curr_context[5])); -+ __asm__ __volatile__("lw $21, %0" : : "m" (curr_context[6])); -+ __asm__ __volatile__("lw $22, %0" : : "m" (curr_context[7])); -+ __asm__ __volatile__("lw $23, %0" : : "m" (curr_context[8])); -+ __asm__ __volatile__("lw $25, %0" : : "m" (curr_context[9])); -+ sp_val = curr_context[10]; -+ fp_val = curr_context[11]; -+ __asm__ __volatile__("lw $29, %0\n\t" -+ "lw $30, %1\n\t" : : "m" (sp_val), "m" (fp_val)); -+ -+ __asm__ __volatile__("li $2, 1"); -+ __asm__ __volatile__("jr $25"); -+ -+ for (;;); -+} -+#endif -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/kernel/kgdb-setjmp.S linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/kgdb-setjmp.S ---- linux-2.6.18-53.1.14/arch/mips/kernel/kgdb-setjmp.S 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/kgdb-setjmp.S 2008-06-10 15:38:24.000000000 +0400 -@@ -0,0 +1,28 @@ -+/* -+ * arch/mips/kernel/kgdb-jmp.c -+ * -+ * Save and restore system registers so that within a limited frame we -+ * may have a fault and "jump back" to a known safe location. -+ * -+ * Copyright (C) 2005 by MontaVista Software. -+ * Author: Manish Lachwani (mlachwani@mvista.com) -+ * -+ * This file is licensed under the terms of the GNU General Public License -+ * version 2. This program as licensed "as is" without any warranty of -+ * any kind, whether express or implied. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+ .ent kgdb_fault_setjmp,0 -+ENTRY (kgdb_fault_setjmp) -+ move a1, sp -+ move a2, fp -+#ifdef CONFIG_MIPS64 -+ nop -+#endif -+ j kgdb_fault_setjmp_aux -+ .end kgdb_fault_setjmp -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/kernel/kgdb.c linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/kgdb.c ---- linux-2.6.18-53.1.14/arch/mips/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/kgdb.c 2008-06-10 15:38:24.000000000 +0400 -@@ -0,0 +1,297 @@ -+/* -+ * arch/mips/kernel/kgdb.c -+ * -+ * Originally written by Glenn Engel, Lake Stevens Instrument Division -+ * -+ * Contributed by HP Systems -+ * -+ * Modified for SPARC by Stu Grossman, Cygnus Support. -+ * -+ * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse -+ * Send complaints, suggestions etc. to -+ * -+ * Copyright (C) 1995 Andreas Busse -+ * -+ * Copyright (C) 2003 MontaVista Software Inc. -+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net -+ * -+ * Copyright (C) 2004-2005 MontaVista Software Inc. -+ * Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com -+ * -+ * This file is licensed under the terms of the GNU General Public License -+ * version 2. This program is licensed "as is" without any warranty of any -+ * kind, whether express or implied. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* for linux pt_regs struct */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static struct hard_trap_info { -+ unsigned char tt; /* Trap type code for MIPS R3xxx and R4xxx */ -+ unsigned char signo; /* Signal that we map this trap into */ -+} hard_trap_info[] = { -+ { 6, SIGBUS }, /* instruction bus error */ -+ { 7, SIGBUS }, /* data bus error */ -+ { 9, SIGTRAP }, /* break */ -+/* { 11, SIGILL }, */ /* CPU unusable */ -+ { 12, SIGFPE }, /* overflow */ -+ { 13, SIGTRAP }, /* trap */ -+ { 14, SIGSEGV }, /* virtual instruction cache coherency */ -+ { 15, SIGFPE }, /* floating point exception */ -+ { 23, SIGSEGV }, /* watch */ -+ { 31, SIGSEGV }, /* virtual data cache coherency */ -+ { 0, 0} /* Must be last */ -+}; -+ -+/* Save the normal trap handlers for user-mode traps. */ -+void *saved_vectors[32]; -+ -+extern void trap_low(void); -+extern void breakinst(void); -+extern void init_IRQ(void); -+ -+void kgdb_call_nmi_hook(void *ignored) -+{ -+ kgdb_nmihook(smp_processor_id(), (void *)0); -+} -+ -+void kgdb_roundup_cpus(unsigned long flags) -+{ -+ local_irq_restore(flags); -+ smp_call_function(kgdb_call_nmi_hook, 0, 0, 0); -+ local_irq_save(flags); -+} -+ -+static int compute_signal(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 */ -+} -+ -+/* -+ * Set up exception handlers for tracing and breakpoints -+ */ -+void handle_exception(struct pt_regs *regs) -+{ -+ int trap = (regs->cp0_cause & 0x7c) >> 2; -+ -+ if (fixup_exception(regs)) { -+ return; -+ } -+ -+ if (atomic_read(&debugger_active)) -+ kgdb_nmihook(smp_processor_id(), regs); -+ -+ if (atomic_read(&kgdb_setting_breakpoint)) -+ if ((trap == 9) && (regs->cp0_epc == (unsigned long)breakinst)) -+ regs->cp0_epc += 4; -+ -+ kgdb_handle_exception(0, compute_signal(trap), 0, regs); -+ -+ /* In SMP mode, __flush_cache_all does IPI */ -+ __flush_cache_all(); -+} -+ -+void set_debug_traps(void) -+{ -+ struct hard_trap_info *ht; -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ -+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++) -+ saved_vectors[ht->tt] = set_except_vector(ht->tt, trap_low); -+ -+ local_irq_restore(flags); -+} -+ -+#if 0 -+/* This should be called before we exit kgdb_handle_exception() I believe. -+ * -- Tom -+ */ -+void restore_debug_traps(void) -+{ -+ struct hard_trap_info *ht; -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++) -+ set_except_vector(ht->tt, saved_vectors[ht->tt]); -+ local_irq_restore(flags); -+} -+#endif -+ -+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) -+{ -+ int reg; -+ gdb_reg_t *ptr = (gdb_reg_t*)gdb_regs; -+ -+ for (reg = 0; reg < 32; reg++) -+ *(ptr++) = regs->regs[reg]; -+ -+ *(ptr++) = regs->cp0_status; -+ *(ptr++) = regs->lo; -+ *(ptr++) = regs->hi; -+ *(ptr++) = regs->cp0_badvaddr; -+ *(ptr++) = regs->cp0_cause; -+ *(ptr++) = regs->cp0_epc; -+ -+ return; -+} -+ -+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs) -+{ -+ -+ int reg; -+ const gdb_reg_t *ptr = (gdb_reg_t*)gdb_regs; -+ -+ for (reg = 0; reg < 32; reg++) -+ regs->regs[reg] = *(ptr++); -+ -+ regs->cp0_status = *(ptr++); -+ regs->lo = *(ptr++); -+ regs->hi = *(ptr++); -+ regs->cp0_badvaddr = *(ptr++); -+ regs->cp0_cause = *(ptr++); -+ regs->cp0_epc = *(ptr++); -+ -+ return; -+} -+ -+/* -+ * Similar to regs_to_gdb_regs() except that process is sleeping and so -+ * we may not be able to get all the info. -+ */ -+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) -+{ -+ int reg; -+ struct thread_info *ti = p->thread_info; -+ unsigned long ksp = (unsigned long)ti + THREAD_SIZE - 32; -+ struct pt_regs *regs = (struct pt_regs *)ksp - 1; -+ gdb_reg_t *ptr = (gdb_reg_t*)gdb_regs; -+ -+ for (reg = 0; reg < 16; reg++) -+ *(ptr++) = regs->regs[reg]; -+ -+ /* S0 - S7 */ -+ for (reg = 16; reg < 24; reg++) -+ *(ptr++) = regs->regs[reg]; -+ -+ for (reg = 24; reg < 28; reg++) -+ *(ptr++) = 0; -+ -+ /* GP, SP, FP, RA */ -+ for (reg = 28; reg < 32; reg++) -+ *(ptr++) = regs->regs[reg]; -+ -+ *(ptr++) = regs->cp0_status; -+ *(ptr++) = regs->lo; -+ *(ptr++) = regs->hi; -+ *(ptr++) = regs->cp0_badvaddr; -+ *(ptr++) = regs->cp0_cause; -+ *(ptr++) = regs->cp0_epc; -+ -+ return; -+} -+ -+/* -+ * Calls linux_debug_hook before the kernel dies. If KGDB is enabled, -+ * then try to fall into the debugger -+ */ -+static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd, -+ void *ptr) -+{ -+ struct die_args *args = (struct die_args *)ptr; -+ struct pt_regs *regs = args->regs; -+ int trap = (regs->cp0_cause & 0x7c) >> 2; -+ -+ /* See if KGDB is interested. */ -+ if (user_mode(regs)) -+ /* Userpace events, ignore. */ -+ return NOTIFY_DONE; -+ -+ kgdb_handle_exception(trap, compute_signal(trap), 0, regs); -+ return NOTIFY_OK; -+} -+ -+static struct notifier_block kgdb_notifier = { -+ .notifier_call = kgdb_mips_notify, -+}; -+ -+/* -+ * Handle the 's' and 'c' commands -+ */ -+int kgdb_arch_handle_exception(int vector, int signo, int err_code, -+ char *remcom_in_buffer, char *remcom_out_buffer, -+ struct pt_regs *regs) -+{ -+ char *ptr; -+ unsigned long address; -+ int cpu = smp_processor_id(); -+ -+ switch (remcom_in_buffer[0]) { -+ case 's': -+ case 'c': -+ /* handle the optional parameter */ -+ ptr = &remcom_in_buffer[1]; -+ if (kgdb_hex2long(&ptr, &address)) -+ regs->cp0_epc = address; -+ -+ atomic_set(&cpu_doing_single_step, -1); -+ if (remcom_in_buffer[0] == 's') -+ if (kgdb_contthread) -+ atomic_set(&cpu_doing_single_step, cpu); -+ -+ return 0; -+ } -+ -+ return -1; -+} -+ -+struct kgdb_arch arch_kgdb_ops = { -+#ifdef CONFIG_CPU_LITTLE_ENDIAN -+ .gdb_bpt_instr = {0xd}, -+#else -+ .gdb_bpt_instr = {0x00, 0x00, 0x00, 0x0d}, -+#endif -+}; -+ -+/* -+ * We use kgdb_early_setup so that functions we need to call now don't -+ * cause trouble when called again later. -+ */ -+int kgdb_arch_init(void) -+{ -+ /* Board-specifics. */ -+ /* Force some calls to happen earlier. */ -+ if (kgdb_early_setup == 0) { -+ trap_init(); -+ init_IRQ(); -+ kgdb_early_setup = 1; -+ } -+ -+ /* Set our traps. */ -+ /* This needs to be done more finely grained again, paired in -+ * a before/after in kgdb_handle_exception(...) -- Tom */ -+ set_debug_traps(); -+ notifier_chain_register(&mips_die_chain, &kgdb_notifier); -+ -+ return 0; -+} -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/kernel/kgdb_handler.S linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/kgdb_handler.S ---- linux-2.6.18-53.1.14/arch/mips/kernel/kgdb_handler.S 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/kgdb_handler.S 2008-06-10 15:38:24.000000000 +0400 -@@ -0,0 +1,57 @@ -+/* -+ * arch/mips/kernel/kgdb_handler.S -+ * -+ * Copyright (C) 2004-2005 MontaVista Software Inc. -+ * Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * version 2. This program is licensed "as is" without any warranty of any -+ * kind, whether express or implied. -+ */ -+ -+/* -+ * Trap Handler for the new KGDB framework. The main KGDB handler is -+ * handle_exception that will be called from here -+ * -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+ .align 5 -+ NESTED(trap_low, PT_SIZE, sp) -+ .set noat -+ .set noreorder -+ -+ /* -+ * Check for privileged instructions in user mode. For -+ * this, check the cu0 bit in the CPU status register. -+ */ -+ mfc0 k0, CP0_STATUS -+ sll k0, 3 -+ bltz k0, 1f -+ move k1, sp -+ -+ /* -+ * GDB userland from within KGDB. If a user mode address -+ * then jump to the saved exception handler -+ */ -+ mfc0 k1, CP0_CAUSE -+ andi k1, k1, 0x7c -+ PTR_L k0, saved_vectors(k1) -+ jr k0 -+ nop -+1: -+ SAVE_ALL -+ .set at -+ .set reorder -+ move a0, sp -+ jal handle_exception -+ j ret_from_exception -+ END(trap_low) -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/kernel/traps.c linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/traps.c ---- linux-2.6.18-53.1.14/arch/mips/kernel/traps.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/kernel/traps.c 2008-06-10 15:38:24.000000000 +0400 -@@ -10,6 +10,8 @@ - * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000, 01 MIPS Technologies, Inc. - * Copyright (C) 2002, 2003, 2004, 2005 Maciej W. Rozycki -+ * -+ * KGDB specific changes - Manish Lachwani (mlachwani@mvista.com) - */ - #include - #include -@@ -20,6 +22,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -40,6 +43,7 @@ - #include - #include - #include -+#include - - extern asmlinkage void handle_int(void); - extern asmlinkage void handle_tlbm(void); -@@ -78,6 +82,21 @@ void (*board_bind_eic_interrupt)(int irq - */ - #define MODULE_RANGE (8*1024*1024) - -+struct notifier_block *mips_die_chain; -+static spinlock_t die_notifier_lock = SPIN_LOCK_UNLOCKED; -+ -+int register_die_notifier(struct notifier_block *nb) -+{ -+ int err = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&die_notifier_lock, flags); -+ err = notifier_chain_register(&mips_die_chain, nb); -+ spin_unlock_irqrestore(&die_notifier_lock, flags); -+ -+ return err; -+} -+ - /* - * This routine abuses get_user()/put_user() to reference pointers - * with at least a bit of error checking ... -@@ -1387,6 +1406,11 @@ void __init trap_init(void) - extern char except_vec4; - unsigned long i; - -+#if defined(CONFIG_KGDB) -+ if (kgdb_early_setup) -+ return; /* Already done */ -+#endif -+ - if (cpu_has_veic || cpu_has_vint) - ebase = (unsigned long) alloc_bootmem_low_pages (0x200 + VECTORSPACING*64); - else -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/mips-boards/generic/Makefile linux-2.6.18-53.1.14.kgdb/arch/mips/mips-boards/generic/Makefile ---- linux-2.6.18-53.1.14/arch/mips/mips-boards/generic/Makefile 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/mips-boards/generic/Makefile 2008-06-10 15:38:24.000000000 +0400 -@@ -21,6 +21,5 @@ - obj-y := reset.o display.o init.o memory.o printf.o \ - cmdline.o time.o - obj-$(CONFIG_PCI) += pci.o --obj-$(CONFIG_KGDB) += gdb_hook.o - - EXTRA_AFLAGS := $(CFLAGS) -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/mips-boards/generic/init.c linux-2.6.18-53.1.14.kgdb/arch/mips/mips-boards/generic/init.c ---- linux-2.6.18-53.1.14/arch/mips/mips-boards/generic/init.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/mips-boards/generic/init.c 2008-06-10 15:38:24.000000000 +0400 -@@ -37,15 +37,6 @@ - - #include - --#ifdef CONFIG_KGDB --extern int rs_kgdb_hook(int, int); --extern int rs_putDebugChar(char); --extern char rs_getDebugChar(void); --extern int saa9730_kgdb_hook(int); --extern int saa9730_putDebugChar(char); --extern char saa9730_getDebugChar(void); --#endif -- - int prom_argc; - int *_prom_argv, *_prom_envp; - -@@ -172,58 +163,6 @@ static void __init console_config(void) - } - #endif - --#ifdef CONFIG_KGDB --void __init kgdb_config (void) --{ -- extern int (*generic_putDebugChar)(char); -- extern char (*generic_getDebugChar)(void); -- char *argptr; -- int line, speed; -- -- argptr = prom_getcmdline(); -- if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) { -- argptr += strlen("kgdb=ttyS"); -- if (*argptr != '0' && *argptr != '1') -- printk("KGDB: Unknown serial line /dev/ttyS%c, " -- "falling back to /dev/ttyS1\n", *argptr); -- line = *argptr == '0' ? 0 : 1; -- printk("KGDB: Using serial line /dev/ttyS%d for session\n", line); -- -- speed = 0; -- if (*++argptr == ',') -- { -- int c; -- while ((c = *++argptr) && ('0' <= c && c <= '9')) -- speed = speed * 10 + c - '0'; -- } --#ifdef CONFIG_MIPS_ATLAS -- if (line == 1) { -- speed = saa9730_kgdb_hook(speed); -- generic_putDebugChar = saa9730_putDebugChar; -- generic_getDebugChar = saa9730_getDebugChar; -- } -- else --#endif -- { -- speed = rs_kgdb_hook(line, speed); -- generic_putDebugChar = rs_putDebugChar; -- generic_getDebugChar = rs_getDebugChar; -- } -- -- prom_printf("KGDB: Using serial line /dev/ttyS%d at %d for session, " -- "please connect your debugger\n", line ? 1 : 0, speed); -- -- { -- char *s; -- for (s = "Please connect GDB to this port\r\n"; *s; ) -- generic_putDebugChar (*s++); -- } -- -- /* Breakpoint is invoked after interrupts are initialised */ -- } --} --#endif -- - void __init mips_nmi_setup (void) - { - void *base; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/mips-boards/malta/malta_setup.c linux-2.6.18-53.1.14.kgdb/arch/mips/mips-boards/malta/malta_setup.c ---- linux-2.6.18-53.1.14/arch/mips/mips-boards/malta/malta_setup.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/mips-boards/malta/malta_setup.c 2008-06-10 15:38:24.000000000 +0400 -@@ -46,10 +46,6 @@ extern void mips_reboot_setup(void); - extern void mips_time_init(void); - extern unsigned long mips_rtc_get_time(void); - --#ifdef CONFIG_KGDB --extern void kgdb_config(void); --#endif -- - struct resource standard_io_resources[] = { - { .name = "dma1", .start = 0x00, .end = 0x1f, .flags = IORESOURCE_BUSY }, - { .name = "timer", .start = 0x40, .end = 0x5f, .flags = IORESOURCE_BUSY }, -@@ -124,10 +120,6 @@ void __init plat_mem_setup(void) - */ - enable_dma(4); - --#ifdef CONFIG_KGDB -- kgdb_config (); --#endif -- - if ((mips_revision_corid == MIPS_REVISION_CORID_BONITO64) || - (mips_revision_corid == MIPS_REVISION_CORID_CORE_20K) || - (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL_BON)) { -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/mm/extable.c linux-2.6.18-53.1.14.kgdb/arch/mips/mm/extable.c ---- linux-2.6.18-53.1.14/arch/mips/mm/extable.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/mm/extable.c 2008-06-10 15:38:24.000000000 +0400 -@@ -3,6 +3,7 @@ - */ - #include - #include -+#include - #include - #include - -@@ -16,6 +17,12 @@ int fixup_exception(struct pt_regs *regs - - return 1; - } -+#ifdef CONFIG_KGDB -+ if (atomic_read(&debugger_active) && kgdb_may_fault) -+ /* Restore our previous state. */ -+ kgdb_fault_longjmp(kgdb_fault_jmp_regs); -+ /* Not reached. */ -+#endif - - return 0; - } -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/sibyte/cfe/setup.c linux-2.6.18-53.1.14.kgdb/arch/mips/sibyte/cfe/setup.c ---- linux-2.6.18-53.1.14/arch/mips/sibyte/cfe/setup.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/sibyte/cfe/setup.c 2008-06-10 15:38:24.000000000 +0400 -@@ -58,10 +58,6 @@ int cfe_cons_handle; - extern unsigned long initrd_start, initrd_end; - #endif - --#ifdef CONFIG_KGDB --extern int kgdb_port; --#endif -- - static void ATTRIB_NORET cfe_linux_exit(void *arg) - { - int warm = *(int *)arg; -@@ -242,9 +238,6 @@ void __init prom_init(void) - int argc = fw_arg0; - char **envp = (char **) fw_arg2; - int *prom_vec = (int *) fw_arg3; --#ifdef CONFIG_KGDB -- char *arg; --#endif - - _machine_restart = cfe_linux_restart; - _machine_halt = cfe_linux_halt; -@@ -308,13 +301,6 @@ void __init prom_init(void) - } - } - --#ifdef CONFIG_KGDB -- if ((arg = strstr(arcs_cmdline,"kgdb=duart")) != NULL) -- kgdb_port = (arg[10] == '0') ? 0 : 1; -- else -- kgdb_port = 1; --#endif -- - #ifdef CONFIG_BLK_DEV_INITRD - { - char *ptr; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/sibyte/sb1250/Makefile linux-2.6.18-53.1.14.kgdb/arch/mips/sibyte/sb1250/Makefile ---- linux-2.6.18-53.1.14/arch/mips/sibyte/sb1250/Makefile 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/sibyte/sb1250/Makefile 2008-06-10 15:38:24.000000000 +0400 -@@ -4,5 +4,6 @@ obj-$(CONFIG_SMP) += smp.o - obj-$(CONFIG_SIBYTE_TBPROF) += bcm1250_tbprof.o - obj-$(CONFIG_SIBYTE_STANDALONE) += prom.o - obj-$(CONFIG_SIBYTE_BUS_WATCHER) += bus_watcher.o -+obj-$(CONFIG_KGDB_SIBYTE) += kgdb_sibyte.o - - EXTRA_AFLAGS := $(CFLAGS) -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/sibyte/sb1250/irq.c linux-2.6.18-53.1.14.kgdb/arch/mips/sibyte/sb1250/irq.c ---- linux-2.6.18-53.1.14/arch/mips/sibyte/sb1250/irq.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/sibyte/sb1250/irq.c 2008-06-10 15:38:24.000000000 +0400 -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -59,16 +60,6 @@ static void sb1250_set_affinity(unsigned - extern unsigned long ldt_eoi_space; - #endif - --#ifdef CONFIG_KGDB --static int kgdb_irq; -- --/* Default to UART1 */ --int kgdb_port = 1; --#ifdef CONFIG_SIBYTE_SB1250_DUART --extern char sb1250_duart_present[]; --#endif --#endif -- - static struct irq_chip sb1250_irq_type = { - .typename = "SB1250-IMR", - .startup = startup_sb1250_irq, -@@ -324,6 +315,11 @@ void __init arch_init_irq(void) - unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 | - STATUSF_IP1 | STATUSF_IP0; - -+#ifdef CONFIG_KGDB -+ if (kgdb_early_setup) -+ return; -+#endif -+ - /* Default everything to IP2 */ - for (i = 0; i < SB1250_NR_IRQS; i++) { /* was I0 */ - __raw_writeq(IMR_IP2_VAL, -@@ -375,50 +371,6 @@ void __init arch_init_irq(void) - /* Enable necessary IPs, disable the rest */ - change_c0_status(ST0_IM, imask); - --#ifdef CONFIG_KGDB -- if (kgdb_flag) { -- kgdb_irq = K_INT_UART_0 + kgdb_port; -- --#ifdef CONFIG_SIBYTE_SB1250_DUART -- sb1250_duart_present[kgdb_port] = 0; --#endif -- /* Setup uart 1 settings, mapper */ -- __raw_writeq(M_DUART_IMR_BRK, -- IOADDR(A_DUART_IMRREG(kgdb_port))); -- -- sb1250_steal_irq(kgdb_irq); -- __raw_writeq(IMR_IP6_VAL, -- IOADDR(A_IMR_REGISTER(0, -- R_IMR_INTERRUPT_MAP_BASE) + -- (kgdb_irq << 3))); -- sb1250_unmask_irq(0, kgdb_irq); -- } --#endif --} -- --#ifdef CONFIG_KGDB -- --#include -- --#define duart_out(reg, val) csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg))) --#define duart_in(reg) csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg))) -- --static void sb1250_kgdb_interrupt(struct pt_regs *regs) --{ -- /* -- * Clear break-change status (allow some time for the remote -- * host to stop the break, since we would see another -- * interrupt on the end-of-break too) -- */ -- kstat_this_cpu.irqs[kgdb_irq]++; -- mdelay(500); -- duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT | -- M_DUART_RX_EN | M_DUART_TX_EN); -- set_async_breakpoint(®s->cp0_epc); --} -- --#endif /* CONFIG_KGDB */ -- - static inline int dclz(unsigned long long x) - { - int lz; -@@ -473,7 +425,7 @@ asmlinkage void plat_irq_dispatch(struct - sb1250_mailbox_interrupt(regs); - #endif - --#ifdef CONFIG_KGDB -+#ifdef CONFIG_KGDB_SIBYTE - else if (pending & CAUSEF_IP6) /* KGDB (uart 1) */ - sb1250_kgdb_interrupt(regs); - #endif -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/sibyte/sb1250/kgdb_sibyte.c linux-2.6.18-53.1.14.kgdb/arch/mips/sibyte/sb1250/kgdb_sibyte.c ---- linux-2.6.18-53.1.14/arch/mips/sibyte/sb1250/kgdb_sibyte.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/sibyte/sb1250/kgdb_sibyte.c 2008-06-10 15:38:24.000000000 +0400 -@@ -0,0 +1,164 @@ -+/* -+ * arch/mips/sibyte/sb1250/kgdb_sibyte.c -+ * -+ * Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com -+ * -+ * 2004 (c) MontaVista Software, Inc. This file is licensed under -+ * the terms of the GNU General Public License version 2. This program -+ * is licensed "as is" without any warranty of any kind, whether express -+ * or implied. -+ */ -+ -+/* -+ * Support for KGDB on the Broadcom Sibyte. The SWARM board -+ * for example does not have a 8250/16550 compatible serial -+ * port. Hence, we need to have a driver for the serial -+ * ports to handle KGDB. This board needs nothing in addition -+ * to what is normally provided by the gdb portion of the stub. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+int kgdb_port = 1; -+static int kgdb_irq; -+ -+extern char sb1250_duart_present[]; -+extern int sb1250_steal_irq(int irq); -+ -+/* Forward declarations. */ -+static void kgdbsibyte_init_duart(void); -+static int kgdb_init_io(void); -+ -+#define IMR_IP6_VAL K_INT_MAP_I4 -+#define duart_out(reg, val) csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg))) -+#define duart_in(reg) csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg))) -+ -+static void kgdb_swarm_write_char(int c) -+{ -+ while ((duart_in(R_DUART_STATUS) & M_DUART_TX_RDY) == 0) ; -+ duart_out(R_DUART_TX_HOLD, c); -+} -+ -+static int kgdb_swarm_read_char(void) -+{ -+ int ret_char; -+ unsigned int status; -+ -+ status = duart_in(R_DUART_STATUS); -+ while ((status & M_DUART_RX_RDY) == 0) { -+ status = duart_in(R_DUART_STATUS); -+ } -+ -+ /* -+ * Check for framing error -+ */ -+ if (status & M_DUART_FRM_ERR) { -+ kgdbsibyte_init_duart(); -+ kgdb_swarm_write_char('-'); -+ return '-'; -+ } -+ -+ ret_char = duart_in(R_DUART_RX_HOLD); -+ -+ return ret_char; -+} -+ -+void sb1250_kgdb_interrupt(struct pt_regs *regs) -+{ -+ int kgdb_irq = K_INT_UART_0 + kgdb_port; -+ /* -+ * Clear break-change status (allow some time for the remote -+ * host to stop the break, since we would see another -+ * interrupt on the end-of-break too) -+ */ -+ kstat_this_cpu.irqs[kgdb_irq]++; -+ mdelay(500); -+ duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT | -+ M_DUART_RX_EN | M_DUART_TX_EN); -+ if (kgdb_io_ops.init != kgdb_init_io) { -+ /* Throw away the data if another I/O routine is -+ * active. -+ */ -+ unsigned int status; -+ -+ status = duart_in(R_DUART_STATUS); -+ while ((status & M_DUART_RX_RDY) == 0) { -+ status = duart_in(R_DUART_STATUS); -+ } -+ /* -+ * Check for framing error -+ */ -+ if (status & M_DUART_FRM_ERR) { -+ kgdbsibyte_init_duart(); -+ } -+ duart_in(R_DUART_RX_HOLD); -+ } else -+ breakpoint(); -+ -+} -+ -+/* -+ * We use port #1 and we set it for 115200 BAUD, 8n1. -+ */ -+static void kgdbsibyte_init_duart(void) -+{ -+ /* Set 8n1. */ -+ duart_out(R_DUART_MODE_REG_1, -+ V_DUART_BITS_PER_CHAR_8 | V_DUART_PARITY_MODE_NONE); -+ duart_out(R_DUART_MODE_REG_2, M_DUART_STOP_BIT_LEN_1); -+ /* Set baud rate of 115200. */ -+ duart_out(R_DUART_CLK_SEL, V_DUART_BAUD_RATE(115200)); -+ /* Enable rx and tx */ -+ duart_out(R_DUART_CMD, M_DUART_RX_EN | M_DUART_TX_EN); -+} -+ -+static int kgdb_init_io(void) -+{ -+#ifdef CONFIG_SIBYTE_SB1250_DUART -+ sb1250_duart_present[kgdb_port] = 0; -+#endif -+ -+ kgdbsibyte_init_duart(); -+ -+ return 0; -+} -+ -+/* -+ * Hookup our IRQ line. We will already have been initialized a -+ * this point. -+ */ -+static void __init kgdbsibyte_hookup_irq(void) -+{ -+ /* Steal the IRQ. */ -+ kgdb_irq = K_INT_UART_0 + kgdb_port; -+ -+ /* Setup uart 1 settings, mapper */ -+ __raw_writeq(M_DUART_IMR_BRK, IOADDR(A_DUART_IMRREG(kgdb_port))); -+ -+ sb1250_steal_irq(kgdb_irq); -+ -+ __raw_writeq(IMR_IP6_VAL, -+ IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) + -+ (kgdb_irq << 3))); -+ -+ sb1250_unmask_irq(0, kgdb_irq); -+} -+ -+struct kgdb_io kgdb_io_ops = { -+ .read_char = kgdb_swarm_read_char, -+ .write_char = kgdb_swarm_write_char, -+ .init = kgdb_init_io, -+ .late_init = kgdbsibyte_hookup_irq, -+ .pre_exception = NULL, -+ .post_exception = NULL -+}; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/sibyte/swarm/Makefile linux-2.6.18-53.1.14.kgdb/arch/mips/sibyte/swarm/Makefile ---- linux-2.6.18-53.1.14/arch/mips/sibyte/swarm/Makefile 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/sibyte/swarm/Makefile 2008-06-10 15:38:24.000000000 +0400 -@@ -1,3 +1 @@ - lib-y = setup.o rtc_xicor1241.o rtc_m41t81.o -- --lib-$(CONFIG_KGDB) += dbg_io.o -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/sibyte/swarm/dbg_io.c linux-2.6.18-53.1.14.kgdb/arch/mips/sibyte/swarm/dbg_io.c ---- linux-2.6.18-53.1.14/arch/mips/sibyte/swarm/dbg_io.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/sibyte/swarm/dbg_io.c 1970-01-01 03:00:00.000000000 +0300 -@@ -1,76 +0,0 @@ --/* -- * kgdb debug routines for SiByte boards. -- * -- * Copyright (C) 2001 MontaVista Software Inc. -- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net -- * -- * This program is free software; you can redistribute it and/or modify it -- * under the terms of the GNU General Public License as published by the -- * Free Software Foundation; either version 2 of the License, or (at your -- * option) any later version. -- * -- */ -- --/* -------------------- BEGINNING OF CONFIG --------------------- */ -- --#include --#include --#include --#include --#include --#include --#include -- --/* -- * We use the second serial port for kgdb traffic. -- * 115200, 8, N, 1. -- */ -- --#define BAUD_RATE 115200 --#define CLK_DIVISOR V_DUART_BAUD_RATE(BAUD_RATE) --#define DATA_BITS V_DUART_BITS_PER_CHAR_8 /* or 7 */ --#define PARITY V_DUART_PARITY_MODE_NONE /* or even */ --#define STOP_BITS M_DUART_STOP_BIT_LEN_1 /* or 2 */ -- --static int duart_initialized = 0; /* 0: need to be init'ed by kgdb */ -- --/* -------------------- END OF CONFIG --------------------- */ --extern int kgdb_port; -- --#define duart_out(reg, val) csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg))) --#define duart_in(reg) csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg))) -- --void putDebugChar(unsigned char c); --unsigned char getDebugChar(void); --static void --duart_init(int clk_divisor, int data, int parity, int stop) --{ -- duart_out(R_DUART_MODE_REG_1, data | parity); -- duart_out(R_DUART_MODE_REG_2, stop); -- duart_out(R_DUART_CLK_SEL, clk_divisor); -- -- duart_out(R_DUART_CMD, M_DUART_RX_EN | M_DUART_TX_EN); /* enable rx and tx */ --} -- --void --putDebugChar(unsigned char c) --{ -- if (!duart_initialized) { -- duart_initialized = 1; -- duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS); -- } -- while ((duart_in(R_DUART_STATUS) & M_DUART_TX_RDY) == 0); -- duart_out(R_DUART_TX_HOLD, c); --} -- --unsigned char --getDebugChar(void) --{ -- if (!duart_initialized) { -- duart_initialized = 1; -- duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS); -- } -- while ((duart_in(R_DUART_STATUS) & M_DUART_RX_RDY) == 0) ; -- return duart_in(R_DUART_RX_HOLD); --} -- -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/mips/tx4938/common/Makefile linux-2.6.18-53.1.14.kgdb/arch/mips/tx4938/common/Makefile ---- linux-2.6.18-53.1.14/arch/mips/tx4938/common/Makefile 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/mips/tx4938/common/Makefile 2008-06-10 15:38:24.000000000 +0400 -@@ -7,5 +7,5 @@ - # - - obj-y += prom.o setup.o irq.o rtc_rx5c348.o --obj-$(CONFIG_KGDB) += dbgio.o -+obj-$(CONFIG_KGDB_8250) += dbgio.o - -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/powerpc/Kconfig.debug linux-2.6.18-53.1.14.kgdb/arch/powerpc/Kconfig.debug ---- linux-2.6.18-53.1.14/arch/powerpc/Kconfig.debug 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/powerpc/Kconfig.debug 2008-06-10 15:38:14.000000000 +0400 -@@ -18,52 +18,9 @@ config DEBUG_STACK_USAGE - - This option will slow down process creation somewhat. - --config DEBUGGER -- bool "Enable debugger hooks" -- depends on DEBUG_KERNEL -- help -- Include in-kernel hooks for kernel debuggers. Unless you are -- intending to debug the kernel, say N here. -- --config KGDB -- bool "Include kgdb kernel debugger" -- depends on DEBUGGER && (BROKEN || PPC_GEN550 || 4xx) -- select DEBUG_INFO -- help -- Include in-kernel hooks for kgdb, the Linux kernel source level -- debugger. See for more information. -- Unless you are intending to debug the kernel, say N here. -- --choice -- prompt "Serial Port" -- depends on KGDB -- default KGDB_TTYS1 -- --config KGDB_TTYS0 -- bool "ttyS0" -- --config KGDB_TTYS1 -- bool "ttyS1" -- --config KGDB_TTYS2 -- bool "ttyS2" -- --config KGDB_TTYS3 -- bool "ttyS3" -- --endchoice -- --config KGDB_CONSOLE -- bool "Enable serial console thru kgdb port" -- depends on KGDB && 8xx || CPM2 -- help -- If you enable this, all serial console messages will be sent -- over the gdb stub. -- If unsure, say N. -- - config XMON - bool "Include xmon kernel debugger" -- depends on DEBUGGER && !PPC_ISERIES -+ depends on DEBUG_KERNEL && !PPC_ISERIES - help - Include in-kernel hooks for the xmon kernel monitor/debugger. - Unless you are intending to debug the kernel, say N here. -@@ -82,6 +39,11 @@ config XMON_DEFAULT - xmon is normally disabled unless booted with 'xmon=on'. - Use 'xmon=off' to disable xmon init during runtime. - -+config DEBUGGER -+ bool -+ depends on KGDB || XMON -+ default y -+ - config IRQSTACKS - bool "Use separate kernel stacks when processing interrupts" - depends on PPC64 -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/powerpc/kernel/Makefile linux-2.6.18-53.1.14.kgdb/arch/powerpc/kernel/Makefile ---- linux-2.6.18-53.1.14/arch/powerpc/kernel/Makefile 2008-03-06 05:54:47.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/powerpc/kernel/Makefile 2008-06-10 15:38:14.000000000 +0400 -@@ -59,6 +59,7 @@ obj-$(CONFIG_PPC64) += misc_64.o dma_64 - obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o - obj-$(CONFIG_MODULES) += ppc_ksyms.o - obj-$(CONFIG_BOOTX_TEXT) += btext.o -+obj-$(CONFIG_KGDB) += kgdb.o - obj-$(CONFIG_SMP) += smp.o - obj-$(CONFIG_KPROBES) += kprobes.o - obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/powerpc/kernel/kgdb.c linux-2.6.18-53.1.14.kgdb/arch/powerpc/kernel/kgdb.c ---- linux-2.6.18-53.1.14/arch/powerpc/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/powerpc/kernel/kgdb.c 2008-06-10 15:38:14.000000000 +0400 -@@ -0,0 +1,568 @@ -+/* -+ * arch/powerpc/kernel/kgdb.c -+ * -+ * PowerPC backend to the KGDB stub. -+ * -+ * Maintainer: Tom Rini -+ * -+ * Copied from arch/ppc/kernel/kgdb.c, updated for ppc64 -+ * -+ * Copyright (C) 1996 Paul Mackerras (setjmp/longjmp) -+ * 1998 (c) Michael AK Tesch (tesch@cs.wisc.edu) -+ * Copyright (C) 2003 Timesys Corporation. -+ * Copyright (C) 2004-2006 MontaVista Software, Inc. -+ * PPC64 Mods (C) 2005 Frank Rowand (frowand@mvista.com) -+ * PPC32 support restored by Vitaly Wool and -+ * Sergei Shtylyov -+ * -+ * This file is licensed under the terms of the GNU General Public License -+ * version 2. This program as licensed "as is" without any warranty of any -+ * kind, whether express or implied. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * This table contains the mapping between PowerPC hardware trap types, and -+ * signals, which are primarily what GDB understands. GDB and the kernel -+ * don't always agree on values, so we use constants taken from gdb-6.2. -+ */ -+static struct hard_trap_info -+{ -+ unsigned int tt; /* Trap type code for powerpc */ -+ unsigned char signo; /* Signal that we map this trap into */ -+} hard_trap_info[] = { -+ { 0x0100, 0x02 /* SIGINT */ }, /* system reset */ -+ { 0x0200, 0x0b /* SIGSEGV */ }, /* machine check */ -+ { 0x0300, 0x0b /* SIGSEGV */ }, /* data access */ -+ { 0x0400, 0x0b /* SIGSEGV */ }, /* instruction access */ -+ { 0x0500, 0x02 /* SIGINT */ }, /* external interrupt */ -+ { 0x0600, 0x0a /* SIGBUS */ }, /* alignment */ -+ { 0x0700, 0x05 /* SIGTRAP */ }, /* program check */ -+ { 0x0800, 0x08 /* SIGFPE */ }, /* fp unavailable */ -+ { 0x0900, 0x0e /* SIGALRM */ }, /* decrementer */ -+ { 0x0c00, 0x14 /* SIGCHLD */ }, /* system call */ -+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) -+ { 0x2002, 0x05 /* SIGTRAP */ }, /* debug */ -+#if defined(CONFIG_FSL_BOOKE) -+ { 0x2010, 0x08 /* SIGFPE */ }, /* spe unavailable */ -+ { 0x2020, 0x08 /* SIGFPE */ }, /* spe unavailable */ -+ { 0x2030, 0x08 /* SIGFPE */ }, /* spe fp data */ -+ { 0x2040, 0x08 /* SIGFPE */ }, /* spe fp data */ -+ { 0x2050, 0x08 /* SIGFPE */ }, /* spe fp round */ -+ { 0x2060, 0x0e /* SIGILL */ }, /* performace monitor */ -+ { 0x2900, 0x08 /* SIGFPE */ }, /* apu unavailable */ -+ { 0x3100, 0x0e /* SIGALRM */ }, /* fixed interval timer */ -+ { 0x3200, 0x02 /* SIGINT */ }, /* watchdog */ -+#else -+ { 0x1000, 0x0e /* SIGALRM */ }, /* programmable interval timer */ -+ { 0x1010, 0x0e /* SIGALRM */ }, /* fixed interval timer */ -+ { 0x1020, 0x02 /* SIGINT */ }, /* watchdog */ -+ { 0x2010, 0x08 /* SIGFPE */ }, /* fp unavailable */ -+ { 0x2020, 0x08 /* SIGFPE */ }, /* ap unavailable */ -+#endif -+#else -+ { 0x0d00, 0x05 /* SIGTRAP */ }, /* single-step */ -+#if defined(CONFIG_8xx) -+ { 0x1000, 0x04 /* SIGILL */ }, /* software emulation */ -+#else -+ { 0x0f00, 0x04 /* SIGILL */ }, /* performance monitor */ -+ { 0x0f20, 0x08 /* SIGFPE */ }, /* altivec unavailable */ -+ { 0x1300, 0x05 /* SIGTRAP */ }, /* instruction address break */ -+#if defined(CONFIG_PPC64) -+ { 0x1200, 0x05 /* SIGILL */ }, /* system error */ -+ { 0x1500, 0x04 /* SIGILL */ }, /* soft patch */ -+ { 0x1600, 0x04 /* SIGILL */ }, /* maintenance */ -+ { 0x1700, 0x08 /* SIGFPE */ }, /* altivec assist */ -+ { 0x1800, 0x04 /* SIGILL */ }, /* thermal */ -+#else -+ { 0x1400, 0x02 /* SIGINT */ }, /* SMI */ -+ { 0x1600, 0x08 /* SIGFPE */ }, /* altivec assist */ -+ { 0x1700, 0x04 /* SIGILL */ }, /* TAU */ -+ { 0x2000, 0x05 /* SIGTRAP */ }, /* run mode */ -+#endif -+#endif -+#endif -+ { 0x0000, 0x00 } /* Must be last */ -+}; -+ -+extern atomic_t cpu_doing_single_step; -+ -+static int computeSignal(unsigned 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 */ -+} -+ -+static int kgdb_call_nmi_hook(struct pt_regs *regs) -+{ -+ kgdb_nmihook(smp_processor_id(), regs); -+ return 0; -+} -+ -+#ifdef CONFIG_SMP -+void kgdb_roundup_cpus(unsigned long flags) -+{ -+ smp_send_debugger_break(MSG_ALL_BUT_SELF); -+} -+#endif -+ -+/* KGDB functions to use existing PowerPC64 hooks. */ -+static int kgdb_debugger(struct pt_regs *regs) -+{ -+ return kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs); -+} -+ -+static int kgdb_breakpoint(struct pt_regs *regs) -+{ -+ if (user_mode(regs)) -+ return 0; -+ -+ kgdb_handle_exception(0, SIGTRAP, 0, regs); -+ -+ if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr)) -+ regs->nip += 4; -+ -+ return 1; -+} -+ -+static int kgdb_singlestep(struct pt_regs *regs) -+{ -+ struct thread_info *thread_info, *exception_thread_info; -+ if (user_mode(regs)) -+ return 0; -+ /* -+ * On Book E and perhaps other processsors, singlestep is handled on -+ * the critical exception stack. This causes current_thread_info() -+ * to fail, since it it locates the thread_info by masking off -+ * the low bits of the current stack pointer. We work around -+ * this issue by copying the thread_info from the kernel stack -+ * before calling kgdb_handle_exception, and copying it back -+ * afterwards. On most processors the copy is avoided since -+ * exception_thread_info == thread_info. -+ */ -+ thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1)); -+ exception_thread_info = current_thread_info(); -+ -+ if (thread_info != exception_thread_info) -+ memcpy(exception_thread_info, thread_info, sizeof *thread_info); -+ -+ kgdb_handle_exception(0, SIGTRAP, 0, regs); -+ -+ if (thread_info != exception_thread_info) -+ memcpy(thread_info, exception_thread_info, sizeof *thread_info); -+ -+ return 1; -+} -+ -+int kgdb_iabr_match(struct pt_regs *regs) -+{ -+ if (user_mode(regs)) -+ return 0; -+ -+ kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs); -+ return 1; -+} -+ -+int kgdb_dabr_match(struct pt_regs *regs) -+{ -+ if (user_mode(regs)) -+ return 0; -+ -+ kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs); -+ return 1; -+} -+ -+#define PACK64(ptr,src) do { *(ptr++) = (src); } while(0) -+ -+#define PACK32(ptr,src) do { \ -+ u32 *ptr32; \ -+ ptr32 = (u32 *)ptr; \ -+ *(ptr32++) = (src); \ -+ ptr = (unsigned long *)ptr32; \ -+ } while(0) -+ -+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) -+{ -+ unsigned long *ptr = gdb_regs; -+ int reg; -+ -+ memset(gdb_regs, 0, NUMREGBYTES); -+ -+ for (reg = 0; reg < 32; reg++) -+ PACK64(ptr, regs->gpr[reg]); -+ -+#ifdef CONFIG_FSL_BOOKE -+#ifdef CONFIG_SPE -+ for (reg = 0; reg < 32; reg++) -+ PACK64(ptr, current->thread.evr[reg]); -+#else -+ ptr += 32; -+#endif -+#else -+ /* fp registers not used by kernel, leave zero */ -+ ptr += 32 * 8 / sizeof(long); -+#endif -+ -+ PACK64(ptr, regs->nip); -+ PACK64(ptr, regs->msr); -+ PACK32(ptr, regs->ccr); -+ PACK64(ptr, regs->link); -+ PACK64(ptr, regs->ctr); -+ PACK32(ptr, regs->xer); -+ -+#if 0 -+ Following are in struct thread_struct, not struct pt_regs, -+ ignoring for now since kernel does not use them. Would it -+ make sense to get them from the thread that kgdb is set to? -+ -+ If this code is enabled, update the definition of NUMREGBYTES to -+ include the vector registers and vector state registers. -+ -+ PACK32(ptr, current->thread->fpscr); -+ -+ /* vr registers not used by kernel, leave zero */ -+ ptr += 32 * 16 / sizeof(long); -+ -+#ifdef CONFIG_ALTIVEC -+ PACK32(ptr, current->thread->vscr); -+ PACK32(ptr, current->thread->vrsave); -+#else -+ ptr += 2 * 4 / sizeof(long); -+#endif -+#else -+#ifdef CONFIG_FSL_BOOKE -+#ifdef CONFIG_SPE -+ /* u64 acc */ -+ PACK32(ptr, current->thread.acc >> 32); -+ PACK32(ptr, current->thread.acc & 0xffffffff); -+ PACK64(ptr, current->thread.spefscr); -+#else -+ ptr += 2 + 1; -+#endif -+#else -+ /* fpscr not used by kernel, leave zero */ -+ PACK32(ptr, 0); -+#endif -+#endif -+ -+ BUG_ON((unsigned long)ptr > -+ (unsigned long)(((void *)gdb_regs) + NUMREGBYTES)); -+} -+ -+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) -+{ -+ struct pt_regs *regs = (struct pt_regs *)(p->thread.ksp + -+ STACK_FRAME_OVERHEAD); -+ unsigned long *ptr = gdb_regs; -+ int reg; -+ -+ memset(gdb_regs, 0, NUMREGBYTES); -+ -+ /* Regs GPR0-2 */ -+ for (reg = 0; reg < 3; reg++) -+ PACK64(ptr, regs->gpr[reg]); -+ -+ /* Regs GPR3-13 are caller saved, not in regs->gpr[] */ -+ ptr += 11; -+ -+ /* Regs GPR14-31 */ -+ for (reg = 14; reg < 32; reg++) -+ PACK64(ptr, regs->gpr[reg]); -+ -+#ifdef CONFIG_FSL_BOOKE -+#ifdef CONFIG_SPE -+ for (reg = 0; reg < 32; reg++) -+ PACK64(ptr, p->thread.evr[reg]); -+#else -+ ptr += 32; -+#endif -+#else -+ /* fp registers not used by kernel, leave zero */ -+ ptr += 32 * 8 / sizeof(long); -+#endif -+ PACK64(ptr, regs->nip); -+ PACK64(ptr, regs->msr); -+ PACK32(ptr, regs->ccr); -+ PACK64(ptr, regs->link); -+ PACK64(ptr, regs->ctr); -+ PACK32(ptr, regs->xer); -+ -+#if 0 -+ Following are in struct thread_struct, not struct pt_regs, -+ ignoring for now since kernel does not use them. Would it -+ make sense to get them from the thread that kgdb is set to? -+ -+ If this code is enabled, update the definition of NUMREGBYTES to -+ include the vector registers and vector state registers. -+ -+ PACK32(ptr, p->thread->fpscr); -+ -+ /* vr registers not used by kernel, leave zero */ -+ ptr += 32 * 16 / sizeof(long); -+ -+#ifdef CONFIG_ALTIVEC -+ PACK32(ptr, p->thread->vscr); -+ PACK32(ptr, p->thread->vrsave); -+#else -+ ptr += 2 * 4 / sizeof(long); -+#endif -+#else -+#ifdef CONFIG_FSL_BOOKE -+#ifdef CONFIG_SPE -+ /* u64 acc */ -+ PACK32(ptr, p->thread.acc >> 32); -+ PACK32(ptr, p->thread.acc & 0xffffffff); -+ PACK64(ptr, p->thread.spefscr); -+#else -+ ptr += 2 + 1; -+#endif -+#else -+ /* fpscr not used by kernel, leave zero */ -+ PACK32(ptr, 0); -+#endif -+#endif -+ -+ BUG_ON((unsigned long)ptr > -+ (unsigned long)(((void *)gdb_regs) + NUMREGBYTES)); -+} -+ -+#define UNPACK64(dest,ptr) do { dest = *(ptr++); } while(0) -+ -+#define UNPACK32(dest,ptr) do { \ -+ u32 *ptr32; \ -+ ptr32 = (u32 *)ptr; \ -+ dest = *(ptr32++); \ -+ ptr = (unsigned long *)ptr32; \ -+ } while(0) -+ -+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs) -+{ -+ unsigned long *ptr = gdb_regs; -+ int reg; -+ -+#ifdef CONFIG_SPE -+ union { -+ u32 v32[2]; -+ u64 v64; -+ } acc; -+#endif -+ for (reg = 0; reg < 32; reg++) -+ UNPACK64(regs->gpr[reg], ptr); -+ -+#ifdef CONFIG_FSL_BOOKE -+#ifdef CONFIG_SPE -+ for (reg = 0; reg < 32; reg++) -+ UNPACK64(current->thread.evr[reg], ptr); -+#else -+ ptr += 32; -+#endif -+#else -+ /* fp registers not used by kernel, leave zero */ -+ ptr += 32 * 8 / sizeof(int); -+#endif -+ UNPACK64(regs->nip, ptr); -+ UNPACK64(regs->msr, ptr); -+ UNPACK32(regs->ccr, ptr); -+ UNPACK64(regs->link, ptr); -+ UNPACK64(regs->ctr, ptr); -+ UNPACK32(regs->xer, ptr); -+ -+#if 0 -+ Following are in struct thread_struct, not struct pt_regs, -+ ignoring for now since kernel does not use them. Would it -+ make sense to get them from the thread that kgdb is set to? -+ -+ If this code is enabled, update the definition of NUMREGBYTES to -+ include the vector registers and vector state registers. -+ -+ /* fpscr, vscr, vrsave not used by kernel, leave unchanged */ -+ -+ UNPACK32(current->thread->fpscr, ptr); -+ -+ /* vr registers not used by kernel, leave zero */ -+ ptr += 32 * 16 / sizeof(long); -+ -+ #ifdef CONFIG_ALTIVEC -+ UNPACK32(current->thread->vscr, ptr); -+ UNPACK32(current->thread->vrsave, ptr); -+#else -+ ptr += 2 * 4 / sizeof(long); -+#endif -+#else -+#ifdef CONFIG_FSL_BOOKE -+#ifdef CONFIG_SPE -+ /* u64 acc */ -+ UNPACK32(acc.v32[0], ptr); -+ UNPACK32(acc.v32[1], ptr); -+ current->thread.acc = acc.v64; -+ UNPACK64(current->thread.spefscr, ptr); -+#else -+ ptr += 2 + 1; -+#endif -+#endif -+#endif -+ -+ BUG_ON((unsigned long)ptr > -+ (unsigned long)(((void *)gdb_regs) + NUMREGBYTES)); -+} -+ -+/* -+ * This function does PowerPC specific procesing for interfacing to gdb. -+ */ -+int kgdb_arch_handle_exception(int vector, int signo, int err_code, -+ char *remcom_in_buffer, char *remcom_out_buffer, -+ struct pt_regs *linux_regs) -+{ -+ char *ptr = &remcom_in_buffer[1]; -+ unsigned long addr; -+ -+ switch (remcom_in_buffer[0]) { -+ /* -+ * sAA..AA Step one instruction from AA..AA -+ * This will return an error to gdb .. -+ */ -+ case 's': -+ case 'c': -+ /* handle the optional parameter */ -+ if (kgdb_hex2long(&ptr, &addr)) -+ linux_regs->nip = addr; -+ -+ atomic_set(&cpu_doing_single_step, -1); -+ /* set the trace bit if we're stepping */ -+ if (remcom_in_buffer[0] == 's') { -+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) -+ mtspr(SPRN_DBCR0, -+ mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM); -+ linux_regs->msr |= MSR_DE; -+#else -+ linux_regs->msr |= MSR_SE; -+#endif -+ debugger_step = 1; -+ if (kgdb_contthread) -+ atomic_set(&cpu_doing_single_step, -+ smp_processor_id()); -+ } -+ return 0; -+ } -+ -+ return -1; -+} -+ -+int kgdb_fault_setjmp(unsigned long *curr_context) -+{ -+#ifdef CONFIG_PPC32 -+ __asm__ __volatile__("mflr 0; stw 0,0(%0);\n\ -+ stw 1,4(%0); stw 2,8(%0);\n\ -+ mfcr 0; stw 0,12(%0);\n\ -+ stmw 13,16(%0)\n" : : "r" (curr_context)); -+#else -+ __asm__ __volatile__("mflr 0; std 0,0(%0)\n\ -+ std 1,8(%0)\n\ -+ std 2,16(%0)\n\ -+ mfcr 0; std 0,24(%0)\n\ -+ std 13,32(%0)\n\ -+ std 14,40(%0)\n\ -+ std 15,48(%0)\n\ -+ std 16,56(%0)\n\ -+ std 17,64(%0)\n\ -+ std 18,72(%0)\n\ -+ std 19,80(%0)\n\ -+ std 20,88(%0)\n\ -+ std 21,96(%0)\n\ -+ std 22,104(%0)\n\ -+ std 23,112(%0)\n\ -+ std 24,120(%0)\n\ -+ std 25,128(%0)\n\ -+ std 26,136(%0)\n\ -+ std 27,144(%0)\n\ -+ std 28,152(%0)\n\ -+ std 29,160(%0)\n\ -+ std 30,168(%0)\n\ -+ std 31,176(%0)\n" : : "r" (curr_context)); -+#endif -+ return 0; -+} -+ -+void kgdb_fault_longjmp(unsigned long *curr_context) -+{ -+#ifdef CONFIG_PPC32 -+ __asm__ __volatile__("lmw 13,16(%0);\n\ -+ lwz 0,12(%0); mtcrf 0x38,0;\n\ -+ lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);\n\ -+ mtlr 0; mr 3,1\n" : : "r" (curr_context)); -+#else -+ __asm__ __volatile__("ld 13,32(%0)\n\ -+ ld 14,40(%0)\n\ -+ ld 15,48(%0)\n\ -+ ld 16,56(%0)\n\ -+ ld 17,64(%0)\n\ -+ ld 18,72(%0)\n\ -+ ld 19,80(%0)\n\ -+ ld 20,88(%0)\n\ -+ ld 21,96(%0)\n\ -+ ld 22,104(%0)\n\ -+ ld 23,112(%0)\n\ -+ ld 24,120(%0)\n\ -+ ld 25,128(%0)\n\ -+ ld 26,136(%0)\n\ -+ ld 27,144(%0)\n\ -+ ld 28,152(%0)\n\ -+ ld 29,160(%0)\n\ -+ ld 30,168(%0)\n\ -+ ld 31,176(%0)\n\ -+ ld 0,24(%0)\n\ -+ mtcrf 0x38,0\n\ -+ ld 0,0(%0)\n\ -+ ld 1,8(%0)\n\ -+ ld 2,16(%0)\n\ -+ mtlr 0\n\ -+ mr 3,1\n" : : "r" (curr_context)); -+#endif -+} -+ -+/* -+ * Global data -+ */ -+struct kgdb_arch arch_kgdb_ops = { -+ .gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08}, -+}; -+ -+int kgdb_not_implemented(struct pt_regs *regs) -+{ -+ return 0; -+} -+ -+int kgdb_arch_init(void) -+{ -+#ifdef CONFIG_XMON -+#error Both XMON and KGDB selected in .config. Unselect one of them. -+#endif -+ -+ __debugger_ipi = kgdb_call_nmi_hook; -+ __debugger = kgdb_debugger; -+ __debugger_bpt = kgdb_breakpoint; -+ __debugger_sstep = kgdb_singlestep; -+ __debugger_iabr_match = kgdb_iabr_match; -+ __debugger_dabr_match = kgdb_dabr_match; -+ __debugger_fault_handler = kgdb_not_implemented; -+ -+ return 0; -+} -+ -+arch_initcall(kgdb_arch_init); -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/powerpc/kernel/legacy_serial.c linux-2.6.18-53.1.14.kgdb/arch/powerpc/kernel/legacy_serial.c ---- linux-2.6.18-53.1.14/arch/powerpc/kernel/legacy_serial.c 2008-03-06 05:54:47.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/powerpc/kernel/legacy_serial.c 2008-06-10 15:38:14.000000000 +0400 -@@ -11,6 +11,9 @@ - #include - #include - #include -+#ifdef CONFIG_KGDB_8250 -+#include -+#endif - - #undef DEBUG - -@@ -485,6 +488,9 @@ static int __init serial_dev_init(void) - fixup_port_pio(i, np, port); - if ((port->iotype == UPIO_MEM) || (port->iotype == UPIO_TSI)) - fixup_port_mmio(i, np, port); -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_platform_port(i, port); -+#endif - } - - DBG("Registering platform serial ports\n"); -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/powerpc/kernel/setup_32.c linux-2.6.18-53.1.14.kgdb/arch/powerpc/kernel/setup_32.c ---- linux-2.6.18-53.1.14/arch/powerpc/kernel/setup_32.c 2008-03-06 05:54:45.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/powerpc/kernel/setup_32.c 2008-06-10 15:38:14.000000000 +0400 -@@ -45,10 +45,6 @@ - - #define DBG(fmt...) - --#if defined CONFIG_KGDB --#include --#endif -- - extern void bootx_init(unsigned long r4, unsigned long phys); - - struct ide_machdep_calls ppc_ide_md; -@@ -251,18 +247,6 @@ void __init setup_arch(char **cmdline_p) - - xmon_setup(); - --#if defined(CONFIG_KGDB) -- if (ppc_md.kgdb_map_scc) -- ppc_md.kgdb_map_scc(); -- set_debug_traps(); -- if (strstr(cmd_line, "gdb")) { -- if (ppc_md.progress) -- ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000); -- printk("kgdb breakpoint activated\n"); -- breakpoint(); -- } --#endif -- - /* - * Set cache line size based on type of cpu as a default. - * Systems with OF can look in the properties on the cpu node(s) -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/powerpc/mm/fault.c linux-2.6.18-53.1.14.kgdb/arch/powerpc/mm/fault.c ---- linux-2.6.18-53.1.14/arch/powerpc/mm/fault.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/powerpc/mm/fault.c 2008-06-10 15:38:14.000000000 +0400 -@@ -28,6 +28,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -424,6 +425,13 @@ void bad_page_fault(struct pt_regs *regs - return; - } - -+#ifdef CONFIG_KGDB -+ if (atomic_read(&debugger_active) && kgdb_may_fault) -+ /* Restore our previous state. */ -+ kgdb_fault_longjmp(kgdb_fault_jmp_regs); -+ /* Not reached. */ -+#endif -+ - /* kernel has accessed a bad area */ - - printk(KERN_ALERT "Unable to handle kernel paging request for "); -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/powerpc/platforms/powermac/setup.c linux-2.6.18-53.1.14.kgdb/arch/powerpc/platforms/powermac/setup.c ---- linux-2.6.18-53.1.14/arch/powerpc/platforms/powermac/setup.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/powerpc/platforms/powermac/setup.c 2008-06-10 15:38:14.000000000 +0400 -@@ -98,8 +98,6 @@ extern struct machdep_calls pmac_md; - int sccdbg; - #endif - --extern void zs_kgdb_hook(int tty_num); -- - sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN; - EXPORT_SYMBOL(sys_ctrler); - -@@ -319,10 +317,6 @@ static void __init pmac_setup_arch(void) - l2cr_init(); - #endif /* CONFIG_PPC32 */ - --#ifdef CONFIG_KGDB -- zs_kgdb_hook(0); --#endif -- - find_via_cuda(); - find_via_pmu(); - smu_init(); -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/Kconfig.debug linux-2.6.18-53.1.14.kgdb/arch/ppc/Kconfig.debug ---- linux-2.6.18-53.1.14/arch/ppc/Kconfig.debug 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/Kconfig.debug 2008-06-10 15:38:14.000000000 +0400 -@@ -2,42 +2,6 @@ menu "Kernel hacking" - - source "lib/Kconfig.debug" - --config KGDB -- bool "Include kgdb kernel debugger" -- depends on DEBUG_KERNEL && (BROKEN || PPC_GEN550 || 4xx) -- select DEBUG_INFO -- help -- Include in-kernel hooks for kgdb, the Linux kernel source level -- debugger. See for more information. -- Unless you are intending to debug the kernel, say N here. -- --choice -- prompt "Serial Port" -- depends on KGDB -- default KGDB_TTYS1 -- --config KGDB_TTYS0 -- bool "ttyS0" -- --config KGDB_TTYS1 -- bool "ttyS1" -- --config KGDB_TTYS2 -- bool "ttyS2" -- --config KGDB_TTYS3 -- bool "ttyS3" -- --endchoice -- --config KGDB_CONSOLE -- bool "Enable serial console thru kgdb port" -- depends on KGDB && 8xx || CPM2 -- help -- If you enable this, all serial console messages will be sent -- over the gdb stub. -- If unsure, say N. -- - config XMON - bool "Include xmon kernel debugger" - depends on DEBUG_KERNEL -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/kernel/kgdb.c linux-2.6.18-53.1.14.kgdb/arch/ppc/kernel/kgdb.c ---- linux-2.6.18-53.1.14/arch/ppc/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/kernel/kgdb.c 2008-06-10 15:39:34.000000000 +0400 -@@ -0,0 +1,350 @@ -+/* -+ * arch/ppc/kernel/kgdb.c -+ * -+ * PowerPC backend to the KGDB stub. -+ * -+ * Maintainer: Tom Rini -+ * -+ * 1998 (c) Michael AK Tesch (tesch@cs.wisc.edu) -+ * Copyright (C) 2003 Timesys Corporation. -+ * 2004 (c) MontaVista Software, Inc. -+ * -+ * This file is licensed under the terms of the GNU General Public License -+ * version 2. This program as licensed "as is" without any warranty of any -+ * kind, whether express or implied. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * This table contains the mapping between PowerPC hardware trap types, and -+ * signals, which are primarily what GDB understands. GDB and the kernel -+ * don't always agree on values, so we use constants taken from gdb-6.2. -+ */ -+static struct hard_trap_info -+{ -+ unsigned int tt; /* Trap type code for powerpc */ -+ unsigned char signo; /* Signal that we map this trap into */ -+} hard_trap_info[] = { -+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) -+ { 0x0100, 0x02 /* SIGINT */ }, /* critical input interrupt */ -+ { 0x0200, 0x0b /* SIGSEGV */ }, /* machine check */ -+ { 0x0300, 0x0b /* SIGSEGV */ }, /* data storage */ -+ { 0x0400, 0x0a /* SIGBUS */ }, /* instruction storage */ -+ { 0x0500, 0x02 /* SIGINT */ }, /* interrupt */ -+ { 0x0600, 0x0a /* SIGBUS */ }, /* alignment */ -+ { 0x0700, 0x04 /* SIGILL */ }, /* program */ -+ { 0x0800, 0x04 /* SIGILL */ }, /* reserved */ -+ { 0x0900, 0x04 /* SIGILL */ }, /* reserved */ -+ { 0x0a00, 0x04 /* SIGILL */ }, /* reserved */ -+ { 0x0b00, 0x04 /* SIGILL */ }, /* reserved */ -+ { 0x0c00, 0x14 /* SIGCHLD */ }, /* syscall */ -+ { 0x0d00, 0x04 /* SIGILL */ }, /* reserved */ -+ { 0x0e00, 0x04 /* SIGILL */ }, /* reserved */ -+ { 0x0f00, 0x04 /* SIGILL */ }, /* reserved */ -+ { 0x2002, 0x05 /* SIGTRAP */}, /* debug */ -+#else -+ { 0x0200, 0x0b /* SIGSEGV */ }, /* machine check */ -+ { 0x0300, 0x0b /* SIGSEGV */ }, /* address error (store) */ -+ { 0x0400, 0x0a /* SIGBUS */ }, /* instruction bus error */ -+ { 0x0500, 0x02 /* SIGINT */ }, /* interrupt */ -+ { 0x0600, 0x0a /* SIGBUS */ }, /* alingment */ -+ { 0x0700, 0x05 /* SIGTRAP */ }, /* breakpoint trap */ -+ { 0x0800, 0x08 /* SIGFPE */}, /* fpu unavail */ -+ { 0x0900, 0x0e /* SIGALRM */ }, /* decrementer */ -+ { 0x0a00, 0x04 /* SIGILL */ }, /* reserved */ -+ { 0x0b00, 0x04 /* SIGILL */ }, /* reserved */ -+ { 0x0c00, 0x14 /* SIGCHLD */ }, /* syscall */ -+ { 0x0d00, 0x05 /* SIGTRAP */ }, /* single-step/watch */ -+ { 0x0e00, 0x08 /* SIGFPE */ }, /* fp assist */ -+#endif -+ { 0x0000, 0x000 } /* Must be last */ -+}; -+ -+extern atomic_t cpu_doing_single_step; -+ -+static int computeSignal(unsigned 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 */ -+} -+ -+/* KGDB functions to use existing PowerPC hooks. */ -+static void kgdb_debugger(struct pt_regs *regs) -+{ -+ kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs); -+} -+ -+static int kgdb_breakpoint(struct pt_regs *regs) -+{ -+ if (user_mode(regs)) -+ return 0; -+ -+ kgdb_handle_exception(0, SIGTRAP, 0, regs); -+ -+ if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr)) -+ regs->nip += 4; -+ -+ return 1; -+} -+ -+static int kgdb_singlestep(struct pt_regs *regs) -+{ -+ struct thread_info *thread_info, *exception_thread_info; -+ -+ if (user_mode(regs)) -+ return 0; -+ /* -+ * On Book E and perhaps other processsors, singlestep is handled on -+ * the critical exception stack. This causes current_thread_info() -+ * to fail, since it it locates the thread_info by masking off -+ * the low bits of the current stack pointer. We work around -+ * this issue by copying the thread_info from the kernel stack -+ * before calling kgdb_handle_exception, and copying it back -+ * afterwards. On most processors the copy is avoided since -+ * exception_thread_info == thread_info. -+ */ -+ thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1)); -+ exception_thread_info = current_thread_info(); -+ -+ if (thread_info != exception_thread_info) -+ memcpy(exception_thread_info, thread_info, sizeof *thread_info); -+ -+ kgdb_handle_exception(0, SIGTRAP, 0, regs); -+ -+ if (thread_info != exception_thread_info) -+ memcpy(thread_info, exception_thread_info, sizeof *thread_info); -+ -+ return 1; -+} -+ -+int kgdb_iabr_match(struct pt_regs *regs) -+{ -+ if (user_mode(regs)) -+ return 0; -+ -+ kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs); -+ return 1; -+} -+ -+int kgdb_dabr_match(struct pt_regs *regs) -+{ -+ if (user_mode(regs)) -+ return 0; -+ -+ kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs); -+ return 1; -+} -+ -+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) -+{ -+ int reg; -+ unsigned long *ptr = gdb_regs; -+ -+ memset(gdb_regs, 0, MAXREG * 4); -+ -+ for (reg = 0; reg < 32; reg++) -+ *(ptr++) = regs->gpr[reg]; -+ -+#ifndef CONFIG_E500 -+ for (reg = 0; reg < 64; reg++) -+ *(ptr++) = 0; -+#else -+ for (reg = 0; reg < 32; reg++) -+ *(ptr++) = current->thread.evr[reg]; -+#endif -+ -+ *(ptr++) = regs->nip; -+ *(ptr++) = regs->msr; -+ *(ptr++) = regs->ccr; -+ *(ptr++) = regs->link; -+ *(ptr++) = regs->ctr; -+ *(ptr++) = regs->xer; -+ -+#ifdef CONFIG_SPE -+ /* u64 acc */ -+ *(ptr++) = (current->thread.acc >> 32); -+ *(ptr++) = (current->thread.acc & 0xffffffff); -+ *(ptr++) = current->thread.spefscr; -+#endif -+} -+ -+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) -+{ -+ struct pt_regs *regs = (struct pt_regs *)(p->thread.ksp + -+ STACK_FRAME_OVERHEAD); -+ int reg; -+ unsigned long *ptr = gdb_regs; -+ -+ memset(gdb_regs, 0, MAXREG * 4); -+ -+ /* Regs GPR0-2 */ -+ for (reg = 0; reg < 3; reg++) -+ *(ptr++) = regs->gpr[reg]; -+ -+ /* Regs GPR3-13 are not saved */ -+ for (reg = 3; reg < 14; reg++) -+ *(ptr++) = 0; -+ -+ /* Regs GPR14-31 */ -+ for (reg = 14; reg < 32; reg++) -+ *(ptr++) = regs->gpr[reg]; -+ -+#ifndef CONFIG_E500 -+ for (reg = 0; reg < 64; reg++) -+ *(ptr++) = 0; -+#else -+ for (reg = 0; reg < 32; reg++) -+ *(ptr++) = current->thread.evr[reg]; -+#endif -+ -+ *(ptr++) = regs->nip; -+ *(ptr++) = regs->msr; -+ *(ptr++) = regs->ccr; -+ *(ptr++) = regs->link; -+ *(ptr++) = regs->ctr; -+ *(ptr++) = regs->xer; -+ -+#ifdef CONFIG_SPE -+ /* u64 acc */ -+ *(ptr++) = (current->thread.acc >> 32); -+ *(ptr++) = (current->thread.acc & 0xffffffff); -+ *(ptr++) = current->thread.spefscr; -+#endif -+} -+ -+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs) -+{ -+ int reg; -+ unsigned long *ptr = gdb_regs; -+#ifdef CONFIG_SPE -+ union { -+ u32 v32[2]; -+ u64 v64; -+ } u; -+#endif -+ -+ for (reg = 0; reg < 32; reg++) -+ regs->gpr[reg] = *(ptr++); -+ -+#ifndef CONFIG_E500 -+ for (reg = 0; reg < 64; reg++) -+ ptr++; -+#else -+ for (reg = 0; reg < 32; reg++) -+ current->thread.evr[reg] = *(ptr++); -+#endif -+ -+ regs->nip = *(ptr++); -+ regs->msr = *(ptr++); -+ regs->ccr = *(ptr++); -+ regs->link = *(ptr++); -+ regs->ctr = *(ptr++); -+ regs->xer = *(ptr++); -+ -+#ifdef CONFIG_SPE -+ /* u64 acc */ -+ u.v32[0] = *(ptr++); -+ u.v32[1] = *(ptr++); -+ current->thread.acc = u.v64; -+ current->thread.spefscr = *(ptr++); -+#endif -+} -+ -+/* -+ * Save/restore state in case a memory access causes a fault. -+ */ -+int kgdb_fault_setjmp(unsigned long *curr_context) -+{ -+ __asm__ __volatile__("mflr 0; stw 0,0(%0);" -+ "stw 1,4(%0); stw 2,8(%0);" -+ "mfcr 0; stw 0,12(%0);" -+ "stmw 13,16(%0)"::"r"(curr_context)); -+ return 0; -+} -+ -+void kgdb_fault_longjmp(unsigned long *curr_context) -+{ -+ __asm__ __volatile__("lmw 13,16(%0);" -+ "lwz 0,12(%0); mtcrf 0x38,0;" -+ "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);" -+ "mtlr 0; mr 3,1"::"r"(curr_context)); -+} -+ -+/* -+ * This function does PoerPC specific procesing for interfacing to gdb. -+ */ -+int kgdb_arch_handle_exception(int vector, int signo, int err_code, -+ char *remcom_in_buffer, char *remcom_out_buffer, -+ struct pt_regs *linux_regs) -+{ -+ char *ptr = &remcom_in_buffer[1]; -+ unsigned long addr; -+ -+ switch (remcom_in_buffer[0]) -+ { -+ /* -+ * sAA..AA Step one instruction from AA..AA -+ * This will return an error to gdb .. -+ */ -+ case 's': -+ case 'c': -+ /* handle the optional parameter */ -+ if (kgdb_hex2long (&ptr, &addr)) -+ linux_regs->nip = addr; -+ -+ atomic_set(&cpu_doing_single_step, -1); -+ /* set the trace bit if we're stepping */ -+ if (remcom_in_buffer[0] == 's') { -+#if defined (CONFIG_40x) || defined(CONFIG_BOOKE) -+ mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | -+ DBCR0_IC | DBCR0_IDM); -+ linux_regs->msr |= MSR_DE; -+#else -+ linux_regs->msr |= MSR_SE; -+#endif -+ debugger_step = 1; -+ if (kgdb_contthread) -+ atomic_set(&cpu_doing_single_step, -+ smp_processor_id()); -+ } -+ return 0; -+ } -+ -+ return -1; -+} -+ -+/* -+ * Global data -+ */ -+struct kgdb_arch arch_kgdb_ops = { -+ .gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08}, -+}; -+ -+int kgdb_arch_init(void) -+{ -+ debugger = kgdb_debugger; -+ debugger_bpt = kgdb_breakpoint; -+ debugger_sstep = kgdb_singlestep; -+ debugger_iabr_match = kgdb_iabr_match; -+ debugger_dabr_match = kgdb_dabr_match; -+ -+ return 0; -+} -+ -+arch_initcall(kgdb_arch_init); -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/kernel/ppc-stub.c linux-2.6.18-53.1.14.kgdb/arch/ppc/kernel/ppc-stub.c ---- linux-2.6.18-53.1.14/arch/ppc/kernel/ppc-stub.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/kernel/ppc-stub.c 1970-01-01 03:00:00.000000000 +0300 -@@ -1,866 +0,0 @@ --/* -- * ppc-stub.c: KGDB support for the Linux kernel. -- * -- * adapted from arch/sparc/kernel/sparc-stub.c for the PowerPC -- * some stuff borrowed from Paul Mackerras' xmon -- * Copyright (C) 1998 Michael AK Tesch (tesch@cs.wisc.edu) -- * -- * 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 -- * qOffsets Get section offsets. Reply is Text=xxx;Data=yyy;Bss=zzz -- * -- * 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 -- * -- * $#. -- * -- * where -- * :: -- * :: > -- * -- * 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 --#include --#include --#include --#include --#include --#include -- --#include --#include --#include --#include --#include --#include -- --void breakinst(void); -- --/* -- * BUFMAX defines the maximum number of characters in inbound/outbound buffers -- * at least NUMREGBYTES*2 are needed for register packets -- */ --#define BUFMAX 2048 --static char remcomInBuffer[BUFMAX]; --static char remcomOutBuffer[BUFMAX]; -- --static int initialized; --static int kgdb_active; --static int kgdb_started; --static u_int fault_jmp_buf[100]; --static int kdebug; -- -- --static const char hexchars[]="0123456789abcdef"; -- --/* Place where we save old trap entries for restoration - sparc*/ --/* struct tt_entry kgdb_savettable[256]; */ --/* typedef void (*trapfunc_t)(void); */ -- --static void kgdb_fault_handler(struct pt_regs *regs); --static int handle_exception (struct pt_regs *regs); -- --#if 0 --/* Install an exception handler for kgdb */ --static void exceptionHandler(int tnum, unsigned int *tfunc) --{ -- /* We are dorking with a live trap table, all irqs off */ --} --#endif -- --int --kgdb_setjmp(long *buf) --{ -- asm ("mflr 0; stw 0,0(%0);" -- "stw 1,4(%0); stw 2,8(%0);" -- "mfcr 0; stw 0,12(%0);" -- "stmw 13,16(%0)" -- : : "r" (buf)); -- /* XXX should save fp regs as well */ -- return 0; --} --void --kgdb_longjmp(long *buf, int val) --{ -- if (val == 0) -- val = 1; -- asm ("lmw 13,16(%0);" -- "lwz 0,12(%0); mtcrf 0x38,0;" -- "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);" -- "mtlr 0; mr 3,%1" -- : : "r" (buf), "r" (val)); --} --/* 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; --} -- --/* 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(const char *mem, char *buf, int count) --{ -- unsigned char ch; -- unsigned short tmp_s; -- unsigned long tmp_l; -- -- if (kgdb_setjmp((long*)fault_jmp_buf) == 0) { -- debugger_fault_handler = kgdb_fault_handler; -- -- /* Accessing 16 bit and 32 bit objects in a single -- ** load instruction is required to avoid bad side -- ** effects for some IO registers. -- */ -- -- if ((count == 2) && (((long)mem & 1) == 0)) { -- tmp_s = *(unsigned short *)mem; -- mem += 2; -- *buf++ = hexchars[(tmp_s >> 12) & 0xf]; -- *buf++ = hexchars[(tmp_s >> 8) & 0xf]; -- *buf++ = hexchars[(tmp_s >> 4) & 0xf]; -- *buf++ = hexchars[tmp_s & 0xf]; -- -- } else if ((count == 4) && (((long)mem & 3) == 0)) { -- tmp_l = *(unsigned int *)mem; -- mem += 4; -- *buf++ = hexchars[(tmp_l >> 28) & 0xf]; -- *buf++ = hexchars[(tmp_l >> 24) & 0xf]; -- *buf++ = hexchars[(tmp_l >> 20) & 0xf]; -- *buf++ = hexchars[(tmp_l >> 16) & 0xf]; -- *buf++ = hexchars[(tmp_l >> 12) & 0xf]; -- *buf++ = hexchars[(tmp_l >> 8) & 0xf]; -- *buf++ = hexchars[(tmp_l >> 4) & 0xf]; -- *buf++ = hexchars[tmp_l & 0xf]; -- -- } else { -- while (count-- > 0) { -- ch = *mem++; -- *buf++ = hexchars[ch >> 4]; -- *buf++ = hexchars[ch & 0xf]; -- } -- } -- -- } else { -- /* error condition */ -- } -- debugger_fault_handler = NULL; -- *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) --{ -- unsigned char ch; -- int i; -- char *orig_mem; -- unsigned short tmp_s; -- unsigned long tmp_l; -- -- orig_mem = mem; -- -- if (kgdb_setjmp((long*)fault_jmp_buf) == 0) { -- debugger_fault_handler = kgdb_fault_handler; -- -- /* Accessing 16 bit and 32 bit objects in a single -- ** store instruction is required to avoid bad side -- ** effects for some IO registers. -- */ -- -- if ((count == 2) && (((long)mem & 1) == 0)) { -- tmp_s = hex(*buf++) << 12; -- tmp_s |= hex(*buf++) << 8; -- tmp_s |= hex(*buf++) << 4; -- tmp_s |= hex(*buf++); -- -- *(unsigned short *)mem = tmp_s; -- mem += 2; -- -- } else if ((count == 4) && (((long)mem & 3) == 0)) { -- tmp_l = hex(*buf++) << 28; -- tmp_l |= hex(*buf++) << 24; -- tmp_l |= hex(*buf++) << 20; -- tmp_l |= hex(*buf++) << 16; -- tmp_l |= hex(*buf++) << 12; -- tmp_l |= hex(*buf++) << 8; -- tmp_l |= hex(*buf++) << 4; -- tmp_l |= hex(*buf++); -- -- *(unsigned long *)mem = tmp_l; -- mem += 4; -- -- } else { -- for (i=0; i# */ --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; -- -- /* $#. */ -- 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 void kgdb_flush_cache_all(void) --{ -- flush_instruction_cache(); --} -- --/* Set up exception handlers for tracing and breakpoints -- * [could be called kgdb_init()] -- */ --void set_debug_traps(void) --{ --#if 0 -- unsigned char c; -- -- save_and_cli(flags); -- -- /* 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 -- */ -- -- while((c = getDebugChar()) != '$'); -- while((c = getDebugChar()) != '#'); -- c = getDebugChar(); /* eat first csum byte */ -- c = getDebugChar(); /* eat second csum byte */ -- putDebugChar('+'); /* ack it */ --#endif -- debugger = kgdb; -- debugger_bpt = kgdb_bpt; -- debugger_sstep = kgdb_sstep; -- debugger_iabr_match = kgdb_iabr_match; -- debugger_dabr_match = kgdb_dabr_match; -- -- initialized = 1; --} -- --static void kgdb_fault_handler(struct pt_regs *regs) --{ -- kgdb_longjmp((long*)fault_jmp_buf, 1); --} -- --int kgdb_bpt(struct pt_regs *regs) --{ -- return handle_exception(regs); --} -- --int kgdb_sstep(struct pt_regs *regs) --{ -- return handle_exception(regs); --} -- --void kgdb(struct pt_regs *regs) --{ -- handle_exception(regs); --} -- --int kgdb_iabr_match(struct pt_regs *regs) --{ -- printk(KERN_ERR "kgdb doesn't support iabr, what?!?\n"); -- return handle_exception(regs); --} -- --int kgdb_dabr_match(struct pt_regs *regs) --{ -- printk(KERN_ERR "kgdb doesn't support dabr, what?!?\n"); -- return handle_exception(regs); --} -- --/* Convert the hardware trap type code to a unix signal number. */ --/* -- * This table contains the mapping between PowerPC hardware trap types, and -- * signals, which are primarily what GDB understands. -- */ --static struct hard_trap_info --{ -- unsigned int tt; /* Trap type code for powerpc */ -- unsigned char signo; /* Signal that we map this trap into */ --} hard_trap_info[] = { --#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) -- { 0x100, SIGINT }, /* critical input interrupt */ -- { 0x200, SIGSEGV }, /* machine check */ -- { 0x300, SIGSEGV }, /* data storage */ -- { 0x400, SIGBUS }, /* instruction storage */ -- { 0x500, SIGINT }, /* interrupt */ -- { 0x600, SIGBUS }, /* alignment */ -- { 0x700, SIGILL }, /* program */ -- { 0x800, SIGILL }, /* reserved */ -- { 0x900, SIGILL }, /* reserved */ -- { 0xa00, SIGILL }, /* reserved */ -- { 0xb00, SIGILL }, /* reserved */ -- { 0xc00, SIGCHLD }, /* syscall */ -- { 0xd00, SIGILL }, /* reserved */ -- { 0xe00, SIGILL }, /* reserved */ -- { 0xf00, SIGILL }, /* reserved */ -- /* -- ** 0x1000 PIT -- ** 0x1010 FIT -- ** 0x1020 watchdog -- ** 0x1100 data TLB miss -- ** 0x1200 instruction TLB miss -- */ -- { 0x2002, SIGTRAP}, /* debug */ --#else -- { 0x200, SIGSEGV }, /* machine check */ -- { 0x300, SIGSEGV }, /* address error (store) */ -- { 0x400, SIGBUS }, /* instruction bus error */ -- { 0x500, SIGINT }, /* interrupt */ -- { 0x600, SIGBUS }, /* alingment */ -- { 0x700, SIGTRAP }, /* breakpoint trap */ -- { 0x800, SIGFPE }, /* fpu unavail */ -- { 0x900, SIGALRM }, /* decrementer */ -- { 0xa00, SIGILL }, /* reserved */ -- { 0xb00, SIGILL }, /* reserved */ -- { 0xc00, SIGCHLD }, /* syscall */ -- { 0xd00, SIGTRAP }, /* single-step/watch */ -- { 0xe00, SIGFPE }, /* fp assist */ --#endif -- { 0, 0} /* Must be last */ -- --}; -- --static int computeSignal(unsigned 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 */ --} -- --#define PC_REGNUM 64 --#define SP_REGNUM 1 -- --/* -- * This function does all command processing for interfacing to gdb. -- */ --static int --handle_exception (struct pt_regs *regs) --{ -- int sigval; -- int addr; -- int length; -- char *ptr; -- unsigned int msr; -- -- /* We don't handle user-mode breakpoints. */ -- if (user_mode(regs)) -- return 0; -- -- if (debugger_fault_handler) { -- debugger_fault_handler(regs); -- panic("kgdb longjump failed!\n"); -- } -- if (kgdb_active) { -- printk(KERN_ERR "interrupt while in kgdb, returning\n"); -- return 0; -- } -- -- kgdb_active = 1; -- kgdb_started = 1; -- --#ifdef KGDB_DEBUG -- printk("kgdb: entering handle_exception; trap [0x%x]\n", -- (unsigned int)regs->trap); --#endif -- -- kgdb_interruptible(0); -- lock_kernel(); -- msr = mfmsr(); -- mtmsr(msr & ~MSR_EE); /* disable interrupts */ -- -- if (regs->nip == (unsigned long)breakinst) { -- /* Skip over breakpoint trap insn */ -- regs->nip += 4; -- } -- -- /* reply to host that an exception has occurred */ -- sigval = computeSignal(regs->trap); -- ptr = remcomOutBuffer; -- -- *ptr++ = 'T'; -- *ptr++ = hexchars[sigval >> 4]; -- *ptr++ = hexchars[sigval & 0xf]; -- *ptr++ = hexchars[PC_REGNUM >> 4]; -- *ptr++ = hexchars[PC_REGNUM & 0xf]; -- *ptr++ = ':'; -- ptr = mem2hex((char *)®s->nip, ptr, 4); -- *ptr++ = ';'; -- *ptr++ = hexchars[SP_REGNUM >> 4]; -- *ptr++ = hexchars[SP_REGNUM & 0xf]; -- *ptr++ = ':'; -- ptr = mem2hex(((char *)regs) + SP_REGNUM*4, ptr, 4); -- *ptr++ = ';'; -- *ptr++ = 0; -- -- putpacket(remcomOutBuffer); -- if (kdebug) -- printk("remcomOutBuffer: %s\n", remcomOutBuffer); -- -- /* XXX We may want to add some features dealing with poking the -- * XXX page tables, ... (look at sparc-stub.c for more info) -- * XXX also required hacking to the gdb sources directly... -- */ -- -- while (1) { -- remcomOutBuffer[0] = 0; -- -- getpacket(remcomInBuffer); -- switch (remcomInBuffer[0]) { -- case '?': /* report most recent signal */ -- remcomOutBuffer[0] = 'S'; -- remcomOutBuffer[1] = hexchars[sigval >> 4]; -- remcomOutBuffer[2] = hexchars[sigval & 0xf]; -- remcomOutBuffer[3] = 0; -- break; --#if 0 -- case 'q': /* this screws up gdb for some reason...*/ -- { -- extern long _start, sdata, __bss_start; -- -- ptr = &remcomInBuffer[1]; -- if (strncmp(ptr, "Offsets", 7) != 0) -- break; -- -- ptr = remcomOutBuffer; -- sprintf(ptr, "Text=%8.8x;Data=%8.8x;Bss=%8.8x", -- &_start, &sdata, &__bss_start); -- break; -- } --#endif -- case 'd': -- /* toggle debug flag */ -- kdebug ^= 1; -- break; -- -- case 'g': /* return the value of the CPU registers. -- * some of them are non-PowerPC names :( -- * they are stored in gdb like: -- * struct { -- * u32 gpr[32]; -- * f64 fpr[32]; -- * u32 pc, ps, cnd, lr; (ps=msr) -- * u32 cnt, xer, mq; -- * } -- */ -- { -- int i; -- ptr = remcomOutBuffer; -- /* General Purpose Regs */ -- ptr = mem2hex((char *)regs, ptr, 32 * 4); -- /* Floating Point Regs - FIXME */ -- /*ptr = mem2hex((char *), ptr, 32 * 8);*/ -- for(i=0; i<(32*8*2); i++) { /* 2chars/byte */ -- ptr[i] = '0'; -- } -- ptr += 32*8*2; -- /* pc, msr, cr, lr, ctr, xer, (mq is unused) */ -- ptr = mem2hex((char *)®s->nip, ptr, 4); -- ptr = mem2hex((char *)®s->msr, ptr, 4); -- ptr = mem2hex((char *)®s->ccr, ptr, 4); -- ptr = mem2hex((char *)®s->link, ptr, 4); -- ptr = mem2hex((char *)®s->ctr, ptr, 4); -- ptr = mem2hex((char *)®s->xer, ptr, 4); -- } -- break; -- -- case 'G': /* set the value of the CPU registers */ -- { -- ptr = &remcomInBuffer[1]; -- -- /* -- * If the stack pointer has moved, you should pray. -- * (cause only god can help you). -- */ -- -- /* General Purpose Regs */ -- hex2mem(ptr, (char *)regs, 32 * 4); -- -- /* Floating Point Regs - FIXME?? */ -- /*ptr = hex2mem(ptr, ??, 32 * 8);*/ -- ptr += 32*8*2; -- -- /* pc, msr, cr, lr, ctr, xer, (mq is unused) */ -- ptr = hex2mem(ptr, (char *)®s->nip, 4); -- ptr = hex2mem(ptr, (char *)®s->msr, 4); -- ptr = hex2mem(ptr, (char *)®s->ccr, 4); -- ptr = hex2mem(ptr, (char *)®s->link, 4); -- ptr = hex2mem(ptr, (char *)®s->ctr, 4); -- ptr = hex2mem(ptr, (char *)®s->xer, 4); -- -- strcpy(remcomOutBuffer,"OK"); -- } -- break; -- case 'H': -- /* don't do anything, yet, just acknowledge */ -- hexToInt(&ptr, &addr); -- 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"); -- flush_icache_range(addr, addr+length); -- } else -- strcpy(remcomOutBuffer, "E02"); -- break; -- -- -- case 'k': /* kill the program, actually just continue */ -- case 'c': /* cAA..AA Continue; address AA..AA optional */ -- /* try to read optional parameter, pc unchanged if no parm */ -- -- ptr = &remcomInBuffer[1]; -- if (hexToInt(&ptr, &addr)) -- regs->nip = addr; -- --/* 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. -- */ -- kgdb_flush_cache_all(); -- mtmsr(msr); -- -- kgdb_interruptible(1); -- unlock_kernel(); -- kgdb_active = 0; -- if (kdebug) { -- printk("remcomInBuffer: %s\n", remcomInBuffer); -- printk("remcomOutBuffer: %s\n", remcomOutBuffer); -- } -- return 1; -- -- case 's': -- kgdb_flush_cache_all(); --#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) -- mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC); -- regs->msr |= MSR_DE; --#else -- regs->msr |= MSR_SE; --#endif -- unlock_kernel(); -- kgdb_active = 0; -- if (kdebug) { -- printk("remcomInBuffer: %s\n", remcomInBuffer); -- printk("remcomOutBuffer: %s\n", remcomOutBuffer); -- } -- return 1; -- -- case 'r': /* Reset (if user process..exit ???)*/ -- panic("kgdb reset."); -- break; -- } /* switch */ -- if (remcomOutBuffer[0] && kdebug) { -- printk("remcomInBuffer: %s\n", remcomInBuffer); -- printk("remcomOutBuffer: %s\n", remcomOutBuffer); -- } -- /* 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) { -- printk("breakpoint() called b4 kgdb init\n"); -- return; -- } -- -- asm(" .globl breakinst \n\ -- breakinst: .long 0x7d821008"); --} -- --#ifdef CONFIG_KGDB_CONSOLE --/* Output string in GDB O-packet format if GDB has connected. If nothing -- output, returns 0 (caller must then handle output). */ --int --kgdb_output_string (const char* s, unsigned int count) --{ -- char buffer[512]; -- -- if (!kgdb_started) -- return 0; -- -- count = (count <= (sizeof(buffer) / 2 - 2)) -- ? count : (sizeof(buffer) / 2 - 2); -- -- buffer[0] = 'O'; -- mem2hex (s, &buffer[1], count); -- putpacket(buffer); -- -- return 1; --} --#endif -- --static void sysrq_handle_gdb(int key, struct pt_regs *pt_regs, -- struct tty_struct *tty) --{ -- printk("Entering GDB stub\n"); -- breakpoint(); --} --static struct sysrq_key_op sysrq_gdb_op = { -- .handler = sysrq_handle_gdb, -- .help_msg = "Gdb", -- .action_msg = "GDB", --}; -- --static int gdb_register_sysrq(void) --{ -- printk("Registering GDB sysrq handler\n"); -- register_sysrq_key('g', &sysrq_gdb_op); -- return 0; --} --module_init(gdb_register_sysrq); -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/kernel/setup.c linux-2.6.18-53.1.14.kgdb/arch/ppc/kernel/setup.c ---- linux-2.6.18-53.1.14/arch/ppc/kernel/setup.c 2008-03-06 05:54:43.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/kernel/setup.c 2008-06-10 15:38:14.000000000 +0400 -@@ -48,10 +48,6 @@ - #include - #endif - --#if defined CONFIG_KGDB --#include --#endif -- - extern void platform_init(unsigned long r3, unsigned long r4, - unsigned long r5, unsigned long r6, unsigned long r7); - extern void reloc_got2(unsigned long offset); -@@ -506,18 +502,6 @@ void __init setup_arch(char **cmdline_p) - #endif /* CONFIG_XMON */ - if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab); - --#if defined(CONFIG_KGDB) -- if (ppc_md.kgdb_map_scc) -- ppc_md.kgdb_map_scc(); -- set_debug_traps(); -- if (strstr(cmd_line, "gdb")) { -- if (ppc_md.progress) -- ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000); -- printk("kgdb breakpoint activated\n"); -- breakpoint(); -- } --#endif -- - /* - * Set cache line size based on type of cpu as a default. - * Systems with OF can look in the properties on the cpu node(s) -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/mm/fault.c linux-2.6.18-53.1.14.kgdb/arch/ppc/mm/fault.c ---- linux-2.6.18-53.1.14/arch/ppc/mm/fault.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/mm/fault.c 2008-06-10 15:38:14.000000000 +0400 -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -329,6 +330,14 @@ bad_page_fault(struct pt_regs *regs, uns - return; - } - -+#ifdef CONFIG_KGDB -+ if (atomic_read(&debugger_active) && kgdb_may_fault) { -+ /* Restore our previous state. */ -+ kgdb_fault_longjmp(kgdb_fault_jmp_regs); -+ /* Not reached. */ -+ } -+#endif -+ - /* kernel has accessed a bad area */ - #if defined(CONFIG_XMON) || defined(CONFIG_KGDB) - if (debugger_kernel_faults) -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/platforms/4xx/bubinga.c linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/4xx/bubinga.c ---- linux-2.6.18-53.1.14/arch/ppc/platforms/4xx/bubinga.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/4xx/bubinga.c 2008-06-10 15:38:14.000000000 +0400 -@@ -4,7 +4,7 @@ - * Author: SAW (IBM), derived from walnut.c. - * Maintained by MontaVista Software - * -- * 2003 (c) MontaVista Softare Inc. This file is licensed under the -+ * 2003-2004 (c) MontaVista Softare Inc. This file is licensed under the - * terms of the GNU General Public License version 2. This program is - * licensed "as is" without any warranty of any kind, whether express - * or implied. -@@ -100,17 +100,26 @@ bubinga_early_serial_map(void) - port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; - port.line = 0; - -- if (early_serial_setup(&port) != 0) { -+#ifdef CONFIG_SERIAL_8250 -+ if (early_serial_setup(&port) != 0) - printk("Early serial init of port 0 failed\n"); -- } -+#endif -+ -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_port(0, &port); -+#endif - - port.membase = (void*)ACTING_UART1_IO_BASE; - port.irq = ACTING_UART1_INT; - port.line = 1; - -- if (early_serial_setup(&port) != 0) { -+#ifdef CONFIG_SERIAL_8250 -+ if (early_serial_setup(&port) != 0) - printk("Early serial init of port 1 failed\n"); -- } -+#endif -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_port(1, &port); -+#endif - } - - void __init -@@ -255,8 +264,4 @@ platform_init(unsigned long r3, unsigned - ppc_md.nvram_read_val = todc_direct_read_val; - ppc_md.nvram_write_val = todc_direct_write_val; - #endif --#ifdef CONFIG_KGDB -- ppc_md.early_serial_map = bubinga_early_serial_map; --#endif - } -- -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/platforms/4xx/ebony.c linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/4xx/ebony.c ---- linux-2.6.18-53.1.14/arch/ppc/platforms/4xx/ebony.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/4xx/ebony.c 2008-06-10 15:38:14.000000000 +0400 -@@ -32,6 +32,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -226,14 +227,20 @@ ebony_early_serial_map(void) - port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; - port.line = 0; - -- if (early_serial_setup(&port) != 0) { -+#ifdef CONFIG_SERIAL_8250 -+ if (early_serial_setup(&port) != 0) - printk("Early serial init of port 0 failed\n"); -- } -+#endif - --#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) -+#ifdef CONFIG_SERIAL_TEXT_DEBUG - /* Configure debug serial access */ - gen550_init(0, &port); -+#endif -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_port(0, &port); -+#endif - -+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250) - /* Purge TLB entry added in head_44x.S for early serial access */ - _tlbie(UART0_IO_BASE); - #endif -@@ -243,14 +250,18 @@ ebony_early_serial_map(void) - port.uartclk = clocks.uart1; - port.line = 1; - -- if (early_serial_setup(&port) != 0) { -+#ifdef CONFIG_SERIAL_8250 -+ if (early_serial_setup(&port) != 1) - printk("Early serial init of port 1 failed\n"); -- } -+#endif - --#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) -+#ifdef CONFIG_SERIAL_TEXT_DEBUG - /* Configure debug serial access */ - gen550_init(1, &port); - #endif -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_port(1, &port); -+#endif - } - - static void __init -@@ -327,8 +338,4 @@ void __init platform_init(unsigned long - - ppc_md.nvram_read_val = todc_direct_read_val; - ppc_md.nvram_write_val = todc_direct_write_val; --#ifdef CONFIG_KGDB -- ppc_md.early_serial_map = ebony_early_serial_map; --#endif - } -- -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/platforms/4xx/ocotea.c linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/4xx/ocotea.c ---- linux-2.6.18-53.1.14/arch/ppc/platforms/4xx/ocotea.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/4xx/ocotea.c 2008-06-10 15:38:14.000000000 +0400 -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -249,14 +250,20 @@ ocotea_early_serial_map(void) - port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; - port.line = 0; - -- if (early_serial_setup(&port) != 0) { -+#ifdef CONFIG_SERIAL_8250 -+ if (early_serial_setup(&port) != 0) - printk("Early serial init of port 0 failed\n"); -- } -+#endif - --#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) -+#ifdef CONFIG_SERIAL_TEXT_DEBUG - /* Configure debug serial access */ - gen550_init(0, &port); -+#endif -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_port(0, &port); -+#endif - -+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250) - /* Purge TLB entry added in head_44x.S for early serial access */ - _tlbie(UART0_IO_BASE); - #endif -@@ -266,14 +273,18 @@ ocotea_early_serial_map(void) - port.uartclk = clocks.uart1; - port.line = 1; - -- if (early_serial_setup(&port) != 0) { -+#ifdef CONFIG_SERIAL_8250 -+ if (early_serial_setup(&port) != 1) - printk("Early serial init of port 1 failed\n"); -- } -+#endif - --#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) -+#ifdef CONFIG_SERIAL_TEXT_DEBUG - /* Configure debug serial access */ - gen550_init(1, &port); - #endif -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_port(1, &port); -+#endif - } - - static void __init -@@ -343,8 +354,5 @@ void __init platform_init(unsigned long - - ppc_md.nvram_read_val = todc_direct_read_val; - ppc_md.nvram_write_val = todc_direct_write_val; --#ifdef CONFIG_KGDB -- ppc_md.early_serial_map = ocotea_early_serial_map; --#endif - ppc_md.init = ocotea_init; - } -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/platforms/4xx/xilinx_ml300.c linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/4xx/xilinx_ml300.c ---- linux-2.6.18-53.1.14/arch/ppc/platforms/4xx/xilinx_ml300.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/4xx/xilinx_ml300.c 2008-06-10 15:38:14.000000000 +0400 -@@ -41,9 +41,6 @@ - * ppc4xx_map_io arch/ppc/syslib/ppc4xx_setup.c - * start_kernel init/main.c - * setup_arch arch/ppc/kernel/setup.c -- * #if defined(CONFIG_KGDB) -- * *ppc_md.kgdb_map_scc() == gen550_kgdb_map_scc -- * #endif - * *ppc_md.setup_arch == ml300_setup_arch this file - * ppc4xx_setup_arch arch/ppc/syslib/ppc4xx_setup.c - * ppc4xx_find_bridges arch/ppc/syslib/ppc405_pci.c -@@ -117,7 +114,6 @@ ml300_early_serial_init(int num, struct - void __init - ml300_early_serial_map(void) - { --#ifdef CONFIG_SERIAL_8250 - struct plat_serial8250_port *pdata; - int i = 0; - -@@ -129,7 +125,14 @@ ml300_early_serial_map(void) - pdata++; - i++; - } --#endif /* CONFIG_SERIAL_8250 */ -+#ifdef CONFIG_SERIAL_8250 -+ if (early_serial_setup(&port) != 0) -+ printk("Early serial init of port %d failed\n", i); -+#endif -+ -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_port(i, &port) -+#endif - } - - void __init -@@ -165,9 +168,4 @@ platform_init(unsigned long r3, unsigned - #if defined(XPAR_POWER_0_POWERDOWN_BASEADDR) - ppc_md.power_off = xilinx_power_off; - #endif -- --#ifdef CONFIG_KGDB -- ppc_md.early_serial_map = ml300_early_serial_map; --#endif - } -- -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/platforms/85xx/sbc8560.c linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/85xx/sbc8560.c ---- linux-2.6.18-53.1.14/arch/ppc/platforms/85xx/sbc8560.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/85xx/sbc8560.c 2008-06-10 15:38:14.000000000 +0400 -@@ -50,7 +50,6 @@ - #include - #include - --#ifdef CONFIG_SERIAL_8250 - static void __init - sbc8560_early_serial_map(void) - { -@@ -66,12 +65,16 @@ sbc8560_early_serial_map(void) - uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART0_SIZE); - uart_req.type = PORT_16650; - --#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) -- gen550_init(0, &uart_req); --#endif -- -+#ifdef CONFIG_SERIAL_8250 - if (early_serial_setup(&uart_req) != 0) - printk("Early serial init of port 0 failed\n"); -+#endif -+#ifdef CONFIG_SERIAL_TEXT_DEBUG -+ gen550_init(0, &uart_req); -+#endif -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_port(0, &uart_req); -+#endif - - /* Assume early_serial_setup() doesn't modify uart_req */ - uart_req.line = 1; -@@ -79,14 +82,17 @@ sbc8560_early_serial_map(void) - uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART1_SIZE); - uart_req.irq = MPC85xx_IRQ_EXT10; - --#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) -- gen550_init(1, &uart_req); --#endif -- -+#ifdef CONFIG_SERIAL_8250 - if (early_serial_setup(&uart_req) != 0) -- printk("Early serial init of port 1 failed\n"); --} -+ printk("Early serial init of port 0 failed\n"); - #endif -+#ifdef CONFIG_SERIAL_TEXT_DEBUG -+ gen550_init(0, &uart_req); -+#endif -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_port(0, &uart_req); -+#endif -+} - - /* ************************************************************************ - * -@@ -115,9 +121,7 @@ sbc8560_setup_arch(void) - /* setup PCI host bridges */ - mpc85xx_setup_hose(); - #endif --#ifdef CONFIG_SERIAL_8250 - sbc8560_early_serial_map(); --#endif - #ifdef CONFIG_SERIAL_TEXT_DEBUG - /* Invalidate the entry we stole earlier the serial ports - * should be properly mapped */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/platforms/chestnut.c linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/chestnut.c ---- linux-2.6.18-53.1.14/arch/ppc/platforms/chestnut.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/chestnut.c 2008-06-10 15:38:14.000000000 +0400 -@@ -492,7 +492,7 @@ chestnut_power_off(void) - static void __init - chestnut_map_io(void) - { --#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) -+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250) - io_block_mapping(CHESTNUT_UART_BASE, CHESTNUT_UART_BASE, 0x100000, - _PAGE_IO); - #endif -@@ -566,9 +566,6 @@ platform_init(unsigned long r3, unsigned - #if defined(CONFIG_SERIAL_TEXT_DEBUG) - ppc_md.progress = gen550_progress; - #endif --#if defined(CONFIG_KGDB) -- ppc_md.kgdb_map_scc = gen550_kgdb_map_scc; --#endif - - if (ppc_md.progress) - ppc_md.progress("chestnut_init(): exit", 0); -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/platforms/pplus.c linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/pplus.c ---- linux-2.6.18-53.1.14/arch/ppc/platforms/pplus.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/pplus.c 2008-06-10 15:38:14.000000000 +0400 -@@ -893,9 +893,6 @@ platform_init(unsigned long r3, unsigned - #ifdef CONFIG_SERIAL_TEXT_DEBUG - ppc_md.progress = gen550_progress; - #endif /* CONFIG_SERIAL_TEXT_DEBUG */ --#ifdef CONFIG_KGDB -- ppc_md.kgdb_map_scc = gen550_kgdb_map_scc; --#endif - #ifdef CONFIG_SMP - smp_ops = &pplus_smp_ops; - #endif /* CONFIG_SMP */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/platforms/sandpoint.c linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/sandpoint.c ---- linux-2.6.18-53.1.14/arch/ppc/platforms/sandpoint.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/sandpoint.c 2008-06-10 15:38:14.000000000 +0400 -@@ -730,9 +730,6 @@ platform_init(unsigned long r3, unsigned - ppc_md.nvram_read_val = todc_mc146818_read_val; - ppc_md.nvram_write_val = todc_mc146818_write_val; - --#ifdef CONFIG_KGDB -- ppc_md.kgdb_map_scc = gen550_kgdb_map_scc; --#endif - #ifdef CONFIG_SERIAL_TEXT_DEBUG - ppc_md.progress = gen550_progress; - #endif -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/platforms/spruce.c linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/spruce.c ---- linux-2.6.18-53.1.14/arch/ppc/platforms/spruce.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/platforms/spruce.c 2008-06-10 15:38:14.000000000 +0400 -@@ -178,26 +178,32 @@ spruce_early_serial_map(void) - serial_req.membase = (u_char *)UART0_IO_BASE; - serial_req.regshift = 0; - --#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG) -- gen550_init(0, &serial_req); --#endif - #ifdef CONFIG_SERIAL_8250 - if (early_serial_setup(&serial_req) != 0) - printk("Early serial init of port 0 failed\n"); - #endif -+#ifdef CONFIG_SERIAL_TEXT_DEBUG -+ gen550_init(0, &serial_req); -+#endif -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_port(0, &port); -+#endif - - /* Assume early_serial_setup() doesn't modify serial_req */ - serial_req.line = 1; - serial_req.irq = UART1_INT; - serial_req.membase = (u_char *)UART1_IO_BASE; - --#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG) -- gen550_init(1, &serial_req); --#endif - #ifdef CONFIG_SERIAL_8250 - if (early_serial_setup(&serial_req) != 0) - printk("Early serial init of port 1 failed\n"); - #endif -+#ifdef CONFIG_SERIAL_TEXT_DEBUG -+ gen550_init(1, &serial_req); -+#endif -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_port(1, &serial_req); -+#endif - } - - TODC_ALLOC(); -@@ -316,7 +322,4 @@ platform_init(unsigned long r3, unsigned - #ifdef CONFIG_SERIAL_TEXT_DEBUG - ppc_md.progress = gen550_progress; - #endif /* CONFIG_SERIAL_TEXT_DEBUG */ --#ifdef CONFIG_KGDB -- ppc_md.kgdb_map_scc = gen550_kgdb_map_scc; --#endif - } -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/syslib/Makefile linux-2.6.18-53.1.14.kgdb/arch/ppc/syslib/Makefile ---- linux-2.6.18-53.1.14/arch/ppc/syslib/Makefile 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/syslib/Makefile 2008-06-10 15:38:14.000000000 +0400 -@@ -76,7 +76,6 @@ obj-$(CONFIG_PCI_8260) += m82xx_pci.o p - obj-$(CONFIG_8260_PCI9) += m8260_pci_erratum9.o - obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o - ifeq ($(CONFIG_PPC_GEN550),y) --obj-$(CONFIG_KGDB) += gen550_kgdb.o gen550_dbg.o - obj-$(CONFIG_SERIAL_TEXT_DEBUG) += gen550_dbg.o - endif - ifeq ($(CONFIG_SERIAL_MPSC_CONSOLE),y) -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/syslib/gen550.h linux-2.6.18-53.1.14.kgdb/arch/ppc/syslib/gen550.h ---- linux-2.6.18-53.1.14/arch/ppc/syslib/gen550.h 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/syslib/gen550.h 2008-06-10 15:38:14.000000000 +0400 -@@ -11,4 +11,3 @@ - - extern void gen550_progress(char *, unsigned short); - extern void gen550_init(int, struct uart_port *); --extern void gen550_kgdb_map_scc(void); -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/syslib/ibm44x_common.c linux-2.6.18-53.1.14.kgdb/arch/ppc/syslib/ibm44x_common.c ---- linux-2.6.18-53.1.14/arch/ppc/syslib/ibm44x_common.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/syslib/ibm44x_common.c 2008-06-10 15:38:14.000000000 +0400 -@@ -192,9 +192,6 @@ void __init ibm44x_platform_init(unsigne - #ifdef CONFIG_SERIAL_TEXT_DEBUG - ppc_md.progress = gen550_progress; - #endif /* CONFIG_SERIAL_TEXT_DEBUG */ --#ifdef CONFIG_KGDB -- ppc_md.kgdb_map_scc = gen550_kgdb_map_scc; --#endif - - /* - * The Abatron BDI JTAG debugger does not tolerate others -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/syslib/mv64x60.c linux-2.6.18-53.1.14.kgdb/arch/ppc/syslib/mv64x60.c ---- linux-2.6.18-53.1.14/arch/ppc/syslib/mv64x60.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/syslib/mv64x60.c 2008-06-10 15:38:14.000000000 +0400 -@@ -241,6 +241,12 @@ static struct resource mv64x60_mpsc0_res - .end = MV64x60_IRQ_SDMA_0, - .flags = IORESOURCE_IRQ, - }, -+ [4] = { -+ .name = "mpsc 0 irq", -+ .start = MV64x60_IRQ_MPSC_0, -+ .end = MV64x60_IRQ_MPSC_0, -+ .flags = IORESOURCE_IRQ, -+ }, - }; - - static struct platform_device mpsc0_device = { -@@ -298,6 +304,12 @@ static struct resource mv64x60_mpsc1_res - .end = MV64360_IRQ_SDMA_1, - .flags = IORESOURCE_IRQ, - }, -+ [4] = { -+ .name = "mpsc 1 irq", -+ .start = MV64360_IRQ_MPSC_1, -+ .end = MV64360_IRQ_MPSC_1, -+ .flags = IORESOURCE_IRQ, -+ }, - }; - - static struct platform_device mpsc1_device = { -@@ -1426,12 +1438,46 @@ mv64x60_pd_fixup(struct mv64x60_handle * - static int __init - mv64x60_add_pds(void) - { -- return platform_add_devices(mv64x60_pd_devs, -- ARRAY_SIZE(mv64x60_pd_devs)); -+ int i, ret = 0; -+ -+ for (i = 0; i < ARRAY_SIZE(mv64x60_pd_devs); i++) { -+ if (mv64x60_pd_devs[i]) { -+ ret = platform_device_register(mv64x60_pd_devs[i]); -+ } -+ if (ret) { -+ while (--i >= 0) -+ platform_device_unregister(mv64x60_pd_devs[i]); -+ break; -+ } -+ } -+ return ret; - } - arch_initcall(mv64x60_add_pds); - - /* -+ * mv64x60_early_get_pdev_data() -+ * -+ * Get the data associated with a platform device by name and number. -+ */ -+struct platform_device * __init -+mv64x60_early_get_pdev_data(const char *name, int id, int remove) -+{ -+ int i; -+ struct platform_device *pdev; -+ -+ for (i = 0; i id == id && -+ !strcmp(pdev->name, name)) { -+ if (remove) -+ mv64x60_pd_devs[i] = NULL; -+ return pdev; -+ } -+ } -+ return NULL; -+} -+ -+/* - ***************************************************************************** - * - * GT64260-Specific Routines -@@ -1764,6 +1810,11 @@ gt64260a_chip_specific_init(struct mv64x - r->start = MV64x60_IRQ_SDMA_0; - r->end = MV64x60_IRQ_SDMA_0; - } -+ if ((r = platform_get_resource(&mpsc1_device, IORESOURCE_IRQ, 1)) -+ != NULL) { -+ r->start = GT64260_IRQ_MPSC_1; -+ r->end = GT64260_IRQ_MPSC_1; -+ } - #endif - } - -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/syslib/mv64x60_dbg.c linux-2.6.18-53.1.14.kgdb/arch/ppc/syslib/mv64x60_dbg.c ---- linux-2.6.18-53.1.14/arch/ppc/syslib/mv64x60_dbg.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/syslib/mv64x60_dbg.c 2008-06-10 15:38:14.000000000 +0400 -@@ -34,7 +34,7 @@ static struct mv64x60_handle mv64x60_dbg - void - mv64x60_progress_init(u32 base) - { -- mv64x60_dbg_bh.v_base = base; -+ mv64x60_dbg_bh.v_base = (void*)base; - return; - } - -@@ -69,53 +69,3 @@ mv64x60_mpsc_progress(char *s, unsigned - return; - } - #endif /* CONFIG_SERIAL_TEXT_DEBUG */ -- -- --#if defined(CONFIG_KGDB) -- --#if defined(CONFIG_KGDB_TTYS0) --#define KGDB_PORT 0 --#elif defined(CONFIG_KGDB_TTYS1) --#define KGDB_PORT 1 --#else --#error "Invalid kgdb_tty port" --#endif -- --void --putDebugChar(unsigned char c) --{ -- mv64x60_polled_putc(KGDB_PORT, (char)c); --} -- --int --getDebugChar(void) --{ -- unsigned char c; -- -- while (!mv64x60_polled_getc(KGDB_PORT, &c)); -- return (int)c; --} -- --void --putDebugString(char* str) --{ -- while (*str != '\0') { -- putDebugChar(*str); -- str++; -- } -- putDebugChar('\r'); -- return; --} -- --void --kgdb_interruptible(int enable) --{ --} -- --void --kgdb_map_scc(void) --{ -- if (ppc_md.early_serial_map) -- ppc_md.early_serial_map(); --} --#endif /* CONFIG_KGDB */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/ppc/syslib/ppc85xx_setup.c linux-2.6.18-53.1.14.kgdb/arch/ppc/syslib/ppc85xx_setup.c ---- linux-2.6.18-53.1.14/arch/ppc/syslib/ppc85xx_setup.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/ppc/syslib/ppc85xx_setup.c 2008-06-10 15:38:14.000000000 +0400 -@@ -69,7 +69,6 @@ mpc85xx_calibrate_decr(void) - mtspr(SPRN_TCR, TCR_DIE); - } - --#ifdef CONFIG_SERIAL_8250 - void __init - mpc85xx_early_serial_map(void) - { -@@ -85,7 +84,7 @@ mpc85xx_early_serial_map(void) - pdata[0].mapbase += binfo->bi_immr_base; - pdata[0].membase = ioremap(pdata[0].mapbase, MPC85xx_UART0_SIZE); - --#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) -+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250) - memset(&serial_req, 0, sizeof (serial_req)); - serial_req.iotype = UPIO_MEM; - serial_req.mapbase = pdata[0].mapbase; -@@ -93,18 +92,24 @@ mpc85xx_early_serial_map(void) - serial_req.regshift = 0; - - gen550_init(0, &serial_req); -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_port(0, &serial_req); -+#endif - #endif - - pdata[1].uartclk = binfo->bi_busfreq; - pdata[1].mapbase += binfo->bi_immr_base; - pdata[1].membase = ioremap(pdata[1].mapbase, MPC85xx_UART0_SIZE); - --#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) -+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250) - /* Assume gen550_init() doesn't modify serial_req */ - serial_req.mapbase = pdata[1].mapbase; - serial_req.membase = pdata[1].membase; - - gen550_init(1, &serial_req); -+#ifdef CONFIG_KGDB_8250 -+ kgdb8250_add_port(1, &serial_req); -+#endif - #endif - } - #endif -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/sh/Kconfig.debug linux-2.6.18-53.1.14.kgdb/arch/sh/Kconfig.debug ---- linux-2.6.18-53.1.14/arch/sh/Kconfig.debug 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/sh/Kconfig.debug 2008-06-10 15:38:50.000000000 +0400 -@@ -29,96 +29,4 @@ config EARLY_PRINTK - This option is only useful porting the kernel to a new machine, - when the kernel may crash or hang before the serial console is - initialised. If unsure, say N. -- --config KGDB -- bool "Include KGDB kernel debugger" -- help -- Include in-kernel hooks for kgdb, the Linux kernel source level -- debugger. See for more information. -- Unless you are intending to debug the kernel, say N here. -- --menu "KGDB configuration options" -- depends on KGDB -- --config MORE_COMPILE_OPTIONS -- bool "Add any additional compile options" -- help -- If you want to add additional CFLAGS to the kernel build, enable this -- option and then enter what you would like to add in the next question. -- Note however that -g is already appended with the selection of KGDB. -- --config COMPILE_OPTIONS -- string "Additional compile arguments" -- depends on MORE_COMPILE_OPTIONS -- --config KGDB_NMI -- bool "Enter KGDB on NMI" -- default n -- --config KGDB_THREAD -- bool "Include KGDB thread support" -- default y -- --config SH_KGDB_CONSOLE -- bool "Console messages through GDB" -- default n -- --config KGDB_SYSRQ -- bool "Allow SysRq 'G' to enter KGDB" -- default y -- --config KGDB_KERNEL_ASSERTS -- bool "Include KGDB kernel assertions" -- default n -- --comment "Serial port setup" -- --config KGDB_DEFPORT -- int "Port number (ttySCn)" -- default "1" -- --config KGDB_DEFBAUD -- int "Baud rate" -- default "115200" -- --choice -- prompt "Parity" -- depends on KGDB -- default KGDB_DEFPARITY_N -- --config KGDB_DEFPARITY_N -- bool "None" -- --config KGDB_DEFPARITY_E -- bool "Even" -- --config KGDB_DEFPARITY_O -- bool "Odd" -- --endchoice -- --choice -- prompt "Data bits" -- depends on KGDB -- default KGDB_DEFBITS_8 -- --config KGDB_DEFBITS_8 -- bool "8" -- --config KGDB_DEFBITS_7 -- bool "7" -- --endchoice -- --endmenu -- --config FRAME_POINTER -- bool "Compile the kernel with frame pointers" -- default y if KGDB -- help -- If you say Y here the resulting kernel image will be slightly larger -- and slower, but it will give very useful debugging information. -- If you don't debug the kernel, you can say N, but we may not be able -- to solve problems without frame pointers. -- - endmenu -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/sh/Makefile linux-2.6.18-53.1.14.kgdb/arch/sh/Makefile ---- linux-2.6.18-53.1.14/arch/sh/Makefile 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/sh/Makefile 2008-06-10 15:38:50.000000000 +0400 -@@ -43,7 +43,6 @@ cflags-$(CONFIG_CPU_SH4) += -m4 \ - cflags-$(CONFIG_CPU_SH4A) += $(call cc-option,-m4a-nofpu,) - - cflags-$(CONFIG_SH_DSP) += -Wa,-dsp --cflags-$(CONFIG_SH_KGDB) += -g - - cflags-$(CONFIG_MORE_COMPILE_OPTIONS) += \ - $(shell echo $(CONFIG_COMPILE_OPTIONS) | sed -e 's/"//g') -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/sh/boards/se/7751/setup.c linux-2.6.18-53.1.14.kgdb/arch/sh/boards/se/7751/setup.c ---- linux-2.6.18-53.1.14/arch/sh/boards/se/7751/setup.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/sh/boards/se/7751/setup.c 2008-06-10 15:38:50.000000000 +0400 -@@ -17,10 +17,6 @@ - #include - #include - --#ifdef CONFIG_SH_KGDB --#include --#endif -- - /* - * Configure the Super I/O chip - */ -@@ -82,12 +78,6 @@ const char *get_system_type(void) - return "7751 SolutionEngine"; - } - --#ifdef CONFIG_SH_KGDB --static int kgdb_uart_setup(void); --static struct kgdb_sermap kgdb_uart_sermap = --{ "ttyS", 0, kgdb_uart_setup, NULL }; --#endif -- - /* - * Initialize the board - */ -@@ -95,133 +85,4 @@ void __init platform_setup(void) - { - /* Call init_smsc() replacement to set up SuperIO. */ - /* XXX: RTC setting comes here */ --#ifdef CONFIG_SH_KGDB -- kgdb_register_sermap(&kgdb_uart_sermap); --#endif --} -- --/********************************************************************* -- * Currently a hack (e.g. does not interact well w/serial.c, lots of * -- * hardcoded stuff) but may be useful if SCI/F needs debugging. * -- * Mostly copied from x86 code (see files asm-i386/kgdb_local.h and * -- * arch/i386/lib/kgdb_serial.c). * -- *********************************************************************/ -- --#ifdef CONFIG_SH_KGDB --#include --#include --#include --#include -- --#define COM1_PORT 0x3f8 /* Base I/O address */ --#define COM1_IRQ 4 /* IRQ not used yet */ --#define COM2_PORT 0x2f8 /* Base I/O address */ --#define COM2_IRQ 3 /* IRQ not used yet */ -- --#define SB_CLOCK 1843200 /* Serial baud clock */ --#define SB_BASE (SB_CLOCK/16) --#define SB_MCR UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS -- --struct uart_port { -- int base; --}; --#define UART_NPORTS 2 --struct uart_port uart_ports[] = { -- { COM1_PORT }, -- { COM2_PORT }, --}; --struct uart_port *kgdb_uart_port; -- --#define UART_IN(reg) inb_p(kgdb_uart_port->base + reg) --#define UART_OUT(reg,v) outb_p((v), kgdb_uart_port->base + reg) -- --/* Basic read/write functions for the UART */ --#define UART_LSR_RXCERR (UART_LSR_BI | UART_LSR_FE | UART_LSR_PE) --static int kgdb_uart_getchar(void) --{ -- int lsr; -- int c = -1; -- -- while (c == -1) { -- lsr = UART_IN(UART_LSR); -- if (lsr & UART_LSR_DR) -- c = UART_IN(UART_RX); -- if ((lsr & UART_LSR_RXCERR)) -- c = -1; -- } -- return c; --} -- --static void kgdb_uart_putchar(int c) --{ -- while ((UART_IN(UART_LSR) & UART_LSR_THRE) == 0) -- ; -- UART_OUT(UART_TX, c); --} -- --/* -- * Initialize UART to configured/requested values. -- * (But we don't interrupts yet, or interact w/serial.c) -- */ --static int kgdb_uart_setup(void) --{ -- int port; -- int lcr = 0; -- int bdiv = 0; -- -- if (kgdb_portnum >= UART_NPORTS) { -- KGDB_PRINTK("uart port %d invalid.\n", kgdb_portnum); -- return -1; -- } -- -- kgdb_uart_port = &uart_ports[kgdb_portnum]; -- -- /* Init sequence from gdb_hook_interrupt */ -- UART_IN(UART_RX); -- UART_OUT(UART_IER, 0); -- -- UART_IN(UART_RX); /* Serial driver comments say */ -- UART_IN(UART_IIR); /* this clears interrupt regs */ -- UART_IN(UART_MSR); -- -- /* Figure basic LCR values */ -- switch (kgdb_bits) { -- case '7': -- lcr |= UART_LCR_WLEN7; -- break; -- default: case '8': -- lcr |= UART_LCR_WLEN8; -- break; -- } -- switch (kgdb_parity) { -- case 'O': -- lcr |= UART_LCR_PARITY; -- break; -- case 'E': -- lcr |= (UART_LCR_PARITY | UART_LCR_EPAR); -- break; -- default: break; -- } -- -- /* Figure the baud rate divisor */ -- bdiv = (SB_BASE/kgdb_baud); -- -- /* Set the baud rate and LCR values */ -- UART_OUT(UART_LCR, (lcr | UART_LCR_DLAB)); -- UART_OUT(UART_DLL, (bdiv & 0xff)); -- UART_OUT(UART_DLM, ((bdiv >> 8) & 0xff)); -- UART_OUT(UART_LCR, lcr); -- -- /* Set the MCR */ -- UART_OUT(UART_MCR, SB_MCR); -- -- /* Turn off FIFOs for now */ -- UART_OUT(UART_FCR, 0); -- -- /* Setup complete: initialize function pointers */ -- kgdb_getchar = kgdb_uart_getchar; -- kgdb_putchar = kgdb_uart_putchar; -- -- return 0; - } --#endif /* CONFIG_SH_KGDB */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/sh/kernel/Makefile linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/Makefile ---- linux-2.6.18-53.1.14/arch/sh/kernel/Makefile 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/Makefile 2008-06-10 15:38:50.000000000 +0400 -@@ -13,7 +13,7 @@ obj-y += cpu/ timers/ - obj-$(CONFIG_SMP) += smp.o - obj-$(CONFIG_CF_ENABLER) += cf-enabler.o - obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o --obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o -+obj-$(CONFIG_KGDB) += kgdb.o kgdb-jmp.o - obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o - obj-$(CONFIG_MODULES) += module.o - obj-$(CONFIG_EARLY_PRINTK) += early_printk.o -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/sh/kernel/cpu/sh3/ex.S linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/cpu/sh3/ex.S ---- linux-2.6.18-53.1.14/arch/sh/kernel/cpu/sh3/ex.S 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/cpu/sh3/ex.S 2008-06-10 15:38:50.000000000 +0400 -@@ -42,7 +42,7 @@ ENTRY(exception_handling_table) - .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */ - .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/ - ENTRY(nmi_slot) --#if defined (CONFIG_KGDB_NMI) -+#if defined (CONFIG_KGDB) - .long debug_enter /* 1C0 */ ! Allow trap to debugger - #else - .long exception_none /* 1C0 */ ! Not implemented yet -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/sh/kernel/cpu/sh4/ex.S linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/cpu/sh4/ex.S ---- linux-2.6.18-53.1.14/arch/sh/kernel/cpu/sh4/ex.S 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/cpu/sh4/ex.S 2008-06-10 15:38:50.000000000 +0400 -@@ -46,7 +46,7 @@ ENTRY(exception_handling_table) - .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */ - .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/ - ENTRY(nmi_slot) --#if defined (CONFIG_KGDB_NMI) -+#if defined (CONFIG_KGDB) - .long debug_enter /* 1C0 */ ! Allow trap to debugger - #else - .long exception_none /* 1C0 */ ! Not implemented yet -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/sh/kernel/entry.S linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/entry.S ---- linux-2.6.18-53.1.14/arch/sh/kernel/entry.S 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/entry.S 2008-06-10 15:38:50.000000000 +0400 -@@ -75,7 +75,7 @@ - ENOSYS = 38 - EINVAL = 22 - --#if defined(CONFIG_KGDB_NMI) -+#if defined(CONFIG_KGDB) - NMI_VEC = 0x1c0 ! Must catch early for debounce - #endif - -@@ -227,31 +227,33 @@ call_dae: - 2: .long do_address_error - #endif /* CONFIG_MMU */ - --#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) -+#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_KGDB) - ! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present. - ! If both are configured, handle the debug traps (breakpoints) in SW, - ! but still allow BIOS traps to FW. - - .align 2 - debug_kernel: --#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB) -+#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_KGDB) - /* Force BIOS call to FW (debug_trap put TRA in r8) */ - mov r8,r0 - shlr2 r0 - cmp/eq #0x3f,r0 - bt debug_kernel_fw --#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */ -+#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_KGDB */ - -+ .align 2 -+ .globl debug_enter - debug_enter: --#if defined(CONFIG_SH_KGDB) -+#if defined(CONFIG_KGDB) - /* Jump to kgdb, pass stacked regs as arg */ - debug_kernel_sw: - mov.l 3f, r0 - jmp @r0 - mov r15, r4 - .align 2 --3: .long kgdb_handle_exception --#endif /* CONFIG_SH_KGDB */ -+3: .long kgdb_exception_handler -+#endif /* CONFIG_KGDB */ - - #if defined(CONFIG_SH_STANDARD_BIOS) - /* Unwind the stack and jmp to the debug entry */ -@@ -293,12 +295,12 @@ debug_kernel_fw: - 2: .long gdb_vbr_vector - #endif /* CONFIG_SH_STANDARD_BIOS */ - --#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ -+#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_KGDB */ - - - .align 2 - debug_trap: --#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) -+#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_KGDB) - mov #OFF_SR, r0 - mov.l @(r0,r15), r0 ! get status register - shll r0 -@@ -642,7 +644,7 @@ skip_restore: - 6: or k0, k2 ! Set the IMASK-bits - ldc k2, ssr - ! --#if defined(CONFIG_KGDB_NMI) -+#if defined(CONFIG_KGDB) - ! Clear in_nmi - mov.l 4f, k0 - mov #0, k1 -@@ -694,7 +696,7 @@ tlb_miss: - interrupt: - mov.l 2f, k2 - mov.l 3f, k3 --#if defined(CONFIG_KGDB_NMI) -+#if defined(CONFIG_KGDB) - ! Debounce (filter nested NMI) - mov.l @k2, k0 - mov.l 5f, k1 -@@ -709,7 +711,7 @@ interrupt: - 5: .long NMI_VEC - 6: .long in_nmi - 0: --#endif /* defined(CONFIG_KGDB_NMI) */ -+#endif /* defined(CONFIG_KGDB) */ - bra handle_exception - mov.l @k2, k2 - -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/sh/kernel/kgdb-jmp.S linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/kgdb-jmp.S ---- linux-2.6.18-53.1.14/arch/sh/kernel/kgdb-jmp.S 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/kgdb-jmp.S 2008-06-10 15:38:50.000000000 +0400 -@@ -0,0 +1,32 @@ -+#include -+ -+ENTRY(kgdb_fault_setjmp) -+ add #(9*4), r4 -+ sts.l pr, @-r4 -+ mov.l r15, @-r4 -+ mov.l r14, @-r4 -+ mov.l r13, @-r4 -+ mov.l r12, @-r4 -+ mov.l r11, @-r4 -+ mov.l r10, @-r4 -+ mov.l r9, @-r4 -+ mov.l r8, @-r4 -+ rts -+ mov #0, r0 -+ -+ENTRY(kgdb_fault_longjmp) -+ mov.l @r4+, r8 -+ mov.l @r4+, r9 -+ mov.l @r4+, r10 -+ mov.l @r4+, r11 -+ mov.l @r4+, r12 -+ mov.l @r4+, r13 -+ mov.l @r4+, r14 -+ mov.l @r4+, r15 -+ lds.l @r4+, pr -+ mov r5, r0 -+ tst r0, r0 -+ bf 1f -+ mov #1, r0 -+1: rts -+ nop -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/sh/kernel/kgdb.c linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/kgdb.c ---- linux-2.6.18-53.1.14/arch/sh/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/kgdb.c 2008-06-10 15:38:50.000000000 +0400 -@@ -0,0 +1,363 @@ -+/* -+ * arch/sh/kernel/kgdb.c -+ * -+ * Contains SH-specific low-level support for KGDB. -+ * -+ * Containes extracts from code by Glenn Engel, Jim Kingdon, -+ * David Grothe , Tigran Aivazian , -+ * Amit S. Kale , William Gatliff , -+ * Ben Lee, Steve Chamberlain and Benoit Miller , -+ * Henry Bell and Jeremy Siegel -+ * -+ * Maintainer: Tom Rini -+ * -+ * 2004 (c) MontaVista Software, Inc. This file is licensed under -+ * the terms of the GNU General Public License version 2. This program -+ * is licensed "as is" without any warranty of any kind, whether express -+ * or implied. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+extern void per_cpu_trap_init(void); -+extern atomic_t cpu_doing_single_step; -+ -+/* Function pointers for linkage */ -+static struct kgdb_regs trap_registers; -+ -+/* Globals. */ -+char in_nmi; /* Set during NMI to prevent reentry */ -+ -+/* TRA differs sh3/4 */ -+#if defined(CONFIG_CPU_SH3) -+#define TRA 0xffffffd0 -+#elif defined(CONFIG_CPU_SH4) -+#define TRA 0xff000020 -+#endif -+ -+/* Macros for single step instruction identification */ -+#define OPCODE_BT(op) (((op) & 0xff00) == 0x8900) -+#define OPCODE_BF(op) (((op) & 0xff00) == 0x8b00) -+#define OPCODE_BTF_DISP(op) (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \ -+ (((op) & 0x7f ) << 1)) -+#define OPCODE_BFS(op) (((op) & 0xff00) == 0x8f00) -+#define OPCODE_BTS(op) (((op) & 0xff00) == 0x8d00) -+#define OPCODE_BRA(op) (((op) & 0xf000) == 0xa000) -+#define OPCODE_BRA_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \ -+ (((op) & 0x7ff) << 1)) -+#define OPCODE_BRAF(op) (((op) & 0xf0ff) == 0x0023) -+#define OPCODE_BRAF_REG(op) (((op) & 0x0f00) >> 8) -+#define OPCODE_BSR(op) (((op) & 0xf000) == 0xb000) -+#define OPCODE_BSR_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \ -+ (((op) & 0x7ff) << 1)) -+#define OPCODE_BSRF(op) (((op) & 0xf0ff) == 0x0003) -+#define OPCODE_BSRF_REG(op) (((op) >> 8) & 0xf) -+#define OPCODE_JMP(op) (((op) & 0xf0ff) == 0x402b) -+#define OPCODE_JMP_REG(op) (((op) >> 8) & 0xf) -+#define OPCODE_JSR(op) (((op) & 0xf0ff) == 0x400b) -+#define OPCODE_JSR_REG(op) (((op) >> 8) & 0xf) -+#define OPCODE_RTS(op) ((op) == 0xb) -+#define OPCODE_RTE(op) ((op) == 0x2b) -+ -+#define SR_T_BIT_MASK 0x1 -+#define STEP_OPCODE 0xc320 -+#define BIOS_CALL_TRAP 0x3f -+ -+/* Exception codes as per SH-4 core manual */ -+#define ADDRESS_ERROR_LOAD_VEC 7 -+#define ADDRESS_ERROR_STORE_VEC 8 -+#define TRAP_VEC 11 -+#define INVALID_INSN_VEC 12 -+#define INVALID_SLOT_VEC 13 -+#define NMI_VEC 14 -+#define SERIAL_BREAK_VEC 58 -+ -+/* Misc static */ -+static int stepped_address; -+static short stepped_opcode; -+ -+/* Translate SH-3/4 exception numbers to unix-like signal values */ -+static int compute_signal(const int excep_code) -+{ -+ switch (excep_code) { -+ case INVALID_INSN_VEC: -+ case INVALID_SLOT_VEC: -+ return SIGILL; -+ case ADDRESS_ERROR_LOAD_VEC: -+ case ADDRESS_ERROR_STORE_VEC: -+ return SIGSEGV; -+ case SERIAL_BREAK_VEC: -+ case NMI_VEC: -+ return SIGINT; -+ default: -+ /* Act like it was a break/trap. */ -+ return SIGTRAP; -+ } -+} -+ -+/* -+ * Translate the registers of the system into the format that GDB wants. Since -+ * we use a local structure to store things, instead of getting them out -+ * of pt_regs, we can just do a memcpy. -+ */ -+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *ign) -+{ -+ memcpy(gdb_regs, &trap_registers, sizeof(trap_registers)); -+} -+ -+/* -+ * On SH we save: r1 (prev->thread.sp) r2 (prev->thread.pc) r4 (prev) r5 (next) -+ * r6 (next->thread.sp) r7 (next->thread.pc) -+ */ -+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) -+{ -+ int count; -+ -+ for (count = 0; count < 16; count++) -+ *(gdb_regs++) = 0; -+ *(gdb_regs++) = p->thread.pc; -+ *(gdb_regs++) = 0; -+ *(gdb_regs++) = 0; -+ *(gdb_regs++) = 0; -+ *(gdb_regs++) = 0; -+ *(gdb_regs++) = 0; -+ *(gdb_regs++) = 0; -+} -+ -+/* -+ * Translate the registers values that GDB has given us back into the -+ * format of the system. See the comment above about memcpy. -+ */ -+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *ign) -+{ -+ memcpy(&trap_registers, gdb_regs, sizeof(trap_registers)); -+} -+ -+/* Calculate the new address for after a step */ -+static short *get_step_address(void) -+{ -+ short op = *(short *)trap_registers.pc; -+ long addr; -+ -+ /* BT */ -+ if (OPCODE_BT(op)) { -+ if (trap_registers.sr & SR_T_BIT_MASK) -+ addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op); -+ else -+ addr = trap_registers.pc + 2; -+ } -+ -+ /* BTS */ -+ else if (OPCODE_BTS(op)) { -+ if (trap_registers.sr & SR_T_BIT_MASK) -+ addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op); -+ else -+ addr = trap_registers.pc + 4; /* Not in delay slot */ -+ } -+ -+ /* BF */ -+ else if (OPCODE_BF(op)) { -+ if (!(trap_registers.sr & SR_T_BIT_MASK)) -+ addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op); -+ else -+ addr = trap_registers.pc + 2; -+ } -+ -+ /* BFS */ -+ else if (OPCODE_BFS(op)) { -+ if (!(trap_registers.sr & SR_T_BIT_MASK)) -+ addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op); -+ else -+ addr = trap_registers.pc + 4; /* Not in delay slot */ -+ } -+ -+ /* BRA */ -+ else if (OPCODE_BRA(op)) -+ addr = trap_registers.pc + 4 + OPCODE_BRA_DISP(op); -+ -+ /* BRAF */ -+ else if (OPCODE_BRAF(op)) -+ addr = trap_registers.pc + 4 -+ + trap_registers.regs[OPCODE_BRAF_REG(op)]; -+ -+ /* BSR */ -+ else if (OPCODE_BSR(op)) -+ addr = trap_registers.pc + 4 + OPCODE_BSR_DISP(op); -+ -+ /* BSRF */ -+ else if (OPCODE_BSRF(op)) -+ addr = trap_registers.pc + 4 -+ + trap_registers.regs[OPCODE_BSRF_REG(op)]; -+ -+ /* JMP */ -+ else if (OPCODE_JMP(op)) -+ addr = trap_registers.regs[OPCODE_JMP_REG(op)]; -+ -+ /* JSR */ -+ else if (OPCODE_JSR(op)) -+ addr = trap_registers.regs[OPCODE_JSR_REG(op)]; -+ -+ /* RTS */ -+ else if (OPCODE_RTS(op)) -+ addr = trap_registers.pr; -+ -+ /* RTE */ -+ else if (OPCODE_RTE(op)) -+ addr = trap_registers.regs[15]; -+ -+ /* Other */ -+ else -+ addr = trap_registers.pc + 2; -+ -+ kgdb_flush_icache_range(addr, addr + 2); -+ return (short *)addr; -+} -+ -+/* The command loop, read and act on requests */ -+int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, -+ char *remcom_in_buffer, char *remcom_out_buffer, -+ struct pt_regs *ign) -+{ -+ unsigned long addr; -+ char *ptr = &remcom_in_buffer[1]; -+ -+ /* Examine first char of buffer to see what we need to do */ -+ switch (remcom_in_buffer[0]) { -+ case 'c': /* Continue at address AA..AA (optional) */ -+ case 's': /* Step one instruction from AA..AA */ -+ /* Try to read optional parameter, PC unchanged if none */ -+ if (kgdb_hex2long(&ptr, &addr)) -+ trap_registers.pc = addr; -+ -+ atomic_set(&cpu_doing_single_step, -1); -+ if (remcom_in_buffer[0] == 's') { -+ /* Replace the instruction immediately after the -+ * current instruction (i.e. next in the expected -+ * flow of control) with a trap instruction, so that -+ * returning will cause only a single instruction to -+ * be executed. Note that this model is slightly -+ * broken for instructions with delay slots -+ * (e.g. B[TF]S, BSR, BRA etc), where both the branch -+ * and the instruction in the delay slot will be -+ * executed. -+ */ -+ /* Determine where the target instruction will send -+ * us to */ -+ unsigned short *next_addr = get_step_address(); -+ stepped_address = (int)next_addr; -+ -+ /* Replace it */ -+ stepped_opcode = *(short *)next_addr; -+ *next_addr = STEP_OPCODE; -+ -+ /* Flush and return */ -+ kgdb_flush_icache_range((long)next_addr, -+ (long)next_addr + 2); -+ if (kgdb_contthread) -+ atomic_set(&cpu_doing_single_step, -+ smp_processor_id()); -+ } -+ return 0; -+ } -+ return -1; -+} -+ -+/* -+ * When an exception has occured, we are called. We need to set things -+ * up so that we can call kgdb_handle_exception to handle requests from -+ * the remote GDB. -+ */ -+void kgdb_exception_handler(struct pt_regs *regs) -+{ -+ int excep_code, vbr_val; -+ int count; -+ -+ /* Copy kernel regs (from stack) */ -+ for (count = 0; count < 16; count++) -+ trap_registers.regs[count] = regs->regs[count]; -+ trap_registers.pc = regs->pc; -+ trap_registers.pr = regs->pr; -+ trap_registers.sr = regs->sr; -+ trap_registers.gbr = regs->gbr; -+ trap_registers.mach = regs->mach; -+ trap_registers.macl = regs->macl; -+ -+ __asm__ __volatile__("stc vbr, %0":"=r"(vbr_val)); -+ trap_registers.vbr = vbr_val; -+ -+ /* Get the execption code. */ -+ __asm__ __volatile__("stc r2_bank, %0":"=r"(excep_code)); -+ -+ excep_code >>= 5; -+ -+ /* If we got an NMI, and KGDB is not yet initialized, call -+ * breakpoint() to try and initialize everything for us. */ -+ if (excep_code == NMI_VEC && !kgdb_initialized) { -+ breakpoint(); -+ return; -+ } -+ -+ /* TRAP_VEC exception indicates a software trap inserted in place of -+ * code by GDB so back up PC by one instruction, as this instruction -+ * will later be replaced by its original one. Do NOT do this for -+ * trap 0xff, since that indicates a compiled-in breakpoint which -+ * will not be replaced (and we would retake the trap forever) */ -+ if (excep_code == TRAP_VEC && -+ (*(volatile unsigned long *)TRA != (0xff << 2))) -+ trap_registers.pc -= 2; -+ -+ /* If we have been single-stepping, put back the old instruction. -+ * We use stepped_address in case we have stopped more than one -+ * instruction away. */ -+ if (stepped_opcode != 0) { -+ *(short *)stepped_address = stepped_opcode; -+ kgdb_flush_icache_range(stepped_address, stepped_address + 2); -+ } -+ stepped_opcode = 0; -+ -+ /* Call the stub to do the processing. Note that not everything we -+ * need to send back and forth lives in pt_regs. */ -+ kgdb_handle_exception(excep_code, compute_signal(excep_code), 0, regs); -+ -+ /* Copy back the (maybe modified) registers */ -+ for (count = 0; count < 16; count++) -+ regs->regs[count] = trap_registers.regs[count]; -+ regs->pc = trap_registers.pc; -+ regs->pr = trap_registers.pr; -+ regs->sr = trap_registers.sr; -+ regs->gbr = trap_registers.gbr; -+ regs->mach = trap_registers.mach; -+ regs->macl = trap_registers.macl; -+ -+ vbr_val = trap_registers.vbr; -+ __asm__ __volatile__("ldc %0, vbr": :"r"(vbr_val)); -+} -+ -+int __init kgdb_arch_init(void) -+{ -+ per_cpu_trap_init(); -+ -+ return 0; -+} -+ -+struct kgdb_arch arch_kgdb_ops = { -+#ifdef CONFIG_CPU_LITTLE_ENDIAN -+ .gdb_bpt_instr = {0xff, 0xc3}, -+#else -+ .gdb_bpt_instr = {0xc3, 0xff}, -+#endif -+}; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/sh/kernel/kgdb_jmp.S linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/kgdb_jmp.S ---- linux-2.6.18-53.1.14/arch/sh/kernel/kgdb_jmp.S 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/kgdb_jmp.S 1970-01-01 03:00:00.000000000 +0300 -@@ -1,33 +0,0 @@ --#include -- --ENTRY(setjmp) -- add #(9*4), r4 -- sts.l pr, @-r4 -- mov.l r15, @-r4 -- mov.l r14, @-r4 -- mov.l r13, @-r4 -- mov.l r12, @-r4 -- mov.l r11, @-r4 -- mov.l r10, @-r4 -- mov.l r9, @-r4 -- mov.l r8, @-r4 -- rts -- mov #0, r0 -- --ENTRY(longjmp) -- mov.l @r4+, r8 -- mov.l @r4+, r9 -- mov.l @r4+, r10 -- mov.l @r4+, r11 -- mov.l @r4+, r12 -- mov.l @r4+, r13 -- mov.l @r4+, r14 -- mov.l @r4+, r15 -- lds.l @r4+, pr -- mov r5, r0 -- tst r0, r0 -- bf 1f -- mov #1, r0 ! in case val==0 --1: rts -- nop -- -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/sh/kernel/kgdb_stub.c linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/kgdb_stub.c ---- linux-2.6.18-53.1.14/arch/sh/kernel/kgdb_stub.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/kgdb_stub.c 1970-01-01 03:00:00.000000000 +0300 -@@ -1,1491 +0,0 @@ --/* -- * May be copied or modified under the terms of the GNU General Public -- * License. See linux/COPYING for more information. -- * -- * Containes extracts from code by Glenn Engel, Jim Kingdon, -- * David Grothe , Tigran Aivazian , -- * Amit S. Kale , William Gatliff , -- * Ben Lee, Steve Chamberlain and Benoit Miller . -- * -- * This version by Henry Bell -- * Minor modifications by Jeremy Siegel -- * -- * Contains low-level support for remote debug using GDB. -- * -- * To enable debugger support, two things need to happen. 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. -- * A breakpoint also needs to be generated to begin communication. This -- * is most easily accomplished by a call to breakpoint() which does -- * a trapa if the initialisation phase has been successfully completed. -- * -- * In this case, set_debug_traps() is not used to "take over" exceptions; -- * other kernel code is modified instead to enter the kgdb functions here -- * when appropriate (see entry.S for breakpoint traps and NMI interrupts, -- * see traps.c for kernel error exceptions). -- * -- * 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 -- * XAA..AA,LLLL: Same, but data is binary (not hex) OK or ENN -- * -- * c Resume at current address SNN ( signal NN) -- * cAA..AA Continue at address AA..AA SNN -- * CNN; Resume at current address with signal SNN -- * CNN;AA..AA Resume at address AA..AA with signal SNN -- * -- * s Step one instruction SNN -- * sAA..AA Step one instruction from AA..AA SNN -- * SNN; Step one instruction with signal SNN -- * SNNAA..AA Step one instruction from AA..AA w/NN SNN -- * -- * k kill (Detach GDB) -- * -- * d Toggle debug flag -- * D Detach GDB -- * -- * Hct Set thread t for operations, OK or ENN -- * c = 'c' (step, cont), c = 'g' (other -- * operations) -- * -- * qC Query current thread ID QCpid -- * qfThreadInfo Get list of current threads (first) m -- * qsThreadInfo " " " " " (subsequent) -- * qOffsets Get section offsets Text=x;Data=y;Bss=z -- * -- * TXX Find if thread XX is alive OK or ENN -- * ? What was the last sigval ? SNN (signal NN) -- * O Output to GDB console -- * -- * Remote communication protocol. -- * -- * A debug packet whose contents are is encapsulated for -- * transmission in the form: -- * -- * $ # CSUM1 CSUM2 -- * -- * must be ASCII alphanumeric and cannot include characters -- * '$' or '#'. If starts with two characters followed by -- * ':', then the existing stubs interpret this as a sequence number. -- * -- * CSUM1 and CSUM2 are ascii hex representation of an 8-bit -- * checksum of , the most significant nibble is sent first. -- * the hex digits 0-9,a-f are used. -- * -- * Receiver responds with: -- * -- * + - if CSUM is correct and ready for next packet -- * - - if CSUM is incorrect -- * -- * Responses can be run-length encoded to save space. A '*' means that -- * the next character is an ASCII encoding giving a repeat count which -- * stands for that many repititions of the character preceding the '*'. -- * The encoding is n+29, yielding a printable character where n >=3 -- * (which is where RLE starts to win). Don't use an n > 126. -- * -- * So "0* " means the same as "0000". -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include -- --#include --#include --#include --#include --#include --#include -- --#ifdef CONFIG_SH_KGDB_CONSOLE --#include --#endif -- --/* Function pointers for linkage */ --kgdb_debug_hook_t *kgdb_debug_hook; --kgdb_bus_error_hook_t *kgdb_bus_err_hook; -- --int (*kgdb_getchar)(void); --void (*kgdb_putchar)(int); -- --static void put_debug_char(int c) --{ -- if (!kgdb_putchar) -- return; -- (*kgdb_putchar)(c); --} --static int get_debug_char(void) --{ -- if (!kgdb_getchar) -- return -1; -- return (*kgdb_getchar)(); --} -- --/* Num chars in in/out bound buffers, register packets need NUMREGBYTES * 2 */ --#define BUFMAX 1024 --#define NUMREGBYTES (MAXREG*4) --#define OUTBUFMAX (NUMREGBYTES*2+512) -- --enum regs { -- R0 = 0, R1, R2, R3, R4, R5, R6, R7, -- R8, R9, R10, R11, R12, R13, R14, R15, -- PC, PR, GBR, VBR, MACH, MACL, SR, -- /* */ -- MAXREG --}; -- --static unsigned int registers[MAXREG]; --struct kgdb_regs trap_registers; -- --char kgdb_in_gdb_mode; --char in_nmi; /* Set during NMI to prevent reentry */ --int kgdb_nofault; /* Boolean to ignore bus errs (i.e. in GDB) */ --int kgdb_enabled = 1; /* Default to enabled, cmdline can disable */ --int kgdb_halt; -- --/* Exposed for user access */ --struct task_struct *kgdb_current; --unsigned int kgdb_g_imask; --int kgdb_trapa_val; --int kgdb_excode; -- --/* Default values for SCI (can override via kernel args in setup.c) */ --#ifndef CONFIG_KGDB_DEFPORT --#define CONFIG_KGDB_DEFPORT 1 --#endif -- --#ifndef CONFIG_KGDB_DEFBAUD --#define CONFIG_KGDB_DEFBAUD 115200 --#endif -- --#if defined(CONFIG_KGDB_DEFPARITY_E) --#define CONFIG_KGDB_DEFPARITY 'E' --#elif defined(CONFIG_KGDB_DEFPARITY_O) --#define CONFIG_KGDB_DEFPARITY 'O' --#else /* CONFIG_KGDB_DEFPARITY_N */ --#define CONFIG_KGDB_DEFPARITY 'N' --#endif -- --#ifdef CONFIG_KGDB_DEFBITS_7 --#define CONFIG_KGDB_DEFBITS '7' --#else /* CONFIG_KGDB_DEFBITS_8 */ --#define CONFIG_KGDB_DEFBITS '8' --#endif -- --/* SCI/UART settings, used in kgdb_console_setup() */ --int kgdb_portnum = CONFIG_KGDB_DEFPORT; --int kgdb_baud = CONFIG_KGDB_DEFBAUD; --char kgdb_parity = CONFIG_KGDB_DEFPARITY; --char kgdb_bits = CONFIG_KGDB_DEFBITS; -- --/* Jump buffer for setjmp/longjmp */ --static jmp_buf rem_com_env; -- --/* TRA differs sh3/4 */ --#if defined(CONFIG_CPU_SH3) --#define TRA 0xffffffd0 --#elif defined(CONFIG_CPU_SH4) --#define TRA 0xff000020 --#endif -- --/* Macros for single step instruction identification */ --#define OPCODE_BT(op) (((op) & 0xff00) == 0x8900) --#define OPCODE_BF(op) (((op) & 0xff00) == 0x8b00) --#define OPCODE_BTF_DISP(op) (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \ -- (((op) & 0x7f ) << 1)) --#define OPCODE_BFS(op) (((op) & 0xff00) == 0x8f00) --#define OPCODE_BTS(op) (((op) & 0xff00) == 0x8d00) --#define OPCODE_BRA(op) (((op) & 0xf000) == 0xa000) --#define OPCODE_BRA_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \ -- (((op) & 0x7ff) << 1)) --#define OPCODE_BRAF(op) (((op) & 0xf0ff) == 0x0023) --#define OPCODE_BRAF_REG(op) (((op) & 0x0f00) >> 8) --#define OPCODE_BSR(op) (((op) & 0xf000) == 0xb000) --#define OPCODE_BSR_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \ -- (((op) & 0x7ff) << 1)) --#define OPCODE_BSRF(op) (((op) & 0xf0ff) == 0x0003) --#define OPCODE_BSRF_REG(op) (((op) >> 8) & 0xf) --#define OPCODE_JMP(op) (((op) & 0xf0ff) == 0x402b) --#define OPCODE_JMP_REG(op) (((op) >> 8) & 0xf) --#define OPCODE_JSR(op) (((op) & 0xf0ff) == 0x400b) --#define OPCODE_JSR_REG(op) (((op) >> 8) & 0xf) --#define OPCODE_RTS(op) ((op) == 0xb) --#define OPCODE_RTE(op) ((op) == 0x2b) -- --#define SR_T_BIT_MASK 0x1 --#define STEP_OPCODE 0xc320 --#define BIOS_CALL_TRAP 0x3f -- --/* Exception codes as per SH-4 core manual */ --#define ADDRESS_ERROR_LOAD_VEC 7 --#define ADDRESS_ERROR_STORE_VEC 8 --#define TRAP_VEC 11 --#define INVALID_INSN_VEC 12 --#define INVALID_SLOT_VEC 13 --#define NMI_VEC 14 --#define USER_BREAK_VEC 15 --#define SERIAL_BREAK_VEC 58 -- --/* Misc static */ --static int stepped_address; --static short stepped_opcode; --static const char hexchars[] = "0123456789abcdef"; --static char in_buffer[BUFMAX]; --static char out_buffer[OUTBUFMAX]; -- --static void kgdb_to_gdb(const char *s); -- --#ifdef CONFIG_KGDB_THREAD --static struct task_struct *trapped_thread; --static struct task_struct *current_thread; --typedef unsigned char threadref[8]; --#define BUF_THREAD_ID_SIZE 16 --#endif -- --/* Return addr as a real volatile address */ --static inline unsigned int ctrl_inl(const unsigned long addr) --{ -- return *(volatile unsigned long *) addr; --} -- --/* Correctly set *addr using volatile */ --static inline void ctrl_outl(const unsigned int b, unsigned long addr) --{ -- *(volatile unsigned long *) addr = b; --} -- --/* Get high hex bits */ --static char highhex(const int x) --{ -- return hexchars[(x >> 4) & 0xf]; --} -- --/* Get low hex bits */ --static char lowhex(const int x) --{ -- return hexchars[x & 0xf]; --} -- --/* Convert ch to hex */ --static int hex(const 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); --} -- --/* Convert the memory pointed to by mem into hex, placing result in buf. -- Returns a pointer to the last char put in buf (null) */ --static char *mem_to_hex(const char *mem, char *buf, const int count) --{ -- int i; -- int ch; -- unsigned short s_val; -- unsigned long l_val; -- -- /* Check for 16 or 32 */ -- if (count == 2 && ((long) mem & 1) == 0) { -- s_val = *(unsigned short *) mem; -- mem = (char *) &s_val; -- } else if (count == 4 && ((long) mem & 3) == 0) { -- l_val = *(unsigned long *) mem; -- mem = (char *) &l_val; -- } -- for (i = 0; i < count; i++) { -- ch = *mem++; -- *buf++ = highhex(ch); -- *buf++ = lowhex(ch); -- } -- *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 *hex_to_mem(const char *buf, char *mem, const int count) --{ -- int i; -- unsigned char ch; -- -- for (i = 0; i < count; i++) { -- ch = hex(*buf++) << 4; -- ch = ch + hex(*buf++); -- *mem++ = ch; -- } -- return (mem); --} -- --/* While finding valid hex chars, convert to an integer, then return it */ --static int hex_to_int(char **ptr, int *int_value) --{ -- int num_chars = 0; -- int hex_value; -- -- *int_value = 0; -- -- while (**ptr) { -- hex_value = hex(**ptr); -- if (hex_value >= 0) { -- *int_value = (*int_value << 4) | hex_value; -- num_chars++; -- } else -- break; -- (*ptr)++; -- } -- return num_chars; --} -- --/* Copy the binary array pointed to by buf into mem. Fix $, #, -- and 0x7d escaped with 0x7d. Return a pointer to the character -- after the last byte written. */ --static char *ebin_to_mem(const char *buf, char *mem, int count) --{ -- for (; count > 0; count--, buf++) { -- if (*buf == 0x7d) -- *mem++ = *(++buf) ^ 0x20; -- else -- *mem++ = *buf; -- } -- return mem; --} -- --/* Pack a hex byte */ --static char *pack_hex_byte(char *pkt, int byte) --{ -- *pkt++ = hexchars[(byte >> 4) & 0xf]; -- *pkt++ = hexchars[(byte & 0xf)]; -- return pkt; --} -- --#ifdef CONFIG_KGDB_THREAD -- --/* Pack a thread ID */ --static char *pack_threadid(char *pkt, threadref * id) --{ -- char *limit; -- unsigned char *altid; -- -- altid = (unsigned char *) id; -- -- limit = pkt + BUF_THREAD_ID_SIZE; -- while (pkt < limit) -- pkt = pack_hex_byte(pkt, *altid++); -- return pkt; --} -- --/* Convert an integer into our threadref */ --static void int_to_threadref(threadref * id, const int value) --{ -- unsigned char *scan = (unsigned char *) id; -- int i = 4; -- -- while (i--) -- *scan++ = 0; -- -- *scan++ = (value >> 24) & 0xff; -- *scan++ = (value >> 16) & 0xff; -- *scan++ = (value >> 8) & 0xff; -- *scan++ = (value & 0xff); --} -- --/* Return a task structure ptr for a particular pid */ --static struct task_struct *get_thread(int pid) --{ -- struct task_struct *thread; -- -- /* Use PID_MAX w/gdb for pid 0 */ -- if (pid == PID_MAX) pid = 0; -- -- /* First check via PID */ -- thread = find_task_by_pid(pid); -- -- if (thread) -- return thread; -- -- /* Start at the start */ -- thread = init_tasks[0]; -- -- /* Walk along the linked list of tasks */ -- do { -- if (thread->pid == pid) -- return thread; -- thread = thread->next_task; -- } while (thread != init_tasks[0]); -- -- return NULL; --} -- --#endif /* CONFIG_KGDB_THREAD */ -- --/* Scan for the start char '$', read the packet and check the checksum */ --static void get_packet(char *buffer, int buflen) --{ -- unsigned char checksum; -- unsigned char xmitcsum; -- int i; -- int count; -- char ch; -- -- do { -- /* Ignore everything until the start character */ -- while ((ch = get_debug_char()) != '$'); -- -- checksum = 0; -- xmitcsum = -1; -- count = 0; -- -- /* Now, read until a # or end of buffer is found */ -- while (count < (buflen - 1)) { -- ch = get_debug_char(); -- -- if (ch == '#') -- break; -- -- checksum = checksum + ch; -- buffer[count] = ch; -- count = count + 1; -- } -- -- buffer[count] = 0; -- -- /* Continue to read checksum following # */ -- if (ch == '#') { -- xmitcsum = hex(get_debug_char()) << 4; -- xmitcsum += hex(get_debug_char()); -- -- /* Checksum */ -- if (checksum != xmitcsum) -- put_debug_char('-'); /* Failed checksum */ -- else { -- /* Ack successful transfer */ -- put_debug_char('+'); -- -- /* If a sequence char is present, reply -- the sequence ID */ -- if (buffer[2] == ':') { -- put_debug_char(buffer[0]); -- put_debug_char(buffer[1]); -- -- /* Remove sequence chars from buffer */ -- count = strlen(buffer); -- for (i = 3; i <= count; i++) -- buffer[i - 3] = buffer[i]; -- } -- } -- } -- } -- while (checksum != xmitcsum); /* Keep trying while we fail */ --} -- --/* Send the packet in the buffer with run-length encoding */ --static void put_packet(char *buffer) --{ -- int checksum; -- char *src; -- int runlen; -- int encode; -- -- do { -- src = buffer; -- put_debug_char('$'); -- checksum = 0; -- -- /* Continue while we still have chars left */ -- while (*src) { -- /* Check for runs up to 99 chars long */ -- for (runlen = 1; runlen < 99; runlen++) { -- if (src[0] != src[runlen]) -- break; -- } -- -- if (runlen > 3) { -- /* Got a useful amount, send encoding */ -- encode = runlen + ' ' - 4; -- put_debug_char(*src); checksum += *src; -- put_debug_char('*'); checksum += '*'; -- put_debug_char(encode); checksum += encode; -- src += runlen; -- } else { -- /* Otherwise just send the current char */ -- put_debug_char(*src); checksum += *src; -- src += 1; -- } -- } -- -- /* '#' Separator, put high and low components of checksum */ -- put_debug_char('#'); -- put_debug_char(highhex(checksum)); -- put_debug_char(lowhex(checksum)); -- } -- while ((get_debug_char()) != '+'); /* While no ack */ --} -- --/* A bus error has occurred - perform a longjmp to return execution and -- allow handling of the error */ --static void kgdb_handle_bus_error(void) --{ -- longjmp(rem_com_env, 1); --} -- --/* Translate SH-3/4 exception numbers to unix-like signal values */ --static int compute_signal(const int excep_code) --{ -- int sigval; -- -- switch (excep_code) { -- -- case INVALID_INSN_VEC: -- case INVALID_SLOT_VEC: -- sigval = SIGILL; -- break; -- case ADDRESS_ERROR_LOAD_VEC: -- case ADDRESS_ERROR_STORE_VEC: -- sigval = SIGSEGV; -- break; -- -- case SERIAL_BREAK_VEC: -- case NMI_VEC: -- sigval = SIGINT; -- break; -- -- case USER_BREAK_VEC: -- case TRAP_VEC: -- sigval = SIGTRAP; -- break; -- -- default: -- sigval = SIGBUS; /* "software generated" */ -- break; -- } -- -- return (sigval); --} -- --/* Make a local copy of the registers passed into the handler (bletch) */ --static void kgdb_regs_to_gdb_regs(const struct kgdb_regs *regs, -- int *gdb_regs) --{ -- gdb_regs[R0] = regs->regs[R0]; -- gdb_regs[R1] = regs->regs[R1]; -- gdb_regs[R2] = regs->regs[R2]; -- gdb_regs[R3] = regs->regs[R3]; -- gdb_regs[R4] = regs->regs[R4]; -- gdb_regs[R5] = regs->regs[R5]; -- gdb_regs[R6] = regs->regs[R6]; -- gdb_regs[R7] = regs->regs[R7]; -- gdb_regs[R8] = regs->regs[R8]; -- gdb_regs[R9] = regs->regs[R9]; -- gdb_regs[R10] = regs->regs[R10]; -- gdb_regs[R11] = regs->regs[R11]; -- gdb_regs[R12] = regs->regs[R12]; -- gdb_regs[R13] = regs->regs[R13]; -- gdb_regs[R14] = regs->regs[R14]; -- gdb_regs[R15] = regs->regs[R15]; -- gdb_regs[PC] = regs->pc; -- gdb_regs[PR] = regs->pr; -- gdb_regs[GBR] = regs->gbr; -- gdb_regs[MACH] = regs->mach; -- gdb_regs[MACL] = regs->macl; -- gdb_regs[SR] = regs->sr; -- gdb_regs[VBR] = regs->vbr; --} -- --/* Copy local gdb registers back to kgdb regs, for later copy to kernel */ --static void gdb_regs_to_kgdb_regs(const int *gdb_regs, -- struct kgdb_regs *regs) --{ -- regs->regs[R0] = gdb_regs[R0]; -- regs->regs[R1] = gdb_regs[R1]; -- regs->regs[R2] = gdb_regs[R2]; -- regs->regs[R3] = gdb_regs[R3]; -- regs->regs[R4] = gdb_regs[R4]; -- regs->regs[R5] = gdb_regs[R5]; -- regs->regs[R6] = gdb_regs[R6]; -- regs->regs[R7] = gdb_regs[R7]; -- regs->regs[R8] = gdb_regs[R8]; -- regs->regs[R9] = gdb_regs[R9]; -- regs->regs[R10] = gdb_regs[R10]; -- regs->regs[R11] = gdb_regs[R11]; -- regs->regs[R12] = gdb_regs[R12]; -- regs->regs[R13] = gdb_regs[R13]; -- regs->regs[R14] = gdb_regs[R14]; -- regs->regs[R15] = gdb_regs[R15]; -- regs->pc = gdb_regs[PC]; -- regs->pr = gdb_regs[PR]; -- regs->gbr = gdb_regs[GBR]; -- regs->mach = gdb_regs[MACH]; -- regs->macl = gdb_regs[MACL]; -- regs->sr = gdb_regs[SR]; -- regs->vbr = gdb_regs[VBR]; --} -- --#ifdef CONFIG_KGDB_THREAD --/* Make a local copy of registers from the specified thread */ --asmlinkage void ret_from_fork(void); --static void thread_regs_to_gdb_regs(const struct task_struct *thread, -- int *gdb_regs) --{ -- int regno; -- int *tregs; -- -- /* Initialize to zero */ -- for (regno = 0; regno < MAXREG; regno++) -- gdb_regs[regno] = 0; -- -- /* Just making sure... */ -- if (thread == NULL) -- return; -- -- /* A new fork has pt_regs on the stack from a fork() call */ -- if (thread->thread.pc == (unsigned long)ret_from_fork) { -- -- int vbr_val; -- struct pt_regs *kregs; -- kregs = (struct pt_regs*)thread->thread.sp; -- -- gdb_regs[R0] = kregs->regs[R0]; -- gdb_regs[R1] = kregs->regs[R1]; -- gdb_regs[R2] = kregs->regs[R2]; -- gdb_regs[R3] = kregs->regs[R3]; -- gdb_regs[R4] = kregs->regs[R4]; -- gdb_regs[R5] = kregs->regs[R5]; -- gdb_regs[R6] = kregs->regs[R6]; -- gdb_regs[R7] = kregs->regs[R7]; -- gdb_regs[R8] = kregs->regs[R8]; -- gdb_regs[R9] = kregs->regs[R9]; -- gdb_regs[R10] = kregs->regs[R10]; -- gdb_regs[R11] = kregs->regs[R11]; -- gdb_regs[R12] = kregs->regs[R12]; -- gdb_regs[R13] = kregs->regs[R13]; -- gdb_regs[R14] = kregs->regs[R14]; -- gdb_regs[R15] = kregs->regs[R15]; -- gdb_regs[PC] = kregs->pc; -- gdb_regs[PR] = kregs->pr; -- gdb_regs[GBR] = kregs->gbr; -- gdb_regs[MACH] = kregs->mach; -- gdb_regs[MACL] = kregs->macl; -- gdb_regs[SR] = kregs->sr; -- -- asm("stc vbr, %0":"=r"(vbr_val)); -- gdb_regs[VBR] = vbr_val; -- return; -- } -- -- /* Otherwise, we have only some registers from switch_to() */ -- tregs = (int *)thread->thread.sp; -- gdb_regs[R15] = (int)tregs; -- gdb_regs[R14] = *tregs++; -- gdb_regs[R13] = *tregs++; -- gdb_regs[R12] = *tregs++; -- gdb_regs[R11] = *tregs++; -- gdb_regs[R10] = *tregs++; -- gdb_regs[R9] = *tregs++; -- gdb_regs[R8] = *tregs++; -- gdb_regs[PR] = *tregs++; -- gdb_regs[GBR] = *tregs++; -- gdb_regs[PC] = thread->thread.pc; --} --#endif /* CONFIG_KGDB_THREAD */ -- --/* Calculate the new address for after a step */ --static short *get_step_address(void) --{ -- short op = *(short *) trap_registers.pc; -- long addr; -- -- /* BT */ -- if (OPCODE_BT(op)) { -- if (trap_registers.sr & SR_T_BIT_MASK) -- addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op); -- else -- addr = trap_registers.pc + 2; -- } -- -- /* BTS */ -- else if (OPCODE_BTS(op)) { -- if (trap_registers.sr & SR_T_BIT_MASK) -- addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op); -- else -- addr = trap_registers.pc + 4; /* Not in delay slot */ -- } -- -- /* BF */ -- else if (OPCODE_BF(op)) { -- if (!(trap_registers.sr & SR_T_BIT_MASK)) -- addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op); -- else -- addr = trap_registers.pc + 2; -- } -- -- /* BFS */ -- else if (OPCODE_BFS(op)) { -- if (!(trap_registers.sr & SR_T_BIT_MASK)) -- addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op); -- else -- addr = trap_registers.pc + 4; /* Not in delay slot */ -- } -- -- /* BRA */ -- else if (OPCODE_BRA(op)) -- addr = trap_registers.pc + 4 + OPCODE_BRA_DISP(op); -- -- /* BRAF */ -- else if (OPCODE_BRAF(op)) -- addr = trap_registers.pc + 4 -- + trap_registers.regs[OPCODE_BRAF_REG(op)]; -- -- /* BSR */ -- else if (OPCODE_BSR(op)) -- addr = trap_registers.pc + 4 + OPCODE_BSR_DISP(op); -- -- /* BSRF */ -- else if (OPCODE_BSRF(op)) -- addr = trap_registers.pc + 4 -- + trap_registers.regs[OPCODE_BSRF_REG(op)]; -- -- /* JMP */ -- else if (OPCODE_JMP(op)) -- addr = trap_registers.regs[OPCODE_JMP_REG(op)]; -- -- /* JSR */ -- else if (OPCODE_JSR(op)) -- addr = trap_registers.regs[OPCODE_JSR_REG(op)]; -- -- /* RTS */ -- else if (OPCODE_RTS(op)) -- addr = trap_registers.pr; -- -- /* RTE */ -- else if (OPCODE_RTE(op)) -- addr = trap_registers.regs[15]; -- -- /* Other */ -- else -- addr = trap_registers.pc + 2; -- -- kgdb_flush_icache_range(addr, addr + 2); -- return (short *) addr; --} -- --/* Set up a single-step. Replace the instruction immediately after the -- current instruction (i.e. next in the expected flow of control) with a -- trap instruction, so that returning will cause only a single instruction -- to be executed. Note that this model is slightly broken for instructions -- with delay slots (e.g. B[TF]S, BSR, BRA etc), where both the branch -- and the instruction in the delay slot will be executed. */ --static void do_single_step(void) --{ -- unsigned short *addr = 0; -- -- /* Determine where the target instruction will send us to */ -- addr = get_step_address(); -- stepped_address = (int)addr; -- -- /* Replace it */ -- stepped_opcode = *(short *)addr; -- *addr = STEP_OPCODE; -- -- /* Flush and return */ -- kgdb_flush_icache_range((long) addr, (long) addr + 2); -- return; --} -- --/* Undo a single step */ --static void undo_single_step(void) --{ -- /* If we have stepped, put back the old instruction */ -- /* Use stepped_address in case we stopped elsewhere */ -- if (stepped_opcode != 0) { -- *(short*)stepped_address = stepped_opcode; -- kgdb_flush_icache_range(stepped_address, stepped_address + 2); -- } -- stepped_opcode = 0; --} -- --/* Send a signal message */ --static void send_signal_msg(const int signum) --{ --#ifndef CONFIG_KGDB_THREAD -- out_buffer[0] = 'S'; -- out_buffer[1] = highhex(signum); -- out_buffer[2] = lowhex(signum); -- out_buffer[3] = 0; -- put_packet(out_buffer); --#else /* CONFIG_KGDB_THREAD */ -- int threadid; -- threadref thref; -- char *out = out_buffer; -- const char *tstring = "thread"; -- -- *out++ = 'T'; -- *out++ = highhex(signum); -- *out++ = lowhex(signum); -- -- while (*tstring) { -- *out++ = *tstring++; -- } -- *out++ = ':'; -- -- threadid = trapped_thread->pid; -- if (threadid == 0) threadid = PID_MAX; -- int_to_threadref(&thref, threadid); -- pack_threadid(out, &thref); -- out += BUF_THREAD_ID_SIZE; -- *out++ = ';'; -- -- *out = 0; -- put_packet(out_buffer); --#endif /* CONFIG_KGDB_THREAD */ --} -- --/* Reply that all was well */ --static void send_ok_msg(void) --{ -- strcpy(out_buffer, "OK"); -- put_packet(out_buffer); --} -- --/* Reply that an error occurred */ --static void send_err_msg(void) --{ -- strcpy(out_buffer, "E01"); -- put_packet(out_buffer); --} -- --/* Empty message indicates unrecognised command */ --static void send_empty_msg(void) --{ -- put_packet(""); --} -- --/* Read memory due to 'm' message */ --static void read_mem_msg(void) --{ -- char *ptr; -- int addr; -- int length; -- -- /* Jmp, disable bus error handler */ -- if (setjmp(rem_com_env) == 0) { -- -- kgdb_nofault = 1; -- -- /* Walk through, have m, */ -- ptr = &in_buffer[1]; -- if (hex_to_int(&ptr, &addr) && (*ptr++ == ',')) -- if (hex_to_int(&ptr, &length)) { -- ptr = 0; -- if (length * 2 > OUTBUFMAX) -- length = OUTBUFMAX / 2; -- mem_to_hex((char *) addr, out_buffer, length); -- } -- if (ptr) -- send_err_msg(); -- else -- put_packet(out_buffer); -- } else -- send_err_msg(); -- -- /* Restore bus error handler */ -- kgdb_nofault = 0; --} -- --/* Write memory due to 'M' or 'X' message */ --static void write_mem_msg(int binary) --{ -- char *ptr; -- int addr; -- int length; -- -- if (setjmp(rem_com_env) == 0) { -- -- kgdb_nofault = 1; -- -- /* Walk through, have M,: */ -- ptr = &in_buffer[1]; -- if (hex_to_int(&ptr, &addr) && (*ptr++ == ',')) -- if (hex_to_int(&ptr, &length) && (*ptr++ == ':')) { -- if (binary) -- ebin_to_mem(ptr, (char*)addr, length); -- else -- hex_to_mem(ptr, (char*)addr, length); -- kgdb_flush_icache_range(addr, addr + length); -- ptr = 0; -- send_ok_msg(); -- } -- if (ptr) -- send_err_msg(); -- } else -- send_err_msg(); -- -- /* Restore bus error handler */ -- kgdb_nofault = 0; --} -- --/* Continue message */ --static void continue_msg(void) --{ -- /* Try to read optional parameter, PC unchanged if none */ -- char *ptr = &in_buffer[1]; -- int addr; -- -- if (hex_to_int(&ptr, &addr)) -- trap_registers.pc = addr; --} -- --/* Continue message with signal */ --static void continue_with_sig_msg(void) --{ -- int signal; -- char *ptr = &in_buffer[1]; -- int addr; -- -- /* Report limitation */ -- kgdb_to_gdb("Cannot force signal in kgdb, continuing anyway.\n"); -- -- /* Signal */ -- hex_to_int(&ptr, &signal); -- if (*ptr == ';') -- ptr++; -- -- /* Optional address */ -- if (hex_to_int(&ptr, &addr)) -- trap_registers.pc = addr; --} -- --/* Step message */ --static void step_msg(void) --{ -- continue_msg(); -- do_single_step(); --} -- --/* Step message with signal */ --static void step_with_sig_msg(void) --{ -- continue_with_sig_msg(); -- do_single_step(); --} -- --/* Send register contents */ --static void send_regs_msg(void) --{ --#ifdef CONFIG_KGDB_THREAD -- if (!current_thread) -- kgdb_regs_to_gdb_regs(&trap_registers, registers); -- else -- thread_regs_to_gdb_regs(current_thread, registers); --#else -- kgdb_regs_to_gdb_regs(&trap_registers, registers); --#endif -- -- mem_to_hex((char *) registers, out_buffer, NUMREGBYTES); -- put_packet(out_buffer); --} -- --/* Set register contents - currently can't set other thread's registers */ --static void set_regs_msg(void) --{ --#ifdef CONFIG_KGDB_THREAD -- if (!current_thread) { --#endif -- kgdb_regs_to_gdb_regs(&trap_registers, registers); -- hex_to_mem(&in_buffer[1], (char *) registers, NUMREGBYTES); -- gdb_regs_to_kgdb_regs(registers, &trap_registers); -- send_ok_msg(); --#ifdef CONFIG_KGDB_THREAD -- } else -- send_err_msg(); --#endif --} -- -- --#ifdef CONFIG_KGDB_THREAD -- --/* Set the status for a thread */ --void set_thread_msg(void) --{ -- int threadid; -- struct task_struct *thread = NULL; -- char *ptr; -- -- switch (in_buffer[1]) { -- -- /* To select which thread for gG etc messages, i.e. supported */ -- case 'g': -- -- ptr = &in_buffer[2]; -- hex_to_int(&ptr, &threadid); -- thread = get_thread(threadid); -- -- /* If we haven't found it */ -- if (!thread) { -- send_err_msg(); -- break; -- } -- -- /* Set current_thread (or not) */ -- if (thread == trapped_thread) -- current_thread = NULL; -- else -- current_thread = thread; -- send_ok_msg(); -- break; -- -- /* To select which thread for cCsS messages, i.e. unsupported */ -- case 'c': -- send_ok_msg(); -- break; -- -- default: -- send_empty_msg(); -- break; -- } --} -- --/* Is a thread alive? */ --static void thread_status_msg(void) --{ -- char *ptr; -- int threadid; -- struct task_struct *thread = NULL; -- -- ptr = &in_buffer[1]; -- hex_to_int(&ptr, &threadid); -- thread = get_thread(threadid); -- if (thread) -- send_ok_msg(); -- else -- send_err_msg(); --} --/* Send the current thread ID */ --static void thread_id_msg(void) --{ -- int threadid; -- threadref thref; -- -- out_buffer[0] = 'Q'; -- out_buffer[1] = 'C'; -- -- if (current_thread) -- threadid = current_thread->pid; -- else if (trapped_thread) -- threadid = trapped_thread->pid; -- else /* Impossible, but just in case! */ -- { -- send_err_msg(); -- return; -- } -- -- /* Translate pid 0 to PID_MAX for gdb */ -- if (threadid == 0) threadid = PID_MAX; -- -- int_to_threadref(&thref, threadid); -- pack_threadid(out_buffer + 2, &thref); -- out_buffer[2 + BUF_THREAD_ID_SIZE] = '\0'; -- put_packet(out_buffer); --} -- --/* Send thread info */ --static void thread_info_msg(void) --{ -- struct task_struct *thread = NULL; -- int threadid; -- char *pos; -- threadref thref; -- -- /* Start with 'm' */ -- out_buffer[0] = 'm'; -- pos = &out_buffer[1]; -- -- /* For all possible thread IDs - this will overrun if > 44 threads! */ -- /* Start at 1 and include PID_MAX (since GDB won't use pid 0...) */ -- for (threadid = 1; threadid <= PID_MAX; threadid++) { -- -- read_lock(&tasklist_lock); -- thread = get_thread(threadid); -- read_unlock(&tasklist_lock); -- -- /* If it's a valid thread */ -- if (thread) { -- int_to_threadref(&thref, threadid); -- pack_threadid(pos, &thref); -- pos += BUF_THREAD_ID_SIZE; -- *pos++ = ','; -- } -- } -- *--pos = 0; /* Lose final comma */ -- put_packet(out_buffer); -- --} -- --/* Return printable info for gdb's 'info threads' command */ --static void thread_extra_info_msg(void) --{ -- int threadid; -- struct task_struct *thread = NULL; -- char buffer[20], *ptr; -- int i; -- -- /* Extract thread ID */ -- ptr = &in_buffer[17]; -- hex_to_int(&ptr, &threadid); -- thread = get_thread(threadid); -- -- /* If we don't recognise it, say so */ -- if (thread == NULL) -- strcpy(buffer, "(unknown)"); -- else -- strcpy(buffer, thread->comm); -- -- /* Construct packet */ -- for (i = 0, ptr = out_buffer; buffer[i]; i++) -- ptr = pack_hex_byte(ptr, buffer[i]); -- -- if (thread->thread.pc == (unsigned long)ret_from_fork) { -- strcpy(buffer, ""); -- for (i = 0; buffer[i]; i++) -- ptr = pack_hex_byte(ptr, buffer[i]); -- } -- -- *ptr = '\0'; -- put_packet(out_buffer); --} -- --/* Handle all qFooBarBaz messages - have to use an if statement as -- opposed to a switch because q messages can have > 1 char id. */ --static void query_msg(void) --{ -- const char *q_start = &in_buffer[1]; -- -- /* qC = return current thread ID */ -- if (strncmp(q_start, "C", 1) == 0) -- thread_id_msg(); -- -- /* qfThreadInfo = query all threads (first) */ -- else if (strncmp(q_start, "fThreadInfo", 11) == 0) -- thread_info_msg(); -- -- /* qsThreadInfo = query all threads (subsequent). We know we have sent -- them all after the qfThreadInfo message, so there are no to send */ -- else if (strncmp(q_start, "sThreadInfo", 11) == 0) -- put_packet("l"); /* el = last */ -- -- /* qThreadExtraInfo = supply printable information per thread */ -- else if (strncmp(q_start, "ThreadExtraInfo", 15) == 0) -- thread_extra_info_msg(); -- -- /* Unsupported - empty message as per spec */ -- else -- send_empty_msg(); --} --#endif /* CONFIG_KGDB_THREAD */ -- --/* -- * Bring up the ports.. -- */ --static int kgdb_serial_setup(void) --{ -- extern int kgdb_console_setup(struct console *co, char *options); -- struct console dummy; -- -- kgdb_console_setup(&dummy, 0); -- -- return 0; --} -- --/* The command loop, read and act on requests */ --static void kgdb_command_loop(const int excep_code, const int trapa_value) --{ -- int sigval; -- -- if (excep_code == NMI_VEC) { --#ifndef CONFIG_KGDB_NMI -- KGDB_PRINTK("Ignoring unexpected NMI?\n"); -- return; --#else /* CONFIG_KGDB_NMI */ -- if (!kgdb_enabled) { -- kgdb_enabled = 1; -- kgdb_init(); -- } --#endif /* CONFIG_KGDB_NMI */ -- } -- -- /* Ignore if we're disabled */ -- if (!kgdb_enabled) -- return; -- --#ifdef CONFIG_KGDB_THREAD -- /* Until GDB specifies a thread */ -- current_thread = NULL; -- trapped_thread = current; --#endif -- -- /* Enter GDB mode (e.g. after detach) */ -- if (!kgdb_in_gdb_mode) { -- /* Do serial setup, notify user, issue preemptive ack */ -- kgdb_serial_setup(); -- KGDB_PRINTK("Waiting for GDB (on %s%d at %d baud)\n", -- (kgdb_porttype ? kgdb_porttype->name : ""), -- kgdb_portnum, kgdb_baud); -- kgdb_in_gdb_mode = 1; -- put_debug_char('+'); -- } -- -- /* Reply to host that an exception has occurred */ -- sigval = compute_signal(excep_code); -- send_signal_msg(sigval); -- -- /* TRAP_VEC exception indicates a software trap inserted in place of -- code by GDB so back up PC by one instruction, as this instruction -- will later be replaced by its original one. Do NOT do this for -- trap 0xff, since that indicates a compiled-in breakpoint which -- will not be replaced (and we would retake the trap forever) */ -- if ((excep_code == TRAP_VEC) && (trapa_value != (0xff << 2))) { -- trap_registers.pc -= 2; -- } -- -- /* Undo any stepping we may have done */ -- undo_single_step(); -- -- while (1) { -- -- out_buffer[0] = 0; -- get_packet(in_buffer, BUFMAX); -- -- /* Examine first char of buffer to see what we need to do */ -- switch (in_buffer[0]) { -- -- case '?': /* Send which signal we've received */ -- send_signal_msg(sigval); -- break; -- -- case 'g': /* Return the values of the CPU registers */ -- send_regs_msg(); -- break; -- -- case 'G': /* Set the value of the CPU registers */ -- set_regs_msg(); -- break; -- -- case 'm': /* Read LLLL bytes address AA..AA */ -- read_mem_msg(); -- break; -- -- case 'M': /* Write LLLL bytes address AA..AA, ret OK */ -- write_mem_msg(0); /* 0 = data in hex */ -- break; -- -- case 'X': /* Write LLLL bytes esc bin address AA..AA */ -- if (kgdb_bits == '8') -- write_mem_msg(1); /* 1 = data in binary */ -- else -- send_empty_msg(); -- break; -- -- case 'C': /* Continue, signum included, we ignore it */ -- continue_with_sig_msg(); -- return; -- -- case 'c': /* Continue at address AA..AA (optional) */ -- continue_msg(); -- return; -- -- case 'S': /* Step, signum included, we ignore it */ -- step_with_sig_msg(); -- return; -- -- case 's': /* Step one instruction from AA..AA */ -- step_msg(); -- return; -- --#ifdef CONFIG_KGDB_THREAD -- -- case 'H': /* Task related */ -- set_thread_msg(); -- break; -- -- case 'T': /* Query thread status */ -- thread_status_msg(); -- break; -- -- case 'q': /* Handle query - currently thread-related */ -- query_msg(); -- break; --#endif -- -- case 'k': /* 'Kill the program' with a kernel ? */ -- break; -- -- case 'D': /* Detach from program, send reply OK */ -- kgdb_in_gdb_mode = 0; -- send_ok_msg(); -- get_debug_char(); -- return; -- -- default: -- send_empty_msg(); -- break; -- } -- } --} -- --/* There has been an exception, most likely a breakpoint. */ --void kgdb_handle_exception(struct pt_regs *regs) --{ -- int excep_code, vbr_val; -- int count; -- int trapa_value = ctrl_inl(TRA); -- -- /* Copy kernel regs (from stack) */ -- for (count = 0; count < 16; count++) -- trap_registers.regs[count] = regs->regs[count]; -- trap_registers.pc = regs->pc; -- trap_registers.pr = regs->pr; -- trap_registers.sr = regs->sr; -- trap_registers.gbr = regs->gbr; -- trap_registers.mach = regs->mach; -- trap_registers.macl = regs->macl; -- -- asm("stc vbr, %0":"=r"(vbr_val)); -- trap_registers.vbr = vbr_val; -- -- /* Get excode for command loop call, user access */ -- asm("stc r2_bank, %0":"=r"(excep_code)); -- kgdb_excode = excep_code; -- -- /* Other interesting environment items for reference */ -- asm("stc r6_bank, %0":"=r"(kgdb_g_imask)); -- kgdb_current = current; -- kgdb_trapa_val = trapa_value; -- -- /* Act on the exception */ -- kgdb_command_loop(excep_code >> 5, trapa_value); -- -- kgdb_current = NULL; -- -- /* Copy back the (maybe modified) registers */ -- for (count = 0; count < 16; count++) -- regs->regs[count] = trap_registers.regs[count]; -- regs->pc = trap_registers.pc; -- regs->pr = trap_registers.pr; -- regs->sr = trap_registers.sr; -- regs->gbr = trap_registers.gbr; -- regs->mach = trap_registers.mach; -- regs->macl = trap_registers.macl; -- -- vbr_val = trap_registers.vbr; -- asm("ldc %0, vbr": :"r"(vbr_val)); -- -- return; --} -- --/* Trigger a breakpoint by function */ --void breakpoint(void) --{ -- if (!kgdb_enabled) { -- kgdb_enabled = 1; -- kgdb_init(); -- } -- BREAKPOINT(); --} -- --/* Initialise the KGDB data structures and serial configuration */ --int kgdb_init(void) --{ -- if (!kgdb_enabled) -- return 1; -- -- in_nmi = 0; -- kgdb_nofault = 0; -- stepped_opcode = 0; -- kgdb_in_gdb_mode = 0; -- -- if (kgdb_serial_setup() != 0) { -- KGDB_PRINTK("serial setup error\n"); -- return -1; -- } -- -- /* Init ptr to exception handler */ -- kgdb_debug_hook = kgdb_handle_exception; -- kgdb_bus_err_hook = kgdb_handle_bus_error; -- -- /* Enter kgdb now if requested, or just report init done */ -- if (kgdb_halt) { -- kgdb_in_gdb_mode = 1; -- put_debug_char('+'); -- breakpoint(); -- } -- else -- { -- KGDB_PRINTK("stub is initialized.\n"); -- } -- -- return 0; --} -- --/* Make function available for "user messages"; console will use it too. */ -- --char gdbmsgbuf[BUFMAX]; --#define MAXOUT ((BUFMAX-2)/2) -- --static void kgdb_msg_write(const char *s, unsigned count) --{ -- int i; -- int wcount; -- char *bufptr; -- -- /* 'O'utput */ -- gdbmsgbuf[0] = 'O'; -- -- /* Fill and send buffers... */ -- while (count > 0) { -- bufptr = gdbmsgbuf + 1; -- -- /* Calculate how many this time */ -- wcount = (count > MAXOUT) ? MAXOUT : count; -- -- /* Pack in hex chars */ -- for (i = 0; i < wcount; i++) -- bufptr = pack_hex_byte(bufptr, s[i]); -- *bufptr = '\0'; -- -- /* Move up */ -- s += wcount; -- count -= wcount; -- -- /* Write packet */ -- put_packet(gdbmsgbuf); -- } --} -- --static void kgdb_to_gdb(const char *s) --{ -- kgdb_msg_write(s, strlen(s)); --} -- --#ifdef CONFIG_SH_KGDB_CONSOLE --void kgdb_console_write(struct console *co, const char *s, unsigned count) --{ -- /* Bail if we're not talking to GDB */ -- if (!kgdb_in_gdb_mode) -- return; -- -- kgdb_msg_write(s, count); --} --#endif -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/sh/kernel/setup.c linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/setup.c ---- linux-2.6.18-53.1.14/arch/sh/kernel/setup.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/setup.c 2008-06-10 15:38:50.000000000 +0400 -@@ -28,10 +28,6 @@ - #include - #include - --#ifdef CONFIG_SH_KGDB --#include --static int kgdb_parse_options(char *options); --#endif - extern void * __rd_start, * __rd_end; - /* - * Machine setup.. -@@ -528,93 +524,3 @@ struct seq_operations cpuinfo_op = { - .show = show_cpuinfo, - }; - #endif /* CONFIG_PROC_FS */ -- --#ifdef CONFIG_SH_KGDB --/* -- * Parse command-line kgdb options. By default KGDB is enabled, -- * entered on error (or other action) using default serial info. -- * The command-line option can include a serial port specification -- * and an action to override default or configured behavior. -- */ --struct kgdb_sermap kgdb_sci_sermap = --{ "ttySC", 5, kgdb_sci_setup, NULL }; -- --struct kgdb_sermap *kgdb_serlist = &kgdb_sci_sermap; --struct kgdb_sermap *kgdb_porttype = &kgdb_sci_sermap; -- --void kgdb_register_sermap(struct kgdb_sermap *map) --{ -- struct kgdb_sermap *last; -- -- for (last = kgdb_serlist; last->next; last = last->next) -- ; -- last->next = map; -- if (!map->namelen) { -- map->namelen = strlen(map->name); -- } --} -- --static int __init kgdb_parse_options(char *options) --{ -- char c; -- int baud; -- -- /* Check for port spec (or use default) */ -- -- /* Determine port type and instance */ -- if (!memcmp(options, "tty", 3)) { -- struct kgdb_sermap *map = kgdb_serlist; -- -- while (map && memcmp(options, map->name, map->namelen)) -- map = map->next; -- -- if (!map) { -- KGDB_PRINTK("unknown port spec in %s\n", options); -- return -1; -- } -- -- kgdb_porttype = map; -- kgdb_serial_setup = map->setup_fn; -- kgdb_portnum = options[map->namelen] - '0'; -- options += map->namelen + 1; -- -- options = (*options == ',') ? options+1 : options; -- -- /* Read optional parameters (baud/parity/bits) */ -- baud = simple_strtoul(options, &options, 10); -- if (baud != 0) { -- kgdb_baud = baud; -- -- c = toupper(*options); -- if (c == 'E' || c == 'O' || c == 'N') { -- kgdb_parity = c; -- options++; -- } -- -- c = *options; -- if (c == '7' || c == '8') { -- kgdb_bits = c; -- options++; -- } -- options = (*options == ',') ? options+1 : options; -- } -- } -- -- /* Check for action specification */ -- if (!memcmp(options, "halt", 4)) { -- kgdb_halt = 1; -- options += 4; -- } else if (!memcmp(options, "disabled", 8)) { -- kgdb_enabled = 0; -- options += 8; -- } -- -- if (*options) { -- KGDB_PRINTK("ignored unknown options: %s\n", options); -- return 0; -- } -- return 1; --} --__setup("kgdb=", kgdb_parse_options); --#endif /* CONFIG_SH_KGDB */ -- -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/sh/kernel/time.c linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/time.c ---- linux-2.6.18-53.1.14/arch/sh/kernel/time.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/time.c 2008-06-10 15:38:50.000000000 +0400 -@@ -184,12 +184,4 @@ void __init time_init(void) - */ - sys_timer = get_sys_timer(); - printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); -- --#if defined(CONFIG_SH_KGDB) -- /* -- * Set up kgdb as requested. We do it here because the serial -- * init uses the timer vars we just set up for figuring baud. -- */ -- kgdb_init(); --#endif - } -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/sh/kernel/traps.c linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/traps.c ---- linux-2.6.18-53.1.14/arch/sh/kernel/traps.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/sh/kernel/traps.c 2008-06-10 15:38:50.000000000 +0400 -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -34,17 +35,8 @@ - #include - #include - --#ifdef CONFIG_SH_KGDB --#include --#define CHK_REMOTE_DEBUG(regs) \ --{ \ -- if ((kgdb_debug_hook != (kgdb_debug_hook_t *) NULL) && (!user_mode(regs))) \ -- { \ -- (*kgdb_debug_hook)(regs); \ -- } \ --} --#else --#define CHK_REMOTE_DEBUG(regs) -+#ifndef CONFIG_KGDB -+#define kgdb_handle_exception(t, s, e, r) - #endif - - #define DO_ERROR(trapnr, signr, str, name, tsk) \ -@@ -65,7 +57,7 @@ asmlinkage void do_##name(unsigned long - local_irq_enable(); \ - tsk->thread.error_code = error_code; \ - tsk->thread.trap_no = trapnr; \ -- CHK_REMOTE_DEBUG(®s); \ -+ kgdb_handle_exception(trapnr, signr, error_code, ®s); \ - force_sig(signr, tsk); \ - die_if_no_fixup(str,®s,error_code); \ - } -@@ -92,10 +84,12 @@ void die(const char * str, struct pt_reg - { - static int die_counter; - -+#ifdef CONFIG_KGDB -+ kgdb_handle_exception(1, SIGTRAP, err, regs); -+#endif - console_verbose(); - spin_lock_irq(&die_lock); - printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); -- CHK_REMOTE_DEBUG(regs); - show_regs(regs); - spin_unlock_irq(&die_lock); - do_exit(SIGSEGV); -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/sh/mm/extable.c linux-2.6.18-53.1.14.kgdb/arch/sh/mm/extable.c ---- linux-2.6.18-53.1.14/arch/sh/mm/extable.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/sh/mm/extable.c 2008-06-10 15:38:50.000000000 +0400 -@@ -5,6 +5,7 @@ - */ - - #include -+#include - #include - - int fixup_exception(struct pt_regs *regs) -@@ -16,6 +17,12 @@ int fixup_exception(struct pt_regs *regs - regs->pc = fixup->fixup; - return 1; - } -+#ifdef CONFIG_KGDB -+ if (atomic_read(&debugger_active) && kgdb_may_fault) -+ /* Restore our previous state. */ -+ kgdb_fault_longjmp(kgdb_fault_jmp_regs); -+ /* Never reached. */ -+#endif - - return 0; - } -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/sh/mm/fault-nommu.c linux-2.6.18-53.1.14.kgdb/arch/sh/mm/fault-nommu.c ---- linux-2.6.18-53.1.14/arch/sh/mm/fault-nommu.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/sh/mm/fault-nommu.c 2008-06-10 15:38:50.000000000 +0400 -@@ -29,10 +29,6 @@ - #include - #include - --#if defined(CONFIG_SH_KGDB) --#include --#endif -- - extern void die(const char *,struct pt_regs *,long); - - /* -@@ -43,11 +39,6 @@ extern void die(const char *,struct pt_r - asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, - unsigned long address) - { --#if defined(CONFIG_SH_KGDB) -- if (kgdb_nofault && kgdb_bus_err_hook) -- kgdb_bus_err_hook(); --#endif -- - /* - * Oops. The kernel tried to access some bad page. We'll have to - * terminate things with extreme prejudice. -@@ -69,11 +60,6 @@ asmlinkage void do_page_fault(struct pt_ - asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess, - unsigned long address) - { --#if defined(CONFIG_SH_KGDB) -- if (kgdb_nofault && kgdb_bus_err_hook) -- kgdb_bus_err_hook(); --#endif -- - if (address >= TASK_SIZE) - return 1; - -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/sh/mm/fault.c linux-2.6.18-53.1.14.kgdb/arch/sh/mm/fault.c ---- linux-2.6.18-53.1.14/arch/sh/mm/fault.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/sh/mm/fault.c 2008-06-10 15:38:50.000000000 +0400 -@@ -28,7 +28,6 @@ - #include - #include - #include --#include - - extern void die(const char *,struct pt_regs *,long); - -@@ -45,11 +44,6 @@ asmlinkage void do_page_fault(struct pt_ - struct vm_area_struct * vma; - unsigned long page; - --#ifdef CONFIG_SH_KGDB -- if (kgdb_nofault && kgdb_bus_err_hook) -- kgdb_bus_err_hook(); --#endif -- - tsk = current; - mm = tsk->mm; - -@@ -153,6 +147,7 @@ no_context: - } - die("Oops", regs, writeaccess); - do_exit(SIGKILL); -+ dump_stack(); - - /* - * We ran out of memory, or some other thing happened to us that made -@@ -202,11 +197,6 @@ asmlinkage int __do_page_fault(struct pt - spinlock_t *ptl; - int ret = 1; - --#ifdef CONFIG_SH_KGDB -- if (kgdb_nofault && kgdb_bus_err_hook) -- kgdb_bus_err_hook(); --#endif -- - #ifdef CONFIG_SH_STORE_QUEUES - addrmax = P4SEG_STORE_QUE + 0x04000000; - #endif -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/x86_64/Kconfig.debug linux-2.6.18-53.1.14.kgdb/arch/x86_64/Kconfig.debug ---- linux-2.6.18-53.1.14/arch/x86_64/Kconfig.debug 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/arch/x86_64/Kconfig.debug 2008-06-10 15:38:44.000000000 +0400 -@@ -55,7 +55,4 @@ config DEBUG_STACK_USAGE - - This option will slow down process creation somewhat. - --#config X86_REMOTE_DEBUG --# bool "kgdb debugging stub" -- - endmenu -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/x86_64/kernel/Makefile linux-2.6.18-53.1.14.kgdb/arch/x86_64/kernel/Makefile ---- linux-2.6.18-53.1.14/arch/x86_64/kernel/Makefile 2008-03-06 05:54:48.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/x86_64/kernel/Makefile 2008-06-10 15:38:44.000000000 +0400 -@@ -35,6 +35,7 @@ obj-$(CONFIG_IOMMU) += pci-gart.o apert - obj-$(CONFIG_CALGARY_IOMMU) += pci-calgary.o tce.o - obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o - obj-$(CONFIG_KPROBES) += kprobes.o -+obj-$(CONFIG_KGDB) += kgdb.o kgdb-jmp.o - obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o - obj-$(CONFIG_X86_VSMP) += vsmp.o - obj-$(CONFIG_K8_NB) += k8.o -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/x86_64/kernel/entry.S linux-2.6.18-53.1.14.kgdb/arch/x86_64/kernel/entry.S ---- linux-2.6.18-53.1.14/arch/x86_64/kernel/entry.S 2008-03-06 05:54:50.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/x86_64/kernel/entry.S 2008-06-10 15:39:01.000000000 +0400 -@@ -42,6 +42,7 @@ - #include - #include - #include -+#include - - .code64 - -@@ -887,6 +888,7 @@ error_exit: - RESTORE_ARGS 0,8,0 - jmp iret_label - CFI_ENDPROC -+ CFI_END_FRAME(kernel_thread) - - error_kernelspace: - incl %ebx -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/x86_64/kernel/kgdb-jmp.S linux-2.6.18-53.1.14.kgdb/arch/x86_64/kernel/kgdb-jmp.S ---- linux-2.6.18-53.1.14/arch/x86_64/kernel/kgdb-jmp.S 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/x86_64/kernel/kgdb-jmp.S 2008-06-10 15:38:44.000000000 +0400 -@@ -0,0 +1,65 @@ -+/* -+ * arch/x86_64/kernel/kgdb-jmp.S -+ * -+ * Save and restore system registers so that within a limited frame we -+ * may have a fault and "jump back" to a known safe location. -+ * -+ * Author: Tom Rini -+ * -+ * Cribbed from glibc, which carries the following: -+ * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. -+ * Copyright (C) 2005 by MontaVista Software. -+ * -+ * This file is licensed under the terms of the GNU General Public License -+ * version 2. This program as licensed "as is" without any warranty of -+ * any kind, whether express or implied. -+ */ -+ -+#include -+ -+#define JB_RBX 0 -+#define JB_RBP 1 -+#define JB_R12 2 -+#define JB_R13 3 -+#define JB_R14 4 -+#define JB_R15 5 -+#define JB_RSP 6 -+#define JB_PC 7 -+ -+ .code64 -+ -+/* This must be called prior to kgdb_fault_longjmp and -+ * kgdb_fault_longjmp must not be called outside of the context of the -+ * last call to kgdb_fault_setjmp. -+ */ -+ENTRY(kgdb_fault_setjmp) -+ /* Save registers. */ -+ movq %rbx, (JB_RBX*8)(%rdi) -+ movq %rbp, (JB_RBP*8)(%rdi) -+ movq %r12, (JB_R12*8)(%rdi) -+ movq %r13, (JB_R13*8)(%rdi) -+ movq %r14, (JB_R14*8)(%rdi) -+ movq %r15, (JB_R15*8)(%rdi) -+ leaq 8(%rsp), %rdx /* Save SP as it will be after we return. */ -+ movq %rdx, (JB_RSP*8)(%rdi) -+ movq (%rsp), %rax /* Save PC we are returning to now. */ -+ movq %rax, (JB_PC*8)(%rdi) -+ /* Set return value for setjmp. */ -+ mov $0,%eax -+ movq (JB_PC*8)(%rdi),%rdx -+ movq (JB_RSP*8)(%rdi),%rsp -+ jmpq *%rdx -+ -+ENTRY(kgdb_fault_longjmp) -+ /* Restore registers. */ -+ movq (JB_RBX*8)(%rdi),%rbx -+ movq (JB_RBP*8)(%rdi),%rbp -+ movq (JB_R12*8)(%rdi),%r12 -+ movq (JB_R13*8)(%rdi),%r13 -+ movq (JB_R14*8)(%rdi),%r14 -+ movq (JB_R15*8)(%rdi),%r15 -+ /* Set return value for setjmp. */ -+ movq (JB_PC*8)(%rdi),%rdx -+ movq (JB_RSP*8)(%rdi),%rsp -+ mov $1,%eax -+ jmpq *%rdx -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/x86_64/kernel/kgdb.c linux-2.6.18-53.1.14.kgdb/arch/x86_64/kernel/kgdb.c ---- linux-2.6.18-53.1.14/arch/x86_64/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/x86_64/kernel/kgdb.c 2008-06-10 15:38:44.000000000 +0400 -@@ -0,0 +1,474 @@ -+/* -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2, or (at your option) any -+ * later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ */ -+ -+/* -+ * Copyright (C) 2004 Amit S. Kale -+ * Copyright (C) 2000-2001 VERITAS Software Corporation. -+ * Copyright (C) 2002 Andi Kleen, SuSE Labs -+ * Copyright (C) 2004 LinSysSoft Technologies Pvt. Ltd. -+ */ -+/**************************************************************************** -+ * Contributor: Lake Stevens Instrument Division$ -+ * Written by: Glenn Engel $ -+ * Updated by: Amit Kale -+ * Modified for 386 by Jim Kingdon, Cygnus Support. -+ * Origianl kgdb, compatibility with 2.1.xx kernel by -+ * David Grothe -+ * Integrated into 2.2.5 kernel by Tigran Aivazian -+ * X86_64 changes from Andi Kleen's patch merged by Jim Houston -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* for linux pt_regs struct */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Put the error code here just in case the user cares. */ -+int gdb_x86_64errcode; -+/* Likewise, the vector number here (since GDB only gets the signal -+ number through the usual means, and that's not very specific). */ -+int gdb_x86_64vector = -1; -+ -+extern atomic_t cpu_doing_single_step; -+ -+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) -+{ -+ gdb_regs[_RAX] = regs->rax; -+ gdb_regs[_RBX] = regs->rbx; -+ gdb_regs[_RCX] = regs->rcx; -+ gdb_regs[_RDX] = regs->rdx; -+ gdb_regs[_RSI] = regs->rsi; -+ gdb_regs[_RDI] = regs->rdi; -+ gdb_regs[_RBP] = regs->rbp; -+ gdb_regs[_PS] = regs->eflags; -+ gdb_regs[_PC] = regs->rip; -+ gdb_regs[_R8] = regs->r8; -+ gdb_regs[_R9] = regs->r9; -+ gdb_regs[_R10] = regs->r10; -+ gdb_regs[_R11] = regs->r11; -+ gdb_regs[_R12] = regs->r12; -+ gdb_regs[_R13] = regs->r13; -+ gdb_regs[_R14] = regs->r14; -+ gdb_regs[_R15] = regs->r15; -+ gdb_regs[_RSP] = regs->rsp; -+} -+ -+extern void thread_return(void); -+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) -+{ -+ gdb_regs[_RAX] = 0; -+ gdb_regs[_RBX] = 0; -+ gdb_regs[_RCX] = 0; -+ gdb_regs[_RDX] = 0; -+ gdb_regs[_RSI] = 0; -+ gdb_regs[_RDI] = 0; -+ gdb_regs[_RBP] = *(unsigned long *)p->thread.rsp; -+ gdb_regs[_PS] = *(unsigned long *)(p->thread.rsp + 8); -+ gdb_regs[_PC] = (unsigned long)&thread_return; -+ gdb_regs[_R8] = 0; -+ gdb_regs[_R9] = 0; -+ gdb_regs[_R10] = 0; -+ gdb_regs[_R11] = 0; -+ gdb_regs[_R12] = 0; -+ gdb_regs[_R13] = 0; -+ gdb_regs[_R14] = 0; -+ gdb_regs[_R15] = 0; -+ gdb_regs[_RSP] = p->thread.rsp; -+} -+ -+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs) -+{ -+ regs->rax = gdb_regs[_RAX]; -+ regs->rbx = gdb_regs[_RBX]; -+ regs->rcx = gdb_regs[_RCX]; -+ regs->rdx = gdb_regs[_RDX]; -+ regs->rsi = gdb_regs[_RSI]; -+ regs->rdi = gdb_regs[_RDI]; -+ regs->rbp = gdb_regs[_RBP]; -+ regs->eflags = gdb_regs[_PS]; -+ regs->rip = gdb_regs[_PC]; -+ regs->r8 = gdb_regs[_R8]; -+ regs->r9 = gdb_regs[_R9]; -+ regs->r10 = gdb_regs[_R10]; -+ regs->r11 = gdb_regs[_R11]; -+ regs->r12 = gdb_regs[_R12]; -+ regs->r13 = gdb_regs[_R13]; -+ regs->r14 = gdb_regs[_R14]; -+ regs->r15 = gdb_regs[_R15]; -+#if 0 /* can't change these */ -+ regs->rsp = gdb_regs[_RSP]; -+ regs->ss = gdb_regs[_SS]; -+ regs->fs = gdb_regs[_FS]; -+ regs->gs = gdb_regs[_GS]; -+#endif -+ -+} /* gdb_regs_to_regs */ -+ -+struct hw_breakpoint { -+ unsigned enabled; -+ unsigned type; -+ unsigned len; -+ unsigned long addr; -+} breakinfo[4] = { { -+enabled:0}, { -+enabled:0}, { -+enabled:0}, { -+enabled:0}}; -+ -+void kgdb_correct_hw_break(void) -+{ -+ int breakno; -+ int correctit; -+ int breakbit; -+ unsigned long dr7; -+ -+ asm volatile ("movq %%db7, %0\n":"=r" (dr7):); -+ do { -+ unsigned long addr0, addr1, addr2, addr3; -+ asm volatile ("movq %%db0, %0\n" -+ "movq %%db1, %1\n" -+ "movq %%db2, %2\n" -+ "movq %%db3, %3\n":"=r" (addr0), "=r"(addr1), -+ "=r"(addr2), "=r"(addr3):); -+ } while (0); -+ correctit = 0; -+ for (breakno = 0; breakno < 3; breakno++) { -+ breakbit = 2 << (breakno << 1); -+ if (!(dr7 & breakbit) && breakinfo[breakno].enabled) { -+ correctit = 1; -+ dr7 |= breakbit; -+ dr7 &= ~(0xf0000 << (breakno << 2)); -+ dr7 |= (((breakinfo[breakno].len << 2) | -+ breakinfo[breakno].type) << 16) << -+ (breakno << 2); -+ switch (breakno) { -+ case 0: -+ asm volatile ("movq %0, %%dr0\n"::"r" -+ (breakinfo[breakno].addr)); -+ break; -+ -+ case 1: -+ asm volatile ("movq %0, %%dr1\n"::"r" -+ (breakinfo[breakno].addr)); -+ break; -+ -+ case 2: -+ asm volatile ("movq %0, %%dr2\n"::"r" -+ (breakinfo[breakno].addr)); -+ break; -+ -+ case 3: -+ asm volatile ("movq %0, %%dr3\n"::"r" -+ (breakinfo[breakno].addr)); -+ break; -+ } -+ } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) { -+ correctit = 1; -+ dr7 &= ~breakbit; -+ dr7 &= ~(0xf0000 << (breakno << 2)); -+ } -+ } -+ if (correctit) { -+ asm volatile ("movq %0, %%db7\n"::"r" (dr7)); -+ } -+} -+ -+int kgdb_remove_hw_break(unsigned long addr) -+{ -+ int i, idx = -1; -+ for (i = 0; i < 4; i++) { -+ if (breakinfo[i].addr == addr && breakinfo[i].enabled) { -+ idx = i; -+ break; -+ } -+ } -+ if (idx == -1) -+ return -1; -+ -+ breakinfo[idx].enabled = 0; -+ return 0; -+} -+ -+int kgdb_set_hw_break(unsigned long addr) -+{ -+ int i, idx = -1; -+ for (i = 0; i < 4; i++) { -+ if (!breakinfo[i].enabled) { -+ idx = i; -+ break; -+ } -+ } -+ if (idx == -1) -+ return -1; -+ -+ breakinfo[idx].enabled = 1; -+ breakinfo[idx].type = 1; -+ breakinfo[idx].len = 1; -+ breakinfo[idx].addr = addr; -+ return 0; -+} -+ -+int remove_hw_break(unsigned breakno) -+{ -+ if (!breakinfo[breakno].enabled) { -+ return -1; -+ } -+ breakinfo[breakno].enabled = 0; -+ return 0; -+} -+ -+int set_hw_break(unsigned breakno, unsigned type, unsigned len, unsigned addr) -+{ -+ if (breakinfo[breakno].enabled) { -+ return -1; -+ } -+ breakinfo[breakno].enabled = 1; -+ breakinfo[breakno].type = type; -+ breakinfo[breakno].len = len; -+ breakinfo[breakno].addr = addr; -+ return 0; -+} -+ -+void kgdb_disable_hw_debug(struct pt_regs *regs) -+{ -+ /* Disable hardware debugging while we are in kgdb */ -+ asm volatile ("movq %0,%%db7": /* no output */ :"r" (0UL)); -+} -+ -+void kgdb_post_master_code(struct pt_regs *regs, int e_vector, int err_code) -+{ -+ /* Master processor is completely in the debugger */ -+ gdb_x86_64vector = e_vector; -+ gdb_x86_64errcode = err_code; -+} -+ -+void kgdb_roundup_cpus(unsigned long flags) -+{ -+ send_IPI_allbutself(APIC_DM_NMI); -+} -+ -+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, length; -+ unsigned long breakno, breaktype; -+ char *ptr; -+ int newPC; -+ unsigned long dr6; -+ -+ switch (remcomInBuffer[0]) { -+ case 'c': -+ case 's': -+ /* try to read optional parameter, pc unchanged if no parm */ -+ ptr = &remcomInBuffer[1]; -+ if (kgdb_hex2long(&ptr, &addr)) -+ linux_regs->rip = addr; -+ newPC = linux_regs->rip; -+ -+ /* clear the trace bit */ -+ linux_regs->eflags &= ~TF_MASK; -+ -+ atomic_set(&cpu_doing_single_step, -1); -+ /* set the trace bit if we're stepping */ -+ if (remcomInBuffer[0] == 's') { -+ linux_regs->eflags |= TF_MASK; -+ debugger_step = 1; -+ if (kgdb_contthread) -+ atomic_set(&cpu_doing_single_step, -+ smp_processor_id()); -+ -+ } -+ -+ asm volatile ("movq %%db6, %0\n":"=r" (dr6)); -+ if (!(dr6 & 0x4000)) { -+ for (breakno = 0; breakno < 4; ++breakno) { -+ if (dr6 & (1 << breakno)) { -+ if (breakinfo[breakno].type == 0) { -+ /* Set restore flag */ -+ linux_regs->eflags |= -+ X86_EFLAGS_RF; -+ break; -+ } -+ } -+ } -+ } -+ kgdb_correct_hw_break(); -+ asm volatile ("movq %0, %%db6\n"::"r" (0UL)); -+ -+ return (0); -+ -+ case 'Y': -+ ptr = &remcomInBuffer[1]; -+ kgdb_hex2long(&ptr, &breakno); -+ ptr++; -+ kgdb_hex2long(&ptr, &breaktype); -+ ptr++; -+ kgdb_hex2long(&ptr, &length); -+ ptr++; -+ kgdb_hex2long(&ptr, &addr); -+ if (set_hw_break(breakno & 0x3, breaktype & 0x3, -+ length & 0x3, addr) == 0) -+ strcpy(remcomOutBuffer, "OK"); -+ else -+ strcpy(remcomOutBuffer, "ERROR"); -+ break; -+ -+ /* Remove hardware breakpoint */ -+ case 'y': -+ ptr = &remcomInBuffer[1]; -+ kgdb_hex2long(&ptr, &breakno); -+ if (remove_hw_break(breakno & 0x3) == 0) -+ strcpy(remcomOutBuffer, "OK"); -+ else -+ strcpy(remcomOutBuffer, "ERROR"); -+ break; -+ -+ } /* switch */ -+ return -1; -+} -+ -+static struct pt_regs *in_interrupt_stack(unsigned long rsp, int cpu) -+{ -+ struct pt_regs *regs; -+ unsigned long end = (unsigned long)cpu_pda(cpu)->irqstackptr; -+ if (rsp <= end && rsp >= end - IRQSTACKSIZE + 8) { -+ regs = *(((struct pt_regs **)end) - 1); -+ return regs; -+ } -+ return NULL; -+} -+ -+static struct pt_regs *in_exception_stack(unsigned long rsp, int cpu) -+{ -+ int i; -+ struct tss_struct *init_tss = &__get_cpu_var(init_tss); -+ for (i = 0; i < N_EXCEPTION_STACKS; i++) -+ if (rsp >= init_tss[cpu].ist[i] && -+ rsp <= init_tss[cpu].ist[i] + EXCEPTION_STKSZ) { -+ struct pt_regs *r = -+ (void *)init_tss[cpu].ist[i] + EXCEPTION_STKSZ; -+ return r - 1; -+ } -+ return NULL; -+} -+ -+void kgdb_shadowinfo(struct pt_regs *regs, char *buffer, unsigned threadid) -+{ -+ static char intr_desc[] = "Stack at interrupt entrypoint"; -+ static char exc_desc[] = "Stack at exception entrypoint"; -+ struct pt_regs *stregs; -+ int cpu = hard_smp_processor_id(); -+ -+ if ((stregs = in_interrupt_stack(regs->rsp, cpu))) -+ kgdb_mem2hex(intr_desc, buffer, strlen(intr_desc)); -+ else if ((stregs = in_exception_stack(regs->rsp, cpu))) -+ kgdb_mem2hex(exc_desc, buffer, strlen(exc_desc)); -+} -+ -+struct task_struct *kgdb_get_shadow_thread(struct pt_regs *regs, int threadid) -+{ -+ struct pt_regs *stregs; -+ int cpu = hard_smp_processor_id(); -+ -+ if ((stregs = in_interrupt_stack(regs->rsp, cpu))) -+ return current; -+ else if ((stregs = in_exception_stack(regs->rsp, cpu))) -+ return current; -+ -+ return NULL; -+} -+ -+struct pt_regs *kgdb_shadow_regs(struct pt_regs *regs, int threadid) -+{ -+ struct pt_regs *stregs; -+ int cpu = hard_smp_processor_id(); -+ -+ if ((stregs = in_interrupt_stack(regs->rsp, cpu))) -+ return stregs; -+ else if ((stregs = in_exception_stack(regs->rsp, cpu))) -+ return stregs; -+ -+ return NULL; -+} -+ -+/* Register KGDB with the die_chain so that we hook into all of the right -+ * spots. */ -+static int kgdb_notify(struct notifier_block *self, unsigned long cmd, -+ void *ptr) -+{ -+ struct die_args *args = ptr; -+ struct pt_regs *regs = args->regs; -+ -+ if (cmd == DIE_PAGE_FAULT_NO_CONTEXT && atomic_read(&debugger_active) -+ && kgdb_may_fault) { -+ kgdb_fault_longjmp(kgdb_fault_jmp_regs); -+ return NOTIFY_STOP; -+ /* CPU roundup? */ -+ } else if (atomic_read(&debugger_active) && cmd == DIE_NMI_IPI) { -+ kgdb_nmihook(smp_processor_id(), regs); -+ return NOTIFY_STOP; -+ /* See if KGDB is interested. */ -+ } else if (cmd == DIE_PAGE_FAULT || user_mode(regs) || -+ cmd == DIE_NMI_IPI || (cmd == DIE_DEBUG && -+ atomic_read(&debugger_active))) -+ /* Userpace events, normal watchdog event, or spurious -+ * debug exception. Ignore. */ -+ return NOTIFY_DONE; -+ -+ kgdb_handle_exception(args->trapnr, args->signr, args->err, regs); -+ -+ return NOTIFY_STOP; -+} -+ -+static struct notifier_block kgdb_notifier = { -+ .notifier_call = kgdb_notify, -+ .priority = 0x7fffffff, /* we need to notified first */ -+}; -+ -+int kgdb_arch_init(void) -+{ -+ atomic_notifier_chain_register(&die_chain, &kgdb_notifier); -+ return 0; -+} -+/* -+ * Skip an int3 exception when it occurs after a breakpoint has been -+ * removed. Backtrack eip by 1 since the int3 would have caused it to -+ * increment by 1. -+ */ -+ -+int kgdb_skipexception(int exception, struct pt_regs *regs) -+{ -+ if (exception == 3 && kgdb_isremovedbreak(regs->rip - 1)) { -+ regs->rip -= 1; -+ return 1; -+ } -+ return 0; -+} -+ -+struct kgdb_arch arch_kgdb_ops = { -+ .gdb_bpt_instr = {0xcc}, -+ .flags = KGDB_HW_BREAKPOINT, -+ .shadowth = 1, -+}; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/arch/x86_64/mm/fault.c linux-2.6.18-53.1.14.kgdb/arch/x86_64/mm/fault.c ---- linux-2.6.18-53.1.14/arch/x86_64/mm/fault.c 2008-03-06 05:54:27.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/arch/x86_64/mm/fault.c 2008-06-10 15:38:41.000000000 +0400 -@@ -557,6 +557,10 @@ no_context: - if (is_errata93(regs, address)) - return; - -+ if (notify_die(DIE_PAGE_FAULT_NO_CONTEXT, "no context", regs, -+ error_code, 14, SIGSEGV) == NOTIFY_STOP) -+ return; -+ - /* - * Oops. The kernel tried to access some bad page. We'll have to - * terminate things with extreme prejudice. -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/char/keyboard.c linux-2.6.18-53.1.14.kgdb/drivers/char/keyboard.c ---- linux-2.6.18-53.1.14/drivers/char/keyboard.c 2008-03-06 05:54:23.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/drivers/char/keyboard.c 2008-06-10 15:39:11.000000000 +0400 -@@ -1174,6 +1174,7 @@ static void kbd_keycode(unsigned int key - sysrq_down = 0; - if (sysrq_down && down && !rep) { - handle_sysrq(kbd_sysrq_xlate[keycode], regs, tty); -+ sysrq_down = 0; /* In case we miss the 'up' event. */ - return; - } - #endif -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/net/Makefile linux-2.6.18-53.1.14.kgdb/drivers/net/Makefile ---- linux-2.6.18-53.1.14/drivers/net/Makefile 2008-03-06 05:54:59.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/drivers/net/Makefile 2008-06-10 15:37:55.000000000 +0400 -@@ -221,6 +221,7 @@ obj-$(CONFIG_ETRAX_ETHERNET) += cris/ - obj-$(CONFIG_ENP2611_MSF_NET) += ixp2000/ - - obj-$(CONFIG_NETCONSOLE) += netconsole.o -+obj-$(CONFIG_KGDBOE) += kgdboe.o - - obj-$(CONFIG_FS_ENET) += fs_enet/ - -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/net/kgdboe.c linux-2.6.18-53.1.14.kgdb/drivers/net/kgdboe.c ---- linux-2.6.18-53.1.14/drivers/net/kgdboe.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/drivers/net/kgdboe.c 2008-06-10 15:37:55.000000000 +0400 -@@ -0,0 +1,294 @@ -+/* -+ * drivers/net/kgdboe.c -+ * -+ * A network interface for GDB. -+ * Based upon 'gdbserial' by David Grothe -+ * and Scott Foehner -+ * -+ * Maintainers: Amit S. Kale and -+ * Tom Rini -+ * -+ * 2004 (c) Amit S. Kale -+ * 2004-2005 (c) MontaVista Software, Inc. -+ * 2005 (c) Wind River Systems, Inc. -+ * -+ * Contributors at various stages not listed above: -+ * San Mehat , Robert Walsh , -+ * wangdi , Matt Mackall , -+ * Pavel Machek , Jason Wessel -+ * -+ * This file is licensed under the terms of the GNU General Public License -+ * version 2. This program is licensed "as is" without any warranty of any -+ * kind, whether express or implied. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define IN_BUF_SIZE 512 /* power of 2, please */ -+#define NOT_CONFIGURED_STRING "not_configured" -+#define OUT_BUF_SIZE 30 /* We don't want to send too big of a packet. */ -+#define MAX_KGDBOE_CONFIG_STR 256 -+ -+static char in_buf[IN_BUF_SIZE], out_buf[OUT_BUF_SIZE]; -+static int in_head, in_tail, out_count; -+static atomic_t in_count; -+/* 0 = unconfigured, 1 = netpoll options parsed, 2 = fully configured. */ -+static int configured; -+static struct kgdb_io local_kgdb_io_ops; -+static int use_dynamic_mac; -+ -+MODULE_DESCRIPTION("KGDB driver for network interfaces"); -+MODULE_LICENSE("GPL"); -+static char config[MAX_KGDBOE_CONFIG_STR] = NOT_CONFIGURED_STRING; -+static struct kparam_string kps = { -+ .string = config, -+ .maxlen = MAX_KGDBOE_CONFIG_STR, -+}; -+ -+static void rx_hook(struct netpoll *np, int port, char *msg, int len, -+ struct sk_buff *skb) -+{ -+ int i; -+ -+ np->remote_port = port; -+ -+ /* Copy the MAC address if we need to. */ -+ if (use_dynamic_mac) { -+ memcpy(np->remote_mac, eth_hdr(skb)->h_source, -+ sizeof(np->remote_mac)); -+ use_dynamic_mac = 0; -+ } -+ -+ /* -+ * This could be GDB trying to attach. But it could also be GDB -+ * finishing up a session, with kgdb_connected=0 but GDB sending -+ * an ACK for the final packet. To make sure we don't try and -+ * make a breakpoint when GDB is leaving, make sure that if -+ * !kgdb_connected the only len == 1 packet we allow is ^C. -+ */ -+ if (!kgdb_connected && (len != 1 || msg[0] == 3) && -+ !atomic_read(&kgdb_setting_breakpoint)) { -+ tasklet_schedule(&kgdb_tasklet_breakpoint); -+ } -+ -+ for (i = 0; i < len; i++) { -+ if (msg[i] == 3) -+ tasklet_schedule(&kgdb_tasklet_breakpoint); -+ -+ if (atomic_read(&in_count) >= IN_BUF_SIZE) { -+ /* buffer overflow, clear it */ -+ in_head = in_tail = 0; -+ atomic_set(&in_count, 0); -+ break; -+ } -+ in_buf[in_head++] = msg[i]; -+ in_head &= (IN_BUF_SIZE - 1); -+ atomic_inc(&in_count); -+ } -+} -+ -+static struct netpoll np = { -+ .dev_name = "eth0", -+ .name = "kgdboe", -+ .rx_hook = rx_hook, -+ .local_port = 6443, -+ .remote_port = 6442, -+ .remote_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, -+}; -+ -+static void eth_pre_exception_handler(void) -+{ -+ /* Increment the module count when the debugger is active */ -+ if (!kgdb_connected) -+ try_module_get(THIS_MODULE); -+ netpoll_set_trap(1); -+} -+ -+static void eth_post_exception_handler(void) -+{ -+ /* decrement the module count when the debugger detaches */ -+ if (!kgdb_connected) -+ module_put(THIS_MODULE); -+ netpoll_set_trap(0); -+} -+ -+static int eth_get_char(void) -+{ -+ int chr; -+ -+ while (atomic_read(&in_count) == 0) -+ netpoll_poll(&np); -+ -+ chr = in_buf[in_tail++]; -+ in_tail &= (IN_BUF_SIZE - 1); -+ atomic_dec(&in_count); -+ return chr; -+} -+ -+static void eth_flush_buf(void) -+{ -+ if (out_count && np.dev) { -+ netpoll_send_udp(&np, out_buf, out_count); -+ memset(out_buf, 0, sizeof(out_buf)); -+ out_count = 0; -+ } -+} -+ -+static void eth_put_char(u8 chr) -+{ -+ out_buf[out_count++] = chr; -+ if (out_count == OUT_BUF_SIZE) -+ eth_flush_buf(); -+} -+ -+static int option_setup(char *opt) -+{ -+ char opt_scratch[MAX_KGDBOE_CONFIG_STR]; -+ -+ /* If we're being given a new configuration, copy it in. */ -+ if (opt != config) -+ strcpy(config, opt); -+ /* But work on a copy as netpoll_parse_options will eat it. */ -+ strcpy(opt_scratch, opt); -+ configured = !netpoll_parse_options(&np, opt_scratch); -+ -+ use_dynamic_mac = 1; -+ -+ return 0; -+} -+__setup("kgdboe=", option_setup); -+ -+/* With our config string set by some means, configure kgdboe. */ -+static int configure_kgdboe(void) -+{ -+ /* Try out the string. */ -+ option_setup(config); -+ -+ if (!configured) { -+ printk(KERN_ERR "kgdboe: configuration incorrect - kgdboe not " -+ "loaded.\n"); -+ printk(KERN_ERR " Usage: kgdboe=[src-port]@[src-ip]/[dev]," -+ "[tgt-port]@/\n"); -+ return -EINVAL; -+ } -+ -+ /* Bring it up. */ -+ if (netpoll_setup(&np)) { -+ printk(KERN_ERR "kgdboe: netpoll_setup failed kgdboe failed\n"); -+ return -EINVAL; -+ } -+ -+ if (kgdb_register_io_module(&local_kgdb_io_ops)) { -+ netpoll_cleanup(&np); -+ return -EINVAL; -+ } -+ -+ configured = 2; -+ -+ return 0; -+} -+ -+static int init_kgdboe(void) -+{ -+ int ret; -+ -+ /* Already done? */ -+ if (configured == 2) -+ return 0; -+ -+ /* OK, go ahead and do it. */ -+ ret = configure_kgdboe(); -+ -+ if (configured == 2) -+ printk(KERN_INFO "kgdboe: debugging over ethernet enabled\n"); -+ -+ return ret; -+} -+ -+static void cleanup_kgdboe(void) -+{ -+ netpoll_cleanup(&np); -+ configured = 0; -+ kgdb_unregister_io_module(&local_kgdb_io_ops); -+} -+ -+static int param_set_kgdboe_var(const char *kmessage, struct kernel_param *kp) -+{ -+ char kmessage_save[MAX_KGDBOE_CONFIG_STR]; -+ int msg_len = strlen(kmessage); -+ -+ if (msg_len + 1 > MAX_KGDBOE_CONFIG_STR) { -+ printk(KERN_ERR "%s: string doesn't fit in %u chars.\n", -+ kp->name, MAX_KGDBOE_CONFIG_STR - 1); -+ return -ENOSPC; -+ } -+ -+ if (kgdb_connected) { -+ printk(KERN_ERR "kgdboe: Cannot reconfigure while KGDB is " -+ "connected.\n"); -+ return 0; -+ } -+ -+ /* Start the reconfiguration process by saving the old string */ -+ strncpy(kmessage_save, config, sizeof(kmessage_save)); -+ -+ -+ /* Copy in the new param and strip out invalid characters so we -+ * can optionally specify the MAC. -+ */ -+ strncpy(config, kmessage, sizeof(config)); -+ msg_len--; -+ while (msg_len > 0 && -+ (config[msg_len] < ',' || config[msg_len] > 'f')) { -+ config[msg_len] = '\0'; -+ msg_len--; -+ } -+ -+ /* Check to see if we are unconfiguring the io module and that it -+ * was in a fully configured state, as this is the only time that -+ * netpoll_cleanup should get called -+ */ -+ if (configured == 2 && strcmp(config, NOT_CONFIGURED_STRING) == 0) { -+ printk(KERN_INFO "kgdboe: reverting to unconfigured state\n"); -+ cleanup_kgdboe(); -+ return 0; -+ } else -+ /* Go and configure with the new params. */ -+ configure_kgdboe(); -+ -+ if (configured == 2) -+ return 0; -+ -+ /* If the new string was invalid, revert to the previous state, which -+ * is at a minimum not_configured. */ -+ strncpy(config, kmessage_save, sizeof(config)); -+ if (strcmp(kmessage_save, NOT_CONFIGURED_STRING) != 0) { -+ printk(KERN_INFO "kgdboe: reverting to prior configuration\n"); -+ /* revert back to the original config */ -+ strncpy(config, kmessage_save, sizeof(config)); -+ configure_kgdboe(); -+ } -+ return 0; -+} -+ -+static struct kgdb_io local_kgdb_io_ops = { -+ .read_char = eth_get_char, -+ .write_char = eth_put_char, -+ .init = init_kgdboe, -+ .flush = eth_flush_buf, -+ .pre_exception = eth_pre_exception_handler, -+ .post_exception = eth_post_exception_handler -+}; -+ -+module_init(init_kgdboe); -+module_exit(cleanup_kgdboe); -+module_param_call(kgdboe, param_set_kgdboe_var, param_get_string, &kps, 0644); -+MODULE_PARM_DESC(kgdboe, " kgdboe=[src-port]@[src-ip]/[dev]," -+ "[tgt-port]@/\n"); -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/serial/8250.c linux-2.6.18-53.1.14.kgdb/drivers/serial/8250.c ---- linux-2.6.18-53.1.14/drivers/serial/8250.c 2008-03-06 05:54:43.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/drivers/serial/8250.c 2008-06-10 15:37:43.000000000 +0400 -@@ -2656,6 +2656,25 @@ void serial8250_unregister_port(int line - } - EXPORT_SYMBOL(serial8250_unregister_port); - -+/** -+ * serial8250_unregister_by_port - remove a 16x50 serial port -+ * at runtime. -+ * @port: A &struct uart_port that describes the port to remove. -+ * -+ * Remove one serial port. This may not be called from interrupt -+ * context. We hand the port back to the our control. -+ */ -+void serial8250_unregister_by_port(struct uart_port *port) -+{ -+ struct uart_8250_port *uart; -+ -+ uart = serial8250_find_match_or_unused(port); -+ -+ if (uart) -+ serial8250_unregister_port(uart->port.line); -+} -+EXPORT_SYMBOL(serial8250_unregister_by_port); -+ - static int __init serial8250_init(void) - { - int ret, i; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/serial/8250_kgdb.c linux-2.6.18-53.1.14.kgdb/drivers/serial/8250_kgdb.c ---- linux-2.6.18-53.1.14/drivers/serial/8250_kgdb.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/drivers/serial/8250_kgdb.c 2008-06-10 15:37:43.000000000 +0400 -@@ -0,0 +1,516 @@ -+/* -+ * 8250 interface for kgdb. -+ * -+ * This is a merging of many different drivers, and all of the people have -+ * had an impact in some form or another: -+ * -+ * 2004-2005 (c) MontaVista Software, Inc. -+ * 2005-2006 (c) Wind River Systems, Inc. -+ * -+ * Amit Kale , David Grothe , -+ * Scott Foehner , George Anzinger , -+ * Robert Walsh , wangdi , -+ * San Mehat, Tom Rini , -+ * Jason Wessel -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include /* For BASE_BAUD and SERIAL_PORT_DFNS */ -+ -+#include "8250.h" -+ -+#define GDB_BUF_SIZE 512 /* power of 2, please */ -+ -+MODULE_DESCRIPTION("KGDB driver for the 8250"); -+MODULE_LICENSE("GPL"); -+/* These will conflict with early_param otherwise. */ -+#ifdef CONFIG_KGDB_8250_MODULE -+static char config[256]; -+module_param_string(kgdb8250, config, 256, 0); -+MODULE_PARM_DESC(kgdb8250, -+ " kgdb8250=,
,,\n"); -+static struct kgdb_io local_kgdb_io_ops; -+#endif /* CONFIG_KGDB_8250_MODULE */ -+ -+/* Speed of the UART. */ -+static int kgdb8250_baud; -+ -+/* Flag for if we need to call request_mem_region */ -+static int kgdb8250_needs_request_mem_region; -+ -+static char kgdb8250_buf[GDB_BUF_SIZE]; -+static atomic_t kgdb8250_buf_in_cnt; -+static int kgdb8250_buf_out_inx; -+ -+/* Old-style serial definitions, if existant, and a counter. */ -+#ifdef CONFIG_KGDB_SIMPLE_SERIAL -+static int __initdata should_copy_rs_table = 1; -+static struct serial_state old_rs_table[] __initdata = { -+#ifdef SERIAL_PORT_DFNS -+ SERIAL_PORT_DFNS -+#endif -+}; -+#endif -+ -+/* Our internal table of UARTS. */ -+#define UART_NR CONFIG_SERIAL_8250_NR_UARTS -+static struct uart_port kgdb8250_ports[UART_NR]; -+ -+static struct uart_port *current_port; -+ -+/* Base of the UART. */ -+static void *kgdb8250_addr; -+ -+/* Forward declarations. */ -+static int kgdb8250_uart_init(void); -+static int __init kgdb_init_io(void); -+static int __init kgdb8250_opt(char *str); -+ -+/* These are much shorter calls to ioread8/iowrite8 that take into -+ * account our shifts, etc. */ -+static inline unsigned int kgdb_ioread(u8 mask) -+{ -+ return ioread8(kgdb8250_addr + (mask << current_port->regshift)); -+} -+ -+static inline void kgdb_iowrite(u8 val, u8 mask) -+{ -+ iowrite8(val, kgdb8250_addr + (mask << current_port->regshift)); -+} -+ -+/* -+ * Wait until the interface can accept a char, then write it. -+ */ -+static void kgdb_put_debug_char(u8 chr) -+{ -+ while (!(kgdb_ioread(UART_LSR) & UART_LSR_THRE)) ; -+ -+ kgdb_iowrite(chr, UART_TX); -+} -+ -+/* -+ * Get a byte from the hardware data buffer and return it -+ */ -+static int read_data_bfr(void) -+{ -+ char it = kgdb_ioread(UART_LSR); -+ -+ if (it & UART_LSR_DR) -+ return kgdb_ioread(UART_RX); -+ -+ /* -+ * If we have a framing error assume somebody messed with -+ * our uart. Reprogram it and send '-' both ways... -+ */ -+ if (it & 0xc) { -+ kgdb8250_uart_init(); -+ kgdb_put_debug_char('-'); -+ return '-'; -+ } -+ -+ return -1; -+} -+ -+/* -+ * Get a char if available, return -1 if nothing available. -+ * Empty the receive buffer first, then look at the interface hardware. -+ */ -+static int kgdb_get_debug_char(void) -+{ -+ int retchr; -+ -+ /* intr routine has q'd chars */ -+ if (atomic_read(&kgdb8250_buf_in_cnt) != 0) { -+ retchr = kgdb8250_buf[kgdb8250_buf_out_inx++]; -+ kgdb8250_buf_out_inx &= (GDB_BUF_SIZE - 1); -+ atomic_dec(&kgdb8250_buf_in_cnt); -+ return retchr; -+ } -+ -+ do { -+ retchr = read_data_bfr(); -+ } while (retchr < 0); -+ -+ return retchr; -+} -+ -+/* -+ * This is the receiver interrupt routine for the GDB stub. -+ * All that we need to do is verify that the interrupt happened on the -+ * line we're in charge of. If this is true, schedule a breakpoint and -+ * return. -+ */ -+static irqreturn_t -+kgdb8250_interrupt(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ if (kgdb_ioread(UART_IIR) & UART_IIR_RDI) { -+ /* Throw away the data if another I/O routine is active. */ -+ if (kgdb_io_ops.read_char != kgdb_get_debug_char && -+ (kgdb_ioread(UART_LSR) & UART_LSR_DR)) -+ kgdb_ioread(UART_RX); -+ else -+ breakpoint(); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+/* -+ * Initializes the UART. -+ * Returns: -+ * 0 on success, 1 on failure. -+ */ -+static int -+kgdb8250_uart_init (void) -+{ -+ unsigned int ier, base_baud = current_port->uartclk ? -+ current_port->uartclk / 16 : BASE_BAUD; -+ -+ /* test uart existance */ -+ if(kgdb_ioread(UART_LSR) == 0xff) -+ return -1; -+ -+ /* disable interrupts */ -+ kgdb_iowrite(0, UART_IER); -+ -+#if defined(CONFIG_ARCH_OMAP1510) -+ /* Workaround to enable 115200 baud on OMAP1510 internal ports */ -+ if (cpu_is_omap1510() && is_omap_port((void *)kgdb8250_addr)) { -+ if (kgdb8250_baud == 115200) { -+ base_baud = 1; -+ kgdb8250_baud = 1; -+ kgdb_iowrite(1, UART_OMAP_OSC_12M_SEL); -+ } else -+ kgdb_iowrite(0, UART_OMAP_OSC_12M_SEL); -+ } -+#endif -+ /* set DLAB */ -+ kgdb_iowrite(UART_LCR_DLAB, UART_LCR); -+ -+ /* set baud */ -+ kgdb_iowrite((base_baud / kgdb8250_baud) & 0xff, UART_DLL); -+ kgdb_iowrite((base_baud / kgdb8250_baud) >> 8, UART_DLM); -+ -+ /* reset DLAB, set LCR */ -+ kgdb_iowrite(UART_LCR_WLEN8, UART_LCR); -+ -+ /* set DTR and RTS */ -+ kgdb_iowrite(UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS, UART_MCR); -+ -+ /* setup fifo */ -+ kgdb_iowrite(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR -+ | UART_FCR_CLEAR_XMIT | UART_FCR_TRIGGER_8, -+ UART_FCR); -+ -+ /* clear pending interrupts */ -+ kgdb_ioread(UART_IIR); -+ kgdb_ioread(UART_RX); -+ kgdb_ioread(UART_LSR); -+ kgdb_ioread(UART_MSR); -+ -+ /* turn on RX interrupt only */ -+ kgdb_iowrite(UART_IER_RDI, UART_IER); -+ -+ /* -+ * Borrowed from the main 8250 driver. -+ * Try writing and reading the UART_IER_UUE bit (b6). -+ * If it works, this is probably one of the Xscale platform's -+ * internal UARTs. -+ * We're going to explicitly set the UUE bit to 0 before -+ * trying to write and read a 1 just to make sure it's not -+ * already a 1 and maybe locked there before we even start start. -+ */ -+ ier = kgdb_ioread(UART_IER); -+ kgdb_iowrite(ier & ~UART_IER_UUE, UART_IER); -+ if (!(kgdb_ioread(UART_IER) & UART_IER_UUE)) { -+ /* -+ * OK it's in a known zero state, try writing and reading -+ * without disturbing the current state of the other bits. -+ */ -+ kgdb_iowrite(ier | UART_IER_UUE, UART_IER); -+ if (kgdb_ioread(UART_IER) & UART_IER_UUE) -+ /* -+ * It's an Xscale. -+ */ -+ ier |= UART_IER_UUE | UART_IER_RTOIE; -+ } -+ kgdb_iowrite(ier, UART_IER); -+ return 0; -+} -+ -+/* -+ * Copy the old serial_state table to our uart_port table if we haven't -+ * had values specifically configured in. We need to make sure this only -+ * happens once. -+ */ -+static void __init kgdb8250_copy_rs_table(void) -+{ -+#ifdef CONFIG_KGDB_SIMPLE_SERIAL -+ int i; -+ -+ if (!should_copy_rs_table) -+ return; -+ -+ for (i = 0; i < ARRAY_SIZE(old_rs_table); i++) { -+ kgdb8250_ports[i].iobase = old_rs_table[i].port; -+ kgdb8250_ports[i].irq = irq_canonicalize(old_rs_table[i].irq); -+ kgdb8250_ports[i].uartclk = old_rs_table[i].baud_base * 16; -+ kgdb8250_ports[i].membase = old_rs_table[i].iomem_base; -+ kgdb8250_ports[i].iotype = old_rs_table[i].io_type; -+ kgdb8250_ports[i].regshift = old_rs_table[i].iomem_reg_shift; -+ kgdb8250_ports[i].line = i; -+ } -+ -+ should_copy_rs_table = 0; -+#endif -+} -+ -+/* -+ * Hookup our IRQ line now that it is safe to do so, after we grab any -+ * memory regions we might need to. If we haven't been initialized yet, -+ * go ahead and copy the old_rs_table in. -+ */ -+static void __init kgdb8250_late_init(void) -+{ -+ /* Try and copy the old_rs_table. */ -+ kgdb8250_copy_rs_table(); -+ -+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE) -+ /* Take the port away from the main driver. */ -+ serial8250_unregister_by_port(current_port); -+ -+ /* Now reinit the port as the above has disabled things. */ -+ kgdb8250_uart_init(); -+#endif -+ /* We may need to call request_mem_region() first. */ -+ if (kgdb8250_needs_request_mem_region) -+ request_mem_region(current_port->mapbase, -+ 8 << current_port->regshift, "kgdb"); -+ if (request_irq(current_port->irq, kgdb8250_interrupt, SA_SHIRQ, -+ "GDB-stub", current_port) < 0) -+ printk(KERN_ERR "KGDB failed to request the serial IRQ (%d)\n", -+ current_port->irq); -+} -+ -+static __init int kgdb_init_io(void) -+{ -+ /* Give us the basic table of uarts. */ -+ kgdb8250_copy_rs_table(); -+ -+ /* We're either a module and parse a config string, or we have a -+ * semi-static config. */ -+#ifdef CONFIG_KGDB_8250_MODULE -+ if (strlen(config)) { -+ if (kgdb8250_opt(config)) -+ return -EINVAL; -+ } else { -+ printk(KERN_ERR "kgdb8250: argument error, usage: " -+ "kgdb8250=,
,,\n"); -+ return -EINVAL; -+ } -+#elif defined(CONFIG_KGDB_SIMPLE_SERIAL) -+ kgdb8250_baud = CONFIG_KGDB_BAUDRATE; -+ -+ /* Setup our pointer to the serial port now. */ -+ current_port = &kgdb8250_ports[CONFIG_KGDB_PORT_NUM]; -+#else -+ if (kgdb8250_opt(CONFIG_KGDB_8250_CONF_STRING)) -+ return -EINVAL; -+#endif -+ -+ -+ /* Internal driver setup. */ -+ switch (current_port->iotype) { -+ case UPIO_MEM: -+ if (current_port->mapbase) -+ kgdb8250_needs_request_mem_region = 1; -+ if (current_port->flags & UPF_IOREMAP) { -+ current_port->membase = ioremap(current_port->mapbase, -+ 8 << current_port->regshift); -+ if (!current_port->membase) -+ return -EIO; /* Failed. */ -+ } -+ kgdb8250_addr = current_port->membase; -+ break; -+ case UPIO_PORT: -+ default: -+ kgdb8250_addr = ioport_map(current_port->iobase, -+ 8 << current_port->regshift); -+ if (!kgdb8250_addr) -+ return -EIO; /* Failed. */ -+ } -+ -+ if (kgdb8250_uart_init() == -1) { -+ printk(KERN_ERR "kgdb8250: init failed\n"); -+ return -EIO; -+ } -+#ifdef CONFIG_KGDB_8250_MODULE -+ /* Attach the kgdb irq. When this is built into the kernel, it -+ * is called as a part of late_init sequence. -+ */ -+ kgdb8250_late_init(); -+ if (kgdb_register_io_module(&local_kgdb_io_ops)) -+ return -EINVAL; -+ -+ printk(KERN_INFO "kgdb8250: debugging enabled\n"); -+#endif /* CONFIG_KGD_8250_MODULE */ -+ -+ return 0; -+} -+ -+#ifdef CONFIG_KGDB_8250_MODULE -+/* If it is a module the kgdb_io_ops should be a static which -+ * is passed to the KGDB I/O initialization -+ */ -+static struct kgdb_io local_kgdb_io_ops = { -+#else /* ! CONFIG_KGDB_8250_MODULE */ -+struct kgdb_io kgdb_io_ops = { -+#endif /* ! CONFIG_KGD_8250_MODULE */ -+ .read_char = kgdb_get_debug_char, -+ .write_char = kgdb_put_debug_char, -+ .init = kgdb_init_io, -+ .late_init = kgdb8250_late_init, -+}; -+ -+/** -+ * kgdb8250_add_port - Define a serial port for use with KGDB -+ * @i: The index of the port being added -+ * @serial_req: The &struct uart_port describing the port -+ * -+ * On platforms where we must register the serial device -+ * dynamically, this is the best option if a platform also normally -+ * calls early_serial_setup(). -+ */ -+void __init kgdb8250_add_port(int i, struct uart_port *serial_req) -+{ -+ /* Make sure we've got the built-in data before we override. */ -+ kgdb8250_copy_rs_table(); -+ -+ /* Copy the whole thing over. */ -+ if (current_port != &kgdb8250_ports[i]) -+ memcpy(&kgdb8250_ports[i], serial_req, sizeof(struct uart_port)); -+} -+ -+/** -+ * kgdb8250_add_platform_port - Define a serial port for use with KGDB -+ * @i: The index of the port being added -+ * @p: The &struct plat_serial8250_port describing the port -+ * -+ * On platforms where we must register the serial device -+ * dynamically, this is the best option if a platform normally -+ * handles uart setup with an array of &struct plat_serial8250_port. -+ */ -+void __init kgdb8250_add_platform_port(int i, struct plat_serial8250_port *p) -+{ -+ /* Make sure we've got the built-in data before we override. */ -+ kgdb8250_copy_rs_table(); -+ -+ kgdb8250_ports[i].iobase = p->iobase; -+ kgdb8250_ports[i].membase = p->membase; -+ kgdb8250_ports[i].irq = p->irq; -+ kgdb8250_ports[i].uartclk = p->uartclk; -+ kgdb8250_ports[i].regshift = p->regshift; -+ kgdb8250_ports[i].iotype = p->iotype; -+ kgdb8250_ports[i].flags = p->flags; -+ kgdb8250_ports[i].mapbase = p->mapbase; -+} -+ -+/* -+ * Syntax for this cmdline option is: -+ * kgdb8250=,
,," -+ */ -+static int __init kgdb8250_opt(char *str) -+{ -+ /* We'll fill out and use the first slot. */ -+ current_port = &kgdb8250_ports[0]; -+ -+ if (!strncmp(str, "io", 2)) { -+ current_port->iotype = UPIO_PORT; -+ str += 2; -+ } else if (!strncmp(str, "mmap", 4)) { -+ current_port->iotype = UPIO_MEM; -+ current_port->flags |= UPF_IOREMAP; -+ str += 4; -+ } else if (!strncmp(str, "mmio", 4)) { -+ current_port->iotype = UPIO_MEM; -+ current_port->flags &= ~UPF_IOREMAP; -+ str += 4; -+ } else -+ goto errout; -+ -+ if (*str != ',') -+ goto errout; -+ str++; -+ -+ if (current_port->iotype == UPIO_PORT) -+ current_port->iobase = simple_strtoul(str, &str, 16); -+ else { -+ if (current_port->flags & UPF_IOREMAP) -+ current_port->mapbase = -+ (unsigned long) simple_strtoul(str, &str, 16); -+ else -+ current_port->membase = -+ (void *) simple_strtoul(str, &str, 16); -+ } -+ -+ if (*str != ',') -+ goto errout; -+ str++; -+ -+ kgdb8250_baud = simple_strtoul(str, &str, 10); -+ if (!kgdb8250_baud) -+ goto errout; -+ -+ if (*str != ',') -+ goto errout; -+ str++; -+ -+ current_port->irq = simple_strtoul(str, &str, 10); -+ -+#ifdef CONFIG_KGDB_SIMPLE_SERIAL -+ should_copy_rs_table = 0; -+#endif -+ -+ return 0; -+ -+ errout: -+ printk(KERN_ERR "Invalid syntax for option kgdb8250=\n"); -+ return 1; -+} -+ -+#ifdef CONFIG_KGDB_8250_MODULE -+static void cleanup_kgdb8250(void) -+{ -+ kgdb_unregister_io_module(&local_kgdb_io_ops); -+ -+ /* Clean up the irq and memory */ -+ free_irq(current_port->irq, current_port); -+ -+ if (kgdb8250_needs_request_mem_region) -+ release_mem_region(current_port->mapbase, -+ 8 << current_port->regshift); -+ /* Hook up the serial port back to what it was previously -+ * hooked up to. -+ */ -+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE) -+ /* Give the port back to the 8250 driver. */ -+ serial8250_register_port(current_port); -+#endif -+} -+ -+module_init(kgdb_init_io); -+module_exit(cleanup_kgdb8250); -+#else /* ! CONFIG_KGDB_8250_MODULE */ -+early_param("kgdb8250", kgdb8250_opt); -+#endif /* ! CONFIG_KGDB_8250_MODULE */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/serial/Kconfig linux-2.6.18-53.1.14.kgdb/drivers/serial/Kconfig ---- linux-2.6.18-53.1.14/drivers/serial/Kconfig 2008-03-06 05:54:47.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/drivers/serial/Kconfig 2008-06-10 15:37:43.000000000 +0400 -@@ -107,7 +107,7 @@ config SERIAL_8250_CS - - config SERIAL_8250_NR_UARTS - int "Maximum number of 8250/16550 serial ports" -- depends on SERIAL_8250 -+ depends on SERIAL_8250 || KGDB_8250 - default "4" - help - Set this to the number of serial ports you want the driver -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/serial/Makefile linux-2.6.18-53.1.14.kgdb/drivers/serial/Makefile ---- linux-2.6.18-53.1.14/drivers/serial/Makefile 2008-03-06 05:54:47.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/drivers/serial/Makefile 2008-06-10 15:38:14.000000000 +0400 -@@ -47,6 +47,7 @@ obj-$(CONFIG_SERIAL_IMX) += imx.o - obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o - obj-$(CONFIG_SERIAL_ICOM) += icom.o - obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o -+obj-$(CONFIG_KGDB_MPSC) += mpsc_kgdb.o - obj-$(CONFIG_SERIAL_MPSC) += mpsc.o - obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o - obj-$(CONFIG_SERIAL_JSM) += jsm/ -@@ -57,3 +58,4 @@ obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_se - obj-$(CONFIG_SERIAL_AT91) += at91_serial.o - obj-$(CONFIG_SERIAL_NETX) += netx-serial.o - obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o -+obj-$(CONFIG_KGDB_8250) += 8250_kgdb.o -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/serial/amba-pl011.c linux-2.6.18-53.1.14.kgdb/drivers/serial/amba-pl011.c ---- linux-2.6.18-53.1.14/drivers/serial/amba-pl011.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/drivers/serial/amba-pl011.c 2008-06-10 15:38:56.000000000 +0400 -@@ -340,7 +340,7 @@ static int pl011_startup(struct uart_por - /* - * Allocate the IRQ - */ -- retval = request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap); -+ retval = request_irq(uap->port.irq, pl011_int, SA_SHIRQ, "uart-pl011", uap); - if (retval) - goto clk_dis; - -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/serial/cpm_uart/Makefile linux-2.6.18-53.1.14.kgdb/drivers/serial/cpm_uart/Makefile ---- linux-2.6.18-53.1.14/drivers/serial/cpm_uart/Makefile 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/drivers/serial/cpm_uart/Makefile 2008-06-10 15:38:14.000000000 +0400 -@@ -7,5 +7,6 @@ obj-$(CONFIG_SERIAL_CPM) += cpm_uart.o - # Select the correct platform objects. - cpm_uart-objs-$(CONFIG_CPM2) += cpm_uart_cpm2.o - cpm_uart-objs-$(CONFIG_8xx) += cpm_uart_cpm1.o -+cpm_uart-objs-$(CONFIG_KGDB_CPM_UART) += cpm_uart_kgdb.o - - cpm_uart-objs := cpm_uart_core.o $(cpm_uart-objs-y) -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/serial/cpm_uart/cpm_uart.h linux-2.6.18-53.1.14.kgdb/drivers/serial/cpm_uart/cpm_uart.h ---- linux-2.6.18-53.1.14/drivers/serial/cpm_uart/cpm_uart.h 2008-03-06 05:54:12.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/drivers/serial/cpm_uart/cpm_uart.h 2008-06-10 15:38:14.000000000 +0400 -@@ -50,6 +50,39 @@ - - #define SCC_WAIT_CLOSING 100 - -+#ifdef CONFIG_KGDB_CPM_UART -+ -+/* Speed of the debug UART. */ -+#if defined(CONFIG_KGDB_9600BAUD) -+#define KGDB_BAUD B9600 -+#elif defined(CONFIG_KGDB_19200BAUD) -+#define KGDB_BAUD B19200 -+#elif defined(CONFIG_KGDB_38400BAUD) -+#define KGDB_BAUD B38400 -+#elif defined(CONFIG_KGDB_57600BAUD) -+#define KGDB_BAUD B57600 -+#else -+#define KGDB_BAUD B115200 /* Start with this if not given */ -+#endif -+ -+#ifdef CONFIG_KGDB_CPM_UART_SCC1 -+#define KGDB_PINFO_INDEX UART_SCC1 -+#elif CONFIG_KGDB_CPM_UART_SCC2 -+#define KGDB_PINFO_INDEX UART_SCC2 -+#elif CONFIG_KGDB_CPM_UART_SCC3 -+#define KGDB_PINFO_INDEX UART_SCC3 -+#elif CONFIG_KGDB_CPM_UART_SCC4 -+#define KGDB_PINFO_INDEX UART_SCC4 -+#elif CONFIG_KGDB_CPM_UART_SMC1 -+#define KGDB_PINFO_INDEX UART_SMC1 -+#elif CONFIG_KGDB_CPM_UART_SMC2 -+#define KGDB_PINFO_INDEX UART_SMC2 -+#else -+#error The S(M)CC for kgdb console is undefined -+#endif -+ -+#endif /* CONFIG_KGDB_CPM_UART */ -+ - struct uart_cpm_port { - struct uart_port port; - u16 rx_nrfifos; -@@ -86,6 +119,9 @@ extern int cpm_uart_port_map[UART_NR]; - extern int cpm_uart_nr; - extern struct uart_cpm_port cpm_uart_ports[UART_NR]; - -+void cpm_uart_early_write(int index, const char *s, u_int count); -+int cpm_uart_early_setup(int index,int early); -+ - /* these are located in their respective files */ - void cpm_line_cr_cmd(int line, int cmd); - int cpm_uart_init_portdesc(void); -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/serial/cpm_uart/cpm_uart_core.c linux-2.6.18-53.1.14.kgdb/drivers/serial/cpm_uart/cpm_uart_core.c ---- linux-2.6.18-53.1.14/drivers/serial/cpm_uart/cpm_uart_core.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/drivers/serial/cpm_uart/cpm_uart_core.c 2008-06-10 15:38:14.000000000 +0400 -@@ -1070,22 +1070,17 @@ int cpm_uart_drv_get_platform_data(struc - return 0; - } - --#ifdef CONFIG_SERIAL_CPM_CONSOLE --/* -- * Print a string to the serial port trying not to disturb -- * any possible real use of the port... -- * -- * Note that this is called with interrupts already disabled -- */ --static void cpm_uart_console_write(struct console *co, const char *s, -+void cpm_uart_early_write(int index, const char *s, - u_int count) - { -- struct uart_cpm_port *pinfo = -- &cpm_uart_ports[cpm_uart_port_map[co->index]]; -+ struct uart_cpm_port *pinfo; - unsigned int i; - volatile cbd_t *bdp, *bdbase; - volatile unsigned char *cp; - -+ BUG_ON(index>UART_NR); -+ pinfo = &cpm_uart_ports[index]; -+ - /* Get the address of the host memory buffer. - */ - bdp = pinfo->tx_cur; -@@ -1149,16 +1144,11 @@ static void cpm_uart_console_write(struc - pinfo->tx_cur = (volatile cbd_t *) bdp; - } - -- --static int __init cpm_uart_console_setup(struct console *co, char *options) -+int cpm_uart_early_setup(int index, int early) - { -+ int ret; - struct uart_port *port; - struct uart_cpm_port *pinfo; -- int baud = 38400; -- int bits = 8; -- int parity = 'n'; -- int flow = 'n'; -- int ret; - - struct fs_uart_platform_info *pdata; - struct platform_device* pdev = early_uart_get_pdev(co->index); -@@ -1169,8 +1159,9 @@ static int __init cpm_uart_console_setup - cpm_uart_init_portdesc(); - } - -+ BUG_ON(index>UART_NR); - port = -- (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]]; -+ (struct uart_port *)&cpm_uart_ports[index]; - pinfo = (struct uart_cpm_port *)port; - if (!pdev) { - if (pinfo->set_lineif) -@@ -1184,19 +1175,6 @@ static int __init cpm_uart_console_setup - cpm_uart_drv_get_platform_data(pdev, 1); - } - -- pinfo->flags |= FLAG_CONSOLE; -- -- if (options) { -- uart_parse_options(options, &baud, &parity, &bits, &flow); -- } else { -- bd_t *bd = (bd_t *) __res; -- -- if (bd->bi_baudrate) -- baud = bd->bi_baudrate; -- else -- baud = 9600; -- } -- - if (IS_SMC(pinfo)) { - pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); - pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); -@@ -1204,8 +1182,7 @@ static int __init cpm_uart_console_setup - pinfo->sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX); - pinfo->sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); - } -- -- ret = cpm_uart_allocbuf(pinfo, 1); -+ ret = cpm_uart_allocbuf(pinfo, early); - - if (ret) - return ret; -@@ -1217,6 +1194,56 @@ static int __init cpm_uart_console_setup - else - cpm_uart_init_scc(pinfo); - -+ return 0; -+} -+ -+#ifdef CONFIG_SERIAL_CPM_CONSOLE -+/* -+ * Print a string to the serial port trying not to disturb -+ * any possible real use of the port... -+ * -+ * Note that this is called with interrupts already disabled -+ */ -+ -+static void cpm_uart_console_write(struct console *co, const char *s, -+ u_int count) -+{ -+ cpm_uart_early_write(cpm_uart_port_map[co->index],s,count); -+} -+ -+/* -+ * Setup console. Be careful is called early ! -+ */ -+static int __init cpm_uart_console_setup(struct console *co, char *options) -+{ -+ struct uart_port *port; -+ struct uart_cpm_port *pinfo; -+ int baud = 115200; -+ int bits = 8; -+ int parity = 'n'; -+ int flow = 'n'; -+ int ret; -+ -+ port = -+ (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]]; -+ pinfo = (struct uart_cpm_port *)port; -+ -+ pinfo->flags |= FLAG_CONSOLE; -+ -+ if (options) { -+ uart_parse_options(options, &baud, &parity, &bits, &flow); -+ } else { -+ bd_t *bd = (bd_t *) __res; -+ -+ if (bd->bi_baudrate) -+ baud = bd->bi_baudrate; -+ else -+ baud = 9600; -+ } -+ -+ ret = cpm_uart_early_setup(cpm_uart_port_map[co->index], 1); -+ if(ret) -+ return ret; - uart_set_options(port, co, baud, parity, bits, flow); - - return 0; -@@ -1364,6 +1391,12 @@ static int cpm_uart_init(void) { - - for (i = 0; i < cpm_uart_nr; i++) { - int con = cpm_uart_port_map[i]; -+ -+#ifdef CONFIG_KGDB_CPM_UART -+ /* We are not interested in ports yet utilized by kgdb */ -+ if(con == KGDB_PINFO_INDEX) -+ continue; -+#endif - cpm_uart_ports[con].port.line = i; - cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF; - uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port); -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/serial/cpm_uart/cpm_uart_cpm1.c linux-2.6.18-53.1.14.kgdb/drivers/serial/cpm_uart/cpm_uart_cpm1.c ---- linux-2.6.18-53.1.14/drivers/serial/cpm_uart/cpm_uart_cpm1.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/drivers/serial/cpm_uart/cpm_uart_cpm1.c 2008-06-10 15:38:14.000000000 +0400 -@@ -52,6 +52,7 @@ void cpm_line_cr_cmd(int line, int cmd) - { - ushort val; - volatile cpm8xx_t *cp = cpmp; -+ unsigned *bcsr_io; - - switch (line) { - case UART_SMC1: -@@ -94,12 +95,35 @@ void scc1_lineif(struct uart_cpm_port *p - { - /* XXX SCC1: insert port configuration here */ - pinfo->brg = 1; -+ -+#if defined (CONFIG_MPC885ADS) || defined (CONFIG_MPC86XADS) -+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); -+ -+ if (bcsr_io == NULL) { -+ printk(KERN_CRIT "Could not remap BCSR\n"); -+ return; -+ } -+ out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_RS232EN_1); -+ iounmap(bcsr_io); -+#endif - } - - void scc2_lineif(struct uart_cpm_port *pinfo) - { - /* XXX SCC2: insert port configuration here */ - pinfo->brg = 2; -+ unsigned *bcsr_io; -+ -+#if defined (CONFIG_MPC885ADS) || defined (CONFIG_MPC86XADS) -+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); -+ -+ if (bcsr_io == NULL) { -+ printk(KERN_CRIT "Could not remap BCSR\n"); -+ return; -+ } -+ out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_RS232EN_2); -+ iounmap(bcsr_io); -+#endif - } - - void scc3_lineif(struct uart_cpm_port *pinfo) -@@ -188,6 +212,10 @@ int cpm_uart_init_portdesc(void) - { - pr_debug("CPM uart[-]:init portdesc\n"); - -+ /* Check if we have called this yet. This may happen if early kgdb -+ breakpoint is on */ -+ if(cpm_uart_nr) -+ return 0; - cpm_uart_nr = 0; - #ifdef CONFIG_SERIAL_CPM_SMC1 - cpm_uart_ports[UART_SMC1].smcp = &cpmp->cp_smc[0]; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/serial/cpm_uart/cpm_uart_cpm2.c linux-2.6.18-53.1.14.kgdb/drivers/serial/cpm_uart/cpm_uart_cpm2.c ---- linux-2.6.18-53.1.14/drivers/serial/cpm_uart/cpm_uart_cpm2.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/drivers/serial/cpm_uart/cpm_uart_cpm2.c 2008-06-10 15:38:14.000000000 +0400 -@@ -256,6 +256,10 @@ int cpm_uart_init_portdesc(void) - { - pr_debug("CPM uart[-]:init portdesc\n"); - -+ /* Check if we have called this yet. This may happen if early kgdb -+ breakpoint is on */ -+ if(cpm_uart_nr) -+ return 0; - cpm_uart_nr = 0; - #ifdef CONFIG_SERIAL_CPM_SMC1 - cpm_uart_ports[UART_SMC1].smcp = (smc_t *) & cpm2_immr->im_smc[0]; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/serial/cpm_uart/cpm_uart_kgdb.c linux-2.6.18-53.1.14.kgdb/drivers/serial/cpm_uart/cpm_uart_kgdb.c ---- linux-2.6.18-53.1.14/drivers/serial/cpm_uart/cpm_uart_kgdb.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/drivers/serial/cpm_uart/cpm_uart_kgdb.c 2008-06-10 15:38:14.000000000 +0400 -@@ -0,0 +1,195 @@ -+/* -+ * drivers/serial/cpm_uart/cpm_uart_kgdb.c -+ * -+ * CPM UART interface for kgdb. -+ * -+ * Author: Vitaly Bordug -+ * -+ * Used some bits from drivers/serial/kgdb_8250.c as a template -+ * -+ * 2005 (c) MontaVista Software, Inc. This file is licensed under -+ * the terms of the GNU General Public License version 2. This program -+ * is licensed "as is" without any warranty of any kind, whether express -+ * or implied. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include /* For BASE_BAUD and SERIAL_PORT_DFNS */ -+ -+#include "cpm_uart.h" -+ -+#define GDB_BUF_SIZE 512 /* power of 2, please */ -+ -+ -+static char kgdb_buf[GDB_BUF_SIZE], *kgdbp; -+static int kgdb_chars; -+ -+/* Forward declarations. */ -+ -+/* -+ * Receive character from the serial port. This only works well -+ * before the port is initialize for real use. -+ */ -+static int kgdb_wait_key(char *obuf) -+{ -+ struct uart_cpm_port *pinfo; -+ -+ u_char c, *cp; -+ volatile cbd_t *bdp; -+ int i; -+ -+ pinfo = &cpm_uart_ports[KGDB_PINFO_INDEX]; -+ -+ /* Get the address of the host memory buffer. -+ */ -+ bdp = pinfo->rx_cur; -+ while (bdp->cbd_sc & BD_SC_EMPTY); -+ -+ /* If the buffer address is in the CPM DPRAM, don't -+ * convert it. -+ */ -+ cp = cpm2cpu_addr(bdp->cbd_bufaddr); -+ -+ if (obuf) { -+ i = c = bdp->cbd_datlen; -+ while (i-- > 0) -+ { -+ *obuf++ = *cp++; -+ } -+ } else { -+ c = *cp; -+ } -+ bdp->cbd_sc |= BD_SC_EMPTY; -+ -+ if (bdp->cbd_sc & BD_SC_WRAP) { -+ bdp = pinfo->rx_bd_base; -+ } else { -+ bdp++; -+ } -+ pinfo->rx_cur = (cbd_t *)bdp; -+ -+ return((int)c); -+} -+ -+ -+/* -+ * Wait until the interface can accept a char, then write it. -+ */ -+static void -+kgdb_put_debug_char(int chr) -+{ -+ static char ch[2]; -+ ch[0]=(char)chr; -+ cpm_uart_early_write(KGDB_PINFO_INDEX, ch, 1); -+} -+ -+ -+/* -+ * Get a char if available, return -1 if nothing available. -+ * Empty the receive buffer first, then look at the interface hardware. -+ */ -+static int -+kgdb_get_debug_char(void) -+{ -+ if (kgdb_chars<=0) { -+ kgdb_chars = kgdb_wait_key(kgdb_buf); -+ kgdbp = kgdb_buf; -+ } -+ kgdb_chars--; -+ -+ return (*kgdbp++); -+} -+ -+static void termios_set_options(int index, -+ int baud, int parity, int bits, int flow) -+{ -+ struct termios termios; -+ struct uart_port *port; -+ struct uart_cpm_port *pinfo; -+ -+ BUG_ON(index>UART_NR); -+ -+ port = -+ (struct uart_port *)&cpm_uart_ports[index]; -+ pinfo = (struct uart_cpm_port *)port; -+ -+ /* -+ * Ensure that the serial console lock is initialised -+ * early. -+ */ -+ spin_lock_init(&port->lock); -+ -+ memset(&termios, 0, sizeof(struct termios)); -+ -+ termios.c_cflag = CREAD | HUPCL | CLOCAL; -+ -+ termios.c_cflag |= baud; -+ -+ if (bits == 7) -+ termios.c_cflag |= CS7; -+ else -+ termios.c_cflag |= CS8; -+ -+ switch (parity) { -+ case 'o': case 'O': -+ termios.c_cflag |= PARODD; -+ /*fall through*/ -+ case 'e': case 'E': -+ termios.c_cflag |= PARENB; -+ break; -+ } -+ -+ if (flow == 'r') -+ termios.c_cflag |= CRTSCTS; -+ -+ port->ops->set_termios(port, &termios, NULL); -+} -+ -+/* -+ * Returns: -+ * 0 on success, 1 on failure. -+ */ -+static int kgdb_init(void) -+{ -+ struct uart_port *port; -+ struct uart_cpm_port *pinfo; -+ -+ int use_bootmem = 0; /* use dma by default */ -+ -+ if(!cpm_uart_nr) -+ { -+ use_bootmem = 1; -+ cpm_uart_init_portdesc(); -+ } -+ port = (struct uart_port *)&cpm_uart_ports[KGDB_PINFO_INDEX]; -+ pinfo = (struct uart_cpm_port *)port; -+ -+ if (cpm_uart_early_setup(KGDB_PINFO_INDEX, use_bootmem)) -+ return 1; -+ -+ termios_set_options(KGDB_PINFO_INDEX, KGDB_BAUD,'n',8,'n'); -+ if (IS_SMC(pinfo)) -+ pinfo->smcp->smc_smcm |= SMCM_TX; -+ else -+ pinfo->sccp->scc_sccm |= UART_SCCM_TX; -+ -+ return 0; -+} -+ -+ -+struct kgdb_io kgdb_io_ops = { -+ .read_char = kgdb_get_debug_char, -+ .write_char = kgdb_put_debug_char, -+ .init = kgdb_init, -+}; -+ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/serial/mpsc.c linux-2.6.18-53.1.14.kgdb/drivers/serial/mpsc.c ---- linux-2.6.18-53.1.14/drivers/serial/mpsc.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/drivers/serial/mpsc.c 2008-06-10 15:38:14.000000000 +0400 -@@ -242,6 +242,11 @@ struct mpsc_port_info *mpsc_device_remov - #define MPSC_RCRR 0x0004 - #define MPSC_TCRR 0x0008 - -+/* MPSC Interrupt registers (offset from MV64x60_SDMA_INTR_OFFSET) */ -+#define MPSC_INTR_CAUSE 0x0004 -+#define MPSC_INTR_MASK 0x0084 -+#define MPSC_INTR_CAUSE_RCC (1<<6) -+ - /* Serial DMA Controller Interface Registers */ - #define SDMA_SDC 0x0000 - #define SDMA_SDCM 0x0008 -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/serial/mpsc_kgdb.c linux-2.6.18-53.1.14.kgdb/drivers/serial/mpsc_kgdb.c ---- linux-2.6.18-53.1.14/drivers/serial/mpsc_kgdb.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/drivers/serial/mpsc_kgdb.c 2008-06-10 15:38:14.000000000 +0400 -@@ -0,0 +1,299 @@ -+/* -+ * drivers/serial/mpsc_kgdb.c -+ * -+ * KGDB driver for the Marvell MultiProtocol Serial Controller (MPCS) -+ * -+ * Based on the polled boot loader driver by Ajit Prem (ajit.prem@motorola.com) -+ * -+ * Author: Randy Vinson -+ * -+ * 2005 (c) MontaVista Software, Inc. -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "mpsc.h" -+ -+/* Speed of the UART. */ -+static int kgdbmpsc_baud = CONFIG_KGDB_BAUDRATE; -+ -+/* Index of the UART, matches ttyMX naming. */ -+static int kgdbmpsc_ttyMM = CONFIG_KGDB_PORT_NUM; -+ -+#define MPSC_INTR_REG_SELECT(x) ((x) + (8 * kgdbmpsc_ttyMM)) -+ -+static int kgdbmpsc_init(void); -+ -+static struct platform_device mpsc_dev, shared_dev; -+ -+static void __iomem *mpsc_base; -+static void __iomem *brg_base; -+static void __iomem *routing_base; -+static void __iomem *sdma_base; -+ -+static unsigned int mpsc_irq; -+ -+static void kgdb_write_debug_char(int c) -+{ -+ u32 data; -+ -+ data = readl(mpsc_base + MPSC_MPCR); -+ writeb(c, mpsc_base + MPSC_CHR_1); -+ mb(); -+ data = readl(mpsc_base + MPSC_CHR_2); -+ data |= MPSC_CHR_2_TTCS; -+ writel(data, mpsc_base + MPSC_CHR_2); -+ mb(); -+ -+ while (readl(mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_TTCS) ; -+} -+ -+static int kgdb_get_debug_char(void) -+{ -+ unsigned char c; -+ -+ while (!(readl(sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_CAUSE)) & -+ MPSC_INTR_CAUSE_RCC)) ; -+ -+ c = readb(mpsc_base + MPSC_CHR_10 + (1 << 1)); -+ mb(); -+ writeb(c, mpsc_base + MPSC_CHR_10 + (1 << 1)); -+ mb(); -+ writel(~MPSC_INTR_CAUSE_RCC, sdma_base + -+ MPSC_INTR_REG_SELECT(MPSC_INTR_CAUSE)); -+ return (c); -+} -+ -+/* -+ * This is the receiver interrupt routine for the GDB stub. -+ * All that we need to do is verify that the interrupt happened on the -+ * line we're in charge of. If this is true, schedule a breakpoint and -+ * return. -+ */ -+static irqreturn_t -+kgdbmpsc_interrupt(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ if (irq != mpsc_irq) -+ return IRQ_NONE; -+ /* -+ * If there is some other CPU in KGDB then this is a -+ * spurious interrupt. so return without even checking a byte -+ */ -+ if (atomic_read(&debugger_active)) -+ return IRQ_NONE; -+ -+ if (readl(sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_CAUSE)) & -+ MPSC_INTR_CAUSE_RCC) -+ breakpoint(); -+ -+ return IRQ_HANDLED; -+} -+ -+static int __init kgdbmpsc_init(void) -+{ -+ struct mpsc_pdata *pdata; -+ u32 cdv; -+ -+ if (!brg_base || !mpsc_base || !routing_base || !sdma_base) -+ return -1; -+ -+ /* Set MPSC Routing to enable both ports */ -+ writel(0x0, routing_base + MPSC_MRR); -+ -+ /* MPSC 0/1 Rx & Tx get clocks BRG0/1 */ -+ writel(0x00000100, routing_base + MPSC_RCRR); -+ writel(0x00000100, routing_base + MPSC_TCRR); -+ -+ /* Disable all MPSC interrupts and clear any pending interrupts */ -+ writel(0, sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_MASK)); -+ writel(0, sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_CAUSE)); -+ -+ pdata = (struct mpsc_pdata *)mpsc_dev.dev.platform_data; -+ -+ /* cdv = (clock/(2*16*baud rate)) for 16X mode. */ -+ cdv = ((pdata->brg_clk_freq / (32 * kgdbmpsc_baud)) - 1); -+ writel((pdata->brg_clk_src << 18) | (1 << 16) | cdv, -+ brg_base + BRG_BCR); -+ -+ /* Put MPSC into UART mode, no null modem, 16x clock mode */ -+ writel(0x000004c4, mpsc_base + MPSC_MMCRL); -+ writel(0x04400400, mpsc_base + MPSC_MMCRH); -+ -+ writel(0, mpsc_base + MPSC_CHR_1); -+ writel(0, mpsc_base + MPSC_CHR_9); -+ writel(0, mpsc_base + MPSC_CHR_10); -+ writel(4, mpsc_base + MPSC_CHR_3); -+ writel(0x20000000, mpsc_base + MPSC_CHR_4); -+ writel(0x9000, mpsc_base + MPSC_CHR_5); -+ writel(0, mpsc_base + MPSC_CHR_6); -+ writel(0, mpsc_base + MPSC_CHR_7); -+ writel(0, mpsc_base + MPSC_CHR_8); -+ -+ /* 8 data bits, 1 stop bit */ -+ writel((3 << 12), mpsc_base + MPSC_MPCR); -+ -+ /* Enter "hunt" mode */ -+ writel((1 << 31), mpsc_base + MPSC_CHR_2); -+ -+ udelay(100); -+ return 0; -+} -+ -+static void __iomem *__init -+kgdbmpsc_map_resource(struct platform_device *pd, int type, int num) -+{ -+ void __iomem *base = NULL; -+ struct resource *r; -+ -+ if ((r = platform_get_resource(pd, IORESOURCE_MEM, num))) -+ base = ioremap(r->start, r->end - r->start + 1); -+ return base; -+} -+ -+static void __iomem *__init -+kgdbmpsc_unmap_resource(struct platform_device *pd, int type, int num, -+ void __iomem * base) -+{ -+ if (base) -+ iounmap(base); -+ return NULL; -+} -+ -+static void __init -+kgdbmpsc_reserve_resource(struct platform_device *pd, int type, int num) -+{ -+ struct resource *r; -+ -+ if ((r = platform_get_resource(pd, IORESOURCE_MEM, num))) -+ request_mem_region(r->start, r->end - r->start + 1, "kgdb"); -+} -+ -+static int __init kgdbmpsc_local_init(void) -+{ -+ if (!mpsc_dev.num_resources || !shared_dev.num_resources) -+ return 1; /* failure */ -+ -+ mpsc_base = kgdbmpsc_map_resource(&mpsc_dev, IORESOURCE_MEM, -+ MPSC_BASE_ORDER); -+ brg_base = kgdbmpsc_map_resource(&mpsc_dev, IORESOURCE_MEM, -+ MPSC_BRG_BASE_ORDER); -+ -+ /* get the platform data for the shared registers and get them mapped */ -+ routing_base = kgdbmpsc_map_resource(&shared_dev, -+ IORESOURCE_MEM, -+ MPSC_ROUTING_BASE_ORDER); -+ sdma_base = -+ kgdbmpsc_map_resource(&shared_dev, IORESOURCE_MEM, -+ MPSC_SDMA_INTR_BASE_ORDER); -+ -+ mpsc_irq = platform_get_irq(&mpsc_dev, 1); -+ -+ if (mpsc_base && brg_base && routing_base && sdma_base) -+ return 0; /* success */ -+ -+ return 1; /* failure */ -+} -+ -+static void __init kgdbmpsc_local_exit(void) -+{ -+ if (sdma_base) -+ sdma_base = kgdbmpsc_unmap_resource(&shared_dev, IORESOURCE_MEM, -+ MPSC_SDMA_INTR_BASE_ORDER, -+ sdma_base); -+ if (routing_base) -+ routing_base = kgdbmpsc_unmap_resource(&shared_dev, -+ IORESOURCE_MEM, -+ MPSC_ROUTING_BASE_ORDER, -+ routing_base); -+ if (brg_base) -+ brg_base = kgdbmpsc_unmap_resource(&mpsc_dev, IORESOURCE_MEM, -+ MPSC_BRG_BASE_ORDER, -+ brg_base); -+ if (mpsc_base) -+ mpsc_base = kgdbmpsc_unmap_resource(&mpsc_dev, IORESOURCE_MEM, -+ MPSC_BASE_ORDER, mpsc_base); -+} -+ -+static void __init kgdbmpsc_update_pdata(struct platform_device *pdev) -+{ -+ -+ snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s%u", pdev->name, pdev->id); -+} -+ -+static int __init kgdbmpsc_pdev_init(void) -+{ -+ struct platform_device *pdev; -+ -+ /* get the platform data for the specified port. */ -+ pdev = mv64x60_early_get_pdev_data(MPSC_CTLR_NAME, kgdbmpsc_ttyMM, 1); -+ if (pdev) { -+ memcpy(&mpsc_dev, pdev, sizeof(struct platform_device)); -+ if (platform_notify) { -+ kgdbmpsc_update_pdata(&mpsc_dev); -+ platform_notify(&mpsc_dev.dev); -+ } -+ -+ /* get the platform data for the shared registers. */ -+ pdev = mv64x60_early_get_pdev_data(MPSC_SHARED_NAME, 0, 0); -+ if (pdev) { -+ memcpy(&shared_dev, pdev, -+ sizeof(struct platform_device)); -+ if (platform_notify) { -+ kgdbmpsc_update_pdata(&shared_dev); -+ platform_notify(&shared_dev.dev); -+ } -+ } -+ } -+ return 0; -+} -+ -+postcore_initcall(kgdbmpsc_pdev_init); -+ -+static int __init kgdbmpsc_init_io(void) -+{ -+ -+ kgdbmpsc_pdev_init(); -+ -+ if (kgdbmpsc_local_init()) { -+ kgdbmpsc_local_exit(); -+ return -1; -+ } -+ -+ if (kgdbmpsc_init() == -1) -+ return -1; -+ return 0; -+} -+ -+static void __init kgdbmpsc_hookup_irq(void) -+{ -+ unsigned int msk; -+ if (!request_irq(mpsc_irq, kgdbmpsc_interrupt, 0, "kgdb mpsc", NULL)) { -+ /* Enable interrupt */ -+ msk = readl(sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_MASK)); -+ msk |= MPSC_INTR_CAUSE_RCC; -+ writel(msk, sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_MASK)); -+ -+ kgdbmpsc_reserve_resource(&mpsc_dev, IORESOURCE_MEM, -+ MPSC_BASE_ORDER); -+ kgdbmpsc_reserve_resource(&mpsc_dev, IORESOURCE_MEM, -+ MPSC_BRG_BASE_ORDER); -+ } -+} -+ -+struct kgdb_io kgdb_io_ops = { -+ .read_char = kgdb_get_debug_char, -+ .write_char = kgdb_write_debug_char, -+ .init = kgdbmpsc_init_io, -+ .late_init = kgdbmpsc_hookup_irq, -+}; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/serial/pxa.c linux-2.6.18-53.1.14.kgdb/drivers/serial/pxa.c ---- linux-2.6.18-53.1.14/drivers/serial/pxa.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/drivers/serial/pxa.c 2008-06-10 15:38:56.000000000 +0400 -@@ -42,6 +42,9 @@ - #include - #include - #include -+#ifdef CONFIG_KGDB_CONSOLE -+#include -+#endif - - #include - #include -@@ -692,6 +695,8 @@ serial_pxa_console_init(void) - console_initcall(serial_pxa_console_init); - - #define PXA_CONSOLE &serial_pxa_console -+#elif defined(CONFIG_KGDB_CONSOLE) -+#define PXA_CONSOLE &kgdbcons - #else - #define PXA_CONSOLE NULL - #endif -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/serial/serial_core.c linux-2.6.18-53.1.14.kgdb/drivers/serial/serial_core.c ---- linux-2.6.18-53.1.14/drivers/serial/serial_core.c 2008-03-06 05:54:07.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/drivers/serial/serial_core.c 2008-06-10 15:37:43.000000000 +0400 -@@ -33,6 +33,7 @@ - #include /* for serial_state and serial_icounter_struct */ - #include - #include -+#include - - #include - #include -@@ -65,6 +66,12 @@ static struct lock_class_key port_lock_k - #define uart_console(port) (0) - #endif - -+#ifdef CONFIG_KGDB_CONSOLE -+#define uart_kgdb(port) (port->cons && !strcmp(port->cons->name, "kgdb")) -+#else -+#define uart_kgdb(port) (0) -+#endif -+ - static void uart_change_speed(struct uart_state *state, struct termios *old_termios); - static void uart_wait_until_sent(struct tty_struct *tty, int timeout); - static void uart_change_pm(struct uart_state *state, int pm_state); -@@ -1673,6 +1680,9 @@ static int uart_line_info(char *buf, str - port->iotype == UPIO_MEM ? port->mapbase : - (unsigned long) port->iobase, - port->irq); -+ if (port->iotype == UPIO_MEM) -+ ret += sprintf(buf+ret, " membase 0x%08lX", -+ (unsigned long) port->membase); - - if (port->type == PORT_UNKNOWN) { - strcat(buf, "\n"); -@@ -2043,7 +2053,8 @@ uart_report_port(struct uart_driver *drv - case UPIO_AU: - case UPIO_TSI: - snprintf(address, sizeof(address), -- "MMIO 0x%lx", port->mapbase); -+ "MMIO map 0x%lx mem 0x%lx", port->mapbase, -+ (unsigned long) port->membase); - break; - default: - strlcpy(address, "*unknown*", sizeof(address)); -@@ -2095,9 +2106,9 @@ uart_configure_port(struct uart_driver * - - /* - * Power down all ports by default, except the -- * console if we have one. -+ * console (real or kgdb) if we have one. - */ -- if (!uart_console(port)) -+ if (!uart_console(port) && !uart_kgdb(port)) - uart_change_pm(state, 3); - } - } -@@ -2289,6 +2300,12 @@ int uart_add_one_port(struct uart_driver - */ - port->flags &= ~UPF_DEAD; - -+#if defined(CONFIG_KGDB_8250) -+ /* Add any 8250-like ports we find later. */ -+ if (port->type <= PORT_MAX_8250) -+ kgdb8250_add_port(port->line, port); -+#endif -+ - out: - mutex_unlock(&state->mutex); - mutex_unlock(&port_mutex); -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/serial/serial_txx9.c linux-2.6.18-53.1.14.kgdb/drivers/serial/serial_txx9.c ---- linux-2.6.18-53.1.14/drivers/serial/serial_txx9.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/drivers/serial/serial_txx9.c 2008-06-10 15:38:24.000000000 +0400 -@@ -1164,6 +1164,96 @@ static struct pci_driver serial_txx9_pci - MODULE_DEVICE_TABLE(pci, serial_txx9_pci_tbl); - #endif /* ENABLE_SERIAL_TXX9_PCI */ - -+/******************************************************************************/ -+/* BEG: KDBG Routines */ -+/******************************************************************************/ -+ -+#ifdef CONFIG_KGDB -+int kgdb_init_count = 0; -+ -+void txx9_sio_kgdb_hook(unsigned int port, unsigned int baud_rate) -+{ -+ static struct resource kgdb_resource; -+ int ret; -+ struct uart_txx9_port *up = &serial_txx9_ports[port]; -+ -+ /* prevent initialization by driver */ -+ kgdb_resource.name = "serial_txx9(debug)"; -+ kgdb_resource.start = (unsigned long)up->port.membase; -+ kgdb_resource.end = (unsigned long)(up->port.membase + 36 - 1); -+ kgdb_resource.flags = IORESOURCE_MEM | IORESOURCE_BUSY; -+ -+ ret = request_resource(&iomem_resource, &kgdb_resource); -+ if(ret == -EBUSY) -+ printk(" serial_txx9(debug): request_resource failed\n"); -+ -+ return; -+} -+void -+txx9_sio_kdbg_init( unsigned int port_number ) -+{ -+ if (port_number == 1) { -+ txx9_sio_kgdb_hook(port_number, 38400); -+ } else { -+ printk("Bad Port Number [%u] != [1]\n",port_number); -+ } -+ return; -+} -+ -+u8 -+txx9_sio_kdbg_rd( void ) -+{ -+ unsigned int status,ch; -+ struct uart_txx9_port *up = &serial_txx9_ports[1]; -+ -+ if (kgdb_init_count == 0) { -+ txx9_sio_kdbg_init(1); -+ kgdb_init_count = 1; -+ } -+ -+ while (1) { -+ status = sio_in(up, TXX9_SIDISR); -+ if ( status & 0x1f ) { -+ ch = sio_in(up, TXX9_SIRFIFO ); -+ break; -+ } -+ } -+ -+ return (ch); -+} -+ -+int -+txx9_sio_kdbg_wr( u8 ch ) -+{ -+ unsigned int status; -+ struct uart_txx9_port *up = &serial_txx9_ports[1]; -+ -+ if (kgdb_init_count == 0) { -+ txx9_sio_kdbg_init(1); -+ kgdb_init_count = 1; -+ } -+ -+ while (1) { -+ status = sio_in(up, TXX9_SICISR); -+ if (status & TXX9_SICISR_TRDY) { -+ if ( ch == '\n' ) { -+ txx9_sio_kdbg_wr( '\r' ); -+ } -+ sio_out(up, TXX9_SITFIFO, (u32)ch ); -+ -+ break; -+ } -+ } -+ -+ return (1); -+} -+#endif /* CONFIG_KGDB */ -+ -+ -+/******************************************************************************/ -+/* END: KDBG Routines */ -+/******************************************************************************/ -+ - static int __init serial_txx9_init(void) - { - int ret; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/drivers/serial/sh-sci.c linux-2.6.18-53.1.14.kgdb/drivers/serial/sh-sci.c ---- linux-2.6.18-53.1.14/drivers/serial/sh-sci.c 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/drivers/serial/sh-sci.c 2008-06-10 15:38:50.000000000 +0400 -@@ -42,6 +42,7 @@ - #include - #include - #include -+#include - - #ifdef CONFIG_CPU_FREQ - #include -@@ -67,14 +68,16 @@ - - #include "sh-sci.h" - --#ifdef CONFIG_SH_KGDB --#include -- --static int kgdb_get_char(struct sci_port *port); --static void kgdb_put_char(struct sci_port *port, char c); --static void kgdb_handle_error(struct sci_port *port); --static struct sci_port *kgdb_sci_port; --#endif /* CONFIG_SH_KGDB */ -+#ifdef CONFIG_KGDB_SH_SCI -+/* Speed of the UART. */ -+static int kgdbsci_baud = CONFIG_KGDB_BAUDRATE -+ -+/* Index of the UART, matches ttySCX naming. */ -+static int kgdbsci_ttySC = CONFIG_KGDB_PORT_NUM; -+ -+/* Make life easier on us. */ -+#define KGDBPORT sci_ports[kgdbsci_ttySC] -+#endif /* CONFIG_KGDB_SH_SCI */ - - #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE - static struct sci_port *serial_console_port = 0; -@@ -87,20 +90,17 @@ static void sci_start_rx(struct uart_por - static void sci_stop_rx(struct uart_port *port); - static int sci_request_irq(struct sci_port *port); - static void sci_free_irq(struct sci_port *port); -+static void sci_set_termios(struct uart_port *port, struct termios *termios, -+ struct termios *old); -+static int kgdbsci_init(void); - - static struct sci_port sci_ports[]; - static struct uart_driver sci_uart_driver; - - #define SCI_NPORTS sci_uart_driver.nr - --#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) -- --static void handle_error(struct uart_port *port) --{ /* Clear error flags */ -- sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); --} -- --static int get_char(struct uart_port *port) -+#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_KGDB_SH_SCI) -+static int get_char_for_gdb(struct uart_port *port) - { - unsigned long flags; - unsigned short status; -@@ -110,7 +110,8 @@ static int get_char(struct uart_port *po - do { - status = sci_in(port, SCxSR); - if (status & SCxSR_ERRORS(port)) { -- handle_error(port); -+ /* Clear error flags. */ -+ sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); - continue; - } - } while (!(status & SCxSR_RDxF(port))); -@@ -121,21 +122,7 @@ static int get_char(struct uart_port *po - - return c; - } -- --/* Taken from sh-stub.c of GDB 4.18 */ --static const char hexchars[] = "0123456789abcdef"; -- --static __inline__ char highhex(int x) --{ -- return hexchars[(x >> 4) & 0xf]; --} -- --static __inline__ char lowhex(int x) --{ -- return hexchars[x & 0xf]; --} -- --#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ -+#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_KGDB_SH_SCI */ - - /* - * Send the packet in buffer. The host gets one chance to read it. -@@ -167,21 +154,14 @@ static void put_string(struct sci_port * - const unsigned char *p = buffer; - int i; - --#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) -+#ifdef CONFIG_SH_STANDARD_BIOS - int checksum; -- int usegdb=0; -+ const char hexchars[] = "0123456789abcdef"; - --#ifdef CONFIG_SH_STANDARD_BIOS - /* This call only does a trap the first time it is - * called, and so is safe to do here unconditionally - */ -- usegdb |= sh_bios_in_gdb_mode(); --#endif --#ifdef CONFIG_SH_KGDB -- usegdb |= (kgdb_in_gdb_mode && (port == kgdb_sci_port)); --#endif -- -- if (usegdb) { -+ if (sh_bios_in_gdb_mode()) { - /* $#. */ - do { - unsigned char c; -@@ -193,18 +173,18 @@ static void put_string(struct sci_port * - int h, l; - - c = *p++; -- h = highhex(c); -- l = lowhex(c); -+ h = hexchars[c >> 4]; -+ l = hexchars[c % 16]; - put_char(port, h); - put_char(port, l); - checksum += h + l; - } - put_char(port, '#'); -- put_char(port, highhex(checksum)); -- put_char(port, lowhex(checksum)); -+ put_char(port, hexchars[checksum >> 4]); -+ put_char(port, hexchars[checksum % 16]); - } while (get_char(port) != '+'); - } else --#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ -+#endif /* CONFIG_SH_STANDARD_BIOS */ - for (i=0; i SCI_NPORTS + '0') -+ goto errout; -+ kgdbsci_ttySC = *str - '0'; -+ str++; -+ if (*str != ',') -+ goto errout; -+ str++; -+ kgdbsci_baud = simple_strtoul(str, &str, 10); -+ if (kgdbsci_baud != 9600 && kgdbsci_baud != 19200 && -+ kgdbsci_baud != 38400 && kgdbsci_baud != 57600 && -+ kgdbsci_baud != 115200) -+ goto errout; -+ -+ return 0; -+ -+errout: -+ printk(KERN_ERR "Invalid syntax for option kgdbsci=\n"); -+ return 1; -+} -+__setup("kgdbsci", kgdbsci_opt); -+#endif /* CONFIG_KGDB_SH_SCI */ - - #if defined(__H8300S__) - enum { sci_disable, sci_enable }; -@@ -555,6 +608,16 @@ static inline void sci_receive_chars(str - continue; - } - -+#ifdef CONFIG_KGDB_SH_SCI -+ /* We assume that a ^C on the port KGDB -+ * is using means that KGDB wants to -+ * interrupt the running system. -+ */ -+ if (port->line == KGDBPORT.port.line && -+ c == 3) -+ breakpoint(); -+#endif -+ - /* Store data and status */ - if (status&SCxSR_FER(port)) { - flag = TTY_FRAME; -@@ -1618,6 +1681,7 @@ static int __init sci_console_init(void) - console_initcall(sci_console_init); - #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */ - -+#if 0 - #ifdef CONFIG_SH_KGDB - /* - * FIXME: Most of this can go away.. at the moment, we rely on -@@ -1663,30 +1727,9 @@ int __init kgdb_console_setup(struct con - return uart_set_options(port, co, baud, parity, bits, flow); - } - #endif /* CONFIG_SH_KGDB */ -+#endif /* 0 */ - --#ifdef CONFIG_SH_KGDB_CONSOLE --static struct console kgdb_console = { -- .name = "ttySC", -- .write = kgdb_console_write, -- .setup = kgdb_console_setup, -- .flags = CON_PRINTBUFFER | CON_ENABLED, -- .index = -1, -- .data = &sci_uart_driver, --}; -- --/* Register the KGDB console so we get messages (d'oh!) */ --static int __init kgdb_console_init(void) --{ -- register_console(&kgdb_console); -- return 0; --} -- --console_initcall(kgdb_console_init); --#endif /* CONFIG_SH_KGDB_CONSOLE */ -- --#if defined(CONFIG_SH_KGDB_CONSOLE) --#define SCI_CONSOLE &kgdb_console --#elif defined(CONFIG_SERIAL_SH_SCI_CONSOLE) -+#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE - #define SCI_CONSOLE &serial_console - #else - #define SCI_CONSOLE 0 -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-arm/kgdb.h linux-2.6.18-53.1.14.kgdb/include/asm-arm/kgdb.h ---- linux-2.6.18-53.1.14/include/asm-arm/kgdb.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-arm/kgdb.h 2008-06-10 15:39:01.000000000 +0400 -@@ -0,0 +1,92 @@ -+/* -+ * include/asm-arm/kgdb.h -+ * -+ * ARM KGDB support -+ * -+ * Author: Deepak Saxena -+ * -+ * Copyright (C) 2002 MontaVista Software Inc. -+ * -+ */ -+ -+#ifndef __ASM_KGDB_H__ -+#define __ASM_KGDB_H__ -+ -+#include -+#include -+#include -+ -+ -+/* -+ * GDB assumes that we're a user process being debugged, so -+ * it will send us an SWI command to write into memory as the -+ * debug trap. When an SWI occurs, the next instruction addr is -+ * placed into R14_svc before jumping to the vector trap. -+ * This doesn't work for kernel debugging as we are already in SVC -+ * we would loose the kernel's LR, which is a bad thing. This -+ * is bad thing. -+ * -+ * By doing this as an undefined instruction trap, we force a mode -+ * switch from SVC to UND mode, allowing us to save full kernel state. -+ * -+ * We also define a KGDB_COMPILED_BREAK which can be used to compile -+ * in breakpoints. This is important for things like sysrq-G and for -+ * the initial breakpoint from trap_init(). -+ * -+ * Note to ARM HW designers: Add real trap support like SH && PPC to -+ * make our lives much much simpler. :) -+ */ -+#define BREAK_INSTR_SIZE 4 -+#define GDB_BREAKINST 0xef9f0001 -+#define KGDB_BREAKINST 0xe7ffdefe -+#define KGDB_COMPILED_BREAK 0xe7ffdeff -+#define CACHE_FLUSH_IS_SAFE 1 -+ -+#ifndef __ASSEMBLY__ -+ -+#define BREAKPOINT() asm(".word 0xe7ffdeff") -+ -+ -+extern void kgdb_handle_bus_error(void); -+extern int kgdb_fault_expected; -+#endif /* !__ASSEMBLY__ */ -+ -+/* -+ * From Amit S. Kale: -+ * -+ * In the register packet, words 0-15 are R0 to R10, FP, IP, SP, LR, PC. But -+ * Register 16 isn't cpsr. GDB passes CPSR in word 25. There are 9 words in -+ * between which are unused. Passing only 26 words to gdb is sufficient. -+ * GDB can figure out that floating point registers are not passed. -+ * GDB_MAX_REGS should be 26. -+ */ -+#define GDB_MAX_REGS (26) -+ -+#define KGDB_MAX_NO_CPUS 1 -+#define BUFMAX 400 -+#define NUMREGBYTES (GDB_MAX_REGS << 2) -+#define NUMCRITREGBYTES (32 << 2) -+ -+#define _R0 0 -+#define _R1 1 -+#define _R2 2 -+#define _R3 3 -+#define _R4 4 -+#define _R5 5 -+#define _R6 6 -+#define _R7 7 -+#define _R8 8 -+#define _R9 9 -+#define _R10 10 -+#define _FP 11 -+#define _IP 12 -+#define _SP 13 -+#define _LR 14 -+#define _PC 15 -+#define _CPSR (GDB_MAX_REGS - 1) -+ -+/* So that we can denote the end of a frame for tracing, in the simple -+ * case. */ -+#define CFI_END_FRAME(func) __CFI_END_FRAME(_PC,_SP,func) -+ -+#endif /* __ASM_KGDB_H__ */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-arm/system.h linux-2.6.18-53.1.14.kgdb/include/asm-arm/system.h ---- linux-2.6.18-53.1.14/include/asm-arm/system.h 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-arm/system.h 2008-06-10 15:38:56.000000000 +0400 -@@ -444,6 +444,47 @@ static inline unsigned long __xchg(unsig - extern void disable_hlt(void); - extern void enable_hlt(void); - -+#define __HAVE_ARCH_CMPXCHG 1 -+ -+#include -+ -+static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old, -+ unsigned long new) -+{ -+ u32 retval; -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ retval = *m; -+ if (retval == old) -+ *m = new; -+ local_irq_restore(flags); /* implies memory barrier */ -+ -+ return retval; -+} -+ -+/* This function doesn't exist, so you'll get a linker error -+ if something tries to do an invalid cmpxchg(). */ -+extern void __cmpxchg_called_with_bad_pointer(void); -+ -+static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old, -+ unsigned long new, int size) -+{ -+ switch (size) { -+ case 4: -+ return __cmpxchg_u32(ptr, old, new); -+ } -+ __cmpxchg_called_with_bad_pointer(); -+ return old; -+} -+ -+#define cmpxchg(ptr,o,n) \ -+ ({ \ -+ __typeof__(*(ptr)) _o_ = (o); \ -+ __typeof__(*(ptr)) _n_ = (n); \ -+ (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ -+ (unsigned long)_n_, sizeof(*(ptr))); \ -+ }) - #endif /* __ASSEMBLY__ */ - - #define arch_align_stack(x) (x) -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-generic/kgdb.h linux-2.6.18-53.1.14.kgdb/include/asm-generic/kgdb.h ---- linux-2.6.18-53.1.14/include/asm-generic/kgdb.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-generic/kgdb.h 2008-06-10 15:39:01.000000000 +0400 -@@ -0,0 +1,34 @@ -+/* -+ * include/asm-generic/kgdb.h -+ * -+ * This provides the assembly level information so that KGDB can provide -+ * a GDB that has been patched with enough information to know to stop -+ * trying to unwind the function. -+ * -+ * Author: Tom Rini -+ * -+ * 2005 (c) MontaVista Software, Inc. This file is licensed under the terms -+ * of the GNU General Public License version 2. This program is licensed -+ * "as is" without any warranty of any kind, whether express or implied. -+ */ -+ -+#ifndef __ASM_GENERIC_KGDB_H__ -+#define __ASM_GENERIC_KGDB_H__ -+ -+#include -+#ifdef __ASSEMBLY__ -+#ifdef CONFIG_KGDB -+/* This MUST be put at the end of a given assembly function */ -+#define __CFI_END_FRAME(pc,sp,func) \ -+CAT3(.Lend_,func,:) \ -+ CFI_preamble(func,pc,0x1,-DATA_ALIGN_FACTOR) \ -+ CFA_define_reference(sp, 0) \ -+ CFA_undefine_reg(pc) \ -+ CFI_postamble() \ -+ FDE_preamble(func,func,CAT3(.Lend,_,func)) \ -+ FDE_postamble() -+#else -+#define __CFI_END_FRAME(pc,sp,fn) -+#endif /* CONFIG_KGDB */ -+#endif /* __ASSEMBLY__ */ -+#endif /* __ASM_GENERIC_KGDB_H__ */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-i386/kdebug.h linux-2.6.18-53.1.14.kgdb/include/asm-i386/kdebug.h ---- linux-2.6.18-53.1.14/include/asm-i386/kdebug.h 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-i386/kdebug.h 2008-06-10 15:38:03.000000000 +0400 -@@ -39,6 +39,7 @@ enum die_val { - DIE_CALL, - DIE_NMI_IPI, - DIE_PAGE_FAULT, -+ DIE_PAGE_FAULT_NO_CONTEXT, - }; - - static inline int notify_die(enum die_val val, const char *str, -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-i386/kgdb.h linux-2.6.18-53.1.14.kgdb/include/asm-i386/kgdb.h ---- linux-2.6.18-53.1.14/include/asm-i386/kgdb.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-i386/kgdb.h 2008-06-10 15:39:01.000000000 +0400 -@@ -0,0 +1,58 @@ -+#ifdef __KERNEL__ -+#ifndef _ASM_KGDB_H_ -+#define _ASM_KGDB_H_ -+ -+/* -+ * Copyright (C) 2001-2004 Amit S. Kale -+ */ -+ -+#include -+ -+/* -+ * Note that this register image is in a different order than -+ * the register image that Linux produces at interrupt time. -+ * -+ * Linux's register image is defined by struct pt_regs in ptrace.h. -+ * Just why GDB uses a different order is a historical mystery. -+ */ -+#define _EAX 0 -+#define _ECX 1 -+#define _EDX 2 -+#define _EBX 3 -+#define _ESP 4 -+#define _EBP 5 -+#define _ESI 6 -+#define _EDI 7 -+#define _PC 8 -+#define _EIP 8 -+#define _PS 9 -+#define _EFLAGS 9 -+#define _CS 10 -+#define _SS 11 -+#define _DS 12 -+#define _ES 13 -+#define _FS 14 -+#define _GS 15 -+ -+/* So that we can denote the end of a frame for tracing, in the simple -+ * case. */ -+#define CFI_END_FRAME(func) __CFI_END_FRAME(_EIP,_ESP,func) -+ -+#ifndef __ASSEMBLY__ -+/************************************************************************/ -+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ -+/* at least NUMREGBYTES*2 are needed for register packets */ -+/* Longer buffer is needed to list all threads */ -+#define BUFMAX 1024 -+ -+/* Number of bytes of registers. */ -+#define NUMREGBYTES 64 -+/* Number of bytes of registers we need to save for a setjmp/longjmp. */ -+#define NUMCRITREGBYTES 24 -+ -+#define BREAKPOINT() asm(" int $3"); -+#define BREAK_INSTR_SIZE 1 -+#define CACHE_FLUSH_IS_SAFE 1 -+#endif /* !__ASSEMBLY__ */ -+#endif /* _ASM_KGDB_H_ */ -+#endif /* __KERNEL__ */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-ia64/kdebug.h linux-2.6.18-53.1.14.kgdb/include/asm-ia64/kdebug.h ---- linux-2.6.18-53.1.14/include/asm-ia64/kdebug.h 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-ia64/kdebug.h 2008-06-10 15:38:32.000000000 +0400 -@@ -72,6 +72,7 @@ enum die_val { - DIE_KDEBUG_LEAVE, - DIE_KDUMP_ENTER, - DIE_KDUMP_LEAVE, -+ DIE_PAGE_FAULT_NO_CONTEXT, - }; - - static inline int notify_die(enum die_val val, char *str, struct pt_regs *regs, -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-ia64/kgdb.h linux-2.6.18-53.1.14.kgdb/include/asm-ia64/kgdb.h ---- linux-2.6.18-53.1.14/include/asm-ia64/kgdb.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-ia64/kgdb.h 2008-06-10 15:38:32.000000000 +0400 -@@ -0,0 +1,36 @@ -+#ifdef __KERNEL__ -+#ifndef _ASM_KGDB_H_ -+#define _ASM_KGDB_H_ -+ -+/* -+ * Copyright (C) 2001-2004 Amit S. Kale -+ */ -+ -+#include -+ -+/************************************************************************/ -+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ -+/* at least NUMREGBYTES*2 are needed for register packets */ -+/* Longer buffer is needed to list all threads */ -+#define BUFMAX 1024 -+ -+/* Number of bytes of registers. We set this to 0 so that certain GDB -+ * packets will fail, forcing the use of others, which are more friendly -+ * on ia64. */ -+#define NUMREGBYTES 0 -+ -+#define NUMCRITREGBYTES (70*8) -+#define JMP_REGS_ALIGNMENT __attribute__ ((aligned (16))) -+ -+#define BREAKNUM 0x00003333300LL -+#define KGDBBREAKNUM 0x6665UL -+#define BREAKPOINT() asm volatile ("break.m 0x6665") -+#define BREAK_INSTR_SIZE 16 -+#define CACHE_FLUSH_IS_SAFE 1 -+ -+struct pt_regs; -+extern volatile int kgdb_hwbreak_sstep[NR_CPUS]; -+extern void smp_send_nmi_allbutself(void); -+extern void kgdb_wait_ipi(struct pt_regs *); -+#endif /* _ASM_KGDB_H_ */ -+#endif /* __KERNEL__ */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-mips/kdebug.h linux-2.6.18-53.1.14.kgdb/include/asm-mips/kdebug.h ---- linux-2.6.18-53.1.14/include/asm-mips/kdebug.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-mips/kdebug.h 2008-06-10 15:38:24.000000000 +0400 -@@ -0,0 +1,47 @@ -+/* -+ * -+ * Copyright (C) 2004 MontaVista Software Inc. -+ * Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ */ -+#ifndef _MIPS_KDEBUG_H -+#define _MIPS_KDEBUG_H -+ -+#include -+ -+struct pt_regs; -+ -+struct die_args { -+ struct pt_regs *regs; -+ const char *str; -+ long err; -+}; -+ -+int register_die_notifier(struct notifier_block *nb); -+extern struct notifier_block *mips_die_chain; -+ -+enum die_val { -+ DIE_OOPS = 1, -+ DIE_PANIC, -+ DIE_DIE, -+ DIE_KERNELDEBUG, -+ DIE_TRAP, -+ DIE_PAGE_FAULT, -+}; -+ -+/* -+ * trap number can be computed from regs and signr can be computed using -+ * compute_signal() -+ */ -+static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err) -+{ -+ struct die_args args = { .regs=regs, .str=str, .err=err }; -+ return notifier_call_chain(&mips_die_chain, val, &args); -+} -+ -+#endif /* _MIPS_KDEBUG_H */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-mips/kgdb.h linux-2.6.18-53.1.14.kgdb/include/asm-mips/kgdb.h ---- linux-2.6.18-53.1.14/include/asm-mips/kgdb.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-mips/kgdb.h 2008-06-10 15:39:01.000000000 +0400 -@@ -0,0 +1,34 @@ -+#ifdef __KERNEL__ -+#ifndef _ASM_KGDB_H_ -+#define _ASM_KGDB_H_ -+ -+#ifndef __ASSEMBLY__ -+#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) -+typedef u32 gdb_reg_t; -+#elif (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) -+typedef u64 gdb_reg_t; -+#else -+#error need to do -+#endif /* _MIPS_ISA */ -+ -+#include -+ -+#ifndef __ASSEMBLY__ -+#define BUFMAX 2048 -+#define NUMREGBYTES (90*sizeof(gdb_reg_t)) -+#define NUMCRITREGBYTES (12*sizeof(gdb_reg_t)) -+#define BREAK_INSTR_SIZE 4 -+#define BREAKPOINT() __asm__ __volatile__( \ -+ ".globl breakinst\n\t" \ -+ ".set\tnoreorder\n\t" \ -+ "nop\n" \ -+ "breakinst:\tbreak\n\t" \ -+ "nop\n\t" \ -+ ".set\treorder") -+#define CACHE_FLUSH_IS_SAFE 0 -+ -+extern int kgdb_early_setup; -+ -+#endif /* !__ASSEMBLY__ */ -+#endif /* _ASM_KGDB_H_ */ -+#endif /* __KERNEL__ */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-powerpc/kgdb.h linux-2.6.18-53.1.14.kgdb/include/asm-powerpc/kgdb.h ---- linux-2.6.18-53.1.14/include/asm-powerpc/kgdb.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-powerpc/kgdb.h 2008-06-10 15:39:01.000000000 +0400 -@@ -0,0 +1,74 @@ -+/* -+ * include/asm-powerpc/kgdb.h -+ * -+ * The PowerPC (32/64) specific defines / externs for KGDB. Based on -+ * the previous 32bit and 64bit specific files, which had the following -+ * copyrights: -+ * -+ * PPC64 Mods (C) 2005 Frank Rowand (frowand@mvista.com) -+ * PPC Mods (C) 2004 Tom Rini (trini@mvista.com) -+ * PPC Mods (C) 2003 John Whitney (john.whitney@timesys.com) -+ * PPC Mods (C) 1998 Michael Tesch (tesch@cs.wisc.edu) -+ * -+ * -+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) -+ * Author: Tom Rini -+ * -+ * 2006 (c) MontaVista Software, Inc. This file is licensed under -+ * the terms of the GNU General Public License version 2. This program -+ * is licensed "as is" without any warranty of any kind, whether express -+ * or implied. -+ */ -+#ifdef __KERNEL__ -+#ifndef __POWERPC_KGDB_H__ -+#define __POWERPC_KGDB_H__ -+ -+#include -+#ifndef __ASSEMBLY__ -+ -+#define BREAK_INSTR_SIZE 4 -+#define BUFMAX ((NUMREGBYTES * 2) + 512) -+#define OUTBUFMAX ((NUMREGBYTES * 2) + 512) -+#define BREAKPOINT() asm(".long 0x7d821008"); /* twge r2, r2 */ -+#define CACHE_FLUSH_IS_SAFE 1 -+ -+/* The number bytes of registers we have to save depends on a few -+ * things. For 64bit we default to not including vector registers and -+ * vector state registers. */ -+#ifdef CONFIG_PPC64 -+/* -+ * 64 bit (8 byte) registers: -+ * 32 gpr, 32 fpr, nip, msr, link, ctr -+ * 32 bit (4 byte) registers: -+ * ccr, xer, fpscr -+ */ -+#define NUMREGBYTES ((68 * 8) + (3 * 4)) -+#if 0 -+/* The following adds in vector registers and vector state registers. */ -+/* 128 bit (16 byte) registers: -+ * 32 vr -+ * 64 bit (8 byte) registers: -+ * 32 gpr, 32 fpr, nip, msr, link, ctr -+ * 32 bit (4 byte) registers: -+ * ccr, xer, fpscr, vscr, vrsave -+ */ -+#define NUMREGBYTES ((128 * 16) + (68 * 8) + (5 * 4)) -+#endif -+#define NUMCRITREGBYTES 184 -+#else /* CONFIG_PPC32 */ -+/* On non-E500 family PPC32 we determine the size by picking the last -+ * register we need, but on E500 we skip sections so we list what we -+ * need to store, and add it up. */ -+#ifndef CONFIG_E500 -+#define MAXREG (PT_FPSCR+1) -+#else -+/* 32 GPRs (8 bytes), nip, msr, ccr, link, ctr, xer, acc (8 bytes), spefscr*/ -+#define MAXREG ((32*2)+6+2+1) -+#endif -+#define NUMREGBYTES (MAXREG * sizeof(int)) -+/* CR/LR, R1, R2, R13-R31 inclusive. */ -+#define NUMCRITREGBYTES (23 * sizeof(int)) -+#endif /* 32/64 */ -+#endif /* !(__ASSEMBLY__) */ -+#endif /* !__POWERPC_KGDB_H__ */ -+#endif /* __KERNEL__ */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-ppc/kgdb.h linux-2.6.18-53.1.14.kgdb/include/asm-ppc/kgdb.h ---- linux-2.6.18-53.1.14/include/asm-ppc/kgdb.h 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-ppc/kgdb.h 2008-06-10 15:38:14.000000000 +0400 -@@ -1,57 +1,18 @@ --/* -- * kgdb.h: Defines and declarations for serial line source level -- * remote debugging of the Linux kernel using gdb. -- * -- * PPC Mods (C) 1998 Michael Tesch (tesch@cs.wisc.edu) -- * -- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) -- */ - #ifdef __KERNEL__ --#ifndef _PPC_KGDB_H --#define _PPC_KGDB_H -- -+#ifndef __PPC_KGDB_H__ -+#define __PPC_KGDB_H__ -+#include - #ifndef __ASSEMBLY__ -- --/* Things specific to the gen550 backend. */ --struct uart_port; -- --extern void gen550_progress(char *, unsigned short); --extern void gen550_kgdb_map_scc(void); --extern void gen550_init(int, struct uart_port *); -- --/* Things specific to the pmac backend. */ --extern void zs_kgdb_hook(int tty_num); -- --/* To init the kgdb engine. (called by serial hook)*/ --extern void set_debug_traps(void); -- --/* To enter the debugger explicitly. */ --extern void breakpoint(void); -- --/* For taking exceptions -+ /* For taking exceptions - * these are defined in traps.c - */ --extern int (*debugger)(struct pt_regs *regs); -+struct pt_regs; -+extern void (*debugger)(struct pt_regs *regs); - extern int (*debugger_bpt)(struct pt_regs *regs); - extern int (*debugger_sstep)(struct pt_regs *regs); - extern int (*debugger_iabr_match)(struct pt_regs *regs); - extern int (*debugger_dabr_match)(struct pt_regs *regs); - extern void (*debugger_fault_handler)(struct pt_regs *regs); -- --/* What we bring to the party */ --int kgdb_bpt(struct pt_regs *regs); --int kgdb_sstep(struct pt_regs *regs); --void kgdb(struct pt_regs *regs); --int kgdb_iabr_match(struct pt_regs *regs); --int kgdb_dabr_match(struct pt_regs *regs); -- --/* -- * external low-level support routines (ie macserial.c) -- */ --extern void kgdb_interruptible(int); /* control interrupts from serial */ --extern void putDebugChar(char); /* write a single character */ --extern char getDebugChar(void); /* read and return a single char */ -- --#endif /* !(__ASSEMBLY__) */ --#endif /* !(_PPC_KGDB_H) */ -+#endif /* !__ASSEMBLY__ */ -+#endif /* __PPC_KGDB_H__ */ - #endif /* __KERNEL__ */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-ppc/machdep.h linux-2.6.18-53.1.14.kgdb/include/asm-ppc/machdep.h ---- linux-2.6.18-53.1.14/include/asm-ppc/machdep.h 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-ppc/machdep.h 2008-06-10 15:38:14.000000000 +0400 -@@ -72,9 +72,7 @@ struct machdep_calls { - unsigned long (*find_end_of_memory)(void); - void (*setup_io_mappings)(void); - -- void (*early_serial_map)(void); - void (*progress)(char *, unsigned short); -- void (*kgdb_map_scc)(void); - - unsigned char (*nvram_read_val)(int addr); - void (*nvram_write_val)(int addr, unsigned char val); -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-ppc/mv64x60.h linux-2.6.18-53.1.14.kgdb/include/asm-ppc/mv64x60.h ---- linux-2.6.18-53.1.14/include/asm-ppc/mv64x60.h 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-ppc/mv64x60.h 2008-06-10 15:38:14.000000000 +0400 -@@ -348,6 +348,8 @@ u32 mv64x60_calc_mem_size(struct mv64x60 - - void mv64x60_progress_init(u32 base); - void mv64x60_mpsc_progress(char *s, unsigned short hex); -+struct platform_device * mv64x60_early_get_pdev_data(const char *name, -+ int id, int remove); - - extern struct mv64x60_32bit_window - gt64260_32bit_windows[MV64x60_32BIT_WIN_COUNT]; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-ppc/mv64x60_defs.h linux-2.6.18-53.1.14.kgdb/include/asm-ppc/mv64x60_defs.h ---- linux-2.6.18-53.1.14/include/asm-ppc/mv64x60_defs.h 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-ppc/mv64x60_defs.h 2008-06-10 15:38:14.000000000 +0400 -@@ -57,7 +57,8 @@ - #define MV64x60_IRQ_I2C 37 - #define MV64x60_IRQ_BRG 39 - #define MV64x60_IRQ_MPSC_0 40 --#define MV64x60_IRQ_MPSC_1 42 -+#define MV64360_IRQ_MPSC_1 41 -+#define GT64260_IRQ_MPSC_1 42 - #define MV64x60_IRQ_COMM 43 - #define MV64x60_IRQ_P0_GPP_0_7 56 - #define MV64x60_IRQ_P0_GPP_8_15 57 -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-sh/kgdb.h linux-2.6.18-53.1.14.kgdb/include/asm-sh/kgdb.h ---- linux-2.6.18-53.1.14/include/asm-sh/kgdb.h 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-sh/kgdb.h 2008-06-10 15:39:01.000000000 +0400 -@@ -2,94 +2,40 @@ - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * -- * Based on original code by Glenn Engel, Jim Kingdon, -- * David Grothe , Tigran Aivazian, and -- * Amit S. Kale -+ * Based on a file that was modified or based on files by: Glenn Engel, -+ * Jim Kingdon, David Grothe , Tigran Aivazian , -+ * Amit S. Kale , sh-stub.c from Ben Lee and -+ * Steve Chamberlain, Henry Bell - * -- * Super-H port based on sh-stub.c (Ben Lee and Steve Chamberlain) by -- * Henry Bell -- * -- * Header file for low-level support for remote debug using GDB. -+ * Maintainer: Tom Rini - * - */ - - #ifndef __KGDB_H - #define __KGDB_H - --#include -- --struct console; -+#include -+/* Based on sh-gdb.c from gdb-6.1, Glenn -+ Engel at HP Ben Lee and Steve Chamberlain */ -+#define NUMREGBYTES 112 /* 92 */ -+#define NUMCRITREGBYTES (9 << 2) -+#define BUFMAX 400 - --/* Same as pt_regs but has vbr in place of syscall_nr */ -+#ifndef __ASSEMBLY__ - struct kgdb_regs { - unsigned long regs[16]; - unsigned long pc; - unsigned long pr; -- unsigned long sr; - unsigned long gbr; -+ unsigned long vbr; - unsigned long mach; - unsigned long macl; -- unsigned long vbr; --}; -- --/* State info */ --extern char kgdb_in_gdb_mode; --extern int kgdb_done_init; --extern int kgdb_enabled; --extern int kgdb_nofault; /* Ignore bus errors (in gdb mem access) */ --extern int kgdb_halt; /* Execute initial breakpoint at startup */ --extern char in_nmi; /* Debounce flag to prevent NMI reentry*/ -- --/* SCI */ --extern int kgdb_portnum; --extern int kgdb_baud; --extern char kgdb_parity; --extern char kgdb_bits; --extern int kgdb_console_setup(struct console *, char *); -- --/* Init and interface stuff */ --extern int kgdb_init(void); --extern int (*kgdb_serial_setup)(void); --extern int (*kgdb_getchar)(void); --extern void (*kgdb_putchar)(int); -- --struct kgdb_sermap { -- char *name; -- int namelen; -- int (*setup_fn)(struct console *, char *); -- struct kgdb_sermap *next; -+ unsigned long sr; - }; --extern void kgdb_register_sermap(struct kgdb_sermap *map); --extern struct kgdb_sermap *kgdb_porttype; - --/* Trap functions */ --typedef void (kgdb_debug_hook_t)(struct pt_regs *regs); --typedef void (kgdb_bus_error_hook_t)(void); --extern kgdb_debug_hook_t *kgdb_debug_hook; --extern kgdb_bus_error_hook_t *kgdb_bus_err_hook; -- --extern void breakpoint(void); -- --/* Console */ --struct console; --void kgdb_console_write(struct console *co, const char *s, unsigned count); --void kgdb_console_init(void); -- --/* Prototypes for jmp fns */ --#define _JBLEN 9 --typedef int jmp_buf[_JBLEN]; --extern void longjmp(jmp_buf __jmpb, int __retval); --extern int setjmp(jmp_buf __jmpb); -- --/* Variadic macro to print our own message to the console */ --#define KGDB_PRINTK(...) printk("KGDB: " __VA_ARGS__) -- --/* Forced breakpoint */ --#define BREAKPOINT() do { \ -- if (kgdb_enabled) { \ -- asm volatile("trapa #0xff"); \ -- } \ --} while (0) -+#define BREAKPOINT() asm("trapa #0xff"); -+#define BREAK_INSTR_SIZE 2 -+#define CACHE_FLUSH_IS_SAFE 1 - - /* KGDB should be able to flush all kernel text space */ - #if defined(CONFIG_CPU_SH4) -@@ -102,30 +48,5 @@ extern int setjmp(jmp_buf __jmpb); - #else - #define kgdb_flush_icache_range(start, end) do { } while (0) - #endif -- --/* Kernel assert macros */ --#ifdef CONFIG_KGDB_KERNEL_ASSERTS -- --/* Predefined conditions */ --#define KA_VALID_ERRNO(errno) ((errno) > 0 && (errno) <= EMEDIUMTYPE) --#define KA_VALID_PTR_ERR(ptr) KA_VALID_ERRNO(-PTR_ERR(ptr)) --#define KA_VALID_KPTR(ptr) (!(ptr) || \ -- ((void *)(ptr) >= (void *)PAGE_OFFSET && \ -- (void *)(ptr) < ERR_PTR(-EMEDIUMTYPE))) --#define KA_VALID_PTRORERR(errptr) \ -- (KA_VALID_KPTR(errptr) || KA_VALID_PTR_ERR(errptr)) --#define KA_HELD_GKL() (current->lock_depth >= 0) -- --/* The actual assert */ --#define KGDB_ASSERT(condition, message) do { \ -- if (!(condition) && (kgdb_enabled)) { \ -- KGDB_PRINTK("Assertion failed at %s:%d: %s\n", \ -- __FILE__, __LINE__, message);\ -- BREAKPOINT(); \ -- } \ --} while (0) --#else --#define KGDB_ASSERT(condition, message) --#endif -- -+#endif /* !__ASSEMBLY__ */ - #endif -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-sh/system.h linux-2.6.18-53.1.14.kgdb/include/asm-sh/system.h ---- linux-2.6.18-53.1.14/include/asm-sh/system.h 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-sh/system.h 2008-06-10 15:38:50.000000000 +0400 -@@ -6,6 +6,7 @@ - * Copyright (C) 2002 Paul Mundt - */ - -+#include - - /* - * switch_to() should switch tasks to task nr n, first -@@ -260,6 +261,45 @@ static __inline__ unsigned long __xchg(u - return x; - } - -+static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old, -+ unsigned long new) -+{ -+ __u32 retval; -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ retval = *m; -+ if (retval == old) -+ *m = new; -+ local_irq_restore(flags); /* implies memory barrier */ -+ return retval; -+} -+ -+/* This function doesn't exist, so you'll get a linker error -+ * if something tries to do an invalid cmpxchg(). */ -+extern void __cmpxchg_called_with_bad_pointer(void); -+ -+#define __HAVE_ARCH_CMPXCHG 1 -+ -+static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old, -+ unsigned long new, int size) -+{ -+ switch (size) { -+ case 4: -+ return __cmpxchg_u32(ptr, old, new); -+ } -+ __cmpxchg_called_with_bad_pointer(); -+ return old; -+} -+ -+#define cmpxchg(ptr,o,n) \ -+ ({ \ -+ __typeof__(*(ptr)) _o_ = (o); \ -+ __typeof__(*(ptr)) _n_ = (n); \ -+ (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ -+ (unsigned long)_n_, sizeof(*(ptr))); \ -+ }) -+ - /* XXX - * disable hlt during certain critical i/o operations - */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-x86_64/kdebug.h linux-2.6.18-53.1.14.kgdb/include/asm-x86_64/kdebug.h ---- linux-2.6.18-53.1.14/include/asm-x86_64/kdebug.h 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-x86_64/kdebug.h 2008-06-10 15:38:41.000000000 +0400 -@@ -34,6 +34,7 @@ enum die_val { - DIE_CALL, - DIE_NMI_IPI, - DIE_PAGE_FAULT, -+ DIE_PAGE_FAULT_NO_CONTEXT, - }; - - static inline int notify_die(enum die_val val, const char *str, -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-x86_64/kgdb.h linux-2.6.18-53.1.14.kgdb/include/asm-x86_64/kgdb.h ---- linux-2.6.18-53.1.14/include/asm-x86_64/kgdb.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-x86_64/kgdb.h 2008-06-10 15:39:01.000000000 +0400 -@@ -0,0 +1,54 @@ -+#ifdef __KERNEL__ -+#ifndef _ASM_KGDB_H_ -+#define _ASM_KGDB_H_ -+ -+/* -+ * Copyright (C) 2001-2004 Amit S. Kale -+ */ -+ -+#include -+ -+/* -+ * Note that this register image is in a different order than -+ * the register image that Linux produces at interrupt time. -+ * -+ * Linux's register image is defined by struct pt_regs in ptrace.h. -+ * Just why GDB uses a different order is a historical mystery. -+ */ -+#define _RAX 0 -+#define _RDX 1 -+#define _RCX 2 -+#define _RBX 3 -+#define _RSI 4 -+#define _RDI 5 -+#define _RBP 6 -+#define _RSP 7 -+#define _R8 8 -+#define _R9 9 -+#define _R10 10 -+#define _R11 11 -+#define _R12 12 -+#define _R13 13 -+#define _R14 14 -+#define _R15 15 -+#define _PC 16 -+#define _PS 17 -+ -+/* Number of bytes of registers. */ -+#define NUMREGBYTES ((_PS+1)*8) -+#define NUMCRITREGBYTES (8 * 8) /* 8 registers. */ -+ -+/* Help GDB to know when to stop backtracing. */ -+#define CFI_END_FRAME(func) __CFI_END_FRAME(_PC,_RSP,func) -+#ifndef __ASSEMBLY__ -+/* BUFMAX defines the maximum number of characters in inbound/outbound -+ * buffers at least NUMREGBYTES*2 are needed for register packets, and -+ * a longer buffer is needed to list all threads. */ -+#define BUFMAX 1024 -+#define BREAKPOINT() asm(" int $3"); -+#define CHECK_EXCEPTION_STACK() ((&__get_cpu_var(init_tss))[0].ist[0]) -+#define BREAK_INSTR_SIZE 1 -+#define CACHE_FLUSH_IS_SAFE 1 -+#endif /* !__ASSEMBLY__ */ -+#endif /* _ASM_KGDB_H_ */ -+#endif /* __KERNEL__ */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/asm-x86_64/system.h linux-2.6.18-53.1.14.kgdb/include/asm-x86_64/system.h ---- linux-2.6.18-53.1.14/include/asm-x86_64/system.h 2008-03-06 05:54:38.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/include/asm-x86_64/system.h 2008-06-10 15:38:44.000000000 +0400 -@@ -22,7 +22,9 @@ - - /* Save restore flags to clear handle leaking NT */ - #define switch_to(prev,next,last) \ -- asm volatile(SAVE_CONTEXT \ -+ asm volatile(".globl __switch_to_begin\n\t" \ -+ "__switch_to_begin:\n\t" \ -+ SAVE_CONTEXT \ - "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */ \ - "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */ \ - "call __switch_to\n\t" \ -@@ -34,6 +36,8 @@ - "movq %%rax,%%rdi\n\t" \ - "jc ret_from_fork\n\t" \ - RESTORE_CONTEXT \ -+ ".globl __switch_to_end\n\t" \ -+ "__switch_to_end:\n\t" \ - : "=a" (last) \ - : [next] "S" (next), [prev] "D" (prev), \ - [threadrsp] "i" (offsetof(struct task_struct, thread.rsp)), \ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/linux/dwarf2-lang.h linux-2.6.18-53.1.14.kgdb/include/linux/dwarf2-lang.h ---- linux-2.6.18-53.1.14/include/linux/dwarf2-lang.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/include/linux/dwarf2-lang.h 2008-06-10 15:39:01.000000000 +0400 -@@ -0,0 +1,300 @@ -+#ifndef DWARF2_LANG -+#define DWARF2_LANG -+ -+/* -+ * This is free software; you can redistribute it and/or modify it under -+ * the terms of the GNU General Public License as published by the Free -+ * Software Foundation; either version 2, or (at your option) any later -+ * version. -+ */ -+/* -+ * This file defines macros that allow generation of DWARF debug records -+ * for asm files. This file is platform independent. Register numbers -+ * (which are about the only thing that is platform dependent) are to be -+ * supplied by a platform defined file. -+ */ -+/* -+ * We need this to work for both asm and C. In asm we are using the -+ * old comment trick to concatenate while C uses the new ANSI thing. -+ * Here we have concat macro... The multi level thing is to allow and -+ * macros used in the names to be resolved prior to the cat (at which -+ * time they are no longer the same string). -+ */ -+#define CAT3(a,b,c) _CAT3(a,b,c) -+#define _CAT3(a,b,c) __CAT3(a,b,c) -+#ifndef __STDC__ -+#define __CAT3(a,b,c) a/**/b/**/c -+#else -+#define __CAT3(a,b,c) a##b##c -+#endif -+#ifdef __ASSEMBLY__ -+#define IFC(a) -+#define IFN_C(a) a -+#define NL ; -+#define QUOTE_THIS(a) a -+#define DWARF_preamble .section .debug_frame,"",%progbits; -+#else -+#define IFC(a) a -+#define IFN_C(a) -+#define NL \n\t -+#define QUOTE_THIS(a) _QUOTE_THIS(a) -+#define _QUOTE_THIS(a) #a -+/* Don't let CPP see the " and , \042=" \054=, */ -+#define DWARF_preamble .section .debug_frame \054\042\042\054%progbits -+#endif -+ -+#ifdef CONFIG_64BIT -+#define DATA_ALIGN_FACTOR 8 -+#define ADDR_LOC .quad -+#else -+#define DATA_ALIGN_FACTOR 4 -+#define ADDR_LOC .long -+#endif -+ -+#include -+/* -+ * This macro starts a debug frame section. The debug_frame describes -+ * where to find the registers that the enclosing function saved on -+ * entry. -+ * -+ * ORD is use by the label generator and should be the same as what is -+ * passed to CFI_postamble. -+ * -+ * pc, pc register gdb ordinal. -+ * -+ * code_align this is the factor used to define locations or regions -+ * where the given definitions apply. If you use labels to define these -+ * this should be 1. -+ * -+ * data_align this is the factor used to define register offsets. If -+ * you use struct offset, this should be the size of the register in -+ * bytes or the negative of that. This is how it is used: you will -+ * define a register as the reference register, say the stack pointer, -+ * then you will say where a register is located relative to this -+ * reference registers value, say 40 for register 3 (the gdb register -+ * number). The <40> will be multiplied by to define the -+ * byte offset of the given register (3, in this example). So if your -+ * <40> is the byte offset and the reference register points at the -+ * begining, you would want 1 for the data_offset. If <40> was the 40th -+ * 4-byte element in that structure you would want 4. And if your -+ * reference register points at the end of the structure you would want -+ * a negative data_align value(and you would have to do other math as -+ * well). -+ */ -+ -+#define CFI_preamble(ORD, pc, code_align, data_align) \ -+ DWARF_preamble NL \ -+ .align DATA_ALIGN_FACTOR NL \ -+ .globl CAT3(frame,_,ORD) NL \ -+CAT3(frame,_,ORD): NL \ -+ .long 7f-6f NL \ -+6: \ -+ .long DW_CIE_ID NL \ -+ .byte DW_CIE_VERSION NL \ -+ .byte 0 NL \ -+ .uleb128 code_align NL \ -+ .sleb128 data_align NL \ -+ .byte pc NL -+ -+/* -+ * After the above macro and prior to the CFI_postamble, you need to -+ * define the initial state. This starts with defining the reference -+ * register and, usually the pc. Here are some helper macros: -+ */ -+ -+#define CFA_define_reference(reg, offset) \ -+ .byte DW_CFA_def_cfa NL \ -+ .uleb128 reg NL \ -+ .uleb128 (offset) NL -+ -+#define CFA_define_offset(reg, offset) \ -+ .byte (DW_CFA_offset + reg) NL \ -+ .uleb128 (offset) NL -+ -+#define CFA_restore(reg) \ -+ .byte (DW_CFA_restore + reg) NL -+ -+#define CFI_postamble() \ -+ .align DATA_ALIGN_FACTOR NL \ -+7: NL \ -+.previous NL -+ -+/* -+ * So now your code pushs stuff on the stack, you need a new location -+ * and the rules for what to do. This starts a running description of -+ * the call frame. You need to describe what changes with respect to -+ * the call registers as the location of the pc moves through the code. -+ * The following builds an FDE (fram descriptor entry?). Like the -+ * above, it has a preamble and a postamble. It also is tied to the CFI -+ * above. -+ * The preamble macro is tied to the CFI thru the first parameter. The -+ * second is the code start address and then the code end address+1. -+ */ -+#define FDE_preamble(ORD, initial_address, end_address) \ -+ DWARF_preamble NL \ -+ .align DATA_ALIGN_FACTOR NL \ -+ .long 9f-8f NL \ -+8: \ -+ .long CAT3(frame,_,ORD) NL \ -+ ADDR_LOC initial_address NL \ -+ ADDR_LOC (end_address - initial_address) NL -+ -+#define FDE_postamble() \ -+ .align DATA_ALIGN_FACTOR NL \ -+9: NL \ -+.previous NL -+ -+/* -+ * That done, you can now add registers, subtract registers, move the -+ * reference and even change the reference. You can also define a new -+ * area of code the info applies to. For discontinuous bits you should -+ * start a new FDE. You may have as many as you like. -+ */ -+ -+/* -+ * To advance the stack address by (0x3f max) -+ */ -+ -+#define CFA_advance_loc(bytes) \ -+ .byte DW_CFA_advance_loc+bytes NL -+ -+/* -+ * This one is good for 0xff or 255 -+ */ -+#define CFA_advance_loc1(bytes) \ -+ .byte DW_CFA_advance_loc1 NL \ -+ .byte bytes NL -+ -+#define CFA_undefine_reg(reg) \ -+ .byte DW_CFA_undefined NL \ -+ .uleb128 reg NL -+/* -+ * With the above you can define all the register locations. But -+ * suppose the reference register moves... Takes the new offset NOT an -+ * increment. This is how esp is tracked if it is not saved. -+ */ -+ -+#define CFA_define_cfa_offset(offset) \ -+ .byte DW_CFA_def_cfa_offset NL \ -+ .uleb128 (offset) NL -+/* -+ * Or suppose you want to use a different reference register... -+ */ -+#define CFA_define_cfa_register(reg) \ -+ .byte DW_CFA_def_cfa_register NL \ -+ .uleb128 reg NL -+ -+/* -+ * If you want to mess with the stack pointer, here is the expression. -+ * The stack starts empty. -+ */ -+#define CFA_def_cfa_expression \ -+ .byte DW_CFA_def_cfa_expression NL \ -+ .uleb128 20f-10f NL \ -+10: NL -+/* -+ * This expression is to be used for other regs. The stack starts with the -+ * stack address. -+ */ -+ -+#define CFA_expression(reg) \ -+ .byte DW_CFA_expression NL \ -+ .uleb128 reg NL \ -+ .uleb128 20f-10f NL \ -+10: NL -+/* -+ * Here we do the expression stuff. You should code the above followed -+ * by expression OPs followed by CFA_expression_end. -+ */ -+ -+ -+#define CFA_expression_end \ -+20: NL -+ -+#define CFA_exp_OP_const4s(a) \ -+ .byte DW_OP_const4s NL \ -+ .long a NL -+ -+#define CFA_exp_OP_swap .byte DW_OP_swap NL -+#define CFA_exp_OP_dup .byte DW_OP_dup NL -+#define CFA_exp_OP_drop .byte DW_OP_drop NL -+/* -+ * All these work on the top two elements on the stack, replacing them -+ * with the result. Top comes first where it matters. True is 1, false 0. -+ */ -+#define CFA_exp_OP_deref .byte DW_OP_deref NL -+#define CFA_exp_OP_and .byte DW_OP_and NL -+#define CFA_exp_OP_div .byte DW_OP_div NL -+#define CFA_exp_OP_minus .byte DW_OP_minus NL -+#define CFA_exp_OP_mod .byte DW_OP_mod NL -+#define CFA_exp_OP_neg .byte DW_OP_neg NL -+#define CFA_exp_OP_plus .byte DW_OP_plus NL -+#define CFA_exp_OP_not .byte DW_OP_not NL -+#define CFA_exp_OP_or .byte DW_OP_or NL -+#define CFA_exp_OP_xor .byte DW_OP_xor NL -+#define CFA_exp_OP_le .byte DW_OP_le NL -+#define CFA_exp_OP_ge .byte DW_OP_ge NL -+#define CFA_exp_OP_eq .byte DW_OP_eq NL -+#define CFA_exp_OP_lt .byte DW_OP_lt NL -+#define CFA_exp_OP_gt .byte DW_OP_gt NL -+#define CFA_exp_OP_ne .byte DW_OP_ne NL -+/* -+ * These take a parameter as noted -+ */ -+/* -+ * Unconditional skip to loc. loc is a label (loc:) -+ */ -+#define CFA_exp_OP_skip(loc) \ -+ .byte DW_OP_skip NL \ -+ .hword loc-.-2 NL -+/* -+ * Conditional skip to loc (TOS != 0, TOS--) (loc is a label) -+ */ -+#define CFA_exp_OP_bra(loc) \ -+ .byte DW_OP_bra NL \ -+ .hword loc-.-2 NL -+ -+/* -+ * TOS += no (an unsigned number) -+ */ -+#define CFA_exp_OP_plus_uconst(no) \ -+ .byte DW_OP_plus_uconst NL \ -+ .uleb128 no NL -+ -+/* -+ * ++TOS = no (a unsigned number) -+ */ -+#define CFA_exp_OP_constu(no) \ -+ .byte DW_OP_constu NL \ -+ .uleb128 no NL -+/* -+ * ++TOS = no (a signed number) -+ */ -+#define CFA_exp_OP_consts(no) \ -+ .byte DW_OP_consts NL \ -+ .sleb128 no NL -+/* -+ * ++TOS = no (an unsigned byte) -+ */ -+#define CFA_exp_OP_const1u(no) \ -+ .byte DW_OP_const1u NL \ -+ .byte no NL -+ -+ -+/* -+ * ++TOS = no (a address) -+ */ -+#define CFA_exp_OP_addr(no) \ -+ .byte DW_OP_addr NL \ -+ .long no NL -+ -+/* -+ * Push current frames value for "reg" + offset -+ * We take advantage of the opcode assignments to make this a litteral reg -+ * rather than use the DW_OP_bregx opcode. -+ */ -+ -+#define CFA_exp_OP_breg(reg,offset) \ -+ .byte DW_OP_breg0+reg NL \ -+ .sleb128 offset NL -+#endif -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/linux/dwarf2.h linux-2.6.18-53.1.14.kgdb/include/linux/dwarf2.h ---- linux-2.6.18-53.1.14/include/linux/dwarf2.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/include/linux/dwarf2.h 2008-06-10 15:39:01.000000000 +0400 -@@ -0,0 +1,775 @@ -+/* Declarations and definitions of codes relating to the DWARF2 symbolic -+ debugging information format. -+ Copyright (C) 1992, 1993, 1995, 1996, 1997, 1999, 2000, 2001, 2002, -+ 2003 Free Software Foundation, Inc. -+ -+ Written by Gary Funck (gary@intrepid.com) The Ada Joint Program -+ Office (AJPO), Florida State Unviversity and Silicon Graphics Inc. -+ provided support for this effort -- June 21, 1995. -+ -+ Derived from the DWARF 1 implementation written by Ron Guilmette -+ (rfg@netcom.com), November 1990. -+ -+ This file is part of GCC. -+ -+ GCC is free software; you can redistribute it and/or modify it under -+ the terms of the GNU General Public License as published by the Free -+ Software Foundation; either version 2, or (at your option) any later -+ version. -+ -+ GCC is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -+ License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with GCC; see the file COPYING. If not, write to the Free -+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA -+ 02111-1307, USA. */ -+ -+/* This file is derived from the DWARF specification (a public document) -+ Revision 2.0.0 (July 27, 1993) developed by the UNIX International -+ Programming Languages Special Interest Group (UI/PLSIG) and distributed -+ by UNIX International. Copies of this specification are available from -+ UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054. -+ -+ This file also now contains definitions from the DWARF 3 specification. */ -+ -+/* This file is shared between GCC and GDB, and should not contain -+ prototypes. */ -+ -+#ifndef _ELF_DWARF2_H -+#define _ELF_DWARF2_H -+ -+/* Structure found in the .debug_line section. */ -+typedef struct -+{ -+ unsigned char li_length [4]; -+ unsigned char li_version [2]; -+ unsigned char li_prologue_length [4]; -+ unsigned char li_min_insn_length [1]; -+ unsigned char li_default_is_stmt [1]; -+ unsigned char li_line_base [1]; -+ unsigned char li_line_range [1]; -+ unsigned char li_opcode_base [1]; -+} -+DWARF2_External_LineInfo; -+ -+typedef struct -+{ -+ unsigned long li_length; -+ unsigned short li_version; -+ unsigned int li_prologue_length; -+ unsigned char li_min_insn_length; -+ unsigned char li_default_is_stmt; -+ int li_line_base; -+ unsigned char li_line_range; -+ unsigned char li_opcode_base; -+} -+DWARF2_Internal_LineInfo; -+ -+/* Structure found in .debug_pubnames section. */ -+typedef struct -+{ -+ unsigned char pn_length [4]; -+ unsigned char pn_version [2]; -+ unsigned char pn_offset [4]; -+ unsigned char pn_size [4]; -+} -+DWARF2_External_PubNames; -+ -+typedef struct -+{ -+ unsigned long pn_length; -+ unsigned short pn_version; -+ unsigned long pn_offset; -+ unsigned long pn_size; -+} -+DWARF2_Internal_PubNames; -+ -+/* Structure found in .debug_info section. */ -+typedef struct -+{ -+ unsigned char cu_length [4]; -+ unsigned char cu_version [2]; -+ unsigned char cu_abbrev_offset [4]; -+ unsigned char cu_pointer_size [1]; -+} -+DWARF2_External_CompUnit; -+ -+typedef struct -+{ -+ unsigned long cu_length; -+ unsigned short cu_version; -+ unsigned long cu_abbrev_offset; -+ unsigned char cu_pointer_size; -+} -+DWARF2_Internal_CompUnit; -+ -+typedef struct -+{ -+ unsigned char ar_length [4]; -+ unsigned char ar_version [2]; -+ unsigned char ar_info_offset [4]; -+ unsigned char ar_pointer_size [1]; -+ unsigned char ar_segment_size [1]; -+} -+DWARF2_External_ARange; -+ -+typedef struct -+{ -+ unsigned long ar_length; -+ unsigned short ar_version; -+ unsigned long ar_info_offset; -+ unsigned char ar_pointer_size; -+ unsigned char ar_segment_size; -+} -+DWARF2_Internal_ARange; -+ -+ -+/* Tag names and codes. */ -+enum dwarf_tag -+ { -+ DW_TAG_padding = 0x00, -+ DW_TAG_array_type = 0x01, -+ DW_TAG_class_type = 0x02, -+ DW_TAG_entry_point = 0x03, -+ DW_TAG_enumeration_type = 0x04, -+ DW_TAG_formal_parameter = 0x05, -+ DW_TAG_imported_declaration = 0x08, -+ DW_TAG_label = 0x0a, -+ DW_TAG_lexical_block = 0x0b, -+ DW_TAG_member = 0x0d, -+ DW_TAG_pointer_type = 0x0f, -+ DW_TAG_reference_type = 0x10, -+ DW_TAG_compile_unit = 0x11, -+ DW_TAG_string_type = 0x12, -+ DW_TAG_structure_type = 0x13, -+ DW_TAG_subroutine_type = 0x15, -+ DW_TAG_typedef = 0x16, -+ DW_TAG_union_type = 0x17, -+ DW_TAG_unspecified_parameters = 0x18, -+ DW_TAG_variant = 0x19, -+ DW_TAG_common_block = 0x1a, -+ DW_TAG_common_inclusion = 0x1b, -+ DW_TAG_inheritance = 0x1c, -+ DW_TAG_inlined_subroutine = 0x1d, -+ DW_TAG_module = 0x1e, -+ DW_TAG_ptr_to_member_type = 0x1f, -+ DW_TAG_set_type = 0x20, -+ DW_TAG_subrange_type = 0x21, -+ DW_TAG_with_stmt = 0x22, -+ DW_TAG_access_declaration = 0x23, -+ DW_TAG_base_type = 0x24, -+ DW_TAG_catch_block = 0x25, -+ DW_TAG_const_type = 0x26, -+ DW_TAG_constant = 0x27, -+ DW_TAG_enumerator = 0x28, -+ DW_TAG_file_type = 0x29, -+ DW_TAG_friend = 0x2a, -+ DW_TAG_namelist = 0x2b, -+ DW_TAG_namelist_item = 0x2c, -+ DW_TAG_packed_type = 0x2d, -+ DW_TAG_subprogram = 0x2e, -+ DW_TAG_template_type_param = 0x2f, -+ DW_TAG_template_value_param = 0x30, -+ DW_TAG_thrown_type = 0x31, -+ DW_TAG_try_block = 0x32, -+ DW_TAG_variant_part = 0x33, -+ DW_TAG_variable = 0x34, -+ DW_TAG_volatile_type = 0x35, -+ /* DWARF 3. */ -+ DW_TAG_dwarf_procedure = 0x36, -+ DW_TAG_restrict_type = 0x37, -+ DW_TAG_interface_type = 0x38, -+ DW_TAG_namespace = 0x39, -+ DW_TAG_imported_module = 0x3a, -+ DW_TAG_unspecified_type = 0x3b, -+ DW_TAG_partial_unit = 0x3c, -+ DW_TAG_imported_unit = 0x3d, -+ /* SGI/MIPS Extensions. */ -+ DW_TAG_MIPS_loop = 0x4081, -+ /* HP extensions. See: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz . */ -+ DW_TAG_HP_array_descriptor = 0x4090, -+ /* GNU extensions. */ -+ DW_TAG_format_label = 0x4101, /* For FORTRAN 77 and Fortran 90. */ -+ DW_TAG_function_template = 0x4102, /* For C++. */ -+ DW_TAG_class_template = 0x4103, /* For C++. */ -+ DW_TAG_GNU_BINCL = 0x4104, -+ DW_TAG_GNU_EINCL = 0x4105, -+ /* Extensions for UPC. See: http://upc.gwu.edu/~upc. */ -+ DW_TAG_upc_shared_type = 0x8765, -+ DW_TAG_upc_strict_type = 0x8766, -+ DW_TAG_upc_relaxed_type = 0x8767, -+ /* PGI (STMicroelectronics) extensions. No documentation available. */ -+ DW_TAG_PGI_kanji_type = 0xA000, -+ DW_TAG_PGI_interface_block = 0xA020 -+ }; -+ -+#define DW_TAG_lo_user 0x4080 -+#define DW_TAG_hi_user 0xffff -+ -+/* Flag that tells whether entry has a child or not. */ -+#define DW_children_no 0 -+#define DW_children_yes 1 -+ -+/* Form names and codes. */ -+enum dwarf_form -+ { -+ DW_FORM_addr = 0x01, -+ DW_FORM_block2 = 0x03, -+ DW_FORM_block4 = 0x04, -+ DW_FORM_data2 = 0x05, -+ DW_FORM_data4 = 0x06, -+ DW_FORM_data8 = 0x07, -+ DW_FORM_string = 0x08, -+ DW_FORM_block = 0x09, -+ DW_FORM_block1 = 0x0a, -+ DW_FORM_data1 = 0x0b, -+ DW_FORM_flag = 0x0c, -+ DW_FORM_sdata = 0x0d, -+ DW_FORM_strp = 0x0e, -+ DW_FORM_udata = 0x0f, -+ DW_FORM_ref_addr = 0x10, -+ DW_FORM_ref1 = 0x11, -+ DW_FORM_ref2 = 0x12, -+ DW_FORM_ref4 = 0x13, -+ DW_FORM_ref8 = 0x14, -+ DW_FORM_ref_udata = 0x15, -+ DW_FORM_indirect = 0x16 -+ }; -+ -+/* Attribute names and codes. */ -+enum dwarf_attribute -+ { -+ DW_AT_sibling = 0x01, -+ DW_AT_location = 0x02, -+ DW_AT_name = 0x03, -+ DW_AT_ordering = 0x09, -+ DW_AT_subscr_data = 0x0a, -+ DW_AT_byte_size = 0x0b, -+ DW_AT_bit_offset = 0x0c, -+ DW_AT_bit_size = 0x0d, -+ DW_AT_element_list = 0x0f, -+ DW_AT_stmt_list = 0x10, -+ DW_AT_low_pc = 0x11, -+ DW_AT_high_pc = 0x12, -+ DW_AT_language = 0x13, -+ DW_AT_member = 0x14, -+ DW_AT_discr = 0x15, -+ DW_AT_discr_value = 0x16, -+ DW_AT_visibility = 0x17, -+ DW_AT_import = 0x18, -+ DW_AT_string_length = 0x19, -+ DW_AT_common_reference = 0x1a, -+ DW_AT_comp_dir = 0x1b, -+ DW_AT_const_value = 0x1c, -+ DW_AT_containing_type = 0x1d, -+ DW_AT_default_value = 0x1e, -+ DW_AT_inline = 0x20, -+ DW_AT_is_optional = 0x21, -+ DW_AT_lower_bound = 0x22, -+ DW_AT_producer = 0x25, -+ DW_AT_prototyped = 0x27, -+ DW_AT_return_addr = 0x2a, -+ DW_AT_start_scope = 0x2c, -+ DW_AT_stride_size = 0x2e, -+ DW_AT_upper_bound = 0x2f, -+ DW_AT_abstract_origin = 0x31, -+ DW_AT_accessibility = 0x32, -+ DW_AT_address_class = 0x33, -+ DW_AT_artificial = 0x34, -+ DW_AT_base_types = 0x35, -+ DW_AT_calling_convention = 0x36, -+ DW_AT_count = 0x37, -+ DW_AT_data_member_location = 0x38, -+ DW_AT_decl_column = 0x39, -+ DW_AT_decl_file = 0x3a, -+ DW_AT_decl_line = 0x3b, -+ DW_AT_declaration = 0x3c, -+ DW_AT_discr_list = 0x3d, -+ DW_AT_encoding = 0x3e, -+ DW_AT_external = 0x3f, -+ DW_AT_frame_base = 0x40, -+ DW_AT_friend = 0x41, -+ DW_AT_identifier_case = 0x42, -+ DW_AT_macro_info = 0x43, -+ DW_AT_namelist_items = 0x44, -+ DW_AT_priority = 0x45, -+ DW_AT_segment = 0x46, -+ DW_AT_specification = 0x47, -+ DW_AT_static_link = 0x48, -+ DW_AT_type = 0x49, -+ DW_AT_use_location = 0x4a, -+ DW_AT_variable_parameter = 0x4b, -+ DW_AT_virtuality = 0x4c, -+ DW_AT_vtable_elem_location = 0x4d, -+ /* DWARF 3 values. */ -+ DW_AT_allocated = 0x4e, -+ DW_AT_associated = 0x4f, -+ DW_AT_data_location = 0x50, -+ DW_AT_stride = 0x51, -+ DW_AT_entry_pc = 0x52, -+ DW_AT_use_UTF8 = 0x53, -+ DW_AT_extension = 0x54, -+ DW_AT_ranges = 0x55, -+ DW_AT_trampoline = 0x56, -+ DW_AT_call_column = 0x57, -+ DW_AT_call_file = 0x58, -+ DW_AT_call_line = 0x59, -+ /* SGI/MIPS extensions. */ -+ DW_AT_MIPS_fde = 0x2001, -+ DW_AT_MIPS_loop_begin = 0x2002, -+ DW_AT_MIPS_tail_loop_begin = 0x2003, -+ DW_AT_MIPS_epilog_begin = 0x2004, -+ DW_AT_MIPS_loop_unroll_factor = 0x2005, -+ DW_AT_MIPS_software_pipeline_depth = 0x2006, -+ DW_AT_MIPS_linkage_name = 0x2007, -+ DW_AT_MIPS_stride = 0x2008, -+ DW_AT_MIPS_abstract_name = 0x2009, -+ DW_AT_MIPS_clone_origin = 0x200a, -+ DW_AT_MIPS_has_inlines = 0x200b, -+ /* HP extensions. */ -+ DW_AT_HP_block_index = 0x2000, -+ DW_AT_HP_unmodifiable = 0x2001, /* Same as DW_AT_MIPS_fde. */ -+ DW_AT_HP_actuals_stmt_list = 0x2010, -+ DW_AT_HP_proc_per_section = 0x2011, -+ DW_AT_HP_raw_data_ptr = 0x2012, -+ DW_AT_HP_pass_by_reference = 0x2013, -+ DW_AT_HP_opt_level = 0x2014, -+ DW_AT_HP_prof_version_id = 0x2015, -+ DW_AT_HP_opt_flags = 0x2016, -+ DW_AT_HP_cold_region_low_pc = 0x2017, -+ DW_AT_HP_cold_region_high_pc = 0x2018, -+ DW_AT_HP_all_variables_modifiable = 0x2019, -+ DW_AT_HP_linkage_name = 0x201a, -+ DW_AT_HP_prof_flags = 0x201b, /* In comp unit of procs_info for -g. */ -+ /* GNU extensions. */ -+ DW_AT_sf_names = 0x2101, -+ DW_AT_src_info = 0x2102, -+ DW_AT_mac_info = 0x2103, -+ DW_AT_src_coords = 0x2104, -+ DW_AT_body_begin = 0x2105, -+ DW_AT_body_end = 0x2106, -+ DW_AT_GNU_vector = 0x2107, -+ /* VMS extensions. */ -+ DW_AT_VMS_rtnbeg_pd_address = 0x2201, -+ /* UPC extension. */ -+ DW_AT_upc_threads_scaled = 0x3210, -+ /* PGI (STMicroelectronics) extensions. */ -+ DW_AT_PGI_lbase = 0x3a00, -+ DW_AT_PGI_soffset = 0x3a01, -+ DW_AT_PGI_lstride = 0x3a02 -+ }; -+ -+#define DW_AT_lo_user 0x2000 /* Implementation-defined range start. */ -+#define DW_AT_hi_user 0x3ff0 /* Implementation-defined range end. */ -+ -+/* Location atom names and codes. */ -+enum dwarf_location_atom -+ { -+ DW_OP_addr = 0x03, -+ DW_OP_deref = 0x06, -+ DW_OP_const1u = 0x08, -+ DW_OP_const1s = 0x09, -+ DW_OP_const2u = 0x0a, -+ DW_OP_const2s = 0x0b, -+ DW_OP_const4u = 0x0c, -+ DW_OP_const4s = 0x0d, -+ DW_OP_const8u = 0x0e, -+ DW_OP_const8s = 0x0f, -+ DW_OP_constu = 0x10, -+ DW_OP_consts = 0x11, -+ DW_OP_dup = 0x12, -+ DW_OP_drop = 0x13, -+ DW_OP_over = 0x14, -+ DW_OP_pick = 0x15, -+ DW_OP_swap = 0x16, -+ DW_OP_rot = 0x17, -+ DW_OP_xderef = 0x18, -+ DW_OP_abs = 0x19, -+ DW_OP_and = 0x1a, -+ DW_OP_div = 0x1b, -+ DW_OP_minus = 0x1c, -+ DW_OP_mod = 0x1d, -+ DW_OP_mul = 0x1e, -+ DW_OP_neg = 0x1f, -+ DW_OP_not = 0x20, -+ DW_OP_or = 0x21, -+ DW_OP_plus = 0x22, -+ DW_OP_plus_uconst = 0x23, -+ DW_OP_shl = 0x24, -+ DW_OP_shr = 0x25, -+ DW_OP_shra = 0x26, -+ DW_OP_xor = 0x27, -+ DW_OP_bra = 0x28, -+ DW_OP_eq = 0x29, -+ DW_OP_ge = 0x2a, -+ DW_OP_gt = 0x2b, -+ DW_OP_le = 0x2c, -+ DW_OP_lt = 0x2d, -+ DW_OP_ne = 0x2e, -+ DW_OP_skip = 0x2f, -+ DW_OP_lit0 = 0x30, -+ DW_OP_lit1 = 0x31, -+ DW_OP_lit2 = 0x32, -+ DW_OP_lit3 = 0x33, -+ DW_OP_lit4 = 0x34, -+ DW_OP_lit5 = 0x35, -+ DW_OP_lit6 = 0x36, -+ DW_OP_lit7 = 0x37, -+ DW_OP_lit8 = 0x38, -+ DW_OP_lit9 = 0x39, -+ DW_OP_lit10 = 0x3a, -+ DW_OP_lit11 = 0x3b, -+ DW_OP_lit12 = 0x3c, -+ DW_OP_lit13 = 0x3d, -+ DW_OP_lit14 = 0x3e, -+ DW_OP_lit15 = 0x3f, -+ DW_OP_lit16 = 0x40, -+ DW_OP_lit17 = 0x41, -+ DW_OP_lit18 = 0x42, -+ DW_OP_lit19 = 0x43, -+ DW_OP_lit20 = 0x44, -+ DW_OP_lit21 = 0x45, -+ DW_OP_lit22 = 0x46, -+ DW_OP_lit23 = 0x47, -+ DW_OP_lit24 = 0x48, -+ DW_OP_lit25 = 0x49, -+ DW_OP_lit26 = 0x4a, -+ DW_OP_lit27 = 0x4b, -+ DW_OP_lit28 = 0x4c, -+ DW_OP_lit29 = 0x4d, -+ DW_OP_lit30 = 0x4e, -+ DW_OP_lit31 = 0x4f, -+ DW_OP_reg0 = 0x50, -+ DW_OP_reg1 = 0x51, -+ DW_OP_reg2 = 0x52, -+ DW_OP_reg3 = 0x53, -+ DW_OP_reg4 = 0x54, -+ DW_OP_reg5 = 0x55, -+ DW_OP_reg6 = 0x56, -+ DW_OP_reg7 = 0x57, -+ DW_OP_reg8 = 0x58, -+ DW_OP_reg9 = 0x59, -+ DW_OP_reg10 = 0x5a, -+ DW_OP_reg11 = 0x5b, -+ DW_OP_reg12 = 0x5c, -+ DW_OP_reg13 = 0x5d, -+ DW_OP_reg14 = 0x5e, -+ DW_OP_reg15 = 0x5f, -+ DW_OP_reg16 = 0x60, -+ DW_OP_reg17 = 0x61, -+ DW_OP_reg18 = 0x62, -+ DW_OP_reg19 = 0x63, -+ DW_OP_reg20 = 0x64, -+ DW_OP_reg21 = 0x65, -+ DW_OP_reg22 = 0x66, -+ DW_OP_reg23 = 0x67, -+ DW_OP_reg24 = 0x68, -+ DW_OP_reg25 = 0x69, -+ DW_OP_reg26 = 0x6a, -+ DW_OP_reg27 = 0x6b, -+ DW_OP_reg28 = 0x6c, -+ DW_OP_reg29 = 0x6d, -+ DW_OP_reg30 = 0x6e, -+ DW_OP_reg31 = 0x6f, -+ DW_OP_breg0 = 0x70, -+ DW_OP_breg1 = 0x71, -+ DW_OP_breg2 = 0x72, -+ DW_OP_breg3 = 0x73, -+ DW_OP_breg4 = 0x74, -+ DW_OP_breg5 = 0x75, -+ DW_OP_breg6 = 0x76, -+ DW_OP_breg7 = 0x77, -+ DW_OP_breg8 = 0x78, -+ DW_OP_breg9 = 0x79, -+ DW_OP_breg10 = 0x7a, -+ DW_OP_breg11 = 0x7b, -+ DW_OP_breg12 = 0x7c, -+ DW_OP_breg13 = 0x7d, -+ DW_OP_breg14 = 0x7e, -+ DW_OP_breg15 = 0x7f, -+ DW_OP_breg16 = 0x80, -+ DW_OP_breg17 = 0x81, -+ DW_OP_breg18 = 0x82, -+ DW_OP_breg19 = 0x83, -+ DW_OP_breg20 = 0x84, -+ DW_OP_breg21 = 0x85, -+ DW_OP_breg22 = 0x86, -+ DW_OP_breg23 = 0x87, -+ DW_OP_breg24 = 0x88, -+ DW_OP_breg25 = 0x89, -+ DW_OP_breg26 = 0x8a, -+ DW_OP_breg27 = 0x8b, -+ DW_OP_breg28 = 0x8c, -+ DW_OP_breg29 = 0x8d, -+ DW_OP_breg30 = 0x8e, -+ DW_OP_breg31 = 0x8f, -+ DW_OP_regx = 0x90, -+ DW_OP_fbreg = 0x91, -+ DW_OP_bregx = 0x92, -+ DW_OP_piece = 0x93, -+ DW_OP_deref_size = 0x94, -+ DW_OP_xderef_size = 0x95, -+ DW_OP_nop = 0x96, -+ /* DWARF 3 extensions. */ -+ DW_OP_push_object_address = 0x97, -+ DW_OP_call2 = 0x98, -+ DW_OP_call4 = 0x99, -+ DW_OP_call_ref = 0x9a, -+ /* GNU extensions. */ -+ DW_OP_GNU_push_tls_address = 0xe0, -+ /* HP extensions. */ -+ DW_OP_HP_unknown = 0xe0, /* Ouch, the same as GNU_push_tls_address. */ -+ DW_OP_HP_is_value = 0xe1, -+ DW_OP_HP_fltconst4 = 0xe2, -+ DW_OP_HP_fltconst8 = 0xe3, -+ DW_OP_HP_mod_range = 0xe4, -+ DW_OP_HP_unmod_range = 0xe5, -+ DW_OP_HP_tls = 0xe6 -+ }; -+ -+#define DW_OP_lo_user 0xe0 /* Implementation-defined range start. */ -+#define DW_OP_hi_user 0xff /* Implementation-defined range end. */ -+ -+/* Type encodings. */ -+enum dwarf_type -+ { -+ DW_ATE_void = 0x0, -+ DW_ATE_address = 0x1, -+ DW_ATE_boolean = 0x2, -+ DW_ATE_complex_float = 0x3, -+ DW_ATE_float = 0x4, -+ DW_ATE_signed = 0x5, -+ DW_ATE_signed_char = 0x6, -+ DW_ATE_unsigned = 0x7, -+ DW_ATE_unsigned_char = 0x8, -+ /* DWARF 3. */ -+ DW_ATE_imaginary_float = 0x9, -+ /* HP extensions. */ -+ DW_ATE_HP_float80 = 0x80, /* Floating-point (80 bit). */ -+ DW_ATE_HP_complex_float80 = 0x81, /* Complex floating-point (80 bit). */ -+ DW_ATE_HP_float128 = 0x82, /* Floating-point (128 bit). */ -+ DW_ATE_HP_complex_float128 = 0x83, /* Complex floating-point (128 bit). */ -+ DW_ATE_HP_floathpintel = 0x84, /* Floating-point (82 bit IA64). */ -+ DW_ATE_HP_imaginary_float80 = 0x85, -+ DW_ATE_HP_imaginary_float128 = 0x86 -+ }; -+ -+#define DW_ATE_lo_user 0x80 -+#define DW_ATE_hi_user 0xff -+ -+/* Array ordering names and codes. */ -+enum dwarf_array_dim_ordering -+ { -+ DW_ORD_row_major = 0, -+ DW_ORD_col_major = 1 -+ }; -+ -+/* Access attribute. */ -+enum dwarf_access_attribute -+ { -+ DW_ACCESS_public = 1, -+ DW_ACCESS_protected = 2, -+ DW_ACCESS_private = 3 -+ }; -+ -+/* Visibility. */ -+enum dwarf_visibility_attribute -+ { -+ DW_VIS_local = 1, -+ DW_VIS_exported = 2, -+ DW_VIS_qualified = 3 -+ }; -+ -+/* Virtuality. */ -+enum dwarf_virtuality_attribute -+ { -+ DW_VIRTUALITY_none = 0, -+ DW_VIRTUALITY_virtual = 1, -+ DW_VIRTUALITY_pure_virtual = 2 -+ }; -+ -+/* Case sensitivity. */ -+enum dwarf_id_case -+ { -+ DW_ID_case_sensitive = 0, -+ DW_ID_up_case = 1, -+ DW_ID_down_case = 2, -+ DW_ID_case_insensitive = 3 -+ }; -+ -+/* Calling convention. */ -+enum dwarf_calling_convention -+ { -+ DW_CC_normal = 0x1, -+ DW_CC_program = 0x2, -+ DW_CC_nocall = 0x3 -+ }; -+ -+#define DW_CC_lo_user 0x40 -+#define DW_CC_hi_user 0xff -+ -+/* Inline attribute. */ -+enum dwarf_inline_attribute -+ { -+ DW_INL_not_inlined = 0, -+ DW_INL_inlined = 1, -+ DW_INL_declared_not_inlined = 2, -+ DW_INL_declared_inlined = 3 -+ }; -+ -+/* Discriminant lists. */ -+enum dwarf_discrim_list -+ { -+ DW_DSC_label = 0, -+ DW_DSC_range = 1 -+ }; -+ -+/* Line number opcodes. */ -+enum dwarf_line_number_ops -+ { -+ DW_LNS_extended_op = 0, -+ DW_LNS_copy = 1, -+ DW_LNS_advance_pc = 2, -+ DW_LNS_advance_line = 3, -+ DW_LNS_set_file = 4, -+ DW_LNS_set_column = 5, -+ DW_LNS_negate_stmt = 6, -+ DW_LNS_set_basic_block = 7, -+ DW_LNS_const_add_pc = 8, -+ DW_LNS_fixed_advance_pc = 9, -+ /* DWARF 3. */ -+ DW_LNS_set_prologue_end = 10, -+ DW_LNS_set_epilogue_begin = 11, -+ DW_LNS_set_isa = 12 -+ }; -+ -+/* Line number extended opcodes. */ -+enum dwarf_line_number_x_ops -+ { -+ DW_LNE_end_sequence = 1, -+ DW_LNE_set_address = 2, -+ DW_LNE_define_file = 3, -+ /* HP extensions. */ -+ DW_LNE_HP_negate_is_UV_update = 0x11, -+ DW_LNE_HP_push_context = 0x12, -+ DW_LNE_HP_pop_context = 0x13, -+ DW_LNE_HP_set_file_line_column = 0x14, -+ DW_LNE_HP_set_routine_name = 0x15, -+ DW_LNE_HP_set_sequence = 0x16, -+ DW_LNE_HP_negate_post_semantics = 0x17, -+ DW_LNE_HP_negate_function_exit = 0x18, -+ DW_LNE_HP_negate_front_end_logical = 0x19, -+ DW_LNE_HP_define_proc = 0x20 -+ }; -+ -+/* Call frame information. */ -+enum dwarf_call_frame_info -+ { -+ DW_CFA_advance_loc = 0x40, -+ DW_CFA_offset = 0x80, -+ DW_CFA_restore = 0xc0, -+ DW_CFA_nop = 0x00, -+ DW_CFA_set_loc = 0x01, -+ DW_CFA_advance_loc1 = 0x02, -+ DW_CFA_advance_loc2 = 0x03, -+ DW_CFA_advance_loc4 = 0x04, -+ DW_CFA_offset_extended = 0x05, -+ DW_CFA_restore_extended = 0x06, -+ DW_CFA_undefined = 0x07, -+ DW_CFA_same_value = 0x08, -+ DW_CFA_register = 0x09, -+ DW_CFA_remember_state = 0x0a, -+ DW_CFA_restore_state = 0x0b, -+ DW_CFA_def_cfa = 0x0c, -+ DW_CFA_def_cfa_register = 0x0d, -+ DW_CFA_def_cfa_offset = 0x0e, -+ /* DWARF 3. */ -+ DW_CFA_def_cfa_expression = 0x0f, -+ DW_CFA_expression = 0x10, -+ DW_CFA_offset_extended_sf = 0x11, -+ DW_CFA_def_cfa_sf = 0x12, -+ DW_CFA_def_cfa_offset_sf = 0x13, -+ /* SGI/MIPS specific. */ -+ DW_CFA_MIPS_advance_loc8 = 0x1d, -+ /* GNU extensions. */ -+ DW_CFA_GNU_window_save = 0x2d, -+ DW_CFA_GNU_args_size = 0x2e, -+ DW_CFA_GNU_negative_offset_extended = 0x2f -+ }; -+ -+#define DW_CIE_ID 0xffffffff -+#define DW_CIE_VERSION 1 -+ -+#define DW_CFA_extended 0 -+#define DW_CFA_lo_user 0x1c -+#define DW_CFA_hi_user 0x3f -+ -+#define DW_CHILDREN_no 0x00 -+#define DW_CHILDREN_yes 0x01 -+ -+#define DW_ADDR_none 0 -+ -+/* Source language names and codes. */ -+enum dwarf_source_language -+ { -+ DW_LANG_C89 = 0x0001, -+ DW_LANG_C = 0x0002, -+ DW_LANG_Ada83 = 0x0003, -+ DW_LANG_C_plus_plus = 0x0004, -+ DW_LANG_Cobol74 = 0x0005, -+ DW_LANG_Cobol85 = 0x0006, -+ DW_LANG_Fortran77 = 0x0007, -+ DW_LANG_Fortran90 = 0x0008, -+ DW_LANG_Pascal83 = 0x0009, -+ DW_LANG_Modula2 = 0x000a, -+ DW_LANG_Java = 0x000b, -+ /* DWARF 3. */ -+ DW_LANG_C99 = 0x000c, -+ DW_LANG_Ada95 = 0x000d, -+ DW_LANG_Fortran95 = 0x000e, -+ /* MIPS. */ -+ DW_LANG_Mips_Assembler = 0x8001, -+ /* UPC. */ -+ DW_LANG_Upc = 0x8765 -+ }; -+ -+#define DW_LANG_lo_user 0x8000 /* Implementation-defined range start. */ -+#define DW_LANG_hi_user 0xffff /* Implementation-defined range start. */ -+ -+/* Names and codes for macro information. */ -+enum dwarf_macinfo_record_type -+ { -+ DW_MACINFO_define = 1, -+ DW_MACINFO_undef = 2, -+ DW_MACINFO_start_file = 3, -+ DW_MACINFO_end_file = 4, -+ DW_MACINFO_vendor_ext = 255 -+ }; -+ -+/* @@@ For use with GNU frame unwind information. */ -+ -+#define DW_EH_PE_absptr 0x00 -+#define DW_EH_PE_omit 0xff -+ -+#define DW_EH_PE_uleb128 0x01 -+#define DW_EH_PE_udata2 0x02 -+#define DW_EH_PE_udata4 0x03 -+#define DW_EH_PE_udata8 0x04 -+#define DW_EH_PE_sleb128 0x09 -+#define DW_EH_PE_sdata2 0x0A -+#define DW_EH_PE_sdata4 0x0B -+#define DW_EH_PE_sdata8 0x0C -+#define DW_EH_PE_signed 0x08 -+ -+#define DW_EH_PE_pcrel 0x10 -+#define DW_EH_PE_textrel 0x20 -+#define DW_EH_PE_datarel 0x30 -+#define DW_EH_PE_funcrel 0x40 -+#define DW_EH_PE_aligned 0x50 -+ -+#define DW_EH_PE_indirect 0x80 -+ -+#endif /* _ELF_DWARF2_H */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/linux/kgdb.h linux-2.6.18-53.1.14.kgdb/include/linux/kgdb.h ---- linux-2.6.18-53.1.14/include/linux/kgdb.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/include/linux/kgdb.h 2008-06-10 15:39:21.000000000 +0400 -@@ -0,0 +1,279 @@ -+/* -+ * include/linux/kgdb.h -+ * -+ * This provides the hooks and functions that KGDB needs to share between -+ * the core, I/O and arch-specific portions. -+ * -+ * Author: Amit Kale and -+ * Tom Rini -+ * -+ * 2001-2004 (c) Amit S. Kale and 2003-2005 (c) MontaVista Software, Inc. -+ * This file is licensed under the terms of the GNU General Public License -+ * version 2. This program is licensed "as is" without any warranty of any -+ * kind, whether express or implied. -+ */ -+#ifdef __KERNEL__ -+#ifndef _KGDB_H_ -+#define _KGDB_H_ -+ -+#include -+ -+#ifdef CONFIG_KGDB -+#include -+#include -+#include -+#include -+ -+#ifndef CHECK_EXCEPTION_STACK -+#define CHECK_EXCEPTION_STACK() 1 -+#endif -+ -+struct tasklet_struct; -+struct pt_regs; -+struct task_struct; -+struct uart_port; -+ -+#ifdef CONFIG_KGDB_CONSOLE -+extern struct console kgdbcons; -+#endif -+ -+/* To enter the debugger explicitly. */ -+extern void breakpoint(void); -+extern int kgdb_connected; -+extern int kgdb_may_fault; -+extern struct tasklet_struct kgdb_tasklet_breakpoint; -+ -+extern atomic_t kgdb_setting_breakpoint; -+extern atomic_t cpu_doing_single_step; -+extern atomic_t kgdb_sync_softlockup[NR_CPUS]; -+ -+extern struct task_struct *kgdb_usethread, *kgdb_contthread; -+ -+enum kgdb_bptype { -+ bp_breakpoint = '0', -+ bp_hardware_breakpoint, -+ bp_write_watchpoint, -+ bp_read_watchpoint, -+ bp_access_watchpoint -+}; -+ -+enum kgdb_bpstate { -+ bp_none = 0, -+ bp_removed, -+ bp_set, -+ bp_active -+}; -+ -+struct kgdb_bkpt { -+ unsigned long bpt_addr; -+ unsigned char saved_instr[BREAK_INSTR_SIZE]; -+ enum kgdb_bptype type; -+ enum kgdb_bpstate state; -+}; -+ -+/* The maximum number of KGDB I/O modules that can be loaded */ -+#define MAX_KGDB_IO_HANDLERS 3 -+ -+#ifndef MAX_BREAKPOINTS -+#define MAX_BREAKPOINTS 1000 -+#endif -+ -+#define KGDB_HW_BREAKPOINT 1 -+ -+/* Required functions. */ -+/** -+ * regs_to_gdb_regs - Convert ptrace regs to GDB regs -+ * @gdb_regs: A pointer to hold the registers in the order GDB wants. -+ * @regs: The &struct pt_regs of the current process. -+ * -+ * Convert the pt_regs in @regs into the format for registers that -+ * GDB expects, stored in @gdb_regs. -+ */ -+extern void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs); -+ -+/** -+ * sleeping_regs_to_gdb_regs - Convert ptrace regs to GDB regs -+ * @gdb_regs: A pointer to hold the registers in the order GDB wants. -+ * @p: The &struct task_struct of the desired process. -+ * -+ * Convert the register values of the sleeping process in @p to -+ * the format that GDB expects. -+ * This function is called when kgdb does not have access to the -+ * &struct pt_regs and therefore it should fill the gdb registers -+ * @gdb_regs with what has been saved in &struct thread_struct -+ * thread field during switch_to. -+ */ -+extern void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, -+ struct task_struct *p); -+ -+/** -+ * gdb_regs_to_regs - Convert GDB regs to ptrace regs. -+ * @gdb_regs: A pointer to hold the registers we've recieved from GDB. -+ * @regs: A pointer to a &struct pt_regs to hold these values in. -+ * -+ * Convert the GDB regs in @gdb_regs into the pt_regs, and store them -+ * in @regs. -+ */ -+extern void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs); -+ -+/** -+ * kgdb_arch_handle_exception - Handle architecture specific GDB packets. -+ * @vector: The error vector of the exception that happened. -+ * @signo: The signal number of the exception that happened. -+ * @err_code: The error code of the exception that happened. -+ * @remcom_in_buffer: The buffer of the packet we have read. -+ * @remcom_out_buffer: The buffer, of %BUFMAX to write a packet into. -+ * @regs: The &struct pt_regs of the current process. -+ * -+ * This function MUST handle the 'c' and 's' command packets, -+ * as well packets to set / remove a hardware breakpoint, if used. -+ * If there are additional packets which the hardware needs to handle, -+ * they are handled here. The code should return -1 if it wants to -+ * process more packets, and a %0 or %1 if it wants to exit from the -+ * kgdb hook. -+ */ -+extern int kgdb_arch_handle_exception(int vector, int signo, int err_code, -+ char *remcom_in_buffer, -+ char *remcom_out_buffer, -+ struct pt_regs *regs); -+ -+#ifndef JMP_REGS_ALIGNMENT -+#define JMP_REGS_ALIGNMENT -+#endif -+ -+extern unsigned long kgdb_fault_jmp_regs[]; -+ -+/** -+ * kgdb_fault_setjmp - Store state in case we fault. -+ * @curr_context: An array to store state into. -+ * -+ * Certain functions may try and access memory, and in doing so may -+ * cause a fault. When this happens, we trap it, restore state to -+ * this call, and let ourself know that something bad has happened. -+ */ -+extern asmlinkage int kgdb_fault_setjmp(unsigned long *curr_context); -+ -+/** -+ * kgdb_fault_longjmp - Restore state when we have faulted. -+ * @curr_context: The previously stored state. -+ * -+ * When something bad does happen, this function is called to -+ * restore the known good state, and set the return value to 1, so -+ * we know something bad happened. -+ */ -+extern asmlinkage void kgdb_fault_longjmp(unsigned long *curr_context); -+ -+/* Optional functions. */ -+extern int kgdb_arch_init(void); -+extern void kgdb_disable_hw_debug(struct pt_regs *regs); -+extern void kgdb_post_master_code(struct pt_regs *regs, int e_vector, -+ int err_code); -+extern void kgdb_roundup_cpus(unsigned long flags); -+extern int kgdb_set_hw_break(unsigned long addr); -+extern int kgdb_remove_hw_break(unsigned long addr); -+extern void kgdb_remove_all_hw_break(void); -+extern void kgdb_correct_hw_break(void); -+extern void kgdb_shadowinfo(struct pt_regs *regs, char *buffer, -+ unsigned threadid); -+extern struct task_struct *kgdb_get_shadow_thread(struct pt_regs *regs, -+ int threadid); -+extern struct pt_regs *kgdb_shadow_regs(struct pt_regs *regs, int threadid); -+extern int kgdb_validate_break_address(unsigned long addr); -+extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr); -+extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle); -+ -+/** -+ * struct kgdb_arch - Desribe architecture specific values. -+ * @gdb_bpt_instr: The instruction to trigger a breakpoint. -+ * @flags: Flags for the breakpoint, currently just %KGDB_HW_BREAKPOINT. -+ * @shadowth: A value of %1 indicates we shadow information on processes. -+ * @set_breakpoint: Allow an architecture to specify how to set a software -+ * breakpoint. -+ * @remove_breakpoint: Allow an architecture to specify how to remove a -+ * software breakpoint. -+ * @set_hw_breakpoint: Allow an architecture to specify how to set a hardware -+ * breakpoint. -+ * @remove_hw_breakpoint: Allow an architecture to specify how to remove a -+ * hardware breakpoint. -+ * -+ * The @shadowth flag is an option to shadow information not retrievable by -+ * gdb otherwise. This is deprecated in favor of a binutils which supports -+ * CFI macros. -+ */ -+struct kgdb_arch { -+ unsigned char gdb_bpt_instr[BREAK_INSTR_SIZE]; -+ unsigned long flags; -+ unsigned shadowth; -+ int (*set_breakpoint) (unsigned long, char *); -+ int (*remove_breakpoint)(unsigned long, char *); -+ int (*set_hw_breakpoint)(unsigned long, int, enum kgdb_bptype); -+ int (*remove_hw_breakpoint)(unsigned long, int, enum kgdb_bptype); -+}; -+ -+/* Thread reference */ -+typedef unsigned char threadref[8]; -+ -+/** -+ * struct kgdb_io - Desribe the interface for an I/O driver to talk with KGDB. -+ * @read_char: Pointer to a function that will return one char. -+ * @write_char: Pointer to a function that will write one char. -+ * @flush: Pointer to a function that will flush any pending writes. -+ * @init: Pointer to a function that will initialize the device. -+ * @late_init: Pointer to a function that will do any setup that has -+ * other dependencies. -+ * @pre_exception: Pointer to a function that will do any prep work for -+ * the I/O driver. -+ * @post_exception: Pointer to a function that will do any cleanup work -+ * for the I/O driver. -+ * -+ * The @init and @late_init function pointers allow for an I/O driver -+ * such as a serial driver to fully initialize the port with @init and -+ * be called very early, yet safely call request_irq() later in the boot -+ * sequence. -+ * -+ * @init is allowed to return a non-0 return value to indicate failure. -+ * If this is called early on, then KGDB will try again when it would call -+ * @late_init. If it has failed later in boot as well, the user will be -+ * notified. -+ */ -+struct kgdb_io { -+ int (*read_char) (void); -+ void (*write_char) (u8); -+ void (*flush) (void); -+ int (*init) (void); -+ void (*late_init) (void); -+ void (*pre_exception) (void); -+ void (*post_exception) (void); -+}; -+ -+extern struct kgdb_io kgdb_io_ops; -+extern struct kgdb_arch arch_kgdb_ops; -+extern int kgdb_initialized; -+ -+extern int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops); -+extern void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops); -+ -+extern void __init kgdb8250_add_port(int i, struct uart_port *serial_req); -+extern void __init kgdb8250_add_platform_port(int i, struct plat_serial8250_port *serial_req); -+ -+extern int kgdb_hex2long(char **ptr, long *long_val); -+extern char *kgdb_mem2hex(char *mem, char *buf, int count); -+extern char *kgdb_hex2mem(char *buf, char *mem, int count); -+extern int kgdb_get_mem(char *addr, unsigned char *buf, int count); -+extern int kgdb_set_mem(char *addr, unsigned char *buf, int count); -+ -+int kgdb_isremovedbreak(unsigned long addr); -+int kgdb_skipexception(int exception, struct pt_regs *regs); -+ -+extern int kgdb_handle_exception(int ex_vector, int signo, int err_code, -+ struct pt_regs *regs); -+extern void kgdb_nmihook(int cpu, void *regs); -+extern int debugger_step; -+extern atomic_t debugger_active; -+extern struct kgdb_arch *kgdb_ops; -+#else -+/* Stubs for when KGDB is not set. */ -+static const atomic_t debugger_active = ATOMIC_INIT(0); -+#endif /* CONFIG_KGDB */ -+#endif /* _KGDB_H_ */ -+#endif /* __KERNEL__ */ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/linux/module.h linux-2.6.18-53.1.14.kgdb/include/linux/module.h ---- linux-2.6.18-53.1.14/include/linux/module.h 2008-03-06 05:54:41.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/include/linux/module.h 2008-06-10 15:39:15.000000000 +0400 -@@ -229,8 +229,17 @@ enum module_state - MODULE_STATE_LIVE, - MODULE_STATE_COMING, - MODULE_STATE_GOING, -+ MODULE_STATE_GONE, - }; - -+#ifdef CONFIG_KGDB -+#define MAX_SECTNAME 31 -+struct mod_section { -+ void *address; -+ char name[MAX_SECTNAME + 1]; -+}; -+#endif -+ - /* Similar stuff for section attributes. */ - #define MODULE_SECT_NAME_LEN 32 - struct module_sect_attr -@@ -258,6 +267,13 @@ struct module - /* Unique handle for this module */ - char name[MODULE_NAME_LEN]; - -+#ifdef CONFIG_KGDB -+ /* keep kgdb info at the begining so that gdb doesn't have a chance to -+ * miss out any fields */ -+ unsigned long num_sections; -+ struct mod_section *mod_sections; -+#endif -+ - /* Sysfs stuff. */ - struct module_kobject mkobj; - struct module_param_attrs *param_attrs; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/linux/netpoll.h linux-2.6.18-53.1.14.kgdb/include/linux/netpoll.h ---- linux-2.6.18-53.1.14/include/linux/netpoll.h 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/include/linux/netpoll.h 2008-06-10 15:37:49.000000000 +0400 -@@ -17,7 +17,7 @@ struct netpoll; - struct netpoll { - struct net_device *dev; - char dev_name[16], *name; -- void (*rx_hook)(struct netpoll *, int, char *, int); -+ void (*rx_hook)(struct netpoll *, int, char *, int, struct sk_buff *); - void (*drop)(struct sk_buff *skb); - u32 local_ip, remote_ip; - u16 local_port, remote_port; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/include/linux/serial_8250.h linux-2.6.18-53.1.14.kgdb/include/linux/serial_8250.h ---- linux-2.6.18-53.1.14/include/linux/serial_8250.h 2006-09-20 07:42:06.000000000 +0400 -+++ linux-2.6.18-53.1.14.kgdb/include/linux/serial_8250.h 2008-06-10 15:37:43.000000000 +0400 -@@ -56,6 +56,7 @@ struct uart_port; - - int serial8250_register_port(struct uart_port *); - void serial8250_unregister_port(int line); -+void serial8250_unregister_by_port(struct uart_port *port); - void serial8250_suspend_port(int line); - void serial8250_resume_port(int line); - -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/kernel/Makefile linux-2.6.18-53.1.14.kgdb/kernel/Makefile ---- linux-2.6.18-53.1.14/kernel/Makefile 2008-03-06 05:54:50.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/kernel/Makefile 2008-06-10 15:37:25.000000000 +0400 -@@ -42,6 +42,7 @@ obj-$(CONFIG_STOP_MACHINE) += stop_machi - obj-$(CONFIG_AUDIT) += audit.o auditfilter.o - obj-$(CONFIG_AUDITSYSCALL) += auditsc.o audit_tree.o - obj-$(CONFIG_KPROBES) += kprobes.o -+obj-$(CONFIG_KGDB) += kgdb.o kgdbarchlib.o - obj-$(CONFIG_SYSFS) += ksysfs.o - obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o - obj-$(CONFIG_GENERIC_HARDIRQS) += irq/ -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/kernel/kgdb.c linux-2.6.18-53.1.14.kgdb/kernel/kgdb.c ---- linux-2.6.18-53.1.14/kernel/kgdb.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/kernel/kgdb.c 2008-06-10 15:39:21.000000000 +0400 -@@ -0,0 +1,1778 @@ -+/* -+ * kernel/kgdb.c -+ * -+ * Maintainer: Tom Rini -+ * -+ * Copyright (C) 2000-2001 VERITAS Software Corporation. -+ * Copyright (C) 2002-2004 Timesys Corporation -+ * Copyright (C) 2003-2004 Amit S. Kale -+ * Copyright (C) 2004 Pavel Machek -+ * Copyright (C) 2004-2005 Tom Rini -+ * Copyright (C) 2004-2006 LinSysSoft Technologies Pvt. Ltd. -+ * Copyright (C) 2005 Wind River Systems, Inc. -+ * -+ * Contributors at various stages not listed above: -+ * Jason Wessel ( jason.wessel@windriver.com ) -+ * George Anzinger -+ * Anurekh Saxena (anurekh.saxena@timesys.com) -+ * Lake Stevens Instrument Division (Glenn Engel) -+ * Jim Kingdon, Cygnus Support. -+ * -+ * Original KGDB stub: David Grothe , -+ * Tigran Aivazian -+ * -+ * This file is licensed under the terms of the GNU General Public License -+ * version 2. This program is licensed "as is" without any warranty of any -+ * kind, whether express or implied. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+extern int pid_max; -+/* How many times to count all of the waiting CPUs */ -+#define ROUNDUP_WAIT 640000 /* Arbitrary, increase if needed. */ -+#define BUF_THREAD_ID_SIZE 16 -+ -+/* -+ * kgdb_initialized with a value of 1 indicates that kgdb is setup and is -+ * all ready to serve breakpoints and other kernel exceptions. A value of -+ * -1 indicates that we have tried to initialize early, and need to try -+ * again later. -+ */ -+int kgdb_initialized; -+/* Is a host GDB connected to us? */ -+int kgdb_connected; -+/* Could we be about to try and access a bad memory location? If so we -+ * also need to flag this has happend. */ -+int kgdb_may_fault; -+/* All the KGDB handlers are installed */ -+int kgdb_from_module_registered = 0; -+ -+/* We provide a kgdb_io_ops structure that may be overriden. */ -+struct kgdb_io __attribute__ ((weak)) kgdb_io_ops; -+ -+static struct kgdb_io kgdb_io_ops_prev[MAX_KGDB_IO_HANDLERS]; -+static int kgdb_io_handler_cnt = 0; -+ -+/* Export the following symbols for use with kernel modules */ -+EXPORT_SYMBOL(kgdb_io_ops); -+EXPORT_SYMBOL(kgdb_tasklet_breakpoint); -+EXPORT_SYMBOL(kgdb_connected); -+EXPORT_SYMBOL(kgdb_register_io_module); -+EXPORT_SYMBOL(kgdb_unregister_io_module); -+EXPORT_SYMBOL(debugger_active); -+ -+/* -+ * Holds information about breakpoints in a kernel. These breakpoints are -+ * added and removed by gdb. -+ */ -+struct kgdb_bkpt kgdb_break[MAX_BREAKPOINTS]; -+ -+static const char hexchars[] = "0123456789abcdef"; -+ -+static spinlock_t slavecpulocks[NR_CPUS]; -+static atomic_t procindebug[NR_CPUS]; -+atomic_t kgdb_setting_breakpoint; -+EXPORT_SYMBOL(kgdb_setting_breakpoint); -+struct task_struct *kgdb_usethread, *kgdb_contthread; -+ -+int debugger_step; -+atomic_t debugger_active; -+ -+/* Our I/O buffers. */ -+static char remcom_in_buffer[BUFMAX]; -+static char remcom_out_buffer[BUFMAX]; -+/* Storage for the registers, in GDB format. */ -+static unsigned long gdb_regs[(NUMREGBYTES + sizeof(unsigned long) - 1) / -+ sizeof(unsigned long)]; -+/* Storage of registers for handling a fault. */ -+unsigned long kgdb_fault_jmp_regs[NUMCRITREGBYTES / sizeof(unsigned long)] -+ JMP_REGS_ALIGNMENT; -+static int kgdb_notify_reboot(struct notifier_block *this, -+ unsigned long code ,void *x); -+struct debuggerinfo_struct { -+ void *debuggerinfo; -+ struct task_struct *task; -+} kgdb_info[NR_CPUS]; -+ -+/* to keep track of the CPU which is doing the single stepping*/ -+atomic_t cpu_doing_single_step = ATOMIC_INIT(-1); -+ -+atomic_t kgdb_sync_softlockup[NR_CPUS] = {ATOMIC_INIT(0)}; -+ -+/* reboot notifier block */ -+static struct notifier_block kgdb_reboot_notifier = { -+ .notifier_call = kgdb_notify_reboot, -+ .next = NULL, -+ .priority = INT_MAX, -+}; -+ -+static int hex(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 $# */ -+static void get_packet(char *buffer) -+{ -+ unsigned char checksum; -+ unsigned char xmitcsum; -+ int count; -+ char ch; -+ if (!kgdb_io_ops.read_char) -+ return; -+ do { -+ /* Spin and wait around for the start character, ignore all -+ * other characters */ -+ while ((ch = (kgdb_io_ops.read_char())) != '$') ; -+ kgdb_connected = 1; -+ checksum = 0; -+ xmitcsum = -1; -+ -+ count = 0; -+ -+ /* now, read until a # or end of buffer is found */ -+ while (count < (BUFMAX - 1)) { -+ ch = kgdb_io_ops.read_char(); -+ if (ch == '#') -+ break; -+ checksum = checksum + ch; -+ buffer[count] = ch; -+ count = count + 1; -+ } -+ buffer[count] = 0; -+ -+ if (ch == '#') { -+ xmitcsum = hex(kgdb_io_ops.read_char()) << 4; -+ xmitcsum += hex(kgdb_io_ops.read_char()); -+ -+ if (checksum != xmitcsum) -+ /* failed checksum */ -+ kgdb_io_ops.write_char('-'); -+ else -+ /* successful transfer */ -+ kgdb_io_ops.write_char('+'); -+ if (kgdb_io_ops.flush) -+ kgdb_io_ops.flush(); -+ } -+ } while (checksum != xmitcsum); -+} -+ -+/* -+ * Send the packet in buffer. -+ * Check for gdb connection if asked for. -+ */ -+static void put_packet(char *buffer) -+{ -+ unsigned char checksum; -+ int count; -+ char ch; -+ -+ if (!kgdb_io_ops.write_char) -+ return; -+ /* $#. */ -+ while (1) { -+ kgdb_io_ops.write_char('$'); -+ checksum = 0; -+ count = 0; -+ -+ while ((ch = buffer[count])) { -+ kgdb_io_ops.write_char(ch); -+ checksum += ch; -+ count++; -+ } -+ -+ kgdb_io_ops.write_char('#'); -+ kgdb_io_ops.write_char(hexchars[checksum >> 4]); -+ kgdb_io_ops.write_char(hexchars[checksum % 16]); -+ if (kgdb_io_ops.flush) -+ kgdb_io_ops.flush(); -+ -+ /* Now see what we get in reply. */ -+ ch = kgdb_io_ops.read_char(); -+ -+ if (ch == 3) -+ ch = kgdb_io_ops.read_char(); -+ -+ /* If we get an ACK, we are done. */ -+ if (ch == '+') -+ return; -+ -+ /* If we get the start of another packet, this means -+ * that GDB is attempting to reconnect. We will NAK -+ * the packet being sent, and stop trying to send this -+ * packet. */ -+ if (ch == '$') { -+ kgdb_io_ops.write_char('-'); -+ if (kgdb_io_ops.flush) -+ kgdb_io_ops.flush(); -+ return; -+ } -+ } -+} -+ -+/* -+ * convert the memory pointed to by mem into hex, placing result in buf -+ * return a pointer to the last char put in buf (null). May return an error. -+ */ -+char *kgdb_mem2hex(char *mem, char *buf, int count) -+{ -+ kgdb_may_fault = 1; -+ if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) { -+ kgdb_may_fault = 0; -+ return ERR_PTR(-EINVAL); -+ } -+ /* Accessing some registers in a single load instruction is -+ * required to avoid bad side effects for some I/O registers. -+ */ -+ if ((count == 2) && (((long)mem & 1) == 0)) { -+ unsigned short tmp_s = *(unsigned short *)mem; -+ mem += 2; -+#ifdef __BIG_ENDIAN -+ *buf++ = hexchars[(tmp_s >> 12) & 0xf]; -+ *buf++ = hexchars[(tmp_s >> 8) & 0xf]; -+ *buf++ = hexchars[(tmp_s >> 4) & 0xf]; -+ *buf++ = hexchars[tmp_s & 0xf]; -+#else -+ *buf++ = hexchars[(tmp_s >> 4) & 0xf]; -+ *buf++ = hexchars[tmp_s & 0xf]; -+ *buf++ = hexchars[(tmp_s >> 12) & 0xf]; -+ *buf++ = hexchars[(tmp_s >> 8) & 0xf]; -+#endif -+ } else if ((count == 4) && (((long)mem & 3) == 0)) { -+ unsigned long tmp_l = *(unsigned int *)mem; -+ mem += 4; -+#ifdef __BIG_ENDIAN -+ *buf++ = hexchars[(tmp_l >> 28) & 0xf]; -+ *buf++ = hexchars[(tmp_l >> 24) & 0xf]; -+ *buf++ = hexchars[(tmp_l >> 20) & 0xf]; -+ *buf++ = hexchars[(tmp_l >> 16) & 0xf]; -+ *buf++ = hexchars[(tmp_l >> 12) & 0xf]; -+ *buf++ = hexchars[(tmp_l >> 8) & 0xf]; -+ *buf++ = hexchars[(tmp_l >> 4) & 0xf]; -+ *buf++ = hexchars[tmp_l & 0xf]; -+#else -+ *buf++ = hexchars[(tmp_l >> 4) & 0xf]; -+ *buf++ = hexchars[tmp_l & 0xf]; -+ *buf++ = hexchars[(tmp_l >> 12) & 0xf]; -+ *buf++ = hexchars[(tmp_l >> 8) & 0xf]; -+ *buf++ = hexchars[(tmp_l >> 20) & 0xf]; -+ *buf++ = hexchars[(tmp_l >> 16) & 0xf]; -+ *buf++ = hexchars[(tmp_l >> 28) & 0xf]; -+ *buf++ = hexchars[(tmp_l >> 24) & 0xf]; -+#endif -+#ifdef CONFIG_64BIT -+ } else if ((count == 8) && (((long)mem & 7) == 0)) { -+ unsigned long long tmp_ll = *(unsigned long long *)mem; -+ mem += 8; -+#ifdef __BIG_ENDIAN -+ *buf++ = hexchars[(tmp_ll >> 60) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 56) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 52) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 48) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 44) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 40) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 36) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 32) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 28) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 24) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 20) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 16) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 12) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 8) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 4) & 0xf]; -+ *buf++ = hexchars[tmp_ll & 0xf]; -+#else -+ *buf++ = hexchars[(tmp_ll >> 4) & 0xf]; -+ *buf++ = hexchars[tmp_ll & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 12) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 8) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 20) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 16) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 28) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 24) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 36) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 32) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 44) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 40) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 52) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 48) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 60) & 0xf]; -+ *buf++ = hexchars[(tmp_ll >> 56) & 0xf]; -+#endif -+#endif -+ } else { -+ while (count-- > 0) { -+ unsigned char ch = *mem++; -+ *buf++ = hexchars[ch >> 4]; -+ *buf++ = hexchars[ch & 0xf]; -+ } -+ } -+ kgdb_may_fault = 0; -+ *buf = 0; -+ return (buf); -+} -+ -+/* -+ * Copy the binary array pointed to by buf into mem. Fix $, #, and -+ * 0x7d escaped with 0x7d. Return a pointer to the character after -+ * the last byte written. -+ */ -+static char *kgdb_ebin2mem(char *buf, char *mem, int count) -+{ -+ kgdb_may_fault = 1; -+ if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) { -+ kgdb_may_fault = 0; -+ return ERR_PTR(-EINVAL); -+ } -+ for (; count > 0; count--, buf++) { -+ if (*buf == 0x7d) -+ *mem++ = *(++buf) ^ 0x20; -+ else -+ *mem++ = *buf; -+ } -+ kgdb_may_fault = 0; -+ return mem; -+} -+ -+/* -+ * 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 -+ * May return an error. -+ */ -+char *kgdb_hex2mem(char *buf, char *mem, int count) -+{ -+ kgdb_may_fault = 1; -+ if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) { -+ kgdb_may_fault = 0; -+ return ERR_PTR(-EINVAL); -+ } -+ if ((count == 2) && (((long)mem & 1) == 0)) { -+ unsigned short tmp_s = 0; -+#ifdef __BIG_ENDIAN -+ tmp_s |= hex(*buf++) << 12; -+ tmp_s |= hex(*buf++) << 8; -+ tmp_s |= hex(*buf++) << 4; -+ tmp_s |= hex(*buf++); -+#else -+ tmp_s |= hex(*buf++) << 4; -+ tmp_s |= hex(*buf++); -+ tmp_s |= hex(*buf++) << 12; -+ tmp_s |= hex(*buf++) << 8; -+#endif -+ *(unsigned short *)mem = tmp_s; -+ mem += 2; -+ } else if ((count == 4) && (((long)mem & 3) == 0)) { -+ unsigned long tmp_l = 0; -+#ifdef __BIG_ENDIAN -+ tmp_l |= hex(*buf++) << 28; -+ tmp_l |= hex(*buf++) << 24; -+ tmp_l |= hex(*buf++) << 20; -+ tmp_l |= hex(*buf++) << 16; -+ tmp_l |= hex(*buf++) << 12; -+ tmp_l |= hex(*buf++) << 8; -+ tmp_l |= hex(*buf++) << 4; -+ tmp_l |= hex(*buf++); -+#else -+ tmp_l |= hex(*buf++) << 4; -+ tmp_l |= hex(*buf++); -+ tmp_l |= hex(*buf++) << 12; -+ tmp_l |= hex(*buf++) << 8; -+ tmp_l |= hex(*buf++) << 20; -+ tmp_l |= hex(*buf++) << 16; -+ tmp_l |= hex(*buf++) << 28; -+ tmp_l |= hex(*buf++) << 24; -+#endif -+ *(unsigned long *)mem = tmp_l; -+ mem += 4; -+ } else { -+ int i; -+ for (i = 0; i < count; i++) { -+ unsigned char ch = hex(*buf++) << 4; -+ ch |= hex(*buf++); -+ *mem++ = ch; -+ } -+ } -+ kgdb_may_fault = 0; -+ return (mem); -+} -+ -+/* -+ * While we find nice hex chars, build a long_val. -+ * Return number of chars processed. -+ */ -+int kgdb_hex2long(char **ptr, long *long_val) -+{ -+ int hex_val, num = 0; -+ -+ *long_val = 0; -+ -+ while (**ptr) { -+ hex_val = hex(**ptr); -+ if (hex_val >= 0) { -+ *long_val = (*long_val << 4) | hex_val; -+ num++; -+ } else -+ break; -+ -+ (*ptr)++; -+ } -+ -+ return (num); -+} -+ -+/* Write memory due to an 'M' or 'X' packet. */ -+static char *write_mem_msg(int binary) -+{ -+ char *ptr = &remcom_in_buffer[1]; -+ unsigned long addr, length; -+ -+ if (kgdb_hex2long(&ptr, &addr) > 0 && *(ptr++) == ',' && -+ kgdb_hex2long(&ptr, &length) > 0 && *(ptr++) == ':') { -+ if (binary) -+ ptr = kgdb_ebin2mem(ptr, (char *)addr, length); -+ else -+ ptr = kgdb_hex2mem(ptr, (char *)addr, length); -+ if (CACHE_FLUSH_IS_SAFE) -+ flush_icache_range(addr, addr + length + 1); -+ if (IS_ERR(ptr)) -+ return ptr; -+ return NULL; -+ } -+ -+ return ERR_PTR(-EINVAL); -+} -+ -+static inline char *pack_hex_byte(char *pkt, int byte) -+{ -+ *pkt++ = hexchars[(byte >> 4) & 0xf]; -+ *pkt++ = hexchars[(byte & 0xf)]; -+ return pkt; -+} -+ -+static inline void error_packet(char *pkt, int error) -+{ -+ error = -error; -+ pkt[0] = 'E'; -+ pkt[1] = hexchars[(error / 10)]; -+ pkt[2] = hexchars[(error % 10)]; -+ pkt[3] = '\0'; -+} -+ -+static char *pack_threadid(char *pkt, threadref * id) -+{ -+ char *limit; -+ unsigned char *altid; -+ -+ altid = (unsigned char *)id; -+ limit = pkt + BUF_THREAD_ID_SIZE; -+ while (pkt < limit) -+ pkt = pack_hex_byte(pkt, *altid++); -+ -+ return pkt; -+} -+ -+void int_to_threadref(threadref * id, int value) -+{ -+ unsigned char *scan; -+ int i = 4; -+ -+ scan = (unsigned char *)id; -+ while (i--) -+ *scan++ = 0; -+ *scan++ = (value >> 24) & 0xff; -+ *scan++ = (value >> 16) & 0xff; -+ *scan++ = (value >> 8) & 0xff; -+ *scan++ = (value & 0xff); -+} -+ -+static struct task_struct *getthread(struct pt_regs *regs, int tid) -+{ -+ if (last_pid == 0) -+ return current; -+ -+ if (num_online_cpus() && -+ (tid >= pid_max + num_online_cpus() + kgdb_ops->shadowth)) -+ return NULL; -+ -+ if (kgdb_ops->shadowth && (tid >= pid_max + num_online_cpus())) -+ return kgdb_get_shadow_thread(regs, tid - pid_max - -+ num_online_cpus()); -+ -+ if (tid >= pid_max) -+ return idle_task(tid - pid_max); -+ -+ if (!tid) -+ return NULL; -+ -+ return find_task_by_pid(tid); -+} -+ -+#ifdef CONFIG_SMP -+static void kgdb_wait(struct pt_regs *regs) -+{ -+ unsigned long flags; -+ int processor; -+ -+ local_irq_save(flags); -+ processor = smp_processor_id(); -+ kgdb_info[processor].debuggerinfo = regs; -+ kgdb_info[processor].task = current; -+ atomic_set(&procindebug[processor], 1); -+ atomic_set(&kgdb_sync_softlockup[smp_processor_id()], 1); -+ -+ /* Wait till master processor goes completely into the debugger. -+ * FIXME: this looks racy */ -+ while (!atomic_read(&procindebug[atomic_read(&debugger_active) - 1])) { -+ int i = 10; /* an arbitrary number */ -+ -+ while (--i) -+ cpu_relax(); -+ } -+ -+ /* Wait till master processor is done with debugging */ -+ spin_lock(&slavecpulocks[processor]); -+ -+ /* This has been taken from x86 kgdb implementation and -+ * will be needed by architectures that have SMP support -+ */ -+ kgdb_correct_hw_break(); -+ -+ kgdb_info[processor].debuggerinfo = NULL; -+ kgdb_info[processor].task = NULL; -+ -+ /* Signal the master processor that we are done */ -+ atomic_set(&procindebug[processor], 0); -+ spin_unlock(&slavecpulocks[processor]); -+ local_irq_restore(flags); -+} -+#endif -+ -+int kgdb_get_mem(char *addr, unsigned char *buf, int count) -+{ -+ kgdb_may_fault = 1; -+ if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) { -+ kgdb_may_fault = 0; -+ return -EINVAL; -+ } -+ while (count) { -+ if ((unsigned long)addr < TASK_SIZE) -+ return -EINVAL; -+ *buf++ = *addr++; -+ count--; -+ } -+ kgdb_may_fault = 0; -+ return 0; -+} -+ -+int kgdb_set_mem(char *addr, unsigned char *buf, int count) -+{ -+ kgdb_may_fault = 1; -+ if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) { -+ kgdb_may_fault = 0; -+ return -EINVAL; -+ } -+ while (count) { -+ if ((unsigned long)addr < TASK_SIZE) -+ return -EINVAL; -+ *addr++ = *buf++; -+ count--; -+ } -+ kgdb_may_fault = 0; -+ return 0; -+} -+int kgdb_activate_sw_breakpoints(void) -+{ -+ int i; -+ int error = 0; -+ unsigned long addr; -+ for (i = 0; i < MAX_BREAKPOINTS; i++) { -+ if (kgdb_break[i].state != bp_set) -+ continue; -+ addr = kgdb_break[i].bpt_addr; -+ if ((error = kgdb_arch_set_breakpoint(addr, -+ kgdb_break[i].saved_instr))) -+ return error; -+ -+ if (CACHE_FLUSH_IS_SAFE) { -+ if (current->mm && addr < TASK_SIZE) -+ flush_cache_range(current->mm->mmap_cache, -+ addr, addr + BREAK_INSTR_SIZE); -+ else -+ flush_icache_range(addr, addr + -+ BREAK_INSTR_SIZE); -+ } -+ -+ kgdb_break[i].state = bp_active; -+ } -+ return 0; -+} -+ -+static int kgdb_set_sw_break(unsigned long addr) -+{ -+ int i, breakno = -1; -+ int error = 0; -+ if ((error = kgdb_validate_break_address(addr)) < 0) -+ return error; -+ for (i = 0; i < MAX_BREAKPOINTS; i++) { -+ if ((kgdb_break[i].state == bp_set) && -+ (kgdb_break[i].bpt_addr == addr)) -+ return -EEXIST; -+ } -+ for (i = 0; i < MAX_BREAKPOINTS; i++) { -+ if (kgdb_break[i].state == bp_removed && -+ kgdb_break[i].bpt_addr == addr) { -+ breakno = i; -+ break; -+ } -+ } -+ -+ if (breakno == -1) { -+ for (i = 0; i < MAX_BREAKPOINTS; i++) { -+ if (kgdb_break[i].state == bp_none) { -+ breakno = i; -+ break; -+ } -+ } -+ } -+ if (breakno == -1) -+ return -E2BIG; -+ -+ kgdb_break[breakno].state = bp_set; -+ kgdb_break[breakno].type = bp_breakpoint; -+ kgdb_break[breakno].bpt_addr = addr; -+ -+ return 0; -+} -+ -+int kgdb_deactivate_sw_breakpoints(void) -+{ -+ int i; -+ int error = 0; -+ unsigned long addr; -+ for (i = 0; i < MAX_BREAKPOINTS; i++) { -+ if (kgdb_break[i].state != bp_active) -+ continue; -+ addr = kgdb_break[i].bpt_addr; -+ if ((error = kgdb_arch_remove_breakpoint(addr, -+ kgdb_break[i].saved_instr))) -+ return error; -+ -+ if (CACHE_FLUSH_IS_SAFE && current->mm && -+ addr < TASK_SIZE) -+ flush_cache_range(current->mm->mmap_cache, -+ addr, addr + BREAK_INSTR_SIZE); -+ else if (CACHE_FLUSH_IS_SAFE) -+ flush_icache_range(addr, -+ addr + BREAK_INSTR_SIZE); -+ kgdb_break[i].state = bp_set; -+ } -+ return 0; -+} -+ -+static int kgdb_remove_sw_break(unsigned long addr) -+{ -+ int i; -+ -+ for (i = 0; i < MAX_BREAKPOINTS; i++) { -+ if ((kgdb_break[i].state == bp_set) && -+ (kgdb_break[i].bpt_addr == addr)) { -+ kgdb_break[i].state = bp_removed; -+ return 0; -+ } -+ } -+ return -ENOENT; -+} -+ -+int kgdb_isremovedbreak(unsigned long addr) -+{ -+ int i; -+ for (i = 0; i < MAX_BREAKPOINTS; i++) { -+ if ((kgdb_break[i].state == bp_removed) && -+ (kgdb_break[i].bpt_addr == addr)) { -+ return 1; -+ } -+ } -+ return 0; -+} -+ -+int remove_all_break(void) -+{ -+ int i; -+ int error; -+ unsigned long addr; -+ -+ /* Clear memory breakpoints. */ -+ for (i = 0; i < MAX_BREAKPOINTS; i++) { -+ if (kgdb_break[i].state != bp_set) -+ continue; -+ addr = kgdb_break[i].bpt_addr; -+ if ((error = kgdb_arch_remove_breakpoint(addr, -+ kgdb_break[i].saved_instr))) -+ return error; -+ kgdb_break[i].state = bp_removed; -+ } -+ -+ /* Clear hardware breakpoints. */ -+ kgdb_remove_all_hw_break(); -+ -+ return 0; -+} -+ -+static inline int shadow_pid(int realpid) -+{ -+ if (realpid) { -+ return realpid; -+ } -+ return pid_max + smp_processor_id(); -+} -+ -+static char gdbmsgbuf[BUFMAX + 1]; -+static void kgdb_msg_write(const char *s, int len) -+{ -+ int i; -+ int wcount; -+ char *bufptr; -+ -+ /* 'O'utput */ -+ gdbmsgbuf[0] = 'O'; -+ -+ /* Fill and send buffers... */ -+ while (len > 0) { -+ bufptr = gdbmsgbuf + 1; -+ -+ /* Calculate how many this time */ -+ if ((len << 1) > (BUFMAX - 2)) -+ wcount = (BUFMAX - 2) >> 1; -+ else -+ wcount = len; -+ -+ /* Pack in hex chars */ -+ for (i = 0; i < wcount; i++) -+ bufptr = pack_hex_byte(bufptr, s[i]); -+ *bufptr = '\0'; -+ -+ /* Move up */ -+ s += wcount; -+ len -= wcount; -+ -+ /* Write packet */ -+ put_packet(gdbmsgbuf); -+ } -+} -+ -+/* -+ * This function does all command procesing for interfacing to gdb. -+ * -+ * Locking hierarchy: -+ * interface locks, if any (begin_session) -+ * kgdb lock (debugger_active) -+ * -+ * Note that since we can be in here prior to our cpumask being filled -+ * out, we err on the side of caution and loop over NR_CPUS instead -+ * of a for_each_online_cpu. -+ * -+ */ -+int kgdb_handle_exception(int ex_vector, int signo, int err_code, -+ struct pt_regs *linux_regs) -+{ -+ unsigned long length, addr; -+ char *ptr; -+ unsigned long flags; -+ unsigned i; -+ long threadid; -+ threadref thref; -+ struct task_struct *thread = NULL; -+ unsigned procid; -+ int numshadowth = num_online_cpus() + kgdb_ops->shadowth; -+ long kgdb_usethreadid = 0; -+ int error = 0, all_cpus_synced = 0; -+ struct pt_regs *shadowregs; -+ int processor = smp_processor_id(); -+ void *local_debuggerinfo; -+ -+ /* Panic on recursive debugger calls. */ -+ if (atomic_read(&debugger_active) == smp_processor_id() + 1) -+ return 0; -+ -+ acquirelock: -+ -+ /* Call the I/O drivers pre_exception routine if the I/O -+ * driver defined one -+ */ -+ if (kgdb_io_ops.pre_exception) -+ kgdb_io_ops.pre_exception(); -+ -+ /* -+ * Interrupts will be restored by the 'trap return' code, except when -+ * single stepping. -+ */ -+ local_irq_save(flags); -+ -+ /* Hold debugger_active */ -+ procid = smp_processor_id(); -+ -+ while (cmpxchg(&atomic_read(&debugger_active), 0, (procid + 1)) != 0) { -+ int i = 25; /* an arbitrary number */ -+ -+ while (--i) -+ cpu_relax(); -+ -+ if (atomic_read(&cpu_doing_single_step) != -1 && -+ atomic_read(&cpu_doing_single_step) != procid) -+ udelay(1); -+ } -+ -+ atomic_set(&kgdb_sync_softlockup[smp_processor_id()], 1); -+ -+ /* -+ * Don't enter if the last instance of the exception handler wanted to -+ * come into the debugger again. -+ */ -+ if (atomic_read(&cpu_doing_single_step) != -1 && -+ atomic_read(&cpu_doing_single_step) != procid) { -+ atomic_set(&debugger_active, 0); -+ local_irq_restore(flags); -+ goto acquirelock; -+ } -+ -+ /* -+ * Don't enter if we have hit a removed breakpoint. -+ */ -+ if (kgdb_skipexception(ex_vector, linux_regs)) -+ goto kgdb_restore; -+ -+ kgdb_info[processor].debuggerinfo = linux_regs; -+ kgdb_info[processor].task = current; -+ -+ kgdb_disable_hw_debug(linux_regs); -+ -+ if (!debugger_step || !kgdb_contthread) -+ for (i = 0; i < NR_CPUS; i++) -+ spin_lock(&slavecpulocks[i]); -+ -+ /* Make sure we get the other CPUs */ -+ if (!debugger_step || !kgdb_contthread) -+ kgdb_roundup_cpus(flags); -+ -+ /* spin_lock code is good enough as a barrier so we don't -+ * need one here */ -+ atomic_set(&procindebug[processor], 1); -+ -+ /* Wait a reasonable time for the other CPUs to be notified and -+ * be waiting for us. Very early on this could be imperfect -+ * as num_online_cpus() could be 0.*/ -+ for (i = 0; i < ROUNDUP_WAIT; i++) { -+ int cpu, num = 0; -+ for (cpu = 0; cpu < NR_CPUS; cpu++) { -+ if (atomic_read(&procindebug[cpu])) -+ num++; -+ } -+ if (num >= num_online_cpus()) { -+ all_cpus_synced = 1; -+ break; -+ } -+ } -+ -+ /* Clear the out buffer. */ -+ memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer)); -+ -+ /* Master processor is completely in the debugger */ -+ kgdb_post_master_code(linux_regs, ex_vector, err_code); -+ kgdb_deactivate_sw_breakpoints(); -+ debugger_step = 0; -+ kgdb_contthread = NULL; -+ -+ if (kgdb_connected) { -+ /* If we're still unable to roundup all of the CPUs, -+ * send an 'O' packet informing the user again. */ -+ if (!all_cpus_synced) -+ kgdb_msg_write("Not all CPUs have been synced for " -+ "KGDB\n", 39); -+ /* Reply to host that an exception has occurred */ -+ ptr = remcom_out_buffer; -+ *ptr++ = 'T'; -+ *ptr++ = hexchars[(signo >> 4) % 16]; -+ *ptr++ = hexchars[signo % 16]; -+ ptr += strlen(strcpy(ptr, "thread:")); -+ int_to_threadref(&thref, shadow_pid(current->pid)); -+ ptr = pack_threadid(ptr, &thref); -+ *ptr++ = ';'; -+ -+ put_packet(remcom_out_buffer); -+ } -+ -+ kgdb_usethread = kgdb_info[processor].task; -+ kgdb_usethreadid = shadow_pid(kgdb_info[processor].task->pid); -+ -+ while (kgdb_io_ops.read_char) { -+ char *bpt_type; -+ error = 0; -+ -+ /* Clear the out buffer. */ -+ memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer)); -+ -+ get_packet(remcom_in_buffer); -+ -+ switch (remcom_in_buffer[0]) { -+ case '?': -+ /* We know that this packet is only sent -+ * during initial connect. So to be safe, -+ * we clear out our breakpoints now incase -+ * GDB is reconnecting. */ -+ remove_all_break(); -+ /* Also, if we haven't been able to roundup all -+ * CPUs, send an 'O' packet informing the user -+ * as much. Only need to do this once. */ -+ if (!all_cpus_synced) -+ kgdb_msg_write("Not all CPUs have been " -+ "synced for KGDB\n", 39); -+ remcom_out_buffer[0] = 'S'; -+ remcom_out_buffer[1] = hexchars[signo >> 4]; -+ remcom_out_buffer[2] = hexchars[signo % 16]; -+ break; -+ -+ case 'g': /* return the value of the CPU registers */ -+ thread = kgdb_usethread; -+ -+ if (!thread) { -+ thread = kgdb_info[processor].task; -+ local_debuggerinfo = -+ kgdb_info[processor].debuggerinfo; -+ } else { -+ local_debuggerinfo = NULL; -+ for (i = 0; i < NR_CPUS; i++) { -+ /* Try to find the task on some other -+ * or possibly this node if we do not -+ * find the matching task then we try -+ * to approximate the results. -+ */ -+ if (thread == kgdb_info[i].task) -+ local_debuggerinfo = -+ kgdb_info[i].debuggerinfo; -+ } -+ } -+ -+ /* All threads that don't have debuggerinfo should be -+ * in __schedule() sleeping, since all other CPUs -+ * are in kgdb_wait, and thus have debuggerinfo. */ -+ if (kgdb_ops->shadowth && -+ kgdb_usethreadid >= pid_max + num_online_cpus()) { -+ shadowregs = kgdb_shadow_regs(linux_regs, -+ kgdb_usethreadid - -+ pid_max - -+ num_online_cpus -+ ()); -+ if (!shadowregs) { -+ error_packet(remcom_out_buffer, -+ -EINVAL); -+ break; -+ } -+ regs_to_gdb_regs(gdb_regs, shadowregs); -+ } else if (local_debuggerinfo) -+ regs_to_gdb_regs(gdb_regs, local_debuggerinfo); -+ else { -+ /* Pull stuff saved during -+ * switch_to; nothing else is -+ * accessible (or even particularly relevant). -+ * This should be enough for a stack trace. */ -+ sleeping_thread_to_gdb_regs(gdb_regs, thread); -+ } -+ kgdb_mem2hex((char *)gdb_regs, remcom_out_buffer, -+ NUMREGBYTES); -+ break; -+ -+ /* set the value of the CPU registers - return OK */ -+ case 'G': -+ kgdb_hex2mem(&remcom_in_buffer[1], (char *)gdb_regs, -+ NUMREGBYTES); -+ -+ if (kgdb_usethread && kgdb_usethread != current) -+ error_packet(remcom_out_buffer, -EINVAL); -+ else { -+ gdb_regs_to_regs(gdb_regs, linux_regs); -+ strcpy(remcom_out_buffer, "OK"); -+ } -+ break; -+ -+ /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ -+ case 'm': -+ ptr = &remcom_in_buffer[1]; -+ if (kgdb_hex2long(&ptr, &addr) > 0 && *ptr++ == ',' && -+ kgdb_hex2long(&ptr, &length) > 0) { -+ if (IS_ERR(ptr = kgdb_mem2hex((char *)addr, -+ remcom_out_buffer, -+ length))) -+ error_packet(remcom_out_buffer, -+ PTR_ERR(ptr)); -+ } else -+ error_packet(remcom_out_buffer, -EINVAL); -+ break; -+ -+ /* MAA..AA,LLLL: Write LLLL bytes at address AA..AA */ -+ case 'M': -+ if (IS_ERR(ptr = write_mem_msg(0))) -+ error_packet(remcom_out_buffer, PTR_ERR(ptr)); -+ else -+ strcpy(remcom_out_buffer, "OK"); -+ break; -+ /* XAA..AA,LLLL: Write LLLL bytes at address AA..AA */ -+ case 'X': -+ if (IS_ERR(ptr = write_mem_msg(1))) -+ error_packet(remcom_out_buffer, PTR_ERR(ptr)); -+ else -+ strcpy(remcom_out_buffer, "OK"); -+ break; -+ -+ /* kill or detach. KGDB should treat this like a -+ * continue. -+ */ -+ case 'D': -+ if ((error = remove_all_break()) < 0) { -+ error_packet(remcom_out_buffer, error); -+ } else { -+ strcpy(remcom_out_buffer, "OK"); -+ kgdb_connected = 0; -+ } -+ put_packet(remcom_out_buffer); -+ goto default_handle; -+ -+ case 'k': -+ /* Don't care about error from remove_all_break */ -+ remove_all_break(); -+ kgdb_connected = 0; -+ goto default_handle; -+ -+ /* Reboot */ -+ case 'R': -+ /* For now, only honor R0 */ -+ if (strcmp(remcom_in_buffer, "R0") == 0) { -+ printk(KERN_CRIT "Executing reboot\n"); -+ strcpy(remcom_out_buffer, "OK"); -+ put_packet(remcom_out_buffer); -+ emergency_sync(); -+ /* Execution should not return from -+ * machine_restart() -+ */ -+ machine_restart(NULL); -+ kgdb_connected = 0; -+ goto default_handle; -+ } -+ -+ /* query */ -+ case 'q': -+ switch (remcom_in_buffer[1]) { -+ case 's': -+ case 'f': -+ if (memcmp(remcom_in_buffer + 2, "ThreadInfo", -+ 10)) { -+ error_packet(remcom_out_buffer, -+ -EINVAL); -+ break; -+ } -+ -+ /* -+ * If we have not yet completed in -+ * pidhash_init() there isn't much we -+ * can give back. -+ */ -+ if (last_pid == 0) { -+ if (remcom_in_buffer[1] == 'f') -+ strcpy(remcom_out_buffer, -+ "m0000000000000001"); -+ break; -+ } -+ -+ if (remcom_in_buffer[1] == 'f') { -+ threadid = 1; -+ } -+ remcom_out_buffer[0] = 'm'; -+ ptr = remcom_out_buffer + 1; -+ for (i = 0; i < 17 && threadid < pid_max + -+ numshadowth; threadid++) { -+ thread = getthread(linux_regs, -+ threadid); -+ if (thread) { -+ int_to_threadref(&thref, -+ threadid); -+ pack_threadid(ptr, &thref); -+ ptr += 16; -+ *(ptr++) = ','; -+ i++; -+ } -+ } -+ *(--ptr) = '\0'; -+ break; -+ -+ case 'C': -+ /* Current thread id */ -+ strcpy(remcom_out_buffer, "QC"); -+ -+ threadid = shadow_pid(current->pid); -+ -+ int_to_threadref(&thref, threadid); -+ pack_threadid(remcom_out_buffer + 2, &thref); -+ break; -+ case 'T': -+ if (memcmp(remcom_in_buffer + 1, -+ "ThreadExtraInfo,", 16)) { -+ error_packet(remcom_out_buffer, -+ -EINVAL); -+ break; -+ } -+ threadid = 0; -+ ptr = remcom_in_buffer + 17; -+ kgdb_hex2long(&ptr, &threadid); -+ if (!getthread(linux_regs, threadid)) { -+ error_packet(remcom_out_buffer, -+ -EINVAL); -+ break; -+ } -+ if (threadid < pid_max) { -+ kgdb_mem2hex(getthread(linux_regs, -+ threadid)->comm, -+ remcom_out_buffer, 16); -+ } else if (threadid >= pid_max + -+ num_online_cpus()) { -+ kgdb_shadowinfo(linux_regs, -+ remcom_out_buffer, -+ threadid - pid_max - -+ num_online_cpus()); -+ } else { -+ static char tmpstr[23 + -+ BUF_THREAD_ID_SIZE]; -+ sprintf(tmpstr, "Shadow task %d" -+ " for pid 0", -+ (int)(threadid - pid_max)); -+ kgdb_mem2hex(tmpstr, remcom_out_buffer, -+ strlen(tmpstr)); -+ } -+ break; -+ } -+ break; -+ -+ /* task related */ -+ case 'H': -+ switch (remcom_in_buffer[1]) { -+ case 'g': -+ ptr = &remcom_in_buffer[2]; -+ kgdb_hex2long(&ptr, &threadid); -+ thread = getthread(linux_regs, threadid); -+ if (!thread && threadid > 0) { -+ error_packet(remcom_out_buffer, -+ -EINVAL); -+ break; -+ } -+ kgdb_usethread = thread; -+ kgdb_usethreadid = threadid; -+ strcpy(remcom_out_buffer, "OK"); -+ break; -+ -+ case 'c': -+ ptr = &remcom_in_buffer[2]; -+ kgdb_hex2long(&ptr, &threadid); -+ if (!threadid) { -+ kgdb_contthread = NULL; -+ } else { -+ thread = getthread(linux_regs, -+ threadid); -+ if (!thread && threadid > 0) { -+ error_packet(remcom_out_buffer, -+ -EINVAL); -+ break; -+ } -+ kgdb_contthread = thread; -+ } -+ strcpy(remcom_out_buffer, "OK"); -+ break; -+ } -+ break; -+ -+ /* Query thread status */ -+ case 'T': -+ ptr = &remcom_in_buffer[1]; -+ kgdb_hex2long(&ptr, &threadid); -+ thread = getthread(linux_regs, threadid); -+ if (thread) -+ strcpy(remcom_out_buffer, "OK"); -+ else -+ error_packet(remcom_out_buffer, -EINVAL); -+ break; -+ /* Since GDB-5.3, it's been drafted that '0' is a software -+ * breakpoint, '1' is a hardware breakpoint, so let's do -+ * that. -+ */ -+ case 'z': -+ case 'Z': -+ bpt_type = &remcom_in_buffer[1]; -+ ptr = &remcom_in_buffer[2]; -+ -+ if (kgdb_ops->set_hw_breakpoint && *bpt_type >= '1') { -+ /* Unsupported */ -+ if (*bpt_type > '4') -+ break; -+ } else if (*bpt_type != '0' && *bpt_type != '1') -+ /* Unsupported. */ -+ break; -+ /* Test if this is a hardware breakpoint, and -+ * if we support it. */ -+ if (*bpt_type == '1' && -+ !kgdb_ops->flags & KGDB_HW_BREAKPOINT) -+ /* Unsupported. */ -+ break; -+ -+ if (*(ptr++) != ',') { -+ error_packet(remcom_out_buffer, -EINVAL); -+ break; -+ } else if (kgdb_hex2long(&ptr, &addr)) { -+ if (*(ptr++) != ',' || -+ !kgdb_hex2long(&ptr, &length)) { -+ error_packet(remcom_out_buffer, -+ -EINVAL); -+ break; -+ } -+ } else { -+ error_packet(remcom_out_buffer, -EINVAL); -+ break; -+ } -+ -+ if (remcom_in_buffer[0] == 'Z' && *bpt_type == '0') -+ error = kgdb_set_sw_break(addr); -+ else if (remcom_in_buffer[0] == 'Z' && *bpt_type == '1') -+ error = kgdb_set_hw_break(addr); -+ else if (remcom_in_buffer[0] == 'z' && *bpt_type == '0') -+ error = kgdb_remove_sw_break(addr); -+ else if (remcom_in_buffer[0] == 'z' && *bpt_type == '1') -+ error = kgdb_remove_hw_break(addr); -+ else if (remcom_in_buffer[0] == 'Z') -+ error = kgdb_ops->set_hw_breakpoint(addr, -+ (int)length, -+ *bpt_type); -+ else if (remcom_in_buffer[0] == 'z') -+ error = kgdb_ops->remove_hw_breakpoint(addr, -+ (int) -+ length, -+ *bpt_type); -+ -+ if (error == 0) -+ strcpy(remcom_out_buffer, "OK"); -+ else -+ error_packet(remcom_out_buffer, error); -+ -+ break; -+ case 'c': -+ case 's': -+ if (kgdb_contthread && kgdb_contthread != current) { -+ /* Can't switch threads in kgdb */ -+ error_packet(remcom_out_buffer, -EINVAL); -+ break; -+ } -+ kgdb_activate_sw_breakpoints(); -+ /* Followthrough to default processing */ -+ default: -+ default_handle: -+ error = kgdb_arch_handle_exception(ex_vector, signo, -+ err_code, -+ remcom_in_buffer, -+ remcom_out_buffer, -+ linux_regs); -+ -+ if (error >= 0 || remcom_in_buffer[0] == 'D' || -+ remcom_in_buffer[0] == 'k') -+ goto kgdb_exit; -+ -+ } /* switch */ -+ -+ /* reply to the request */ -+ put_packet(remcom_out_buffer); -+ } -+ -+ kgdb_exit: -+ /* Call the I/O driver's post_exception routine if the I/O -+ * driver defined one. -+ */ -+ if (kgdb_io_ops.post_exception) -+ kgdb_io_ops.post_exception(); -+ -+ kgdb_info[processor].debuggerinfo = NULL; -+ kgdb_info[processor].task = NULL; -+ atomic_set(&procindebug[processor], 0); -+ -+ if (!debugger_step || !kgdb_contthread) { -+ for (i = 0; i < NR_CPUS; i++) -+ spin_unlock(&slavecpulocks[i]); -+ /* Wait till all the processors have quit -+ * from the debugger. */ -+ for (i = 0; i < NR_CPUS; i++) { -+ while (atomic_read(&procindebug[i])) { -+ int j = 10; /* an arbitrary number */ -+ -+ while (--j) -+ cpu_relax(); -+ } -+ } -+ } -+ -+#ifdef CONFIG_SMP -+ /* This delay has a real purpose. The problem is that if you -+ * are single-stepping, you are sending an NMI to all the -+ * other processors to stop them. Interrupts come in, but -+ * don't get handled. Then you let them go just long enough -+ * to get into their interrupt routines and use up some stack. -+ * You stop them again, and then do the same thing. After a -+ * while you blow the stack on the other processors. This -+ * delay gives some time for interrupts to be cleared out on -+ * the other processors. -+ */ -+ if (debugger_step) -+ mdelay(2); -+#endif -+kgdb_restore: -+ /* Free debugger_active */ -+ atomic_set(&debugger_active, 0); -+ local_irq_restore(flags); -+ -+ return error; -+} -+ -+/* -+ * GDB places a breakpoint at this function to know dynamically -+ * loaded objects. It's not defined static so that only one instance with this -+ * name exists in the kernel. -+ */ -+ -+int module_event(struct notifier_block *self, unsigned long val, void *data) -+{ -+ return 0; -+} -+ -+static struct notifier_block kgdb_module_load_nb = { -+ .notifier_call = module_event, -+}; -+ -+void kgdb_nmihook(int cpu, void *regs) -+{ -+#ifdef CONFIG_SMP -+ if (!atomic_read(&procindebug[cpu]) && atomic_read(&debugger_active) != (cpu + 1)) -+ kgdb_wait((struct pt_regs *)regs); -+#endif -+} -+ -+/* -+ * This is called when a panic happens. All we need to do is -+ * breakpoint(). -+ */ -+static int kgdb_panic_notify(struct notifier_block *self, unsigned long cmd, -+ void *ptr) -+{ -+ breakpoint(); -+ -+ return 0; -+} -+ -+static struct notifier_block kgdb_panic_notifier = { -+ .notifier_call = kgdb_panic_notify, -+}; -+ -+/* -+ * Initialization that needs to be done in either of our entry points. -+ */ -+static void __init kgdb_internal_init(void) -+{ -+ int i; -+ -+ /* Initialize our spinlocks. */ -+ for (i = 0; i < NR_CPUS; i++) -+ spin_lock_init(&slavecpulocks[i]); -+ -+ for (i = 0; i < MAX_BREAKPOINTS; i++) -+ kgdb_break[i].state = bp_none; -+ -+ /* Initialize the I/O handles */ -+ memset(&kgdb_io_ops_prev, 0, sizeof(kgdb_io_ops_prev)); -+ -+ /* We can't do much if this fails */ -+ register_module_notifier(&kgdb_module_load_nb); -+ -+ kgdb_initialized = 1; -+} -+ -+static void kgdb_register_for_panic(void) -+{ -+ /* Register for panics(). */ -+ /* The registration is done in the kgdb_register_for_panic -+ * routine because KGDB should not try to handle a panic when -+ * there are no kgdb_io_ops setup. It is assumed that the -+ * kgdb_io_ops are setup at the time this method is called. -+ */ -+ if (!kgdb_from_module_registered) { -+ atomic_notifier_chain_register(&panic_notifier_list, -+ &kgdb_panic_notifier); -+ kgdb_from_module_registered = 1; -+ } -+} -+ -+static void kgdb_unregister_for_panic(void) -+{ -+ /* When this routine is called KGDB should unregister from the -+ * panic handler and clean up, making sure it is not handling any -+ * break exceptions at the time. -+ */ -+ if (kgdb_from_module_registered) { -+ kgdb_from_module_registered = 0; -+ atomic_notifier_chain_unregister(&panic_notifier_list, -+ &kgdb_panic_notifier); -+ } -+} -+ -+int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops) -+{ -+ -+ if (kgdb_connected) { -+ printk(KERN_ERR "kgdb: Cannot load I/O module while KGDB " -+ "connected.\n"); -+ return -EINVAL; -+ } -+ -+ /* Save the old values so they can be restored */ -+ if (kgdb_io_handler_cnt >= MAX_KGDB_IO_HANDLERS) { -+ printk(KERN_ERR "kgdb: No more I/O handles available.\n"); -+ return -EINVAL; -+ } -+ -+ /* Check to see if there is an existing driver and if so save its -+ * values. Also check to make sure the same driver was not trying -+ * to re-register. -+ */ -+ if (kgdb_io_ops.read_char != NULL && -+ kgdb_io_ops.read_char != local_kgdb_io_ops->read_char) { -+ memcpy(&kgdb_io_ops_prev[kgdb_io_handler_cnt], -+ &kgdb_io_ops, sizeof(struct kgdb_io)); -+ kgdb_io_handler_cnt++; -+ } -+ -+ /* Initialize the io values for this module */ -+ memcpy(&kgdb_io_ops, local_kgdb_io_ops, sizeof(struct kgdb_io)); -+ -+ /* Make the call to register kgdb if is not initialized */ -+ kgdb_register_for_panic(); -+ -+ return 0; -+} -+ -+void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops) -+{ -+ int i; -+ -+ /* Unregister KGDB if there were no other prior io hooks, else -+ * restore the io hooks. -+ */ -+ if (kgdb_io_handler_cnt > 0 && kgdb_io_ops_prev[0].read_char != NULL) { -+ /* First check if the hook that is in use is the one being -+ * removed */ -+ if (kgdb_io_ops.read_char == local_kgdb_io_ops->read_char) { -+ /* Set 'i' to the value of where the list should be -+ * shifed */ -+ i = kgdb_io_handler_cnt - 1; -+ memcpy(&kgdb_io_ops, &kgdb_io_ops_prev[i], -+ sizeof(struct kgdb_io)); -+ } else { -+ /* Simple case to remove an entry for an I/O handler -+ * that is not in use */ -+ for (i = 0; i < kgdb_io_handler_cnt; i++) { -+ if (kgdb_io_ops_prev[i].read_char == -+ local_kgdb_io_ops->read_char) -+ break; -+ } -+ } -+ -+ /* Shift all the entries in the handler array so it is -+ * ordered from oldest to newest. -+ */ -+ kgdb_io_handler_cnt--; -+ for (; i < kgdb_io_handler_cnt; i++) { -+ memcpy(&kgdb_io_ops_prev[i], &kgdb_io_ops_prev[i + 1], -+ sizeof(struct kgdb_io)); -+ } -+ /* Handle the case if we are on the last element and set it -+ * to NULL; */ -+ memset(&kgdb_io_ops_prev[kgdb_io_handler_cnt], 0, -+ sizeof(struct kgdb_io)); -+ -+ if (kgdb_connected) -+ printk(KERN_ERR "kgdb: WARNING: I/O method changed " -+ "while kgdb was connected state.\n"); -+ } else { -+ /* KGDB is no longer able to communicate out, so -+ * unregister our hooks and reset state. */ -+ kgdb_unregister_for_panic(); -+ if (kgdb_connected) { -+ printk(KERN_CRIT "kgdb: I/O module was unloaded while " -+ "a debugging session was running. " -+ "KGDB will be reset.\n"); -+ if (remove_all_break() < 0) -+ printk(KERN_CRIT "kgdb: Reset failed.\n"); -+ kgdb_connected = 0; -+ } -+ memset(&kgdb_io_ops, 0, sizeof(struct kgdb_io)); -+ } -+} -+ -+/* -+ * There are times we need to call a tasklet to cause a breakpoint -+ * as calling breakpoint() at that point might be fatal. We have to -+ * check that the exception stack is setup, as tasklets may be scheduled -+ * prior to this. When that happens, it is up to the architecture to -+ * schedule this when it is safe to run. -+ */ -+static void kgdb_tasklet_bpt(unsigned long ing) -+{ -+ if(CHECK_EXCEPTION_STACK()) -+ breakpoint(); -+} -+ -+DECLARE_TASKLET(kgdb_tasklet_breakpoint, kgdb_tasklet_bpt, 0); -+ -+/* -+ * This function can be called very early, either via early_param() or -+ * an explicit breakpoint() early on. -+ */ -+static void __init kgdb_early_entry(void) -+{ -+ /* -+ * Don't try and do anything until the architecture is able to -+ * setup the exception stack. In this case, it is up to the -+ * architecture to hook in and look at us when they are ready. -+ */ -+ if(!CHECK_EXCEPTION_STACK()) { -+ kgdb_initialized = -1; -+ tasklet_schedule(&kgdb_tasklet_breakpoint); -+ return; -+ } -+ -+ /* Let the architecture do any setup that it needs to. */ -+ kgdb_arch_init(); -+ -+ /* Now try the I/O. */ -+ /* For early entry kgdb_io_ops.init must be defined */ -+ if (!kgdb_io_ops.init || kgdb_io_ops.init()) { -+ /* Try again later. */ -+ kgdb_initialized = -1; -+ return; -+ } -+ -+ /* Finish up. */ -+ kgdb_internal_init(); -+ -+ /* KGDB can assume that if kgdb_io_ops.init was defined that the -+ * panic registion should be performed at this time. This means -+ * kgdb_io_ops.init did not come from a kernel module and was -+ * initialized statically by a built in. -+ */ -+ if (kgdb_io_ops.init) -+ kgdb_register_for_panic(); -+} -+ -+/* -+ * This function will always be invoked to make sure that KGDB will grab -+ * what it needs to so that if something happens while the system is -+ * running, KGDB will get involved. If kgdb_early_entry() has already -+ * been invoked, there is little we need to do. -+ */ -+static int __init kgdb_late_entry(void) -+{ -+ int need_break = 0; -+ -+ /* If kgdb_initialized is -1 then we were passed kgdbwait. */ -+ if (kgdb_initialized == -1) -+ need_break = 1; -+ -+ /* -+ * If we haven't tried to initialize KGDB yet, we need to call -+ * kgdb_arch_init before moving onto the I/O. -+ */ -+ if (!kgdb_initialized) -+ kgdb_arch_init(); -+ -+ if (kgdb_initialized != 1) { -+ if (kgdb_io_ops.init && kgdb_io_ops.init()) { -+ /* When KGDB allows I/O via modules and the core -+ * I/O init fails KGDB must default to defering the -+ * I/O setup, and appropriately print an error about -+ * it. -+ */ -+ printk(KERN_ERR "kgdb: Could not setup core I/O " -+ "for KGDB.\n"); -+ printk(KERN_INFO "kgdb: Defering I/O setup to kernel " -+ "module.\n"); -+ memset(&kgdb_io_ops, 0, sizeof(struct kgdb_io)); -+ } -+ -+ kgdb_internal_init(); -+ -+ /* KGDB can assume that if kgdb_io_ops.init was defined that -+ * panic registion should be performed at this time. This means -+ * kgdb_io_ops.init did not come from a kernel module and was -+ * initialized statically by a built in. -+ */ -+ if (kgdb_io_ops.init) -+ kgdb_register_for_panic(); -+ } -+ -+ /* Registering to reboot notifier list*/ -+ register_reboot_notifier(&kgdb_reboot_notifier); -+ -+ /* Now do any late init of the I/O. */ -+ if (kgdb_io_ops.late_init) -+ kgdb_io_ops.late_init(); -+ -+ if (need_break) { -+ printk(KERN_CRIT "kgdb: Waiting for connection from remote" -+ " gdb...\n"); -+ breakpoint(); -+ } -+ -+ return 0; -+} -+ -+late_initcall(kgdb_late_entry); -+ -+/* -+ * 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 (kgdb_initialized != 1) { -+ kgdb_early_entry(); -+ if (kgdb_initialized == 1) -+ printk(KERN_CRIT "Waiting for connection from remote " -+ "gdb...\n"); -+ else { -+ printk(KERN_CRIT "KGDB cannot initialize I/O yet.\n"); -+ return; -+ } -+ } -+ -+ atomic_set(&kgdb_setting_breakpoint, 1); -+ wmb(); -+ BREAKPOINT(); -+ wmb(); -+ atomic_set(&kgdb_setting_breakpoint, 0); -+} -+ -+EXPORT_SYMBOL(breakpoint); -+ -+#ifdef CONFIG_MAGIC_SYSRQ -+static void sysrq_handle_gdb(int key, struct pt_regs *pt_regs, -+ struct tty_struct *tty) -+{ -+ printk("Entering GDB stub\n"); -+ breakpoint(); -+} -+static struct sysrq_key_op sysrq_gdb_op = { -+ .handler = sysrq_handle_gdb, -+ .help_msg = "Gdb", -+ .action_msg = "GDB", -+}; -+ -+static int gdb_register_sysrq(void) -+{ -+ printk("Registering GDB sysrq handler\n"); -+ register_sysrq_key('g', &sysrq_gdb_op); -+ return 0; -+} -+ -+module_init(gdb_register_sysrq); -+#endif -+ -+static int kgdb_notify_reboot(struct notifier_block *this, -+ unsigned long code, void *x) -+{ -+ -+ unsigned long flags; -+ -+ /* If we're debugging, or KGDB has not connected, don't try -+ * and print. */ -+ if (!kgdb_connected || atomic_read(&debugger_active) != 0) -+ return 0; -+ if ((code == SYS_RESTART) || (code == SYS_HALT) || (code == SYS_POWER_OFF)){ -+ local_irq_save(flags); -+ put_packet("X00"); -+ local_irq_restore(flags); -+ } -+ return NOTIFY_DONE; -+} -+ -+#ifdef CONFIG_KGDB_CONSOLE -+void kgdb_console_write(struct console *co, const char *s, unsigned count) -+{ -+ unsigned long flags; -+ -+ /* If we're debugging, or KGDB has not connected, don't try -+ * and print. */ -+ if (!kgdb_connected || atomic_read(&debugger_active) != 0) -+ return; -+ -+ local_irq_save(flags); -+ kgdb_msg_write(s, count); -+ local_irq_restore(flags); -+} -+ -+struct console kgdbcons = { -+ .name = "kgdb", -+ .write = kgdb_console_write, -+ .flags = CON_PRINTBUFFER | CON_ENABLED, -+}; -+static int __init kgdb_console_init(void) -+{ -+ register_console(&kgdbcons); -+ return 0; -+} -+ -+console_initcall(kgdb_console_init); -+#endif -+ -+static int __init opt_kgdb_enter(char *str) -+{ -+ /* We've already done this by an explicit breakpoint() call. */ -+ if (kgdb_initialized) -+ return 0; -+ -+ /* Call breakpoint() which will take care of init. */ -+ breakpoint(); -+ -+ return 0; -+} -+ -+early_param("kgdbwait", opt_kgdb_enter); -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/kernel/kgdbarchlib.c linux-2.6.18-53.1.14.kgdb/kernel/kgdbarchlib.c ---- linux-2.6.18-53.1.14/kernel/kgdbarchlib.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/kernel/kgdbarchlib.c 2008-06-10 15:37:25.000000000 +0400 -@@ -0,0 +1,198 @@ -+#include -+ -+struct kgdb_arch *kgdb_ops = &arch_kgdb_ops; -+ -+/** -+ * kgdb_arch_init - Perform any architecture specific initalization. -+ * -+ * RETURN: -+ * The return value is ignored. -+ * -+ * This function will handle the initalization of any architecture -+ * specific hooks. -+ */ -+int __attribute__ ((weak)) -+ kgdb_arch_init(void) -+{ -+ return 0; -+} -+ -+/** -+ * kgdb_disable_hw_debug - Disable hardware debugging while we in kgdb. -+ * @regs: Current &struct pt_regs. -+ * -+ * This function will be called if the particular architecture must -+ * disable hardware debugging while it is processing gdb packets or -+ * handling exception. -+ */ -+void __attribute__ ((weak)) -+ kgdb_disable_hw_debug(struct pt_regs *regs) -+{ -+} -+ -+/* -+ * Skip an int3 exception when it occurs after a breakpoint has been -+ * removed. Backtrack eip by 1 since the int3 would have caused it to -+ * increment by 1. -+ */ -+int __attribute__ ((weak)) -+ kgdb_skipexception(int exception, struct pt_regs *regs) -+{ -+ return 0; -+} -+ -+/** -+ * kgdb_set_hw_break - Set a hardware breakpoint at @addr. -+ * @addr: The address to set a hardware breakpoint at. -+ */ -+int __attribute__ ((weak)) -+ kgdb_set_hw_break(unsigned long addr) -+{ -+ return 0; -+} -+ -+/** -+ * kgdb_remove_hw_break - Remove a hardware breakpoint at @addr. -+ * @addr: The address to remove a hardware breakpoint from. -+ */ -+int __attribute__ ((weak)) -+ kgdb_remove_hw_break(unsigned long addr) -+{ -+ return 0; -+} -+ -+/** -+ * kgdb_remove_all_hw_break - Clear all hardware breakpoints. -+ */ -+void __attribute__ ((weak)) -+ kgdb_remove_all_hw_break(void) -+{ -+} -+ -+/** -+ * kgdb_correct_hw_break - Correct hardware breakpoints. -+ * -+ * A hook to allow for changes to the hardware breakpoint, called -+ * after a single step (s) or continue (c) packet, and once we're about -+ * to let the kernel continue running. -+ * -+ * This is used to set the hardware breakpoint registers for all the -+ * slave cpus on an SMP configuration. This must be called after any -+ * changes are made to the hardware breakpoints (such as by a single -+ * step (s) or continue (c) packet. This is only required on -+ * architectures that support SMP and every processor has its own set -+ * of breakpoint registers. -+ */ -+void __attribute__ ((weak)) -+ kgdb_correct_hw_break(void) -+{ -+} -+ -+/** -+ * kgdb_post_master_code - Save error vector/code numbers. -+ * @regs: Original pt_regs. -+ * @e_vector: Original error vector. -+ * @err_code: Original error code. -+ * -+ * This is needed on architectures which support SMP and KGDB. -+ * This function is called after all the slave cpus have been put -+ * to a know spin state and the master CPU has control over KGDB. -+ */ -+ -+void __attribute__ ((weak)) -+ kgdb_post_master_code(struct pt_regs *regs, int e_vector, int err_code) -+{ -+} -+ -+/** -+ * kgdb_roundup_cpus - Get other CPUs into a holding pattern -+ * @flags: Current IRQ state -+ * -+ * On SMP systems, we need to get the attention of the other CPUs -+ * and get them be in a known state. This should do what is needed -+ * to get the other CPUs to call kgdb_wait(). Note that on some arches, -+ * the NMI approach is not used for rounding up all the CPUs. For example, -+ * in case of MIPS, smp_call_function() is used to roundup CPUs. In -+ * this case, we have to make sure that interrupts are enabled before -+ * calling smp_call_function(). The argument to this function is -+ * the flags that will be used when restoring the interrupts. There is -+ * local_irq_save() call before kgdb_roundup_cpus(). -+ */ -+void __attribute__ ((weak)) -+ kgdb_roundup_cpus(unsigned long flags) -+{ -+} -+ -+/** -+ * kgdb_shadowinfo - Get shadowed information on @threadid. -+ * @regs: The &struct pt_regs of the current process. -+ * @buffer: A buffer of %BUFMAX size. -+ * @threadid: The thread id of the shadowed process to get information on. -+ */ -+void __attribute__ ((weak)) -+ kgdb_shadowinfo(struct pt_regs *regs, char *buffer, unsigned threadid) -+{ -+} -+ -+/** -+ * kgdb_get_shadow_thread - Get the shadowed &task_struct of @threadid. -+ * @regs: The &struct pt_regs of the current thread. -+ * @threadid: The thread id of the shadowed process to get information on. -+ * -+ * RETURN: -+ * This returns a pointer to the &struct task_struct of the shadowed -+ * thread, @threadid. -+ */ -+struct task_struct __attribute__ ((weak)) -+ * kgdb_get_shadow_thread(struct pt_regs *regs, int threadid) -+{ -+ return NULL; -+} -+ -+/** -+ * kgdb_shadow_regs - Return the shadowed registers of @threadid. -+ * @regs: The &struct pt_regs of the current thread. -+ * @threadid: The thread id we want the &struct pt_regs for. -+ * -+ * RETURN: -+ * The a pointer to the &struct pt_regs of the shadowed thread @threadid. -+ */ -+struct pt_regs __attribute__ ((weak)) -+ * kgdb_shadow_regs(struct pt_regs *regs, int threadid) -+{ -+ return NULL; -+} -+ -+int __attribute__ ((weak)) -+ kgdb_validate_break_address(unsigned long addr) -+{ -+ int error = 0; -+ char tmp_variable[BREAK_INSTR_SIZE]; -+ error = kgdb_get_mem((char *)addr, tmp_variable, BREAK_INSTR_SIZE); -+ return error; -+} -+ -+int __attribute__ ((weak)) -+ kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) -+{ -+ int error = 0; -+ if ((error = kgdb_get_mem((char *)addr, -+ saved_instr, BREAK_INSTR_SIZE)) < 0) -+ return error; -+ -+ if ((error = kgdb_set_mem((char *)addr, kgdb_ops->gdb_bpt_instr, -+ BREAK_INSTR_SIZE)) < 0) -+ return error; -+ return 0; -+} -+ -+int __attribute__ ((weak)) -+ kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle) -+{ -+ -+ int error = 0; -+ if ((error =kgdb_set_mem((char *)addr, (char *)bundle, -+ BREAK_INSTR_SIZE)) < 0) -+ return error; -+ return 0; -+} -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/kernel/module.c linux-2.6.18-53.1.14.kgdb/kernel/module.c ---- linux-2.6.18-53.1.14/kernel/module.c 2008-03-06 05:54:13.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/kernel/module.c 2008-06-10 15:39:15.000000000 +0400 -@@ -65,6 +65,7 @@ static DEFINE_SPINLOCK(modlist_lock); - /* List of modules, protected by module_mutex AND modlist_lock */ - static DEFINE_MUTEX(module_mutex); - static LIST_HEAD(modules); -+static DECLARE_MUTEX(notify_mutex); - - static BLOCKING_NOTIFIER_HEAD(module_notify_list); - -@@ -701,6 +702,12 @@ sys_delete_module(const char __user *nam - if (ret != 0) - goto out; - -+ down(¬ify_mutex); -+ blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_GOING, -+ mod); -+ up(¬ify_mutex); -+ -+ - /* Never wait if forced. */ - if (!forced && module_refcount(mod) != 0) - wait_for_zero_refcount(mod); -@@ -713,6 +720,11 @@ sys_delete_module(const char __user *nam - } - free_module(mod); - -+ down(¬ify_mutex); -+ blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_GONE, -+ NULL); -+ up(¬ify_mutex); -+ - out: - mutex_unlock(&module_mutex); - return ret; -@@ -1119,6 +1131,11 @@ static void free_module(struct module *m - /* Arch-specific cleanup. */ - module_arch_cleanup(mod); - -+#ifdef CONFIG_KGDB -+ /* kgdb info */ -+ vfree(mod->mod_sections); -+#endif -+ - /* Module unload stuff */ - module_unload_free(mod); - -@@ -1378,6 +1395,31 @@ static void setup_modinfo(struct module - } - } - -+#ifdef CONFIG_KGDB -+int add_modsects (struct module *mod, Elf_Ehdr *hdr, Elf_Shdr *sechdrs, const -+ char *secstrings) -+{ -+ int i; -+ -+ mod->num_sections = hdr->e_shnum - 1; -+ mod->mod_sections = vmalloc((hdr->e_shnum - 1)* -+ sizeof (struct mod_section)); -+ -+ if (mod->mod_sections == NULL) { -+ return -ENOMEM; -+ } -+ -+ for (i = 1; i < hdr->e_shnum; i++) { -+ mod->mod_sections[i - 1].address = (void *)sechdrs[i].sh_addr; -+ strncpy(mod->mod_sections[i - 1].name, secstrings + -+ sechdrs[i].sh_name, MAX_SECTNAME); -+ mod->mod_sections[i - 1].name[MAX_SECTNAME] = '\0'; -+ } -+ -+ return 0; -+} -+#endif -+ - #ifdef CONFIG_KALLSYMS - int is_exported(const char *name, const struct module *mod) - { -@@ -1796,6 +1838,12 @@ static struct module *load_module(void _ - - add_kallsyms(mod, sechdrs, symindex, strindex, secstrings); - -+#ifdef CONFIG_KGDB -+ if ((err = add_modsects(mod, hdr, sechdrs, secstrings)) < 0) { -+ goto nomodsectinfo; -+ } -+#endif -+ - err = module_finalize(hdr, sechdrs, mod); - if (err < 0) - goto cleanup; -@@ -1856,6 +1904,11 @@ static struct module *load_module(void _ - arch_cleanup: - module_arch_cleanup(mod); - cleanup: -+ -+#ifdef CONFIG_KGDB -+nomodsectinfo: -+ vfree(mod->mod_sections); -+#endif - module_unload_free(mod); - module_free(mod, mod->module_init); - free_core: -@@ -1927,6 +1980,10 @@ sys_init_module(void __user *umod, - /* Init routine failed: abort. Try to protect us from - buggy refcounters. */ - mod->state = MODULE_STATE_GOING; -+ down(¬ify_mutex); -+ blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_GOING, -+ mod); -+ up(¬ify_mutex); - synchronize_sched(); - if (mod->unsafe) - printk(KERN_ERR "%s: module is now stuck!\n", -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/kernel/sched.c linux-2.6.18-53.1.14.kgdb/kernel/sched.c ---- linux-2.6.18-53.1.14/kernel/sched.c 2008-03-06 05:54:44.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/kernel/sched.c 2008-06-10 15:37:25.000000000 +0400 -@@ -52,6 +52,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -6835,6 +6836,9 @@ void __might_sleep(char *file, int line) - #ifdef in_atomic - static unsigned long prev_jiffy; /* ratelimiting */ - -+ if (atomic_read(&debugger_active)) -+ return; -+ - if ((in_atomic() || irqs_disabled()) && - system_state == SYSTEM_RUNNING && !oops_in_progress) { - if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy) -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/kernel/softlockup.c linux-2.6.18-53.1.14.kgdb/kernel/softlockup.c ---- linux-2.6.18-53.1.14/kernel/softlockup.c 2008-03-06 05:54:44.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/kernel/softlockup.c 2008-06-10 15:39:21.000000000 +0400 -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - - static DEFINE_SPINLOCK(print_lock); - -@@ -37,6 +38,9 @@ static struct notifier_block panic_block - void touch_softlockup_watchdog(void) - { - __raw_get_cpu_var(touch_timestamp) = jiffies; -+#ifdef CONFIG_KGDB -+ atomic_set(&kgdb_sync_softlockup[raw_smp_processor_id()], 0); -+#endif - } - EXPORT_SYMBOL(touch_softlockup_watchdog); - -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/kernel/timer.c linux-2.6.18-53.1.14.kgdb/kernel/timer.c ---- linux-2.6.18-53.1.14/kernel/timer.c 2008-03-06 05:54:50.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/kernel/timer.c 2008-06-10 15:39:21.000000000 +0400 -@@ -34,6 +34,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -1385,7 +1386,11 @@ static void run_timer_softirq(struct sof - */ - void run_local_timers(void) - { -+ int this_cpu = smp_processor_id(); - raise_softirq(TIMER_SOFTIRQ); -+#ifdef CONFIG_KGDB -+ if(!atomic_read(&kgdb_sync_softlockup[this_cpu])) -+#endif - softlockup_tick(); - } - -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/lib/Kconfig.debug linux-2.6.18-53.1.14.kgdb/lib/Kconfig.debug ---- linux-2.6.18-53.1.14/lib/Kconfig.debug 2008-03-06 05:54:32.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/lib/Kconfig.debug 2008-06-10 15:38:56.000000000 +0400 -@@ -324,7 +324,7 @@ config DEBUG_LIST - - config FRAME_POINTER - bool "Compile the kernel with frame pointers" -- depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390) -+ depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || SUPERH) - default y if DEBUG_INFO && UML - help - If you say Y here the resulting kernel image will be slightly larger -@@ -377,3 +377,158 @@ config RCU_TORTURE_TEST - at boot time (you probably don't). - Say M if you want the RCU torture tests to build as a module. - Say N if you are unsure. -+ -+config WANT_EXTRA_DEBUG_INFORMATION -+ bool -+ select DEBUG_INFO -+ select FRAME_POINTER if X86 || SUPERH -+ default n -+ -+config KGDB -+ bool "KGDB: kernel debugging with remote gdb" -+ select WANT_EXTRA_DEBUG_INFORMATION -+ depends on DEBUG_KERNEL && (ARM || X86 || MIPS || (SUPERH && !SUPERH64) || IA64 || X86_64 || PPC) -+ help -+ If you say Y here, it will be possible to remotely debug the -+ kernel using gdb. It is strongly suggested that you enable -+ DEBUG_INFO, and if available on your platform, FRAME_POINTER. -+ Documentation of kernel debugger available at -+ http://kgdb.sourceforge.net as well as in DocBook form -+ in Documentation/DocBook/. If unsure, say N. -+ -+config KGDB_CONSOLE -+ bool "KGDB: Console messages through gdb" -+ depends on KGDB -+ help -+ If you say Y here, console messages will appear through gdb. -+ Other consoles such as tty or ttyS will continue to work as usual. -+ Note, that if you use this in conjunction with KGDB_ETH, if the -+ ethernet driver runs into an error condition during use with KGDB -+ it is possible to hit an infinite recusrion, causing the kernel -+ to crash, and typically reboot. For this reason, it is preferable -+ to use NETCONSOLE in conjunction with KGDB_ETH instead of -+ KGDB_CONSOLE. -+ -+choice -+ prompt "Method for KGDB communication" -+ depends on KGDB -+ default KGDB_8250_NOMODULE -+ default KGDB_MPSC if SERIAL_MPSC -+ default KGDB_CPM_UART if (8xx || 8260) -+ default KGDB_SIBYTE if SIBYTE_SB1xxx_SOC -+ help -+ There are a number of different ways in which you can communicate -+ with KGDB. The most common is via serial, with the 8250 driver -+ (should your hardware have an 8250, or ns1655x style uart). -+ Another option is to use the NETPOLL framework and UDP, should -+ your ethernet card support this. Other options may exist. -+ You can elect to have one core I/O driver that is built into the -+ kernel for debugging as the kernel is booting, or using only -+ kernel modules. -+ -+config KGDB_ONLY_MODULES -+ bool "KGDB: Use only kernel modules for I/O" -+ depends on MODULES -+ help -+ Use only kernel modules to configure KGDB I/O after the -+ kernel is booted. -+ -+config KGDB_8250_NOMODULE -+ bool "KGDB: On generic serial port (8250)" -+ select KGDB_8250 -+ help -+ Uses generic serial port (8250) to communicate with the host -+ GDB. This is independent of the normal (SERIAL_8250) driver -+ for this chipset. -+ -+config KGDBOE_NOMODULE -+ bool "KGDB: On ethernet - in kernel" -+ select KGDBOE -+ select NETPOLL -+ select NETPOLL_TRAP -+ select NETPOLL_RX -+ help -+ Uses the NETPOLL API to communicate with the host GDB via UDP. -+ In order for this to work, the ethernet interface specified must -+ support the NETPOLL API, and this must be initialized at boot. -+ See the documentation for syntax. -+ -+config KGDB_MPSC -+ bool "KGDB on MV64x60 MPSC" -+ depends on SERIAL_MPSC -+ help -+ Uses a Marvell GT64260B or MV64x60 Multi-Purpose Serial -+ Controller (MPSC) channel. Note that the GT64260A is not -+ supported. -+ -+config KGDB_CPM_UART -+ bool "KGDB: On CPM UART" -+ depends on PPC && (CPM2 || 8xx) -+ help -+ Uses CPM UART to communicate with the host GDB. -+ -+config KGDB_SIBYTE -+ bool "KGDB: On the Broadcom SWARM serial port" -+ depends on MIPS && SIBYTE_SB1xxx_SOC -+endchoice -+ -+config KGDBOE -+ tristate "KGDB: On ethernet" if !KGDBOE_NOMODULE -+ depends on m && KGDB -+ select NETPOLL -+ select NETPOLL_TRAP -+ select NETPOLL_RX -+ help -+ Uses the NETPOLL API to communicate with the host GDB via UDP. -+ In order for this to work, the ethernet interface specified must -+ support the NETPOLL API, and this must be initialized at boot. -+ See the documentation for syntax. -+ -+config KGDB_8250 -+ tristate "KGDB: On generic serial port (8250)" if !KGDB_8250_NOMODULE -+ depends on m && KGDB_ONLY_MODULES -+ help -+ Uses generic serial port (8250) to communicate with the host -+ GDB. This is independent of the normal (SERIAL_8250) driver -+ for this chipset. -+ -+config KGDB_SIMPLE_SERIAL -+ bool "Simple selection of KGDB serial port" -+ depends on KGDB_8250_NOMODULE -+ default y -+ help -+ If you say Y here, you will only have to pick the baud rate -+ and port number that you wish to use for KGDB. Note that this -+ only works on architectures that register known serial ports -+ early on. If you say N, you will have to provide, either here -+ or on the command line, the type (I/O or MMIO), IRQ and -+ address to use. If in doubt, say Y. -+ -+config KGDB_BAUDRATE -+ int "Debug serial port baud rate" -+ depends on (KGDB_8250 && KGDB_SIMPLE_SERIAL) -+ default "115200" -+ help -+ gdb and the kernel stub need to agree on the baud rate to be -+ used. Standard rates from 9600 to 115200 are allowed, and this -+ may be overridden via the commandline. -+ -+config KGDB_PORT_NUM -+ int "Serial port number for KGDB" -+ range 0 1 if KGDB_MPSC -+ range 0 3 -+ depends on (KGDB_8250 && KGDB_SIMPLE_SERIAL) || KGDB_MPSC -+ default "1" -+ help -+ Pick the port number (0 based) for KGDB to use. -+ -+config KGDB_8250_CONF_STRING -+ string "Configuration string for KGDB" -+ depends on KGDB_8250_NOMODULE && !KGDB_SIMPLE_SERIAL -+ default "io,2f8,115200,3" if X86 -+ help -+ The format of this string should be ,
,,. For example, to use the -+ serial port on an i386 box located at 0x2f8 and 115200 baud -+ on IRQ 3 at use: -+ io,2f8,115200,3 -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/net/core/netpoll.c linux-2.6.18-53.1.14.kgdb/net/core/netpoll.c ---- linux-2.6.18-53.1.14/net/core/netpoll.c 2008-03-06 05:54:27.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/net/core/netpoll.c 2008-06-10 15:37:49.000000000 +0400 -@@ -525,7 +525,8 @@ int __netpoll_rx(struct sk_buff *skb) - - np->rx_hook(np, ntohs(uh->source), - (char *)(uh+1), -- ulen - sizeof(struct udphdr)); -+ ulen - sizeof(struct udphdr), -+ skb); - - kfree_skb(skb); - return 1; -diff -rupbBN -X ../client-cleanup/dontdiff linux-2.6.18-53.1.14/scripts/dwarfh.awk linux-2.6.18-53.1.14.kgdb/scripts/dwarfh.awk ---- linux-2.6.18-53.1.14/scripts/dwarfh.awk 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.6.18-53.1.14.kgdb/scripts/dwarfh.awk 2008-06-10 15:39:01.000000000 +0400 -@@ -0,0 +1,19 @@ -+BEGIN { -+ print "#ifndef _ELF_DWARF_H" -+ print "/* Machine generated from dwarf2.h by scripts/dwarfh.awk */" -+} -+$2 == "=" { -+ gsub(/,/, "", $3) -+ print "#define " $1 "\t " $3 -+} -+$1 == "#define" { -+ print $0 -+ while( index($0,"\\") == length($0)){ -+ getline -+ print $0 -+ } -+} -+/.*/ {} -+END { -+ print "#endif" -+} diff --git a/lustre/kernel_patches/patches/lockdep_chains-2.6.18-vanilla.patch b/lustre/kernel_patches/patches/lockdep_chains-2.6.18-vanilla.patch deleted file mode 100644 index f0f3894..0000000 --- a/lustre/kernel_patches/patches/lockdep_chains-2.6.18-vanilla.patch +++ /dev/null @@ -1,269 +0,0 @@ -commit 443cd507ce7f78c6f8742b72736585c031d5a921 -Author: Huang, Ying -Date: Fri Jun 20 16:39:21 2008 +0800 - - lockdep: add lock_class information to lock_chain and output it - - This patch records array of lock_class into lock_chain, and export - lock_chain information via /proc/lockdep_chains. - - It is based on x86/master branch of git-x86 tree, and has been tested - on x86_64 platform. - - Signed-off-by: Huang Ying - Cc: Peter Zijlstra - Signed-off-by: Ingo Molnar - -diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h -index 4c4d236..b26fbc7 100644 ---- a/include/linux/lockdep.h -+++ b/include/linux/lockdep.h -@@ -182,6 +182,9 @@ struct lock_list { - * We record lock dependency chains, so that we can cache them: - */ - struct lock_chain { -+ u8 irq_context; -+ u8 depth; -+ u16 base; - struct list_head entry; - u64 chain_key; - }; -diff --git a/kernel/lockdep.c b/kernel/lockdep.c -index 81a4e4a..a796f1f 100644 ---- a/kernel/lockdep.c -+++ b/kernel/lockdep.c -@@ -1458,7 +1458,14 @@ out_bug: - } - - unsigned long nr_lock_chains; --static struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS]; -+struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS]; -+atomic_t nr_chain_hlocks; -+static u16 chain_hlocks[MAX_LOCKDEP_CHAIN_HLOCKS]; -+ -+struct lock_class *lock_chain_get_class(struct lock_chain *chain, int i) -+{ -+ return lock_classes + chain_hlocks[chain->base + i]; -+} - - /* - * Look up a dependency chain. If the key is not present yet then -@@ -1466,9 +1473,14 @@ static struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS]; - * validated. If the key is already hashed, return 0. - */ --static inline int lookup_chain_cache(u64 chain_key) -+static inline int lookup_chain_cache(struct task_struct *curr, -+ struct held_lock *hlock, -+ u64 chain_key) - { -+ struct lock_class *class = hlock->class; - struct list_head *hash_head = chainhashentry(chain_key); - struct lock_chain *chain; -+ struct held_lock *hlock_curr, *hlock_next; -+ int i, j, n; - - if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) - return 0; -@@ -1517,6 +1529,26 @@ cache_hit: - } - chain = lock_chains + nr_lock_chains++; - chain->chain_key = chain_key; -+ chain->irq_context = hlock->irq_context; -+ /* Find the first held_lock of current chain */ -+ hlock_next = hlock; -+ for (i = curr->lockdep_depth - 1; i >= 0; i--) { -+ hlock_curr = curr->held_locks + i; -+ if (hlock_curr->irq_context != hlock_next->irq_context) -+ break; -+ hlock_next = hlock; -+ } -+ i++; -+ chain->depth = curr->lockdep_depth + 1 - i; -+ n = atomic_add_return(chain->depth, &nr_chain_hlocks); -+ if (unlikely(n < MAX_LOCKDEP_CHAIN_HLOCKS)) { -+ chain->base = n - chain->depth; -+ for (j = 0; j < chain->depth - 1; j++, i++) { -+ int lock_id = curr->held_locks[i].class - lock_classes; -+ chain_hlocks[chain->base + j] = lock_id; -+ } -+ chain_hlocks[chain->base + j] = class - lock_classes; -+ } - list_add_tail_rcu(&chain->entry, hash_head); - debug_atomic_inc(&chain_lookup_misses); - inc_chains(); -@@ -1538,7 +1570,7 @@ static int validate_chain(struct task_struct *curr, struct lockdep_map *lock, - * (If lookup_chain_cache() returns with 1 it acquires - * hash_lock for us) - */ -- if (!trylock && (check == 2) && lookup_chain_cache(chain_key)) { -+ if (!trylock && (check == 2) && lookup_chain_cache(curr, hlock, chain_key)) { - /* - * Check whether last held lock: - * -diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h -index 8ce09bc..db09b17 100644 ---- a/kernel/lockdep_internals.h -+++ b/kernel/lockdep_internals.h -@@ -23,6 +23,8 @@ - #define MAX_LOCKDEP_CHAINS_BITS 14 - #define MAX_LOCKDEP_CHAINS (1UL << MAX_LOCKDEP_CHAINS_BITS) - -+#define MAX_LOCKDEP_CHAIN_HLOCKS (MAX_LOCKDEP_CHAINS*5) -+ - /* - * Stack-trace: tightly packed array of stack backtrace - * addresses. Protected by the hash_lock. -@@ -30,15 +32,19 @@ - #define MAX_STACK_TRACE_ENTRIES 262144UL - - extern struct list_head all_lock_classes; -+extern struct lock_chain lock_chains[]; - - extern void - get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4); - - extern const char * __get_key_name(struct lockdep_subclass_key *key, char *str); - -+struct lock_class *lock_chain_get_class(struct lock_chain *chain, int i); -+ - extern unsigned long nr_lock_classes; - extern unsigned long nr_list_entries; - extern unsigned long nr_lock_chains; -+extern atomic_t nr_chain_hlocks; - extern unsigned long nr_stack_trace_entries; - - extern unsigned int nr_hardirq_chains; -diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c -index 688c5f1..14d052c 100644 ---- a/kernel/lockdep_proc.c -+++ b/kernel/lockdep_proc.c -@@ -178,6 +178,110 @@ static const struct file_operations proc_lockdep_operations = { - .release = seq_release, - }; - -+static void print_name(struct seq_file *m, struct lock_class *class) -+{ -+ char str[128]; -+ const char *name = class->name; -+ -+ if (!name) { -+ name = __get_key_name(class->key, str); -+ seq_printf(m, "%s", name); -+ } else{ -+ seq_printf(m, "%s", name); -+ if (class->name_version > 1) -+ seq_printf(m, "#%d", class->name_version); -+ if (class->subclass) -+ seq_printf(m, "/%d", class->subclass); -+ } -+} -+ -+static void *lc_next(struct seq_file *m, void *v, loff_t *pos) -+{ -+ struct lock_chain *chain; -+ -+ (*pos)++; -+ -+ if (v == SEQ_START_TOKEN) -+ chain = m->private; -+ else { -+ chain = v; -+ -+ if (*pos < nr_lock_chains) -+ chain = lock_chains + *pos; -+ else -+ chain = NULL; -+ } -+ -+ return chain; -+} -+ -+static void *lc_start(struct seq_file *m, loff_t *pos) -+{ -+ if (*pos == 0) -+ return SEQ_START_TOKEN; -+ -+ if (*pos < nr_lock_chains) -+ return lock_chains + *pos; -+ -+ return NULL; -+} -+ -+static void lc_stop(struct seq_file *m, void *v) -+{ -+} -+ -+static int lc_show(struct seq_file *m, void *v) -+{ -+ struct lock_chain *chain = v; -+ struct lock_class *class; -+ int i; -+ -+ if (v == SEQ_START_TOKEN) { -+ seq_printf(m, "all lock chains:\n"); -+ return 0; -+ } -+ -+ seq_printf(m, "irq_context: %d\n", chain->irq_context); -+ -+ for (i = 0; i < chain->depth; i++) { -+ class = lock_chain_get_class(chain, i); -+ seq_printf(m, "[%p] ", class->key); -+ print_name(m, class); -+ seq_puts(m, "\n"); -+ } -+ seq_puts(m, "\n"); -+ -+ return 0; -+} -+ -+static const struct seq_operations lockdep_chains_ops = { -+ .start = lc_start, -+ .next = lc_next, -+ .stop = lc_stop, -+ .show = lc_show, -+}; -+ -+static int lockdep_chains_open(struct inode *inode, struct file *file) -+{ -+ int res = seq_open(file, &lockdep_chains_ops); -+ if (!res) { -+ struct seq_file *m = file->private_data; -+ -+ if (nr_lock_chains) -+ m->private = lock_chains; -+ else -+ m->private = NULL; -+ } -+ return res; -+} -+ -+static const struct file_operations proc_lockdep_chains_operations = { -+ .open = lockdep_chains_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = seq_release, -+}; -+ - static void lockdep_stats_debug_show(struct seq_file *m) - { - #ifdef CONFIG_DEBUG_LOCKDEP -@@ -294,5 +381,7 @@ static int lockdep_stats_show(struct seq_file *m, void *v) - - seq_printf(m, " dependency chains: %11lu [max: %lu]\n", - nr_lock_chains, MAX_LOCKDEP_CHAINS); -+ seq_printf(m, " dependency chain hlocks: %11d [max: %lu]\n", -+ atomic_read(&nr_chain_hlocks), MAX_LOCKDEP_CHAIN_HLOCKS); - - #ifdef CONFIG_TRACE_IRQFLAGS -@@ -661,6 +750,9 @@ static const struct file_operations proc_lock_stat_operations = { - entry = create_proc_entry("lockdep", S_IRUSR, NULL); - if (entry) - entry->proc_fops = &proc_lockdep_operations; -+ entry = create_proc_entry("lockdep_chains", S_IRUSR, NULL); -+ if (entry) -+ entry->proc_fops = &proc_lockdep_chains_operations; - - entry = create_proc_entry("lockdep_stats", S_IRUSR, NULL); - if (entry) -