From patchwork Fri May 29 08:21:50 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ehrhardt@linux.vnet.ibm.com X-Patchwork-Id: 26885 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n4T8MgD3016048 for ; Fri, 29 May 2009 08:22:43 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756269AbZE2IV7 (ORCPT ); Fri, 29 May 2009 04:21:59 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756265AbZE2IV6 (ORCPT ); Fri, 29 May 2009 04:21:58 -0400 Received: from mtagate3.de.ibm.com ([195.212.29.152]:56553 "EHLO mtagate3.de.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756250AbZE2IVz (ORCPT ); Fri, 29 May 2009 04:21:55 -0400 Received: from d12nrmr1607.megacenter.de.ibm.com (d12nrmr1607.megacenter.de.ibm.com [9.149.167.49]) by mtagate3.de.ibm.com (8.14.3/8.13.8) with ESMTP id n4T8Lu8h081974 for ; Fri, 29 May 2009 08:21:56 GMT Received: from d12av01.megacenter.de.ibm.com (d12av01.megacenter.de.ibm.com [9.149.165.212]) by d12nrmr1607.megacenter.de.ibm.com (8.13.8/8.13.8/NCO v9.2) with ESMTP id n4T8Lt0V3076114 for ; Fri, 29 May 2009 10:21:55 +0200 Received: from d12av01.megacenter.de.ibm.com (loopback [127.0.0.1]) by d12av01.megacenter.de.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id n4T8LsRa018604 for ; Fri, 29 May 2009 10:21:55 +0200 Received: from localhost.localdomain (dyn-9-152-212-64.boeblingen.de.ibm.com [9.152.212.64]) by d12av01.megacenter.de.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id n4T8LstO018591; Fri, 29 May 2009 10:21:54 +0200 From: ehrhardt@linux.vnet.ibm.com To: kvm@vger.kernel.org, avi@redhat.com Cc: ehrhardt@linux.vnet.ibm.com, borntraeger@de.ibm.com, cotte@de.ibm.com, heiko.carstens@de.ibm.com, schwidefsky@de.ibm.com, mtosatti@redhat.com Subject: [PATCH 1/5] kvm-s390: infrastructure to kick vcpus out of guest state - v3 Date: Fri, 29 May 2009 10:21:50 +0200 Message-Id: <1243585314-13734-2-git-send-email-ehrhardt@linux.vnet.ibm.com> X-Mailer: git-send-email 1.6.0.4 In-Reply-To: <1243585314-13734-1-git-send-email-ehrhardt@linux.vnet.ibm.com> References: <1243585314-13734-1-git-send-email-ehrhardt@linux.vnet.ibm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Christian Ehrhardt *updates in v3* - ensure allocations (might_sleep) are out of atomic context *updates in v2* instead of a "kick to level" behaviour the patch now implements a kick to the lowest level. The check there bails out to upper levels if not all outstanding vcpu->requests could be handled internally (it could still support an explicit kick to level if ever needed). To ensure vcpu's come out of guest context in certain cases this patch adds a s390 specific way to kick them out of guest context. Currently it kicks them out to rerun the vcpu_run path in the s390 code, but the mechanism itself is expandable and with a new flag we could also add e.g. kicks to userspace etc. Signed-off-by: Christian Ehrhardt --- [diffstat] include/asm/kvm_host.h | 5 ++-- kvm/intercept.c | 14 +++++++++-- kvm/kvm-s390.c | 6 ++++ kvm/kvm-s390.h | 17 ++++++++++++++ kvm/sigp.c | 59 ++++++++++++++++++++++++++++++++++--------------- 5 files changed, 79 insertions(+), 22 deletions(-) [diff] -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Index: kvm/arch/s390/kvm/intercept.c =================================================================== --- kvm.orig/arch/s390/kvm/intercept.c +++ kvm/arch/s390/kvm/intercept.c @@ -128,7 +128,7 @@ static int handle_noop(struct kvm_vcpu * static int handle_stop(struct kvm_vcpu *vcpu) { - int rc; + int rc = 0; vcpu->stat.exit_stop_request++; atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); @@ -141,12 +141,20 @@ static int handle_stop(struct kvm_vcpu * rc = -ENOTSUPP; } + if (vcpu->arch.local_int.action_bits & ACTION_VCPUREQUEST_ON_STOP) { + vcpu->arch.local_int.action_bits &= ~ACTION_VCPUREQUEST_ON_STOP; + if (kvm_s390_handle_vcpu_requests(vcpu, VCPUREQUESTLVL_SIGP)) { + rc = SIE_INTERCEPT_CHECKREQUESTS; + vcpu->run->exit_reason = KVM_EXIT_INTR; + } + } + 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; } Index: kvm/arch/s390/kvm/kvm-s390.c =================================================================== --- kvm.orig/arch/s390/kvm/kvm-s390.c +++ kvm/arch/s390/kvm/kvm-s390.c @@ -487,6 +487,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v vcpu_load(vcpu); +rerun_vcpu: + kvm_s390_handle_vcpu_requests(vcpu, VCPUREQUESTLVL_VCPURUN); + /* verify, that memory has been registered */ if (!vcpu->kvm->arch.guest_memsize) { vcpu_put(vcpu); @@ -519,6 +522,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v rc = kvm_handle_sie_intercept(vcpu); } while (!signal_pending(current) && !rc); + if (rc == SIE_INTERCEPT_CHECKREQUESTS) + goto rerun_vcpu; + if (signal_pending(current) && !rc) rc = -EINTR; Index: kvm/arch/s390/kvm/kvm-s390.h =================================================================== --- kvm.orig/arch/s390/kvm/kvm-s390.h +++ kvm/arch/s390/kvm/kvm-s390.h @@ -20,6 +20,8 @@ typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu); +/* negativ values are error codes, positive values for internal conditions */ +#define SIE_INTERCEPT_CHECKREQUESTS (1<<0) int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu); #define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\ @@ -50,6 +52,21 @@ int kvm_s390_inject_vm(struct kvm *kvm, int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, struct kvm_s390_interrupt *s390int); int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code); +int kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action); + +/* interception levels from which handle vcpu requests can be called */ +#define VCPUREQUESTLVL_SIGP 1 +#define VCPUREQUESTLVL_VCPURUN 2 +static inline unsigned long kvm_s390_handle_vcpu_requests(struct kvm_vcpu *vcpu, + int level) +{ + BUG_ON(!level); + + if (!vcpu->requests) + return 0; + + return vcpu->requests; +} /* implemented in priv.c */ int kvm_s390_handle_b2(struct kvm_vcpu *vcpu); Index: kvm/arch/s390/include/asm/kvm_host.h =================================================================== --- kvm.orig/arch/s390/include/asm/kvm_host.h +++ kvm/arch/s390/include/asm/kvm_host.h @@ -180,8 +180,9 @@ struct kvm_s390_interrupt_info { }; /* for local_interrupt.action_flags */ -#define ACTION_STORE_ON_STOP 1 -#define ACTION_STOP_ON_STOP 2 +#define ACTION_STORE_ON_STOP (1<<0) +#define ACTION_STOP_ON_STOP (1<<1) +#define ACTION_VCPUREQUEST_ON_STOP (1<<2) struct kvm_s390_local_interrupt { spinlock_t lock; Index: kvm/arch/s390/kvm/sigp.c =================================================================== --- kvm.orig/arch/s390/kvm/sigp.c +++ kvm/arch/s390/kvm/sigp.c @@ -1,7 +1,7 @@ /* * sigp.c - handlinge interprocessor communication * - * Copyright IBM Corp. 2008 + * Copyright IBM Corp. 2008,2009 * * 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) @@ -9,6 +9,7 @@ * * Author(s): Carsten Otte * Christian Borntraeger + * Christian Ehrhardt */ #include @@ -107,7 +108,22 @@ unlock: return rc; } -static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int store) +static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action, + struct kvm_s390_interrupt_info *inti) +{ + spin_lock_bh(&li->lock); + list_add_tail(&inti->list, &li->list); + atomic_set(&li->active, 1); + atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags); + li->action_bits |= action; + if (waitqueue_active(&li->wq)) + wake_up_interruptible(&li->wq); + spin_unlock_bh(&li->lock); + + return 0; /* order accepted */ +} + +static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int action) { struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; struct kvm_s390_local_interrupt *li; @@ -120,33 +136,42 @@ static int __sigp_stop(struct kvm_vcpu * inti = kzalloc(sizeof(*inti), GFP_KERNEL); if (!inti) return -ENOMEM; - inti->type = KVM_S390_SIGP_STOP; spin_lock(&fi->lock); li = fi->local_int[cpu_addr]; if (li == NULL) { rc = 3; /* not operational */ - kfree(inti); goto unlock; } - spin_lock_bh(&li->lock); - list_add_tail(&inti->list, &li->list); - atomic_set(&li->active, 1); - atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags); - if (store) - li->action_bits |= ACTION_STORE_ON_STOP; - li->action_bits |= ACTION_STOP_ON_STOP; - if (waitqueue_active(&li->wq)) - wake_up_interruptible(&li->wq); - spin_unlock_bh(&li->lock); - rc = 0; /* order accepted */ + + rc = __inject_sigp_stop(li, action, inti); + unlock: spin_unlock(&fi->lock); + if (rc) + kfree(inti); VCPU_EVENT(vcpu, 4, "sent sigp stop to cpu %x", cpu_addr); return rc; } +int kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action) +{ + struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; + struct kvm_s390_interrupt_info *inti; + int rc; + + inti = kzalloc(sizeof(*inti), GFP_KERNEL); + if (!inti) + return -ENOMEM; + inti->type = KVM_S390_SIGP_STOP; + + rc = __inject_sigp_stop(li, action, inti); + if (rc) + kfree(inti); + return rc; +} + static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter) { int rc; @@ -261,11 +286,11 @@ int kvm_s390_handle_sigp(struct kvm_vcpu break; case SIGP_STOP: vcpu->stat.instruction_sigp_stop++; - rc = __sigp_stop(vcpu, cpu_addr, 0); + rc = __sigp_stop(vcpu, cpu_addr, ACTION_STOP_ON_STOP); break; case SIGP_STOP_STORE_STATUS: vcpu->stat.instruction_sigp_stop++; - rc = __sigp_stop(vcpu, cpu_addr, 1); + rc = __sigp_stop(vcpu, cpu_addr, ACTION_STORE_ON_STOP); break; case SIGP_SET_ARCH: vcpu->stat.instruction_sigp_arch++;