~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/kernel/module_32.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /arch/powerpc/kernel/module_32.c (Architecture sparc64) and /arch/ppc/kernel/module_32.c (Architecture ppc)


  1 // SPDX-License-Identifier: GPL-2.0-or-later        1 
  2 /*  Kernel module help for PPC.                   
  3     Copyright (C) 2001 Rusty Russell.             
  4                                                   
  5 */                                                
  6                                                   
  7 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt       
  8                                                   
  9 #include <linux/module.h>                         
 10 #include <linux/moduleloader.h>                   
 11 #include <linux/elf.h>                            
 12 #include <linux/vmalloc.h>                        
 13 #include <linux/fs.h>                             
 14 #include <linux/string.h>                         
 15 #include <linux/kernel.h>                         
 16 #include <linux/ftrace.h>                         
 17 #include <linux/cache.h>                          
 18 #include <linux/bug.h>                            
 19 #include <linux/sort.h>                           
 20 #include <asm/setup.h>                            
 21 #include <asm/code-patching.h>                    
 22                                                   
 23 /* Count how many different relocations (diffe    
 24    addend) */                                     
 25 static unsigned int count_relocs(const Elf32_R    
 26 {                                                 
 27         unsigned int i, r_info, r_addend, _cou    
 28                                                   
 29         _count_relocs = 0;                        
 30         r_info = 0;                               
 31         r_addend = 0;                             
 32         for (i = 0; i < num; i++)                 
 33                 /* Only count 24-bit relocs, o    
 34                 if (ELF32_R_TYPE(rela[i].r_inf    
 35                     (r_info != ELF32_R_SYM(rel    
 36                      r_addend != rela[i].r_add    
 37                         _count_relocs++;          
 38                         r_info = ELF32_R_SYM(r    
 39                         r_addend = rela[i].r_a    
 40                 }                                 
 41                                                   
 42 #ifdef CONFIG_DYNAMIC_FTRACE                      
 43         _count_relocs++;        /* add one for    
 44 #endif                                            
 45         return _count_relocs;                     
 46 }                                                 
 47                                                   
 48 static int relacmp(const void *_x, const void     
 49 {                                                 
 50         const Elf32_Rela *x, *y;                  
 51                                                   
 52         y = (Elf32_Rela *)_x;                     
 53         x = (Elf32_Rela *)_y;                     
 54                                                   
 55         /* Compare the entire r_info (as oppos    
 56          * make the comparison cheaper/faster.    
 57          * the counting algorithms' performanc    
 58          */                                       
 59         if (x->r_info < y->r_info)                
 60                 return -1;                        
 61         else if (x->r_info > y->r_info)           
 62                 return 1;                         
 63         else if (x->r_addend < y->r_addend)       
 64                 return -1;                        
 65         else if (x->r_addend > y->r_addend)       
 66                 return 1;                         
 67         else                                      
 68                 return 0;                         
 69 }                                                 
 70                                                   
 71 /* Get the potential trampolines size required    
 72    non-init sections */                           
 73 static unsigned long get_plt_size(const Elf32_    
 74                                   const Elf32_    
 75                                   const char *    
 76                                   int is_init)    
 77 {                                                 
 78         unsigned long ret = 0;                    
 79         unsigned i;                               
 80                                                   
 81         /* Everything marked ALLOC (this inclu    
 82            symbols) */                            
 83         for (i = 1; i < hdr->e_shnum; i++) {      
 84                 /* If it's called *.init*, and    
 85                    not interested */              
 86                 if ((strstr(secstrings + sechd    
 87                     != is_init)                   
 88                         continue;                 
 89                                                   
 90                 /* We don't want to look at de    
 91                 if (strstr(secstrings + sechdr    
 92                         continue;                 
 93                                                   
 94                 if (sechdrs[i].sh_type == SHT_    
 95                         pr_debug("Found reloca    
 96                         pr_debug("Ptr: %p.  Nu    
 97                                (void *)hdr + s    
 98                                sechdrs[i].sh_s    
 99                                                   
100                         /* Sort the relocation    
101                          * addend key. This is    
102                          * algorithm but it wi    
103                          * count_relocs() to l    
104                          */                       
105                         sort((void *)hdr + sec    
106                              sechdrs[i].sh_siz    
107                              sizeof(Elf32_Rela    
108                                                   
109                         ret += count_relocs((v    
110                                              +    
111                                              s    
112                                              /    
113                                 * sizeof(struc    
114                 }                                 
115         }                                         
116                                                   
117         return ret;                               
118 }                                                 
119                                                   
120 int module_frob_arch_sections(Elf32_Ehdr *hdr,    
121                               Elf32_Shdr *sech    
122                               char *secstrings    
123                               struct module *m    
124 {                                                 
125         unsigned int i;                           
126                                                   
127         /* Find .plt and .init.plt sections */    
128         for (i = 0; i < hdr->e_shnum; i++) {      
129                 if (strcmp(secstrings + sechdr    
130                         me->arch.init_plt_sect    
131                 else if (strcmp(secstrings + s    
132                         me->arch.core_plt_sect    
133         }                                         
134         if (!me->arch.core_plt_section || !me-    
135                 pr_err("Module doesn't contain    
136                 return -ENOEXEC;                  
137         }                                         
138                                                   
139         /* Override their sizes */                
140         sechdrs[me->arch.core_plt_section].sh_    
141                 = get_plt_size(hdr, sechdrs, s    
142         sechdrs[me->arch.init_plt_section].sh_    
143                 = get_plt_size(hdr, sechdrs, s    
144         return 0;                                 
145 }                                                 
146                                                   
147 static inline int entry_matches(struct ppc_plt    
148 {                                                 
149         if (entry->jump[0] != PPC_RAW_LIS(_R12    
150                 return 0;                         
151         if (entry->jump[1] != PPC_RAW_ADDI(_R1    
152                 return 0;                         
153         return 1;                                 
154 }                                                 
155                                                   
156 /* Set up a trampoline in the PLT to bounce us    
157 static uint32_t do_plt_call(void *location,       
158                             Elf32_Addr val,       
159                             const Elf32_Shdr *    
160                             struct module *mod    
161 {                                                 
162         struct ppc_plt_entry *entry;              
163                                                   
164         pr_debug("Doing plt for call to 0x%x a    
165         /* Init, or core PLT? */                  
166         if (within_module_core((unsigned long)    
167                 entry = (void *)sechdrs[mod->a    
168         else                                      
169                 entry = (void *)sechdrs[mod->a    
170                                                   
171         /* Find this entry, or if that fails,     
172         while (entry->jump[0]) {                  
173                 if (entry_matches(entry, val))    
174                 entry++;                          
175         }                                         
176                                                   
177         if (patch_instruction(&entry->jump[0],    
178                 return 0;                         
179         if (patch_instruction(&entry->jump[1],    
180                 return 0;                         
181         if (patch_instruction(&entry->jump[2],    
182                 return 0;                         
183         if (patch_instruction(&entry->jump[3],    
184                 return 0;                         
185                                                   
186         pr_debug("Initialized plt for 0x%x at     
187         return (uint32_t)entry;                   
188 }                                                 
189                                                   
190 static int patch_location_16(uint32_t *loc, u1    
191 {                                                 
192         loc = PTR_ALIGN_DOWN(loc, sizeof(u32))    
193         return patch_instruction(loc, ppc_inst    
194 }                                                 
195                                                   
196 int apply_relocate_add(Elf32_Shdr *sechdrs,       
197                        const char *strtab,        
198                        unsigned int symindex,     
199                        unsigned int relsec,       
200                        struct module *module)     
201 {                                                 
202         unsigned int i;                           
203         Elf32_Rela *rela = (void *)sechdrs[rel    
204         Elf32_Sym *sym;                           
205         uint32_t *location;                       
206         uint32_t value;                           
207                                                   
208         pr_debug("Applying ADD relocate sectio    
209                sechdrs[relsec].sh_info);          
210         for (i = 0; i < sechdrs[relsec].sh_siz    
211                 /* This is where to make the c    
212                 location = (void *)sechdrs[sec    
213                         + rela[i].r_offset;       
214                 /* This is the symbol it is re    
215                    undefined symbols have been    
216                 sym = (Elf32_Sym *)sechdrs[sym    
217                         + ELF32_R_SYM(rela[i].    
218                 /* `Everything is relative'. *    
219                 value = sym->st_value + rela[i    
220                                                   
221                 switch (ELF32_R_TYPE(rela[i].r    
222                 case R_PPC_ADDR32:                
223                         /* Simply set it */       
224                         *(uint32_t *)location     
225                         break;                    
226                                                   
227                 case R_PPC_ADDR16_LO:             
228                         /* Low half of the sym    
229                         if (patch_location_16(    
230                                 return -EFAULT    
231                         break;                    
232                                                   
233                 case R_PPC_ADDR16_HI:             
234                         /* Higher half of the     
235                         if (patch_location_16(    
236                                 return -EFAULT    
237                         break;                    
238                                                   
239                 case R_PPC_ADDR16_HA:             
240                         if (patch_location_16(    
241                                 return -EFAULT    
242                         break;                    
243                                                   
244                 case R_PPC_REL24:                 
245                         if ((int)(value - (uin    
246                             || (int)(value - (    
247                                 value = do_plt    
248                                                   
249                                 if (!value)       
250                                         return    
251                         }                         
252                                                   
253                         /* Only replace bits 2    
254                         pr_debug("REL24 value     
255                                value, (uint32_    
256                         pr_debug("Location bef    
257                                *(uint32_t *)lo    
258                         value = (*(uint32_t *)    
259                                 PPC_LI(value -    
260                                                   
261                         if (patch_instruction(    
262                                 return -EFAULT    
263                                                   
264                         pr_debug("Location aft    
265                                *(uint32_t *)lo    
266                         pr_debug("ie. jump to     
267                                  *(uint32_t *)    
268                                  (*(uint32_t *    
269                         break;                    
270                                                   
271                 case R_PPC_REL32:                 
272                         /* 32-bit relative jum    
273                         *(uint32_t *)location     
274                         break;                    
275                                                   
276                 default:                          
277                         pr_err("%s: unknown AD    
278                                module->name,      
279                                ELF32_R_TYPE(re    
280                         return -ENOEXEC;          
281                 }                                 
282         }                                         
283                                                   
284         return 0;                                 
285 }                                                 
286                                                   
287 #ifdef CONFIG_DYNAMIC_FTRACE                      
288 notrace int module_trampoline_target(struct mo    
289                                      unsigned     
290 {                                                 
291         ppc_inst_t jmp[4];                        
292                                                   
293         /* Find where the trampoline jumps to     
294         if (copy_inst_from_kernel_nofault(jmp,    
295                 return -EFAULT;                   
296         if (__copy_inst_from_kernel_nofault(jm    
297                 return -EFAULT;                   
298         if (__copy_inst_from_kernel_nofault(jm    
299                 return -EFAULT;                   
300         if (__copy_inst_from_kernel_nofault(jm    
301                 return -EFAULT;                   
302                                                   
303         /* verify that this is what we expect     
304         if ((ppc_inst_val(jmp[0]) & 0xffff0000    
305                 return -EINVAL;                   
306         if ((ppc_inst_val(jmp[1]) & 0xffff0000    
307                 return -EINVAL;                   
308         if (ppc_inst_val(jmp[2]) != PPC_RAW_MT    
309                 return -EINVAL;                   
310         if (ppc_inst_val(jmp[3]) != PPC_RAW_BC    
311                 return -EINVAL;                   
312                                                   
313         addr = (ppc_inst_val(jmp[1]) & 0xffff)    
314         if (addr & 0x8000)                        
315                 addr -= 0x10000;                  
316                                                   
317         *target = addr;                           
318                                                   
319         return 0;                                 
320 }                                                 
321                                                   
322 int module_finalize_ftrace(struct module *modu    
323 {                                                 
324         module->arch.tramp = do_plt_call(modul    
325                                          (unsi    
326                                          sechd    
327         if (!module->arch.tramp)                  
328                 return -ENOENT;                   
329                                                   
330 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS            
331         module->arch.tramp_regs = do_plt_call(    
332                                                   
333                                                   
334         if (!module->arch.tramp_regs)             
335                 return -ENOENT;                   
336 #endif                                            
337                                                   
338         return 0;                                 
339 }                                                 
340 #endif                                            
341                                                   

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php