KVM: s390: Add SIGP store-status-at-address order
authorThomas Huth <thuth@linux.vnet.ibm.com>
Wed, 13 Nov 2013 19:48:51 +0000 (20:48 +0100)
committerCornelia Huck <cornelia.huck@de.ibm.com>
Thu, 28 Nov 2013 10:08:16 +0000 (11:08 +0100)
The STORE STATUS AT ADDRESS order of SIGP was still missing.
Now it is supported, using the common kvm_s390_store_status()
function.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
arch/s390/kvm/sigp.c
arch/s390/kvm/trace.h

index 6805601262e0f97fbd7af6f8eeaa8b6cba3e1b01..c137ed35a86d05e0cedb840f0b84df554ced8716 100644 (file)
@@ -275,6 +275,37 @@ out_fi:
        return rc;
 }
 
+static int __sigp_store_status_at_addr(struct kvm_vcpu *vcpu, u16 cpu_id,
+                                       u32 addr, u64 *reg)
+{
+       struct kvm_vcpu *dst_vcpu = NULL;
+       int flags;
+       int rc;
+
+       if (cpu_id < KVM_MAX_VCPUS)
+               dst_vcpu = kvm_get_vcpu(vcpu->kvm, cpu_id);
+       if (!dst_vcpu)
+               return SIGP_CC_NOT_OPERATIONAL;
+
+       spin_lock_bh(&dst_vcpu->arch.local_int.lock);
+       flags = atomic_read(dst_vcpu->arch.local_int.cpuflags);
+       spin_unlock_bh(&dst_vcpu->arch.local_int.lock);
+       if (!(flags & CPUSTAT_STOPPED)) {
+               *reg &= 0xffffffff00000000UL;
+               *reg |= SIGP_STATUS_INCORRECT_STATE;
+               return SIGP_CC_STATUS_STORED;
+       }
+
+       addr &= 0x7ffffe00;
+       rc = kvm_s390_store_status_unloaded(dst_vcpu, addr);
+       if (rc == -EFAULT) {
+               *reg &= 0xffffffff00000000UL;
+               *reg |= SIGP_STATUS_INVALID_PARAMETER;
+               rc = SIGP_CC_STATUS_STORED;
+       }
+       return rc;
+}
+
 static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
                                u64 *reg)
 {
@@ -379,6 +410,10 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
                rc = __sigp_stop(vcpu, cpu_addr, ACTION_STORE_ON_STOP |
                                                 ACTION_STOP_ON_STOP);
                break;
+       case SIGP_STORE_STATUS_AT_ADDRESS:
+               rc = __sigp_store_status_at_addr(vcpu, cpu_addr, parameter,
+                                                &vcpu->run->s.regs.gprs[r1]);
+               break;
        case SIGP_SET_ARCHITECTURE:
                vcpu->stat.instruction_sigp_arch++;
                rc = __sigp_set_arch(vcpu, parameter);
index 0c991c6748ab3a4d860c890b7c1b1526808d4ed6..3db76b2daed7d274ba9d1110b568223ba2df8489 100644 (file)
@@ -175,6 +175,7 @@ TRACE_EVENT(kvm_s390_intercept_validity,
        {SIGP_STOP_AND_STORE_STATUS, "stop and store status"},  \
        {SIGP_SET_ARCHITECTURE, "set architecture"},            \
        {SIGP_SET_PREFIX, "set prefix"},                        \
+       {SIGP_STORE_STATUS_AT_ADDRESS, "store status at addr"}, \
        {SIGP_SENSE_RUNNING, "sense running"},                  \
        {SIGP_RESTART, "restart"}