KVM: PPC: Book3S HV: Migrate pinned pages out of CMA
Subsystems (3)
PATCH RESEND v2 1/1 KVM: PPC: Book3S HV: Migrate pinned pages out of CMA
From: Balbir Singh <[email protected]>
Subject: [RESEND][v2][PATCH] KVM: PPC: Book3S HV: Migrate pinned pages out of CMA
When PCI Device pass-through is enabled via VFIO, KVM-PPC will pin pages using get_user_pages_fast(). One of the downsides of the pinning is that the page could be in CMA region. The CMA region is used for other allocations like the hash page table. Ideally we want the pinned pages to be from non CMA region.
This patch (currently only for KVM PPC with VFIO) forcefully migrates the pages out (huge pages are omitted for the moment). There are more efficient ways of doing this, but that might be elaborate and might impact a larger audience beyond just the kvm ppc implementation.
The magic is in new_iommu_non_cma_page() which allocates the new page from a non CMA region.
I've tested the patches lightly at my end, but there might be bugs For example if after lru_add_drain(), the page is not isolated is this a BUG?
Previous discussion was at
http://permalink.gmane.org/gmane.linux.kernel.mm/136738
--- arch/powerpc/include/asm/mmu_context.h | 1 + arch/powerpc/mm/mmu_context_iommu.c | 80 ++++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 4 deletions(-)
arch/powerpc/include/asm/mmu_context.h +1 -0
@@ -18,6 +18,7 @@ extern void destroy_context(struct mm_struct *mm);#ifdef CONFIG_SPAPR_TCE_IOMMU struct mm_iommu_table_group_mem_t ; +extern int isolate_lru_page (struct page *page);/* from internal.h */ extern bool mm_iommu_preregistered (void );extern long mm_iommu_get (unsigned long ua,unsigned long entries,struct mm_iommu_table_group_mem_t **pmem);
arch/powerpc/mm/mmu_context_iommu.c +76 -4
103 lines not on this page · raw message
Signature · 7 lines
2.5.5 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 26 lines · Balbir Singh
From: Balbir Singh <[email protected]>
Subject: [RESEND][v2][PATCH] KVM: PPC: Book3S HV: Migrate pinned pages out of CMAWhen PCI Device pass-through is enabled via VFIO, KVM-PPC will pin pages using
get_user_pages_fast(). One of the downsides of the pinning is that the page could be in CMA region. The CMA region is used for other allocations like the hash page table. Ideally we want the pinned pages to be from non CMA region.This patch (currently only for KVM PPC with VFIO) forcefully migrates the pages out (huge pages are omitted for the moment). There are more efficient ways of doing this, but that might be elaborate and might impact a larger audience beyond just the kvm ppc implementation.
The magic is in
new_iommu_non_cma_page()which allocates the new page from a non CMA region.I've tested the patches lightly at my end, but there might be bugs For example if after
lru_add_drain(), the page is not isolated is this a BUG?Previous discussion was at
http://permalink.gmane.org/gmane.linux.kernel.mm/136738
Quoted 6 lines
Cc Benjamin Herrenschmidt <[email protected]>Cc Michael Ellerman <[email protected]>Cc Paul Mackerras <[email protected]>Cc Alexey Kardashevskiy <[email protected]>Signed-off-by Balbir Singh <[email protected]>
Quoted 128 lines
--- arch/powerpc/include/asm/mmu_context.h | 1 + arch/powerpc/mm/mmu_context_iommu.c | 80 ++++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 4 deletions(-)arch/powerpc/include/asm/mmu_context.h +1
-0@@ -18,6 +18,7 @@ extern void destroy_context(struct mm_struct *mm);#ifdef CONFIG_SPAPR_TCE_IOMMU struct mm_iommu_table_group_mem_t ; +extern int isolate_lru_page (struct page *page);/* from internal.h */ extern bool mm_iommu_preregistered (void );extern long mm_iommu_get (unsigned long ua,unsigned long entries,struct mm_iommu_table_group_mem_t **pmem);arch/powerpc/mm/mmu_context_iommu.c +76
-4@@ -15,6 +15,9 @@#include <linux/rculist.h> #include <linux/vmalloc.h> #include <linux/mutex.h> +#include <linux/migrate.h> +#include <linux/hugetlb.h> +#include <linux/swap.h> #include <asm/mmu_context.h> static DEFINE_MUTEX (mem_list_mutex);@@ -72,6 +75,54 @@ bool mm_iommu_preregistered(void) }EXPORT_SYMBOL_GPL (mm_iommu_preregistered); +/* +* Taken from alloc_migrate_target with changes to remove CMA allocations +*/ +struct page *new_iommu_non_cma_page (struct page *page,unsigned long private, +int **resultp) +{ +gfp_t gfp_mask =GFP_USER ; +struct page *new_page; + +if (PageHuge (page) ||PageTransHuge (page) ||PageCompound (page)) +return NULL ; + +if (PageHighMem (page)) + gfp_mask |= __GFP_HIGHMEM; + +/* +* We don't want the allocation to force an OOM if possibe +*/ + new_page =alloc_page (gfp_mask | __GFP_NORETRY | __GFP_NOWARN); +return new_page; +} + +static int mm_iommu_move_page_from_cma (struct page *page) +{ +int ret; +LIST_HEAD (cma_migrate_pages); + +/* Ignore huge pages for now */ +if (PageHuge (page) ||PageTransHuge (page) ||PageCompound (page)) +return -EBUSY ; + +lru_add_drain (); + ret =isolate_lru_page (page); +if (ret) +get_page (page);/* Potential BUG? */ + +list_add (&page->lru, &cma_migrate_pages); +put_page (page);/* Drop the gup reference */ + + ret =migrate_pages (&cma_migrate_pages, new_iommu_non_cma_page, +NULL ,0 ,MIGRATE_SYNC ,MR_CMA ); +if (ret) { +if (!list_empty (&cma_migrate_pages)) +putback_movable_pages (&cma_migrate_pages); + } +return 0 ; +} +long mm_iommu_get (unsigned long ua,unsigned long entries,struct mm_iommu_table_group_mem_t **pmem) {@@ -124,15 +175,36 @@ long mm_iommu_get(unsigned long ua, unsigned long entries,for (i =0 ; i < entries; ++i) {if (1 !=get_user_pages_fast (ua + (i <<PAGE_SHIFT ),1 /* pages */ ,1 /* iswrite */ , &page)) { + ret = -EFAULT ;for (j =0 ; j < i; ++j) -put_page (pfn_to_page ( - mem->hpas[j] >>PAGE_SHIFT )); +put_page (pfn_to_page (mem->hpas[j] >> +PAGE_SHIFT ));vfree (mem->hpas);kfree (mem); - ret = -EFAULT ; goto unlock_exit; } - +/* +* If we get a page from the CMA zone, since we are going to +* be pinning these entries, we might as well move them out +* of the CMA zone if possible. NOTE: faulting in + migration +* can be expensive. Batching can be considered later +*/ +if (get_pageblock_migratetype (page) ==MIGRATE_CMA ) { +if (mm_iommu_move_page_from_cma (page)) + goto populate; +if (1 !=get_user_pages_fast (ua + (i <<PAGE_SHIFT ), +1 /* pages */ ,1 /* iswrite */ , + &page)) { + ret = -EFAULT ; +for (j =0 ; j < i; ++j) +put_page (pfn_to_page (mem->hpas[j] >> +PAGE_SHIFT )); +vfree (mem->hpas); +kfree (mem); + goto unlock_exit; + } + } +populate: mem->hpas[i] =page_to_pfn (page) <<PAGE_SHIFT ; }
Signature · 7 lines
Alexey -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 32 lines · Alexey Kardashevskiy
Quoted 31 lines · Balbir Singh
From: Balbir Singh <[email protected]>
Subject: [RESEND][v2][PATCH] KVM: PPC: Book3S HV: Migrate pinned pages out of CMAWhen PCI Device pass-through is enabled via VFIO, KVM-PPC will pin pages using
get_user_pages_fast(). One of the downsides of the pinning is that the page could be in CMA region. The CMA region is used for other allocations like the hash page table. Ideally we want the pinned pages to be from non CMA region.This patch (currently only for KVM PPC with VFIO) forcefully migrates the pages out (huge pages are omitted for the moment). There are more efficient ways of doing this, but that might be elaborate and might impact a larger audience beyond just the kvm ppc implementation.
The magic is in
new_iommu_non_cma_page()which allocates the new page from a non CMA region.I've tested the patches lightly at my end, but there might be bugs For example if after
lru_add_drain(), the page is not isolated is this a BUG?Previous discussion was at
http://permalink.gmane.org/gmane.linux.kernel.mm/136738Cc Benjamin Herrenschmidt <[email protected]>Cc Michael Ellerman <[email protected]>Cc Paul Mackerras <[email protected]>Cc Alexey Kardashevskiy <[email protected]>
Quoted 6 lines
Quoted 1 line
Signed-off-by Balbir Singh <[email protected]>
Thanks! I tested this patch against latest mainline and here are the test results
System RAM - 64GB
VM instance 1 - size 55GB
Before patch - nr_free_cma after launch 8900
After patch - nr_free_cma after launch 39500
Balbir Singh.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v3 1/1 KVM: PPC: Book3S HV: Migrate pinned pages out of CMA
When PCI Device pass-through is enabled via VFIO, KVM-PPC will pin pages using get_user_pages_fast(). One of the downsides of the pinning is that the page could be in CMA region. The CMA region is used for other allocations like the hash page table. Ideally we want the pinned pages to be from non CMA region.
This patch (currently only for KVM PPC with VFIO) forcefully migrates the pages out (huge pages are omitted for the moment). There are more efficient ways of doing this, but that might be elaborate and might impact a larger audience beyond just the kvm ppc implementation.
The magic is in new_iommu_non_cma_page() which allocates the new page from a non CMA region.
I've tested the patches lightly at my end. The full solution requires migration of THP pages in the CMA region. That work will be done incrementally on top of this.
Previous discussion was at
http://permalink.gmane.org/gmane.linux.kernel.mm/136738
--- arch/powerpc/include/asm/mmu_context.h | 1 + arch/powerpc/mm/mmu_context_iommu.c | 81 ++++++++++++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 4 deletions(-)
arch/powerpc/include/asm/mmu_context.h +1 -0
@@ -18,6 +18,7 @@ extern void destroy_context(struct mm_struct *mm);#ifdef CONFIG_SPAPR_TCE_IOMMU struct mm_iommu_table_group_mem_t ; +extern int isolate_lru_page (struct page *page);/* from internal.h */ extern bool mm_iommu_preregistered (void );extern long mm_iommu_get (unsigned long ua,unsigned long entries,struct mm_iommu_table_group_mem_t **pmem);
arch/powerpc/mm/mmu_context_iommu.c +77 -4
104 lines not on this page · raw message
Signature · 7 lines
2.5.5 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 40 lines · Balbir Singh
When PCI Device pass-through is enabled via VFIO, KVM-PPC will pin pages using
get_user_pages_fast(). One of the downsides of the pinning is that the page could be in CMA region. The CMA region is used for other allocations like the hash page table. Ideally we want the pinned pages to be from non CMA region.This patch (currently only for KVM PPC with VFIO) forcefully migrates the pages out (huge pages are omitted for the moment). There are more efficient ways of doing this, but that might be elaborate and might impact a larger audience beyond just the kvm ppc implementation.
The magic is in
new_iommu_non_cma_page()which allocates the new page from a non CMA region.I've tested the patches lightly at my end. The full solution requires migration of THP pages in the CMA region. That work will be done incrementally on top of this.
Previous discussion was at
http://permalink.gmane.org/gmane.linux.kernel.mm/136738Cc Benjamin Herrenschmidt <[email protected]>Cc Michael Ellerman <[email protected]>Cc Paul Mackerras <[email protected]>Cc Alexey Kardashevskiy <[email protected]>Signed-off-by Balbir Singh <[email protected]>--- arch/powerpc/include/asm/mmu_context.h | 1 + arch/powerpc/mm/mmu_context_iommu.c | 81 ++++++++++++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 4 deletions(-)arch/powerpc/include/asm/mmu_context.h +0
-0
arch/powerpc/include/asm/mmu_context.h extern void destroy_context(struct mm_struct *mm); · line 21
Quoted 4 lines
arch/powerpc/include/asm/mmu_context.h +1
-0@@ -18,6 +18,7 @@ extern void destroy_context(struct mm_struct *mm);#ifdef CONFIG_SPAPR_TCE_IOMMU struct mm_iommu_table_group_mem_t ; +extern int isolate_lru_page (struct page *page);/* from internal.h */
Small nit, cant we just add "mm/internal.h" header here with full path ?
Quoted 30 lines
arch/powerpc/include/asm/mmu_context.h +0
-0extern bool mm_iommu_preregistered (void );extern long mm_iommu_get (unsigned long ua,unsigned long entries,struct mm_iommu_table_group_mem_t **pmem);arch/powerpc/mm/mmu_context_iommu.c +12
-0@@ -15,6 +15,9 @@#include <linux/rculist.h> #include <linux/vmalloc.h> #include <linux/mutex.h> +#include <linux/migrate.h> +#include <linux/hugetlb.h> +#include <linux/swap.h> #include <asm/mmu_context.h> static DEFINE_MUTEX (mem_list_mutex);@@ -72,6 +75,55 @@ bool mm_iommu_preregistered(void) }EXPORT_SYMBOL_GPL (mm_iommu_preregistered); +/* +* Taken from alloc_migrate_target with changes to remove CMA allocations +*/ +struct page *new_iommu_non_cma_page (struct page *page,unsigned long private, +int **resultp) +{ +gfp_t gfp_mask =GFP_USER ; +struct page *new_page; +
arch/powerpc/mm/mmu_context_iommu.c bool mm_iommu_preregistered(void) · line 96
Quoted 10 lines
arch/powerpc/mm/mmu_context_iommu.c +10
-0+if (PageHuge (page) ||PageTransHuge (page) ||PageCompound (page)) +return NULL ; + +if (PageHighMem (page)) + gfp_mask |= __GFP_HIGHMEM; + +/* +* We don't want the allocation to force an OOM if possibe +*/ + new_page =alloc_page (gfp_mask | __GFP_NORETRY | __GFP_NOWARN);
So what guarantees that the new page too wont come from MIGRATE_CMA page block ? Is absence of __GFP_MOVABLE flag enough. Also should not we be checking that migrate type of the new allocated page is indeed not MIGRATE_CMA ?
Quoted 44 lines · Anshuman Khandual
Quoted 43 lines · Balbir Singh
When PCI Device pass-through is enabled via VFIO, KVM-PPC will pin pages using
get_user_pages_fast(). One of the downsides of the pinning is that the page could be in CMA region. The CMA region is used for other allocations like the hash page table. Ideally we want the pinned pages to be from non CMA region.This patch (currently only for KVM PPC with VFIO) forcefully migrates the pages out (huge pages are omitted for the moment). There are more efficient ways of doing this, but that might be elaborate and might impact a larger audience beyond just the kvm ppc implementation.
The magic is in
new_iommu_non_cma_page()which allocates the new page from a non CMA region.I've tested the patches lightly at my end. The full solution requires migration of THP pages in the CMA region. That work will be done incrementally on top of this.
Previous discussion was at
http://permalink.gmane.org/gmane.linux.kernel.mm/136738Cc Benjamin Herrenschmidt <[email protected]>Cc Michael Ellerman <[email protected]>Cc Paul Mackerras <[email protected]>Cc Alexey Kardashevskiy <[email protected]>Signed-off-by Balbir Singh <[email protected]>--- arch/powerpc/include/asm/mmu_context.h | 1 + arch/powerpc/mm/mmu_context_iommu.c | 81 ++++++++++++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 4 deletions(-)arch/powerpc/include/asm/mmu_context.h +0
-0@@ -18,6 +18,7 @@ extern void destroy_context(struct mm_struct *mm);#ifdef CONFIG_SPAPR_TCE_IOMMU struct mm_iommu_table_group_mem_t ;
Quoted 4 lines
arch/powerpc/include/asm/mmu_context.h extern void destroy_context(struct mm_struct *mm); · line 21
Quoted 1 line
arch/powerpc/include/asm/mmu_context.h +1
-0+extern int isolate_lru_page (struct page *page);/* from internal.h */ Small nit, cant we just add "
mm/internal.h" header here with full path ?
I did not think it was worth including it here
Quoted 35 lines
Quoted 35 lines
arch/powerpc/include/asm/mmu_context.h +0
-0extern bool mm_iommu_preregistered (void );extern long mm_iommu_get (unsigned long ua,unsigned long entries,struct mm_iommu_table_group_mem_t **pmem);arch/powerpc/mm/mmu_context_iommu.c +17
-0@@ -15,6 +15,9 @@#include <linux/rculist.h> #include <linux/vmalloc.h> #include <linux/mutex.h> +#include <linux/migrate.h> +#include <linux/hugetlb.h> +#include <linux/swap.h> #include <asm/mmu_context.h> static DEFINE_MUTEX (mem_list_mutex);@@ -72,6 +75,55 @@ bool mm_iommu_preregistered(void) }EXPORT_SYMBOL_GPL (mm_iommu_preregistered); +/* +* Taken from alloc_migrate_target with changes to remove CMA allocations +*/ +struct page *new_iommu_non_cma_page (struct page *page,unsigned long private, +int **resultp) +{ +gfp_t gfp_mask =GFP_USER ; +struct page *new_page; + +if (PageHuge (page) ||PageTransHuge (page) ||PageCompound (page)) +return NULL ; + +if (PageHighMem (page)) + gfp_mask |= __GFP_HIGHMEM;
Quoted 8 lines
arch/powerpc/mm/mmu_context_iommu.c bool mm_iommu_preregistered(void) · line 96
Quoted 5 lines
arch/powerpc/mm/mmu_context_iommu.c +5
-0+ +/* +* We don't want the allocation to force an OOM if possibe +*/ + new_page =alloc_page (gfp_mask | __GFP_NORETRY | __GFP_NOWARN);So what guarantees that the new page too wont come from
MIGRATE_CMApage block ? Is absence of__GFP_MOVABLEflag enough.
I think so, that is what I am relying on and checked for
Also should not
Quoted 3 lines
we be checking that migrate type of the new allocated page is indeed not
MIGRATE_CMA?
I don't think that is required, may be I can do a VM_WARN_ON for debugging
Balbir Singh.
Michael Ellerman
AppliedQuoted 15 lines · Balbir Singh
When PCI Device pass-through is enabled via VFIO, KVM-PPC will pin pages using
get_user_pages_fast(). One of the downsides of the pinning is that the page could be in CMA region. The CMA region is used for other allocations like the hash page table. Ideally we want the pinned pages to be from non CMA region.This patch (currently only for KVM PPC with VFIO) forcefully migrates the pages out (huge pages are omitted for the moment). There are more efficient ways of doing this, but that might be elaborate and might impact a larger audience beyond just the kvm ppc implementation.
The magic is in
new_iommu_non_cma_page()which allocates the new page from a non CMA region.
Quoted 6 lines
I've tested the patches lightly at my end. The full solution requires migration of THP pages in the CMA region. That work will be done incrementally on top of this.
Signed-off-by Balbir Singh <[email protected]>
Applied to powerpc next, thanks.
https://git.kernel.org/powerpc/c/2e5bbb5461f138cac631fe21b4ad95
cheers
Quoted 67 lines · Balbir Singh
From: Balbir Singh <[email protected]>
Subject: [RESEND][v2][PATCH] KVM: PPC: Book3S HV: Migrate pinned pages out of CMAWhen PCI Device pass-through is enabled via VFIO, KVM-PPC will pin pages using
get_user_pages_fast(). One of the downsides of the pinning is that the page could be in CMA region. The CMA region is used for other allocations like the hash page table. Ideally we want the pinned pages to be from non CMA region.This patch (currently only for KVM PPC with VFIO) forcefully migrates the pages out (huge pages are omitted for the moment). There are more efficient ways of doing this, but that might be elaborate and might impact a larger audience beyond just the kvm ppc implementation.
The magic is in
new_iommu_non_cma_page()which allocates the new page from a non CMA region.I've tested the patches lightly at my end, but there might be bugs For example if after
lru_add_drain(), the page is not isolated is this a BUG?Previous discussion was at
http://permalink.gmane.org/gmane.linux.kernel.mm/136738Cc Benjamin Herrenschmidt <[email protected]>Cc Michael Ellerman <[email protected]>Cc Paul Mackerras <[email protected]>Cc Alexey Kardashevskiy <[email protected]>Signed-off-by Balbir Singh <[email protected]>--- arch/powerpc/include/asm/mmu_context.h | 1 + arch/powerpc/mm/mmu_context_iommu.c | 80 ++++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 4 deletions(-)arch/powerpc/include/asm/mmu_context.h +1
-0@@ -18,6 +18,7 @@ extern void destroy_context(struct mm_struct *mm);#ifdef CONFIG_SPAPR_TCE_IOMMU struct mm_iommu_table_group_mem_t ; +extern int isolate_lru_page (struct page *page);/* from internal.h */ extern bool mm_iommu_preregistered (void );extern long mm_iommu_get (unsigned long ua,unsigned long entries,struct mm_iommu_table_group_mem_t **pmem);arch/powerpc/mm/mmu_context_iommu.c +4
-0@@ -15,6 +15,9 @@#include <linux/rculist.h> #include <linux/vmalloc.h> #include <linux/mutex.h> +#include <linux/migrate.h> +#include <linux/hugetlb.h> +#include <linux/swap.h> #include <asm/mmu_context.h> static DEFINE_MUTEX (mem_list_mutex);@@ -72,6 +75,54 @@ bool mm_iommu_preregistered(void) }EXPORT_SYMBOL_GPL (mm_iommu_preregistered); +/*
arch/powerpc/mm/mmu_context_iommu.c bool mm_iommu_preregistered(void) · line 88
Quoted 10 lines
arch/powerpc/mm/mmu_context_iommu.c +10
-0+* Taken from alloc_migrate_target with changes to remove CMA allocations +*/ +struct page *new_iommu_non_cma_page (struct page *page,unsigned long private, +int **resultp) +{ +gfp_t gfp_mask =GFP_USER ; +struct page *new_page; + +if (PageHuge (page) ||PageTransHuge (page) ||PageCompound (page)) +return NULL ;
Doesn't a PageCompound check cover all ?
Quoted 11 lines
arch/powerpc/mm/mmu_context_iommu.c +11
-0+ +if (PageHighMem (page)) + gfp_mask |= __GFP_HIGHMEM; + +/* +* We don't want the allocation to force an OOM if possibe +*/ + new_page =alloc_page (gfp_mask | __GFP_NORETRY | __GFP_NOWARN); +return new_page; +} +
arch/powerpc/mm/mmu_context_iommu.c bool mm_iommu_preregistered(void) · line 109
Quoted 10 lines
arch/powerpc/mm/mmu_context_iommu.c +10
-0+static int mm_iommu_move_page_from_cma (struct page *page) +{ +int ret; +LIST_HEAD (cma_migrate_pages); + +/* Ignore huge pages for now */ +if (PageHuge (page) ||PageTransHuge (page) ||PageCompound (page)) +return -EBUSY ; + +lru_add_drain ();
I guess I asked this last time. Shouldn't this be lru_add_drain_all() ? What if the page is in other cpu's pagevec ?
arch/powerpc/mm/mmu_context_iommu.c bool mm_iommu_preregistered(void) · line 114
Quoted 5 lines
arch/powerpc/mm/mmu_context_iommu.c +5
-0+ ret =isolate_lru_page (page); +if (ret) +get_page (page);/* Potential BUG? */ + +list_add (&page->lru, &cma_migrate_pages);
Is that correct ? if we failed the isolate_lru_page(), can we be sure we are not on lru at all ? ie, what if the page was on other cpu pagevec ?
arch/powerpc/mm/mmu_context_iommu.c bool mm_iommu_preregistered(void) · line 116
Quoted 2 lines
arch/powerpc/mm/mmu_context_iommu.c +2
-0+put_page (page);/* Drop the gup reference */ +
Where is get user page (gup) here ? . I guess you mean drop the reference taken above ?
arch/powerpc/mm/mmu_context_iommu.c bool mm_iommu_preregistered(void) · line 125
Quoted 9 lines
arch/powerpc/mm/mmu_context_iommu.c +9
-0+ ret =migrate_pages (&cma_migrate_pages, new_iommu_non_cma_page, +NULL ,0 ,MIGRATE_SYNC ,MR_CMA ); +if (ret) { +if (!list_empty (&cma_migrate_pages)) +putback_movable_pages (&cma_migrate_pages); + } +return 0 ; +} +
I guess the plan was to not do it one page at a time and switch this to list of pages which we need to migrate. Any reason why that is not tried ?
Quoted 52 lines
arch/powerpc/mm/mmu_context_iommu.c +25
-4long mm_iommu_get (unsigned long ua,unsigned long entries,struct mm_iommu_table_group_mem_t **pmem) {@@ -124,15 +175,36 @@ long mm_iommu_get(unsigned long ua, unsigned long entries,for (i =0 ; i < entries; ++i) {if (1 !=get_user_pages_fast (ua + (i <<PAGE_SHIFT ),1 /* pages */ ,1 /* iswrite */ , &page)) { + ret = -EFAULT ;for (j =0 ; j < i; ++j) -put_page (pfn_to_page ( - mem->hpas[j] >>PAGE_SHIFT )); +put_page (pfn_to_page (mem->hpas[j] >> +PAGE_SHIFT ));vfree (mem->hpas);kfree (mem); - ret = -EFAULT ; goto unlock_exit; } - +/* +* If we get a page from the CMA zone, since we are going to +* be pinning these entries, we might as well move them out +* of the CMA zone if possible. NOTE: faulting in + migration +* can be expensive. Batching can be considered later +*/ +if (get_pageblock_migratetype (page) ==MIGRATE_CMA ) { +if (mm_iommu_move_page_from_cma (page)) + goto populate; +if (1 !=get_user_pages_fast (ua + (i <<PAGE_SHIFT ), +1 /* pages */ ,1 /* iswrite */ , + &page)) { + ret = -EFAULT ; +for (j =0 ; j < i; ++j) +put_page (pfn_to_page (mem->hpas[j] >> +PAGE_SHIFT )); +vfree (mem->hpas); +kfree (mem); + goto unlock_exit; + } + } +populate: mem->hpas[i] =page_to_pfn (page) <<PAGE_SHIFT ; }Signature · 7 lines
2.5.5 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
-aneesh
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 68 lines · Aneesh Kumar K.V
Quoted 66 lines · Balbir Singh
From: Balbir Singh <[email protected]>
Subject: [RESEND][v2][PATCH] KVM: PPC: Book3S HV: Migrate pinned pages out of CMAWhen PCI Device pass-through is enabled via VFIO, KVM-PPC will pin pages using
get_user_pages_fast(). One of the downsides of the pinning is that the page could be in CMA region. The CMA region is used for other allocations like the hash page table. Ideally we want the pinned pages to be from non CMA region.This patch (currently only for KVM PPC with VFIO) forcefully migrates the pages out (huge pages are omitted for the moment). There are more efficient ways of doing this, but that might be elaborate and might impact a larger audience beyond just the kvm ppc implementation.
The magic is in
new_iommu_non_cma_page()which allocates the new page from a non CMA region.I've tested the patches lightly at my end, but there might be bugs For example if after
lru_add_drain(), the page is not isolated is this a BUG?Previous discussion was at
http://permalink.gmane.org/gmane.linux.kernel.mm/136738Cc Benjamin Herrenschmidt <[email protected]>Cc Michael Ellerman <[email protected]>Cc Paul Mackerras <[email protected]>Cc Alexey Kardashevskiy <[email protected]>Signed-off-by Balbir Singh <[email protected]>--- arch/powerpc/include/asm/mmu_context.h | 1 + arch/powerpc/mm/mmu_context_iommu.c | 80 ++++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 4 deletions(-)arch/powerpc/include/asm/mmu_context.h +1
-0@@ -18,6 +18,7 @@ extern void destroy_context(struct mm_struct *mm);#ifdef CONFIG_SPAPR_TCE_IOMMU struct mm_iommu_table_group_mem_t ; +extern int isolate_lru_page (struct page *page);/* from internal.h */ extern bool mm_iommu_preregistered (void );extern long mm_iommu_get (unsigned long ua,unsigned long entries,struct mm_iommu_table_group_mem_t **pmem);arch/powerpc/mm/mmu_context_iommu.c +3
-0@@ -15,6 +15,9 @@#include <linux/rculist.h> #include <linux/vmalloc.h> #include <linux/mutex.h> +#include <linux/migrate.h> +#include <linux/hugetlb.h> +#include <linux/swap.h> #include <asm/mmu_context.h> static DEFINE_MUTEX (mem_list_mutex);@@ -72,6 +75,54 @@ bool mm_iommu_preregistered(void) }EXPORT_SYMBOL_GPL (mm_iommu_preregistered);
Quoted 13 lines
arch/powerpc/mm/mmu_context_iommu.c bool mm_iommu_preregistered(void) · line 88
Quoted 11 lines
arch/powerpc/mm/mmu_context_iommu.c +11
-0+/* +* Taken from alloc_migrate_target with changes to remove CMA allocations +*/ +struct page *new_iommu_non_cma_page (struct page *page,unsigned long private, +int **resultp) +{ +gfp_t gfp_mask =GFP_USER ; +struct page *new_page; + +if (PageHuge (page) ||PageTransHuge (page) ||PageCompound (page)) +return NULL ;Doesn't a PageCompound check cover all ?
Yes, I was being overly conservative with the checks
Quoted 18 lines
Quoted 18 lines
arch/powerpc/mm/mmu_context_iommu.c +16
-0+ +if (PageHighMem (page)) + gfp_mask |= __GFP_HIGHMEM; + +/* +* We don't want the allocation to force an OOM if possibe +*/ + new_page =alloc_page (gfp_mask | __GFP_NORETRY | __GFP_NOWARN); +return new_page; +} + +static int mm_iommu_move_page_from_cma (struct page *page) +{ +int ret; +LIST_HEAD (cma_migrate_pages); +
Quoted 8 lines
arch/powerpc/mm/mmu_context_iommu.c bool mm_iommu_preregistered(void) · line 109
Quoted 5 lines
arch/powerpc/mm/mmu_context_iommu.c +5
-0+/* Ignore huge pages for now */ +if (PageHuge (page) ||PageTransHuge (page) ||PageCompound (page)) +return -EBUSY ; + +lru_add_drain ();I guess I asked this last time. Shouldn't this be
lru_add_drain_all()? What if the page is in other cpu's pagevec ?
lru_add_drain_all() is too expensive for a per-page migration. This is best effort. If it is on the pagevec of another CPU, we skip it -- see v3
Quoted 12 lines
arch/powerpc/mm/mmu_context_iommu.c bool mm_iommu_preregistered(void) · line 114
Quoted 7 lines
arch/powerpc/mm/mmu_context_iommu.c +5
-0+ ret =isolate_lru_page (page); +if (ret) +get_page (page);/* Potential BUG? */ + +list_add (&page->lru, &cma_migrate_pages);Is that correct ? if we failed the
isolate_lru_page(), can we be sure we are not on lru at all ? ie, what if the page was on other cpu pagevec ?
Fixed in v3
Quoted 6 lines
arch/powerpc/mm/mmu_context_iommu.c bool mm_iommu_preregistered(void) · line 116
Quoted 2 lines
arch/powerpc/mm/mmu_context_iommu.c +2
-0+put_page (page);/* Drop the gup reference */ +Where is get user page (gup) here ? . I guess you mean drop the reference taken above ?
I say gup, because we'll do gup after this point if migration fails and that we reacquire the reference lost here.
Quoted 14 lines
arch/powerpc/mm/mmu_context_iommu.c bool mm_iommu_preregistered(void) · line 125
Quoted 10 lines
arch/powerpc/mm/mmu_context_iommu.c +9
-0+ ret =migrate_pages (&cma_migrate_pages, new_iommu_non_cma_page, +NULL ,0 ,MIGRATE_SYNC ,MR_CMA ); +if (ret) { +if (!list_empty (&cma_migrate_pages)) +putback_movable_pages (&cma_migrate_pages); + } +return 0 ; +} +I guess the plan was to not do it one page at a time and switch this to list of pages which we need to migrate. Any reason why that is not tried ?
Yes, it is a TODO. Here is my order of preference
1. get this in
2. Get THP migration in -- larger workset
3. Do page aggregation for both 1 and 2
Balbir Singh.