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

TOMOYO Linux Cross Reference
Linux/arch/mips/tools/loongson3-llsc-check.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ 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.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /arch/mips/tools/loongson3-llsc-check.c (Version linux-6.11-rc3) and /arch/ppc/tools/loongson3-llsc-check.c (Version linux-5.0.21)


  1 // SPDX-License-Identifier: GPL-2.0-only            1 
  2 #include <byteswap.h>                             
  3 #include <elf.h>                                  
  4 #include <endian.h>                               
  5 #include <errno.h>                                
  6 #include <fcntl.h>                                
  7 #include <inttypes.h>                             
  8 #include <stdbool.h>                              
  9 #include <stdio.h>                                
 10 #include <stdlib.h>                               
 11 #include <string.h>                               
 12 #include <sys/mman.h>                             
 13 #include <sys/types.h>                            
 14 #include <sys/stat.h>                             
 15 #include <unistd.h>                               
 16                                                   
 17 #ifdef be32toh                                    
 18 /* If libc provides le{16,32,64}toh() then we'    
 19 #elif BYTE_ORDER == LITTLE_ENDIAN                 
 20 # define le16toh(x)     (x)                       
 21 # define le32toh(x)     (x)                       
 22 # define le64toh(x)     (x)                       
 23 #elif BYTE_ORDER == BIG_ENDIAN                    
 24 # define le16toh(x)     bswap_16(x)               
 25 # define le32toh(x)     bswap_32(x)               
 26 # define le64toh(x)     bswap_64(x)               
 27 #endif                                            
 28                                                   
 29 /* MIPS opcodes, in bits 31:26 of an instructi    
 30 #define OP_SPECIAL      0x00                      
 31 #define OP_REGIMM       0x01                      
 32 #define OP_BEQ          0x04                      
 33 #define OP_BNE          0x05                      
 34 #define OP_BLEZ         0x06                      
 35 #define OP_BGTZ         0x07                      
 36 #define OP_BEQL         0x14                      
 37 #define OP_BNEL         0x15                      
 38 #define OP_BLEZL        0x16                      
 39 #define OP_BGTZL        0x17                      
 40 #define OP_LL           0x30                      
 41 #define OP_LLD          0x34                      
 42 #define OP_SC           0x38                      
 43 #define OP_SCD          0x3c                      
 44                                                   
 45 /* Bits 20:16 of OP_REGIMM instructions */        
 46 #define REGIMM_BLTZ     0x00                      
 47 #define REGIMM_BGEZ     0x01                      
 48 #define REGIMM_BLTZL    0x02                      
 49 #define REGIMM_BGEZL    0x03                      
 50 #define REGIMM_BLTZAL   0x10                      
 51 #define REGIMM_BGEZAL   0x11                      
 52 #define REGIMM_BLTZALL  0x12                      
 53 #define REGIMM_BGEZALL  0x13                      
 54                                                   
 55 /* Bits 5:0 of OP_SPECIAL instructions */         
 56 #define SPECIAL_SYNC    0x0f                      
 57                                                   
 58 static void usage(FILE *f)                        
 59 {                                                 
 60         fprintf(f, "Usage: loongson3-llsc-chec    
 61 }                                                 
 62                                                   
 63 static int se16(uint16_t x)                       
 64 {                                                 
 65         return (int16_t)x;                        
 66 }                                                 
 67                                                   
 68 static bool is_ll(uint32_t insn)                  
 69 {                                                 
 70         switch (insn >> 26) {                     
 71         case OP_LL:                               
 72         case OP_LLD:                              
 73                 return true;                      
 74                                                   
 75         default:                                  
 76                 return false;                     
 77         }                                         
 78 }                                                 
 79                                                   
 80 static bool is_sc(uint32_t insn)                  
 81 {                                                 
 82         switch (insn >> 26) {                     
 83         case OP_SC:                               
 84         case OP_SCD:                              
 85                 return true;                      
 86                                                   
 87         default:                                  
 88                 return false;                     
 89         }                                         
 90 }                                                 
 91                                                   
 92 static bool is_sync(uint32_t insn)                
 93 {                                                 
 94         /* Bits 31:11 should all be zeroes */     
 95         if (insn >> 11)                           
 96                 return false;                     
 97                                                   
 98         /* Bits 5:0 specify the SYNC special e    
 99         if ((insn & 0x3f) != SPECIAL_SYNC)        
100                 return false;                     
101                                                   
102         return true;                              
103 }                                                 
104                                                   
105 static bool is_branch(uint32_t insn, int *off)    
106 {                                                 
107         switch (insn >> 26) {                     
108         case OP_BEQ:                              
109         case OP_BEQL:                             
110         case OP_BNE:                              
111         case OP_BNEL:                             
112         case OP_BGTZ:                             
113         case OP_BGTZL:                            
114         case OP_BLEZ:                             
115         case OP_BLEZL:                            
116                 *off = se16(insn) + 1;            
117                 return true;                      
118                                                   
119         case OP_REGIMM:                           
120                 switch ((insn >> 16) & 0x1f) {    
121                 case REGIMM_BGEZ:                 
122                 case REGIMM_BGEZL:                
123                 case REGIMM_BGEZAL:               
124                 case REGIMM_BGEZALL:              
125                 case REGIMM_BLTZ:                 
126                 case REGIMM_BLTZL:                
127                 case REGIMM_BLTZAL:               
128                 case REGIMM_BLTZALL:              
129                         *off = se16(insn) + 1;    
130                         return true;              
131                                                   
132                 default:                          
133                         return false;             
134                 }                                 
135                                                   
136         default:                                  
137                 return false;                     
138         }                                         
139 }                                                 
140                                                   
141 static int check_ll(uint64_t pc, uint32_t *cod    
142 {                                                 
143         ssize_t i, max, sc_pos;                   
144         int off;                                  
145                                                   
146         /*                                        
147          * Every LL must be preceded by a sync    
148          * that instruction reordering doesn't    
149          * execute after the LL & cause errone    
150          */                                       
151         if (!is_sync(le32toh(code[-1]))) {        
152                 fprintf(stderr, "%" PRIx64 ":     
153                 return -EINVAL;                   
154         }                                         
155                                                   
156         /* Find the matching SC instruction */    
157         max = sz / 4;                             
158         for (sc_pos = 0; sc_pos < max; sc_pos+    
159                 if (is_sc(le32toh(code[sc_pos]    
160                         break;                    
161         }                                         
162         if (sc_pos >= max) {                      
163                 fprintf(stderr, "%" PRIx64 ":     
164                 return -EINVAL;                   
165         }                                         
166                                                   
167         /*                                        
168          * Check branches within the LL/SC loo    
169          * ensuring that speculative execution    
170          * due to instructions outside of the     
171          */                                       
172         for (i = 0; i < sc_pos; i++) {            
173                 if (!is_branch(le32toh(code[i]    
174                         continue;                 
175                                                   
176                 /*                                
177                  * If the branch target is wit    
178                  * need to worry about it.        
179                  */                               
180                 if ((off >= -i) && (off <= sc_    
181                         continue;                 
182                                                   
183                 /* If the branch targets a syn    
184                 if (is_sync(le32toh(code[i + o    
185                         continue;                 
186                                                   
187                 /* ...but if not, we have a pr    
188                 fprintf(stderr, "%" PRIx64 ":     
189                         pc + (i * 4));            
190                 return -EINVAL;                   
191         }                                         
192                                                   
193         return 0;                                 
194 }                                                 
195                                                   
196 static int check_code(uint64_t pc, uint32_t *c    
197 {                                                 
198         int err = 0;                              
199                                                   
200         if (sz % 4) {                             
201                 fprintf(stderr, "%" PRIx64 ":     
202                         pc);                      
203                 err = -EINVAL;                    
204                 sz -= (sz % 4);                   
205         }                                         
206                                                   
207         if (is_ll(le32toh(code[0]))) {            
208                 fprintf(stderr, "%" PRIx64 ":     
209                         pc);                      
210                 err = -EINVAL;                    
211         }                                         
212                                                   
213 #define advance() (     \                         
214         code++,         \                         
215         pc += 4,        \                         
216         sz -= 4         \                         
217 )                                                 
218                                                   
219         /*                                        
220          * Skip the first instruction, allowin    
221          * unconditionally.                       
222          */                                       
223         advance();                                
224                                                   
225         /* Now scan through the code looking f    
226         for (; sz; advance()) {                   
227                 if (is_ll(le32toh(code[0])))      
228                         err |= check_ll(pc, co    
229         }                                         
230                                                   
231         return err;                               
232 }                                                 
233                                                   
234 int main(int argc, char *argv[])                  
235 {                                                 
236         int vmlinux_fd, status, err, i;           
237         const char *vmlinux_path;                 
238         struct stat st;                           
239         Elf64_Ehdr *eh;                           
240         Elf64_Shdr *sh;                           
241         void *vmlinux;                            
242                                                   
243         status = EXIT_FAILURE;                    
244                                                   
245         if (argc < 2) {                           
246                 usage(stderr);                    
247                 goto out_ret;                     
248         }                                         
249                                                   
250         vmlinux_path = argv[1];                   
251         vmlinux_fd = open(vmlinux_path, O_RDON    
252         if (vmlinux_fd == -1) {                   
253                 perror("Unable to open vmlinux    
254                 goto out_ret;                     
255         }                                         
256                                                   
257         err = fstat(vmlinux_fd, &st);             
258         if (err) {                                
259                 perror("Unable to stat vmlinux    
260                 goto out_close;                   
261         }                                         
262                                                   
263         vmlinux = mmap(NULL, st.st_size, PROT_    
264         if (vmlinux == MAP_FAILED) {              
265                 perror("Unable to mmap vmlinux    
266                 goto out_close;                   
267         }                                         
268                                                   
269         eh = vmlinux;                             
270         if (memcmp(eh->e_ident, ELFMAG, SELFMA    
271                 fprintf(stderr, "vmlinux is no    
272                 goto out_munmap;                  
273         }                                         
274                                                   
275         if (eh->e_ident[EI_CLASS] != ELFCLASS6    
276                 fprintf(stderr, "vmlinux is no    
277                 goto out_munmap;                  
278         }                                         
279                                                   
280         if (eh->e_ident[EI_DATA] != ELFDATA2LS    
281                 fprintf(stderr, "vmlinux is no    
282                 goto out_munmap;                  
283         }                                         
284                                                   
285         for (i = 0; i < le16toh(eh->e_shnum);     
286                 sh = vmlinux + le64toh(eh->e_s    
287                                                   
288                 if (sh->sh_type != SHT_PROGBIT    
289                         continue;                 
290                 if (!(sh->sh_flags & SHF_EXECI    
291                         continue;                 
292                                                   
293                 err = check_code(le64toh(sh->s    
294                                  vmlinux + le6    
295                                  le64toh(sh->s    
296                 if (err)                          
297                         goto out_munmap;          
298         }                                         
299                                                   
300         status = EXIT_SUCCESS;                    
301 out_munmap:                                       
302         munmap(vmlinux, st.st_size);              
303 out_close:                                        
304         close(vmlinux_fd);                        
305 out_ret:                                          
306         fprintf(stdout, "loongson3-llsc-check     
307                 status ? "failure" : "success"    
308         return status;                            
309 }                                                 
310                                                   

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