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

TOMOYO Linux Cross Reference
Linux/arch/riscv/kernel/sys_hwprobe.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/sys_hwprobe.c (Architecture m68k) and /arch/sparc/kernel/sys_hwprobe.c (Architecture sparc)


  1 // SPDX-License-Identifier: GPL-2.0-only            1 
  2 /*                                                
  3  * The hwprobe interface, for allowing userspa    
  4  * are supported by the hardware.  See Documen    
  5  * more details.                                  
  6  */                                               
  7 #include <linux/syscalls.h>                       
  8 #include <asm/cacheflush.h>                       
  9 #include <asm/cpufeature.h>                       
 10 #include <asm/hwprobe.h>                          
 11 #include <asm/processor.h>                        
 12 #include <asm/delay.h>                            
 13 #include <asm/sbi.h>                              
 14 #include <asm/switch_to.h>                        
 15 #include <asm/uaccess.h>                          
 16 #include <asm/unistd.h>                           
 17 #include <asm/vector.h>                           
 18 #include <vdso/vsyscall.h>                        
 19                                                   
 20                                                   
 21 static void hwprobe_arch_id(struct riscv_hwpro    
 22                             const struct cpuma    
 23 {                                                 
 24         u64 id = -1ULL;                           
 25         bool first = true;                        
 26         int cpu;                                  
 27                                                   
 28         for_each_cpu(cpu, cpus) {                 
 29                 u64 cpu_id;                       
 30                                                   
 31                 switch (pair->key) {              
 32                 case RISCV_HWPROBE_KEY_MVENDOR    
 33                         cpu_id = riscv_cached_    
 34                         break;                    
 35                 case RISCV_HWPROBE_KEY_MIMPID:    
 36                         cpu_id = riscv_cached_    
 37                         break;                    
 38                 case RISCV_HWPROBE_KEY_MARCHID    
 39                         cpu_id = riscv_cached_    
 40                         break;                    
 41                 }                                 
 42                                                   
 43                 if (first) {                      
 44                         id = cpu_id;              
 45                         first = false;            
 46                 }                                 
 47                                                   
 48                 /*                                
 49                  * If there's a mismatch for t    
 50                  * value.                         
 51                  */                               
 52                 if (id != cpu_id) {               
 53                         id = -1ULL;               
 54                         break;                    
 55                 }                                 
 56         }                                         
 57                                                   
 58         pair->value = id;                         
 59 }                                                 
 60                                                   
 61 static void hwprobe_isa_ext0(struct riscv_hwpr    
 62                              const struct cpum    
 63 {                                                 
 64         int cpu;                                  
 65         u64 missing = 0;                          
 66                                                   
 67         pair->value = 0;                          
 68         if (has_fpu())                            
 69                 pair->value |= RISCV_HWPROBE_I    
 70                                                   
 71         if (riscv_isa_extension_available(NULL    
 72                 pair->value |= RISCV_HWPROBE_I    
 73                                                   
 74         if (has_vector() && riscv_isa_extensio    
 75                 pair->value |= RISCV_HWPROBE_I    
 76                                                   
 77         /*                                        
 78          * Loop through and record extensions     
 79          * doesn't have.                          
 80          */                                       
 81         for_each_cpu(cpu, cpus) {                 
 82                 struct riscv_isainfo *isainfo     
 83                                                   
 84 #define EXT_KEY(ext)                              
 85         do {                                      
 86                 if (__riscv_isa_extension_avai    
 87                         pair->value |= RISCV_H    
 88                 else                              
 89                         missing |= RISCV_HWPRO    
 90         } while (false)                           
 91                                                   
 92                 /*                                
 93                  * Only use EXT_KEY() for exte    
 94                  * regardless of the kernel's     
 95                  * presence in the hart_isa bi    
 96                  */                               
 97                 EXT_KEY(ZACAS);                   
 98                 EXT_KEY(ZAWRS);                   
 99                 EXT_KEY(ZBA);                     
100                 EXT_KEY(ZBB);                     
101                 EXT_KEY(ZBC);                     
102                 EXT_KEY(ZBKB);                    
103                 EXT_KEY(ZBKC);                    
104                 EXT_KEY(ZBKX);                    
105                 EXT_KEY(ZBS);                     
106                 EXT_KEY(ZCA);                     
107                 EXT_KEY(ZCB);                     
108                 EXT_KEY(ZCMOP);                   
109                 EXT_KEY(ZICBOZ);                  
110                 EXT_KEY(ZICOND);                  
111                 EXT_KEY(ZIHINTNTL);               
112                 EXT_KEY(ZIHINTPAUSE);             
113                 EXT_KEY(ZIMOP);                   
114                 EXT_KEY(ZKND);                    
115                 EXT_KEY(ZKNE);                    
116                 EXT_KEY(ZKNH);                    
117                 EXT_KEY(ZKSED);                   
118                 EXT_KEY(ZKSH);                    
119                 EXT_KEY(ZKT);                     
120                 EXT_KEY(ZTSO);                    
121                                                   
122                 /*                                
123                  * All the following extension    
124                  * support of V.                  
125                  */                               
126                 if (has_vector()) {               
127                         EXT_KEY(ZVBB);            
128                         EXT_KEY(ZVBC);            
129                         EXT_KEY(ZVE32F);          
130                         EXT_KEY(ZVE32X);          
131                         EXT_KEY(ZVE64D);          
132                         EXT_KEY(ZVE64F);          
133                         EXT_KEY(ZVE64X);          
134                         EXT_KEY(ZVFH);            
135                         EXT_KEY(ZVFHMIN);         
136                         EXT_KEY(ZVKB);            
137                         EXT_KEY(ZVKG);            
138                         EXT_KEY(ZVKNED);          
139                         EXT_KEY(ZVKNHA);          
140                         EXT_KEY(ZVKNHB);          
141                         EXT_KEY(ZVKSED);          
142                         EXT_KEY(ZVKSH);           
143                         EXT_KEY(ZVKT);            
144                 }                                 
145                                                   
146                 if (has_fpu()) {                  
147                         EXT_KEY(ZCD);             
148                         EXT_KEY(ZCF);             
149                         EXT_KEY(ZFA);             
150                         EXT_KEY(ZFH);             
151                         EXT_KEY(ZFHMIN);          
152                 }                                 
153 #undef EXT_KEY                                    
154         }                                         
155                                                   
156         /* Now turn off reporting features if     
157         pair->value &= ~missing;                  
158 }                                                 
159                                                   
160 static bool hwprobe_ext0_has(const struct cpum    
161 {                                                 
162         struct riscv_hwprobe pair;                
163                                                   
164         hwprobe_isa_ext0(&pair, cpus);            
165         return (pair.value & ext);                
166 }                                                 
167                                                   
168 #if defined(CONFIG_RISCV_PROBE_UNALIGNED_ACCES    
169 static u64 hwprobe_misaligned(const struct cpu    
170 {                                                 
171         int cpu;                                  
172         u64 perf = -1ULL;                         
173                                                   
174         for_each_cpu(cpu, cpus) {                 
175                 int this_perf = per_cpu(misali    
176                                                   
177                 if (perf == -1ULL)                
178                         perf = this_perf;         
179                                                   
180                 if (perf != this_perf) {          
181                         perf = RISCV_HWPROBE_M    
182                         break;                    
183                 }                                 
184         }                                         
185                                                   
186         if (perf == -1ULL)                        
187                 return RISCV_HWPROBE_MISALIGNE    
188                                                   
189         return perf;                              
190 }                                                 
191 #else                                             
192 static u64 hwprobe_misaligned(const struct cpu    
193 {                                                 
194         if (IS_ENABLED(CONFIG_RISCV_EFFICIENT_    
195                 return RISCV_HWPROBE_MISALIGNE    
196                                                   
197         if (IS_ENABLED(CONFIG_RISCV_EMULATED_U    
198                 return RISCV_HWPROBE_MISALIGNE    
199                                                   
200         return RISCV_HWPROBE_MISALIGNED_SCALAR    
201 }                                                 
202 #endif                                            
203                                                   
204 static void hwprobe_one_pair(struct riscv_hwpr    
205                              const struct cpum    
206 {                                                 
207         switch (pair->key) {                      
208         case RISCV_HWPROBE_KEY_MVENDORID:         
209         case RISCV_HWPROBE_KEY_MARCHID:           
210         case RISCV_HWPROBE_KEY_MIMPID:            
211                 hwprobe_arch_id(pair, cpus);      
212                 break;                            
213         /*                                        
214          * The kernel already assumes that the    
215          * extensions are supported on all har    
216          * IMA base, so just cheat a bit here     
217          * userspace.                             
218          */                                       
219         case RISCV_HWPROBE_KEY_BASE_BEHAVIOR:     
220                 pair->value = RISCV_HWPROBE_BA    
221                 break;                            
222                                                   
223         case RISCV_HWPROBE_KEY_IMA_EXT_0:         
224                 hwprobe_isa_ext0(pair, cpus);     
225                 break;                            
226                                                   
227         case RISCV_HWPROBE_KEY_CPUPERF_0:         
228         case RISCV_HWPROBE_KEY_MISALIGNED_SCAL    
229                 pair->value = hwprobe_misalign    
230                 break;                            
231                                                   
232         case RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SI    
233                 pair->value = 0;                  
234                 if (hwprobe_ext0_has(cpus, RIS    
235                         pair->value = riscv_cb    
236                 break;                            
237         case RISCV_HWPROBE_KEY_HIGHEST_VIRT_AD    
238                 pair->value = user_max_virt_ad    
239                 break;                            
240                                                   
241         case RISCV_HWPROBE_KEY_TIME_CSR_FREQ:     
242                 pair->value = riscv_timebase;     
243                 break;                            
244                                                   
245         /*                                        
246          * For forward compatibility, unknown     
247          * call, but get their element key set    
248          * indicating they're unrecognized.       
249          */                                       
250         default:                                  
251                 pair->key = -1;                   
252                 pair->value = 0;                  
253                 break;                            
254         }                                         
255 }                                                 
256                                                   
257 static int hwprobe_get_values(struct riscv_hwp    
258                               size_t pair_coun    
259                               unsigned long __    
260                               unsigned int fla    
261 {                                                 
262         size_t out;                               
263         int ret;                                  
264         cpumask_t cpus;                           
265                                                   
266         /* Check the reserved flags. */           
267         if (flags != 0)                           
268                 return -EINVAL;                   
269                                                   
270         /*                                        
271          * The interface supports taking in a     
272          * are consistent across that mask. Al    
273          * 0 as a shortcut to all online CPUs.    
274          */                                       
275         cpumask_clear(&cpus);                     
276         if (!cpusetsize && !cpus_user) {          
277                 cpumask_copy(&cpus, cpu_online    
278         } else {                                  
279                 if (cpusetsize > cpumask_size(    
280                         cpusetsize = cpumask_s    
281                                                   
282                 ret = copy_from_user(&cpus, cp    
283                 if (ret)                          
284                         return -EFAULT;           
285                                                   
286                 /*                                
287                  * Userspace must provide at l    
288                  * there's no way to define wh    
289                  */                               
290                 cpumask_and(&cpus, &cpus, cpu_    
291                 if (cpumask_empty(&cpus))         
292                         return -EINVAL;           
293         }                                         
294                                                   
295         for (out = 0; out < pair_count; out++,    
296                 struct riscv_hwprobe pair;        
297                                                   
298                 if (get_user(pair.key, &pairs-    
299                         return -EFAULT;           
300                                                   
301                 pair.value = 0;                   
302                 hwprobe_one_pair(&pair, &cpus)    
303                 ret = put_user(pair.key, &pair    
304                 if (ret == 0)                     
305                         ret = put_user(pair.va    
306                                                   
307                 if (ret)                          
308                         return -EFAULT;           
309         }                                         
310                                                   
311         return 0;                                 
312 }                                                 
313                                                   
314 static int hwprobe_get_cpus(struct riscv_hwpro    
315                             size_t pair_count,    
316                             unsigned long __us    
317                             unsigned int flags    
318 {                                                 
319         cpumask_t cpus, one_cpu;                  
320         bool clear_all = false;                   
321         size_t i;                                 
322         int ret;                                  
323                                                   
324         if (flags != RISCV_HWPROBE_WHICH_CPUS)    
325                 return -EINVAL;                   
326                                                   
327         if (!cpusetsize || !cpus_user)            
328                 return -EINVAL;                   
329                                                   
330         if (cpusetsize > cpumask_size())          
331                 cpusetsize = cpumask_size();      
332                                                   
333         ret = copy_from_user(&cpus, cpus_user,    
334         if (ret)                                  
335                 return -EFAULT;                   
336                                                   
337         if (cpumask_empty(&cpus))                 
338                 cpumask_copy(&cpus, cpu_online    
339                                                   
340         cpumask_and(&cpus, &cpus, cpu_online_m    
341                                                   
342         cpumask_clear(&one_cpu);                  
343                                                   
344         for (i = 0; i < pair_count; i++) {        
345                 struct riscv_hwprobe pair, tmp    
346                 int cpu;                          
347                                                   
348                 ret = copy_from_user(&pair, &p    
349                 if (ret)                          
350                         return -EFAULT;           
351                                                   
352                 if (!riscv_hwprobe_key_is_vali    
353                         clear_all = true;         
354                         pair = (struct riscv_h    
355                         ret = copy_to_user(&pa    
356                         if (ret)                  
357                                 return -EFAULT    
358                 }                                 
359                                                   
360                 if (clear_all)                    
361                         continue;                 
362                                                   
363                 tmp = (struct riscv_hwprobe){     
364                                                   
365                 for_each_cpu(cpu, &cpus) {        
366                         cpumask_set_cpu(cpu, &    
367                                                   
368                         hwprobe_one_pair(&tmp,    
369                                                   
370                         if (!riscv_hwprobe_pai    
371                                 cpumask_clear_    
372                                                   
373                         cpumask_clear_cpu(cpu,    
374                 }                                 
375         }                                         
376                                                   
377         if (clear_all)                            
378                 cpumask_clear(&cpus);             
379                                                   
380         ret = copy_to_user(cpus_user, &cpus, c    
381         if (ret)                                  
382                 return -EFAULT;                   
383                                                   
384         return 0;                                 
385 }                                                 
386                                                   
387 static int do_riscv_hwprobe(struct riscv_hwpro    
388                             size_t pair_count,    
389                             unsigned long __us    
390                             unsigned int flags    
391 {                                                 
392         if (flags & RISCV_HWPROBE_WHICH_CPUS)     
393                 return hwprobe_get_cpus(pairs,    
394                                         cpus_u    
395                                                   
396         return hwprobe_get_values(pairs, pair_    
397                                   cpus_user, f    
398 }                                                 
399                                                   
400 #ifdef CONFIG_MMU                                 
401                                                   
402 static int __init init_hwprobe_vdso_data(void)    
403 {                                                 
404         struct vdso_data *vd = __arch_get_k_vd    
405         struct arch_vdso_data *avd = &vd->arch    
406         u64 id_bitsmash = 0;                      
407         struct riscv_hwprobe pair;                
408         int key;                                  
409                                                   
410         /*                                        
411          * Initialize vDSO data with the answe    
412          * save a syscall in the common case.     
413          */                                       
414         for (key = 0; key <= RISCV_HWPROBE_MAX    
415                 pair.key = key;                   
416                 hwprobe_one_pair(&pair, cpu_on    
417                                                   
418                 WARN_ON_ONCE(pair.key < 0);       
419                                                   
420                 avd->all_cpu_hwprobe_values[ke    
421                 /*                                
422                  * Smash together the vendor,     
423                  * they're all 0 or any negati    
424                  */                               
425                 if (key <= RISCV_HWPROBE_KEY_M    
426                         id_bitsmash |= pair.va    
427         }                                         
428                                                   
429         /*                                        
430          * If the arch, vendor, and implementa    
431          * all harts, then assume all CPUs are    
432          * answer queries for arbitrary masks.    
433          * populated) or any value returns -1     
434          * vDSO should defer to the kernel for    
435          */                                       
436         avd->homogeneous_cpus = id_bitsmash !=    
437         return 0;                                 
438 }                                                 
439                                                   
440 arch_initcall_sync(init_hwprobe_vdso_data);       
441                                                   
442 #endif /* CONFIG_MMU */                           
443                                                   
444 SYSCALL_DEFINE5(riscv_hwprobe, struct riscv_hw    
445                 size_t, pair_count, size_t, cp    
446                 cpus, unsigned int, flags)        
447 {                                                 
448         return do_riscv_hwprobe(pairs, pair_co    
449                                 cpus, flags);     
450 }                                                 
451                                                   

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