Skip to content

Commit b3efacc

Browse files
jgunthorpejoergroedel
authored andcommitted
iommu/pages: Allow sub page sizes to be passed into the allocator
Generally drivers have a specific idea what their HW structure size should be. In a lot of cases this is related to PAGE_SIZE, but not always. ARM64, for example, allows a 4K IO page table size on a 64K CPU page table system. Currently we don't have any good support for sub page allocations, but make the API accommodate this by accepting a sub page size from the caller and rounding up internally. This is done by moving away from order as the size input and using size: size == 1 << (order + PAGE_SHIFT) Following patches convert drivers away from using order and try to specify allocation sizes independent of PAGE_SIZE. Reviewed-by: Lu Baolu <[email protected]> Tested-by: Alejandro Jimenez <[email protected]> Tested-by: Nicolin Chen <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 580ccca commit b3efacc

File tree

3 files changed

+61
-18
lines changed

3 files changed

+61
-18
lines changed

drivers/iommu/iommu-pages.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,32 @@ IOPTDESC_MATCH(memcg_data, memcg_data);
2323
static_assert(sizeof(struct ioptdesc) <= sizeof(struct page));
2424

2525
/**
26-
* iommu_alloc_pages_node - Allocate a zeroed page of a given order from
27-
* specific NUMA node
26+
* iommu_alloc_pages_node_sz - Allocate a zeroed page of a given size from
27+
* specific NUMA node
2828
* @nid: memory NUMA node id
2929
* @gfp: buddy allocator flags
30-
* @order: page order
30+
* @size: Memory size to allocate, rounded up to a power of 2
3131
*
32-
* Returns the virtual address of the allocated page. The page must be
33-
* freed either by calling iommu_free_pages() or via iommu_put_pages_list().
32+
* Returns the virtual address of the allocated page. The page must be freed
33+
* either by calling iommu_free_pages() or via iommu_put_pages_list(). The
34+
* returned allocation is round_up_pow_two(size) big, and is physically aligned
35+
* to its size.
3436
*/
35-
void *iommu_alloc_pages_node(int nid, gfp_t gfp, unsigned int order)
37+
void *iommu_alloc_pages_node_sz(int nid, gfp_t gfp, size_t size)
3638
{
37-
const unsigned long pgcnt = 1UL << order;
39+
unsigned long pgcnt;
3840
struct folio *folio;
41+
unsigned int order;
3942

4043
/* This uses page_address() on the memory. */
4144
if (WARN_ON(gfp & __GFP_HIGHMEM))
4245
return NULL;
4346

47+
/*
48+
* Currently sub page allocations result in a full page being returned.
49+
*/
50+
order = get_order(size);
51+
4452
/*
4553
* __folio_alloc_node() does not handle NUMA_NO_NODE like
4654
* alloc_pages_node() did.
@@ -61,12 +69,13 @@ void *iommu_alloc_pages_node(int nid, gfp_t gfp, unsigned int order)
6169
* This is necessary for the proper accounting as IOMMU state can be
6270
* rather large, i.e. multiple gigabytes in size.
6371
*/
72+
pgcnt = 1UL << order;
6473
mod_node_page_state(folio_pgdat(folio), NR_IOMMU_PAGES, pgcnt);
6574
lruvec_stat_mod_folio(folio, NR_SECONDARY_PAGETABLE, pgcnt);
6675

6776
return folio_address(folio);
6877
}
69-
EXPORT_SYMBOL_GPL(iommu_alloc_pages_node);
78+
EXPORT_SYMBOL_GPL(iommu_alloc_pages_node_sz);
7079

