[S390] s390-kvm: leave sie context on work. Removes preemption requirement
[safe/jmp/linux-2.6] / arch / s390 / kvm / intercept.c
index 7f7347b..47a0b64 100644 (file)
@@ -95,6 +95,9 @@ static int handle_lctl(struct kvm_vcpu *vcpu)
 }
 
 static intercept_handler_t instruction_handlers[256] = {
+       [0x83] = kvm_s390_handle_diag,
+       [0xae] = kvm_s390_handle_sigp,
+       [0xb2] = kvm_s390_handle_priv,
        [0xb7] = handle_lctl,
        [0xeb] = handle_lctg,
 };
@@ -102,6 +105,9 @@ static intercept_handler_t instruction_handlers[256] = {
 static int handle_noop(struct kvm_vcpu *vcpu)
 {
        switch (vcpu->arch.sie_block->icptcode) {
+       case 0x0:
+               vcpu->stat.exit_null++;
+               break;
        case 0x10:
                vcpu->stat.exit_external_request++;
                break;
@@ -116,10 +122,27 @@ static int handle_noop(struct kvm_vcpu *vcpu)
 
 static int handle_stop(struct kvm_vcpu *vcpu)
 {
+       int rc;
+
        vcpu->stat.exit_stop_request++;
-       VCPU_EVENT(vcpu, 3, "%s", "cpu stopped");
        atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
-       return -ENOTSUPP;
+       spin_lock_bh(&vcpu->arch.local_int.lock);
+       if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) {
+               vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP;
+               rc = __kvm_s390_vcpu_store_status(vcpu,
+                                                 KVM_S390_STORE_STATUS_NOADDR);
+               if (rc >= 0)
+                       rc = -ENOTSUPP;
+       }
+
+       if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) {
+               vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP;
+               VCPU_EVENT(vcpu, 3, "%s", "cpu stopped");
+               rc = -ENOTSUPP;
+       } else
+               rc = 0;
+       spin_unlock_bh(&vcpu->arch.local_int.lock);
+       return rc;
 }
 
 static int handle_validity(struct kvm_vcpu *vcpu)