From patchwork Fri Jul 26 16:47:58 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Freimann X-Patchwork-Id: 262214 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 59F4B2C00D6 for ; Sat, 27 Jul 2013 02:49:09 +1000 (EST) Received: from localhost ([::1]:57865 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V2lCV-00033B-Fw for incoming@patchwork.ozlabs.org; Fri, 26 Jul 2013 12:49:07 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50831) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V2lBt-0002t0-SQ for qemu-devel@nongnu.org; Fri, 26 Jul 2013 12:48:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1V2lBq-0006PK-Tp for qemu-devel@nongnu.org; Fri, 26 Jul 2013 12:48:29 -0400 Received: from e06smtp11.uk.ibm.com ([195.75.94.107]:52899) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V2lBq-0006P3-FL for qemu-devel@nongnu.org; Fri, 26 Jul 2013 12:48:26 -0400 Received: from /spool/local by e06smtp11.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 26 Jul 2013 17:42:21 +0100 Received: from d06dlp02.portsmouth.uk.ibm.com (9.149.20.14) by e06smtp11.uk.ibm.com (192.168.101.141) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 26 Jul 2013 17:42:19 +0100 Received: from b06cxnps4076.portsmouth.uk.ibm.com (d06relay13.portsmouth.uk.ibm.com [9.149.109.198]) by d06dlp02.portsmouth.uk.ibm.com (Postfix) with ESMTP id 36A9B2190019 for ; Fri, 26 Jul 2013 17:52:34 +0100 (BST) Received: from d06av06.portsmouth.uk.ibm.com (d06av06.portsmouth.uk.ibm.com [9.149.37.217]) by b06cxnps4076.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id r6QGmBRW63897710 for ; Fri, 26 Jul 2013 16:48:11 GMT Received: from d06av06.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av06.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id r6QGmMrW015515 for ; Fri, 26 Jul 2013 10:48:22 -0600 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d06av06.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id r6QGmMtr015510; Fri, 26 Jul 2013 10:48:22 -0600 Received: by tuxmaker.boeblingen.de.ibm.com (Postfix, from userid 1122) id 471271224439; Fri, 26 Jul 2013 18:48:22 +0200 (CEST) From: Jens Freimann To: Christian Borntraeger , Cornelia Huck Date: Fri, 26 Jul 2013 18:47:58 +0200 Message-Id: <1374857279-28248-2-git-send-email-jfrei@linux.vnet.ibm.com> X-Mailer: git-send-email 1.8.2.3 In-Reply-To: <1374857279-28248-1-git-send-email-jfrei@linux.vnet.ibm.com> References: <1374857279-28248-1-git-send-email-jfrei@linux.vnet.ibm.com> X-TM-AS-MML: No X-Content-Scanned: Fidelis XPS MAILER x-cbid: 13072616-5024-0000-0000-000006B46DF8 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4.x-2.6.x [generic] X-Received-From: 195.75.94.107 Cc: Dominik Dingel , Jens Freimann , qemu-devel@nongnu.org, kvm@vger.kernel.org, Alexander Graf Subject: [Qemu-devel] [RFC 1/2] KVM: s390: add and extend interrupt information data structs X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org With the currently available struct kvm_s390_interrupt it is not possible to inject all kinds of interrupts as defined in the z/Architecture. Add interruption parameters to the structures to make sure we can inject all kinds of interrupts and move it to kvm.h Signed-off-by: Jens Freimann --- arch/s390/include/asm/kvm_host.h | 45 +--------- arch/s390/kvm/interrupt.c | 189 +++++++++++++++++++-------------------- arch/s390/kvm/priv.c | 22 ++--- arch/s390/kvm/sigp.c | 14 +-- include/uapi/linux/kvm.h | 62 +++++++++++++ 5 files changed, 175 insertions(+), 157 deletions(-) diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 3238d40..c755a9d 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -162,18 +163,6 @@ struct kvm_vcpu_stat { u32 diagnose_9c; }; -struct kvm_s390_io_info { - __u16 subchannel_id; /* 0x0b8 */ - __u16 subchannel_nr; /* 0x0ba */ - __u32 io_int_parm; /* 0x0bc */ - __u32 io_int_word; /* 0x0c0 */ -}; - -struct kvm_s390_ext_info { - __u32 ext_params; - __u64 ext_params2; -}; - #define PGM_OPERATION 0x01 #define PGM_PRIVILEGED_OP 0x02 #define PGM_EXECUTE 0x03 @@ -182,39 +171,9 @@ struct kvm_s390_ext_info { #define PGM_SPECIFICATION 0x06 #define PGM_DATA 0x07 -struct kvm_s390_pgm_info { - __u16 code; -}; - -struct kvm_s390_prefix_info { - __u32 address; -}; - -struct kvm_s390_extcall_info { - __u16 code; -}; - -struct kvm_s390_emerg_info { - __u16 code; -}; - -struct kvm_s390_mchk_info { - __u64 cr14; - __u64 mcic; -}; - struct kvm_s390_interrupt_info { struct list_head list; - u64 type; - union { - struct kvm_s390_io_info io; - struct kvm_s390_ext_info ext; - struct kvm_s390_pgm_info pgm; - struct kvm_s390_emerg_info emerg; - struct kvm_s390_extcall_info extcall; - struct kvm_s390_prefix_info prefix; - struct kvm_s390_mchk_info mchk; - }; + struct kvm_s390_irq irq; }; /* for local_interrupt.action_flags */ diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 7f35cb3..25cf71d 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -65,7 +65,7 @@ static u64 int_word_to_isc_bits(u32 int_word) static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu, struct kvm_s390_interrupt_info *inti) { - switch (inti->type) { + switch (inti->irq.type) { case KVM_S390_INT_EXTERNAL_CALL: if (psw_extint_disabled(vcpu)) return 0; @@ -97,19 +97,19 @@ static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu, case KVM_S390_MCHK: if (psw_mchk_disabled(vcpu)) return 0; - if (vcpu->arch.sie_block->gcr[14] & inti->mchk.cr14) + if (vcpu->arch.sie_block->gcr[14] & inti->irq.mchk.cr14) return 1; return 0; case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: if (psw_ioint_disabled(vcpu)) return 0; if (vcpu->arch.sie_block->gcr[6] & - int_word_to_isc_bits(inti->io.io_int_word)) + int_word_to_isc_bits(inti->irq.io.io_int_word)) return 1; return 0; default: printk(KERN_WARNING "illegal interrupt type %llx\n", - inti->type); + inti->irq.type); BUG(); } return 0; @@ -146,7 +146,7 @@ static void __set_cpuflag(struct kvm_vcpu *vcpu, u32 flag) static void __set_intercept_indicator(struct kvm_vcpu *vcpu, struct kvm_s390_interrupt_info *inti) { - switch (inti->type) { + switch (inti->irq.type) { case KVM_S390_INT_EXTERNAL_CALL: case KVM_S390_INT_EMERGENCY: case KVM_S390_INT_SERVICE: @@ -182,14 +182,14 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu, const unsigned short table[] = { 2, 4, 4, 6 }; int rc = 0; - switch (inti->type) { + switch (inti->irq.type) { case KVM_S390_INT_EMERGENCY: VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp emerg"); vcpu->stat.deliver_emergency_signal++; - trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, - inti->emerg.code, 0); + trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type, + inti->irq.emerg.code, 0); rc = put_guest(vcpu, 0x1201, (u16 __user *)__LC_EXT_INT_CODE); - rc |= put_guest(vcpu, inti->emerg.code, + rc |= put_guest(vcpu, inti->irq.emerg.code, (u16 __user *)__LC_EXT_CPU_ADDR); rc |= copy_to_guest(vcpu, __LC_EXT_OLD_PSW, &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); @@ -199,10 +199,10 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu, case KVM_S390_INT_EXTERNAL_CALL: VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call"); vcpu->stat.deliver_external_call++; - trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, - inti->extcall.code, 0); + trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type, + inti->irq.extcall.code, 0); rc = put_guest(vcpu, 0x1202, (u16 __user *)__LC_EXT_INT_CODE); - rc |= put_guest(vcpu, inti->extcall.code, + rc |= put_guest(vcpu, inti->irq.extcall.code, (u16 __user *)__LC_EXT_CPU_ADDR); rc |= copy_to_guest(vcpu, __LC_EXT_OLD_PSW, &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); @@ -211,57 +211,57 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu, break; case KVM_S390_INT_SERVICE: VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x", - inti->ext.ext_params); + inti->irq.ext.ext_params); vcpu->stat.deliver_service_signal++; - trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, - inti->ext.ext_params, 0); + trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type, + inti->irq.ext.ext_params, 0); rc = put_guest(vcpu, 0x2401, (u16 __user *)__LC_EXT_INT_CODE); rc |= copy_to_guest(vcpu, __LC_EXT_OLD_PSW, &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw, __LC_EXT_NEW_PSW, sizeof(psw_t)); - rc |= put_guest(vcpu, inti->ext.ext_params, + rc |= put_guest(vcpu, inti->irq.ext.ext_params, (u32 __user *)__LC_EXT_PARAMS); break; case KVM_S390_INT_VIRTIO: VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx", - inti->ext.ext_params, inti->ext.ext_params2); + inti->irq.ext.ext_params, inti->irq.ext.ext_params2); vcpu->stat.deliver_virtio_interrupt++; - trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, - inti->ext.ext_params, - inti->ext.ext_params2); + trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type, + inti->irq.ext.ext_params, + inti->irq.ext.ext_params2); rc = put_guest(vcpu, 0x2603, (u16 __user *)__LC_EXT_INT_CODE); rc |= put_guest(vcpu, 0x0d00, (u16 __user *)__LC_EXT_CPU_ADDR); rc |= copy_to_guest(vcpu, __LC_EXT_OLD_PSW, &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw, __LC_EXT_NEW_PSW, sizeof(psw_t)); - rc |= put_guest(vcpu, inti->ext.ext_params, + rc |= put_guest(vcpu, inti->irq.ext.ext_params, (u32 __user *)__LC_EXT_PARAMS); - rc |= put_guest(vcpu, inti->ext.ext_params2, + rc |= put_guest(vcpu, inti->irq.ext.ext_params2, (u64 __user *)__LC_EXT_PARAMS2); break; case KVM_S390_SIGP_STOP: VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu stop"); vcpu->stat.deliver_stop_signal++; - trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, + trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type, 0, 0); __set_intercept_indicator(vcpu, inti); break; case KVM_S390_SIGP_SET_PREFIX: VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x", - inti->prefix.address); + inti->irq.prefix.address); vcpu->stat.deliver_prefix_signal++; - trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, - inti->prefix.address, 0); - kvm_s390_set_prefix(vcpu, inti->prefix.address); + trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type, + inti->irq.prefix.address, 0); + kvm_s390_set_prefix(vcpu, inti->irq.prefix.address); break; case KVM_S390_RESTART: VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu restart"); vcpu->stat.deliver_restart_signal++; - trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, + trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type, 0, 0); rc = copy_to_guest(vcpu, offsetof(struct _lowcore, restart_old_psw), @@ -273,12 +273,12 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu, break; case KVM_S390_PROGRAM_INT: VCPU_EVENT(vcpu, 4, "interrupt: pgm check code:%x, ilc:%x", - inti->pgm.code, + inti->irq.pgm.code, table[vcpu->arch.sie_block->ipa >> 14]); vcpu->stat.deliver_program_int++; - trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, - inti->pgm.code, 0); - rc = put_guest(vcpu, inti->pgm.code, (u16 __user *)__LC_PGM_INT_CODE); + trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type, + inti->irq.pgm.code, 0); + rc = put_guest(vcpu, inti->irq.pgm.code, (u16 __user *)__LC_PGM_INT_CODE); rc |= put_guest(vcpu, table[vcpu->arch.sie_block->ipa >> 14], (u16 __user *)__LC_PGM_ILC); rc |= copy_to_guest(vcpu, __LC_PGM_OLD_PSW, @@ -289,13 +289,13 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu, case KVM_S390_MCHK: VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx", - inti->mchk.mcic); - trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, - inti->mchk.cr14, - inti->mchk.mcic); + inti->irq.mchk.mcic); + trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type, + inti->irq.mchk.cr14, + inti->irq.mchk.mcic); rc = kvm_s390_vcpu_store_status(vcpu, KVM_S390_STORE_STATUS_PREFIXED); - rc |= put_guest(vcpu, inti->mchk.mcic, (u64 __user *) __LC_MCCK_CODE); + rc |= put_guest(vcpu, inti->irq.mchk.mcic, (u64 __user *) __LC_MCCK_CODE); rc |= copy_to_guest(vcpu, __LC_MCK_OLD_PSW, &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw, @@ -304,21 +304,21 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu, case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: { - __u32 param0 = ((__u32)inti->io.subchannel_id << 16) | - inti->io.subchannel_nr; - __u64 param1 = ((__u64)inti->io.io_int_parm << 32) | - inti->io.io_int_word; - VCPU_EVENT(vcpu, 4, "interrupt: I/O %llx", inti->type); + __u32 param0 = ((__u32)inti->irq.io.subchannel_id << 16) | + inti->irq.io.subchannel_nr; + __u64 param1 = ((__u64)inti->irq.io.io_int_parm << 32) | + inti->irq.io.io_int_word; + VCPU_EVENT(vcpu, 4, "interrupt: I/O %llx", inti->irq.type); vcpu->stat.deliver_io_int++; - trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, + trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type, param0, param1); - rc = put_guest(vcpu, inti->io.subchannel_id, + rc = put_guest(vcpu, inti->irq.io.subchannel_id, (u16 __user *) __LC_SUBCHANNEL_ID); - rc |= put_guest(vcpu, inti->io.subchannel_nr, + rc |= put_guest(vcpu, inti->irq.io.subchannel_nr, (u16 __user *) __LC_SUBCHANNEL_NR); - rc |= put_guest(vcpu, inti->io.io_int_parm, + rc |= put_guest(vcpu, inti->irq.io.io_int_parm, (u32 __user *) __LC_IO_INT_PARM); - rc |= put_guest(vcpu, inti->io.io_int_word, + rc |= put_guest(vcpu, inti->irq.io.io_int_word, (u32 __user *) __LC_IO_INT_WORD); rc |= copy_to_guest(vcpu, __LC_IO_OLD_PSW, &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); @@ -554,7 +554,7 @@ void kvm_s390_deliver_pending_machine_checks(struct kvm_vcpu *vcpu) deliver = 0; spin_lock_bh(&li->lock); list_for_each_entry_safe(inti, n, &li->list, list) { - if ((inti->type == KVM_S390_MCHK) && + if ((inti->irq.type == KVM_S390_MCHK) && __interrupt_is_deliverable(vcpu, inti)) { list_del(&inti->list); deliver = 1; @@ -577,7 +577,7 @@ void kvm_s390_deliver_pending_machine_checks(struct kvm_vcpu *vcpu) deliver = 0; spin_lock(&fi->lock); list_for_each_entry_safe(inti, n, &fi->list, list) { - if ((inti->type == KVM_S390_MCHK) && + if ((inti->irq.type == KVM_S390_MCHK) && __interrupt_is_deliverable(vcpu, inti)) { list_del(&inti->list); deliver = 1; @@ -605,11 +605,11 @@ int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code) if (!inti) return -ENOMEM; - inti->type = KVM_S390_PROGRAM_INT; - inti->pgm.code = code; + inti->irq.type = KVM_S390_PROGRAM_INT; + inti->irq.pgm.code = code; VCPU_EVENT(vcpu, 3, "inject: program check %d (from kernel)", code); - trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, inti->type, code, 0, 1); + trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, inti->irq.type, code, 0, 1); spin_lock_bh(&li->lock); list_add(&inti->list, &li->list); atomic_set(&li->active, 1); @@ -631,17 +631,17 @@ struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, spin_lock(&fi->lock); inti = NULL; list_for_each_entry(iter, &fi->list, list) { - if (!is_ioint(iter->type)) + if (!is_ioint(iter->irq.type)) continue; if (cr6 && - ((cr6 & int_word_to_isc_bits(iter->io.io_int_word)) == 0)) + ((cr6 & int_word_to_isc_bits(iter->irq.io.io_int_word)) == 0)) continue; if (schid) { if (((schid & 0x00000000ffff0000) >> 16) != - iter->io.subchannel_id) + iter->irq.io.subchannel_id) continue; if ((schid & 0x000000000000ffff) != - iter->io.subchannel_nr) + iter->irq.io.subchannel_nr) continue; } inti = iter; @@ -662,72 +662,69 @@ int kvm_s390_inject_vm(struct kvm *kvm, struct kvm_s390_local_interrupt *li; struct kvm_s390_float_interrupt *fi; struct kvm_s390_interrupt_info *inti, *iter; + struct kvm_s390_irq *irq; int sigcpu; inti = kzalloc(sizeof(*inti), GFP_KERNEL); if (!inti) return -ENOMEM; - switch (s390int->type) { + irq = &inti->irq; + + irq->type = s390int->type; + switch (irq->type) { case KVM_S390_INT_VIRTIO: VM_EVENT(kvm, 5, "inject: virtio parm:%x,parm64:%llx", s390int->parm, s390int->parm64); - inti->type = s390int->type; - inti->ext.ext_params = s390int->parm; - inti->ext.ext_params2 = s390int->parm64; + irq->ext.ext_params = s390int->parm; + irq->ext.ext_params2 = s390int->parm64; break; case KVM_S390_INT_SERVICE: VM_EVENT(kvm, 5, "inject: sclp parm:%x", s390int->parm); - inti->type = s390int->type; - inti->ext.ext_params = s390int->parm; + irq->ext.ext_params = s390int->parm; break; - case KVM_S390_PROGRAM_INT: - case KVM_S390_SIGP_STOP: - case KVM_S390_INT_EXTERNAL_CALL: - case KVM_S390_INT_EMERGENCY: - kfree(inti); - return -EINVAL; case KVM_S390_MCHK: VM_EVENT(kvm, 5, "inject: machine check parm64:%llx", s390int->parm64); - inti->type = s390int->type; - inti->mchk.cr14 = s390int->parm; /* upper bits are not used */ - inti->mchk.mcic = s390int->parm64; + irq->mchk.cr14 = s390int->parm; /* upper bits are not used */ + irq->mchk.mcic = s390int->parm64; break; case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: - if (s390int->type & IOINT_AI_MASK) + if (irq->type & IOINT_AI_MASK) VM_EVENT(kvm, 5, "%s", "inject: I/O (AI)"); else VM_EVENT(kvm, 5, "inject: I/O css %x ss %x schid %04x", s390int->type & IOINT_CSSID_MASK, s390int->type & IOINT_SSID_MASK, s390int->type & IOINT_SCHID_MASK); - inti->type = s390int->type; - inti->io.subchannel_id = s390int->parm >> 16; - inti->io.subchannel_nr = s390int->parm & 0x0000ffffu; - inti->io.io_int_parm = s390int->parm64 >> 32; - inti->io.io_int_word = s390int->parm64 & 0x00000000ffffffffull; + irq->io.subchannel_id = s390int->parm >> 16; + irq->io.subchannel_nr = s390int->parm & 0x0000ffffu; + irq->io.io_int_parm = s390int->parm64 >> 32; + irq->io.io_int_word = s390int->parm64 & 0x00000000ffffffffull; break; + case KVM_S390_PROGRAM_INT: + case KVM_S390_SIGP_STOP: + case KVM_S390_INT_EXTERNAL_CALL: + case KVM_S390_INT_EMERGENCY: default: kfree(inti); return -EINVAL; } - trace_kvm_s390_inject_vm(s390int->type, s390int->parm, s390int->parm64, - 2); + trace_kvm_s390_inject_vm(s390int->type, s390int->parm, s390int->parm64, 2); mutex_lock(&kvm->lock); fi = &kvm->arch.float_int; spin_lock(&fi->lock); - if (!is_ioint(inti->type)) + if (!is_ioint(inti->irq.type)) list_add_tail(&inti->list, &fi->list); else { - u64 isc_bits = int_word_to_isc_bits(inti->io.io_int_word); + u64 isc_bits = int_word_to_isc_bits(inti->irq.io.io_int_word); /* Keep I/O interrupts sorted in isc order. */ list_for_each_entry(iter, &fi->list, list) { - if (!is_ioint(iter->type)) + if (!is_ioint(iter->irq.type)) continue; - if (int_word_to_isc_bits(iter->io.io_int_word) + if (int_word_to_isc_bits(iter->irq.io.io_int_word) <= isc_bits) continue; break; @@ -770,21 +767,21 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, kfree(inti); return -EINVAL; } - inti->type = s390int->type; - inti->pgm.code = s390int->parm; + inti->irq.type = s390int->type; + inti->irq.pgm.code = s390int->parm; VCPU_EVENT(vcpu, 3, "inject: program check %d (from user)", s390int->parm); break; case KVM_S390_SIGP_SET_PREFIX: - inti->prefix.address = s390int->parm; - inti->type = s390int->type; + inti->irq.prefix.address = s390int->parm; + inti->irq.type = s390int->type; VCPU_EVENT(vcpu, 3, "inject: set prefix to %x (from user)", s390int->parm); break; case KVM_S390_SIGP_STOP: case KVM_S390_RESTART: VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type); - inti->type = s390int->type; + inti->irq.type = s390int->type; break; case KVM_S390_INT_EXTERNAL_CALL: if (s390int->parm & 0xffff0000) { @@ -793,8 +790,8 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, } VCPU_EVENT(vcpu, 3, "inject: external call source-cpu:%u", s390int->parm); - inti->type = s390int->type; - inti->extcall.code = s390int->parm; + inti->irq.type = s390int->type; + inti->irq.extcall.code = s390int->parm; break; case KVM_S390_INT_EMERGENCY: if (s390int->parm & 0xffff0000) { @@ -802,14 +799,14 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, return -EINVAL; } VCPU_EVENT(vcpu, 3, "inject: emergency %u\n", s390int->parm); - inti->type = s390int->type; - inti->emerg.code = s390int->parm; + inti->irq.type = s390int->type; + inti->irq.emerg.code = s390int->parm; break; case KVM_S390_MCHK: VCPU_EVENT(vcpu, 5, "inject: machine check parm64:%llx", s390int->parm64); - inti->type = s390int->type; - inti->mchk.mcic = s390int->parm64; + inti->irq.type = s390int->type; + inti->irq.mchk.mcic = s390int->parm64; break; case KVM_S390_INT_VIRTIO: case KVM_S390_INT_SERVICE: @@ -824,12 +821,12 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, mutex_lock(&vcpu->kvm->lock); li = &vcpu->arch.local_int; spin_lock_bh(&li->lock); - if (inti->type == KVM_S390_PROGRAM_INT) + if (inti->irq.type == KVM_S390_PROGRAM_INT) list_add(&inti->list, &li->list); else list_add_tail(&inti->list, &li->list); atomic_set(&li->active, 1); - if (inti->type == KVM_S390_SIGP_STOP) + if (inti->irq.type == KVM_S390_SIGP_STOP) li->action_bits |= ACTION_STOP_ON_STOP; atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); if (waitqueue_active(&vcpu->wq)) diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 0da3e6e..897fff2 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c @@ -146,19 +146,19 @@ static int handle_tpi(struct kvm_vcpu *vcpu) * Store the two-word I/O interruption code into the * provided area. */ - if (put_guest(vcpu, inti->io.subchannel_id, (u16 __user *)addr) - || put_guest(vcpu, inti->io.subchannel_nr, (u16 __user *)(addr + 2)) - || put_guest(vcpu, inti->io.io_int_parm, (u32 __user *)(addr + 4))) + if (put_guest(vcpu, inti->irq.io.subchannel_id, (u16 __user *)addr) + || put_guest(vcpu, inti->irq.io.subchannel_nr, (u16 __user *)(addr + 2)) + || put_guest(vcpu, inti->irq.io.io_int_parm, (u32 __user *)(addr + 4))) return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); } else { /* * Store the three-word I/O interruption code into * the appropriate lowcore area. */ - put_guest(vcpu, inti->io.subchannel_id, (u16 __user *) __LC_SUBCHANNEL_ID); - put_guest(vcpu, inti->io.subchannel_nr, (u16 __user *) __LC_SUBCHANNEL_NR); - put_guest(vcpu, inti->io.io_int_parm, (u32 __user *) __LC_IO_INT_PARM); - put_guest(vcpu, inti->io.io_int_word, (u32 __user *) __LC_IO_INT_WORD); + put_guest(vcpu, inti->irq.io.subchannel_id, (u16 __user *) __LC_SUBCHANNEL_ID); + put_guest(vcpu, inti->irq.io.subchannel_nr, (u16 __user *) __LC_SUBCHANNEL_NR); + put_guest(vcpu, inti->irq.io.io_int_parm, (u32 __user *) __LC_IO_INT_PARM); + put_guest(vcpu, inti->irq.io.io_int_word, (u32 __user *) __LC_IO_INT_WORD); } kfree(inti); no_interrupt: @@ -186,10 +186,10 @@ static int handle_tsch(struct kvm_vcpu *vcpu) vcpu->run->exit_reason = KVM_EXIT_S390_TSCH; vcpu->run->s390_tsch.dequeued = !!inti; if (inti) { - vcpu->run->s390_tsch.subchannel_id = inti->io.subchannel_id; - vcpu->run->s390_tsch.subchannel_nr = inti->io.subchannel_nr; - vcpu->run->s390_tsch.io_int_parm = inti->io.io_int_parm; - vcpu->run->s390_tsch.io_int_word = inti->io.io_int_word; + vcpu->run->s390_tsch.subchannel_id = inti->irq.io.subchannel_id; + vcpu->run->s390_tsch.subchannel_nr = inti->irq.io.subchannel_nr; + vcpu->run->s390_tsch.io_int_parm = inti->irq.io.io_int_parm; + vcpu->run->s390_tsch.io_int_word = inti->irq.io.io_int_word; } vcpu->run->s390_tsch.ipb = vcpu->arch.sie_block->ipb; kfree(inti); diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index bec398c..a8cd912 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -65,8 +65,8 @@ static int __sigp_emergency(struct kvm_vcpu *vcpu, u16 cpu_addr) if (!inti) return -ENOMEM; - inti->type = KVM_S390_INT_EMERGENCY; - inti->emerg.code = vcpu->vcpu_id; + inti->irq.type = KVM_S390_INT_EMERGENCY; + inti->irq.emerg.code = vcpu->vcpu_id; spin_lock(&fi->lock); li = fi->local_int[cpu_addr]; @@ -103,8 +103,8 @@ static int __sigp_external_call(struct kvm_vcpu *vcpu, u16 cpu_addr) if (!inti) return -ENOMEM; - inti->type = KVM_S390_INT_EXTERNAL_CALL; - inti->extcall.code = vcpu->vcpu_id; + inti->irq.type = KVM_S390_INT_EXTERNAL_CALL; + inti->irq.extcall.code = vcpu->vcpu_id; spin_lock(&fi->lock); li = fi->local_int[cpu_addr]; @@ -134,7 +134,7 @@ static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action) inti = kzalloc(sizeof(*inti), GFP_ATOMIC); if (!inti) return -ENOMEM; - inti->type = KVM_S390_SIGP_STOP; + inti->irq.type = KVM_S390_SIGP_STOP; spin_lock_bh(&li->lock); if ((atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) { @@ -245,8 +245,8 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, goto out_li; } - inti->type = KVM_S390_SIGP_SET_PREFIX; - inti->prefix.address = address; + inti->irq.type = KVM_S390_SIGP_SET_PREFIX; + inti->irq.prefix.address = address; list_add_tail(&inti->list, &li->list); atomic_set(&li->active, 1); diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index acccd08..d6a1584 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -434,6 +434,68 @@ struct kvm_s390_interrupt { __u64 parm64; }; +struct kvm_s390_io_info { + __u16 subchannel_id; + __u16 subchannel_nr; + __u32 io_int_parm; + __u32 io_int_word; +}; + +struct kvm_s390_ext_info { + __u32 ext_params; + __u64 ext_params2; +}; + +struct kvm_s390_pgm_info { + __u64 trans_exc_code; + __u64 mon_code; + __u64 per_address; + __u32 data_exc_code; + __u16 code; + __u16 mon_class_nr; + __u8 per_code; + __u8 per_atmid; + __u8 exc_access_id; + __u8 per_access_id; + __u8 op_access_id; + __u8 pad[3]; +}; + +struct kvm_s390_prefix_info { + __u32 address; +}; + +struct kvm_s390_extcall_info { + __u16 code; +}; + +struct kvm_s390_emerg_info { + __u16 code; +}; + +struct kvm_s390_mchk_info { + __u64 cr14; + __u64 mcic; + __u64 failing_storage_address; + __u32 ext_damage_code; + __u32 pad; + __u8 fixed_logout[16]; +}; + +struct kvm_s390_irq { + __u64 type; + union { + struct kvm_s390_io_info io; + struct kvm_s390_ext_info ext; + struct kvm_s390_pgm_info pgm; + struct kvm_s390_emerg_info emerg; + struct kvm_s390_extcall_info extcall; + struct kvm_s390_prefix_info prefix; + struct kvm_s390_mchk_info mchk; + }; + char reserved[64]; +}; + /* for KVM_SET_GUEST_DEBUG */ #define KVM_GUESTDBG_ENABLE 0x00000001