{"id":1152957,"url":"http://patchwork.ozlabs.org/api/patches/1152957/?format=json","web_url":"http://patchwork.ozlabs.org/project/linuxppc-dev/patch/20190826061705.92048-2-aik@ozlabs.ru/","project":{"id":2,"url":"http://patchwork.ozlabs.org/api/projects/2/?format=json","name":"Linux PPC development","link_name":"linuxppc-dev","list_id":"linuxppc-dev.lists.ozlabs.org","list_email":"linuxppc-dev@lists.ozlabs.org","web_url":"https://github.com/linuxppc/wiki/wiki","scm_url":"https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git","webscm_url":"https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/","list_archive_url":"https://lore.kernel.org/linuxppc-dev/","list_archive_url_format":"https://lore.kernel.org/linuxppc-dev/{}/","commit_url_format":"https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/commit/?id={}"},"msgid":"<20190826061705.92048-2-aik@ozlabs.ru>","list_archive_url":"https://lore.kernel.org/linuxppc-dev/20190826061705.92048-2-aik@ozlabs.ru/","date":"2019-08-26T06:17:02","name":"[kernel,v2,1/4] powerpc/powernv/ioda: Split out TCE invalidation from TCE updates","commit_ref":null,"pull_url":null,"state":"changes-requested","archived":false,"hash":"7b90c43a025ac7d91670fe60c2541716d7e3694f","submitter":{"id":7621,"url":"http://patchwork.ozlabs.org/api/people/7621/?format=json","name":"Alexey Kardashevskiy","email":"aik@ozlabs.ru"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/linuxppc-dev/patch/20190826061705.92048-2-aik@ozlabs.ru/mbox/","series":[{"id":127248,"url":"http://patchwork.ozlabs.org/api/series/127248/?format=json","web_url":"http://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=127248","date":"2019-08-26T06:17:02","name":"powerpc/powernv/kvm: Invalidate multiple TCEs at once","version":2,"mbox":"http://patchwork.ozlabs.org/series/127248/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/1152957/comments/","check":"warning","checks":"http://patchwork.ozlabs.org/api/patches/1152957/checks/","tags":{},"related":[],"headers":{"Return-Path":"<linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org>","X-Original-To":["patchwork-incoming@ozlabs.org","linuxppc-dev@lists.ozlabs.org"],"Delivered-To":["patchwork-incoming@ozlabs.org","linuxppc-dev@lists.ozlabs.org"],"Received":["from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\tkey-exchange X25519 server-signature RSA-PSS (4096 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 46H1zm1dLWz9sN1\n\tfor <patchwork-incoming@ozlabs.org>;\n\tMon, 26 Aug 2019 16:19:00 +1000 (AEST)","from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 46H1zm0P0yzDqdf\n\tfor <patchwork-incoming@ozlabs.org>;\n\tMon, 26 Aug 2019 16:19:00 +1000 (AEST)","from ozlabs.ru (ozlabs.ru [107.173.13.209])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 46H1xs0hNgzDqZy\n\tfor <linuxppc-dev@lists.ozlabs.org>;\n\tMon, 26 Aug 2019 16:17:20 +1000 (AEST)","from fstn1-p1.ozlabs.ibm.com (localhost [IPv6:::1])\n\tby ozlabs.ru (Postfix) with ESMTP id 9A820AE801D4;\n\tMon, 26 Aug 2019 02:16:56 -0400 (EDT)"],"Authentication-Results":["ozlabs.org;\n\tdmarc=none (p=none dis=none) header.from=ozlabs.ru","lists.ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=ozlabs.ru\n\t(client-ip=107.173.13.209; helo=ozlabs.ru; envelope-from=aik@ozlabs.ru;\n\treceiver=<UNKNOWN>)","lists.ozlabs.org;\n\tdmarc=none (p=none dis=none) header.from=ozlabs.ru"],"From":"Alexey Kardashevskiy <aik@ozlabs.ru>","To":"linuxppc-dev@lists.ozlabs.org","Subject":"[PATCH kernel v2 1/4] powerpc/powernv/ioda: Split out TCE\n\tinvalidation from TCE updates","Date":"Mon, 26 Aug 2019 16:17:02 +1000","Message-Id":"<20190826061705.92048-2-aik@ozlabs.ru>","X-Mailer":"git-send-email 2.17.1","In-Reply-To":"<20190826061705.92048-1-aik@ozlabs.ru>","References":"<20190826061705.92048-1-aik@ozlabs.ru>","X-BeenThere":"linuxppc-dev@lists.ozlabs.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"Linux on PowerPC Developers Mail List\n\t<linuxppc-dev.lists.ozlabs.org>","List-Unsubscribe":"<https://lists.ozlabs.org/options/linuxppc-dev>,\n\t<mailto:linuxppc-dev-request@lists.ozlabs.org?subject=unsubscribe>","List-Archive":"<http://lists.ozlabs.org/pipermail/linuxppc-dev/>","List-Post":"<mailto:linuxppc-dev@lists.ozlabs.org>","List-Help":"<mailto:linuxppc-dev-request@lists.ozlabs.org?subject=help>","List-Subscribe":"<https://lists.ozlabs.org/listinfo/linuxppc-dev>,\n\t<mailto:linuxppc-dev-request@lists.ozlabs.org?subject=subscribe>","Cc":"kvm@vger.kernel.org, Alexey Kardashevskiy <aik@ozlabs.ru>,\n\tkvm-ppc@vger.kernel.org, Alex Williamson <alex.williamson@redhat.com>,\n\tAlistair Popple <alistair@popple.id.au>,\n\tDavid Gibson <david@gibson.dropbear.id.au>","Errors-To":"linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org","Sender":"\"Linuxppc-dev\"\n\t<linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org>"},"content":"At the moment updates in a TCE table are made by iommu_table_ops::exchange\nwhich update one TCE and invalidates an entry in the PHB/NPU TCE cache\nvia set of registers called \"TCE Kill\" (hence the naming).\nWriting a TCE is a simple xchg() but invalidating the TCE cache is\na relatively expensive OPAL call. Mapping a 100GB guest with PCI+NPU\npassed through devices takes about 20s.\n\nThankfully we can do better. Since such big mappings happen at the boot\ntime and when memory is plugged/onlined (i.e. not often), these requests\ncome in 512 pages so we call call OPAL 512 times less which brings 20s\nfrom the above to less than 10s. Also, since TCE caches can be flushed\nentirely, calling OPAL for 512 TCEs helps skiboot [1] to decide whether\nto flush the entire cache or not.\n\nThis implements 2 new iommu_table_ops callbacks:\n- xchg_no_kill() to update a single TCE with no TCE invalidation;\n- tce_kill() to invalidate multiple TCEs.\nThis uses the same xchg_no_kill() callback for IODA1/2.\n\nThis implements 2 new wrappers on top of the new callbacks similar to\nthe existing iommu_tce_xchg().\n\nThis does not use the new callbacks yet, the next patches will;\nso this should not cause any behavioral change.\n\nSigned-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>\n---\n arch/powerpc/include/asm/iommu.h          | 17 ++++++++++++++\n arch/powerpc/kernel/iommu.c               | 27 +++++++++++++++++++++++\n arch/powerpc/platforms/powernv/pci-ioda.c | 12 ++++++++++\n 3 files changed, 56 insertions(+)","diff":"diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h\nindex d7bf1f104c15..837b5122f257 100644\n--- a/arch/powerpc/include/asm/iommu.h\n+++ b/arch/powerpc/include/asm/iommu.h\n@@ -58,6 +58,17 @@ struct iommu_table_ops {\n \t\t\tunsigned long *hpa,\n \t\t\tenum dma_data_direction *direction);\n \n+\tint (*xchg_no_kill)(struct iommu_table *tbl,\n+\t\t\tlong index,\n+\t\t\tunsigned long *hpa,\n+\t\t\tenum dma_data_direction *direction,\n+\t\t\tbool realmode);\n+\n+\tvoid (*tce_kill)(struct iommu_table *tbl,\n+\t\t\tunsigned long index,\n+\t\t\tunsigned long pages,\n+\t\t\tbool realmode);\n+\n \t__be64 *(*useraddrptr)(struct iommu_table *tbl, long index, bool alloc);\n #endif\n \tvoid (*clear)(struct iommu_table *tbl,\n@@ -209,6 +220,12 @@ extern void iommu_del_device(struct device *dev);\n extern long iommu_tce_xchg(struct mm_struct *mm, struct iommu_table *tbl,\n \t\tunsigned long entry, unsigned long *hpa,\n \t\tenum dma_data_direction *direction);\n+extern long iommu_tce_xchg_no_kill(struct mm_struct *mm,\n+\t\tstruct iommu_table *tbl,\n+\t\tunsigned long entry, unsigned long *hpa,\n+\t\tenum dma_data_direction *direction);\n+extern void iommu_tce_kill(struct iommu_table *tbl,\n+\t\tunsigned long entry, unsigned long pages);\n #else\n static inline void iommu_register_group(struct iommu_table_group *table_group,\n \t\t\t\t\tint pci_domain_number,\ndiff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c\nindex e7a2b160d4c6..070492f9b46e 100644\n--- a/arch/powerpc/kernel/iommu.c\n+++ b/arch/powerpc/kernel/iommu.c\n@@ -1037,6 +1037,33 @@ long iommu_tce_xchg(struct mm_struct *mm, struct iommu_table *tbl,\n }\n EXPORT_SYMBOL_GPL(iommu_tce_xchg);\n \n+extern long iommu_tce_xchg_no_kill(struct mm_struct *mm,\n+\t\tstruct iommu_table *tbl,\n+\t\tunsigned long entry, unsigned long *hpa,\n+\t\tenum dma_data_direction *direction)\n+{\n+\tlong ret;\n+\tunsigned long size = 0;\n+\n+\tret = tbl->it_ops->xchg_no_kill(tbl, entry, hpa, direction, false);\n+\tif (!ret && ((*direction == DMA_FROM_DEVICE) ||\n+\t\t\t(*direction == DMA_BIDIRECTIONAL)) &&\n+\t\t\t!mm_iommu_is_devmem(mm, *hpa, tbl->it_page_shift,\n+\t\t\t\t\t&size))\n+\t\tSetPageDirty(pfn_to_page(*hpa >> PAGE_SHIFT));\n+\n+\treturn ret;\n+}\n+EXPORT_SYMBOL_GPL(iommu_tce_xchg_no_kill);\n+\n+void iommu_tce_kill(struct iommu_table *tbl,\n+\t\tunsigned long entry, unsigned long pages)\n+{\n+\tif (tbl->it_ops->tce_kill)\n+\t\ttbl->it_ops->tce_kill(tbl, entry, pages, false);\n+}\n+EXPORT_SYMBOL_GPL(iommu_tce_kill);\n+\n int iommu_take_ownership(struct iommu_table *tbl)\n {\n \tunsigned long flags, i, sz = (tbl->it_size + 7) >> 3;\ndiff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c\nindex ec48ea25a674..4e56b2c620ec 100644\n--- a/arch/powerpc/platforms/powernv/pci-ioda.c\n+++ b/arch/powerpc/platforms/powernv/pci-ioda.c\n@@ -1939,6 +1939,14 @@ static int pnv_ioda1_tce_build(struct iommu_table *tbl, long index,\n }\n \n #ifdef CONFIG_IOMMU_API\n+/* Common for IODA1 and IODA2 */\n+static int pnv_ioda_tce_xchg_no_kill(struct iommu_table *tbl, long index,\n+\t\tunsigned long *hpa, enum dma_data_direction *direction,\n+\t\tbool realmode)\n+{\n+\treturn pnv_tce_xchg(tbl, index, hpa, direction, !realmode);\n+}\n+\n static int pnv_ioda1_tce_xchg(struct iommu_table *tbl, long index,\n \t\tunsigned long *hpa, enum dma_data_direction *direction)\n {\n@@ -1975,6 +1983,8 @@ static struct iommu_table_ops pnv_ioda1_iommu_ops = {\n #ifdef CONFIG_IOMMU_API\n \t.exchange = pnv_ioda1_tce_xchg,\n \t.exchange_rm = pnv_ioda1_tce_xchg_rm,\n+\t.xchg_no_kill = pnv_ioda_tce_xchg_no_kill,\n+\t.tce_kill = pnv_pci_p7ioc_tce_invalidate,\n \t.useraddrptr = pnv_tce_useraddrptr,\n #endif\n \t.clear = pnv_ioda1_tce_free,\n@@ -2140,6 +2150,8 @@ static struct iommu_table_ops pnv_ioda2_iommu_ops = {\n #ifdef CONFIG_IOMMU_API\n \t.exchange = pnv_ioda2_tce_xchg,\n \t.exchange_rm = pnv_ioda2_tce_xchg_rm,\n+\t.xchg_no_kill = pnv_ioda_tce_xchg_no_kill,\n+\t.tce_kill = pnv_pci_ioda2_tce_invalidate,\n \t.useraddrptr = pnv_tce_useraddrptr,\n #endif\n \t.clear = pnv_ioda2_tce_free,\n","prefixes":["kernel","v2","1/4"]}