From d9101fca3d572b8675b7fe3f4ef9f6f99bbf4364 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 13 Nov 2013 11:15:02 +0100 Subject: [PATCH 1/6] KVM: s390: diagnose call documentation Add some further documentation on the DIAGNOSE calls we support. Reviewed-by: Thomas Huth Signed-off-by: Cornelia Huck --- Documentation/virtual/kvm/hypercalls.txt | 3 + Documentation/virtual/kvm/s390-diag.txt | 80 ++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 Documentation/virtual/kvm/s390-diag.txt diff --git a/Documentation/virtual/kvm/hypercalls.txt b/Documentation/virtual/kvm/hypercalls.txt index 022198e389d7..d922d73efa7b 100644 --- a/Documentation/virtual/kvm/hypercalls.txt +++ b/Documentation/virtual/kvm/hypercalls.txt @@ -17,6 +17,9 @@ S390: S390 uses diagnose instruction as hypercall (0x500) along with hypercall number in R1. + For further information on the S390 diagnose call as supported by KVM, + refer to Documentation/virtual/kvm/s390-diag.txt. + PowerPC: It uses R3-R10 and hypercall number in R11. R4-R11 are used as output registers. Return value is placed in R3. diff --git a/Documentation/virtual/kvm/s390-diag.txt b/Documentation/virtual/kvm/s390-diag.txt new file mode 100644 index 000000000000..f1de4fbade15 --- /dev/null +++ b/Documentation/virtual/kvm/s390-diag.txt @@ -0,0 +1,80 @@ +The s390 DIAGNOSE call on KVM +============================= + +KVM on s390 supports the DIAGNOSE call for making hypercalls, both for +native hypercalls and for selected hypercalls found on other s390 +hypervisors. + +Note that bits are numbered as by the usual s390 convention (most significant +bit on the left). + + +General remarks +--------------- + +DIAGNOSE calls by the guest cause a mandatory intercept. This implies +all supported DIAGNOSE calls need to be handled by either KVM or its +userspace. + +All DIAGNOSE calls supported by KVM use the RS-a format: + +-------------------------------------- +| '83' | R1 | R3 | B2 | D2 | +-------------------------------------- +0 8 12 16 20 31 + +The second-operand address (obtained by the base/displacement calculation) +is not used to address data. Instead, bits 48-63 of this address specify +the function code, and bits 0-47 are ignored. + +The supported DIAGNOSE function codes vary by the userspace used. For +DIAGNOSE function codes not specific to KVM, please refer to the +documentation for the s390 hypervisors defining them. + + +DIAGNOSE function code 'X'500' - KVM virtio functions +----------------------------------------------------- + +If the function code specifies 0x500, various virtio-related functions +are performed. + +General register 1 contains the virtio subfunction code. Supported +virtio subfunctions depend on KVM's userspace. Generally, userspace +provides either s390-virtio (subcodes 0-2) or virtio-ccw (subcode 3). + +Upon completion of the DIAGNOSE instruction, general register 2 contains +the function's return code, which is either a return code or a subcode +specific value. + +Subcode 0 - s390-virtio notification and early console printk + Handled by userspace. + +Subcode 1 - s390-virtio reset + Handled by userspace. + +Subcode 2 - s390-virtio set status + Handled by userspace. + +Subcode 3 - virtio-ccw notification + Handled by either userspace or KVM (ioeventfd case). + + General register 2 contains a subchannel-identification word denoting + the subchannel of the virtio-ccw proxy device to be notified. + + General register 3 contains the number of the virtqueue to be notified. + + General register 4 contains a 64bit identifier for KVM usage (the + kvm_io_bus cookie). If general register 4 does not contain a valid + identifier, it is ignored. + + After completion of the DIAGNOSE call, general register 2 may contain + a 64bit identifier (in the kvm_io_bus cookie case). + + See also the virtio standard for a discussion of this hypercall. + + +DIAGNOSE function code 'X'501 - KVM breakpoint +---------------------------------------------- + +If the function code specifies 0x501, breakpoint functions may be performed. +This function code is handled by userspace. From 949c007acd8b6887cf5f3ac86512a7b12fa245dc Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 26 Nov 2013 12:27:16 +0100 Subject: [PATCH 2/6] KVM: s390: Use helper function to set CC in SIGP handler We've got a helper function for setting the condition code now, so let's use it in the SIGP handler, too. Signed-off-by: Thomas Huth Reviewed-by: Cornelia Huck Signed-off-by: Cornelia Huck --- arch/s390/kvm/sigp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index c3700585b4bb..bc0d85a24b1b 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -435,7 +435,6 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) if (rc < 0) return rc; - vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); - vcpu->arch.sie_block->gpsw.mask |= (rc & 3ul) << 44; + kvm_s390_set_psw_cc(vcpu, rc); return 0; } From b13d3580ee47ba3b2814e90b8a9b8241f7a4ba83 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 21 Nov 2013 16:01:48 +0100 Subject: [PATCH 3/6] KVM: s390: Add the SIGP order CONDITIONAL EMERGENCY SIGNAL This patch adds the missing SIGP order "conditional emergency signal" by calling the "emergency signal" SIGP handler if the required conditions are met. Signed-off-by: Thomas Huth Reviewed-by: Cornelia Huck Signed-off-by: Cornelia Huck --- arch/s390/include/asm/sigp.h | 1 + arch/s390/kvm/sigp.c | 37 +++++++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/arch/s390/include/asm/sigp.h b/arch/s390/include/asm/sigp.h index 5a87d16d3e7c..c002cd529c71 100644 --- a/arch/s390/include/asm/sigp.h +++ b/arch/s390/include/asm/sigp.h @@ -12,6 +12,7 @@ #define SIGP_SET_PREFIX 13 #define SIGP_STORE_STATUS_AT_ADDRESS 14 #define SIGP_SET_ARCHITECTURE 18 +#define SIGP_COND_EMERGENCY_SIGNAL 19 #define SIGP_SENSE_RUNNING 21 /* SIGP condition codes */ diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index bc0d85a24b1b..eee1402349f2 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -1,7 +1,7 @@ /* * handling interprocessor communication * - * Copyright IBM Corp. 2008, 2009 + * Copyright IBM Corp. 2008, 2013 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License (version 2 only) @@ -89,6 +89,37 @@ unlock: return rc; } +static int __sigp_conditional_emergency(struct kvm_vcpu *vcpu, u16 cpu_addr, + u16 asn, u64 *reg) +{ + struct kvm_vcpu *dst_vcpu = NULL; + const u64 psw_int_mask = PSW_MASK_IO | PSW_MASK_EXT; + u16 p_asn, s_asn; + psw_t *psw; + u32 flags; + + if (cpu_addr < KVM_MAX_VCPUS) + dst_vcpu = kvm_get_vcpu(vcpu->kvm, cpu_addr); + if (!dst_vcpu) + return SIGP_CC_NOT_OPERATIONAL; + flags = atomic_read(&dst_vcpu->arch.sie_block->cpuflags); + psw = &dst_vcpu->arch.sie_block->gpsw; + p_asn = dst_vcpu->arch.sie_block->gcr[4] & 0xffff; /* Primary ASN */ + s_asn = dst_vcpu->arch.sie_block->gcr[3] & 0xffff; /* Secondary ASN */ + + /* Deliver the emergency signal? */ + if (!(flags & CPUSTAT_STOPPED) + || (psw->mask & psw_int_mask) != psw_int_mask + || ((flags & CPUSTAT_WAIT) && psw->addr != 0) + || (!(flags & CPUSTAT_WAIT) && (asn == p_asn || asn == s_asn))) { + return __sigp_emergency(vcpu, cpu_addr); + } else { + *reg &= 0xffffffff00000000UL; + *reg |= SIGP_STATUS_INCORRECT_STATE; + return SIGP_CC_STATUS_STORED; + } +} + static int __sigp_external_call(struct kvm_vcpu *vcpu, u16 cpu_addr) { struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; @@ -417,6 +448,10 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) rc = __sigp_set_prefix(vcpu, cpu_addr, parameter, &vcpu->run->s.regs.gprs[r1]); break; + case SIGP_COND_EMERGENCY_SIGNAL: + rc = __sigp_conditional_emergency(vcpu, cpu_addr, parameter, + &vcpu->run->s.regs.gprs[r1]); + break; case SIGP_SENSE_RUNNING: vcpu->stat.instruction_sigp_sense_running++; rc = __sigp_sense_running(vcpu, cpu_addr, From cc92d6dea11cd43842e20cd05c066963de586417 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 27 Nov 2013 11:47:10 +0100 Subject: [PATCH 4/6] KVM: s390: Reworked SIGP RESTART order When SIGP RESTART detected an illegal CPU address, there is no need to drop to userspace, we can return CC3 to the guest directly instead. Also renamed __sigp_restart() to sigp_check_callable() (since this is a better description of what the function is really doing) and moved a string specific to RESTART to the calling place instead, so that this function gets usable by other SIGP orders, too. Signed-off-by: Thomas Huth Reviewed-by: Cornelia Huck Signed-off-by: Cornelia Huck --- arch/s390/kvm/sigp.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index eee1402349f2..509547d4fca1 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -363,7 +363,8 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr, return rc; } -static int __sigp_restart(struct kvm_vcpu *vcpu, u16 cpu_addr) +/* Test whether the destination CPU is available and not busy */ +static int sigp_check_callable(struct kvm_vcpu *vcpu, u16 cpu_addr) { struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; struct kvm_s390_local_interrupt *li; @@ -382,9 +383,6 @@ static int __sigp_restart(struct kvm_vcpu *vcpu, u16 cpu_addr) spin_lock_bh(&li->lock); if (li->action_bits & ACTION_STOP_ON_STOP) rc = SIGP_CC_BUSY; - else - VCPU_EVENT(vcpu, 4, "sigp restart %x to handle userspace", - cpu_addr); spin_unlock_bh(&li->lock); out: spin_unlock(&fi->lock); @@ -459,10 +457,15 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) break; case SIGP_RESTART: vcpu->stat.instruction_sigp_restart++; - rc = __sigp_restart(vcpu, cpu_addr); - if (rc == SIGP_CC_BUSY) - break; - /* user space must know about restart */ + rc = sigp_check_callable(vcpu, cpu_addr); + 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; + } + break; default: return -EOPNOTSUPP; } From 58bc33b2b700f8524772f3fc20272da2187060c8 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 3 Dec 2013 12:54:55 +0100 Subject: [PATCH 5/6] KVM: s390: SIGP START has to report BUSY while stopping a CPU Just like the RESTART order, the START order also has to report BUSY while a STOP request is pending, to avoid that the START might be ignored due to a race condition between the STOP and the START order. Signed-off-by: Thomas Huth Reviewed-by: Cornelia Huck Signed-off-by: Cornelia Huck --- arch/s390/include/asm/sigp.h | 1 + arch/s390/kvm/sigp.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/arch/s390/include/asm/sigp.h b/arch/s390/include/asm/sigp.h index c002cd529c71..d091aa1aaf11 100644 --- a/arch/s390/include/asm/sigp.h +++ b/arch/s390/include/asm/sigp.h @@ -5,6 +5,7 @@ #define SIGP_SENSE 1 #define SIGP_EXTERNAL_CALL 2 #define SIGP_EMERGENCY_SIGNAL 3 +#define SIGP_START 4 #define SIGP_STOP 5 #define SIGP_RESTART 6 #define SIGP_STOP_AND_STORE_STATUS 9 diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index 509547d4fca1..87c2b3a3bd3e 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -455,6 +455,11 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) rc = __sigp_sense_running(vcpu, cpu_addr, &vcpu->run->s.regs.gprs[r1]); break; + case SIGP_START: + rc = sigp_check_callable(vcpu, cpu_addr); + if (rc == SIGP_CC_ORDER_CODE_ACCEPTED) + rc = -EOPNOTSUPP; /* Handle START in user space */ + break; case SIGP_RESTART: vcpu->stat.instruction_sigp_restart++; rc = sigp_check_callable(vcpu, cpu_addr); From ff1f3cb4b3ac5d039f02679f34cb1498d110d241 Mon Sep 17 00:00:00 2001 From: Dominik Dingel Date: Mon, 9 Dec 2013 18:30:01 +0100 Subject: [PATCH 6/6] KVM: s390: ioeventfd: ignore leftmost bits The diagnose 500 subcode 3 contains the 32 bit subchannel id in bits 32-63 (counting from the left). As for other I/O instructions, bits 0-31 should be ignored and thus not be passed to kvm_io_bus_write_cookie(). This fixes a bug where the guest passed non-zero bits 0-31 which the host tried to interpret, leading to ioeventfd notification failures. Cc: stable@vger.kernel.org Signed-off-by: Dominik Dingel Reviewed-by: Cornelia Huck Signed-off-by: Cornelia Huck --- arch/s390/kvm/diag.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c index 5ff29be7d87a..8216c0e0b2e2 100644 --- a/arch/s390/kvm/diag.c +++ b/arch/s390/kvm/diag.c @@ -121,7 +121,7 @@ static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu) * - gpr 4 contains the index on the bus (optionally) */ ret = kvm_io_bus_write_cookie(vcpu->kvm, KVM_VIRTIO_CCW_NOTIFY_BUS, - vcpu->run->s.regs.gprs[2], + vcpu->run->s.regs.gprs[2] & 0xffffffff, 8, &vcpu->run->s.regs.gprs[3], vcpu->run->s.regs.gprs[4]);