[PATCH v4 20/22] iommu/vt-d: add intel iommu page response function
This patch adds page response support for Intel VT-d. Generic response data is taken from the IOMMU API then parsed into VT-d specific response descriptor format. Signed-off-by: Jacob Pan--- drivers/iommu/intel-iommu.c | 47 + include/linux/intel-iommu.h | 3 +++ 2 files changed, 50 insertions(+) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index a6ea67d..38f76d4 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -5142,6 +5142,52 @@ static int intel_iommu_sva_invalidate(struct iommu_domain *domain, return ret; } +static int intel_iommu_page_response(struct device *dev, struct page_response_msg *msg) +{ + struct qi_desc resp; + struct intel_iommu *iommu; + struct pci_dev *pdev; + u8 bus, devfn; + u16 rid; + u64 desc; + + pdev = to_pci_dev(dev); + iommu = device_to_iommu(dev, , ); + if (!iommu) { + dev_err(dev, "No IOMMU for device to unbind PASID table\n"); + return -ENODEV; + } + + pci_dev_get(pdev); + rid = ((u16)bus << 8) | devfn; + /* Iommu private data contains preserved page request descriptor, so we +* inspect the SRR bit for response type then queue response with only +* the private data [54:32]. +*/ + desc = msg->private_data; + if (desc & QI_PRQ_SRR) { + /* Page Stream Response */ + resp.low = QI_PSTRM_IDX(msg->page_req_group_id) | + (desc & QI_PRQ_PRIV) | QI_PSTRM_BUS(PCI_BUS_NUM(pdev->bus->number)) | + QI_PSTRM_PASID(msg->pasid) | QI_PSTRM_RESP_TYPE; + resp.high = QI_PSTRM_ADDR(msg->addr) | QI_PSTRM_DEVFN(pdev->devfn & 0xff) | + QI_PSTRM_RESP_CODE(msg->resp_code); + } else { + /* Page Group Response */ + resp.low = QI_PGRP_PASID(msg->pasid) | + QI_PGRP_DID(rid) | + QI_PGRP_PASID_P(msg->pasid_present) | + QI_PGRP_RESP_TYPE; + resp.high = QI_PGRP_IDX(msg->page_req_group_id) | + (desc & QI_PRQ_PRIV) | QI_PGRP_RESP_CODE(msg->resp_code); + + } + qi_submit_sync(, iommu); + pci_dev_put(pdev); + + return 0; +} + static int intel_iommu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t hpa, size_t size, int iommu_prot) @@ -5568,6 +5614,7 @@ const struct iommu_ops intel_iommu_ops = { .bind_pasid_table = intel_iommu_bind_pasid_table, .unbind_pasid_table = intel_iommu_unbind_pasid_table, .sva_invalidate = intel_iommu_sva_invalidate, + .page_response = intel_iommu_page_response, #endif .map= intel_iommu_map, .unmap = intel_iommu_unmap, diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index dbe8c93..ed2883a 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -337,6 +337,9 @@ enum { #define QI_PSTRM_BUS(bus) (((u64)(bus)) << 24) #define QI_PSTRM_PASID(pasid) (((u64)(pasid)) << 4) +#define QI_PRQ_SRR BIT_ULL(0) +#define QI_PRQ_PRIVGENMASK_ULL(54, 32) + #define QI_RESP_SUCCESS0x0 #define QI_RESP_INVALID0x1 #define QI_RESP_FAILURE0xf -- 2.7.4 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v4 20/22] iommu/vt-d: add intel iommu page response function
Hi Jacob, I love your patch! Perhaps something to improve: [auto build test WARNING on iommu/next] [also build test WARNING on v4.16-rc6 next-20180323] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Jacob-Pan/IOMMU-and-VT-d-driver-support-for-Shared-Virtual-Address-SVA/20180325-024555 base: https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next reproduce: # apt-get install sparse make ARCH=x86_64 allmodconfig make C=1 CF=-D__CHECK_ENDIAN__ sparse warnings: (new ones prefixed by >>) drivers/iommu/intel-iommu.c:500:5: sparse: symbol 'intel_iommu_gfx_mapped' was not declared. Should it be static? drivers/iommu/intel-iommu.c:3066:41: sparse: incorrect type in argument 1 (different address spaces) @@expected void volatile [noderef] *addr @@got ile [noderef] *addr @@ drivers/iommu/intel-iommu.c:3066:41:expected void volatile [noderef] *addr drivers/iommu/intel-iommu.c:3066:41:got struct context_entry *old_ce >> drivers/iommu/intel-iommu.c:5198:5: sparse: symbol >> 'intel_iommu_page_response' was not declared. Should it be static? >> drivers/iommu/intel-iommu.c:5224:48: sparse: right shift by bigger than >> source value Please review and possibly fold the followup patch. --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v4 20/22] iommu/vt-d: add intel iommu page response function
This patch adds page response support for Intel VT-d. Generic response data is taken from the IOMMU API then parsed into VT-d specific response descriptor format. Signed-off-by: Jacob Pan--- drivers/iommu/intel-iommu.c | 47 + include/linux/intel-iommu.h | 3 +++ 2 files changed, 50 insertions(+) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 3229e20..8d73ff0 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -5195,6 +5195,52 @@ static int intel_iommu_sva_invalidate(struct iommu_domain *domain, return ret; } +int intel_iommu_page_response(struct device *dev, struct page_response_msg *msg) +{ + struct qi_desc resp; + struct intel_iommu *iommu; + struct pci_dev *pdev; + u8 bus, devfn; + u16 rid; + u64 desc; + + pdev = to_pci_dev(dev); + iommu = device_to_iommu(dev, , ); + if (!iommu) { + dev_err(dev, "No IOMMU for device to unbind PASID table\n"); + return -ENODEV; + } + + pci_dev_get(pdev); + rid = ((u16)bus << 8) | devfn; + /* Iommu private data contains preserved page request descriptor, so we +* inspect the SRR bit for response type then queue response with only +* the private data [54:32]. +*/ + desc = msg->private_data; + if (desc & QI_PRQ_SRR) { + /* Page Stream Response */ + resp.low = QI_PSTRM_IDX(msg->page_req_group_id) | + (desc & QI_PRQ_PRIV) | QI_PSTRM_BUS(PCI_BUS_NUM(pdev->bus->number)) | + QI_PSTRM_PASID(msg->pasid) | QI_PSTRM_RESP_TYPE; + resp.high = QI_PSTRM_ADDR(msg->addr) | QI_PSTRM_DEVFN(pdev->devfn & 0xff) | + QI_PSTRM_RESP_CODE(msg->resp_code); + } else { + /* Page Group Response */ + resp.low = QI_PGRP_PASID(msg->pasid) | + QI_PGRP_DID(rid) | + QI_PGRP_PASID_P(msg->pasid_present) | + QI_PGRP_RESP_TYPE; + resp.high = QI_PGRP_IDX(msg->page_req_group_id) | + (desc & QI_PRQ_PRIV) | QI_PGRP_RESP_CODE(msg->resp_code); + + } + qi_submit_sync(, iommu); + pci_dev_put(pdev); + + return 0; +} + static int intel_iommu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t hpa, size_t size, int iommu_prot) @@ -5625,6 +5671,7 @@ const struct iommu_ops intel_iommu_ops = { .bind_pasid_table = intel_iommu_bind_pasid_table, .unbind_pasid_table = intel_iommu_unbind_pasid_table, .sva_invalidate = intel_iommu_sva_invalidate, + .page_response = intel_iommu_page_response, #endif .map= intel_iommu_map, .unmap = intel_iommu_unmap, diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index dacb6cf..d2e1b5c 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -337,6 +337,9 @@ enum { #define QI_PSTRM_BUS(bus) (((u64)(bus)) << 24) #define QI_PSTRM_PASID(pasid) (((u64)(pasid)) << 4) +#define QI_PRQ_SRR BIT_ULL(0) +#define QI_PRQ_PRIVGENMASK_ULL(54, 32) + #define QI_RESP_SUCCESS0x0 #define QI_RESP_INVALID0x1 #define QI_RESP_FAILURE0xf -- 2.7.4 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu