Skip to content

Commit 6326c26

Browse files
VMoolaakpm00
authored andcommitted
s390: convert various pgalloc functions to use ptdescs
As part of the conversions to replace pgtable constructor/destructors with ptdesc equivalents, convert various page table functions to use ptdescs. Some of the functions use the *get*page*() helper functions. Convert these to use pagetable_alloc() and ptdesc_address() instead to help standardize page tables further. Link: https://lkml.kernel.org/r/20230807230513.102486-15-vishal.moola@gmail.com Signed-off-by: Vishal Moola (Oracle) <vishal.moola@gmail.com> Acked-by: Mike Rapoport (IBM) <rppt@kernel.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Christophe Leroy <christophe.leroy@csgroup.eu> Cc: Claudio Imbrenda <imbrenda@linux.ibm.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: David Hildenbrand <david@redhat.com> Cc: "David S. Miller" <davem@davemloft.net> Cc: Dinh Nguyen <dinguyen@kernel.org> Cc: Geert Uytterhoeven <geert@linux-m68k.org> Cc: Geert Uytterhoeven <geert+renesas@glider.be> Cc: Guo Ren <guoren@kernel.org> Cc: Huacai Chen <chenhuacai@kernel.org> Cc: Hugh Dickins <hughd@google.com> Cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> Cc: Jonas Bonn <jonas@southpole.se> Cc: Matthew Wilcox <willy@infradead.org> Cc: Palmer Dabbelt <palmer@rivosinc.com> Cc: Paul Walmsley <paul.walmsley@sifive.com> Cc: Richard Weinberger <richard@nod.at> Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de> Cc: Yoshinori Sato <ysato@users.sourceforge.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent f92c494 commit 6326c26

File tree

3 files changed

+69
-67
lines changed

3 files changed

+69
-67
lines changed

