aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm/intercept.c
diff options
context:
space:
mode:
authorThomas Huth <thuth@linux.vnet.ibm.com>2014-11-12 11:13:29 -0500
committerChristian Borntraeger <borntraeger@de.ibm.com>2014-11-28 06:32:56 -0500
commit04b41acd060541fa76407d4de1e0acf0edd57c2a (patch)
tree2672c0911920ece6247afb7d0be6631ee4e45258 /arch/s390/kvm/intercept.c
parenta02689fecdbc36503b1496a5d36707bb4559db63 (diff)
KVM: s390: Fix rewinding of the PSW pointing to an EXECUTE instruction
A couple of our interception handlers rewind the PSW to the beginning of the instruction to run the intercepted instruction again during the next SIE entry. This normally works fine, but there is also the possibility that the instruction did not get run directly but via an EXECUTE instruction. In this case, the PSW does not point to the instruction that caused the interception, but to the EXECUTE instruction! So we've got to rewind the PSW to the beginning of the EXECUTE instruction instead. This is now accomplished with a new helper function kvm_s390_rewind_psw(). Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com> Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch/s390/kvm/intercept.c')
-rw-r--r--arch/s390/kvm/intercept.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index eaf46291d361..1d244df5f8c4 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -38,6 +38,19 @@ static const intercept_handler_t instruction_handlers[256] = {
38 [0xeb] = kvm_s390_handle_eb, 38 [0xeb] = kvm_s390_handle_eb,
39}; 39};
40 40
41void kvm_s390_rewind_psw(struct kvm_vcpu *vcpu, int ilc)
42{
43 struct kvm_s390_sie_block *sie_block = vcpu->arch.sie_block;
44
45 /* Use the length of the EXECUTE instruction if necessary */
46 if (sie_block->icptstatus & 1) {
47 ilc = (sie_block->icptstatus >> 4) & 0x6;
48 if (!ilc)
49 ilc = 4;
50 }
51 sie_block->gpsw.addr = __rewind_psw(sie_block->gpsw, ilc);
52}
53
41static int handle_noop(struct kvm_vcpu *vcpu) 54static int handle_noop(struct kvm_vcpu *vcpu)
42{ 55{
43 switch (vcpu->arch.sie_block->icptcode) { 56 switch (vcpu->arch.sie_block->icptcode) {
@@ -288,7 +301,6 @@ static int handle_external_interrupt(struct kvm_vcpu *vcpu)
288 */ 301 */
289static int handle_mvpg_pei(struct kvm_vcpu *vcpu) 302static int handle_mvpg_pei(struct kvm_vcpu *vcpu)
290{ 303{
291 psw_t *psw = &vcpu->arch.sie_block->gpsw;
292 unsigned long srcaddr, dstaddr; 304 unsigned long srcaddr, dstaddr;
293 int reg1, reg2, rc; 305 int reg1, reg2, rc;
294 306
@@ -310,7 +322,7 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu)
310 if (rc != 0) 322 if (rc != 0)
311 return rc; 323 return rc;
312 324
313 psw->addr = __rewind_psw(*psw, 4); 325 kvm_s390_rewind_psw(vcpu, 4);
314 326
315 return 0; 327 return 0;
316} 328}