Re: [PATCH 8/8] KVM: PPC: Add hugepage support for IOMMU in-kernel handling

From
Alexander Graf <hidden>
Date
2013-07-11 09:52:49
Also in
kvm, lkml
Reply to
Alexey Kardashevskiy, 2013-07-11
On 11.07.2013, at 10:57, Alexey Kardashevskiy wrote:
On 07/10/2013 03:32 AM, Alexander Graf wrote:
quoted
On 07/06/2013 05:07 PM, Alexey Kardashevskiy wrote:
quoted
This adds special support for huge pages (16MB).  The reference
counting cannot be easily done for such pages in real mode (when
MMU is off) so we added a list of huge pages.  It is populated in
virtual mode and get_page is called just once per a huge page.
Real mode handlers check if the requested page is huge and in the =
list,
quoted
quoted
then no reference counting is done, otherwise an exit to virtual =
mode
quoted
quoted
happens.  The list is released at KVM exit.  At the moment the =
fastest
quoted
quoted
card available for tests uses up to 9 huge pages so walking through =
this
quoted
quoted
list is not very expensive.  However this can change and we may want
to optimize this.
=20
Signed-off-by: Paul Mackerras<redacted>
Signed-off-by: Alexey Kardashevskiy<redacted>
=20
---
=20
Changes:
2013/06/27:
* list of huge pages replaces with hashtable for better performance
=20
So the only thing your patch description really talks about is not =
true
quoted
anymore?
=20
quoted
* spinlock removed from real mode and only protects insertion of new
huge [ages descriptors into the hashtable
=20
2013/06/05:
* fixed compile error when CONFIG_IOMMU_API=3Dn
=20
2013/05/20:
* the real mode handler now searches for a huge page by gpa (used to =
be pte)
quoted
quoted
* the virtual mode handler prints warning if it is called twice for =
the same
quoted
quoted
huge page as the real mode handler is expected to fail just once - =
when a
quoted
quoted
huge
page is not in the list yet.
* the huge page is refcounted twice - when added to the hugepage =
list and
quoted
quoted
when used in the virtual mode hcall handler (can be optimized but it =
will
quoted
quoted
make the patch less nice).
=20
Signed-off-by: Alexey Kardashevskiy<redacted>
---
 arch/powerpc/include/asm/kvm_host.h |  25 +++++++++
 arch/powerpc/kernel/iommu.c         |   6 ++-
 arch/powerpc/kvm/book3s_64_vio.c    | 104
+++++++++++++++++++++++++++++++++---
 arch/powerpc/kvm/book3s_64_vio_hv.c |  21 ++++++--
 4 files changed, 146 insertions(+), 10 deletions(-)
=20
diff --git a/arch/powerpc/include/asm/kvm_host.h
b/arch/powerpc/include/asm/kvm_host.h
index 53e61b2..a7508cf 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -30,6 +30,7 @@
 #include<linux/kvm_para.h>
 #include<linux/list.h>
 #include<linux/atomic.h>
+#include<linux/hashtable.h>
 #include<asm/kvm_asm.h>
 #include<asm/processor.h>
 #include<asm/page.h>
@@ -182,10 +183,34 @@ struct kvmppc_spapr_tce_table {
     u32 window_size;
     struct iommu_group *grp;        /* used for IOMMU groups */
     struct vfio_group *vfio_grp;        /* used for IOMMU groups */
+    DECLARE_HASHTABLE(hash_tab, ilog2(64));    /* used for IOMMU =
groups */
quoted
quoted
+    spinlock_t hugepages_write_lock;    /* used for IOMMU groups */
     struct { struct { unsigned long put, indir, stuff; } rm, vm; } =
stat;
quoted
quoted
     struct page *pages[0];
 };
=20
+/*
+ * The KVM guest can be backed with 16MB pages.
+ * In this case, we cannot do page counting from the real mode
+ * as the compound pages are used - they are linked in a list
+ * with pointers as virtual addresses which are inaccessible
+ * in real mode.
+ *
+ * The code below keeps a 16MB pages list and uses page struct
+ * in real mode if it is already locked in RAM and inserted into
+ * the list or switches to the virtual mode where it can be
+ * handled in a usual manner.
+ */
+#define KVMPPC_SPAPR_HUGEPAGE_HASH(gpa)    hash_32(gpa>>  24, 32)
+
+struct kvmppc_spapr_iommu_hugepage {
+    struct hlist_node hash_node;
+    unsigned long gpa;    /* Guest physical address */
+    unsigned long hpa;    /* Host physical address */
+    struct page *page;    /* page struct of the very first subpage =
*/
quoted
quoted
+    unsigned long size;    /* Huge page size (always 16MB at the =
moment) */
quoted
quoted
+};
+
 struct kvmppc_linear_info {
     void        *base_virt;
     unsigned long     base_pfn;
diff --git a/arch/powerpc/kernel/iommu.c =
b/arch/powerpc/kernel/iommu.c
quoted
quoted
index 51678ec..e0b6eca 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -999,7 +999,8 @@ int iommu_free_tces(struct iommu_table *tbl, =
unsigned
quoted
quoted
long entry,
             if (!pg) {
                 ret =3D -EAGAIN;
             } else if (PageCompound(pg)) {
-                ret =3D -EAGAIN;
+                /* Hugepages will be released at KVM exit */
+                ret =3D 0;
             } else {
                 if (oldtce&  TCE_PCI_WRITE)
                     SetPageDirty(pg);
@@ -1009,6 +1010,9 @@ int iommu_free_tces(struct iommu_table *tbl,
unsigned long entry,
             struct page *pg =3D pfn_to_page(oldtce>>  PAGE_SHIFT);
             if (!pg) {
                 ret =3D -EAGAIN;
+            } else if (PageCompound(pg)) {
+                /* Hugepages will be released at KVM exit */
+                ret =3D 0;
             } else {
                 if (oldtce&  TCE_PCI_WRITE)
                     SetPageDirty(pg);
diff --git a/arch/powerpc/kvm/book3s_64_vio.c
b/arch/powerpc/kvm/book3s_64_vio.c
index 2b51f4a..c037219 100644
--- a/arch/powerpc/kvm/book3s_64_vio.c
+++ b/arch/powerpc/kvm/book3s_64_vio.c
@@ -46,6 +46,40 @@
=20
 #define ERROR_ADDR      ((void *)~(unsigned long)0x0)
=20
+#ifdef CONFIG_IOMMU_API
=20
Can't you just make CONFIG_IOMMU_API mandatory in Kconfig?
=20
=20
Where exactly (it is rather SPAPR_TCE_IOMMU but does not really =
matter)?
Select it on KVM_BOOK3S_64? CONFIG_KVM_BOOK3S_64_HV?
CONFIG_KVM_BOOK3S_64_PR? PPC_BOOK3S_64?
I'd say the most logical choice would be to check the Makefile and see =
when it gets compiled. For those cases we want it enabled.
I am trying to imagine a configuration where we really do not want
IOMMU_API. Ben mentioned PPC32 and embedded PPC64 and that's it so any =
of
BOOK3S (KVM_BOOK3S_64 is the best) should be fine, no?
book3s_32 doesn't want this, but any book3s_64 implementation could =
potentially use it, yes. That's pretty much what the Makefile tells you =
too :).


Alex
Thread (53 messages) 53 messages, 5 authors, last reply 2013-07-11
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help