arch/s390/include/asm/pgalloc.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
8686
if (!table)
8787
return NULL;
8888
crst_table_init(table, _SEGMENT_ENTRY_EMPTY);
89-
if (!pgtable_pmd_page_ctor(virt_to_page(table))) {
89+
if (!pagetable_pmd_ctor(virt_to_ptdesc(table))) {
9090
crst_table_free(mm, table);
9191
return NULL;
9292
}
@@ -97,7 +97,7 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
9797
{
9898
if (mm_pmd_folded(mm))
9999
return;
100-
pgtable_pmd_page_dtor(virt_to_page(pmd));
100+
pagetable_pmd_dtor(virt_to_ptdesc(pmd));
101101
crst_table_free(mm, (unsigned long *) pmd);
102102
}
103103

arch/s390/include/asm/tlb.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,12 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
8989
{
9090
if (mm_pmd_folded(tlb->mm))
9191
return;
92-
pgtable_pmd_page_dtor(virt_to_page(pmd));
92+
pagetable_pmd_dtor(virt_to_ptdesc(pmd));
9393
__tlb_adjust_range(tlb, address, PAGE_SIZE);
9494
tlb->mm->context.flush_mm = 1;
9595
tlb->freed_tables = 1;
9696
tlb->cleared_puds = 1;
97-
tlb_remove_table(tlb, pmd);
97+
tlb_remove_ptdesc(tlb, pmd);
9898
}
9999

100100
/*

arch/s390/mm/pgalloc.c

Lines changed: 65 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,17 @@ __initcall(page_table_register_sysctl);
4343

4444
unsigned long *crst_table_alloc(struct mm_struct *mm)
4545
{
46-
struct page *page = alloc_pages(GFP_KERNEL, CRST_ALLOC_ORDER);
46+
struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL, CRST_ALLOC_ORDER);
4747

48-
if (!page)
48+
if (!ptdesc)
4949
return NULL;
50-
arch_set_page_dat(page, CRST_ALLOC_ORDER);
51-
return (unsigned long *) page_to_virt(page);
50+
arch_set_page_dat(ptdesc_page(ptdesc), CRST_ALLOC_ORDER);
51+
return (unsigned long *) ptdesc_to_virt(ptdesc);
5252
}
5353

5454
void crst_table_free(struct mm_struct *mm, unsigned long *table)
5555
{
56-
free_pages((unsigned long)table, CRST_ALLOC_ORDER);
56+
pagetable_free(virt_to_ptdesc(table));
5757
}
5858

5959
static void __crst_table_upgrade(void *arg)
@@ -140,21 +140,21 @@ static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits)
140140

141141
struct page *page_table_alloc_pgste(struct mm_struct *mm)
142142
{
143-
struct page *page;
143+
struct ptdesc *ptdesc;
144144
u64 *table;
145145

146-
page = alloc_page(GFP_KERNEL);
147-
if (page) {
148-
table = (u64 *)page_to_virt(page);
146+
ptdesc = pagetable_alloc(GFP_KERNEL, 0);
147+
if (ptdesc) {
148+
table = (u64 *)ptdesc_to_virt(ptdesc);
149149
memset64(table, _PAGE_INVALID, PTRS_PER_PTE);
150150
memset64(table + PTRS_PER_PTE, 0, PTRS_PER_PTE);
151151
}
152-
return page;
152+
return ptdesc_page(ptdesc);
153153
}
154154

155155
void page_table_free_pgste(struct page *page)
156156
{
157-
__free_page(page);
157+
pagetable_free(page_ptdesc(page));
158158
}
159159

160160
#endif /* CONFIG_PGSTE */
@@ -242,17 +242,17 @@ void page_table_free_pgste(struct page *page)
242242
unsigned long *page_table_alloc(struct mm_struct *mm)
243243
{
244244
unsigned long *table;
245-
struct page *page;
245+
struct ptdesc *ptdesc;
246246
unsigned int mask, bit;
247247

248248
/* Try to get a fragment of a 4K page as a 2K page table */
249249
if (!mm_alloc_pgste(mm)) {
250250
table = NULL;
251251
spin_lock_bh(&mm->context.lock);
252252
if (!list_empty(&mm->context.pgtable_list)) {
253-
page = list_first_entry(&mm->context.pgtable_list,
254-
struct page, lru);
255-
mask = atomic_read(&page->_refcount) >> 24;
253+
ptdesc = list_first_entry(&mm->context.pgtable_list,
254+
struct ptdesc, pt_list);
255+
mask = atomic_read(&ptdesc->_refcount) >> 24;
256256
/*
257257
* The pending removal bits must also be checked.
258258
* Failure to do so might lead to an impossible
@@ -264,42 +264,42 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
264264
*/
265265
mask = (mask | (mask >> 4)) & 0x03U;
266266
if (mask != 0x03U) {
267-
table = (unsigned long *) page_to_virt(page);
267+
table = (unsigned long *) ptdesc_to_virt(ptdesc);
268268
bit = mask & 1; /* =1 -> second 2K */
269269
if (bit)
270270
table += PTRS_PER_PTE;
271-
atomic_xor_bits(&page->_refcount,
271+
atomic_xor_bits(&ptdesc->_refcount,
272272
0x01U << (bit + 24));
273-
list_del_init(&page->lru);
273+
list_del_init(&ptdesc->pt_list);
274274
}
275275
}
276276
spin_unlock_bh(&mm->context.lock);
277277
if (table)
278278
return table;
279279
}
280280
/* Allocate a fresh page */
281-
page = alloc_page(GFP_KERNEL);
282-
if (!page)
281+
ptdesc = pagetable_alloc(GFP_KERNEL, 0);
282+
if (!ptdesc)
283283
return NULL;
284-
if (!pgtable_pte_page_ctor(page)) {
285-
__free_page(page);
284+
if (!pagetable_pte_ctor(ptdesc)) {
285+
pagetable_free(ptdesc);
286286
return NULL;
287287
}
288-
arch_set_page_dat(page, 0);
288+
arch_set_page_dat(ptdesc_page(ptdesc), 0);
289289
/* Initialize page table */
290-
table = (unsigned long *) page_to_virt(page);
290+
table = (unsigned long *) ptdesc_to_virt(ptdesc);
291291
if (mm_alloc_pgste(mm)) {
292292
/* Return 4K page table with PGSTEs */
293-
INIT_LIST_HEAD(&page->lru);
294-
atomic_xor_bits(&page->_refcount, 0x03U << 24);
293+
INIT_LIST_HEAD(&ptdesc->pt_list);
294+
atomic_xor_bits(&ptdesc->_refcount, 0x03U << 24);
295295
memset64((u64 *)table, _PAGE_INVALID, PTRS_PER_PTE);
296296
memset64((u64 *)table + PTRS_PER_PTE, 0, PTRS_PER_PTE);
297297
} else {
298298
/* Return the first 2K fragment of the page */
299-
atomic_xor_bits(&page->_refcount, 0x01U << 24);
299+
atomic_xor_bits(&ptdesc->_refcount, 0x01U << 24);
300300
memset64((u64 *)table, _PAGE_INVALID, 2 * PTRS_PER_PTE);
301301
spin_lock_bh(&mm->context.lock);
302-
list_add(&page->lru, &mm->context.pgtable_list);
302+
list_add(&ptdesc->pt_list, &mm->context.pgtable_list);
303303
spin_unlock_bh(&mm->context.lock);
304304
}
305305
return table;
@@ -322,19 +322,18 @@ static void page_table_release_check(struct page *page, void *table,
322322

323323
static void pte_free_now(struct rcu_head *head)
324324
{
325-
struct page *page;
325+
struct ptdesc *ptdesc;
326326

327-
page = container_of(head, struct page, rcu_head);
328-
pgtable_pte_page_dtor(page);
329-
__free_page(page);
327+
ptdesc = container_of(head, struct ptdesc, pt_rcu_head);
328+
pagetable_pte_dtor(ptdesc);
329+
pagetable_free(ptdesc);
330330
}
331331

332332
void page_table_free(struct mm_struct *mm, unsigned long *table)
333333
{
334334
unsigned int mask, bit, half;
335-
struct page *page;
335+
struct ptdesc *ptdesc = virt_to_ptdesc(table);
336336

337-
page = virt_to_page(table);
338337
if (!mm_alloc_pgste(mm)) {
339338
/* Free 2K page table fragment of a 4K page */
340339
bit = ((unsigned long) table & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t));
@@ -344,51 +343,50 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
344343
* will happen outside of the critical section from this
345344
* function or from __tlb_remove_table()
346345
*/
347-
mask = atomic_xor_bits(&page->_refcount, 0x11U << (bit + 24));
346+
mask = atomic_xor_bits(&ptdesc->_refcount, 0x11U << (bit + 24));
348347
mask >>= 24;
349-
if ((mask & 0x03U) && !PageActive(page)) {
348+
if ((mask & 0x03U) && !folio_test_active(ptdesc_folio(ptdesc))) {
350349
/*
351350
* Other half is allocated, and neither half has had
352351
* its free deferred: add page to head of list, to make
353352
* this freed half available for immediate reuse.
354353
*/
355-
list_add(&page->lru, &mm->context.pgtable_list);
354+
list_add(&ptdesc->pt_list, &mm->context.pgtable_list);
356355
} else {
357356
/* If page is on list, now remove it. */
358-
list_del_init(&page->lru);
357+
list_del_init(&ptdesc->pt_list);
359358
}
360359
spin_unlock_bh(&mm->context.lock);
361-
mask = atomic_xor_bits(&page->_refcount, 0x10U << (bit + 24));
360+
mask = atomic_xor_bits(&ptdesc->_refcount, 0x10U << (bit + 24));
362361
mask >>= 24;
363362
if (mask != 0x00U)
364363
return;
365364
half = 0x01U << bit;
366365
} else {
367366
half = 0x03U;
368-
mask = atomic_xor_bits(&page->_refcount, 0x03U << 24);
367+
mask = atomic_xor_bits(&ptdesc->_refcount, 0x03U << 24);
369368
mask >>= 24;
370369
}
371370

372-
page_table_release_check(page, table, half, mask);
373-
if (TestClearPageActive(page))
374-
call_rcu(&page->rcu_head, pte_free_now);
371+
page_table_release_check(ptdesc_page(ptdesc), table, half, mask);
372+
if (folio_test_clear_active(ptdesc_folio(ptdesc)))
373+
call_rcu(&ptdesc->pt_rcu_head, pte_free_now);
375374
else
376-
pte_free_now(&page->rcu_head);
375+
pte_free_now(&ptdesc->pt_rcu_head);
377376
}
378377

379378
void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table,
380379
unsigned long vmaddr)
381380
{
382381
struct mm_struct *mm;
383-
struct page *page;
384382
unsigned int bit, mask;
383+
struct ptdesc *ptdesc = virt_to_ptdesc(table);
385384

386385
mm = tlb->mm;
387-
page = virt_to_page(table);
388386
if (mm_alloc_pgste(mm)) {
389387
gmap_unlink(mm, table, vmaddr);
390388
table = (unsigned long *) ((unsigned long)table | 0x03U);
391-
tlb_remove_table(tlb, table);
389+
tlb_remove_ptdesc(tlb, table);
392390
return;
393391
}
394392
bit = ((unsigned long) table & ~PAGE_MASK) / (PTRS_PER_PTE*sizeof(pte_t));
@@ -398,19 +396,19 @@ void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table,
398396
* outside of the critical section from __tlb_remove_table() or from
399397
* page_table_free()
400398
*/
401-
mask = atomic_xor_bits(&page->_refcount, 0x11U << (bit + 24));
399+
mask = atomic_xor_bits(&ptdesc->_refcount, 0x11U << (bit + 24));
402400
mask >>= 24;
403-
if ((mask & 0x03U) && !PageActive(page)) {
401+
if ((mask & 0x03U) && !folio_test_active(ptdesc_folio(ptdesc))) {
404402
/*
405403
* Other half is allocated, and neither half has had
406404
* its free deferred: add page to end of list, to make
407405
* this freed half available for reuse once its pending
408406
* bit has been cleared by __tlb_remove_table().
409407
*/
410-
list_add_tail(&page->lru, &mm->context.pgtable_list);
408+
list_add_tail(&ptdesc->pt_list, &mm->context.pgtable_list);
411409
} else {
412410
/* If page is on list, now remove it. */
413-
list_del_init(&page->lru);
411+
list_del_init(&ptdesc->pt_list);
414412
}
415413
spin_unlock_bh(&mm->context.lock);
416414
table = (unsigned long *) ((unsigned long) table | (0x01U << bit));
@@ -421,30 +419,30 @@ void __tlb_remove_table(void *_table)
421419
{
422420
unsigned int mask = (unsigned long) _table & 0x03U, half = mask;
423421
void *table = (void *)((unsigned long) _table ^ mask);
424-
struct page *page = virt_to_page(table);
422+
struct ptdesc *ptdesc = virt_to_ptdesc(table);
425423

426424
switch (half) {
427425
case 0x00U: /* pmd, pud, or p4d */
428-
free_pages((unsigned long)table, CRST_ALLOC_ORDER);
426+
pagetable_free(ptdesc);
429427
return;
430428
case 0x01U: /* lower 2K of a 4K page table */
431429
case 0x02U: /* higher 2K of a 4K page table */
432-
mask = atomic_xor_bits(&page->_refcount, mask << (4 + 24));
430+
mask = atomic_xor_bits(&ptdesc->_refcount, mask << (4 + 24));
433431
mask >>= 24;
434432
if (mask != 0x00U)
435433
return;
436434
break;
437435
case 0x03U: /* 4K page table with pgstes */
438-
mask = atomic_xor_bits(&page->_refcount, 0x03U << 24);
436+
mask = atomic_xor_bits(&ptdesc->_refcount, 0x03U << 24);
439437
mask >>= 24;
440438
break;
441439
}
442440

443-
page_table_release_check(page, table, half, mask);
444-
if (TestClearPageActive(page))
445-
call_rcu(&page->rcu_head, pte_free_now);
441+
page_table_release_check(ptdesc_page(ptdesc), table, half, mask);
442+
if (folio_test_clear_active(ptdesc_folio(ptdesc)))
443+
call_rcu(&ptdesc->pt_rcu_head, pte_free_now);
446444
else
447-
pte_free_now(&page->rcu_head);
445+
pte_free_now(&ptdesc->pt_rcu_head);
448446
}
449447

450448
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -488,16 +486,20 @@ static void base_pgt_free(unsigned long *table)
488486
static unsigned long *base_crst_alloc(unsigned long val)
489487
{
490488
unsigned long *table;
489+
struct ptdesc *ptdesc;
491490

492-
table = (unsigned long *)__get_free_pages(GFP_KERNEL, CRST_ALLOC_ORDER);
493-
if (table)
494-
crst_table_init(table, val);
491+
ptdesc = pagetable_alloc(GFP_KERNEL & ~__GFP_HIGHMEM, CRST_ALLOC_ORDER);
492+
if (!ptdesc)
493+
return NULL;
494+
table = ptdesc_address(ptdesc);
495+
496+
crst_table_init(table, val);
495497
return table;
496498
}
497499

498500
static void base_crst_free(unsigned long *table)
499501
{
500-
free_pages((unsigned long)table, CRST_ALLOC_ORDER);
502+
pagetable_free(virt_to_ptdesc(table));
501503
}
502504

503505
#define BASE_ADDR_END_FUNC(NAME, SIZE) \

0 commit comments

Comments
 (0)