aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2012-12-20 09:32:10 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2013-01-07 16:53:41 -0500
commitf379aae558b8daff0f7a1c5fc225af5d35c741f7 (patch)
tree26f66b7da5a2883cc4049e838f4a1fb75ef604aa
parent48a3e950f4cee6a345ffbe9baf599f1e9a54c479 (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>
-rw-r--r--arch/s390/kvm/intercept.c19
-rw-r--r--arch/s390/kvm/kvm-s390.h1
-rw-r--r--arch/s390/kvm/priv.c56
3 files changed, 56 insertions, 20 deletions
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index 950c13ecaf60..71af87dbb42c 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -30,8 +30,6 @@ static int handle_lctlg(struct kvm_vcpu *vcpu)
30 int reg, rc; 30 int reg, rc;
31 31
32 vcpu->stat.instruction_lctlg++; 32 vcpu->stat.instruction_lctlg++;
33 if ((vcpu->arch.sie_block->ipb & 0xff) != 0x2f)
34 return -EOPNOTSUPP;
35 33
36 useraddr = kvm_s390_get_base_disp_rsy(vcpu); 34 useraddr = kvm_s390_get_base_disp_rsy(vcpu);
37 35
@@ -95,6 +93,21 @@ static int handle_lctl(struct kvm_vcpu *vcpu)
95 return 0; 93 return 0;
96} 94}
97 95
96static const intercept_handler_t eb_handlers[256] = {
97 [0x2f] = handle_lctlg,
98 [0x8a] = kvm_s390_handle_priv_eb,
99};
100
101static int handle_eb(struct kvm_vcpu *vcpu)
102{
103 intercept_handler_t handler;
104
105 handler = eb_handlers[vcpu->arch.sie_block->ipb & 0xff];
106 if (handler)
107 return handler(vcpu);
108 return -EOPNOTSUPP;
109}
110
98static const intercept_handler_t instruction_handlers[256] = { 111static const intercept_handler_t instruction_handlers[256] = {
99 [0x01] = kvm_s390_handle_01, 112 [0x01] = kvm_s390_handle_01,
100 [0x82] = kvm_s390_handle_lpsw, 113 [0x82] = kvm_s390_handle_lpsw,
@@ -104,7 +117,7 @@ static const intercept_handler_t instruction_handlers[256] = {
104 [0xb7] = handle_lctl, 117 [0xb7] = handle_lctl,
105 [0xb9] = kvm_s390_handle_b9, 118 [0xb9] = kvm_s390_handle_b9,
106 [0xe5] = kvm_s390_handle_e5, 119 [0xe5] = kvm_s390_handle_e5,
107 [0xeb] = handle_lctlg, 120 [0xeb] = handle_eb,
108}; 121};
109 122
110static int handle_noop(struct kvm_vcpu *vcpu) 123static int handle_noop(struct kvm_vcpu *vcpu)
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 1f7cc6ccf102..211b340385a7 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -120,6 +120,7 @@ int kvm_s390_handle_e5(struct kvm_vcpu *vcpu);
120int kvm_s390_handle_01(struct kvm_vcpu *vcpu); 120int kvm_s390_handle_01(struct kvm_vcpu *vcpu);
121int kvm_s390_handle_b9(struct kvm_vcpu *vcpu); 121int kvm_s390_handle_b9(struct kvm_vcpu *vcpu);
122int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu); 122int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu);
123int kvm_s390_handle_priv_eb(struct kvm_vcpu *vcpu);
123 124
124/* implemented in sigp.c */ 125/* implemented in sigp.c */
125int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); 126int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu);
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
130static int handle_stsch(struct kvm_vcpu *vcpu) 130static 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
140static 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
378static const intercept_handler_t priv_handlers[256] = { 367static 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
433static const intercept_handler_t b9_handlers[256] = { 436static const intercept_handler_t b9_handlers[256] = {
434 [0x8d] = handle_epsw, 437 [0x8d] = handle_epsw,
438 [0x9c] = handle_io_inst,
435}; 439};
436 440
437int kvm_s390_handle_b9(struct kvm_vcpu *vcpu) 441int 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
458static const intercept_handler_t eb_handlers[256] = {
459 [0x8a] = handle_io_inst,
460};
461
462int 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
454static int handle_tprot(struct kvm_vcpu *vcpu) 476static int handle_tprot(struct kvm_vcpu *vcpu)
455{ 477{
456 u64 address1, address2; 478 u64 address1, address2;