aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/kernel/module.c')
-rw-r--r--arch/blackfin/kernel/module.c111
1 files changed, 60 insertions, 51 deletions
diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c
index 50d7fbfe1ce6..2ad805e67afc 100644
--- a/arch/blackfin/kernel/module.c
+++ b/arch/blackfin/kernel/module.c
@@ -53,7 +53,7 @@ void module_free(struct module *mod, void *module_region)
53 53
54/* Transfer the section to the L1 memory */ 54/* Transfer the section to the L1 memory */
55int 55int
56module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, 56module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
57 char *secstrings, struct module *mod) 57 char *secstrings, struct module *mod)
58{ 58{
59 /* 59 /*
@@ -64,12 +64,18 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
64 * NOTE: this breaks the semantic of mod->arch structure. 64 * NOTE: this breaks the semantic of mod->arch structure.
65 */ 65 */
66 Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum; 66 Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
67 void *dest = NULL; 67 void *dest;
68 68
69 for (s = sechdrs; s < sechdrs_end; ++s) { 69 for (s = sechdrs; s < sechdrs_end; ++s) {
70 if ((strcmp(".l1.text", secstrings + s->sh_name) == 0) || 70 const char *shname = secstrings + s->sh_name;
71 ((strcmp(".text", secstrings + s->sh_name) == 0) && 71
72 (hdr->e_flags & EF_BFIN_CODE_IN_L1) && (s->sh_size > 0))) { 72 if (s->sh_size == 0)
73 continue;
74
75 if (!strcmp(".l1.text", shname) ||
76 (!strcmp(".text", shname) &&
77 (hdr->e_flags & EF_BFIN_CODE_IN_L1))) {
78
73 dest = l1_inst_sram_alloc(s->sh_size); 79 dest = l1_inst_sram_alloc(s->sh_size);
74 mod->arch.text_l1 = dest; 80 mod->arch.text_l1 = dest;
75 if (dest == NULL) { 81 if (dest == NULL) {
@@ -78,12 +84,11 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
78 return -1; 84 return -1;
79 } 85 }
80 dma_memcpy(dest, (void *)s->sh_addr, s->sh_size); 86 dma_memcpy(dest, (void *)s->sh_addr, s->sh_size);
81 s->sh_flags &= ~SHF_ALLOC; 87
82 s->sh_addr = (unsigned long)dest; 88 } else if (!strcmp(".l1.data", shname) ||
83 } 89 (!strcmp(".data", shname) &&
84 if ((strcmp(".l1.data", secstrings + s->sh_name) == 0) || 90 (hdr->e_flags & EF_BFIN_DATA_IN_L1))) {
85 ((strcmp(".data", secstrings + s->sh_name) == 0) && 91
86 (hdr->e_flags & EF_BFIN_DATA_IN_L1) && (s->sh_size > 0))) {
87 dest = l1_data_sram_alloc(s->sh_size); 92 dest = l1_data_sram_alloc(s->sh_size);
88 mod->arch.data_a_l1 = dest; 93 mod->arch.data_a_l1 = dest;
89 if (dest == NULL) { 94 if (dest == NULL) {
@@ -92,12 +97,11 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
92 return -1; 97 return -1;
93 } 98 }
94 memcpy(dest, (void *)s->sh_addr, s->sh_size); 99 memcpy(dest, (void *)s->sh_addr, s->sh_size);
95 s->sh_flags &= ~SHF_ALLOC; 100
96 s->sh_addr = (unsigned long)dest; 101 } else if (!strcmp(".l1.bss", shname) ||
97 } 102 (!strcmp(".bss", shname) &&
98 if (strcmp(".l1.bss", secstrings + s->sh_name) == 0 || 103 (hdr->e_flags & EF_BFIN_DATA_IN_L1))) {
99 ((strcmp(".bss", secstrings + s->sh_name) == 0) && 104
100 (hdr->e_flags & EF_BFIN_DATA_IN_L1) && (s->sh_size > 0))) {
101 dest = l1_data_sram_zalloc(s->sh_size); 105 dest = l1_data_sram_zalloc(s->sh_size);
102 mod->arch.bss_a_l1 = dest; 106 mod->arch.bss_a_l1 = dest;
103 if (dest == NULL) { 107 if (dest == NULL) {
@@ -105,10 +109,9 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
105 mod->name); 109 mod->name);
106 return -1; 110 return -1;
107 } 111 }
108 s->sh_flags &= ~SHF_ALLOC; 112
109 s->sh_addr = (unsigned long)dest; 113 } else if (!strcmp(".l1.data.B", shname)) {
110 } 114
111 if (strcmp(".l1.data.B", secstrings + s->sh_name) == 0) {
112 dest = l1_data_B_sram_alloc(s->sh_size); 115 dest = l1_data_B_sram_alloc(s->sh_size);
113 mod->arch.data_b_l1 = dest; 116 mod->arch.data_b_l1 = dest;
114 if (dest == NULL) { 117 if (dest == NULL) {
@@ -117,10 +120,9 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
117 return -1; 120 return -1;
118 } 121 }
119 memcpy(dest, (void *)s->sh_addr, s->sh_size); 122 memcpy(dest, (void *)s->sh_addr, s->sh_size);
120 s->sh_flags &= ~SHF_ALLOC; 123
121 s->sh_addr = (unsigned long)dest; 124 } else if (!strcmp(".l1.bss.B", shname)) {
122 } 125
123 if (strcmp(".l1.bss.B", secstrings + s->sh_name) == 0) {
124 dest = l1_data_B_sram_alloc(s->sh_size); 126 dest = l1_data_B_sram_alloc(s->sh_size);
125 mod->arch.bss_b_l1 = dest; 127 mod->arch.bss_b_l1 = dest;
126 if (dest == NULL) { 128 if (dest == NULL) {
@@ -129,12 +131,11 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
129 return -1; 131 return -1;
130 } 132 }
131 memset(dest, 0, s->sh_size); 133 memset(dest, 0, s->sh_size);
132 s->sh_flags &= ~SHF_ALLOC; 134
133 s->sh_addr = (unsigned long)dest; 135 } else if (!strcmp(".l2.text", shname) ||
134 } 136 (!strcmp(".text", shname) &&
135 if ((strcmp(".l2.text", secstrings + s->sh_name) == 0) || 137 (hdr->e_flags & EF_BFIN_CODE_IN_L2))) {
136 ((strcmp(".text", secstrings + s->sh_name) == 0) && 138
137 (hdr->e_flags & EF_BFIN_CODE_IN_L2) && (s->sh_size > 0))) {
138 dest = l2_sram_alloc(s->sh_size); 139 dest = l2_sram_alloc(s->sh_size);
139 mod->arch.text_l2 = dest; 140 mod->arch.text_l2 = dest;
140 if (dest == NULL) { 141 if (dest == NULL) {
@@ -143,12 +144,11 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
143 return -1; 144 return -1;
144 } 145 }
145 memcpy(dest, (void *)s->sh_addr, s->sh_size); 146 memcpy(dest, (void *)s->sh_addr, s->sh_size);
146 s->sh_flags &= ~SHF_ALLOC; 147
147 s->sh_addr = (unsigned long)dest; 148 } else if (!strcmp(".l2.data", shname) ||
148 } 149 (!strcmp(".data", shname) &&
149 if ((strcmp(".l2.data", secstrings + s->sh_name) == 0) || 150 (hdr->e_flags & EF_BFIN_DATA_IN_L2))) {
150 ((strcmp(".data", secstrings + s->sh_name) == 0) && 151
151 (hdr->e_flags & EF_BFIN_DATA_IN_L2) && (s->sh_size > 0))) {
152 dest = l2_sram_alloc(s->sh_size); 152 dest = l2_sram_alloc(s->sh_size);
153 mod->arch.data_l2 = dest; 153 mod->arch.data_l2 = dest;
154 if (dest == NULL) { 154 if (dest == NULL) {
@@ -157,12 +157,11 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
157 return -1; 157 return -1;
158 } 158 }
159 memcpy(dest, (void *)s->sh_addr, s->sh_size); 159 memcpy(dest, (void *)s->sh_addr, s->sh_size);
160 s->sh_flags &= ~SHF_ALLOC; 160
161 s->sh_addr = (unsigned long)dest; 161 } else if (!strcmp(".l2.bss", shname) ||
162 } 162 (!strcmp(".bss", shname) &&
163 if (strcmp(".l2.bss", secstrings + s->sh_name) == 0 || 163 (hdr->e_flags & EF_BFIN_DATA_IN_L2))) {
164 ((strcmp(".bss", secstrings + s->sh_name) == 0) && 164
165 (hdr->e_flags & EF_BFIN_DATA_IN_L2) && (s->sh_size > 0))) {
166 dest = l2_sram_zalloc(s->sh_size); 165 dest = l2_sram_zalloc(s->sh_size);
167 mod->arch.bss_l2 = dest; 166 mod->arch.bss_l2 = dest;
168 if (dest == NULL) { 167 if (dest == NULL) {
@@ -170,10 +169,14 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
170 mod->name); 169 mod->name);
171 return -1; 170 return -1;
172 } 171 }
173 s->sh_flags &= ~SHF_ALLOC; 172
174 s->sh_addr = (unsigned long)dest; 173 } else
175 } 174 continue;
175
176 s->sh_flags &= ~SHF_ALLOC;
177 s->sh_addr = (unsigned long)dest;
176 } 178 }
179
177 return 0; 180 return 0;
178} 181}
179 182
@@ -295,22 +298,28 @@ module_finalize(const Elf_Ehdr * hdr,
295 for (i = 1; i < hdr->e_shnum; i++) { 298 for (i = 1; i < hdr->e_shnum; i++) {
296 const char *strtab = (char *)sechdrs[strindex].sh_addr; 299 const char *strtab = (char *)sechdrs[strindex].sh_addr;
297 unsigned int info = sechdrs[i].sh_info; 300 unsigned int info = sechdrs[i].sh_info;
301 const char *shname = secstrings + sechdrs[i].sh_name;
298 302
299 /* Not a valid relocation section? */ 303 /* Not a valid relocation section? */
300 if (info >= hdr->e_shnum) 304 if (info >= hdr->e_shnum)
301 continue; 305 continue;
302 306
303 if ((sechdrs[i].sh_type == SHT_RELA) && 307 /* Only support RELA relocation types */
304 ((strcmp(".rela.l2.text", secstrings + sechdrs[i].sh_name) == 0) || 308 if (sechdrs[i].sh_type != SHT_RELA)
305 (strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) || 309 continue;
306 ((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) && 310
307 (hdr->e_flags & (EF_BFIN_CODE_IN_L1|EF_BFIN_CODE_IN_L2))))) { 311 if (!strcmp(".rela.l2.text", shname) ||
312 !strcmp(".rela.l1.text", shname) ||
313 (!strcmp(".rela.text", shname) &&
314 (hdr->e_flags & (EF_BFIN_CODE_IN_L1 | EF_BFIN_CODE_IN_L2)))) {
315
308 err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab, 316 err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
309 symindex, i, mod); 317 symindex, i, mod);
310 if (err < 0) 318 if (err < 0)
311 return -ENOEXEC; 319 return -ENOEXEC;
312 } 320 }
313 } 321 }
322
314 return 0; 323 return 0;
315} 324}
316 325