15a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel/*
2f30c2269544bffc7bf1b0d7c0abe5be1be83b8cbUwe Zeisberger * arch/xtensa/kernel/module.c
35a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel *
45a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel * Module support.
55a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel *
65a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel * This file is subject to the terms and conditions of the GNU General Public
75a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel * License.  See the file "COPYING" in the main directory of this archive
85a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel * for more details.
95a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel *
10ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel * Copyright (C) 2001 - 2006 Tensilica Inc.
115a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel *
125a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel * Chris Zankel <chris@zankel.net>
135a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel *
145a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel */
155a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel
165a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel#include <linux/module.h>
175a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel#include <linux/moduleloader.h>
185a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel#include <linux/elf.h>
195a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel#include <linux/vmalloc.h>
205a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel#include <linux/fs.h>
215a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel#include <linux/string.h>
225a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel#include <linux/kernel.h>
235a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel#include <linux/cache.h>
245a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel
25ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#undef DEBUG_RELOCATE
265a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel
27ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankelstatic int
28ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankeldecode_calln_opcode (unsigned char *location)
29ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel{
30ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef __XTENSA_EB__
31ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel	return (location[0] & 0xf0) == 0x50;
32ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif
33ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef __XTENSA_EL__
34ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel	return (location[0] & 0xf) == 0x5;
35ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif
36ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel}
37ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel
38ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankelstatic int
39ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankeldecode_l32r_opcode (unsigned char *location)
40ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel{
41ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef __XTENSA_EB__
42ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel	return (location[0] & 0xf0) == 0x10;
43ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif
44ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef __XTENSA_EL__
45ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel	return (location[0] & 0xf) == 0x1;
46ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif
475a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel}
485a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel
495a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankelint apply_relocate_add(Elf32_Shdr *sechdrs,
505a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel		       const char *strtab,
515a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel		       unsigned int symindex,
525a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel		       unsigned int relsec,
53ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		       struct module *mod)
545a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel{
55ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel	unsigned int i;
56c4c4594b005d89b56964071bbbdeb07daac5bc76Chris Zankel	Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
57ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel	Elf32_Sym *sym;
58ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel	unsigned char *location;
59ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel	uint32_t value;
60ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel
61ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef DEBUG_RELOCATE
62ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel	printk("Applying relocate section %u to %u\n", relsec,
63ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel	       sechdrs[relsec].sh_info);
64ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif
65ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
66ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		location = (char *)sechdrs[sechdrs[relsec].sh_info].sh_addr
67ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			+ rela[i].r_offset;
68ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
69ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			+ ELF32_R_SYM(rela[i].r_info);
70ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		value = sym->st_value + rela[i].r_addend;
71ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel
72ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		switch (ELF32_R_TYPE(rela[i].r_info)) {
73ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_NONE:
74ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_DIFF8:
75ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_DIFF16:
76ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_DIFF32:
77ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_ASM_EXPAND:
78ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			break;
79ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel
80ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_32:
81ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_PLT:
82ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			*(uint32_t *)location += value;
83ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			break;
84ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel
85ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT0_OP:
86ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			if (decode_calln_opcode(location)) {
87ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				value -= ((unsigned long)location & -4) + 4;
88ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				if ((value & 3) != 0 ||
89ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				    ((value + (1 << 19)) >> 20) != 0) {
90ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel					printk("%s: relocation out of range, "
91ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel					       "section %d reloc %d "
92ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel					       "sym '%s'\n",
93ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel					       mod->name, relsec, i,
94ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel					       strtab + sym->st_name);
95ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel					return -ENOEXEC;
96ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				}
97ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				value = (signed int)value >> 2;
98ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef __XTENSA_EB__
99ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				location[0] = ((location[0] & ~0x3) |
100ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel					    ((value >> 16) & 0x3));
101ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				location[1] = (value >> 8) & 0xff;
102ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				location[2] = value & 0xff;
103ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif
104ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef __XTENSA_EL__
105ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				location[0] = ((location[0] & ~0xc0) |
106ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel					    ((value << 6) & 0xc0));
107ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				location[1] = (value >> 2) & 0xff;
108ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				location[2] = (value >> 10) & 0xff;
109ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif
110ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			} else if (decode_l32r_opcode(location)) {
111ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				value -= (((unsigned long)location + 3) & -4);
112ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				if ((value & 3) != 0 ||
113ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				    (signed int)value >> 18 != -1) {
114ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel					printk("%s: relocation out of range, "
115ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel					       "section %d reloc %d "
116ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel					       "sym '%s'\n",
117ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel					       mod->name, relsec, i,
118ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel					       strtab + sym->st_name);
119ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel					return -ENOEXEC;
120ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				}
121ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				value = (signed int)value >> 2;
122ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel
123ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef __XTENSA_EB__
124ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				location[1] = (value >> 8) & 0xff;
125ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				location[2] = value & 0xff;
126ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif
127ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#ifdef __XTENSA_EL__
128ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				location[1] = value & 0xff;
129ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel				location[2] = (value >> 8) & 0xff;
130ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel#endif
131ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			}
132ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			/* FIXME: Ignore any other opcodes.  The Xtensa
133ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			   assembler currently assumes that the linker will
134ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			   always do relaxation and so all PC-relative
135ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			   operands need relocations.  (The assembler also
136ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			   writes out the tentative PC-relative values,
137ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			   assuming no link-time relaxation, so it is usually
138ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			   safe to ignore the relocations.)  If the
139ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			   assembler's "--no-link-relax" flag can be made to
140ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			   work, and if all kernel modules can be assembled
141ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			   with that flag, then unexpected relocations could
142ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			   be detected here.  */
143ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			break;
144ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel
145ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT1_OP:
146ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT2_OP:
147ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT3_OP:
148ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT4_OP:
149ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT5_OP:
150ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT6_OP:
151ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT7_OP:
152ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT8_OP:
153ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT9_OP:
154ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT10_OP:
155ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT11_OP:
156ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT12_OP:
157ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT13_OP:
158ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT14_OP:
159ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			printk("%s: unexpected FLIX relocation: %u\n",
160ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			       mod->name,
161ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			       ELF32_R_TYPE(rela[i].r_info));
162ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			return -ENOEXEC;
163ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel
164ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT0_ALT:
165ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT1_ALT:
166ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT2_ALT:
167ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT3_ALT:
168ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT4_ALT:
169ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT5_ALT:
170ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT6_ALT:
171ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT7_ALT:
172ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT8_ALT:
173ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT9_ALT:
174ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT10_ALT:
175ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT11_ALT:
176ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT12_ALT:
177ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT13_ALT:
178ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		case R_XTENSA_SLOT14_ALT:
179ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			printk("%s: unexpected ALT relocation: %u\n",
180ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			       mod->name,
181ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			       ELF32_R_TYPE(rela[i].r_info));
182ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			return -ENOEXEC;
183ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel
184ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		default:
185ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			printk("%s: unexpected relocation: %u\n",
186ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			       mod->name,
187ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			       ELF32_R_TYPE(rela[i].r_info));
188ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel			return -ENOEXEC;
189ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel		}
190ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel	}
191ff6fd469885aafa5ec387babcb6537f3c00d6df0Chris Zankel	return 0;
1925a0015d62668e64c8b6e02e360fbbea121bfd5e6Chris Zankel}
193