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:
parent
3053a46e6f
commit
c84f867d94
3 changed files with 75 additions and 5 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Add table
Reference in a new issue