From patchwork Mon Nov 12 06:44:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Baolu Lu X-Patchwork-Id: 10678203 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7EAE615E9 for ; Mon, 12 Nov 2018 06:48:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 694CD204FF for ; Mon, 12 Nov 2018 06:48:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5843828BAE; Mon, 12 Nov 2018 06:48:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1F730204FF for ; Mon, 12 Nov 2018 06:48:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732080AbeKLQkR (ORCPT ); Mon, 12 Nov 2018 11:40:17 -0500 Received: from mga17.intel.com ([192.55.52.151]:53355 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731996AbeKLQj4 (ORCPT ); Mon, 12 Nov 2018 11:39:56 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 11 Nov 2018 22:48:04 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.54,494,1534834800"; d="scan'208";a="88579687" Received: from allen-box.sh.intel.com ([10.239.161.122]) by orsmga007.jf.intel.com with ESMTP; 11 Nov 2018 22:48:01 -0800 From: Lu Baolu To: Joerg Roedel , David Woodhouse , Alex Williamson , Kirti Wankhede Cc: ashok.raj@intel.com, sanjay.k.kumar@intel.com, jacob.jun.pan@intel.com, kevin.tian@intel.com, Jean-Philippe Brucker , yi.l.liu@intel.com, yi.y.sun@intel.com, peterx@redhat.com, tiwei.bie@intel.com, Zeng Xin , iommu@lists.linux-foundation.org, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Lu Baolu , Jacob Pan Subject: [RFC PATCH 3/5] iommu/vt-d: Enlightened PASID allocation Date: Mon, 12 Nov 2018 14:44:59 +0800 Message-Id: <20181112064501.2290-4-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181112064501.2290-1-baolu.lu@linux.intel.com> References: <20181112064501.2290-1-baolu.lu@linux.intel.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP If Intel IOMMU runs in caching mode, a.k.a. virtual IOMMU, the IOMMU driver should rely on the emulation software to allocate and free PASID IDs. The Intel vt-d spec revision 3.0 defines a register set to support this. This includes a capability register, a virtual command register and a virtual response register. Refer to section 10.4.42, 10.4.43, 10.4.44 for more information. This patch adds the enlightened PASID allocation/free interfaces via the virtual command register. Cc: Ashok Raj Cc: Jacob Pan Cc: Kevin Tian Signed-off-by: Liu Yi L Signed-off-by: Lu Baolu --- drivers/iommu/intel-pasid.c | 70 +++++++++++++++++++++++++++++++++++++ drivers/iommu/intel-pasid.h | 13 ++++++- include/linux/intel-iommu.h | 2 ++ 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/intel-pasid.c b/drivers/iommu/intel-pasid.c index 839f83974aca..fb42f0c2493e 100644 --- a/drivers/iommu/intel-pasid.c +++ b/drivers/iommu/intel-pasid.c @@ -28,6 +28,76 @@ static DEFINE_SPINLOCK(pasid_lock); u32 intel_pasid_max_id = PASID_MAX; static DEFINE_IDR(pasid_idr); +int vcmd_alloc_pasid(struct intel_iommu *iommu, unsigned int *pasid) +{ + u64 res; + u64 cap; + u8 err_code; + unsigned long flags; + int ret = 0; + + if (!ecap_vcs(iommu->ecap)) { + pr_warn("IOMMU: %s: Hardware doesn't support virtual command\n", + iommu->name); + return -ENODEV; + } + + cap = dmar_readq(iommu->reg + DMAR_VCCAP_REG); + if (!(cap & DMA_VCS_PAS)) { + pr_warn("IOMMU: %s: Emulation software doesn't support PASID allocation\n", + iommu->name); + return -ENODEV; + } + + raw_spin_lock_irqsave(&iommu->register_lock, flags); + dmar_writeq(iommu->reg + DMAR_VCMD_REG, VCMD_CMD_ALLOC); + IOMMU_WAIT_OP(iommu, DMAR_VCRSP_REG, dmar_readq, + !(res & VCMD_VRSP_IP), res); + raw_spin_unlock_irqrestore(&iommu->register_lock, flags); + + err_code = VCMD_VRSP_EC(res); + switch (err_code) { + case VCMD_VRSP_EC_SUCCESS: + *pasid = VCMD_VRSP_RESULE(res); + break; + case VCMD_VRSP_EC_UNAVAIL: + pr_info("IOMMU: %s: No PASID available\n", iommu->name); + ret = -ENOMEM; + break; + default: + ret = -ENODEV; + pr_warn("IOMMU: %s: Unkonwn error code %d\n", + iommu->name, err_code); + } + + return ret; +} + +void vcmd_free_pasid(struct intel_iommu *iommu, unsigned int pasid) +{ + u64 res; + u8 err_code; + unsigned long flags; + + raw_spin_lock_irqsave(&iommu->register_lock, flags); + dmar_writeq(iommu->reg + DMAR_VCMD_REG, (pasid << 8) | VCMD_CMD_FREE); + IOMMU_WAIT_OP(iommu, DMAR_VCRSP_REG, dmar_readq, + !(res & VCMD_VRSP_IP), res); + raw_spin_unlock_irqrestore(&iommu->register_lock, flags); + + err_code = VCMD_VRSP_EC(res); + switch (err_code) { + case VCMD_VRSP_EC_SUCCESS: + break; + case VCMD_VRSP_EC_INVAL: + pr_info("IOMMU: %s: Invalid PASID\n", iommu->name); + break; + default: + pr_warn("IOMMU: %s: Unkonwn error code %d\n", + iommu->name, err_code); + } +} + int intel_pasid_alloc_id(void *ptr, int start, int end, gfp_t gfp) { int ret, min, max; diff --git a/drivers/iommu/intel-pasid.h b/drivers/iommu/intel-pasid.h index 381545ff9fb7..c80787d02e2d 100644 --- a/drivers/iommu/intel-pasid.h +++ b/drivers/iommu/intel-pasid.h @@ -19,6 +19,16 @@ #define PASID_PDE_SHIFT 6 #define MAX_NR_PASID_BITS 20 +/* Virtual command interface for enlightened pasid management. */ +#define VCMD_CMD_ALLOC 0x1 +#define VCMD_CMD_FREE 0x2 +#define VCMD_VRSP_IP 0x1 +#define VCMD_VRSP_EC(e) (((e) >> 1) & 0x3) +#define VCMD_VRSP_EC_SUCCESS 0 +#define VCMD_VRSP_EC_UNAVAIL 1 +#define VCMD_VRSP_EC_INVAL 1 +#define VCMD_VRSP_RESULE(e) (((e) >> 8) & 0xfffff) + /* * Domain ID reserved for pasid entries programmed for first-level * only and pass-through transfer modes. @@ -69,5 +79,6 @@ int intel_pasid_setup_pass_through(struct intel_iommu *iommu, struct device *dev, int pasid); void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev, int pasid); - +int vcmd_alloc_pasid(struct intel_iommu *iommu, unsigned int *pasid); +void vcmd_free_pasid(struct intel_iommu *iommu, unsigned int pasid); #endif /* __INTEL_PASID_H */ diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index b563a61a6c39..4605eef3686c 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -173,6 +173,7 @@ #define ecap_smpwc(e) (((e) >> 48) & 0x1) #define ecap_flts(e) (((e) >> 47) & 0x1) #define ecap_slts(e) (((e) >> 46) & 0x1) +#define ecap_vcs(e) (((e) >> 45) & 0x1) #define ecap_smts(e) (((e) >> 43) & 0x1) #define ecap_dit(e) ((e >> 41) & 0x1) #define ecap_pasid(e) ((e >> 40) & 0x1) @@ -289,6 +290,7 @@ /* PRS_REG */ #define DMA_PRS_PPR ((u32)1) +#define DMA_VCS_PAS ((u64)1) #define IOMMU_WAIT_OP(iommu, offset, op, cond, sts) \ do { \