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.