mm: cma: debugfs interface
authorSasha Levin <sasha.levin@oracle.com>
Tue, 14 Apr 2015 22:44:57 +0000 (15:44 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 14 Apr 2015 23:49:00 +0000 (16:49 -0700)
I've noticed that there is no interfaces exposed by CMA which would let me
fuzz what's going on in there.

This small patchset exposes some information out to userspace, plus adds
the ability to trigger allocation and freeing from userspace.

This patch (of 3):

Implement a simple debugfs interface to expose information about CMA areas
in the system.

Useful for testing/sanity checks for CMA since it was impossible to
previously retrieve this information in userspace.

Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Acked-by: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: Laura Abbott <lauraa@codeaurora.org>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
mm/Kconfig
mm/Makefile
mm/cma.c
mm/cma.h [new file with mode: 0644]
mm/cma_debug.c [new file with mode: 0644]

index a03131b6ba8e7877b537a77fa0c21f5cd005e275..390214da45463e0b134709af6f072ddcc9162f7d 100644 (file)
@@ -517,6 +517,12 @@ config CMA_DEBUG
          processing calls such as dma_alloc_from_contiguous().
          This option does not affect warning and error messages.
 
+config CMA_DEBUGFS
+       bool "CMA debugfs interface"
+       depends on CMA && DEBUG_FS
+       help
+         Turns on the DebugFS interface for CMA.
+
 config CMA_AREAS
        int "Maximum count of the CMA areas"
        depends on CMA
index 15dbe9903c273f87c3e7c6a09e3c4a659647bd48..668a9bb82be4de01f13dd41f4e7b3cbb665d2e74 100644 (file)
@@ -76,3 +76,4 @@ obj-$(CONFIG_GENERIC_EARLY_IOREMAP) += early_ioremap.o
 obj-$(CONFIG_CMA)      += cma.o
 obj-$(CONFIG_MEMORY_BALLOON) += balloon_compaction.o
 obj-$(CONFIG_PAGE_EXTENSION) += page_ext.o
+obj-$(CONFIG_CMA_DEBUGFS) += cma_debug.o
index 68ecb7a42983a589fe4c057f109e327b352c8a0b..2655b8191656b1b87bd20373eaac0e85110e3079 100644 (file)
--- a/mm/cma.c
+++ b/mm/cma.c
 #include <linux/highmem.h>
 #include <linux/io.h>
 
-struct cma {
-       unsigned long   base_pfn;
-       unsigned long   count;
-       unsigned long   *bitmap;
-       unsigned int order_per_bit; /* Order of pages represented by one bit */
-       struct mutex    lock;
-};
-
-static struct cma cma_areas[MAX_CMA_AREAS];
-static unsigned cma_area_count;
+#include "cma.h"
+
+struct cma cma_areas[MAX_CMA_AREAS];
+unsigned cma_area_count;
 static DEFINE_MUTEX(cma_mutex);
 
 phys_addr_t cma_get_base(struct cma *cma)
@@ -77,11 +71,6 @@ static unsigned long cma_bitmap_aligned_offset(struct cma *cma, int align_order)
                - cma->base_pfn) >> cma->order_per_bit;
 }
 
-static unsigned long cma_bitmap_maxno(struct cma *cma)
-{
-       return cma->count >> cma->order_per_bit;
-}
-
 static unsigned long cma_bitmap_pages_to_bits(struct cma *cma,
                                                unsigned long pages)
 {
diff --git a/mm/cma.h b/mm/cma.h
new file mode 100644 (file)
index 0000000..4141887
--- /dev/null
+++ b/mm/cma.h
@@ -0,0 +1,20 @@
+#ifndef __MM_CMA_H__
+#define __MM_CMA_H__
+
+struct cma {
+       unsigned long   base_pfn;
+       unsigned long   count;
+       unsigned long   *bitmap;
+       unsigned int order_per_bit; /* Order of pages represented by one bit */
+       struct mutex    lock;
+};
+
+extern struct cma cma_areas[MAX_CMA_AREAS];
+extern unsigned cma_area_count;
+
+static unsigned long cma_bitmap_maxno(struct cma *cma)
+{
+       return cma->count >> cma->order_per_bit;
+}
+
+#endif
diff --git a/mm/cma_debug.c b/mm/cma_debug.c
new file mode 100644 (file)
index 0000000..3af2de6
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * CMA DebugFS Interface
+ *
+ * Copyright (c) 2015 Sasha Levin <sasha.levin@oracle.com>
+ */
+
+
+#include <linux/debugfs.h>
+#include <linux/cma.h>
+
+#include "cma.h"
+
+static struct dentry *cma_debugfs_root;
+
+static int cma_debugfs_get(void *data, u64 *val)
+{
+       unsigned long *p = data;
+
+       *val = *p;
+
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(cma_debugfs_fops, cma_debugfs_get, NULL, "%llu\n");
+
+static void cma_debugfs_add_one(struct cma *cma, int idx)
+{
+       struct dentry *tmp;
+       char name[16];
+       int u32s;
+
+       sprintf(name, "cma-%d", idx);
+
+       tmp = debugfs_create_dir(name, cma_debugfs_root);
+
+       debugfs_create_file("base_pfn", S_IRUGO, tmp,
+                               &cma->base_pfn, &cma_debugfs_fops);
+       debugfs_create_file("count", S_IRUGO, tmp,
+                               &cma->count, &cma_debugfs_fops);
+       debugfs_create_file("order_per_bit", S_IRUGO, tmp,
+                       &cma->order_per_bit, &cma_debugfs_fops);
+
+       u32s = DIV_ROUND_UP(cma_bitmap_maxno(cma), BITS_PER_BYTE * sizeof(u32));
+       debugfs_create_u32_array("bitmap", S_IRUGO, tmp, (u32*)cma->bitmap, u32s);
+}
+
+static int __init cma_debugfs_init(void)
+{
+       int i;
+
+       cma_debugfs_root = debugfs_create_dir("cma", NULL);
+       if (!cma_debugfs_root)
+               return -ENOMEM;
+
+       for (i = 0; i < cma_area_count; i++)
+               cma_debugfs_add_one(&cma_areas[i], i);
+
+       return 0;
+}
+late_initcall(cma_debugfs_init);