1#ifndef _ASM_IA64_MODULE_H 2#define _ASM_IA64_MODULE_H 3/* 4 * This file contains the ia64 architecture specific module code. 5 * 6 * Copyright (C) 2000 Intel Corporation. 7 * Copyright (C) 2000 Mike Stephens <mike.stephens@intel.com> 8 */ 9 10#include <linux/module.h> 11#include <linux/vmalloc.h> 12#include <asm/unwind.h> 13 14#define module_map(x) vmalloc(x) 15#define module_unmap(x) ia64_module_unmap(x) 16#define module_arch_init(x) ia64_module_init(x) 17 18/* 19 * This must match in size and layout the data created by 20 * modutils/obj/obj-ia64.c 21 */ 22struct archdata { 23 const char *unw_table; 24 const char *segment_base; 25 const char *unw_start; 26 const char *unw_end; 27 const char *gp; 28}; 29 30static inline void 31arch_init_modules (struct module *kmod) 32{ 33 static struct archdata archdata; 34 register char *kernel_gp asm ("gp"); 35 36 archdata.gp = kernel_gp; 37 kmod->archdata_start = (const char *) &archdata; 38 kmod->archdata_end = (const char *) (&archdata + 1); 39} 40 41/* 42 * functions to add/remove a modules unwind info when 43 * it is loaded or unloaded. 44 */ 45static inline int 46ia64_module_init (struct module *mod) 47{ 48 struct archdata *archdata; 49 50 if (!mod_member_present(mod, archdata_start) || !mod->archdata_start) 51 return 0; 52 archdata = (struct archdata *)(mod->archdata_start); 53 54 if (archdata->unw_start == 0) 55 return 0; 56 57 /* 58 * Make sure the unwind pointers are sane. 59 */ 60 61 if (archdata->unw_table) { 62 printk(KERN_ERR "module_arch_init: archdata->unw_table must be zero.\n"); 63 return 1; 64 } 65 if (!mod_bound(archdata->gp, 0, mod)) { 66 printk(KERN_ERR "module_arch_init: archdata->gp out of bounds.\n"); 67 return 1; 68 } 69 if (!mod_bound(archdata->unw_start, 0, mod)) { 70 printk(KERN_ERR "module_arch_init: archdata->unw_start out of bounds.\n"); 71 return 1; 72 } 73 if (!mod_bound(archdata->unw_end, 0, mod)) { 74 printk(KERN_ERR "module_arch_init: archdata->unw_end out of bounds.\n"); 75 return 1; 76 } 77 if (!mod_bound(archdata->segment_base, 0, mod)) { 78 printk(KERN_ERR "module_arch_init: archdata->segment_base out of bounds.\n"); 79 return 1; 80 } 81 82 /* 83 * Pointers are reasonable, add the module unwind table 84 */ 85 archdata->unw_table = unw_add_unwind_table(mod->name, 86 (unsigned long) archdata->segment_base, 87 (unsigned long) archdata->gp, 88 archdata->unw_start, archdata->unw_end); 89 return 0; 90} 91 92static inline void 93ia64_module_unmap (void * addr) 94{ 95 struct module *mod = (struct module *) addr; 96 struct archdata *archdata; 97 98 /* 99 * Before freeing the module memory remove the unwind table entry 100 */ 101 if (mod_member_present(mod, archdata_start) && mod->archdata_start) { 102 archdata = (struct archdata *)(mod->archdata_start); 103 104 if (archdata->unw_table != NULL) 105 unw_remove_unwind_table((void *) archdata->unw_table); 106 } 107 108 vfree(addr); 109} 110 111#endif /* _ASM_IA64_MODULE_H */ 112