diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2012-12-20 09:32:10 -0500 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2013-01-07 16:53:41 -0500 |
commit | f379aae558b8daff0f7a1c5fc225af5d35c741f7 (patch) | |
tree | 26f66b7da5a2883cc4049e838f4a1fb75ef604aa /arch/s390/kvm/priv.c | |
parent | 48a3e950f4cee6a345ffbe9baf599f1e9a54c479 (diff) |
KVM: s390: In-kernel handling of I/O instructions.
Explicitely catch all channel I/O related instructions intercepts
in the kernel and set condition code 3 for them.
This paves the way for properly handling these instructions later
on.
Note: This is not architecture compliant (the previous code wasn't
either) since setting cc 3 is not the correct thing to do for some
of these instructions. For Linux guests, however, it still has the
intended effect of stopping css probing.
Reviewed-by: Marcelo Tosatti <mtosatti@redhat.com>
Reviewed-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/s390/kvm/priv.c')
-rw-r--r-- | arch/s390/kvm/priv.c | 56 |
1 files changed, 39 insertions, 17 deletions
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index d3cbcd3c9ada..8ad776f87856 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c | |||
@@ -127,20 +127,9 @@ static int handle_skey(struct kvm_vcpu *vcpu) | |||
127 | return 0; | 127 | return 0; |
128 | } | 128 | } |
129 | 129 | ||
130 | static int handle_stsch(struct kvm_vcpu *vcpu) | 130 | static int handle_io_inst(struct kvm_vcpu *vcpu) |
131 | { | 131 | { |
132 | vcpu->stat.instruction_stsch++; | 132 | VCPU_EVENT(vcpu, 4, "%s", "I/O instruction"); |
133 | VCPU_EVENT(vcpu, 4, "%s", "store subchannel - CC3"); | ||
134 | /* condition code 3 */ | ||
135 | vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); | ||
136 | vcpu->arch.sie_block->gpsw.mask |= (3 & 3ul) << 44; | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static int handle_chsc(struct kvm_vcpu *vcpu) | ||
141 | { | ||
142 | vcpu->stat.instruction_chsc++; | ||
143 | VCPU_EVENT(vcpu, 4, "%s", "channel subsystem call - CC3"); | ||
144 | /* condition code 3 */ | 133 | /* condition code 3 */ |
145 | vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); | 134 | vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); |
146 | vcpu->arch.sie_block->gpsw.mask |= (3 & 3ul) << 44; | 135 | vcpu->arch.sie_block->gpsw.mask |= (3 & 3ul) << 44; |
@@ -375,7 +364,7 @@ out_fail: | |||
375 | return 0; | 364 | return 0; |
376 | } | 365 | } |
377 | 366 | ||
378 | static const intercept_handler_t priv_handlers[256] = { | 367 | static const intercept_handler_t b2_handlers[256] = { |
379 | [0x02] = handle_stidp, | 368 | [0x02] = handle_stidp, |
380 | [0x10] = handle_set_prefix, | 369 | [0x10] = handle_set_prefix, |
381 | [0x11] = handle_store_prefix, | 370 | [0x11] = handle_store_prefix, |
@@ -383,8 +372,22 @@ static const intercept_handler_t priv_handlers[256] = { | |||
383 | [0x29] = handle_skey, | 372 | [0x29] = handle_skey, |
384 | [0x2a] = handle_skey, | 373 | [0x2a] = handle_skey, |
385 | [0x2b] = handle_skey, | 374 | [0x2b] = handle_skey, |
386 | [0x34] = handle_stsch, | 375 | [0x30] = handle_io_inst, |
387 | [0x5f] = handle_chsc, | 376 | [0x31] = handle_io_inst, |
377 | [0x32] = handle_io_inst, | ||
378 | [0x33] = handle_io_inst, | ||
379 | [0x34] = handle_io_inst, | ||
380 | [0x35] = handle_io_inst, | ||
381 | [0x36] = handle_io_inst, | ||
382 | [0x37] = handle_io_inst, | ||
383 | [0x38] = handle_io_inst, | ||
384 | [0x39] = handle_io_inst, | ||
385 | [0x3a] = handle_io_inst, | ||
386 | [0x3b] = handle_io_inst, | ||
387 | [0x3c] = handle_io_inst, | ||
388 | [0x5f] = handle_io_inst, | ||
389 | [0x74] = handle_io_inst, | ||
390 | [0x76] = handle_io_inst, | ||
388 | [0x7d] = handle_stsi, | 391 | [0x7d] = handle_stsi, |
389 | [0xb1] = handle_stfl, | 392 | [0xb1] = handle_stfl, |
390 | [0xb2] = handle_lpswe, | 393 | [0xb2] = handle_lpswe, |
@@ -401,7 +404,7 @@ int kvm_s390_handle_b2(struct kvm_vcpu *vcpu) | |||
401 | * state bit and (a) handle the instruction or (b) send a code 2 | 404 | * state bit and (a) handle the instruction or (b) send a code 2 |
402 | * program check. | 405 | * program check. |
403 | * Anything else goes to userspace.*/ | 406 | * Anything else goes to userspace.*/ |
404 | handler = priv_handlers[vcpu->arch.sie_block->ipa & 0x00ff]; | 407 | handler = b2_handlers[vcpu->arch.sie_block->ipa & 0x00ff]; |
405 | if (handler) { | 408 | if (handler) { |
406 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | 409 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) |
407 | return kvm_s390_inject_program_int(vcpu, | 410 | return kvm_s390_inject_program_int(vcpu, |
@@ -432,6 +435,7 @@ static int handle_epsw(struct kvm_vcpu *vcpu) | |||
432 | 435 | ||
433 | static const intercept_handler_t b9_handlers[256] = { | 436 | static const intercept_handler_t b9_handlers[256] = { |
434 | [0x8d] = handle_epsw, | 437 | [0x8d] = handle_epsw, |
438 | [0x9c] = handle_io_inst, | ||
435 | }; | 439 | }; |
436 | 440 | ||
437 | int kvm_s390_handle_b9(struct kvm_vcpu *vcpu) | 441 | int kvm_s390_handle_b9(struct kvm_vcpu *vcpu) |
@@ -451,6 +455,24 @@ int kvm_s390_handle_b9(struct kvm_vcpu *vcpu) | |||
451 | return -EOPNOTSUPP; | 455 | return -EOPNOTSUPP; |
452 | } | 456 | } |
453 | 457 | ||
458 | static const intercept_handler_t eb_handlers[256] = { | ||
459 | [0x8a] = handle_io_inst, | ||
460 | }; | ||
461 | |||
462 | int kvm_s390_handle_priv_eb(struct kvm_vcpu *vcpu) | ||
463 | { | ||
464 | intercept_handler_t handler; | ||
465 | |||
466 | /* All eb instructions that end up here are privileged. */ | ||
467 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
468 | return kvm_s390_inject_program_int(vcpu, | ||
469 | PGM_PRIVILEGED_OPERATION); | ||
470 | handler = eb_handlers[vcpu->arch.sie_block->ipb & 0xff]; | ||
471 | if (handler) | ||
472 | return handler(vcpu); | ||
473 | return -EOPNOTSUPP; | ||
474 | } | ||
475 | |||
454 | static int handle_tprot(struct kvm_vcpu *vcpu) | 476 | static int handle_tprot(struct kvm_vcpu *vcpu) |
455 | { | 477 | { |
456 | u64 address1, address2; | 478 | u64 address1, address2; |