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

TOMOYO Linux Cross Reference
Linux/arch/riscv/kernel/alternative.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/riscv/kernel/alternative.c (Version linux-6.12-rc7) and /arch/sparc64/kernel/alternative.c (Version linux-6.1.116)


  1 // SPDX-License-Identifier: GPL-2.0-only            1 
  2 /*                                                
  3  * alternative runtime patching                   
  4  * inspired by the ARM64 and x86 version          
  5  *                                                
  6  * Copyright (C) 2021 Sifive.                     
  7  */                                               
  8                                                   
  9 #include <linux/init.h>                           
 10 #include <linux/module.h>                         
 11 #include <linux/cpu.h>                            
 12 #include <linux/uaccess.h>                        
 13 #include <asm/alternative.h>                      
 14 #include <asm/module.h>                           
 15 #include <asm/sections.h>                         
 16 #include <asm/vdso.h>                             
 17 #include <asm/vendorid_list.h>                    
 18 #include <asm/sbi.h>                              
 19 #include <asm/csr.h>                              
 20 #include <asm/insn.h>                             
 21 #include <asm/patch.h>                            
 22                                                   
 23 struct cpu_manufacturer_info_t {                  
 24         unsigned long vendor_id;                  
 25         unsigned long arch_id;                    
 26         unsigned long imp_id;                     
 27         void (*patch_func)(struct alt_entry *b    
 28                                   unsigned lon    
 29                                   unsigned int    
 30 };                                                
 31                                                   
 32 static void riscv_fill_cpu_mfr_info(struct cpu    
 33 {                                                 
 34 #ifdef CONFIG_RISCV_M_MODE                        
 35         cpu_mfr_info->vendor_id = csr_read(CSR    
 36         cpu_mfr_info->arch_id = csr_read(CSR_M    
 37         cpu_mfr_info->imp_id = csr_read(CSR_MI    
 38 #else                                             
 39         cpu_mfr_info->vendor_id = sbi_get_mven    
 40         cpu_mfr_info->arch_id = sbi_get_marchi    
 41         cpu_mfr_info->imp_id = sbi_get_mimpid(    
 42 #endif                                            
 43                                                   
 44         switch (cpu_mfr_info->vendor_id) {        
 45 #ifdef CONFIG_ERRATA_ANDES                        
 46         case ANDES_VENDOR_ID:                     
 47                 cpu_mfr_info->patch_func = and    
 48                 break;                            
 49 #endif                                            
 50 #ifdef CONFIG_ERRATA_SIFIVE                       
 51         case SIFIVE_VENDOR_ID:                    
 52                 cpu_mfr_info->patch_func = sif    
 53                 break;                            
 54 #endif                                            
 55 #ifdef CONFIG_ERRATA_THEAD                        
 56         case THEAD_VENDOR_ID:                     
 57                 cpu_mfr_info->patch_func = the    
 58                 break;                            
 59 #endif                                            
 60         default:                                  
 61                 cpu_mfr_info->patch_func = NUL    
 62         }                                         
 63 }                                                 
 64                                                   
 65 static u32 riscv_instruction_at(void *p)          
 66 {                                                 
 67         u16 *parcel = p;                          
 68                                                   
 69         return (u32)parcel[0] | (u32)parcel[1]    
 70 }                                                 
 71                                                   
 72 static void riscv_alternative_fix_auipc_jalr(v    
 73                                              u    
 74 {                                                 
 75         u32 call[2] = { auipc_insn, jalr_insn     
 76         s32 imm;                                  
 77                                                   
 78         /* get and adjust new target address *    
 79         imm = riscv_insn_extract_utype_itype_i    
 80         imm -= patch_offset;                      
 81                                                   
 82         /* update instructions */                 
 83         riscv_insn_insert_utype_itype_imm(&cal    
 84                                                   
 85         /* patch the call place again */          
 86         patch_text_nosync(ptr, call, sizeof(u3    
 87 }                                                 
 88                                                   
 89 static void riscv_alternative_fix_jal(void *pt    
 90 {                                                 
 91         s32 imm;                                  
 92                                                   
 93         /* get and adjust new target address *    
 94         imm = riscv_insn_extract_jtype_imm(jal    
 95         imm -= patch_offset;                      
 96                                                   
 97         /* update instruction */                  
 98         riscv_insn_insert_jtype_imm(&jal_insn,    
 99                                                   
100         /* patch the call place again */          
101         patch_text_nosync(ptr, &jal_insn, size    
102 }                                                 
103                                                   
104 void riscv_alternative_fix_offsets(void *alt_p    
105                                       int patc    
106 {                                                 
107         int num_insn = len / sizeof(u32);         
108         int i;                                    
109                                                   
110         for (i = 0; i < num_insn; i++) {          
111                 u32 insn = riscv_instruction_a    
112                                                   
113                 /*                                
114                  * May be the start of an auip    
115                  * Needs to check that at leas    
116                  * is in the list.                
117                  */                               
118                 if (riscv_insn_is_auipc(insn)     
119                         u32 insn2 = riscv_inst    
120                                                   
121                         if (!riscv_insn_is_jal    
122                                 continue;         
123                                                   
124                         /* if instruction pair    
125                         if (RV_EXTRACT_RD_REG(    
126                                 continue;         
127                                                   
128                         riscv_alternative_fix_    
129                                                   
130                         i++;                      
131                 }                                 
132                                                   
133                 if (riscv_insn_is_jal(insn)) {    
134                         s32 imm = riscv_insn_e    
135                                                   
136                         /* Don't modify jumps     
137                         if ((alt_ptr + i * siz    
138                             (alt_ptr + i * siz    
139                                 continue;         
140                                                   
141                         riscv_alternative_fix_    
142                                                   
143                 }                                 
144         }                                         
145 }                                                 
146                                                   
147 /*                                                
148  * This is called very early in the boot proce    
149  * a feature detect on the boot CPU). No need     
150  * here.                                          
151  */                                               
152 static void __init_or_module _apply_alternativ    
153                                                   
154                                                   
155 {                                                 
156         struct cpu_manufacturer_info_t cpu_mfr    
157                                                   
158         riscv_fill_cpu_mfr_info(&cpu_mfr_info)    
159                                                   
160         riscv_cpufeature_patch_func(begin, end    
161                                                   
162         if (!cpu_mfr_info.patch_func)             
163                 return;                           
164                                                   
165         cpu_mfr_info.patch_func(begin, end,       
166                                 cpu_mfr_info.a    
167                                 cpu_mfr_info.i    
168                                 stage);           
169 }                                                 
170                                                   
171 #ifdef CONFIG_MMU                                 
172 static void __init apply_vdso_alternatives(voi    
173 {                                                 
174         const Elf_Ehdr *hdr;                      
175         const Elf_Shdr *shdr;                     
176         const Elf_Shdr *alt;                      
177         struct alt_entry *begin, *end;            
178                                                   
179         hdr = (Elf_Ehdr *)vdso_start;             
180         shdr = (void *)hdr + hdr->e_shoff;        
181         alt = find_section(hdr, shdr, ".altern    
182         if (!alt)                                 
183                 return;                           
184                                                   
185         begin = (void *)hdr + alt->sh_offset,     
186         end = (void *)hdr + alt->sh_offset + a    
187                                                   
188         _apply_alternatives((struct alt_entry     
189                             (struct alt_entry     
190                             RISCV_ALTERNATIVES    
191 }                                                 
192 #else                                             
193 static void __init apply_vdso_alternatives(voi    
194 #endif                                            
195                                                   
196 void __init apply_boot_alternatives(void)         
197 {                                                 
198         /* If called on non-boot cpu things co    
199         WARN_ON(smp_processor_id() != 0);         
200                                                   
201         _apply_alternatives((struct alt_entry     
202                             (struct alt_entry     
203                             RISCV_ALTERNATIVES    
204                                                   
205         apply_vdso_alternatives();                
206 }                                                 
207                                                   
208 /*                                                
209  * apply_early_boot_alternatives() is called f    
210  *                                                
211  * Following requirements should be honoured f    
212  * 1) It should use PC-relative addressing for    
213  *    To achieve this we always use GCC cmodel    
214  * 2) The compiler instrumentation for FTRACE     
215  *    so disable compiler instrumentation when    
216  *                                                
217  * Currently, the above requirements are honou    
218  * for alternative.o in kernel/Makefile.          
219  */                                               
220 void __init apply_early_boot_alternatives(void    
221 {                                                 
222 #ifdef CONFIG_RISCV_ALTERNATIVE_EARLY             
223         _apply_alternatives((struct alt_entry     
224                             (struct alt_entry     
225                             RISCV_ALTERNATIVES    
226 #endif                                            
227 }                                                 
228                                                   
229 #ifdef CONFIG_MODULES                             
230 void apply_module_alternatives(void *start, si    
231 {                                                 
232         _apply_alternatives((struct alt_entry     
233                             (struct alt_entry     
234                             RISCV_ALTERNATIVES    
235 }                                                 
236 #endif                                            
237                                                   

~ [ 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