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