On Thu, 31 Mar 2022 15:34:42 +0200 Janosch Frank <frankja@xxxxxxxxxxxxx> wrote: > On 3/30/22 14:25, Claudio Imbrenda wrote: > > When ptep_get_and_clear_full is called for a mm teardown, we will now > > attempt to destroy the secure pages. This will be faster than export. > > > > In case it was not a teardown, or if for some reason the destroy page > > UVC failed, we try with an export page, like before. > > > > Signed-off-by: Claudio Imbrenda <imbrenda@xxxxxxxxxxxxx> > > Acked-by: Janosch Frank <frankja@xxxxxxxxxxxxx> > > --- > > arch/s390/include/asm/pgtable.h | 18 +++++++++++++++--- > > 1 file changed, 15 insertions(+), 3 deletions(-) > > > > diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h > > index 23ca0d8e058a..72544a1b4a68 100644 > > --- a/arch/s390/include/asm/pgtable.h > > +++ b/arch/s390/include/asm/pgtable.h > > @@ -1118,9 +1118,21 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, > > } else { > > res = ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID)); > > } > > - /* At this point the reference through the mapping is still present */ > > - if (mm_is_protected(mm) && pte_present(res)) > > - uv_convert_owned_from_secure(pte_val(res) & PAGE_MASK); > > + /* Nothing to do */ > > + if (!mm_is_protected(mm) || !pte_present(res)) > > + return res; > > + /* > > + * At this point the reference through the mapping is still present. > > That's the case because we zap ptes within a mm that's still existing, > right? The mm will be deleted after we have unmapped the memory. not exactly, the mm can exist without pages. the reference is there because when we enter the function, there is still a pointer to the page (the PTE itself), the page is still reachable, and therefore its reference count cannot be less than 1. when we leave the function, there is no more mapping for the page (that's the point of the function after all), and only then the counter can be decremented. if you look at zap_pte_range in mm/memory.c, you see that we call ptep_get_and_clear_full first, and then a few lines below we call __tlb_remove_page which in the end calls put_page on that page. > > > > + * The notifier should have destroyed all protected vCPUs at this > > + * point, so the destroy should be successful. > > + */ > > + if (full && !uv_destroy_owned_page(pte_val(res) & PAGE_MASK)) > > + return res; > > + /* > > + * But if something went wrong and the pages could not be destroyed, > > + * the slower export is used as fallback instead. > > + */ > > + uv_convert_owned_from_secure(pte_val(res) & PAGE_MASK); > > return res; > > } > > >