Message ID | 20240412142120.220087-5-david@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | s390: PG_arch_1+folio cleanups for uv+hugetlb | expand |
On Fri, 12 Apr 2024 16:21:14 +0200 David Hildenbrand <david@redhat.com> wrote: > Now that make_folio_secure() may only set PG_arch_1 for small folios, > let's convert relevant remaining UV code to only work on (small) folios > and simply reject large folios early. This way, we'll never end up > touching PG_arch_1 on tail pages of a large folio in UV code. > > The folio_get()/folio_put() for functions that are documented to already > hold a folio reference look weird; likely they are required to make > concurrent gmap_make_secure() back off because the caller might only hold > an implicit reference due to the page mapping. So leave that alone for now. > > Signed-off-by: David Hildenbrand <david@redhat.com> Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com> > --- > arch/s390/include/asm/page.h | 2 ++ > arch/s390/kernel/uv.c | 41 ++++++++++++++++++++++-------------- > 2 files changed, 27 insertions(+), 16 deletions(-) > > diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h > index 9381879f7ecf..b64384872c0f 100644 > --- a/arch/s390/include/asm/page.h > +++ b/arch/s390/include/asm/page.h > @@ -214,7 +214,9 @@ static inline unsigned long __phys_addr(unsigned long x, bool is_31bit) > #define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT) > > #define phys_to_page(phys) pfn_to_page(phys_to_pfn(phys)) > +#define phys_to_folio(phys) page_folio(phys_to_page(phys)) > #define page_to_phys(page) pfn_to_phys(page_to_pfn(page)) > +#define folio_to_phys(page) pfn_to_phys(folio_pfn(folio)) > > static inline void *pfn_to_virt(unsigned long pfn) > { > diff --git a/arch/s390/kernel/uv.c b/arch/s390/kernel/uv.c > index 3c6d86e3e828..914dcec27329 100644 > --- a/arch/s390/kernel/uv.c > +++ b/arch/s390/kernel/uv.c > @@ -135,14 +135,18 @@ static int uv_destroy_page(unsigned long paddr) > */ > int uv_destroy_owned_page(unsigned long paddr) > { > - struct page *page = phys_to_page(paddr); > + struct folio *folio = phys_to_folio(paddr); > int rc; > > - get_page(page); > + /* See gmap_make_secure(): large folios cannot be secure */ > + if (unlikely(folio_test_large(folio))) > + return 0; > + > + folio_get(folio); > rc = uv_destroy_page(paddr); > if (!rc) > - clear_bit(PG_arch_1, &page->flags); > - put_page(page); > + clear_bit(PG_arch_1, &folio->flags); > + folio_put(folio); > return rc; > } > > @@ -170,14 +174,18 @@ int uv_convert_from_secure(unsigned long paddr) > */ > int uv_convert_owned_from_secure(unsigned long paddr) > { > - struct page *page = phys_to_page(paddr); > + struct folio *folio = phys_to_folio(paddr); > int rc; > > - get_page(page); > + /* See gmap_make_secure(): large folios cannot be secure */ > + if (unlikely(folio_test_large(folio))) > + return 0; > + > + folio_get(folio); > rc = uv_convert_from_secure(paddr); > if (!rc) > - clear_bit(PG_arch_1, &page->flags); > - put_page(page); > + clear_bit(PG_arch_1, &folio->flags); > + folio_put(folio); > return rc; > } > > @@ -479,33 +487,34 @@ EXPORT_SYMBOL_GPL(gmap_destroy_page); > */ > int arch_make_page_accessible(struct page *page) > { > + struct folio *folio = page_folio(page); > int rc = 0; > > - /* Hugepage cannot be protected, so nothing to do */ > - if (PageHuge(page)) > + /* See gmap_make_secure(): large folios cannot be secure */ > + if (unlikely(folio_test_large(folio))) > return 0; > > /* > * PG_arch_1 is used in 3 places: > * 1. for kernel page tables during early boot > * 2. for storage keys of huge pages and KVM > - * 3. As an indication that this page might be secure. This can > + * 3. As an indication that this small folio might be secure. This can > * overindicate, e.g. we set the bit before calling > * convert_to_secure. > * As secure pages are never huge, all 3 variants can co-exists. > */ > - if (!test_bit(PG_arch_1, &page->flags)) > + if (!test_bit(PG_arch_1, &folio->flags)) > return 0; > > - rc = uv_pin_shared(page_to_phys(page)); > + rc = uv_pin_shared(folio_to_phys(folio)); > if (!rc) { > - clear_bit(PG_arch_1, &page->flags); > + clear_bit(PG_arch_1, &folio->flags); > return 0; > } > > - rc = uv_convert_from_secure(page_to_phys(page)); > + rc = uv_convert_from_secure(folio_to_phys(folio)); > if (!rc) { > - clear_bit(PG_arch_1, &page->flags); > + clear_bit(PG_arch_1, &folio->flags); > return 0; > } >
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index 9381879f7ecf..b64384872c0f 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h @@ -214,7 +214,9 @@ static inline unsigned long __phys_addr(unsigned long x, bool is_31bit) #define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT) #define phys_to_page(phys) pfn_to_page(phys_to_pfn(phys)) +#define phys_to_folio(phys) page_folio(phys_to_page(phys)) #define page_to_phys(page) pfn_to_phys(page_to_pfn(page)) +#define folio_to_phys(page) pfn_to_phys(folio_pfn(folio)) static inline void *pfn_to_virt(unsigned long pfn) { diff --git a/arch/s390/kernel/uv.c b/arch/s390/kernel/uv.c index 3c6d86e3e828..914dcec27329 100644 --- a/arch/s390/kernel/uv.c +++ b/arch/s390/kernel/uv.c @@ -135,14 +135,18 @@ static int uv_destroy_page(unsigned long paddr) */ int uv_destroy_owned_page(unsigned long paddr) { - struct page *page = phys_to_page(paddr); + struct folio *folio = phys_to_folio(paddr); int rc; - get_page(page); + /* See gmap_make_secure(): large folios cannot be secure */ + if (unlikely(folio_test_large(folio))) + return 0; + + folio_get(folio); rc = uv_destroy_page(paddr); if (!rc) - clear_bit(PG_arch_1, &page->flags); - put_page(page); + clear_bit(PG_arch_1, &folio->flags); + folio_put(folio); return rc; } @@ -170,14 +174,18 @@ int uv_convert_from_secure(unsigned long paddr) */ int uv_convert_owned_from_secure(unsigned long paddr) { - struct page *page = phys_to_page(paddr); + struct folio *folio = phys_to_folio(paddr); int rc; - get_page(page); + /* See gmap_make_secure(): large folios cannot be secure */ + if (unlikely(folio_test_large(folio))) + return 0; + + folio_get(folio); rc = uv_convert_from_secure(paddr); if (!rc) - clear_bit(PG_arch_1, &page->flags); - put_page(page); + clear_bit(PG_arch_1, &folio->flags); + folio_put(folio); return rc; } @@ -479,33 +487,34 @@ EXPORT_SYMBOL_GPL(gmap_destroy_page); */ int arch_make_page_accessible(struct page *page) { + struct folio *folio = page_folio(page); int rc = 0; - /* Hugepage cannot be protected, so nothing to do */ - if (PageHuge(page)) + /* See gmap_make_secure(): large folios cannot be secure */ + if (unlikely(folio_test_large(folio))) return 0; /* * PG_arch_1 is used in 3 places: * 1. for kernel page tables during early boot * 2. for storage keys of huge pages and KVM - * 3. As an indication that this page might be secure. This can + * 3. As an indication that this small folio might be secure. This can * overindicate, e.g. we set the bit before calling * convert_to_secure. * As secure pages are never huge, all 3 variants can co-exists. */ - if (!test_bit(PG_arch_1, &page->flags)) + if (!test_bit(PG_arch_1, &folio->flags)) return 0; - rc = uv_pin_shared(page_to_phys(page)); + rc = uv_pin_shared(folio_to_phys(folio)); if (!rc) { - clear_bit(PG_arch_1, &page->flags); + clear_bit(PG_arch_1, &folio->flags); return 0; } - rc = uv_convert_from_secure(page_to_phys(page)); + rc = uv_convert_from_secure(folio_to_phys(folio)); if (!rc) { - clear_bit(PG_arch_1, &page->flags); + clear_bit(PG_arch_1, &folio->flags); return 0; }
Now that make_folio_secure() may only set PG_arch_1 for small folios, let's convert relevant remaining UV code to only work on (small) folios and simply reject large folios early. This way, we'll never end up touching PG_arch_1 on tail pages of a large folio in UV code. The folio_get()/folio_put() for functions that are documented to already hold a folio reference look weird; likely they are required to make concurrent gmap_make_secure() back off because the caller might only hold an implicit reference due to the page mapping. So leave that alone for now. Signed-off-by: David Hildenbrand <david@redhat.com> --- arch/s390/include/asm/page.h | 2 ++ arch/s390/kernel/uv.c | 41 ++++++++++++++++++++++-------------- 2 files changed, 27 insertions(+), 16 deletions(-)