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

TOMOYO Linux Cross Reference
Linux/arch/parisc/kernel/syscall.S

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/parisc/kernel/syscall.S (Version linux-6.11-rc3) and /arch/i386/kernel/syscall.S (Version linux-3.10.108)


  1 /*                                                
  2  * Linux/PA-RISC Project (http://www.parisc-li    
  3  *                                                
  4  * System call entry code / Linux gateway page    
  5  * Copyright (c) Matthew Wilcox 1999 <willy@inf    
  6  * Licensed under the GNU GPL.                    
  7  * thanks to Philipp Rumpf, Mike Shaver and va    
  8  * sorry about the wall, puffin..                 
  9  */                                               
 10                                                   
 11 /*                                                
 12 How does the Linux gateway page on PA-RISC wor    
 13 ----------------------------------------------    
 14 The Linux gateway page on PA-RISC is "special"    
 15 It actually has PAGE_GATEWAY bits set (this is    
 16 terminology it's Execute, promote to PL0) in t    
 17 executing on this page executes with kernel le    
 18 than that: to have this happen, you also have     
 19 completer to activate the privilege promotion)    
 20 that runs on the gateway page runs at kernel p    
 21 user process address space (although you have     
 22 For the 0x100 syscall entry, we redo the space    
 23 address space (preserving the user address spa    
 24 required, save the user registers and branch i    
 25 point.  For all the other functions, we execut    
 26 flip address spaces. The basic upshot of this     
 27 executed atomically (because the kernel can't     
 28 perform architecturally forbidden (to PL3) ope    
 29 registers).                                       
 30 */                                                
 31                                                   
 32                                                   
 33 #include <asm/asm-offsets.h>                      
 34 #include <asm/unistd.h>                           
 35 #include <asm/errno.h>                            
 36 #include <asm/page.h>                             
 37 #include <asm/psw.h>                              
 38 #include <asm/thread_info.h>                      
 39 #include <asm/assembly.h>                         
 40 #include <asm/processor.h>                        
 41 #include <asm/cache.h>                            
 42 #include <asm/spinlock_types.h>                   
 43                                                   
 44 #include <linux/linkage.h>                        
 45                                                   
 46         /* We fill the empty parts of the gate    
 47          * something that will kill the kernel    
 48          * userspace application.                 
 49          */                                       
 50 #define KILL_INSN       break   0,0               
 51                                                   
 52         .level          PA_ASM_LEVEL              
 53                                                   
 54         .macro  lws_pagefault_disable reg1,reg    
 55         mfctl   %cr30, \reg2                      
 56         ldo     TASK_PAGEFAULT_DISABLED(\reg2)    
 57         ldw     0(%sr2,\reg2), \reg1              
 58         ldo     1(\reg1), \reg1                   
 59         stw     \reg1, 0(%sr2,\reg2)              
 60         .endm                                     
 61                                                   
 62         .macro  lws_pagefault_enable reg1,reg2    
 63         mfctl   %cr30, \reg2                      
 64         ldo     TASK_PAGEFAULT_DISABLED(\reg2)    
 65         ldw     0(%sr2,\reg2), \reg1              
 66         ldo     -1(\reg1), \reg1                  
 67         stw     \reg1, 0(%sr2,\reg2)              
 68         .endm                                     
 69                                                   
 70         /* raise exception if spinlock content    
 71          * __ARCH_SPIN_LOCK_UNLOCKED_VAL */       
 72         .macro  spinlock_check spin_val,tmpreg    
 73 #ifdef CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK          
 74         ldi     __ARCH_SPIN_LOCK_UNLOCKED_VAL,    
 75         andcm,= \spin_val, \tmpreg, %r0           
 76         .word   SPINLOCK_BREAK_INSN               
 77 #endif                                            
 78         .endm                                     
 79                                                   
 80         .text                                     
 81                                                   
 82         .import syscall_exit,code                 
 83         .import syscall_exit_rfi,code             
 84                                                   
 85         /* Linux gateway page is aliased to vi    
 86          * address space. Since it is a gatewa    
 87          * dereferenced, so null pointers will    
 88          * the actual entry point at 0x100. We    
 89          * at the beginning of the page to tra    
 90          * pointers.                              
 91          */                                       
 92                                                   
 93         .align PAGE_SIZE                          
 94 ENTRY(linux_gateway_page)                         
 95                                                   
 96         /* ADDRESS 0x00 to 0xb0 = 176 bytes /     
 97         .rept 44                                  
 98         KILL_INSN                                 
 99         .endr                                     
100                                                   
101         /* ADDRESS 0xb0 to 0xb8, lws uses two     
102         /* Light-weight-syscall entry must alw    
103         /* WARNING: Keep this number updated w    
104 #define __NR_lws_entries (5)                      
105                                                   
106 lws_entry:                                        
107         gate    lws_start, %r0          /* inc    
108         depi    PRIV_USER, 31, 2, %r31  /* Ens    
109                                                   
110         /* Fill from 0xb8 to 0xe0 */              
111         .rept 10                                  
112         KILL_INSN                                 
113         .endr                                     
114                                                   
115         /* This function MUST be located at 0x    
116         mechanism to work. DO NOT MOVE THIS CO    
117 set_thread_pointer:                               
118         gate    .+8, %r0                /* inc    
119         depi    PRIV_USER, 31, 2, %r31  /* Ens    
120         be      0(%sr7,%r31)            /* ret    
121         mtctl   %r26, %cr27             /* mov    
122                                                   
123         /* Increase the chance of trapping if     
124         address, fill from 0xf0 to 0x100 */       
125         .rept 4                                   
126         KILL_INSN                                 
127         .endr                                     
128                                                   
129 /* This address must remain fixed at 0x100 for    
130         .align LINUX_GATEWAY_ADDR                 
131 linux_gateway_entry:                              
132         gate    .+8, %r0                          
133         mtsp    %r0,%sr4                          
134         mtsp    %r0,%sr5                          
135         mtsp    %r0,%sr6                          
136                                                   
137 #ifdef CONFIG_64BIT                               
138         /* Store W bit on entry to the syscall    
139          * process. */                            
140         ssm     PSW_SM_W, %r1                     
141         extrd,u %r1,PSW_W_BIT,1,%r1               
142         /* sp must be aligned on 4, so deposit    
143          * the bottom of sp temporarily */        
144         or,ev   %r1,%r30,%r30                     
145         b,n     1f                                
146         /* The top halves of argument register    
147          * entry from narrow executable.          
148          */                                       
149         depdi   0, 31, 32, %r26                   
150         depdi   0, 31, 32, %r25                   
151         depdi   0, 31, 32, %r24                   
152         depdi   0, 31, 32, %r23                   
153         depdi   0, 31, 32, %r22                   
154         depdi   0, 31, 32, %r21                   
155 1:                                                
156 #endif                                            
157                                                   
158         /* We use a rsm/ssm pair to prevent sr    
159          * by external interrupts.                
160          */                                       
161         mfsp    %sr7,%r1                          
162         rsm     PSW_SM_I, %r0                     
163         mtsp    %r1,%sr3                          
164                                                   
165         mfctl   %cr30,%r1                         
166         xor     %r1,%r30,%r30                     
167         xor     %r1,%r30,%r1                      
168         xor     %r1,%r30,%r30                     
169                                                   
170         LDREG   TASK_STACK(%r30),%r30             
171         ldo     FRAME_SIZE(%r30),%r30             
172         /* N.B.: It is critical that we don't     
173          *       contains a valid kernel stack    
174          *       critical that we don't start     
175          *       until after sr7 has been set     
176          */                                       
177                                                   
178         mtsp    %r0,%sr7                          
179         ssm     PSW_SM_I, %r0                     
180         STREGM  %r1,FRAME_SIZE(%r30)              
181         mfctl   %cr30,%r1                         
182                                                   
183         /* Save some registers for sigcontext     
184            switch (see entry.S for the details    
185            saved/restored).  TASK_PT_PSW is ze    
186            a process is on a syscall or not.      
187            PSW value is stored.  This is neede    
188         STREG   %r0,  TASK_PT_PSW(%r1)            
189         STREG   %r2,  TASK_PT_GR2(%r1)            
190         STREG   %r19, TASK_PT_GR19(%r1)           
191                                                   
192         LDREGM  -FRAME_SIZE(%r30), %r2            
193 #ifdef CONFIG_64BIT                               
194         extrd,u %r2,63,1,%r19                     
195 #if 0                                             
196         xor     %r19,%r2,%r2                      
197         depd,z  %r19,1,1,%r19                     
198         std     %r19,TASK_PT_PSW(%r1)             
199 #endif                                            
200 #endif                                            
201         STREG   %r2,  TASK_PT_GR30(%r1)           
202                                                   
203         STREG   %r20, TASK_PT_GR20(%r1)           
204         STREG   %r21, TASK_PT_GR21(%r1)           
205         STREG   %r22, TASK_PT_GR22(%r1)           
206         STREG   %r23, TASK_PT_GR23(%r1)           
207         STREG   %r24, TASK_PT_GR24(%r1)           
208         STREG   %r25, TASK_PT_GR25(%r1)           
209         STREG   %r26, TASK_PT_GR26(%r1)           
210         STREG   %r27, TASK_PT_GR27(%r1)           
211         STREG   %r28, TASK_PT_GR28(%r1)           
212         STREG   %r0, TASK_PT_ORIG_R28(%r1)        
213         STREG   %r29, TASK_PT_GR29(%r1)           
214         STREG   %r31, TASK_PT_GR31(%r1)           
215                                                   
216         ldo     TASK_PT_FR0(%r1), %r27            
217         save_fp %r27                              
218                                                   
219         mfctl   %cr11, %r27                       
220         STREG   %r27, TASK_PT_SAR(%r1)            
221                                                   
222         loadgp                                    
223                                                   
224 #ifdef CONFIG_64BIT                               
225         ldo     -16(%r30),%r29                    
226         copy    %r19,%r2                          
227 #else                                             
228         /* no need to save these on stack in w    
229          * args are passed in registers */        
230         stw     %r22, -52(%r30)                   
231         stw     %r21, -56(%r30)                   
232 #endif                                            
233                                                   
234         /* Are we being ptraced? */               
235         mfctl   %cr30, %r1                        
236         LDREG   TASK_TI_FLAGS(%r1),%r1            
237         ldi     _TIF_SYSCALL_TRACE_MASK, %r19     
238         and,COND(=) %r1, %r19, %r0                
239         b,n     .Ltracesys                        
240                                                   
241         /* Note!  We cannot use the syscall ta    
242         nearby since the gateway page is mappe    
243                                                   
244 #ifdef CONFIG_64BIT                               
245         ldil    L%sys_call_table, %r1             
246         or,=    %r2,%r2,%r2                       
247         addil   L%(sys_call_table64-sys_call_t    
248         ldo     R%sys_call_table(%r1), %r19       
249         or,=    %r2,%r2,%r2                       
250         ldo     R%sys_call_table64(%r1), %r19     
251 #else                                             
252         load32  sys_call_table, %r19              
253 #endif                                            
254         comiclr,>>      __NR_Linux_syscalls, %    
255         b,n     .Lsyscall_nosys                   
256                                                   
257         LDREGX  %r20(%r19), %r19                  
258                                                   
259         /* If this is a sys_rt_sigreturn call,    
260          * when not in_syscall, then we want t    
261          * not syscall_exit.  Signal no. in r2    
262          * trampoline code in signal.c).          
263          */                                       
264         ldi     __NR_rt_sigreturn,%r2             
265         comb,=  %r2,%r20,.Lrt_sigreturn           
266 .Lin_syscall:                                     
267         ldil    L%syscall_exit,%r2                
268         be      0(%sr7,%r19)                      
269         ldo     R%syscall_exit(%r2),%r2           
270 .Lrt_sigreturn:                                   
271         comib,<> 0,%r25,.Lin_syscall              
272         ldil    L%syscall_exit_rfi,%r2            
273         be      0(%sr7,%r19)                      
274         ldo     R%syscall_exit_rfi(%r2),%r2       
275                                                   
276         /* Note!  Because we are not running w    
277         calls to functions external to this fi    
278         be safe, we apply the opposite rule to    
279         file, with local labels given to them     
280                                                   
281 .Lsyscall_nosys:                                  
282 syscall_nosys:                                    
283         ldil    L%syscall_exit,%r1                
284         be      R%syscall_exit(%sr7,%r1)          
285         ldo     -ENOSYS(%r0),%r28                 
286                                                   
287                                                   
288 /* Warning! This trace code is a virtual dupli    
289  * sure to maintain both! */                      
290 .Ltracesys:                                       
291 tracesys:                                         
292         /* Need to save more registers so the     
293          * are.  This saves only the lower 8 b    
294          * bit is still clear on syscalls, and    
295          * full register save path has been ex    
296          * bit on syscall_return_rfi to determ    
297          * restore.  An interrupt results in a    
298          * C bit set, a non-straced syscall en    
299          * in the saved PSW.                      
300          */                                       
301         mfctl   %cr30,%r1                         
302         ssm     0,%r2                             
303         STREG   %r2,TASK_PT_PSW(%r1)              
304         mfsp    %sr0,%r2                          
305         STREG   %r2,TASK_PT_SR0(%r1)              
306         mfsp    %sr1,%r2                          
307         STREG   %r2,TASK_PT_SR1(%r1)              
308         mfsp    %sr2,%r2                          
309         STREG   %r2,TASK_PT_SR2(%r1)              
310         mfsp    %sr3,%r2                          
311         STREG   %r2,TASK_PT_SR3(%r1)              
312         STREG   %r2,TASK_PT_SR4(%r1)              
313         STREG   %r2,TASK_PT_SR5(%r1)              
314         STREG   %r2,TASK_PT_SR6(%r1)              
315         STREG   %r2,TASK_PT_SR7(%r1)              
316         STREG   %r2,TASK_PT_IASQ0(%r1)            
317         STREG   %r2,TASK_PT_IASQ1(%r1)            
318         LDREG   TASK_PT_GR31(%r1),%r2             
319         STREG   %r2,TASK_PT_IAOQ0(%r1)            
320         ldo     4(%r2),%r2                        
321         STREG   %r2,TASK_PT_IAOQ1(%r1)            
322         ldo     TASK_REGS(%r1),%r2                
323         /* reg_save %r2 */                        
324         STREG   %r3,PT_GR3(%r2)                   
325         STREG   %r4,PT_GR4(%r2)                   
326         STREG   %r5,PT_GR5(%r2)                   
327         STREG   %r6,PT_GR6(%r2)                   
328         STREG   %r7,PT_GR7(%r2)                   
329         STREG   %r8,PT_GR8(%r2)                   
330         STREG   %r9,PT_GR9(%r2)                   
331         STREG   %r10,PT_GR10(%r2)                 
332         STREG   %r11,PT_GR11(%r2)                 
333         STREG   %r12,PT_GR12(%r2)                 
334         STREG   %r13,PT_GR13(%r2)                 
335         STREG   %r14,PT_GR14(%r2)                 
336         STREG   %r15,PT_GR15(%r2)                 
337         STREG   %r16,PT_GR16(%r2)                 
338         STREG   %r17,PT_GR17(%r2)                 
339         STREG   %r18,PT_GR18(%r2)                 
340         /* Finished saving things for the debu    
341                                                   
342         copy    %r2,%r26                          
343         ldil    L%do_syscall_trace_enter,%r1      
344         ldil    L%tracesys_next,%r2               
345         be      R%do_syscall_trace_enter(%sr7,    
346         ldo     R%tracesys_next(%r2),%r2          
347                                                   
348 tracesys_next:                                    
349         /* do_syscall_trace_enter either retur    
350          *  so we skip restoring the PT_GR20 b    
351          *  task->thread.regs.gr[20] above.       
352          */                                       
353         copy    %ret0,%r20                        
354                                                   
355         mfctl   %cr30,%r1                         
356         LDREG   TASK_PT_GR28(%r1), %r28           
357         LDREG   TASK_PT_GR26(%r1), %r26           
358         LDREG   TASK_PT_GR25(%r1), %r25           
359         LDREG   TASK_PT_GR24(%r1), %r24           
360         LDREG   TASK_PT_GR23(%r1), %r23           
361         LDREG   TASK_PT_GR22(%r1), %r22           
362         LDREG   TASK_PT_GR21(%r1), %r21           
363 #ifdef CONFIG_64BIT                               
364         ldo     -16(%r30),%r29                    
365 #else                                             
366         stw     %r22, -52(%r30)                   
367         stw     %r21, -56(%r30)                   
368 #endif                                            
369                                                   
370         cmpib,COND(=),n -1,%r20,tracesys_exit     
371         comiclr,>>      __NR_Linux_syscalls, %    
372         b,n     .Ltracesys_nosys                  
373                                                   
374         /* Note!  We cannot use the syscall ta    
375         nearby since the gateway page is mappe    
376                                                   
377 #ifdef CONFIG_64BIT                               
378         LDREG   TASK_PT_GR30(%r1), %r19           
379         extrd,u %r19,63,1,%r2                     
380                                                   
381         ldil    L%sys_call_table, %r1             
382         or,=    %r2,%r2,%r2                       
383         addil   L%(sys_call_table64-sys_call_t    
384         ldo     R%sys_call_table(%r1), %r19       
385         or,=    %r2,%r2,%r2                       
386         ldo     R%sys_call_table64(%r1), %r19     
387 #else                                             
388         load32  sys_call_table, %r19              
389 #endif                                            
390                                                   
391         LDREGX  %r20(%r19), %r19                  
392                                                   
393         /* If this is a sys_rt_sigreturn call,    
394          * when not in_syscall, then we want t    
395          * not syscall_exit.  Signal no. in r2    
396          * trampoline code in signal.c).          
397          */                                       
398         ldi     __NR_rt_sigreturn,%r2             
399         comb,=  %r2,%r20,.Ltrace_rt_sigreturn     
400 .Ltrace_in_syscall:                               
401         ldil    L%tracesys_exit,%r2               
402         be      0(%sr7,%r19)                      
403         ldo     R%tracesys_exit(%r2),%r2          
404                                                   
405 .Ltracesys_nosys:                                 
406         ldo     -ENOSYS(%r0),%r28                 
407                                                   
408         /* Do *not* call this function on the     
409         makes a direct call to syscall_trace.     
410                                                   
411 tracesys_exit:                                    
412         mfctl   %cr30,%r1                         
413 #ifdef CONFIG_64BIT                               
414         ldo     -16(%r30),%r29                    
415 #endif                                            
416         ldo     TASK_REGS(%r1),%r26               
417         BL      do_syscall_trace_exit,%r2         
418         STREG   %r28,TASK_PT_GR28(%r1)            
419         mfctl   %cr30,%r1                         
420         LDREG   TASK_PT_GR28(%r1), %r28           
421                                                   
422         ldil    L%syscall_exit,%r1                
423         be,n    R%syscall_exit(%sr7,%r1)          
424                                                   
425 .Ltrace_rt_sigreturn:                             
426         comib,<> 0,%r25,.Ltrace_in_syscall        
427         ldil    L%tracesys_sigexit,%r2            
428         be      0(%sr7,%r19)                      
429         ldo     R%tracesys_sigexit(%r2),%r2       
430                                                   
431 tracesys_sigexit:                                 
432         mfctl   %cr30,%r1                         
433 #ifdef CONFIG_64BIT                               
434         ldo     -16(%r30),%r29                    
435 #endif                                            
436         BL      do_syscall_trace_exit,%r2         
437         ldo     TASK_REGS(%r1),%r26               
438                                                   
439         ldil    L%syscall_exit_rfi,%r1            
440         be,n    R%syscall_exit_rfi(%sr7,%r1)      
441                                                   
442                                                   
443         /*************************************    
444                 32/64-bit Light-Weight-Syscall    
445                                                   
446                 * - Indicates a hint for users    
447                 implementations.                  
448                                                   
449                 Syscall number (caller-saves)     
450                 - %r20                            
451                 * In asm clobber.                 
452                                                   
453                 Argument registers (caller-sav    
454                 - %r26, %r25, %r24, %r23, %r22    
455                 * In asm input.                   
456                                                   
457                 Return registers (caller-saves    
458                 - %r28 (return), %r21 (errno)     
459                 * In asm output.                  
460                                                   
461                 Caller-saves registers            
462                 - %r1, %r27, %r29                 
463                 - %r2 (return pointer)            
464                 - %r31 (ble link register)        
465                 * In asm clobber.                 
466                                                   
467                 Callee-saves registers            
468                 - %r3-%r18                        
469                 - %r30 (stack pointer)            
470                 * Not in asm clobber.             
471                                                   
472                 If userspace is 32-bit:           
473                 Callee-saves registers            
474                 - %r19 (32-bit PIC register)      
475                                                   
476                 Differences from 32-bit callin    
477                 - Syscall number in %r20          
478                 - Additional argument register    
479                 - Callee-saves %r19.              
480                                                   
481                 If userspace is 64-bit:           
482                 Callee-saves registers            
483                 - %r27 (64-bit PIC register)      
484                                                   
485                 Differences from 64-bit callin    
486                 - Syscall number in %r20          
487                 - Additional argument register    
488                 - Callee-saves %r27.              
489                                                   
490                 Error codes returned by entry     
491                                                   
492                 ENOSYS - r20 was an invalid LW    
493                                                   
494         **************************************    
495 lws_start:                                        
496                                                   
497 #ifdef CONFIG_64BIT                               
498         ssm     PSW_SM_W, %r1                     
499         extrd,u %r1,PSW_W_BIT,1,%r1               
500         /* sp must be aligned on 4, so deposit    
501          * the bottom of sp temporarily */        
502         or,od   %r1,%r30,%r30                     
503                                                   
504         /* Clip LWS number to a 32-bit value f    
505         depdi   0, 31, 32, %r20                   
506 #endif                                            
507                                                   
508         /* Is the lws entry number valid? */      
509         comiclr,>>      __NR_lws_entries, %r20    
510         b,n     lws_exit_nosys                    
511                                                   
512         /* Load table start */                    
513         ldil    L%lws_table, %r1                  
514         ldo     R%lws_table(%r1), %r28  /* Scr    
515         LDREGX  %r20(%sr2,r28), %r21    /* Scr    
516                                                   
517         /* Jump to lws, lws table pointers alr    
518         be,n    0(%sr2,%r21)                      
519                                                   
520 lws_exit_noerror:                                 
521         lws_pagefault_enable    %r1,%r21          
522         ldi     __ARCH_SPIN_LOCK_UNLOCKED_VAL,    
523         stw,ma  %r21, 0(%sr2,%r20)                
524         ssm     PSW_SM_I, %r0                     
525         b       lws_exit                          
526         copy    %r0, %r21                         
527                                                   
528 lws_wouldblock:                                   
529         ssm     PSW_SM_I, %r0                     
530         ldo     2(%r0), %r28                      
531         b       lws_exit                          
532         ldo     -EAGAIN(%r0), %r21                
533                                                   
534 lws_pagefault:                                    
535         lws_pagefault_enable    %r1,%r21          
536         ldi     __ARCH_SPIN_LOCK_UNLOCKED_VAL,    
537         stw,ma  %r21, 0(%sr2,%r20)                
538         ssm     PSW_SM_I, %r0                     
539         ldo     3(%r0),%r28                       
540         b       lws_exit                          
541         ldo     -EAGAIN(%r0),%r21                 
542                                                   
543 lws_fault:                                        
544         ldo     1(%r0),%r28                       
545         b       lws_exit                          
546         ldo     -EFAULT(%r0),%r21                 
547                                                   
548 lws_exit_nosys:                                   
549         ldo     -ENOSYS(%r0),%r21                 
550         /* Fall through: Return to userspace *    
551                                                   
552 lws_exit:                                         
553 #ifdef CONFIG_64BIT                               
554         /* decide whether to reset the wide mo    
555          *                                        
556          * For a syscall, the W bit is stored     
557          * of sp.  Extract it and reset W if i    
558         extrd,u,*<>     %r30,63,1,%r1             
559         rsm     PSW_SM_W, %r0                     
560         /* now reset the lowest bit of sp if i    
561         xor     %r30,%r1,%r30                     
562 #endif                                            
563         be,n    0(%sr7, %r31)                     
564                                                   
565                                                   
566                                                   
567         /*************************************    
568                 Implementing 32bit CAS as an a    
569                                                   
570                 %r26 - Address to examine         
571                 %r25 - Old value to check (old    
572                 %r24 - New value to set (new)     
573                 %r28 - Return prev through thi    
574                 %r21 - Kernel error code          
575                                                   
576                 %r21 returns the following err    
577                 EAGAIN - CAS is busy, ldcw fai    
578                 EFAULT - Read or write failed.    
579                                                   
580                 If EAGAIN is returned, %r28 in    
581                 r28 == 1 - CAS is busy. lock c    
582                 r28 == 2 - CAS is busy. ldcw f    
583                 r28 == 3 - CAS is busy. page f    
584                                                   
585                 Scratch: r20, r28, r1             
586                                                   
587         **************************************    
588                                                   
589         /* ELF64 Process entry path */            
590 lws_compare_and_swap64:                           
591 #ifdef CONFIG_64BIT                               
592         b,n     lws_compare_and_swap              
593 #else                                             
594         /* If we are not a 64-bit kernel, then    
595          * have 64-bit input registers, and ca    
596          * the 64-bit LWS CAS returns ENOSYS.     
597          */                                       
598         b,n     lws_exit_nosys                    
599 #endif                                            
600                                                   
601         /* ELF32/ELF64 Process entry path */      
602 lws_compare_and_swap32:                           
603 #ifdef CONFIG_64BIT                               
604         /* Wide mode user process? */             
605         bb,<,n  %sp, 31, lws_compare_and_swap     
606                                                   
607         /* Clip all the input registers for 32    
608         depdi   0, 31, 32, %r26                   
609         depdi   0, 31, 32, %r25                   
610         depdi   0, 31, 32, %r24                   
611 #endif                                            
612                                                   
613 lws_compare_and_swap:                             
614         /* Trigger memory reference interrupti    
615 1:      ldw     0(%r26), %r28                     
616 2:      stbys,e %r0, 0(%r26)                      
617                                                   
618         /* Calculate 8-bit hash index from vir    
619         extru_safe      %r26, 27, 8, %r20         
620                                                   
621         /* Load start of lock table */            
622         ldil    L%lws_lock_start, %r28            
623         ldo     R%lws_lock_start(%r28), %r28      
624                                                   
625         /* Find lock to use, the hash index is    
626            255, multiplied by 16 (keep it 16-b    
627            and add to the lock table offset. *    
628         shlw    %r20, 4, %r20                     
629         add     %r20, %r28, %r20                  
630                                                   
631         rsm     PSW_SM_I, %r0                     
632                                                   
633         /* Try to acquire the lock */             
634         LDCW    0(%sr2,%r20), %r28                
635         spinlock_check  %r28, %r21                
636         comclr,<>       %r0, %r28, %r0            
637         b,n     lws_wouldblock                    
638                                                   
639         /* Disable page faults to prevent slee    
640         lws_pagefault_disable   %r21,%r28         
641                                                   
642         /*                                        
643                 prev = *addr;                     
644                 if ( prev == old )                
645                   *addr = new;                    
646                 return prev;                      
647         */                                        
648                                                   
649         /* NOTES:                                 
650                 This all works because intr_do    
651                 and schedule both check the re    
652                 and see that we are on the ker    
653                 so this process is never sched    
654                 or is ever sent any signal of     
655                 thus it is wholly atomic from     
656                 perspective                       
657         */                                        
658         /* The load and store could fail */       
659 3:      ldw     0(%r26), %r28                     
660         sub,<>  %r28, %r25, %r0                   
661 4:      stw     %r24, 0(%r26)                     
662         b,n     lws_exit_noerror                  
663                                                   
664         /* A fault occurred on load or stbys,e    
665 5:      b,n     lws_fault                         
666         ASM_EXCEPTIONTABLE_ENTRY(1b-linux_gate    
667         ASM_EXCEPTIONTABLE_ENTRY(2b-linux_gate    
668                                                   
669         /* A page fault occurred in critical r    
670 6:      b,n     lws_pagefault                     
671         ASM_EXCEPTIONTABLE_ENTRY(3b-linux_gate    
672         ASM_EXCEPTIONTABLE_ENTRY(4b-linux_gate    
673                                                   
674                                                   
675         /*************************************    
676                 New CAS implementation which u    
677                 information. The value pointed    
678                 while performing CAS. The lock    
679                                                   
680                 %r26 - Address to examine         
681                 %r25 - Pointer to the value to    
682                 %r24 - Pointer to the value to    
683                 %r23 - Size of the variable (0    
684                 %r28 - Return non-zero on fail    
685                 %r21 - Kernel error code          
686                                                   
687                 %r21 returns the following err    
688                 EAGAIN - CAS is busy, ldcw fai    
689                 EFAULT - Read or write failed.    
690                                                   
691                 If EAGAIN is returned, %r28 in    
692                 r28 == 1 - CAS is busy. lock c    
693                 r28 == 2 - CAS is busy. ldcw f    
694                 r28 == 3 - CAS is busy. page f    
695                                                   
696                 Scratch: r20, r22, r28, r29, r    
697                                                   
698         **************************************    
699                                                   
700 lws_compare_and_swap_2:                           
701 #ifdef CONFIG_64BIT                               
702         /* Wide mode user process? */             
703         bb,<,n  %sp, 31, cas2_begin               
704                                                   
705         /* Clip the input registers for 32-bit    
706            need to clip %r23 as we only use it    
707         depdi   0, 31, 32, %r26                   
708         depdi   0, 31, 32, %r25                   
709         depdi   0, 31, 32, %r24                   
710 #endif                                            
711                                                   
712 cas2_begin:                                       
713         /* Check the validity of the size poin    
714         subi,>>= 3, %r23, %r0                     
715         b,n     lws_exit_nosys                    
716                                                   
717         /* Jump to the functions which will lo    
718            registers depending on the their si    
719         shlw    %r23, 2, %r29                     
720         blr     %r29, %r0                         
721         nop                                       
722                                                   
723         /* 8-bit load */                          
724 1:      ldb     0(%r25), %r25                     
725         b       cas2_lock_start                   
726 2:      ldb     0(%r24), %r24                     
727         nop                                       
728         nop                                       
729         nop                                       
730         nop                                       
731         nop                                       
732                                                   
733         /* 16-bit load */                         
734 3:      ldh     0(%r25), %r25                     
735         b       cas2_lock_start                   
736 4:      ldh     0(%r24), %r24                     
737         nop                                       
738         nop                                       
739         nop                                       
740         nop                                       
741         nop                                       
742                                                   
743         /* 32-bit load */                         
744 5:      ldw     0(%r25), %r25                     
745         b       cas2_lock_start                   
746 6:      ldw     0(%r24), %r24                     
747         nop                                       
748         nop                                       
749         nop                                       
750         nop                                       
751         nop                                       
752                                                   
753         /* 64-bit load */                         
754 #ifdef CONFIG_64BIT                               
755 7:      ldd     0(%r25), %r25                     
756 8:      ldd     0(%r24), %r24                     
757 #else                                             
758         /* Load old value into r22/r23 - high/    
759 7:      ldw     0(%r25), %r22                     
760 8:      ldw     4(%r25), %r23                     
761         /* Load new value into fr4 for atomic     
762 9:      flddx   0(%r24), %fr4                     
763 #endif                                            
764                                                   
765 cas2_lock_start:                                  
766         /* Trigger memory reference interrupti    
767         copy    %r26, %r28                        
768         depi_safe       0, 31, 2, %r28            
769 10:     ldw     0(%r28), %r1                      
770 11:     stbys,e %r0, 0(%r28)                      
771                                                   
772         /* Calculate 8-bit hash index from vir    
773         extru_safe      %r26, 27, 8, %r20         
774                                                   
775         /* Load start of lock table */            
776         ldil    L%lws_lock_start, %r28            
777         ldo     R%lws_lock_start(%r28), %r28      
778                                                   
779         /* Find lock to use, the hash index is    
780            255, multiplied by 16 (keep it 16-b    
781            and add to the lock table offset. *    
782         shlw    %r20, 4, %r20                     
783         add     %r20, %r28, %r20                  
784                                                   
785         rsm     PSW_SM_I, %r0                     
786                                                   
787         /* Try to acquire the lock */             
788         LDCW    0(%sr2,%r20), %r28                
789         spinlock_check  %r28, %r21                
790         comclr,<>       %r0, %r28, %r0            
791         b,n     lws_wouldblock                    
792                                                   
793         /* Disable page faults to prevent slee    
794         lws_pagefault_disable   %r21,%r28         
795                                                   
796         /*                                        
797                 prev = *addr;                     
798                 if ( prev == old )                
799                   *addr = new;                    
800                 return prev;                      
801         */                                        
802                                                   
803         /* NOTES:                                 
804                 This all works because intr_do    
805                 and schedule both check the re    
806                 and see that we are on the ker    
807                 so this process is never sched    
808                 or is ever sent any signal of     
809                 thus it is wholly atomic from     
810                 perspective                       
811         */                                        
812                                                   
813         /* Jump to the correct function */        
814         blr     %r29, %r0                         
815         /* Set %r28 as non-zero for now */        
816         ldo     1(%r0),%r28                       
817                                                   
818         /* 8-bit CAS */                           
819 12:     ldb     0(%r26), %r29                     
820         sub,=   %r29, %r25, %r0                   
821         b,n     lws_exit_noerror                  
822 13:     stb     %r24, 0(%r26)                     
823         b       lws_exit_noerror                  
824         copy    %r0, %r28                         
825         nop                                       
826         nop                                       
827                                                   
828         /* 16-bit CAS */                          
829 14:     ldh     0(%r26), %r29                     
830         sub,=   %r29, %r25, %r0                   
831         b,n     lws_exit_noerror                  
832 15:     sth     %r24, 0(%r26)                     
833         b       lws_exit_noerror                  
834         copy    %r0, %r28                         
835         nop                                       
836         nop                                       
837                                                   
838         /* 32-bit CAS */                          
839 16:     ldw     0(%r26), %r29                     
840         sub,=   %r29, %r25, %r0                   
841         b,n     lws_exit_noerror                  
842 17:     stw     %r24, 0(%r26)                     
843         b       lws_exit_noerror                  
844         copy    %r0, %r28                         
845         nop                                       
846         nop                                       
847                                                   
848         /* 64-bit CAS */                          
849 #ifdef CONFIG_64BIT                               
850 18:     ldd     0(%r26), %r29                     
851         sub,*=  %r29, %r25, %r0                   
852         b,n     lws_exit_noerror                  
853 19:     std     %r24, 0(%r26)                     
854         copy    %r0, %r28                         
855 #else                                             
856         /* Compare first word */                  
857 18:     ldw     0(%r26), %r29                     
858         sub,=   %r29, %r22, %r0                   
859         b,n     lws_exit_noerror                  
860         /* Compare second word */                 
861 19:     ldw     4(%r26), %r29                     
862         sub,=   %r29, %r23, %r0                   
863         b,n     lws_exit_noerror                  
864         /* Perform the store */                   
865 20:     fstdx   %fr4, 0(%r26)                     
866         copy    %r0, %r28                         
867 #endif                                            
868         b       lws_exit_noerror                  
869         copy    %r0, %r28                         
870                                                   
871         /* A fault occurred on load or stbys,e    
872 30:     b,n     lws_fault                         
873         ASM_EXCEPTIONTABLE_ENTRY(1b-linux_gate    
874         ASM_EXCEPTIONTABLE_ENTRY(2b-linux_gate    
875         ASM_EXCEPTIONTABLE_ENTRY(3b-linux_gate    
876         ASM_EXCEPTIONTABLE_ENTRY(4b-linux_gate    
877         ASM_EXCEPTIONTABLE_ENTRY(5b-linux_gate    
878         ASM_EXCEPTIONTABLE_ENTRY(6b-linux_gate    
879         ASM_EXCEPTIONTABLE_ENTRY(7b-linux_gate    
880         ASM_EXCEPTIONTABLE_ENTRY(8b-linux_gate    
881 #ifndef CONFIG_64BIT                              
882         ASM_EXCEPTIONTABLE_ENTRY(9b-linux_gate    
883 #endif                                            
884                                                   
885         ASM_EXCEPTIONTABLE_ENTRY(10b-linux_gat    
886         ASM_EXCEPTIONTABLE_ENTRY(11b-linux_gat    
887                                                   
888         /* A page fault occurred in critical r    
889 31:     b,n     lws_pagefault                     
890         ASM_EXCEPTIONTABLE_ENTRY(12b-linux_gat    
891         ASM_EXCEPTIONTABLE_ENTRY(13b-linux_gat    
892         ASM_EXCEPTIONTABLE_ENTRY(14b-linux_gat    
893         ASM_EXCEPTIONTABLE_ENTRY(15b-linux_gat    
894         ASM_EXCEPTIONTABLE_ENTRY(16b-linux_gat    
895         ASM_EXCEPTIONTABLE_ENTRY(17b-linux_gat    
896         ASM_EXCEPTIONTABLE_ENTRY(18b-linux_gat    
897         ASM_EXCEPTIONTABLE_ENTRY(19b-linux_gat    
898 #ifndef CONFIG_64BIT                              
899         ASM_EXCEPTIONTABLE_ENTRY(20b-linux_gat    
900 #endif                                            
901                                                   
902                                                   
903         /*************************************    
904                 LWS atomic exchange.              
905                                                   
906                 %r26 - Exchange address           
907                 %r25 - Size of the variable (0    
908                 %r24 - Address of new value       
909                 %r23 - Address of old value       
910                 %r28 - Return non-zero on fail    
911                 %r21 - Kernel error code          
912                                                   
913                 %r21 returns the following err    
914                 EAGAIN - CAS is busy, ldcw fai    
915                 EFAULT - Read or write failed.    
916                                                   
917                 If EAGAIN is returned, %r28 in    
918                 r28 == 1 - CAS is busy. lock c    
919                 r28 == 2 - CAS is busy. ldcw f    
920                 r28 == 3 - CAS is busy. page f    
921                                                   
922                 Scratch: r20, r1                  
923                                                   
924         **************************************    
925                                                   
926 lws_atomic_xchg:                                  
927 #ifdef CONFIG_64BIT                               
928         /* Wide mode user process? */             
929         bb,<,n  %sp, 31, atomic_xchg_begin        
930                                                   
931         /* Clip the input registers for 32-bit    
932            need to clip %r23 as we only use it    
933         depdi   0, 31, 32, %r26                   
934         depdi   0, 31, 32, %r25                   
935         depdi   0, 31, 32, %r24                   
936         depdi   0, 31, 32, %r23                   
937 #endif                                            
938                                                   
939 atomic_xchg_begin:                                
940         /* Check the validity of the size poin    
941         subi,>>= 3, %r25, %r0                     
942         b,n     lws_exit_nosys                    
943                                                   
944         /* Jump to the functions which will lo    
945            registers depending on the their si    
946         shlw    %r25, 2, %r1                      
947         blr     %r1, %r0                          
948         nop                                       
949                                                   
950         /* Perform exception checks */            
951                                                   
952         /* 8-bit exchange */                      
953 1:      ldb     0(%r24), %r20                     
954         copy    %r23, %r20                        
955         depi_safe       0, 31, 2, %r20            
956         b       atomic_xchg_start                 
957 2:      stbys,e %r0, 0(%r20)                      
958         nop                                       
959         nop                                       
960         nop                                       
961                                                   
962         /* 16-bit exchange */                     
963 3:      ldh     0(%r24), %r20                     
964         copy    %r23, %r20                        
965         depi_safe       0, 31, 2, %r20            
966         b       atomic_xchg_start                 
967 4:      stbys,e %r0, 0(%r20)                      
968         nop                                       
969         nop                                       
970         nop                                       
971                                                   
972         /* 32-bit exchange */                     
973 5:      ldw     0(%r24), %r20                     
974         b       atomic_xchg_start                 
975 6:      stbys,e %r0, 0(%r23)                      
976         nop                                       
977         nop                                       
978         nop                                       
979         nop                                       
980         nop                                       
981                                                   
982         /* 64-bit exchange */                     
983 #ifdef CONFIG_64BIT                               
984 7:      ldd     0(%r24), %r20                     
985 8:      stdby,e %r0, 0(%r23)                      
986 #else                                             
987 7:      ldw     0(%r24), %r20                     
988 8:      ldw     4(%r24), %r20                     
989         copy    %r23, %r20                        
990         depi_safe       0, 31, 2, %r20            
991 9:      stbys,e %r0, 0(%r20)                      
992 10:     stbys,e %r0, 4(%r20)                      
993 #endif                                            
994                                                   
995 atomic_xchg_start:                                
996         /* Trigger memory reference interrupti    
997         copy    %r26, %r28                        
998         depi_safe       0, 31, 2, %r28            
999 11:     ldw     0(%r28), %r1                      
1000 12:     stbys,e %r0, 0(%r28)                     
1001                                                  
1002         /* Calculate 8-bit hash index from vi    
1003         extru_safe  %r26, 27, 8, %r20            
1004                                                  
1005         /* Load start of lock table */           
1006         ldil    L%lws_lock_start, %r28           
1007         ldo     R%lws_lock_start(%r28), %r28     
1008                                                  
1009         /* Find lock to use, the hash index i    
1010            255, multiplied by 16 (keep it 16-    
1011            and add to the lock table offset.     
1012         shlw    %r20, 4, %r20                    
1013         add     %r20, %r28, %r20                 
1014                                                  
1015         rsm     PSW_SM_I, %r0                    
1016                                                  
1017         /* Try to acquire the lock */            
1018         LDCW    0(%sr2,%r20), %r28               
1019         spinlock_check  %r28, %r21               
1020         comclr,<>       %r0, %r28, %r0           
1021         b,n     lws_wouldblock                   
1022                                                  
1023         /* Disable page faults to prevent sle    
1024         lws_pagefault_disable   %r21,%r28        
1025                                                  
1026         /* NOTES:                                
1027                 This all works because intr_d    
1028                 and schedule both check the r    
1029                 and see that we are on the ke    
1030                 so this process is never sche    
1031                 or is ever sent any signal of    
1032                 thus it is wholly atomic from    
1033                 perspective                      
1034         */                                       
1035                                                  
1036         /* Jump to the correct function */       
1037         blr     %r1, %r0                         
1038         /* Set %r28 as non-zero for now */       
1039         ldo     1(%r0),%r28                      
1040                                                  
1041         /* 8-bit exchange */                     
1042 14:     ldb     0(%r26), %r1                     
1043 15:     stb     %r1, 0(%r23)                     
1044 15:     ldb     0(%r24), %r1                     
1045 17:     stb     %r1, 0(%r26)                     
1046         b       lws_exit_noerror                 
1047         copy    %r0, %r28                        
1048         nop                                      
1049         nop                                      
1050                                                  
1051         /* 16-bit exchange */                    
1052 18:     ldh     0(%r26), %r1                     
1053 19:     sth     %r1, 0(%r23)                     
1054 20:     ldh     0(%r24), %r1                     
1055 21:     sth     %r1, 0(%r26)                     
1056         b       lws_exit_noerror                 
1057         copy    %r0, %r28                        
1058         nop                                      
1059         nop                                      
1060                                                  
1061         /* 32-bit exchange */                    
1062 22:     ldw     0(%r26), %r1                     
1063 23:     stw     %r1, 0(%r23)                     
1064 24:     ldw     0(%r24), %r1                     
1065 25:     stw     %r1, 0(%r26)                     
1066         b       lws_exit_noerror                 
1067         copy    %r0, %r28                        
1068         nop                                      
1069         nop                                      
1070                                                  
1071         /* 64-bit exchange */                    
1072 #ifdef CONFIG_64BIT                              
1073 26:     ldd     0(%r26), %r1                     
1074 27:     std     %r1, 0(%r23)                     
1075 28:     ldd     0(%r24), %r1                     
1076 29:     std     %r1, 0(%r26)                     
1077 #else                                            
1078 26:     flddx   0(%r26), %fr4                    
1079 27:     fstdx   %fr4, 0(%r23)                    
1080 28:     flddx   0(%r24), %fr4                    
1081 29:     fstdx   %fr4, 0(%r26)                    
1082 #endif                                           
1083         b       lws_exit_noerror                 
1084         copy    %r0, %r28                        
1085                                                  
1086         /* A fault occurred on load or stbys,    
1087 30:     b,n     lws_fault                        
1088         ASM_EXCEPTIONTABLE_ENTRY(1b-linux_gat    
1089         ASM_EXCEPTIONTABLE_ENTRY(2b-linux_gat    
1090         ASM_EXCEPTIONTABLE_ENTRY(3b-linux_gat    
1091         ASM_EXCEPTIONTABLE_ENTRY(4b-linux_gat    
1092         ASM_EXCEPTIONTABLE_ENTRY(5b-linux_gat    
1093         ASM_EXCEPTIONTABLE_ENTRY(6b-linux_gat    
1094         ASM_EXCEPTIONTABLE_ENTRY(7b-linux_gat    
1095         ASM_EXCEPTIONTABLE_ENTRY(8b-linux_gat    
1096 #ifndef CONFIG_64BIT                             
1097         ASM_EXCEPTIONTABLE_ENTRY(9b-linux_gat    
1098         ASM_EXCEPTIONTABLE_ENTRY(10b-linux_ga    
1099 #endif                                           
1100                                                  
1101         ASM_EXCEPTIONTABLE_ENTRY(11b-linux_ga    
1102         ASM_EXCEPTIONTABLE_ENTRY(12b-linux_ga    
1103                                                  
1104         /* A page fault occurred in critical     
1105 31:     b,n     lws_pagefault                    
1106         ASM_EXCEPTIONTABLE_ENTRY(14b-linux_ga    
1107         ASM_EXCEPTIONTABLE_ENTRY(15b-linux_ga    
1108         ASM_EXCEPTIONTABLE_ENTRY(16b-linux_ga    
1109         ASM_EXCEPTIONTABLE_ENTRY(17b-linux_ga    
1110         ASM_EXCEPTIONTABLE_ENTRY(18b-linux_ga    
1111         ASM_EXCEPTIONTABLE_ENTRY(19b-linux_ga    
1112         ASM_EXCEPTIONTABLE_ENTRY(20b-linux_ga    
1113         ASM_EXCEPTIONTABLE_ENTRY(21b-linux_ga    
1114         ASM_EXCEPTIONTABLE_ENTRY(22b-linux_ga    
1115         ASM_EXCEPTIONTABLE_ENTRY(23b-linux_ga    
1116         ASM_EXCEPTIONTABLE_ENTRY(24b-linux_ga    
1117         ASM_EXCEPTIONTABLE_ENTRY(25b-linux_ga    
1118         ASM_EXCEPTIONTABLE_ENTRY(26b-linux_ga    
1119         ASM_EXCEPTIONTABLE_ENTRY(27b-linux_ga    
1120         ASM_EXCEPTIONTABLE_ENTRY(28b-linux_ga    
1121         ASM_EXCEPTIONTABLE_ENTRY(29b-linux_ga    
1122                                                  
1123         /************************************    
1124                 LWS atomic store.                
1125                                                  
1126                 %r26 - Address to store          
1127                 %r25 - Size of the variable (    
1128                 %r24 - Address of value to st    
1129                 %r28 - Return non-zero on fai    
1130                 %r21 - Kernel error code         
1131                                                  
1132                 %r21 returns the following er    
1133                 EAGAIN - CAS is busy, ldcw fa    
1134                 EFAULT - Read or write failed    
1135                                                  
1136                 If EAGAIN is returned, %r28 i    
1137                 r28 == 1 - CAS is busy. lock     
1138                 r28 == 2 - CAS is busy. ldcw     
1139                 r28 == 3 - CAS is busy. page     
1140                                                  
1141                 Scratch: r20, r1                 
1142                                                  
1143         *************************************    
1144                                                  
1145 lws_atomic_store:                                
1146 #ifdef CONFIG_64BIT                              
1147         /* Wide mode user process? */            
1148         bb,<,n  %sp, 31, atomic_store_begin      
1149                                                  
1150         /* Clip the input registers for 32-bi    
1151            need to clip %r23 as we only use i    
1152         depdi   0, 31, 32, %r26                  
1153         depdi   0, 31, 32, %r25                  
1154         depdi   0, 31, 32, %r24                  
1155 #endif                                           
1156                                                  
1157 atomic_store_begin:                              
1158         /* Check the validity of the size poi    
1159         subi,>>= 3, %r25, %r0                    
1160         b,n     lws_exit_nosys                   
1161                                                  
1162         shlw    %r25, 1, %r1                     
1163         blr     %r1, %r0                         
1164         nop                                      
1165                                                  
1166         /* Perform exception checks */           
1167                                                  
1168         /* 8-bit store */                        
1169 1:      ldb     0(%r24), %r20                    
1170         b,n     atomic_store_start               
1171         nop                                      
1172         nop                                      
1173                                                  
1174         /* 16-bit store */                       
1175 2:      ldh     0(%r24), %r20                    
1176         b,n     atomic_store_start               
1177         nop                                      
1178         nop                                      
1179                                                  
1180         /* 32-bit store */                       
1181 3:      ldw     0(%r24), %r20                    
1182         b,n     atomic_store_start               
1183         nop                                      
1184         nop                                      
1185                                                  
1186         /* 64-bit store */                       
1187 #ifdef CONFIG_64BIT                              
1188 4:      ldd     0(%r24), %r20                    
1189 #else                                            
1190 4:      ldw     0(%r24), %r20                    
1191 5:      ldw     4(%r24), %r20                    
1192 #endif                                           
1193                                                  
1194 atomic_store_start:                              
1195         /* Trigger memory reference interrupt    
1196         copy    %r26, %r28                       
1197         depi_safe       0, 31, 2, %r28           
1198 6:      ldw     0(%r28), %r1                     
1199 7:      stbys,e %r0, 0(%r28)                     
1200                                                  
1201         /* Calculate 8-bit hash index from vi    
1202         extru_safe  %r26, 27, 8, %r20            
1203                                                  
1204         /* Load start of lock table */           
1205         ldil    L%lws_lock_start, %r28           
1206         ldo     R%lws_lock_start(%r28), %r28     
1207                                                  
1208         /* Find lock to use, the hash index i    
1209            255, multiplied by 16 (keep it 16-    
1210            and add to the lock table offset.     
1211         shlw    %r20, 4, %r20                    
1212         add     %r20, %r28, %r20                 
1213                                                  
1214         rsm     PSW_SM_I, %r0                    
1215                                                  
1216         /* Try to acquire the lock */            
1217         LDCW    0(%sr2,%r20), %r28               
1218         spinlock_check  %r28, %r21               
1219         comclr,<>       %r0, %r28, %r0           
1220         b,n     lws_wouldblock                   
1221                                                  
1222         /* Disable page faults to prevent sle    
1223         lws_pagefault_disable   %r21,%r28        
1224                                                  
1225         /* NOTES:                                
1226                 This all works because intr_d    
1227                 and schedule both check the r    
1228                 and see that we are on the ke    
1229                 so this process is never sche    
1230                 or is ever sent any signal of    
1231                 thus it is wholly atomic from    
1232                 perspective                      
1233         */                                       
1234                                                  
1235         /* Jump to the correct function */       
1236         blr     %r1, %r0                         
1237         /* Set %r28 as non-zero for now */       
1238         ldo     1(%r0),%r28                      
1239                                                  
1240         /* 8-bit store */                        
1241 9:      ldb     0(%r24), %r1                     
1242 10:     stb     %r1, 0(%r26)                     
1243         b       lws_exit_noerror                 
1244         copy    %r0, %r28                        
1245                                                  
1246         /* 16-bit store */                       
1247 11:     ldh     0(%r24), %r1                     
1248 12:     sth     %r1, 0(%r26)                     
1249         b       lws_exit_noerror                 
1250         copy    %r0, %r28                        
1251                                                  
1252         /* 32-bit store */                       
1253 13:     ldw     0(%r24), %r1                     
1254 14:     stw     %r1, 0(%r26)                     
1255         b       lws_exit_noerror                 
1256         copy    %r0, %r28                        
1257                                                  
1258         /* 64-bit store */                       
1259 #ifdef CONFIG_64BIT                              
1260 15:     ldd     0(%r24), %r1                     
1261 16:     std     %r1, 0(%r26)                     
1262 #else                                            
1263 15:     flddx   0(%r24), %fr4                    
1264 16:     fstdx   %fr4, 0(%r26)                    
1265 #endif                                           
1266         b       lws_exit_noerror                 
1267         copy    %r0, %r28                        
1268                                                  
1269         /* A fault occurred on load or stbys,    
1270 30:     b,n     lws_fault                        
1271         ASM_EXCEPTIONTABLE_ENTRY(1b-linux_gat    
1272         ASM_EXCEPTIONTABLE_ENTRY(2b-linux_gat    
1273         ASM_EXCEPTIONTABLE_ENTRY(3b-linux_gat    
1274         ASM_EXCEPTIONTABLE_ENTRY(4b-linux_gat    
1275 #ifndef CONFIG_64BIT                             
1276         ASM_EXCEPTIONTABLE_ENTRY(5b-linux_gat    
1277 #endif                                           
1278                                                  
1279         ASM_EXCEPTIONTABLE_ENTRY(6b-linux_gat    
1280         ASM_EXCEPTIONTABLE_ENTRY(7b-linux_gat    
1281                                                  
1282         /* A page fault occurred in critical     
1283 31:     b,n     lws_pagefault                    
1284         ASM_EXCEPTIONTABLE_ENTRY(9b-linux_gat    
1285         ASM_EXCEPTIONTABLE_ENTRY(10b-linux_ga    
1286         ASM_EXCEPTIONTABLE_ENTRY(11b-linux_ga    
1287         ASM_EXCEPTIONTABLE_ENTRY(12b-linux_ga    
1288         ASM_EXCEPTIONTABLE_ENTRY(13b-linux_ga    
1289         ASM_EXCEPTIONTABLE_ENTRY(14b-linux_ga    
1290         ASM_EXCEPTIONTABLE_ENTRY(15b-linux_ga    
1291         ASM_EXCEPTIONTABLE_ENTRY(16b-linux_ga    
1292                                                  
1293         /* Make sure nothing else is placed o    
1294         .align PAGE_SIZE                         
1295 END(linux_gateway_page)                          
1296 ENTRY(end_linux_gateway_page)                    
1297                                                  
1298         /* Relocate symbols assuming linux_ga    
1299            to virtual address 0x0 */             
1300                                                  
1301 #define LWS_ENTRY(_name_) ASM_ULONG_INSN (lws    
1302                                                  
1303         .section .rodata,"a"                     
1304                                                  
1305         .align 8                                 
1306         /* Light-weight-syscall table */         
1307         /* Start of lws table. */                
1308 ENTRY(lws_table)                                 
1309         LWS_ENTRY(compare_and_swap32)            
1310         LWS_ENTRY(compare_and_swap64)            
1311         LWS_ENTRY(compare_and_swap_2)            
1312         LWS_ENTRY(atomic_xchg)                   
1313         LWS_ENTRY(atomic_store)                  
1314 END(lws_table)                                   
1315         /* End of lws table */                   
1316                                                  
1317 #ifdef CONFIG_64BIT                              
1318 #define __SYSCALL_WITH_COMPAT(nr, native, com    
1319 #else                                            
1320 #define __SYSCALL_WITH_COMPAT(nr, native, com    
1321 #endif                                           
1322 #define __SYSCALL(nr, entry)    ASM_ULONG_INS    
1323         .align 8                                 
1324 ENTRY(sys_call_table)                            
1325         .export sys_call_table,data              
1326 #include <asm/syscall_table_32.h>    /* 32-bi    
1327 END(sys_call_table)                              
1328                                                  
1329 #ifdef CONFIG_64BIT                              
1330         .align 8                                 
1331 ENTRY(sys_call_table64)                          
1332 #include <asm/syscall_table_64.h>    /* 64-bi    
1333 END(sys_call_table64)                            
1334 #endif                                           
1335                                                  
1336         /*                                       
1337                 All light-weight-syscall atom    
1338                 will use this set of locks       
1339                                                  
1340                 NOTE: The lws_lock_start symb    
1341                 at least 16-byte aligned for     
1342                 with ldcw.                       
1343         */                                       
1344         .section .data                           
1345         .align  L1_CACHE_BYTES                   
1346 ENTRY(lws_lock_start)                            
1347         /* lws locks */                          
1348         .rept 256                                
1349         /* Keep locks aligned at 16-bytes */     
1350         .word __ARCH_SPIN_LOCK_UNLOCKED_VAL      
1351         .word 0                                  
1352         .word 0                                  
1353         .word 0                                  
1354         .endr                                    
1355 END(lws_lock_start)                              
1356         .previous                                
1357                                                  
1358 .end                                             
                                                      

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