Message ID | 20201203050812.5234-1-alistair@popple.id.au (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | powerpc/book3s_hv_uvmem: Check for failed page migration | expand |
Context | Check | Description |
---|---|---|
snowpatch_ozlabs/apply_patch | success | Successfully applied on branch powerpc/merge (a1aeabd25a36d9e019381278e543e2d538dd44a7) |
snowpatch_ozlabs/build-ppc64le | success | Build succeeded |
snowpatch_ozlabs/build-ppc64be | success | Build succeeded |
snowpatch_ozlabs/build-ppc64e | success | Build succeeded |
snowpatch_ozlabs/build-pmac32 | success | Build succeeded |
snowpatch_ozlabs/checkpatch | success | total: 0 errors, 0 warnings, 0 checks, 19 lines checked |
snowpatch_ozlabs/needsstable | success | Patch has no Fixes tags |
On Thu, Dec 03, 2020 at 04:08:12PM +1100, Alistair Popple wrote: > migrate_vma_pages() may still clear MIGRATE_PFN_MIGRATE on pages which > are not able to be migrated. Drivers may safely copy data prior to > calling migrate_vma_pages() however a remote mapping must not be > established until after migrate_vma_pages() has returned as the > migration could still fail. > > UV_PAGE_IN_in both copies and maps the data page, therefore it should > only be called after checking the results of migrate_vma_pages(). > > Signed-off-by: Alistair Popple <alistair@popple.id.au> > --- > arch/powerpc/kvm/book3s_hv_uvmem.c | 7 ++++--- > 1 file changed, 4 insertions(+), 3 deletions(-) > > diff --git a/arch/powerpc/kvm/book3s_hv_uvmem.c b/arch/powerpc/kvm/book3s_hv_uvmem.c > index 84e5a2dc8be5..08aa6a90c525 100644 > --- a/arch/powerpc/kvm/book3s_hv_uvmem.c > +++ b/arch/powerpc/kvm/book3s_hv_uvmem.c > @@ -762,7 +762,10 @@ static int kvmppc_svm_page_in(struct vm_area_struct *vma, > goto out_finalize; > } > > - if (pagein) { > + *mig.dst = migrate_pfn(page_to_pfn(dpage)) | MIGRATE_PFN_LOCKED; > + migrate_vma_pages(&mig); > + > + if ((*mig.src & MIGRATE_PFN_MIGRATE) && pagein) { > pfn = *mig.src >> MIGRATE_PFN_SHIFT; > spage = migrate_pfn_to_page(*mig.src); > if (spage) { > @@ -773,8 +776,6 @@ static int kvmppc_svm_page_in(struct vm_area_struct *vma, > } > } > > - *mig.dst = migrate_pfn(page_to_pfn(dpage)) | MIGRATE_PFN_LOCKED; > - migrate_vma_pages(&mig); > out_finalize: > migrate_vma_finalize(&mig); > return ret; Reviewed-by: Bharata B Rao <bharata@linux.ibm.com> Did you actually hit this scenario with secure VMs where a UV-paged-in page was later found to be not migratable? Regards, Bharata.
On Fri, Dec 04, 2020 at 03:48:41PM +0530, Bharata B Rao wrote: > On Thu, Dec 03, 2020 at 04:08:12PM +1100, Alistair Popple wrote: > > migrate_vma_pages() may still clear MIGRATE_PFN_MIGRATE on pages which > > are not able to be migrated. Drivers may safely copy data prior to > > calling migrate_vma_pages() however a remote mapping must not be > > established until after migrate_vma_pages() has returned as the > > migration could still fail. > > > > UV_PAGE_IN_in both copies and maps the data page, therefore it should > > only be called after checking the results of migrate_vma_pages(). > > > > Signed-off-by: Alistair Popple <alistair@popple.id.au> > > --- > > arch/powerpc/kvm/book3s_hv_uvmem.c | 7 ++++--- > > 1 file changed, 4 insertions(+), 3 deletions(-) > > > > diff --git a/arch/powerpc/kvm/book3s_hv_uvmem.c b/arch/powerpc/kvm/book3s_hv_uvmem.c > > index 84e5a2dc8be5..08aa6a90c525 100644 > > --- a/arch/powerpc/kvm/book3s_hv_uvmem.c > > +++ b/arch/powerpc/kvm/book3s_hv_uvmem.c > > @@ -762,7 +762,10 @@ static int kvmppc_svm_page_in(struct vm_area_struct *vma, > > goto out_finalize; > > } > > > > - if (pagein) { > > + *mig.dst = migrate_pfn(page_to_pfn(dpage)) | MIGRATE_PFN_LOCKED; > > + migrate_vma_pages(&mig); > > + > > + if ((*mig.src & MIGRATE_PFN_MIGRATE) && pagein) { > > pfn = *mig.src >> MIGRATE_PFN_SHIFT; > > spage = migrate_pfn_to_page(*mig.src); > > if (spage) { > > @@ -773,8 +776,6 @@ static int kvmppc_svm_page_in(struct vm_area_struct *vma, > > } > > } > > > > - *mig.dst = migrate_pfn(page_to_pfn(dpage)) | MIGRATE_PFN_LOCKED; > > - migrate_vma_pages(&mig); > > out_finalize: > > migrate_vma_finalize(&mig); > > return ret; This patch certainly looks like the problem, that has been hurting us for a while. Let me run this patch through my SVM tests. Looks very promising. BTW: The code does a similar thing while paging out. It pages out from the UV, and then does the migration. Is there a bug there aswell? RP
On Friday, 4 December 2020 9:18:41 PM AEDT Bharata B Rao wrote: > > Reviewed-by: Bharata B Rao <bharata@linux.ibm.com> > > Did you actually hit this scenario with secure VMs where a UV-paged-in > page was later found to be not migratable? No, this was found by inspection. I have no way of testing this but we had a similar issue in Nouveau and I think you would have a similar issue here although it might be hard to hit. migrate_vma_pages() will fail a page migration if a CPU thread has raced and established a non-zero page PTE for the address. See migrate_vma_insert_page() for the implementation. It will also fail if something else has taken a reference on the page after calling migrate_vma_setup(), but that is less likely as any existing pages will have been isolated. - Alistair > Regards, > Bharata. >
On Saturday, 5 December 2020 3:52:44 AM AEDT Ram Pai wrote: > On Fri, Dec 04, 2020 at 03:48:41PM +0530, Bharata B Rao wrote: > > On Thu, Dec 03, 2020 at 04:08:12PM +1100, Alistair Popple wrote: > This patch certainly looks like the problem, that has been hurting > us for a while. Let me run this patch through my SVM tests. Looks very > promising. > > BTW: The code does a similar thing while paging out. It pages out from the > UV, and then does the migration. Is there a bug there aswell? As specified the migrate_pages_vma() API can fail to migrate device private pages. However the fix was less obvious to me, and in practice I don't think it will ever fail for device private pages as you don't have the same races to establish the page and device private pages can't be pinned. It might be worth adding some kind of warning though in case this ever changes. - Alistair > RP >
On Thu, Dec 03, 2020 at 04:08:12PM +1100, Alistair Popple wrote: > migrate_vma_pages() may still clear MIGRATE_PFN_MIGRATE on pages which > are not able to be migrated. Drivers may safely copy data prior to > calling migrate_vma_pages() however a remote mapping must not be > established until after migrate_vma_pages() has returned as the > migration could still fail. > > UV_PAGE_IN_in both copies and maps the data page, therefore it should > only be called after checking the results of migrate_vma_pages(). > > Signed-off-by: Alistair Popple <alistair@popple.id.au> > --- > arch/powerpc/kvm/book3s_hv_uvmem.c | 7 ++++--- > 1 file changed, 4 insertions(+), 3 deletions(-) > > diff --git a/arch/powerpc/kvm/book3s_hv_uvmem.c b/arch/powerpc/kvm/book3s_hv_uvmem.c > index 84e5a2dc8be5..08aa6a90c525 100644 > --- a/arch/powerpc/kvm/book3s_hv_uvmem.c > +++ b/arch/powerpc/kvm/book3s_hv_uvmem.c > @@ -762,7 +762,10 @@ static int kvmppc_svm_page_in(struct vm_area_struct *vma, > goto out_finalize; > } > > - if (pagein) { > + *mig.dst = migrate_pfn(page_to_pfn(dpage)) | MIGRATE_PFN_LOCKED; > + migrate_vma_pages(&mig); > + > + if ((*mig.src & MIGRATE_PFN_MIGRATE) && pagein) { > pfn = *mig.src >> MIGRATE_PFN_SHIFT; > spage = migrate_pfn_to_page(*mig.src); > if (spage) { > @@ -773,8 +776,6 @@ static int kvmppc_svm_page_in(struct vm_area_struct *vma, > } > } > > - *mig.dst = migrate_pfn(page_to_pfn(dpage)) | MIGRATE_PFN_LOCKED; > - migrate_vma_pages(&mig); > out_finalize: > migrate_vma_finalize(&mig); > return ret; Though this patch did not solve the specific problem, I am running into, my tests did not expose any regression. Tested-by: Ram Pai <linuxram@us.ibm.com> Reviewed-by: Ram Pai <linuxram@us.ibm.com>
diff --git a/arch/powerpc/kvm/book3s_hv_uvmem.c b/arch/powerpc/kvm/book3s_hv_uvmem.c index 84e5a2dc8be5..08aa6a90c525 100644 --- a/arch/powerpc/kvm/book3s_hv_uvmem.c +++ b/arch/powerpc/kvm/book3s_hv_uvmem.c @@ -762,7 +762,10 @@ static int kvmppc_svm_page_in(struct vm_area_struct *vma, goto out_finalize; } - if (pagein) { + *mig.dst = migrate_pfn(page_to_pfn(dpage)) | MIGRATE_PFN_LOCKED; + migrate_vma_pages(&mig); + + if ((*mig.src & MIGRATE_PFN_MIGRATE) && pagein) { pfn = *mig.src >> MIGRATE_PFN_SHIFT; spage = migrate_pfn_to_page(*mig.src); if (spage) { @@ -773,8 +776,6 @@ static int kvmppc_svm_page_in(struct vm_area_struct *vma, } } - *mig.dst = migrate_pfn(page_to_pfn(dpage)) | MIGRATE_PFN_LOCKED; - migrate_vma_pages(&mig); out_finalize: migrate_vma_finalize(&mig); return ret;
migrate_vma_pages() may still clear MIGRATE_PFN_MIGRATE on pages which are not able to be migrated. Drivers may safely copy data prior to calling migrate_vma_pages() however a remote mapping must not be established until after migrate_vma_pages() has returned as the migration could still fail. UV_PAGE_IN_in both copies and maps the data page, therefore it should only be called after checking the results of migrate_vma_pages(). Signed-off-by: Alistair Popple <alistair@popple.id.au> --- arch/powerpc/kvm/book3s_hv_uvmem.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)