From patchwork Fri Sep 18 06:24:29 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gavin Shan X-Patchwork-Id: 519133 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 5DA95140281 for ; Fri, 18 Sep 2015 16:25:36 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752351AbbIRGZf (ORCPT ); Fri, 18 Sep 2015 02:25:35 -0400 Received: from e23smtp05.au.ibm.com ([202.81.31.147]:39666 "EHLO e23smtp05.au.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752165AbbIRGZd (ORCPT ); Fri, 18 Sep 2015 02:25:33 -0400 Received: from /spool/local by e23smtp05.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 18 Sep 2015 16:25:30 +1000 Received: from d23dlp01.au.ibm.com (202.81.31.203) by e23smtp05.au.ibm.com (202.81.31.211) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 18 Sep 2015 16:25:28 +1000 X-Helo: d23dlp01.au.ibm.com X-MailFrom: gwshan@linux.vnet.ibm.com X-RcptTo: kvm@vger.kernel.org Received: from d23relay08.au.ibm.com (d23relay08.au.ibm.com [9.185.71.33]) by d23dlp01.au.ibm.com (Postfix) with ESMTP id 0B5402CE8058; Fri, 18 Sep 2015 16:25:28 +1000 (EST) Received: from d23av04.au.ibm.com (d23av04.au.ibm.com [9.190.235.139]) by d23relay08.au.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t8I6PA4Q50724894; Fri, 18 Sep 2015 16:25:18 +1000 Received: from d23av04.au.ibm.com (localhost [127.0.0.1]) by d23av04.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t8I6OsX8021013; Fri, 18 Sep 2015 16:24:55 +1000 Received: from ozlabs.au.ibm.com (ozlabs.au.ibm.com [9.192.253.14]) by d23av04.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id t8I6OsKp020454; Fri, 18 Sep 2015 16:24:54 +1000 Received: from bran.ozlabs.ibm.com (haven.au.ibm.com [9.192.254.114]) by ozlabs.au.ibm.com (Postfix) with ESMTP id B6530A03BE; Fri, 18 Sep 2015 16:24:30 +1000 (AEST) Received: from gwshan (shangw.ozlabs.ibm.com [10.61.2.199]) by bran.ozlabs.ibm.com (Postfix) with ESMTP id AE9E4E451B; Fri, 18 Sep 2015 16:24:30 +1000 (AEST) Received: by gwshan (Postfix, from userid 1000) id 8C4B8941D64; Fri, 18 Sep 2015 16:24:30 +1000 (AEST) From: Gavin Shan To: linuxppc-dev@lists.ozlabs.org Cc: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org, david@gibson.dropbear.id.au, alex.williamson@redhat.com, Gavin Shan Subject: [PATCH 2/2] drivers/vfio: Support IOMMU group for EEH operations Date: Fri, 18 Sep 2015 16:24:29 +1000 Message-Id: <1442557469-22185-3-git-send-email-gwshan@linux.vnet.ibm.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1442557469-22185-1-git-send-email-gwshan@linux.vnet.ibm.com> References: <1442557469-22185-1-git-send-email-gwshan@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15091806-0017-0000-0000-000001E80DB4 Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org Currently, EEH module works based on the assumption that every container has only one attached IOMMU group. It's not true any more. So the userland has to specify the IOMMU group (PE) to which the requested EEH operation is applied. This exposes "v2" interface for the userland to specify IOMMU group (PE) ID when requesting EEH operation. Signed-off-by: Gavin Shan --- drivers/vfio/vfio_iommu_spapr_tce.c | 51 ++++++++++++++++++++++++++++++++----- drivers/vfio/vfio_spapr_eeh.c | 39 ++++++++++++++++------------ include/linux/vfio.h | 7 ++--- include/uapi/linux/vfio.h | 3 +++ 4 files changed, 75 insertions(+), 25 deletions(-) diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c index 812b43b..f85bde7 100644 --- a/drivers/vfio/vfio_iommu_spapr_tce.c +++ b/drivers/vfio/vfio_iommu_spapr_tce.c @@ -724,7 +724,8 @@ static long tce_iommu_ioctl(void *iommu_data, ret = 1; break; default: - ret = vfio_spapr_iommu_eeh_ioctl(NULL, cmd, arg); + ret = vfio_spapr_iommu_eeh_ioctl(NULL, cmd, + arg, NULL, 0); break; } @@ -953,17 +954,55 @@ static long tce_iommu_ioctl(void *iommu_data, return 0; case VFIO_EEH_PE_OP: { - struct tce_iommu_group *tcegrp; - int eeh_enabled; + struct tce_iommu_group *tmp, *tcegrp; + struct vfio_eeh_pe_op op; + int enabled, flag; + + enabled = vfio_spapr_pci_eeh_enabled(); + if (enabled == VFIO_EEH_DISABLED) + return -ENOTTY; - eeh_enabled = vfio_spapr_pci_eeh_enabled(); - if (eeh_enabled == VFIO_EEH_DISABLED) + /* Get the specified version */ + minsz = offsetofend(struct vfio_eeh_pe_op, flags); + if (copy_from_user(&op, (void __user *)arg, minsz)) + return -EFAULT; + flag = (op.flags & VFIO_EEH_ENABLED_MASK); + if (flag > enabled) return -ENOTTY; + else if (flag == VFIO_EEH_DISABLED) + flag = VFIO_EEH_ENABLED_V1; + + if (flag == VFIO_EEH_ENABLED_V1) + minsz = offsetofend(struct vfio_eeh_pe_op, op); + else if (flag == VFIO_EEH_ENABLED_V2) + minsz = offsetofend(struct vfio_eeh_pe_op, groupid); + if (copy_from_user(&op, (void __user *)arg, minsz)) + return -EFAULT; + + if (op.argsz < minsz) + return -EINVAL; + + if (flag == VFIO_EEH_ENABLED_V2) { + tcegrp = NULL; + list_for_each_entry(tmp, &container->group_list, next) { + if (tmp->grp && + iommu_group_id(tmp->grp) == op.groupid) { + tcegrp = tmp; + break; + } + } + + if (!tcegrp) + return -ENODEV; + + return vfio_spapr_iommu_eeh_ioctl(tcegrp->grp, + cmd, arg, &op, flag); + } ret = 0; list_for_each_entry(tcegrp, &container->group_list, next) { ret = vfio_spapr_iommu_eeh_ioctl(tcegrp->grp, - cmd, arg); + cmd, arg, &op, flag); if (ret) return ret; } diff --git a/drivers/vfio/vfio_spapr_eeh.c b/drivers/vfio/vfio_spapr_eeh.c index d208d77..e77dcb8 100644 --- a/drivers/vfio/vfio_spapr_eeh.c +++ b/drivers/vfio/vfio_spapr_eeh.c @@ -20,7 +20,7 @@ int vfio_spapr_pci_eeh_enabled(void) { - return VFIO_EEH_ENABLED_V1; + return VFIO_EEH_ENABLED_V2; } EXPORT_SYMBOL_GPL(vfio_spapr_pci_eeh_enabled); @@ -38,11 +38,12 @@ void vfio_spapr_pci_eeh_release(struct pci_dev *pdev) EXPORT_SYMBOL_GPL(vfio_spapr_pci_eeh_release); long vfio_spapr_iommu_eeh_ioctl(struct iommu_group *group, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg, + void *parm, int flag) { struct eeh_pe *pe; - struct vfio_eeh_pe_op op; - unsigned long minsz; + struct vfio_eeh_pe_op *op; + unsigned long src, dst, len; long ret = -EINVAL; switch (cmd) { @@ -54,17 +55,12 @@ long vfio_spapr_iommu_eeh_ioctl(struct iommu_group *group, ret = 0; break; case VFIO_EEH_PE_OP: + op = (struct vfio_eeh_pe_op *)parm; pe = eeh_iommu_group_to_pe(group); if (!pe) return -ENODEV; - minsz = offsetofend(struct vfio_eeh_pe_op, op); - if (copy_from_user(&op, (void __user *)arg, minsz)) - return -EFAULT; - if (op.argsz < minsz || op.flags) - return -EINVAL; - - switch (op.op) { + switch (op->op) { case VFIO_EEH_PE_DISABLE: ret = eeh_pe_set_option(pe, EEH_OPT_DISABLE); break; @@ -93,14 +89,25 @@ long vfio_spapr_iommu_eeh_ioctl(struct iommu_group *group, ret = eeh_pe_configure(pe); break; case VFIO_EEH_PE_INJECT_ERR: - minsz = offsetofend(struct vfio_eeh_pe_op, err.mask); - if (op.argsz < minsz) + if (flag == VFIO_EEH_ENABLED_V1) + src = offsetofend(struct vfio_eeh_pe_op, op); + else if (flag == VFIO_EEH_ENABLED_V2) + src = offsetofend(struct vfio_eeh_pe_op, + groupid); + else + return -ENOTTY; + + len = sizeof(struct vfio_eeh_pe_err); + if (op->argsz < src + len) return -EINVAL; - if (copy_from_user(&op, (void __user *)arg, minsz)) + + dst = offsetofend(struct vfio_eeh_pe_op, groupid); + if (copy_from_user(parm + dst, + (void __user *)(arg + src), len)) return -EFAULT; - ret = eeh_pe_inject_err(pe, op.err.type, op.err.func, - op.err.addr, op.err.mask); + ret = eeh_pe_inject_err(pe, op->err.type, op->err.func, + op->err.addr, op->err.mask); break; default: ret = -EINVAL; diff --git a/include/linux/vfio.h b/include/linux/vfio.h index ff036ca..c004307 100644 --- a/include/linux/vfio.h +++ b/include/linux/vfio.h @@ -95,8 +95,8 @@ extern int vfio_spapr_pci_eeh_enabled(void); extern void vfio_spapr_pci_eeh_open(struct pci_dev *pdev); extern void vfio_spapr_pci_eeh_release(struct pci_dev *pdev); extern long vfio_spapr_iommu_eeh_ioctl(struct iommu_group *group, - unsigned int cmd, - unsigned long arg); + unsigned int cmd, unsigned long arg, + void *param, int flag); #else static inline int vfio_spapr_pci_eeh_enabled(void) { @@ -113,7 +113,8 @@ static inline void vfio_spapr_pci_eeh_release(struct pci_dev *pdev) static inline long vfio_spapr_iommu_eeh_ioctl(struct iommu_group *group, unsigned int cmd, - unsigned long arg) + unsigned long arg, + void *param, int flag) { return -ENOTTY; } diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h index 74f5b8b..66ded6b 100644 --- a/include/uapi/linux/vfio.h +++ b/include/uapi/linux/vfio.h @@ -497,6 +497,7 @@ struct vfio_iommu_spapr_tce_info { */ #define VFIO_EEH_DISABLED 0 #define VFIO_EEH_ENABLED_V1 1 +#define VFIO_EEH_ENABLED_V2 2 struct vfio_eeh_pe_err { __u32 type; @@ -508,7 +509,9 @@ struct vfio_eeh_pe_err { struct vfio_eeh_pe_op { __u32 argsz; __u32 flags; +#define VFIO_EEH_ENABLED_MASK 0xFF __u32 op; + __u32 groupid; union { struct vfio_eeh_pe_err err; };