7180
static void __iommu_free_desc(struct ioptdesc *iopt)
7281
{
@@ -82,7 +91,7 @@ static void __iommu_free_desc(struct ioptdesc *iopt)
8291
* iommu_free_pages - free pages
8392
* @virt: virtual address of the page to be freed.
8493
*
85-
* The page must have have been allocated by iommu_alloc_pages_node()
94+
* The page must have have been allocated by iommu_alloc_pages_node_sz()
8695
*/
8796
void iommu_free_pages(void *virt)
8897
{
@@ -96,7 +105,7 @@ EXPORT_SYMBOL_GPL(iommu_free_pages);
96105
* iommu_put_pages_list - free a list of pages.
97106
* @list: The list of pages to be freed
98107
*
99-
* Frees a list of pages allocated by iommu_alloc_pages_node().
108+
* Frees a list of pages allocated by iommu_alloc_pages_node_sz().
100109
*/
101110
void iommu_put_pages_list(struct iommu_pages_list *list)
102111
{

drivers/iommu/iommu-pages.h

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,14 @@ static inline struct ioptdesc *virt_to_ioptdesc(void *virt)
4646
return folio_ioptdesc(virt_to_folio(virt));
4747
}
4848

49-
void *iommu_alloc_pages_node(int nid, gfp_t gfp, unsigned int order);
49+
void *iommu_alloc_pages_node_sz(int nid, gfp_t gfp, size_t size);
5050
void iommu_free_pages(void *virt);
5151
void iommu_put_pages_list(struct iommu_pages_list *list);
5252

5353
/**
5454
* iommu_pages_list_add - add the page to a iommu_pages_list
5555
* @list: List to add the page to
56-
* @virt: Address returned from iommu_alloc_pages_node()
56+
* @virt: Address returned from iommu_alloc_pages_node_sz()
5757
*/
5858
static inline void iommu_pages_list_add(struct iommu_pages_list *list,
5959
void *virt)
@@ -84,16 +84,48 @@ static inline bool iommu_pages_list_empty(struct iommu_pages_list *list)
8484
return list_empty(&list->pages);
8585
}
8686

87+
/**
88+
* iommu_alloc_pages_node - Allocate a zeroed page of a given order from
89+
* specific NUMA node
90+
* @nid: memory NUMA node id
91+
* @gfp: buddy allocator flags
92+
* @order: page order
93+
*
94+
* Returns the virtual address of the allocated page.
95+
* Prefer to use iommu_alloc_pages_node_lg2()
96+
*/
97+
static inline void *iommu_alloc_pages_node(int nid, gfp_t gfp,
98+
unsigned int order)
99+
{
100+
return iommu_alloc_pages_node_sz(nid, gfp, 1 << (order + PAGE_SHIFT));
101+
}
102+
87103
/**
88104
* iommu_alloc_pages - allocate a zeroed page of a given order
89105
* @gfp: buddy allocator flags
90106
* @order: page order
91107
*
92108
* returns the virtual address of the allocated page
109+
* Prefer to use iommu_alloc_pages_lg2()
93110
*/
94111
static inline void *iommu_alloc_pages(gfp_t gfp, int order)
95112
{
96-
return iommu_alloc_pages_node(NUMA_NO_NODE, gfp, order);
113+
return iommu_alloc_pages_node_sz(NUMA_NO_NODE, gfp,
114+
1 << (order + PAGE_SHIFT));
115+
}
116+
117+
/**
118+
* iommu_alloc_pages_sz - Allocate a zeroed page of a given size from
119+
* specific NUMA node
120+
* @nid: memory NUMA node id
121+
* @gfp: buddy allocator flags
122+
* @size: Memory size to allocate, this is rounded up to a power of 2
123+
*
124+
* Returns the virtual address of the allocated page.
125+
*/
126+
static inline void *iommu_alloc_pages_sz(gfp_t gfp, size_t size)
127+
{
128+
return iommu_alloc_pages_node_sz(NUMA_NO_NODE, gfp, size);
97129
}
98130

99131
/**
@@ -102,21 +134,23 @@ static inline void *iommu_alloc_pages(gfp_t gfp, int order)
102134
* @gfp: buddy allocator flags
103135
*
104136
* returns the virtual address of the allocated page
137+
* Prefer to use iommu_alloc_pages_node_lg2()
105138
*/
106139
static inline void *iommu_alloc_page_node(int nid, gfp_t gfp)
107140
{
108-
return iommu_alloc_pages_node(nid, gfp, 0);
141+
return iommu_alloc_pages_node_sz(nid, gfp, PAGE_SIZE);
109142
}
110143

111144
/**
112145
* iommu_alloc_page - allocate a zeroed page
113146
* @gfp: buddy allocator flags
114147
*
115148
* returns the virtual address of the allocated page
149+
* Prefer to use iommu_alloc_pages_lg2()
116150
*/
117151
static inline void *iommu_alloc_page(gfp_t gfp)
118152
{
119-
return iommu_alloc_pages_node(NUMA_NO_NODE, gfp, 0);
153+
return iommu_alloc_pages_node_sz(NUMA_NO_NODE, gfp, PAGE_SIZE);
120154
}
121155

122156
#endif /* __IOMMU_PAGES_H */

include/linux/iommu.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,9 +342,9 @@ typedef unsigned int ioasid_t;
342342
#define IOMMU_DIRTY_NO_CLEAR (1 << 0)
343343

344344
/*
345-
* Pages allocated through iommu_alloc_pages_node() can be placed on this list
346-
* using iommu_pages_list_add(). Note: ONLY pages from iommu_alloc_pages_node()
347-
* can be used this way!
345+
* Pages allocated through iommu_alloc_pages_node_sz() can be placed on this
346+
* list using iommu_pages_list_add(). Note: ONLY pages from
347+
* iommu_alloc_pages_node_sz() can be used this way!
348348
*/
349349
struct iommu_pages_list {
350350
struct list_head pages;

0 commit comments

Comments
 (0)