summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/sigp.h1
-rw-r--r--arch/s390/kvm/sigp.c47
2 files changed, 33 insertions, 15 deletions
diff --git a/arch/s390/include/asm/sigp.h b/arch/s390/include/asm/sigp.h
index 49576115dbb7..fad4ae23ece0 100644
--- a/arch/s390/include/asm/sigp.h
+++ b/arch/s390/include/asm/sigp.h
@@ -10,6 +10,7 @@
#define SIGP_RESTART 6
#define SIGP_STOP_AND_STORE_STATUS 9
#define SIGP_INITIAL_CPU_RESET 11
+#define SIGP_CPU_RESET 12
#define SIGP_SET_PREFIX 13
#define SIGP_STORE_STATUS_AT_ADDRESS 14
#define SIGP_SET_ARCHITECTURE 18
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index 660a9459ff2a..a9e17397305e 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -284,11 +284,12 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu,
return rc;
}
-/* Test whether the destination CPU is available and not busy */
-static int sigp_check_callable(struct kvm_vcpu *vcpu, struct kvm_vcpu *dst_vcpu)
+static int __prepare_sigp_re_start(struct kvm_vcpu *vcpu,
+ struct kvm_vcpu *dst_vcpu, u8 order_code)
{
struct kvm_s390_local_interrupt *li = &dst_vcpu->arch.local_int;
- int rc = SIGP_CC_ORDER_CODE_ACCEPTED;
+ /* handle (RE)START in user space */
+ int rc = -EOPNOTSUPP;
spin_lock(&li->lock);
if (li->action_bits & ACTION_STOP_ON_STOP)
@@ -298,6 +299,20 @@ static int sigp_check_callable(struct kvm_vcpu *vcpu, struct kvm_vcpu *dst_vcpu)
return rc;
}
+static int __prepare_sigp_cpu_reset(struct kvm_vcpu *vcpu,
+ struct kvm_vcpu *dst_vcpu, u8 order_code)
+{
+ /* handle (INITIAL) CPU RESET in user space */
+ return -EOPNOTSUPP;
+}
+
+static int __prepare_sigp_unknown(struct kvm_vcpu *vcpu,
+ struct kvm_vcpu *dst_vcpu)
+{
+ /* handle unknown orders in user space */
+ return -EOPNOTSUPP;
+}
+
static int handle_sigp_dst(struct kvm_vcpu *vcpu, u8 order_code,
u16 cpu_addr, u32 parameter, u64 *status_reg)
{
@@ -350,25 +365,27 @@ static int handle_sigp_dst(struct kvm_vcpu *vcpu, u8 order_code,
rc = __sigp_sense_running(vcpu, dst_vcpu, status_reg);
break;
case SIGP_START:
- rc = sigp_check_callable(vcpu, dst_vcpu);
- if (rc == SIGP_CC_ORDER_CODE_ACCEPTED)
- rc = -EOPNOTSUPP; /* Handle START in user space */
+ rc = __prepare_sigp_re_start(vcpu, dst_vcpu, order_code);
break;
case SIGP_RESTART:
vcpu->stat.instruction_sigp_restart++;
- rc = sigp_check_callable(vcpu, dst_vcpu);
- if (rc == SIGP_CC_ORDER_CODE_ACCEPTED) {
- VCPU_EVENT(vcpu, 4,
- "sigp restart %x to handle userspace",
- cpu_addr);
- /* user space must know about restart */
- rc = -EOPNOTSUPP;
- }
+ rc = __prepare_sigp_re_start(vcpu, dst_vcpu, order_code);
+ break;
+ case SIGP_INITIAL_CPU_RESET:
+ rc = __prepare_sigp_cpu_reset(vcpu, dst_vcpu, order_code);
+ break;
+ case SIGP_CPU_RESET:
+ rc = __prepare_sigp_cpu_reset(vcpu, dst_vcpu, order_code);
break;
default:
- rc = -EOPNOTSUPP;
+ rc = __prepare_sigp_unknown(vcpu, dst_vcpu);
}
+ if (rc == -EOPNOTSUPP)
+ VCPU_EVENT(vcpu, 4,
+ "sigp order %u -> cpu %x: handled in user space",
+ order_code, dst_vcpu->vcpu_id);
+
return rc;
}