* [PATCH] powerpc: convert put_page() to put_user_page*()
@ 2019-08-05 2:38 john.hubbard
2019-08-07 23:24 ` kbuild test robot
0 siblings, 1 reply; 3+ messages in thread
From: john.hubbard @ 2019-08-05 2:38 UTC (permalink / raw)
To: Andrew Morton
Cc: Christoph Hellwig, Ira Weiny, Jan Kara, Jason Gunthorpe,
Jerome Glisse, LKML, linux-mm, linux-fsdevel, John Hubbard,
Benjamin Herrenschmidt, Christoph Hellwig, Michael Ellerman,
linuxppc-dev
From: John Hubbard <jhubbard@nvidia.com>
For pages that were retained via get_user_pages*(), release those pages
via the new put_user_page*() routines, instead of via put_page() or
release_pages().
This is part a tree-wide conversion, as described in commit fc1d8e7cca2d
("mm: introduce put_user_page*(), placeholder versions").
Note that this effectively changes the code's behavior in
mm_iommu_unpin(): it now ultimately calls set_page_dirty_lock(),
instead of set_page_dirty(). This is probably more accurate.
As Christoph Hellwig put it, "set_page_dirty() is only safe if we are
dealing with a file backed page where we have reference on the inode it
hangs off." [1]
[1] https://lore.kernel.org/r/20190723153640.GB720@lst.de
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
---
arch/powerpc/kvm/book3s_64_mmu_hv.c | 4 ++--
arch/powerpc/kvm/book3s_64_mmu_radix.c | 19 ++++++++++++++-----
arch/powerpc/kvm/e500_mmu.c | 3 +--
arch/powerpc/mm/book3s64/iommu_api.c | 11 +++++------
4 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index 9a75f0e1933b..18646b738ce1 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -731,7 +731,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
* we have to drop the reference on the correct tail
* page to match the get inside gup()
*/
- put_page(pages[0]);
+ put_user_page(pages[0]);
}
return ret;
@@ -1206,7 +1206,7 @@ void kvmppc_unpin_guest_page(struct kvm *kvm, void *va, unsigned long gpa,
unsigned long gfn;
int srcu_idx;
- put_page(page);
+ put_user_page(page);
if (!dirty)
return;
diff --git a/arch/powerpc/kvm/book3s_64_mmu_radix.c b/arch/powerpc/kvm/book3s_64_mmu_radix.c
index 2d415c36a61d..f53273fbfa2d 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_radix.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_radix.c
@@ -821,8 +821,12 @@ int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu,
*/
if (!ptep) {
local_irq_enable();
- if (page)
- put_page(page);
+ if (page) {
+ if (upgrade_write)
+ put_user_page(page);
+ else
+ put_page(page);
+ }
return RESUME_GUEST;
}
pte = *ptep;
@@ -870,9 +874,14 @@ int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu,
*levelp = level;
if (page) {
- if (!ret && (pte_val(pte) & _PAGE_WRITE))
- set_page_dirty_lock(page);
- put_page(page);
+ bool dirty = !ret && (pte_val(pte) & _PAGE_WRITE);
+ if (upgrade_write)
+ put_user_pages_dirty_lock(&page, 1, dirty);
+ else {
+ if (dirty)
+ set_page_dirty_lock(page);
+ put_page(page);
+ }
}
/* Increment number of large pages if we (successfully) inserted one */
diff --git a/arch/powerpc/kvm/e500_mmu.c b/arch/powerpc/kvm/e500_mmu.c
index 2d910b87e441..67bb8d59d4b1 100644
--- a/arch/powerpc/kvm/e500_mmu.c
+++ b/arch/powerpc/kvm/e500_mmu.c
@@ -850,8 +850,7 @@ int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
free_privs_first:
kfree(privs[0]);
put_pages:
- for (i = 0; i < num_pages; i++)
- put_page(pages[i]);
+ put_user_pages(pages, num_pages);
free_pages:
kfree(pages);
return ret;
diff --git a/arch/powerpc/mm/book3s64/iommu_api.c b/arch/powerpc/mm/book3s64/iommu_api.c
index b056cae3388b..e126193ba295 100644
--- a/arch/powerpc/mm/book3s64/iommu_api.c
+++ b/arch/powerpc/mm/book3s64/iommu_api.c
@@ -170,9 +170,8 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, unsigned long ua,
return 0;
free_exit:
- /* free the reference taken */
- for (i = 0; i < pinned; i++)
- put_page(mem->hpages[i]);
+ /* free the references taken */
+ put_user_pages(mem->hpages, pinned);
vfree(mem->hpas);
kfree(mem);
@@ -203,6 +202,7 @@ static void mm_iommu_unpin(struct mm_iommu_table_group_mem_t *mem)
{
long i;
struct page *page = NULL;
+ bool dirty = false;
if (!mem->hpas)
return;
@@ -215,10 +215,9 @@ static void mm_iommu_unpin(struct mm_iommu_table_group_mem_t *mem)
if (!page)
continue;
- if (mem->hpas[i] & MM_IOMMU_TABLE_GROUP_PAGE_DIRTY)
- SetPageDirty(page);
+ dirty = mem->hpas[i] & MM_IOMMU_TABLE_GROUP_PAGE_DIRTY;
- put_page(page);
+ put_user_pages_dirty_lock(&page, 1, dirty);
mem->hpas[i] = 0;
}
}
--
2.22.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] powerpc: convert put_page() to put_user_page*()
2019-08-05 2:38 [PATCH] powerpc: convert put_page() to put_user_page*() john.hubbard
@ 2019-08-07 23:24 ` kbuild test robot
2019-08-07 23:34 ` John Hubbard
0 siblings, 1 reply; 3+ messages in thread
From: kbuild test robot @ 2019-08-07 23:24 UTC (permalink / raw)
To: john.hubbard
Cc: kbuild-all, Andrew Morton, Christoph Hellwig, Ira Weiny,
Jan Kara, Jason Gunthorpe, Jerome Glisse, LKML, linux-mm,
linux-fsdevel, John Hubbard, Benjamin Herrenschmidt,
Christoph Hellwig, Michael Ellerman, linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 6865 bytes --]
Hi,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on linus/master]
[cannot apply to v5.3-rc3 next-20190807]
[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/john-hubbard-gmail-com/powerpc-convert-put_page-to-put_user_page/20190805-132131
config: powerpc-allmodconfig (attached as .config)
compiler: powerpc64-linux-gcc (GCC) 7.4.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=7.4.0 make.cross ARCH=powerpc
If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
arch/powerpc/kvm/book3s_64_mmu_radix.c: In function 'kvmppc_book3s_instantiate_page':
>> arch/powerpc/kvm/book3s_64_mmu_radix.c:879:4: error: too many arguments to function 'put_user_pages_dirty_lock'
put_user_pages_dirty_lock(&page, 1, dirty);
^~~~~~~~~~~~~~~~~~~~~~~~~
In file included from arch/powerpc/include/asm/io.h:29:0,
from include/linux/io.h:13,
from include/linux/irq.h:20,
from arch/powerpc/include/asm/hardirq.h:6,
from include/linux/hardirq.h:9,
from include/linux/kvm_host.h:7,
from arch/powerpc/kvm/book3s_64_mmu_radix.c:10:
include/linux/mm.h:1061:6: note: declared here
void put_user_pages_dirty_lock(struct page **pages, unsigned long npages);
^~~~~~~~~~~~~~~~~~~~~~~~~
--
arch/powerpc/mm/book3s64/iommu_api.c: In function 'mm_iommu_unpin':
>> arch/powerpc/mm/book3s64/iommu_api.c:220:3: error: too many arguments to function 'put_user_pages_dirty_lock'
put_user_pages_dirty_lock(&page, 1, dirty);
^~~~~~~~~~~~~~~~~~~~~~~~~
In file included from include/linux/migrate.h:5:0,
from arch/powerpc/mm/book3s64/iommu_api.c:13:
include/linux/mm.h:1061:6: note: declared here
void put_user_pages_dirty_lock(struct page **pages, unsigned long npages);
^~~~~~~~~~~~~~~~~~~~~~~~~
vim +/put_user_pages_dirty_lock +879 arch/powerpc/kvm/book3s_64_mmu_radix.c
765
766 int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu,
767 unsigned long gpa,
768 struct kvm_memory_slot *memslot,
769 bool writing, bool kvm_ro,
770 pte_t *inserted_pte, unsigned int *levelp)
771 {
772 struct kvm *kvm = vcpu->kvm;
773 struct page *page = NULL;
774 unsigned long mmu_seq;
775 unsigned long hva, gfn = gpa >> PAGE_SHIFT;
776 bool upgrade_write = false;
777 bool *upgrade_p = &upgrade_write;
778 pte_t pte, *ptep;
779 unsigned int shift, level;
780 int ret;
781 bool large_enable;
782
783 /* used to check for invalidations in progress */
784 mmu_seq = kvm->mmu_notifier_seq;
785 smp_rmb();
786
787 /*
788 * Do a fast check first, since __gfn_to_pfn_memslot doesn't
789 * do it with !atomic && !async, which is how we call it.
790 * We always ask for write permission since the common case
791 * is that the page is writable.
792 */
793 hva = gfn_to_hva_memslot(memslot, gfn);
794 if (!kvm_ro && __get_user_pages_fast(hva, 1, 1, &page) == 1) {
795 upgrade_write = true;
796 } else {
797 unsigned long pfn;
798
799 /* Call KVM generic code to do the slow-path check */
800 pfn = __gfn_to_pfn_memslot(memslot, gfn, false, NULL,
801 writing, upgrade_p);
802 if (is_error_noslot_pfn(pfn))
803 return -EFAULT;
804 page = NULL;
805 if (pfn_valid(pfn)) {
806 page = pfn_to_page(pfn);
807 if (PageReserved(page))
808 page = NULL;
809 }
810 }
811
812 /*
813 * Read the PTE from the process' radix tree and use that
814 * so we get the shift and attribute bits.
815 */
816 local_irq_disable();
817 ptep = __find_linux_pte(vcpu->arch.pgdir, hva, NULL, &shift);
818 /*
819 * If the PTE disappeared temporarily due to a THP
820 * collapse, just return and let the guest try again.
821 */
822 if (!ptep) {
823 local_irq_enable();
824 if (page) {
825 if (upgrade_write)
826 put_user_page(page);
827 else
828 put_page(page);
829 }
830 return RESUME_GUEST;
831 }
832 pte = *ptep;
833 local_irq_enable();
834
835 /* If we're logging dirty pages, always map single pages */
836 large_enable = !(memslot->flags & KVM_MEM_LOG_DIRTY_PAGES);
837
838 /* Get pte level from shift/size */
839 if (large_enable && shift == PUD_SHIFT &&
840 (gpa & (PUD_SIZE - PAGE_SIZE)) ==
841 (hva & (PUD_SIZE - PAGE_SIZE))) {
842 level = 2;
843 } else if (large_enable && shift == PMD_SHIFT &&
844 (gpa & (PMD_SIZE - PAGE_SIZE)) ==
845 (hva & (PMD_SIZE - PAGE_SIZE))) {
846 level = 1;
847 } else {
848 level = 0;
849 if (shift > PAGE_SHIFT) {
850 /*
851 * If the pte maps more than one page, bring over
852 * bits from the virtual address to get the real
853 * address of the specific single page we want.
854 */
855 unsigned long rpnmask = (1ul << shift) - PAGE_SIZE;
856 pte = __pte(pte_val(pte) | (hva & rpnmask));
857 }
858 }
859
860 pte = __pte(pte_val(pte) | _PAGE_EXEC | _PAGE_ACCESSED);
861 if (writing || upgrade_write) {
862 if (pte_val(pte) & _PAGE_WRITE)
863 pte = __pte(pte_val(pte) | _PAGE_DIRTY);
864 } else {
865 pte = __pte(pte_val(pte) & ~(_PAGE_WRITE | _PAGE_DIRTY));
866 }
867
868 /* Allocate space in the tree and write the PTE */
869 ret = kvmppc_create_pte(kvm, kvm->arch.pgtable, pte, gpa, level,
870 mmu_seq, kvm->arch.lpid, NULL, NULL);
871 if (inserted_pte)
872 *inserted_pte = pte;
873 if (levelp)
874 *levelp = level;
875
876 if (page) {
877 bool dirty = !ret && (pte_val(pte) & _PAGE_WRITE);
878 if (upgrade_write)
> 879 put_user_pages_dirty_lock(&page, 1, dirty);
880 else {
881 if (dirty)
882 set_page_dirty_lock(page);
883 put_page(page);
884 }
885 }
886
887 /* Increment number of large pages if we (successfully) inserted one */
888 if (!ret) {
889 if (level == 1)
890 kvm->stat.num_2M_pages++;
891 else if (level == 2)
892 kvm->stat.num_1G_pages++;
893 }
894
895 return ret;
896 }
897
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 62277 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] powerpc: convert put_page() to put_user_page*()
2019-08-07 23:24 ` kbuild test robot
@ 2019-08-07 23:34 ` John Hubbard
0 siblings, 0 replies; 3+ messages in thread
From: John Hubbard @ 2019-08-07 23:34 UTC (permalink / raw)
To: kbuild test robot, john.hubbard
Cc: kbuild-all, Andrew Morton, Christoph Hellwig, Ira Weiny,
Jan Kara, Jason Gunthorpe, Jerome Glisse, LKML, linux-mm,
linux-fsdevel, Benjamin Herrenschmidt, Christoph Hellwig,
Michael Ellerman, linuxppc-dev
On 8/7/19 4:24 PM, kbuild test robot wrote:
> Hi,
>
> Thank you for the patch! Yet something to improve:
>
> [auto build test ERROR on linus/master]
> [cannot apply to v5.3-rc3 next-20190807]
> [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/john-hubbard-gmail-com/powerpc-convert-put_page-to-put_user_page/20190805-132131
> config: powerpc-allmodconfig (attached as .config)
> compiler: powerpc64-linux-gcc (GCC) 7.4.0
> reproduce:
> wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
> chmod +x ~/bin/make.cross
> # save the attached .config to linux build tree
> GCC_VERSION=7.4.0 make.cross ARCH=powerpc
>
> If you fix the issue, kindly add following tag
> Reported-by: kbuild test robot <lkp@intel.com>
>
> All errors (new ones prefixed by >>):
>
> arch/powerpc/kvm/book3s_64_mmu_radix.c: In function 'kvmppc_book3s_instantiate_page':
>>> arch/powerpc/kvm/book3s_64_mmu_radix.c:879:4: error: too many arguments to function 'put_user_pages_dirty_lock'
> put_user_pages_dirty_lock(&page, 1, dirty);
> ^~~~~~~~~~~~~~~~~~~~~~~~~
Yep, I should have included the prerequisite patch. But this is obsolete now,
please refer to the larger patchset instead:
https://lore.kernel.org/r/20190807013340.9706-1-jhubbard@nvidia.com
thanks,
--
John Hubbard
NVIDIA
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2019-08-08 0:31 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-05 2:38 [PATCH] powerpc: convert put_page() to put_user_page*() john.hubbard
2019-08-07 23:24 ` kbuild test robot
2019-08-07 23:34 ` John Hubbard
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).