Merge branch 'sh/dwarf-unwinder'
Paul Mundt [Sun, 11 Oct 2009 23:50:07 +0000 (08:50 +0900)]
Conflicts:
arch/sh/kernel/dwarf.c

1  2 
arch/sh/include/asm/dwarf.h
arch/sh/kernel/dwarf.c

Simple merge
@@@ -957,6 -954,92 +953,95 @@@ int dwarf_parse_section(char *eh_frame_
        printk(KERN_INFO "DWARF unwinder initialised: read %u CIEs, %u FDEs\n",
               c_entries, f_entries);
  
+       return 0;
+ out:
+       return err;
+ }
+ /**
+  *    dwarf_module_unload - remove FDE/CIEs associated with @mod
+  *    @mod: the module that is being unloaded
+  *
+  *    Remove any FDEs and CIEs from the global lists that came from
+  *    @mod's .eh_frame section because @mod is being unloaded.
+  */
+ void dwarf_module_unload(struct module *mod)
+ {
+       struct dwarf_fde *fde;
+       struct dwarf_cie *cie;
+       unsigned long flags;
+       spin_lock_irqsave(&dwarf_cie_lock, flags);
+ again_cie:
+       list_for_each_entry(cie, &dwarf_cie_list, link) {
+               if (cie->mod == mod)
+                       break;
+       }
+       if (&cie->link != &dwarf_cie_list) {
+               list_del(&cie->link);
+               kfree(cie);
+               goto again_cie;
+       }
+       spin_unlock_irqrestore(&dwarf_cie_lock, flags);
+       spin_lock_irqsave(&dwarf_fde_lock, flags);
+ again_fde:
+       list_for_each_entry(fde, &dwarf_fde_list, link) {
+               if (fde->mod == mod)
+                       break;
+       }
+       if (&fde->link != &dwarf_fde_list) {
+               list_del(&fde->link);
+               kfree(fde);
+               goto again_fde;
+       }
+       spin_unlock_irqrestore(&dwarf_fde_lock, flags);
+ }
+ /**
+  *    dwarf_unwinder_init - initialise the dwarf unwinder
+  *
+  *    Build the data structures describing the .dwarf_frame section to
+  *    make it easier to lookup CIE and FDE entries. Because the
+  *    .eh_frame section is packed as tightly as possible it is not
+  *    easy to lookup the FDE for a given PC, so we build a list of FDE
+  *    and CIE entries that make it easier.
+  */
+ static int __init dwarf_unwinder_init(void)
+ {
+       int err;
+       INIT_LIST_HEAD(&dwarf_cie_list);
+       INIT_LIST_HEAD(&dwarf_fde_list);
+       dwarf_frame_cachep = kmem_cache_create("dwarf_frames",
 -                      sizeof(struct dwarf_frame), 0, SLAB_PANIC, NULL);
++                      sizeof(struct dwarf_frame), 0,
++                      SLAB_PANIC | SLAB_HWCACHE_ALIGN | SLAB_NOTRACK, NULL);
++
+       dwarf_reg_cachep = kmem_cache_create("dwarf_regs",
 -                      sizeof(struct dwarf_reg), 0, SLAB_PANIC, NULL);
++                      sizeof(struct dwarf_reg), 0,
++                      SLAB_PANIC | SLAB_HWCACHE_ALIGN | SLAB_NOTRACK, NULL);
+       dwarf_frame_pool = mempool_create(DWARF_FRAME_MIN_REQ,
+                                         mempool_alloc_slab,
+                                         mempool_free_slab,
+                                         dwarf_frame_cachep);
+       dwarf_reg_pool = mempool_create(DWARF_REG_MIN_REQ,
+                                        mempool_alloc_slab,
+                                        mempool_free_slab,
+                                        dwarf_reg_cachep);
+       err = dwarf_parse_section(__start_eh_frame, __stop_eh_frame, NULL);
+       if (err)
+               goto out;
        err = unwinder_register(&dwarf_unwinder);
        if (err)
                goto out;