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

TOMOYO Linux Cross Reference
Linux/arch/s390/mm/pfault.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/s390/mm/pfault.c (Version linux-6.12-rc7) and /arch/sparc/mm/pfault.c (Version linux-6.0.19)


  1 // SPDX-License-Identifier: GPL-2.0                 1 
  2 /*                                                
  3  * Copyright IBM Corp. 1999, 2023                 
  4  */                                               
  5                                                   
  6 #include <linux/cpuhotplug.h>                     
  7 #include <linux/sched/task.h>                     
  8 #include <linux/errno.h>                          
  9 #include <linux/init.h>                           
 10 #include <linux/irq.h>                            
 11 #include <asm/asm-extable.h>                      
 12 #include <asm/pfault.h>                           
 13 #include <asm/diag.h>                             
 14                                                   
 15 #define __SUBCODE_MASK 0x0600                     
 16 #define __PF_RES_FIELD 0x8000000000000000UL       
 17                                                   
 18 /*                                                
 19  * 'pfault' pseudo page faults routines.          
 20  */                                               
 21 static int pfault_disable;                        
 22                                                   
 23 static int __init nopfault(char *str)             
 24 {                                                 
 25         pfault_disable = 1;                       
 26         return 1;                                 
 27 }                                                 
 28 early_param("nopfault", nopfault);                
 29                                                   
 30 struct pfault_refbk {                             
 31         u16 refdiagc;                             
 32         u16 reffcode;                             
 33         u16 refdwlen;                             
 34         u16 refversn;                             
 35         u64 refgaddr;                             
 36         u64 refselmk;                             
 37         u64 refcmpmk;                             
 38         u64 reserved;                             
 39 };                                                
 40                                                   
 41 static struct pfault_refbk pfault_init_refbk =    
 42         .refdiagc = 0x258,                        
 43         .reffcode = 0,                            
 44         .refdwlen = 5,                            
 45         .refversn = 2,                            
 46         .refgaddr = __LC_LPP,                     
 47         .refselmk = 1UL << 48,                    
 48         .refcmpmk = 1UL << 48,                    
 49         .reserved = __PF_RES_FIELD                
 50 };                                                
 51                                                   
 52 int __pfault_init(void)                           
 53 {                                                 
 54         int rc = -EOPNOTSUPP;                     
 55                                                   
 56         if (pfault_disable)                       
 57                 return rc;                        
 58         diag_stat_inc(DIAG_STAT_X258);            
 59         asm volatile(                             
 60                 "       diag    %[refbk],%[rc]    
 61                 "0:     nopr    %%r7\n"           
 62                 EX_TABLE(0b, 0b)                  
 63                 : [rc] "+d" (rc)                  
 64                 : [refbk] "a" (&pfault_init_re    
 65                 : "cc");                          
 66         return rc;                                
 67 }                                                 
 68                                                   
 69 static struct pfault_refbk pfault_fini_refbk =    
 70         .refdiagc = 0x258,                        
 71         .reffcode = 1,                            
 72         .refdwlen = 5,                            
 73         .refversn = 2,                            
 74 };                                                
 75                                                   
 76 void __pfault_fini(void)                          
 77 {                                                 
 78         if (pfault_disable)                       
 79                 return;                           
 80         diag_stat_inc(DIAG_STAT_X258);            
 81         asm volatile(                             
 82                 "       diag    %[refbk],0,0x2    
 83                 "0:     nopr    %%r7\n"           
 84                 EX_TABLE(0b, 0b)                  
 85                 :                                 
 86                 : [refbk] "a" (&pfault_fini_re    
 87                 : "cc");                          
 88 }                                                 
 89                                                   
 90 static DEFINE_SPINLOCK(pfault_lock);              
 91 static LIST_HEAD(pfault_list);                    
 92                                                   
 93 #define PF_COMPLETE     0x0080                    
 94                                                   
 95 /*                                                
 96  * The mechanism of our pfault code: if Linux     
 97  * space process and the user space process ac    
 98  * paged out we get a pfault interrupt.           
 99  *                                                
100  * This allows us, within the guest, to schedu    
101  * this mechanism the host would have to suspe    
102  * the page has been paged in.                    
103  *                                                
104  * So when we get such an interrupt then we se    
105  * to uninterruptible and also set the need_re    
106  * interrupt context(!). If we later on want t    
107  * recognize the need_resched flag and then ca    
108  * obvious how this works...                      
109  *                                                
110  * Of course we have a lot of additional fun w    
111  * host signals that a page of a process has b    
112  * continue to run). This interrupt can arrive    
113  * virtual cpus, actually appear before the in    
114  * is missing.                                    
115  */                                               
116 static void pfault_interrupt(struct ext_code e    
117                              unsigned int para    
118 {                                                 
119         struct task_struct *tsk;                  
120         __u16 subcode;                            
121         pid_t pid;                                
122                                                   
123         /*                                        
124          * Get the external interruption subco    
125          * signal bit. VM stores this in the '    
126          * with the external interrupt.           
127          */                                       
128         subcode = ext_code.subcode;               
129         if ((subcode & 0xff00) != __SUBCODE_MA    
130                 return;                           
131         inc_irq_stat(IRQEXT_PFL);                 
132         /* Get the token (= pid of the affecte    
133         pid = param64 & LPP_PID_MASK;             
134         rcu_read_lock();                          
135         tsk = find_task_by_pid_ns(pid, &init_p    
136         if (tsk)                                  
137                 get_task_struct(tsk);             
138         rcu_read_unlock();                        
139         if (!tsk)                                 
140                 return;                           
141         spin_lock(&pfault_lock);                  
142         if (subcode & PF_COMPLETE) {              
143                 /* signal bit is set -> a page    
144                 if (tsk->thread.pfault_wait ==    
145                         /*                        
146                          * Initial interrupt w    
147                          * interrupt. pfault_w    
148                          * back to zero and wa    
149                          * safely be done beca    
150                          * and can't produce n    
151                          */                       
152                         tsk->thread.pfault_wai    
153                         list_del(&tsk->thread.    
154                         wake_up_process(tsk);     
155                         put_task_struct(tsk);     
156                 } else {                          
157                         /*                        
158                          * Completion interrup    
159                          * interrupt. Set pfau    
160                          * interrupt doesn't p    
161                          * If the task is not     
162                          * interrupt since it     
163                          * CANCEL operation wh    
164                          * completion interrup    
165                          */                       
166                         if (task_is_running(ts    
167                                 tsk->thread.pf    
168                 }                                 
169         } else {                                  
170                 /* signal bit not set -> a rea    
171                 if (WARN_ON_ONCE(tsk != curren    
172                         goto out;                 
173                 if (tsk->thread.pfault_wait ==    
174                         /* Already on the list    
175                         goto block;               
176                 } else if (tsk->thread.pfault_    
177                         /*                        
178                          * Completion interrup    
179                          * interrupt (pfault_w    
180                          * back to zero and ex    
181                          */                       
182                         tsk->thread.pfault_wai    
183                 } else {                          
184                         /*                        
185                          * Initial interrupt a    
186                          * interrupt. Let the     
187                          * An extra task refer    
188                          * cpu may set the tas    
189                          * before the schedule    
190                          */                       
191                         get_task_struct(tsk);     
192                         tsk->thread.pfault_wai    
193                         list_add(&tsk->thread.    
194 block:                                            
195                         /*                        
196                          * Since this must be     
197                          * is no kernel task s    
198                          * return to userspace    
199                          */                       
200                         __set_current_state(TA    
201                         set_tsk_need_resched(t    
202                         set_preempt_need_resch    
203                 }                                 
204         }                                         
205 out:                                              
206         spin_unlock(&pfault_lock);                
207         put_task_struct(tsk);                     
208 }                                                 
209                                                   
210 static int pfault_cpu_dead(unsigned int cpu)      
211 {                                                 
212         struct thread_struct *thread, *next;      
213         struct task_struct *tsk;                  
214                                                   
215         spin_lock_irq(&pfault_lock);              
216         list_for_each_entry_safe(thread, next,    
217                 thread->pfault_wait = 0;          
218                 list_del(&thread->list);          
219                 tsk = container_of(thread, str    
220                 wake_up_process(tsk);             
221                 put_task_struct(tsk);             
222         }                                         
223         spin_unlock_irq(&pfault_lock);            
224         return 0;                                 
225 }                                                 
226                                                   
227 static int __init pfault_irq_init(void)           
228 {                                                 
229         int rc;                                   
230                                                   
231         rc = register_external_irq(EXT_IRQ_CP_    
232         if (rc)                                   
233                 goto out_extint;                  
234         rc = pfault_init() == 0 ? 0 : -EOPNOTS    
235         if (rc)                                   
236                 goto out_pfault;                  
237         irq_subclass_register(IRQ_SUBCLASS_SER    
238         cpuhp_setup_state_nocalls(CPUHP_S390_P    
239                                   NULL, pfault    
240         return 0;                                 
241                                                   
242 out_pfault:                                       
243         unregister_external_irq(EXT_IRQ_CP_SER    
244 out_extint:                                       
245         pfault_disable = 1;                       
246         return rc;                                
247 }                                                 
248 early_initcall(pfault_irq_init);                  
249                                                   

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