[PATCH] fix KDB backtrace for ppc64 (reworked)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, May 05, 2004 at 01:20:42PM -0500, linas at austin.ibm.com wrote:
> 
> On Wed, May 05, 2004 at 07:16:47PM +0500, Ananth N Mavinakayanahalli wrote:
> > @@ -200,25 +196,49 @@ kdba_bt_stack_ppc(struct pt_regs *regs,
> > +		if (!flag && (task_curr(p))) {
> > +
> > +			lr = regs->link;
> 
> Its not obvious that regs might not be a null pointer.  Code
> higher up tries to make sure that regs is set to something,
> but its not clear that every branch is correctly handled.
> 

Right.. Here is a reworked patch that handles NULL regs.


Anton,

Please consider this patch for inclusion to Ameslab.


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 22:06:39.401239784 -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,50 @@ 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++;
+			if ((!regs) || (regs->link < PAGE_OFFSET) || 
+					(regs->link == eip))
+				goto next_frame;
+
+			lr = regs->link;
+			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 +257,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)
---------------------------
Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe.


[Index of Archives]     [Linux Kernel Development]     [Linux Kernel Newbies]     [Linux USB Development]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux