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: Mitchel Humpherys <mitchelh@codeaurora.org>
This commit is contained in:
Mitchel Humpherys 2015-07-15 18:25:07 -07:00 committed by David Keitel
parent 3053a46e6f
commit c84f867d94
3 changed files with 75 additions and 5 deletions

View file

@ -249,8 +249,8 @@ 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,
GFP_ATOMIC | __GFP_ZERO);
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;

View file

@ -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);

View file

@ -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 */