Commit f379aae5 authored by Cornelia Huck's avatar Cornelia Huck Committed by Marcelo Tosatti

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: default avatarMarcelo Tosatti <mtosatti@redhat.com>
Reviewed-by: default avatarAlexander Graf <agraf@suse.de>
Signed-off-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: default avatarMarcelo Tosatti <mtosatti@redhat.com>
parent 48a3e950
...@@ -30,8 +30,6 @@ static int handle_lctlg(struct kvm_vcpu *vcpu) ...@@ -30,8 +30,6 @@ static int handle_lctlg(struct kvm_vcpu *vcpu)
int reg, rc; int reg, rc;
vcpu->stat.instruction_lctlg++; vcpu->stat.instruction_lctlg++;
if ((vcpu->arch.sie_block->ipb & 0xff) != 0x2f)
return -EOPNOTSUPP;
useraddr = kvm_s390_get_base_disp_rsy(vcpu); useraddr = kvm_s390_get_base_disp_rsy(vcpu);
...@@ -95,6 +93,21 @@ static int handle_lctl(struct kvm_vcpu *vcpu) ...@@ -95,6 +93,21 @@ static int handle_lctl(struct kvm_vcpu *vcpu)
return 0; return 0;
} }
static const intercept_handler_t eb_handlers[256] = {
[0x2f] = handle_lctlg,
[0x8a] = kvm_s390_handle_priv_eb,
};
static int handle_eb(struct kvm_vcpu *vcpu)
{
intercept_handler_t handler;
handler = eb_handlers[vcpu->arch.sie_block->ipb & 0xff];
if (handler)
return handler(vcpu);
return -EOPNOTSUPP;
}
static const intercept_handler_t instruction_handlers[256] = { static const intercept_handler_t instruction_handlers[256] = {
[0x01] = kvm_s390_handle_01, [0x01] = kvm_s390_handle_01,
[0x82] = kvm_s390_handle_lpsw, [0x82] = kvm_s390_handle_lpsw,
...@@ -104,7 +117,7 @@ static const intercept_handler_t instruction_handlers[256] = { ...@@ -104,7 +117,7 @@ static const intercept_handler_t instruction_handlers[256] = {
[0xb7] = handle_lctl, [0xb7] = handle_lctl,
[0xb9] = kvm_s390_handle_b9, [0xb9] = kvm_s390_handle_b9,
[0xe5] = kvm_s390_handle_e5, [0xe5] = kvm_s390_handle_e5,
[0xeb] = handle_lctlg, [0xeb] = handle_eb,
}; };
static int handle_noop(struct kvm_vcpu *vcpu) static int handle_noop(struct kvm_vcpu *vcpu)
......
...@@ -120,6 +120,7 @@ int kvm_s390_handle_e5(struct kvm_vcpu *vcpu); ...@@ -120,6 +120,7 @@ int kvm_s390_handle_e5(struct kvm_vcpu *vcpu);
int kvm_s390_handle_01(struct kvm_vcpu *vcpu); int kvm_s390_handle_01(struct kvm_vcpu *vcpu);
int kvm_s390_handle_b9(struct kvm_vcpu *vcpu); int kvm_s390_handle_b9(struct kvm_vcpu *vcpu);
int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu); int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu);
int kvm_s390_handle_priv_eb(struct kvm_vcpu *vcpu);
/* implemented in sigp.c */ /* implemented in sigp.c */
int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu);
......
...@@ -127,20 +127,9 @@ static int handle_skey(struct kvm_vcpu *vcpu) ...@@ -127,20 +127,9 @@ static int handle_skey(struct kvm_vcpu *vcpu)
return 0; return 0;
} }
static int handle_stsch(struct kvm_vcpu *vcpu) static int handle_io_inst(struct kvm_vcpu *vcpu)
{ {
vcpu->stat.instruction_stsch++; VCPU_EVENT(vcpu, 4, "%s", "I/O instruction");
VCPU_EVENT(vcpu, 4, "%s", "store subchannel - CC3");
/* condition code 3 */
vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
vcpu->arch.sie_block->gpsw.mask |= (3 & 3ul) << 44;
return 0;
}
static int handle_chsc(struct kvm_vcpu *vcpu)
{
vcpu->stat.instruction_chsc++;
VCPU_EVENT(vcpu, 4, "%s", "channel subsystem call - CC3");
/* condition code 3 */ /* condition code 3 */
vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
vcpu->arch.sie_block->gpsw.mask |= (3 & 3ul) << 44; vcpu->arch.sie_block->gpsw.mask |= (3 & 3ul) << 44;
...@@ -375,7 +364,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu) ...@@ -375,7 +364,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
return 0; return 0;
} }
static const intercept_handler_t priv_handlers[256] = { static const intercept_handler_t b2_handlers[256] = {
[0x02] = handle_stidp, [0x02] = handle_stidp,
[0x10] = handle_set_prefix, [0x10] = handle_set_prefix,
[0x11] = handle_store_prefix, [0x11] = handle_store_prefix,
...@@ -383,8 +372,22 @@ static const intercept_handler_t priv_handlers[256] = { ...@@ -383,8 +372,22 @@ static const intercept_handler_t priv_handlers[256] = {
[0x29] = handle_skey, [0x29] = handle_skey,
[0x2a] = handle_skey, [0x2a] = handle_skey,
[0x2b] = handle_skey, [0x2b] = handle_skey,
[0x34] = handle_stsch, [0x30] = handle_io_inst,
[0x5f] = handle_chsc, [0x31] = handle_io_inst,
[0x32] = handle_io_inst,
[0x33] = handle_io_inst,
[0x34] = handle_io_inst,
[0x35] = handle_io_inst,
[0x36] = handle_io_inst,
[0x37] = handle_io_inst,
[0x38] = handle_io_inst,
[0x39] = handle_io_inst,
[0x3a] = handle_io_inst,
[0x3b] = handle_io_inst,
[0x3c] = handle_io_inst,
[0x5f] = handle_io_inst,
[0x74] = handle_io_inst,
[0x76] = handle_io_inst,
[0x7d] = handle_stsi, [0x7d] = handle_stsi,
[0xb1] = handle_stfl, [0xb1] = handle_stfl,
[0xb2] = handle_lpswe, [0xb2] = handle_lpswe,
...@@ -401,7 +404,7 @@ int kvm_s390_handle_b2(struct kvm_vcpu *vcpu) ...@@ -401,7 +404,7 @@ int kvm_s390_handle_b2(struct kvm_vcpu *vcpu)
* state bit and (a) handle the instruction or (b) send a code 2 * state bit and (a) handle the instruction or (b) send a code 2
* program check. * program check.
* Anything else goes to userspace.*/ * Anything else goes to userspace.*/
handler = priv_handlers[vcpu->arch.sie_block->ipa & 0x00ff]; handler = b2_handlers[vcpu->arch.sie_block->ipa & 0x00ff];
if (handler) { if (handler) {
if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
return kvm_s390_inject_program_int(vcpu, return kvm_s390_inject_program_int(vcpu,
...@@ -432,6 +435,7 @@ static int handle_epsw(struct kvm_vcpu *vcpu) ...@@ -432,6 +435,7 @@ static int handle_epsw(struct kvm_vcpu *vcpu)
static const intercept_handler_t b9_handlers[256] = { static const intercept_handler_t b9_handlers[256] = {
[0x8d] = handle_epsw, [0x8d] = handle_epsw,
[0x9c] = handle_io_inst,
}; };
int kvm_s390_handle_b9(struct kvm_vcpu *vcpu) int kvm_s390_handle_b9(struct kvm_vcpu *vcpu)
...@@ -451,6 +455,24 @@ int kvm_s390_handle_b9(struct kvm_vcpu *vcpu) ...@@ -451,6 +455,24 @@ int kvm_s390_handle_b9(struct kvm_vcpu *vcpu)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static const intercept_handler_t eb_handlers[256] = {
[0x8a] = handle_io_inst,
};
int kvm_s390_handle_priv_eb(struct kvm_vcpu *vcpu)
{
intercept_handler_t handler;
/* All eb instructions that end up here are privileged. */
if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
return kvm_s390_inject_program_int(vcpu,
PGM_PRIVILEGED_OPERATION);
handler = eb_handlers[vcpu->arch.sie_block->ipb & 0xff];
if (handler)
return handler(vcpu);
return -EOPNOTSUPP;
}
static int handle_tprot(struct kvm_vcpu *vcpu) static int handle_tprot(struct kvm_vcpu *vcpu)
{ {
u64 address1, address2; u64 address1, address2;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment