]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
iommu: observability of the IOMMU allocations
authorPasha Tatashin <pasha.tatashin@soleen.com>
Sat, 13 Apr 2024 00:25:21 +0000 (00:25 +0000)
committerJoerg Roedel <jroedel@suse.de>
Mon, 15 Apr 2024 12:31:47 +0000 (14:31 +0200)
Add NR_IOMMU_PAGES into node_stat_item that counts number of pages
that are allocated by the IOMMU subsystem.

The allocations can be view per-node via:
/sys/devices/system/node/nodeN/vmstat.

For example:

$ grep iommu /sys/devices/system/node/node*/vmstat
/sys/devices/system/node/node0/vmstat:nr_iommu_pages 106025
/sys/devices/system/node/node1/vmstat:nr_iommu_pages 3464

The value is in page-count, therefore, in the above example
the iommu allocations amount to ~428M.

Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Acked-by: David Rientjes <rientjes@google.com>
Tested-by: Bagas Sanjaya <bagasdotme@gmail.com>
Link: https://lore.kernel.org/r/20240413002522.1101315-11-pasha.tatashin@soleen.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/iommu-pages.h
include/linux/mmzone.h
mm/vmstat.c

index 5a222d0ad25cc386f93ec9124fca553062283b51..1264b0f6b6c3cb568c2cc078926b36a08b3bdb8c 100644 (file)
  * large, i.e. multiple gigabytes in size.
  */
 
+/**
+ * __iommu_alloc_account - account for newly allocated page.
+ * @page: head struct page of the page.
+ * @order: order of the page
+ */
+static inline void __iommu_alloc_account(struct page *page, int order)
+{
+       const long pgcnt = 1l << order;
+
+       mod_node_page_state(page_pgdat(page), NR_IOMMU_PAGES, pgcnt);
+}
+
+/**
+ * __iommu_free_account - account a page that is about to be freed.
+ * @page: head struct page of the page.
+ * @order: order of the page
+ */
+static inline void __iommu_free_account(struct page *page, int order)
+{
+       const long pgcnt = 1l << order;
+
+       mod_node_page_state(page_pgdat(page), NR_IOMMU_PAGES, -pgcnt);
+}
+
 /**
  * __iommu_alloc_pages - allocate a zeroed page of a given order.
  * @gfp: buddy allocator flags
@@ -35,6 +59,8 @@ static inline struct page *__iommu_alloc_pages(gfp_t gfp, int order)
        if (unlikely(!page))
                return NULL;
 
+       __iommu_alloc_account(page, order);
+
        return page;
 }
 
@@ -48,6 +74,7 @@ static inline void __iommu_free_pages(struct page *page, int order)
        if (!page)
                return;
 
+       __iommu_free_account(page, order);
        __free_pages(page, order);
 }
 
@@ -67,6 +94,8 @@ static inline void *iommu_alloc_pages_node(int nid, gfp_t gfp, int order)
        if (unlikely(!page))
                return NULL;
 
+       __iommu_alloc_account(page, order);
+
        return page_address(page);
 }
 
@@ -147,6 +176,7 @@ static inline void iommu_put_pages_list(struct list_head *page)
                struct page *p = list_entry(page->prev, struct page, lru);
 
                list_del(&p->lru);
+               __iommu_free_account(p, 0);
                put_page(p);
        }
 }
index c11b7cde81efae9d9b57e266f531d4f1fd0d0592..be17195f6f868ccbd7f431112b588275918a5a7c 100644 (file)
@@ -206,6 +206,9 @@ enum node_stat_item {
 #endif
        NR_PAGETABLE,           /* used for pagetables */
        NR_SECONDARY_PAGETABLE, /* secondary pagetables, e.g. KVM pagetables */
+#ifdef CONFIG_IOMMU_SUPPORT
+       NR_IOMMU_PAGES,         /* # of pages allocated by IOMMU */
+#endif
 #ifdef CONFIG_SWAP
        NR_SWAPCACHE,
 #endif
index db79935e4a5437b8cf329a32b9772f1c26d745df..8507c497218b8fc766842981cecc5db4f5fd8d22 100644 (file)
@@ -1242,6 +1242,9 @@ const char * const vmstat_text[] = {
 #endif
        "nr_page_table_pages",
        "nr_sec_page_table_pages",
+#ifdef CONFIG_IOMMU_SUPPORT
+       "nr_iommu_pages",
+#endif
 #ifdef CONFIG_SWAP
        "nr_swapcached",
 #endif