[PATCH] fix KDB backtrace for ppc64

Ananth N Mavinakayanahalli ananth at in.ibm.com
Thu May 6 00:16:47 EST 2004


Hi Anton,

Here is a patch that fixes backtracing in KDB for ppc64. We were not
handling the link register and were missing an intermediate call
during bt.

The patch also contains updates to bring KDB in Ameslab to the latest
SGI released level.

Please apply!


Thanks,
Ananth
--
Ananth Narayan
Linux Technology Center,
IBM Software Lab, INDIA


diff -Naurp temp/ameslab/arch/ppc64/kdb/kdba_bt.c ameslab/arch/ppc64/kdb/kdba_bt.c
--- temp/ameslab/arch/ppc64/kdb/kdba_bt.c	2004-04-22 21:52:09.000000000 -0700
+++ ameslab/arch/ppc64/kdb/kdba_bt.c	2004-05-05 02:51:12.321319240 -0700
@@ -101,17 +101,15 @@ kdba_bt_stack_ppc(struct pt_regs *regs,
 		   struct task_struct *p, int regs_esp)
 {

-	kdb_machreg_t	esp,eip,ebp,old_esp;
-/*	kdb_symtab_t	symtab, *sym; */
-	kdbtbtable_t	tbtab;
+	kdb_machreg_t	esp, eip, ebp, old_esp;
 	/* declare these as raw ptrs so we don't get func descriptors */
 	extern void *ret_from_except, *ret_from_syscall_1;
-/*	int do_bottom_half_ret=0; */

 	const char *name;
-	char namebuf[128];
-	unsigned long symsize,symoffset;
+	unsigned long symsize, symoffset;
 	char *symmodname;
+	int flag = 0;
+	char namebuf[128];

 	/*
 	 * The caller may have supplied an address at which the
@@ -155,7 +153,8 @@ kdba_bt_stack_ppc(struct pt_regs *regs,

 	kdb_printf("          SP(esp)            PC(eip)      Function(args)\n");

-	/* (Ref: 64-bit PowerPC ELF ABI Spplement; Ian Lance Taylor, Zembu Labs).
+	/* (Ref: 64-bit PowerPC ELF ABI Supplement:
+				Ian Lance Taylor, Zembu Labs).
 	 A PPC stack frame looks like this:

 	 High Address
@@ -180,18 +179,15 @@ kdba_bt_stack_ppc(struct pt_regs *regs,
 	 */
 	while (1) {
 		kdb_printf("0x%016lx  0x%016lx  ", esp, eip);
-		/*		kdbnearsym(eip, &symtab); */
-		kdba_find_tb_table(eip, &tbtab);
-
-		/* sym = symtab.sym_name ? &symtab : &tbtab.symtab; */
-		/* use fake symtab if necessary */
 		name = NULL;
 		if (esp >= PAGE_OFFSET) {
-			/*if ((sym) )*/
-			/* if this fails, eip is outside of kernel space, dont trust it. */
+			/*
+			 * if this fails, eip is outside of kernel space,
+			 * dont trust it.
+			 */
 			if (eip > PAGE_OFFSET) {
-				name = kallsyms_lookup(eip, &symsize, &symoffset, &symmodname,
-						       namebuf);
+				name = kallsyms_lookup(eip, &symsize,
+					&symoffset, &symmodname, namebuf);
 			}
 			if (name) {
 				kdb_printf("%s", name);
@@ -200,25 +196,49 @@ kdba_bt_stack_ppc(struct pt_regs *regs,
 			}
 		}

-		/* if this fails, eip is outside of kernel space, dont trust data. */
+		/*
+		 * if this fails, eip is outside of kernel space,
+		 * dont trust data.
+		 */
 		if (eip > PAGE_OFFSET) {
 			if (eip - symoffset > 0) {
 				kdb_printf(" +0x%lx", /*eip -*/ symoffset);
 			}
 		}
 		kdb_printf("\n");
+		if (!flag && (task_curr(p))) {
+			kdb_machreg_t lr;
+			unsigned long start = 0, end = 0;
+
+			flag++;
+			lr = regs->link;
+			if ((lr < PAGE_OFFSET) || (lr == eip))
+				goto next_frame;
+
+			start = eip - symoffset;
+			end = eip - symoffset + symsize;
+			if (lr >= start && lr < end)
+				goto next_frame;
+
+			name = NULL;
+			name = kallsyms_lookup(lr, &symsize,
+				&symoffset, &symmodname, namebuf);
+			if (name)
+				kdb_printf("0x%016lx  0x%016lx (lr) %s +0x%lx\n",
+					esp, lr, name, symoffset);
+		}

-		/* ret_from_except=0xa5e0 ret_from_syscall_1=a378 do_bottom_half_ret=a5e0 */
+next_frame:
 		if (esp < PAGE_OFFSET) { /* below kernelspace..   */
 			kdb_printf("<Stack contents outside of kernel space.  %.16lx>\n", esp );
 			break;
 		} else {
 			if (eip == (kdb_machreg_t)ret_from_except ||
-			    eip == (kdb_machreg_t)ret_from_syscall_1 /* ||
-								      eip == (kdb_machreg_t)do_bottom_half_ret */) {
+			    eip == (kdb_machreg_t)ret_from_syscall_1) {
 				/* pull exception regs from the stack */
 				struct pt_regs eregs;
-				kdba_getmem(esp+STACK_FRAME_OVERHEAD, &eregs, sizeof(eregs));
+				kdba_getmem(esp+STACK_FRAME_OVERHEAD,
+							&eregs, sizeof(eregs));
 				kdb_printf("  [exception: %lx:%s regs 0x%lx] "
 				           "nip:[0x%lx] gpr[1]:[0x%lx]\n",
 				           eregs.trap,getvecname(eregs.trap),
@@ -236,7 +256,10 @@ kdba_bt_stack_ppc(struct pt_regs *regs,
 						break;
 					}
 				}
-				/* we want to follow exception registers, not into user stack.  ...   */
+				/*
+				 * we want to follow exception registers,
+				 * not into user stack.  ...
+				 */
 				esp = eregs.gpr[1];
 				eip = eregs.nip;
 			} else {
diff -Naurp temp/ameslab/kdb/ChangeLog ameslab/kdb/ChangeLog
--- temp/ameslab/kdb/ChangeLog	2004-05-04 02:07:51.000000000 -0700
+++ ameslab/kdb/ChangeLog	2004-05-05 02:51:18.168228408 -0700
@@ -1,3 +1,8 @@
+2004-04-30 Keith Owens  <kaos at sgi.com>
+
+	* Rewrite inode_pages command for new radix code in struct page.
+	* kdb v4.3-2.6.6-rc1-common-1.
+
 2004-04-11 Keith Owens  <kaos at sgi.com>

 	* Unlock sn_sal_lock before entering kdb from sn_serial.
diff -Naurp temp/ameslab/kdb/gen-kdb_cmds.c ameslab/kdb/gen-kdb_cmds.c
--- temp/ameslab/kdb/gen-kdb_cmds.c	2004-04-22 21:54:41.000000000 -0700
+++ ameslab/kdb/gen-kdb_cmds.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,4 +0,0 @@
-#include <linux/init.h>
-char __initdata *kdb_cmds[] = {
-  0
-};
diff -Naurp temp/ameslab/kdb/modules/kdbm_pg.c ameslab/kdb/modules/kdbm_pg.c
--- temp/ameslab/kdb/modules/kdbm_pg.c	2004-05-04 02:07:51.000000000 -0700
+++ ameslab/kdb/modules/kdbm_pg.c	2004-05-05 03:07:16.033237072 -0700
@@ -151,42 +151,25 @@ kdbm_page(int argc, const char **argv, c
 	long	offset=0;
 	int nextarg;
 	int diag;
-	int lookup_page = 0;

-	if (argc == 2) {
-		if (strcmp(argv[1], "-s") != 0) {
-			return KDB_ARGCOUNT;
-		}
-		lookup_page = 1;
-	} else if (argc != 1) {
+	if (argc != 1)
 		return KDB_ARGCOUNT;
-	}

-	nextarg = argc;
+	nextarg = 1;
 	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
 	if (diag)
 		return diag;

-	/* Assume argument is a page number, not address */
 	if (addr < PAGE_OFFSET)
 		addr = (unsigned long) &mem_map[addr];

-	/* Get the struct page * that corresponds to this addr */
-	if (lookup_page)
-	{
-		addr = (unsigned long) virt_to_page(addr);
-	}
-
 	if ((diag = kdb_getarea(page, addr)))
 		return(diag);

 	kdb_printf("struct page at 0x%lx\n", addr);
-/*	kdb_printf("  next 0x%p prev 0x%p addr space 0x%p index %lu (offset 0x%x)\n",
-		   page.list.next, page.list.prev, page.mapping, page.index,
-		   (int)(page.index << PAGE_CACHE_SHIFT)); */
-	kdb_printf("  addr space 0x%p index %lu (offset 0x%x)\n",
+	kdb_printf("  addr space 0x%p index %lu (offset 0x%llx)\n",
 		   page.mapping, page.index,
-		   (int)(page.index << PAGE_CACHE_SHIFT));
+		   (unsigned long long)page.index << PAGE_CACHE_SHIFT);
 	kdb_printf("  count %d flags %s\n",
 		   page.count.counter, page_flags(page.flags));
 	kdb_printf("  virtual 0x%p\n", page_address((struct page *)addr));
@@ -276,7 +259,7 @@ kdbm_rqueue(int argc, const char **argv,
 	return 0;
 }

-/* routine not used currently.. sync with upstream later
+
 static void
 do_buffer(unsigned long addr)
 {
@@ -285,13 +268,54 @@ do_buffer(unsigned long addr)
 	if (kdb_getarea(bh, addr))
 		return;

-	kdb_printf("bh 0x%lx bno %8llu [%s]\n", addr,
+	kdb_printf(" bh 0x%lx bno %8llu [%s]", addr,
 		 (unsigned long long)bh.b_blocknr,
 		 map_flags(bh.b_state, bh_state_vals));
 }
-*/

-/* inode_struct changed in 2.6.6-rc series.. sync with upstream later
+static void
+kdbm_show_page(struct page *page, int first)
+{
+	if (first)
+		kdb_printf("page_struct       index   cnt zone nid flags\n");
+	kdb_printf("%p%s %6lu %5d %3ld %3ld 0x%lx",
+		page_address(page), sizeof(void *) == 4 ? "        " : "",
+		page->index, atomic_read(&(page->count)),
+		page_zonenum(page), page_to_nid(page),
+		page->flags & (~0UL >> ZONES_SHIFT));
+#define kdb_page_flags(page, type) if (Page ## type(page)) kdb_printf(" " #type);
+	kdb_page_flags(page, Locked);
+	kdb_page_flags(page, Error);
+	kdb_page_flags(page, Referenced);
+	kdb_page_flags(page, Uptodate);
+	kdb_page_flags(page, Dirty);
+	kdb_page_flags(page, LRU);
+	kdb_page_flags(page, Active);
+	kdb_page_flags(page, Slab);
+	kdb_page_flags(page, HighMem);
+	kdb_page_flags(page, Checked);
+	if (page->flags & (1UL << PG_arch_1))
+		kdb_printf(" arch_1");
+	kdb_page_flags(page, Reserved);
+	kdb_page_flags(page, Private);
+	kdb_page_flags(page, Writeback);
+	kdb_page_flags(page, Nosave);
+	if (page->flags & (1UL << PG_maplock))
+		kdb_printf(" maplock");
+	kdb_page_flags(page, Direct);
+	kdb_page_flags(page, MappedToDisk);
+	kdb_page_flags(page, Reclaim);
+	kdb_page_flags(page, Compound);
+	kdb_page_flags(page, Anon);
+	kdb_page_flags(page, SwapCache);
+	if (page_has_buffers(page))
+		do_buffer((unsigned long) page_buffers(page));
+	else if (page->private)
+		kdb_printf(" private=0x%lx", page->private);
+	kdb_printf("\n");
+#undef kdb_page_flags
+}
+
 static int
 kdbm_inode_pages(int argc, const char **argv, const char **envp,
 	struct pt_regs *regs)
@@ -302,12 +326,9 @@ kdbm_inode_pages(int argc, const char **
 	long offset=0;
 	int nextarg;
 	int diag;
-	int which=0;
-
-	struct list_head *head, *curr;
-
-	if (argc < 1)
-		return KDB_ARGCOUNT;
+	pgoff_t next = 0;
+	struct page *page;
+	int first;

 	nextarg = 1;
 	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
@@ -321,6 +342,7 @@ kdbm_inode_pages(int argc, const char **
 		if (diag)
 			goto out;
 		kdb_printf("Looking for page index 0x%lx ... \n", addr1);
+		next = addr1;
 	}

 	if (!(inode = kmalloc(sizeof(*inode), GFP_ATOMIC))) {
@@ -340,58 +362,23 @@ kdbm_inode_pages(int argc, const char **
 	if ((diag = kdb_getarea(*ap, (unsigned long) inode->i_mapping)))
 		goto out;

- again:
-	if (which == 0){
-	  which=1;
-	  head = &inode->i_mapping->clean_pages;
-	  kdb_printf("CLEAN  page_struct   index  cnt  flags\n");
-	} else if (which == 1) {
-	  which=2;
-	  head = &inode->i_mapping->dirty_pages;
-	  kdb_printf("DIRTY  page_struct   index  cnt  flags\n");
-	} else if (which == 2) {
-	  which=3;
-	  head = &inode->i_mapping->locked_pages;
-	  kdb_printf("LOCKED page_struct   index  cnt  flags\n");
-	} else {
-	  goto out;
+	/* Run the pages in the radix tree, printing the state of each page */
+	first = 1;
+ 	while (radix_tree_gang_lookup(&ap->page_tree, (void **)&page, next, 1)) {
+		kdbm_show_page(page, first);
+		if (addr1)
+			break;
+		first = 0;
+		next = page->index + 1;
 	}
-
-	curr = head->next;
-	while (curr != head) {
-		struct page 	 page;
-		struct list_head curr_struct;
-
-		addr = (unsigned long) list_entry(curr, struct page, list);
-		if ((diag = kdb_getarea(page, addr)))
-			goto out;
-
-		if (!addr1 || page.index == addr1 ||
-			(addr1 == -1 && (page.flags & ( 1 << PG_locked))))
-		{
-			kdb_printf("    0x%lx    %6lu    %5d    0x%lx ",
-				addr, page.index, page.count.counter,
-				page.flags);
-			if (page_has_buffers(&page))
-				do_buffer((unsigned long) page_buffers(&page));
-			else
-				kdb_printf("bh [NULL]\n");
-		}
-
-		if ((diag = kdb_getarea(curr_struct, (unsigned long) curr)))
-			goto out;
-
-		curr = curr_struct.next;
-	}
-	goto again;
- out:
+
+out:
 	if (inode)
 		kfree(inode);
 	if (ap)
 		kfree(ap);
 	return diag;
 }
-*/

 static int
 kdbm_inode(int argc, const char **argv, const char **envp,
@@ -567,13 +554,12 @@ kdbm_memmap(int argc, const char **argv,
 static int __init kdbm_pg_init(void)
 {
 #ifndef CONFIG_DISCONTIGMEM
-	kdb_register("page", kdbm_page, "[-s] <vaddr>", "Display page [or page of addr]", 0);
+	kdb_register("page", kdbm_page, "<vaddr>", "Display page", 0);
 #endif
 	kdb_register("inode", kdbm_inode, "<vaddr>", "Display inode", 0);
 	kdb_register("sb", kdbm_sb, "<vaddr>", "Display super_block", 0);
 	kdb_register("bh", kdbm_buffers, "<buffer head address>", "Display buffer", 0);
-/* inode struct changed in 2.6.6-rc series.. sync with upstream later
-	kdb_register("inode_pages", kdbm_inode_pages, "<inode *>", "Display pages in an inode", 0); */
+	kdb_register("inode_pages", kdbm_inode_pages, "<inode *>", "Display pages in an inode", 0);
 	kdb_register("req", kdbm_request, "<vaddr>", "dump request struct", 0);
 	kdb_register("rqueue", kdbm_rqueue, "<vaddr>", "dump request queue", 0);
 #if	defined(CONFIG_X86) | defined(CONFIG_PPC64)

** Sent via the linuxppc64-dev mail list. See http://lists.linuxppc.org/





More information about the Linuxppc64-dev mailing list