]> Git Repo - J-linux.git/blob - drivers/iommu/iommu-pages.h
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / iommu / iommu-pages.h
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (c) 2024, Google LLC.
4  * Pasha Tatashin <[email protected]>
5  */
6
7 #ifndef __IOMMU_PAGES_H
8 #define __IOMMU_PAGES_H
9
10 #include <linux/vmstat.h>
11 #include <linux/gfp.h>
12 #include <linux/mm.h>
13
14 /*
15  * All page allocations that should be reported to as "iommu-pagetables" to
16  * userspace must use one of the functions below.  This includes allocations of
17  * page-tables and other per-iommu_domain configuration structures.
18  *
19  * This is necessary for the proper accounting as IOMMU state can be rather
20  * large, i.e. multiple gigabytes in size.
21  */
22
23 /**
24  * __iommu_alloc_account - account for newly allocated page.
25  * @page: head struct page of the page.
26  * @order: order of the page
27  */
28 static inline void __iommu_alloc_account(struct page *page, int order)
29 {
30         const long pgcnt = 1l << order;
31
32         mod_node_page_state(page_pgdat(page), NR_IOMMU_PAGES, pgcnt);
33         mod_lruvec_page_state(page, NR_SECONDARY_PAGETABLE, pgcnt);
34 }
35
36 /**
37  * __iommu_free_account - account a page that is about to be freed.
38  * @page: head struct page of the page.
39  * @order: order of the page
40  */
41 static inline void __iommu_free_account(struct page *page, int order)
42 {
43         const long pgcnt = 1l << order;
44
45         mod_node_page_state(page_pgdat(page), NR_IOMMU_PAGES, -pgcnt);
46         mod_lruvec_page_state(page, NR_SECONDARY_PAGETABLE, -pgcnt);
47 }
48
49 /**
50  * __iommu_alloc_pages - allocate a zeroed page of a given order.
51  * @gfp: buddy allocator flags
52  * @order: page order
53  *
54  * returns the head struct page of the allocated page.
55  */
56 static inline struct page *__iommu_alloc_pages(gfp_t gfp, int order)
57 {
58         struct page *page;
59
60         page = alloc_pages(gfp | __GFP_ZERO, order);
61         if (unlikely(!page))
62                 return NULL;
63
64         __iommu_alloc_account(page, order);
65
66         return page;
67 }
68
69 /**
70  * __iommu_free_pages - free page of a given order
71  * @page: head struct page of the page
72  * @order: page order
73  */
74 static inline void __iommu_free_pages(struct page *page, int order)
75 {
76         if (!page)
77                 return;
78
79         __iommu_free_account(page, order);
80         __free_pages(page, order);
81 }
82
83 /**
84  * iommu_alloc_pages_node - allocate a zeroed page of a given order from
85  * specific NUMA node.
86  * @nid: memory NUMA node id
87  * @gfp: buddy allocator flags
88  * @order: page order
89  *
90  * returns the virtual address of the allocated page
91  */
92 static inline void *iommu_alloc_pages_node(int nid, gfp_t gfp, int order)
93 {
94         struct page *page = alloc_pages_node(nid, gfp | __GFP_ZERO, order);
95
96         if (unlikely(!page))
97                 return NULL;
98
99         __iommu_alloc_account(page, order);
100
101         return page_address(page);
102 }
103
104 /**
105  * iommu_alloc_pages - allocate a zeroed page of a given order
106  * @gfp: buddy allocator flags
107  * @order: page order
108  *
109  * returns the virtual address of the allocated page
110  */
111 static inline void *iommu_alloc_pages(gfp_t gfp, int order)
112 {
113         struct page *page = __iommu_alloc_pages(gfp, order);
114
115         if (unlikely(!page))
116                 return NULL;
117
118         return page_address(page);
119 }
120
121 /**
122  * iommu_alloc_page_node - allocate a zeroed page at specific NUMA node.
123  * @nid: memory NUMA node id
124  * @gfp: buddy allocator flags
125  *
126  * returns the virtual address of the allocated page
127  */
128 static inline void *iommu_alloc_page_node(int nid, gfp_t gfp)
129 {
130         return iommu_alloc_pages_node(nid, gfp, 0);
131 }
132
133 /**
134  * iommu_alloc_page - allocate a zeroed page
135  * @gfp: buddy allocator flags
136  *
137  * returns the virtual address of the allocated page
138  */
139 static inline void *iommu_alloc_page(gfp_t gfp)
140 {
141         return iommu_alloc_pages(gfp, 0);
142 }
143
144 /**
145  * iommu_free_pages - free page of a given order
146  * @virt: virtual address of the page to be freed.
147  * @order: page order
148  */
149 static inline void iommu_free_pages(void *virt, int order)
150 {
151         if (!virt)
152                 return;
153
154         __iommu_free_pages(virt_to_page(virt), order);
155 }
156
157 /**
158  * iommu_free_page - free page
159  * @virt: virtual address of the page to be freed.
160  */
161 static inline void iommu_free_page(void *virt)
162 {
163         iommu_free_pages(virt, 0);
164 }
165
166 /**
167  * iommu_put_pages_list - free a list of pages.
168  * @page: the head of the lru list to be freed.
169  *
170  * There are no locking requirement for these pages, as they are going to be
171  * put on a free list as soon as refcount reaches 0. Pages are put on this LRU
172  * list once they are removed from the IOMMU page tables. However, they can
173  * still be access through debugfs.
174  */
175 static inline void iommu_put_pages_list(struct list_head *page)
176 {
177         while (!list_empty(page)) {
178                 struct page *p = list_entry(page->prev, struct page, lru);
179
180                 list_del(&p->lru);
181                 __iommu_free_account(p, 0);
182                 put_page(p);
183         }
184 }
185
186 #endif  /* __IOMMU_PAGES_H */
This page took 0.035392 seconds and 4 git commands to generate.