blob: f72e737dda214fd1dcbbe70835e05c515a2f1b05 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 1994 - 2001, 2003 by Ralf Baechle
7 * Copyright (C) 1999, 2000, 2001 Silicon Graphics, Inc.
8 */
9#ifndef _ASM_PGALLOC_H
10#define _ASM_PGALLOC_H
11
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include <linux/highmem.h>
13#include <linux/mm.h>
Alexey Dobriyane8edc6e2007-05-21 01:22:52 +040014#include <linux/sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015
Mike Rapoport1355c312020-08-06 23:22:39 -070016#define __HAVE_ARCH_PMD_ALLOC_ONE
Mike Rapoportd9e8b922020-08-06 23:22:44 -070017#define __HAVE_ARCH_PUD_ALLOC_ONE
Yaliang Wang2bc5bab92022-03-10 19:31:16 +080018#define __HAVE_ARCH_PGD_FREE
Mike Rapoport1355c312020-08-06 23:22:39 -070019#include <asm-generic/pgalloc.h>
Mike Rapoportb7902ce2019-07-11 20:58:14 -070020
Linus Torvalds1da177e2005-04-16 15:20:36 -070021static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
22 pte_t *pte)
23{
24 set_pmd(pmd, __pmd((unsigned long)pte));
25}
26
27static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
Martin Schwidefsky2f569af2008-02-08 04:22:04 -080028 pgtable_t pte)
Linus Torvalds1da177e2005-04-16 15:20:36 -070029{
30 set_pmd(pmd, __pmd((unsigned long)page_address(pte)));
31}
32
33/*
Ralf Baechlec6e8b582005-02-10 12:19:59 +000034 * Initialize a new pmd table with invalid pointers.
35 */
Feiyang Chen22c4e802022-10-27 20:52:50 +080036extern void pmd_init(void *addr);
Ralf Baechlec6e8b582005-02-10 12:19:59 +000037
David Daney325f8a02009-12-04 13:52:36 -080038#ifndef __PAGETABLE_PMD_FOLDED
Ralf Baechlec6e8b582005-02-10 12:19:59 +000039
40static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
41{
42 set_pud(pud, __pud((unsigned long)pmd));
43}
44#endif
45
46/*
Feiyang Chen22c4e802022-10-27 20:52:50 +080047 * Initialize a new pgd table with invalid pointers.
Linus Torvalds1da177e2005-04-16 15:20:36 -070048 */
Feiyang Chen22c4e802022-10-27 20:52:50 +080049extern void pgd_init(void *addr);
James Hogan814f91b2017-02-02 01:21:35 +000050extern pgd_t *pgd_alloc(struct mm_struct *mm);
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
Yaliang Wang2bc5bab92022-03-10 19:31:16 +080052static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
53{
Mike Rapoportbb5af4f2022-07-03 17:11:55 +030054 free_pages((unsigned long)pgd, PGD_TABLE_ORDER);
Yaliang Wang2bc5bab92022-03-10 19:31:16 +080055}
56
Benjamin Herrenschmidt9e1b32c2009-07-22 15:44:28 +100057#define __pte_free_tlb(tlb,pte,address) \
Martin Schwidefsky2f569af2008-02-08 04:22:04 -080058do { \
Mark Rutlandb4ed71f2019-09-25 16:49:46 -070059 pgtable_pte_page_dtor(pte); \
Martin Schwidefsky2f569af2008-02-08 04:22:04 -080060 tlb_remove_page((tlb), pte); \
61} while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
David Daney325f8a02009-12-04 13:52:36 -080063#ifndef __PAGETABLE_PMD_FOLDED
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Linus Torvalds1da177e2005-04-16 15:20:36 -070065static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
66{
Huang Pei6aa32462021-07-21 17:30:45 +080067 pmd_t *pmd;
Huang Peied914d42021-06-11 15:09:46 +080068 struct page *pg;
Linus Torvalds1da177e2005-04-16 15:20:36 -070069
Matthew Wilcox (Oracle)c94b14b2022-07-03 17:11:52 +030070 pg = alloc_pages(GFP_KERNEL_ACCOUNT, PMD_TABLE_ORDER);
Huang Pei6aa32462021-07-21 17:30:45 +080071 if (!pg)
72 return NULL;
73
74 if (!pgtable_pmd_page_ctor(pg)) {
Matthew Wilcox (Oracle)c94b14b2022-07-03 17:11:52 +030075 __free_pages(pg, PMD_TABLE_ORDER);
Huang Pei6aa32462021-07-21 17:30:45 +080076 return NULL;
Huang Peied914d42021-06-11 15:09:46 +080077 }
Huang Pei6aa32462021-07-21 17:30:45 +080078
79 pmd = (pmd_t *)page_address(pg);
Feiyang Chen22c4e802022-10-27 20:52:50 +080080 pmd_init(pmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 return pmd;
82}
83
Benjamin Herrenschmidt9e1b32c2009-07-22 15:44:28 +100084#define __pmd_free_tlb(tlb, x, addr) pmd_free((tlb)->mm, x)
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
86#endif
87
Alex Belits3377e222017-02-16 17:27:34 -080088#ifndef __PAGETABLE_PUD_FOLDED
89
90static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
91{
92 pud_t *pud;
93
Mike Rapoport8e20a4d2022-07-03 17:11:53 +030094 pud = (pud_t *) __get_free_pages(GFP_KERNEL, PUD_TABLE_ORDER);
Alex Belits3377e222017-02-16 17:27:34 -080095 if (pud)
Feiyang Chen22c4e802022-10-27 20:52:50 +080096 pud_init(pud);
Alex Belits3377e222017-02-16 17:27:34 -080097 return pud;
98}
99
Mike Rapoport2bee1b52019-11-21 18:21:33 +0200100static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4d, pud_t *pud)
Alex Belits3377e222017-02-16 17:27:34 -0800101{
Mike Rapoport2bee1b52019-11-21 18:21:33 +0200102 set_p4d(p4d, __p4d((unsigned long)pud));
Alex Belits3377e222017-02-16 17:27:34 -0800103}
104
105#define __pud_free_tlb(tlb, x, addr) pud_free((tlb)->mm, x)
106
107#endif /* __PAGETABLE_PUD_FOLDED */
108
Atsushi Nemoto6a1e5522007-02-19 01:27:34 +0900109extern void pagetable_init(void);
110
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111#endif /* _ASM_PGALLOC_H */