Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8fb0156d authored by Mitchel Humpherys's avatar Mitchel Humpherys
Browse files

iommu/io-pgtable: Add memory stats debugfs file



It can be useful for debugging to know how much memory is being used for
IOMMU page tables.  Add some dedicated allocation functions and a
debugfs file for this.

Change-Id: Id69b4b1b5df5dcc6c604eec3a12a894b8eab0eb6
Signed-off-by: default avatarMitchel Humpherys <mitchelh@codeaurora.org>
parent 4e1e4ed2
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -249,7 +249,7 @@ static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova,
	/* Grab a pointer to the next level */
	pte = *ptep;
	if (!pte) {
		cptep = alloc_pages_exact(1UL << data->pg_shift,
		cptep = io_pgtable_alloc_pages_exact(1UL << data->pg_shift,
						     GFP_ATOMIC | __GFP_ZERO);
		if (!cptep)
			return -ENOMEM;
@@ -414,7 +414,7 @@ static void __arm_lpae_free_pgtable(struct arm_lpae_io_pgtable *data, int lvl,
	}

	data->iop.cfg.tlb->unprepare_pgtable(data->iop.cookie, start);
	free_pages_exact(start, table_size);
	io_pgtable_free_pages_exact(start, table_size);
}

static void arm_lpae_free_pgtable(struct io_pgtable *iop)
@@ -733,7 +733,8 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)
	cfg->arm_lpae_s1_cfg.mair[1] = 0;

	/* Looking good; allocate a pgd */
	data->pgd = alloc_pages_exact(data->pgd_size, GFP_KERNEL | __GFP_ZERO);
	data->pgd = io_pgtable_alloc_pages_exact(data->pgd_size,
						 GFP_KERNEL | __GFP_ZERO);
	if (!data->pgd)
		goto out_free_data;

@@ -821,7 +822,8 @@ arm_64_lpae_alloc_pgtable_s2(struct io_pgtable_cfg *cfg, void *cookie)
	cfg->arm_lpae_s2_cfg.vtcr = reg;

	/* Allocate pgd pages */
	data->pgd = alloc_pages_exact(data->pgd_size, GFP_KERNEL | __GFP_ZERO);
	data->pgd = io_pgtable_alloc_pages_exact(data->pgd_size,
						 GFP_KERNEL | __GFP_ZERO);
	if (!data->pgd)
		goto out_free_data;

+48 −0
Original line number Diff line number Diff line
@@ -18,9 +18,14 @@
 * Author: Will Deacon <will.deacon@arm.com>
 */

#define pr_fmt(fmt)	"io-pgtable: " fmt

#include <linux/bug.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/iommu.h>
#include <linux/debugfs.h>
#include <linux/atomic.h>

#include "io-pgtable.h"

@@ -40,6 +45,8 @@ io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] =
#endif
};

static struct dentry *io_pgtable_top;

struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt,
					    struct io_pgtable_cfg *cfg,
					    void *cookie)
@@ -80,3 +87,44 @@ void free_io_pgtable_ops(struct io_pgtable_ops *ops)
	iop->cfg.tlb->tlb_flush_all(iop->cookie);
	io_pgtable_init_table[iop->fmt]->free(iop);
}

static atomic_t pages_allocated;

void *io_pgtable_alloc_pages_exact(size_t size, gfp_t gfp_mask)
{
	void *ret = alloc_pages_exact(size, gfp_mask);

	if (likely(ret))
		atomic_add(1 << get_order(size), &pages_allocated);
	return ret;
}

void io_pgtable_free_pages_exact(void *virt, size_t size)
{
	free_pages_exact(virt, size);
	atomic_sub(1 << get_order(size), &pages_allocated);
}

static int io_pgtable_init(void)
{
	io_pgtable_top = debugfs_create_dir("io-pgtable", iommu_debugfs_top);

	if (!io_pgtable_top)
		return -ENODEV;

	if (!debugfs_create_atomic_t("pages", 0600,
				     io_pgtable_top, &pages_allocated)) {
		debugfs_remove_recursive(io_pgtable_top);
		return -ENODEV;
	}

	return 0;
}

static void io_pgtable_exit(void)
{
	debugfs_remove_recursive(io_pgtable_top);
}

module_init(io_pgtable_init);
module_exit(io_pgtable_exit);
+20 −0
Original line number Diff line number Diff line
@@ -148,4 +148,24 @@ struct io_pgtable_init_fns {
	void (*free)(struct io_pgtable *iop);
};

/**
 * io_pgtable_alloc_pages_exact - allocate an exact number physically-contiguous pages.
 * @size: the number of bytes to allocate
 * @gfp_mask: GFP flags for the allocation
 *
 * Like alloc_pages_exact(), but with some additional accounting for debug
 * purposes.
 */
void *io_pgtable_alloc_pages_exact(size_t size, gfp_t gfp_mask);

/**
 * io_pgtable_free_pages_exact - release memory allocated via io_pgtable_alloc_pages_exact()
 * @virt: the value returned by alloc_pages_exact.
 * @size: size of allocation, same value as passed to alloc_pages_exact().
 *
 * Like free_pages_exact(), but with some additional accounting for debug
 * purposes.
 */
void io_pgtable_free_pages_exact(void *virt, size_t size);

#endif /* __IO_PGTABLE_H */