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

TOMOYO Linux Cross Reference
Linux/arch/s390/kvm/intercept.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/kvm/intercept.c (Version linux-6.12-rc7) and /arch/mips/kvm/intercept.c (Version linux-5.18.19)


  1 // SPDX-License-Identifier: GPL-2.0                 1 
  2 /*                                                
  3  * in-kernel handling for sie intercepts          
  4  *                                                
  5  * Copyright IBM Corp. 2008, 2020                 
  6  *                                                
  7  *    Author(s): Carsten Otte <cotte@de.ibm.co    
  8  *               Christian Borntraeger <borntr    
  9  */                                               
 10                                                   
 11 #include <linux/kvm_host.h>                       
 12 #include <linux/errno.h>                          
 13 #include <linux/pagemap.h>                        
 14                                                   
 15 #include <asm/asm-offsets.h>                      
 16 #include <asm/irq.h>                              
 17 #include <asm/sysinfo.h>                          
 18 #include <asm/uv.h>                               
 19                                                   
 20 #include "kvm-s390.h"                             
 21 #include "gaccess.h"                              
 22 #include "trace.h"                                
 23 #include "trace-s390.h"                           
 24                                                   
 25 u8 kvm_s390_get_ilen(struct kvm_vcpu *vcpu)       
 26 {                                                 
 27         struct kvm_s390_sie_block *sie_block =    
 28         u8 ilen = 0;                              
 29                                                   
 30         switch (vcpu->arch.sie_block->icptcode    
 31         case ICPT_INST:                           
 32         case ICPT_INSTPROGI:                      
 33         case ICPT_OPEREXC:                        
 34         case ICPT_PARTEXEC:                       
 35         case ICPT_IOINST:                         
 36                 /* instruction only stored for    
 37                 ilen = insn_length(vcpu->arch.    
 38                 /* Use the length of the EXECU    
 39                 if (sie_block->icptstatus & 1)    
 40                         ilen = (sie_block->icp    
 41                         if (!ilen)                
 42                                 ilen = 4;         
 43                 }                                 
 44                 break;                            
 45         case ICPT_PROGI:                          
 46                 /* bit 1+2 of pgmilc are the i    
 47                 ilen = vcpu->arch.sie_block->p    
 48                 break;                            
 49         }                                         
 50         return ilen;                              
 51 }                                                 
 52                                                   
 53 static int handle_stop(struct kvm_vcpu *vcpu)     
 54 {                                                 
 55         struct kvm_s390_local_interrupt *li =     
 56         int rc = 0;                               
 57         uint8_t flags, stop_pending;              
 58                                                   
 59         vcpu->stat.exit_stop_request++;           
 60                                                   
 61         /* delay the stop if any non-stop irq     
 62         if (kvm_s390_vcpu_has_irq(vcpu, 1))       
 63                 return 0;                         
 64                                                   
 65         /* avoid races with the injection/SIGP    
 66         spin_lock(&li->lock);                     
 67         flags = li->irq.stop.flags;               
 68         stop_pending = kvm_s390_is_stop_irq_pe    
 69         spin_unlock(&li->lock);                   
 70                                                   
 71         trace_kvm_s390_stop_request(stop_pendi    
 72         if (!stop_pending)                        
 73                 return 0;                         
 74                                                   
 75         if (flags & KVM_S390_STOP_FLAG_STORE_S    
 76                 rc = kvm_s390_vcpu_store_statu    
 77                                                   
 78                 if (rc)                           
 79                         return rc;                
 80         }                                         
 81                                                   
 82         /*                                        
 83          * no need to check the return value o    
 84          * an error for protvirt, but protvirt    
 85          */                                       
 86         if (!kvm_s390_user_cpu_state_ctrl(vcpu    
 87                 kvm_s390_vcpu_stop(vcpu);         
 88         return -EOPNOTSUPP;                       
 89 }                                                 
 90                                                   
 91 static int handle_validity(struct kvm_vcpu *vc    
 92 {                                                 
 93         int viwhy = vcpu->arch.sie_block->ipb     
 94                                                   
 95         vcpu->stat.exit_validity++;               
 96         trace_kvm_s390_intercept_validity(vcpu    
 97         KVM_EVENT(3, "validity intercept 0x%x     
 98                   current->pid, vcpu->kvm);       
 99                                                   
100         /* do not warn on invalid runtime inst    
101         WARN_ONCE(viwhy != 0x44, "kvm: unhandl    
102                   viwhy);                         
103         return -EINVAL;                           
104 }                                                 
105                                                   
106 static int handle_instruction(struct kvm_vcpu     
107 {                                                 
108         vcpu->stat.exit_instruction++;            
109         trace_kvm_s390_intercept_instruction(v    
110                                              v    
111                                              v    
112                                                   
113         switch (vcpu->arch.sie_block->ipa >> 8    
114         case 0x01:                                
115                 return kvm_s390_handle_01(vcpu    
116         case 0x82:                                
117                 return kvm_s390_handle_lpsw(vc    
118         case 0x83:                                
119                 return kvm_s390_handle_diag(vc    
120         case 0xaa:                                
121                 return kvm_s390_handle_aa(vcpu    
122         case 0xae:                                
123                 return kvm_s390_handle_sigp(vc    
124         case 0xb2:                                
125                 return kvm_s390_handle_b2(vcpu    
126         case 0xb6:                                
127                 return kvm_s390_handle_stctl(v    
128         case 0xb7:                                
129                 return kvm_s390_handle_lctl(vc    
130         case 0xb9:                                
131                 return kvm_s390_handle_b9(vcpu    
132         case 0xe3:                                
133                 return kvm_s390_handle_e3(vcpu    
134         case 0xe5:                                
135                 return kvm_s390_handle_e5(vcpu    
136         case 0xeb:                                
137                 return kvm_s390_handle_eb(vcpu    
138         default:                                  
139                 return -EOPNOTSUPP;               
140         }                                         
141 }                                                 
142                                                   
143 static int inject_prog_on_prog_intercept(struc    
144 {                                                 
145         struct kvm_s390_pgm_info pgm_info = {     
146                 .code = vcpu->arch.sie_block->    
147                 /* the PSW has already been re    
148                 .flags = KVM_S390_PGM_FLAGS_NO    
149         };                                        
150                                                   
151         switch (vcpu->arch.sie_block->iprcc &     
152         case PGM_AFX_TRANSLATION:                 
153         case PGM_ASX_TRANSLATION:                 
154         case PGM_EX_TRANSLATION:                  
155         case PGM_LFX_TRANSLATION:                 
156         case PGM_LSTE_SEQUENCE:                   
157         case PGM_LSX_TRANSLATION:                 
158         case PGM_LX_TRANSLATION:                  
159         case PGM_PRIMARY_AUTHORITY:               
160         case PGM_SECONDARY_AUTHORITY:             
161         case PGM_SPACE_SWITCH:                    
162                 pgm_info.trans_exc_code = vcpu    
163                 break;                            
164         case PGM_ALEN_TRANSLATION:                
165         case PGM_ALE_SEQUENCE:                    
166         case PGM_ASTE_INSTANCE:                   
167         case PGM_ASTE_SEQUENCE:                   
168         case PGM_ASTE_VALIDITY:                   
169         case PGM_EXTENDED_AUTHORITY:              
170                 pgm_info.exc_access_id = vcpu-    
171                 break;                            
172         case PGM_ASCE_TYPE:                       
173         case PGM_PAGE_TRANSLATION:                
174         case PGM_REGION_FIRST_TRANS:              
175         case PGM_REGION_SECOND_TRANS:             
176         case PGM_REGION_THIRD_TRANS:              
177         case PGM_SEGMENT_TRANSLATION:             
178                 pgm_info.trans_exc_code = vcpu    
179                 pgm_info.exc_access_id  = vcpu    
180                 pgm_info.op_access_id  = vcpu-    
181                 break;                            
182         case PGM_MONITOR:                         
183                 pgm_info.mon_class_nr = vcpu->    
184                 pgm_info.mon_code = vcpu->arch    
185                 break;                            
186         case PGM_VECTOR_PROCESSING:               
187         case PGM_DATA:                            
188                 pgm_info.data_exc_code = vcpu-    
189                 break;                            
190         case PGM_PROTECTION:                      
191                 pgm_info.trans_exc_code = vcpu    
192                 pgm_info.exc_access_id  = vcpu    
193                 break;                            
194         default:                                  
195                 break;                            
196         }                                         
197                                                   
198         if (vcpu->arch.sie_block->iprcc & PGM_    
199                 pgm_info.per_code = vcpu->arch    
200                 pgm_info.per_atmid = vcpu->arc    
201                 pgm_info.per_address = vcpu->a    
202                 pgm_info.per_access_id = vcpu-    
203         }                                         
204         return kvm_s390_inject_prog_irq(vcpu,     
205 }                                                 
206                                                   
207 /*                                                
208  * restore ITDB to program-interruption TDB in    
209  * and set TX abort indication if required        
210 */                                                
211 static int handle_itdb(struct kvm_vcpu *vcpu)     
212 {                                                 
213         struct kvm_s390_itdb *itdb;               
214         int rc;                                   
215                                                   
216         if (!IS_TE_ENABLED(vcpu) || !IS_ITDB_V    
217                 return 0;                         
218         if (current->thread.per_flags & PER_FL    
219                 return 0;                         
220         itdb = phys_to_virt(vcpu->arch.sie_blo    
221         rc = write_guest_lc(vcpu, __LC_PGM_TDB    
222         if (rc)                                   
223                 return rc;                        
224         memset(itdb, 0, sizeof(*itdb));           
225                                                   
226         return 0;                                 
227 }                                                 
228                                                   
229 #define per_event(vcpu) (vcpu->arch.sie_block-    
230                                                   
231 static bool should_handle_per_event(const stru    
232 {                                                 
233         if (!guestdbg_enabled(vcpu) || !per_ev    
234                 return false;                     
235         if (guestdbg_sstep_enabled(vcpu) &&       
236             vcpu->arch.sie_block->iprcc != PGM    
237                 /*                                
238                  * __vcpu_run() will exit afte    
239                  * indicated condition.           
240                  */                               
241                 return false;                     
242         }                                         
243         return true;                              
244 }                                                 
245                                                   
246 static int handle_prog(struct kvm_vcpu *vcpu)     
247 {                                                 
248         psw_t psw;                                
249         int rc;                                   
250                                                   
251         vcpu->stat.exit_program_interruption++    
252                                                   
253         /*                                        
254          * Intercept 8 indicates a loop of spe    
255          * for protected guests.                  
256          */                                       
257         if (kvm_s390_pv_cpu_is_protected(vcpu)    
258                 return -EOPNOTSUPP;               
259                                                   
260         if (should_handle_per_event(vcpu)) {      
261                 rc = kvm_s390_handle_per_event    
262                 if (rc)                           
263                         return rc;                
264                 /* the interrupt might have be    
265                 if (vcpu->arch.sie_block->iprc    
266                         return 0;                 
267         }                                         
268                                                   
269         trace_kvm_s390_intercept_prog(vcpu, vc    
270         if (vcpu->arch.sie_block->iprcc == PGM    
271                 rc = read_guest_lc(vcpu, __LC_    
272                 if (rc)                           
273                         return rc;                
274                 /* Avoid endless loops of spec    
275                 if (!is_valid_psw(&psw))          
276                         return -EOPNOTSUPP;       
277         }                                         
278         rc = handle_itdb(vcpu);                   
279         if (rc)                                   
280                 return rc;                        
281                                                   
282         return inject_prog_on_prog_intercept(v    
283 }                                                 
284                                                   
285 /**                                               
286  * handle_external_interrupt - used for extern    
287  * @vcpu: virtual cpu                             
288  *                                                
289  * This interception occurs if:                   
290  * - the CPUSTAT_EXT_INT bit was already set w    
291  *   occurred. In this case, the interrupt nee    
292  *   preserve interrupt priority.                 
293  * - the external new PSW has external interru    
294  *   interruption loop. We drop to userspace i    
295  *                                                
296  * The latter case can be detected by inspecti    
297  * external new psw.                              
298  *                                                
299  * Under PV, only the latter case can occur, s    
300  * handled in the ultravisor.                     
301  */                                               
302 static int handle_external_interrupt(struct kv    
303 {                                                 
304         u16 eic = vcpu->arch.sie_block->eic;      
305         struct kvm_s390_irq irq;                  
306         psw_t newpsw;                             
307         int rc;                                   
308                                                   
309         vcpu->stat.exit_external_interrupt++;     
310                                                   
311         if (kvm_s390_pv_cpu_is_protected(vcpu)    
312                 newpsw = vcpu->arch.sie_block-    
313         } else {                                  
314                 rc = read_guest_lc(vcpu, __LC_    
315                 if (rc)                           
316                         return rc;                
317         }                                         
318                                                   
319         /*                                        
320          * Clock comparator or timer interrupt    
321          * will cause interrupt loop. Drop to     
322          */                                       
323         if ((eic == EXT_IRQ_CLK_COMP || eic ==    
324             (newpsw.mask & PSW_MASK_EXT))         
325                 return -EOPNOTSUPP;               
326                                                   
327         switch (eic) {                            
328         case EXT_IRQ_CLK_COMP:                    
329                 irq.type = KVM_S390_INT_CLOCK_    
330                 break;                            
331         case EXT_IRQ_CPU_TIMER:                   
332                 irq.type = KVM_S390_INT_CPU_TI    
333                 break;                            
334         case EXT_IRQ_EXTERNAL_CALL:               
335                 irq.type = KVM_S390_INT_EXTERN    
336                 irq.u.extcall.code = vcpu->arc    
337                 rc = kvm_s390_inject_vcpu(vcpu    
338                 /* ignore if another external     
339                 if (rc == -EBUSY)                 
340                         return 0;                 
341                 return rc;                        
342         default:                                  
343                 return -EOPNOTSUPP;               
344         }                                         
345                                                   
346         return kvm_s390_inject_vcpu(vcpu, &irq    
347 }                                                 
348                                                   
349 /**                                               
350  * handle_mvpg_pei - Handle MOVE PAGE partial     
351  * @vcpu: virtual cpu                             
352  *                                                
353  * This interception can only happen for guest    
354  * addresses that are currently not mapped in     
355  * set up the mappings for the corresponding u    
356  * addressing exceptions in case of illegal gu    
357  */                                               
358 static int handle_mvpg_pei(struct kvm_vcpu *vc    
359 {                                                 
360         unsigned long srcaddr, dstaddr;           
361         int reg1, reg2, rc;                       
362                                                   
363         kvm_s390_get_regs_rre(vcpu, &reg1, &re    
364                                                   
365         /* Ensure that the source is paged-in,    
366         rc = guest_translate_address_with_key(    
367                                                   
368         if (rc)                                   
369                 return kvm_s390_inject_prog_co    
370         rc = kvm_arch_fault_in_page(vcpu, srca    
371         if (rc != 0)                              
372                 return rc;                        
373                                                   
374         /* Ensure that the source is paged-in,    
375         rc = guest_translate_address_with_key(    
376                                                   
377         if (rc)                                   
378                 return kvm_s390_inject_prog_co    
379         rc = kvm_arch_fault_in_page(vcpu, dsta    
380         if (rc != 0)                              
381                 return rc;                        
382                                                   
383         kvm_s390_retry_instr(vcpu);               
384                                                   
385         return 0;                                 
386 }                                                 
387                                                   
388 static int handle_partial_execution(struct kvm    
389 {                                                 
390         vcpu->stat.exit_pei++;                    
391                                                   
392         if (vcpu->arch.sie_block->ipa == 0xb25    
393                 return handle_mvpg_pei(vcpu);     
394         if (vcpu->arch.sie_block->ipa >> 8 ==     
395                 return kvm_s390_handle_sigp_pe    
396                                                   
397         return -EOPNOTSUPP;                       
398 }                                                 
399                                                   
400 /*                                                
401  * Handle the sthyi instruction that provides     
402  * information, like current CPU resources ava    
403  * the machine.                                   
404  */                                               
405 int handle_sthyi(struct kvm_vcpu *vcpu)           
406 {                                                 
407         int reg1, reg2, cc = 0, r = 0;            
408         u64 code, addr, rc = 0;                   
409         struct sthyi_sctns *sctns = NULL;         
410                                                   
411         if (!test_kvm_facility(vcpu->kvm, 74))    
412                 return kvm_s390_inject_program    
413                                                   
414         kvm_s390_get_regs_rre(vcpu, &reg1, &re    
415         code = vcpu->run->s.regs.gprs[reg1];      
416         addr = vcpu->run->s.regs.gprs[reg2];      
417                                                   
418         vcpu->stat.instruction_sthyi++;           
419         VCPU_EVENT(vcpu, 3, "STHYI: fc: %llu a    
420         trace_kvm_s390_handle_sthyi(vcpu, code    
421                                                   
422         if (reg1 == reg2 || reg1 & 1 || reg2 &    
423                 return kvm_s390_inject_program    
424                                                   
425         if (code & 0xffff) {                      
426                 cc = 3;                           
427                 rc = 4;                           
428                 goto out;                         
429         }                                         
430                                                   
431         if (!kvm_s390_pv_cpu_is_protected(vcpu    
432                 return kvm_s390_inject_program    
433                                                   
434         sctns = (void *)get_zeroed_page(GFP_KE    
435         if (!sctns)                               
436                 return -ENOMEM;                   
437                                                   
438         cc = sthyi_fill(sctns, &rc);              
439         if (cc < 0) {                             
440                 free_page((unsigned long)sctns    
441                 return cc;                        
442         }                                         
443 out:                                              
444         if (!cc) {                                
445                 if (kvm_s390_pv_cpu_is_protect    
446                         memcpy(sida_addr(vcpu-    
447                 } else {                          
448                         r = write_guest(vcpu,     
449                         if (r) {                  
450                                 free_page((uns    
451                                 return kvm_s39    
452                         }                         
453                 }                                 
454         }                                         
455                                                   
456         free_page((unsigned long)sctns);          
457         vcpu->run->s.regs.gprs[reg2 + 1] = rc;    
458         kvm_s390_set_psw_cc(vcpu, cc);            
459         return r;                                 
460 }                                                 
461                                                   
462 static int handle_operexc(struct kvm_vcpu *vcp    
463 {                                                 
464         psw_t oldpsw, newpsw;                     
465         int rc;                                   
466                                                   
467         vcpu->stat.exit_operation_exception++;    
468         trace_kvm_s390_handle_operexc(vcpu, vc    
469                                       vcpu->ar    
470                                                   
471         if (vcpu->arch.sie_block->ipa == 0xb25    
472                 return handle_sthyi(vcpu);        
473                                                   
474         if (vcpu->arch.sie_block->ipa == 0 &&     
475                 return -EOPNOTSUPP;               
476         rc = read_guest_lc(vcpu, __LC_PGM_NEW_    
477         if (rc)                                   
478                 return rc;                        
479         /*                                        
480          * Avoid endless loops of operation ex    
481          * PSW will cause a new operation exce    
482          * The heuristic checks if the pgm new    
483          * the faulting psw address (with same    
484          * new psw is not a wait psw and the f    
485          * problem state.                         
486          */                                       
487         oldpsw = vcpu->arch.sie_block->gpsw;      
488         if (oldpsw.addr - newpsw.addr <= 6 &&     
489             !(newpsw.mask & PSW_MASK_WAIT) &&     
490             !(oldpsw.mask & PSW_MASK_PSTATE) &    
491             (newpsw.mask & PSW_MASK_ASC) == (o    
492             (newpsw.mask & PSW_MASK_DAT) == (o    
493                 return -EOPNOTSUPP;               
494                                                   
495         return kvm_s390_inject_program_int(vcp    
496 }                                                 
497                                                   
498 static int handle_pv_spx(struct kvm_vcpu *vcpu    
499 {                                                 
500         u32 pref = *(u32 *)sida_addr(vcpu->arc    
501                                                   
502         kvm_s390_set_prefix(vcpu, pref);          
503         trace_kvm_s390_handle_prefix(vcpu, 1,     
504         return 0;                                 
505 }                                                 
506                                                   
507 static int handle_pv_sclp(struct kvm_vcpu *vcp    
508 {                                                 
509         struct kvm_s390_float_interrupt *fi =     
510                                                   
511         spin_lock(&fi->lock);                     
512         /*                                        
513          * 2 cases:                               
514          * a: an sccb answering interrupt was     
515          *    As the sccb value is not known w    
516          *    trigger delivery of a saved SCCB    
517          *    copy of the SCCB value.             
518          * b: an error SCCB interrupt needs to    
519          *    a fake SCCB address. Firmware wi    
520          * This makes sure, that both errors a    
521          * be delivered after a notification i    
522          * finished) but not after others.        
523          */                                       
524         fi->srv_signal.ext_params |= 0x43000;     
525         set_bit(IRQ_PEND_EXT_SERVICE, &fi->pen    
526         clear_bit(IRQ_PEND_EXT_SERVICE, &fi->m    
527         spin_unlock(&fi->lock);                   
528         return 0;                                 
529 }                                                 
530                                                   
531 static int handle_pv_uvc(struct kvm_vcpu *vcpu    
532 {                                                 
533         struct uv_cb_share *guest_uvcb = sida_    
534         struct uv_cb_cts uvcb = {                 
535                 .header.cmd     = UVC_CMD_UNPI    
536                 .header.len     = sizeof(uvcb)    
537                 .guest_handle   = kvm_s390_pv_    
538                 .gaddr          = guest_uvcb->    
539         };                                        
540         int rc;                                   
541                                                   
542         if (guest_uvcb->header.cmd != UVC_CMD_    
543                 WARN_ONCE(1, "Unexpected notif    
544                           guest_uvcb->header.c    
545                 return 0;                         
546         }                                         
547         rc = gmap_make_secure(vcpu->arch.gmap,    
548         /*                                        
549          * If the unpin did not succeed, the g    
550          * and we will retry the unpin.           
551          */                                       
552         if (rc == -EINVAL)                        
553                 return 0;                         
554         /*                                        
555          * If we got -EAGAIN here, we simply r    
556          * get propagated all the way to users    
557          * again.                                 
558          */                                       
559         return rc;                                
560 }                                                 
561                                                   
562 static int handle_pv_notification(struct kvm_v    
563 {                                                 
564         int ret;                                  
565                                                   
566         if (vcpu->arch.sie_block->ipa == 0xb21    
567                 return handle_pv_spx(vcpu);       
568         if (vcpu->arch.sie_block->ipa == 0xb22    
569                 return handle_pv_sclp(vcpu);      
570         if (vcpu->arch.sie_block->ipa == 0xb9a    
571                 return handle_pv_uvc(vcpu);       
572         if (vcpu->arch.sie_block->ipa >> 8 ==     
573                 /*                                
574                  * Besides external call, othe    
575                  * 108 (pv notify) intercept.     
576                  * these orders need to be emu    
577                  * place to handle them is in     
578                  * So first try kvm_s390_handl    
579                  * successful, go on with hand    
580                  */                               
581                 ret = kvm_s390_handle_sigp_pei    
582                 if (!ret)                         
583                         return ret;               
584         }                                         
585                                                   
586         return handle_instruction(vcpu);          
587 }                                                 
588                                                   
589 static bool should_handle_per_ifetch(const str    
590 {                                                 
591         /* Process PER, also if the instructio    
592         if (!(vcpu->arch.sie_block->icptstatus    
593                 return false;                     
594         if (rc != 0 && rc != -EOPNOTSUPP)         
595                 return false;                     
596         if (guestdbg_sstep_enabled(vcpu) && vc    
597                 /* __vcpu_run() will exit afte    
598                 return false;                     
599         return true;                              
600 }                                                 
601                                                   
602 int kvm_handle_sie_intercept(struct kvm_vcpu *    
603 {                                                 
604         int rc, per_rc = 0;                       
605                                                   
606         if (kvm_is_ucontrol(vcpu->kvm))           
607                 return -EOPNOTSUPP;               
608                                                   
609         switch (vcpu->arch.sie_block->icptcode    
610         case ICPT_EXTREQ:                         
611                 vcpu->stat.exit_external_reque    
612                 return 0;                         
613         case ICPT_IOREQ:                          
614                 vcpu->stat.exit_io_request++;     
615                 return 0;                         
616         case ICPT_INST:                           
617                 rc = handle_instruction(vcpu);    
618                 break;                            
619         case ICPT_PROGI:                          
620                 return handle_prog(vcpu);         
621         case ICPT_EXTINT:                         
622                 return handle_external_interru    
623         case ICPT_WAIT:                           
624                 return kvm_s390_handle_wait(vc    
625         case ICPT_VALIDITY:                       
626                 return handle_validity(vcpu);     
627         case ICPT_STOP:                           
628                 return handle_stop(vcpu);         
629         case ICPT_OPEREXC:                        
630                 rc = handle_operexc(vcpu);        
631                 break;                            
632         case ICPT_PARTEXEC:                       
633                 rc = handle_partial_execution(    
634                 break;                            
635         case ICPT_KSS:                            
636                 /* Instruction will be redrive    
637                 return kvm_s390_skey_check_ena    
638         case ICPT_MCHKREQ:                        
639         case ICPT_INT_ENABLE:                     
640                 /*                                
641                  * PSW bit 13 or a CR (0, 6, 1    
642                  * now be able to deliver inte    
643                  * will take care of this.        
644                  */                               
645                 rc = 0;                           
646                 break;                            
647         case ICPT_PV_INSTR:                       
648                 rc = handle_instruction(vcpu);    
649                 break;                            
650         case ICPT_PV_NOTIFY:                      
651                 rc = handle_pv_notification(vc    
652                 break;                            
653         case ICPT_PV_PREF:                        
654                 rc = 0;                           
655                 gmap_convert_to_secure(vcpu->a    
656                                        kvm_s39    
657                 gmap_convert_to_secure(vcpu->a    
658                                        kvm_s39    
659                 break;                            
660         default:                                  
661                 return -EOPNOTSUPP;               
662         }                                         
663                                                   
664         if (should_handle_per_ifetch(vcpu, rc)    
665                 per_rc = kvm_s390_handle_per_i    
666         return per_rc ? per_rc : rc;              
667 }                                                 
668                                                   

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