diff mbox

[5/6] Pmalloc: self-test

Message ID 20180204170056.28772-1-igor.stoppa@huawei.com (mailing list archive)
State New, archived
Headers show

Commit Message

Igor Stoppa Feb. 4, 2018, 5 p.m. UTC
Add basic self-test functionality for pmalloc.

Signed-off-by: Igor Stoppa <igor.stoppa@huawei.com>
---
 mm/Kconfig            |  9 ++++++++
 mm/Makefile           |  1 +
 mm/pmalloc-selftest.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++
 mm/pmalloc-selftest.h | 26 ++++++++++++++++++++++
 4 files changed, 97 insertions(+)
 create mode 100644 mm/pmalloc-selftest.c
 create mode 100644 mm/pmalloc-selftest.h

Comments

kernel test robot Feb. 7, 2018, 5:18 p.m. UTC | #1
Hi Igor,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on kees/for-next/pstore]
[also build test ERROR on v4.15]
[cannot apply to linus/master mmotm/master next-20180207]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Igor-Stoppa/mm-security-ro-protection-for-dynamic-data/20180207-171252
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/pstore
config: i386-randconfig-s1-201805+bisect_validate (attached as .config)
compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   mm/pmalloc.o: In function `pmalloc_pool_show_chunks':
>> mm/pmalloc.c:100: undefined reference to `gen_pool_for_each_chunk'
   mm/pmalloc.o: In function `pmalloc_pool_show_size':
>> mm/pmalloc.c:81: undefined reference to `gen_pool_size'
   mm/pmalloc.o: In function `pmalloc_pool_show_avail':
>> mm/pmalloc.c:70: undefined reference to `gen_pool_avail'
   mm/pmalloc.o: In function `pmalloc_chunk_free':
>> mm/pmalloc.c:459: undefined reference to `gen_pool_flush_chunk'
   mm/pmalloc.o: In function `pmalloc_create_pool':
>> mm/pmalloc.c:173: undefined reference to `gen_pool_create'
>> mm/pmalloc.c:210: undefined reference to `gen_pool_destroy'
   mm/pmalloc.o: In function `gen_pool_add':
>> include/linux/genalloc.h:115: undefined reference to `gen_pool_add_virt'
   mm/pmalloc.o: In function `pmalloc':
>> mm/pmalloc.c:357: undefined reference to `gen_pool_alloc'
   mm/pmalloc.o: In function `gen_pool_add':
>> include/linux/genalloc.h:115: undefined reference to `gen_pool_add_virt'
   mm/pmalloc.o: In function `pmalloc':
   mm/pmalloc.c:386: undefined reference to `gen_pool_alloc'
   mm/pmalloc.o: In function `pmalloc_destroy_pool':
   mm/pmalloc.c:484: undefined reference to `gen_pool_for_each_chunk'
   mm/pmalloc.c:485: undefined reference to `gen_pool_destroy'

vim +100 mm/pmalloc.c

13e2be64 Igor Stoppa 2018-02-04   61  
13e2be64 Igor Stoppa 2018-02-04   62  static ssize_t pmalloc_pool_show_avail(struct kobject *dev,
13e2be64 Igor Stoppa 2018-02-04   63  				       struct kobj_attribute *attr,
13e2be64 Igor Stoppa 2018-02-04   64  				       char *buf)
13e2be64 Igor Stoppa 2018-02-04   65  {
13e2be64 Igor Stoppa 2018-02-04   66  	struct pmalloc_data *data;
13e2be64 Igor Stoppa 2018-02-04   67  
13e2be64 Igor Stoppa 2018-02-04   68  	data = container_of(attr, struct pmalloc_data, attr_avail);
13e2be64 Igor Stoppa 2018-02-04   69  	return sprintf(buf, "%lu\n",
13e2be64 Igor Stoppa 2018-02-04  @70  		       (unsigned long)gen_pool_avail(data->pool));
13e2be64 Igor Stoppa 2018-02-04   71  }
13e2be64 Igor Stoppa 2018-02-04   72  
13e2be64 Igor Stoppa 2018-02-04   73  static ssize_t pmalloc_pool_show_size(struct kobject *dev,
13e2be64 Igor Stoppa 2018-02-04   74  				      struct kobj_attribute *attr,
13e2be64 Igor Stoppa 2018-02-04   75  				      char *buf)
13e2be64 Igor Stoppa 2018-02-04   76  {
13e2be64 Igor Stoppa 2018-02-04   77  	struct pmalloc_data *data;
13e2be64 Igor Stoppa 2018-02-04   78  
13e2be64 Igor Stoppa 2018-02-04   79  	data = container_of(attr, struct pmalloc_data, attr_size);
13e2be64 Igor Stoppa 2018-02-04   80  	return sprintf(buf, "%lu\n",
13e2be64 Igor Stoppa 2018-02-04  @81  		       (unsigned long)gen_pool_size(data->pool));
13e2be64 Igor Stoppa 2018-02-04   82  }
13e2be64 Igor Stoppa 2018-02-04   83  
13e2be64 Igor Stoppa 2018-02-04   84  static void pool_chunk_number(struct gen_pool *pool,
13e2be64 Igor Stoppa 2018-02-04   85  			      struct gen_pool_chunk *chunk, void *data)
13e2be64 Igor Stoppa 2018-02-04   86  {
13e2be64 Igor Stoppa 2018-02-04   87  	unsigned long *counter = data;
13e2be64 Igor Stoppa 2018-02-04   88  
13e2be64 Igor Stoppa 2018-02-04   89  	(*counter)++;
13e2be64 Igor Stoppa 2018-02-04   90  }
13e2be64 Igor Stoppa 2018-02-04   91  
13e2be64 Igor Stoppa 2018-02-04   92  static ssize_t pmalloc_pool_show_chunks(struct kobject *dev,
13e2be64 Igor Stoppa 2018-02-04   93  					struct kobj_attribute *attr,
13e2be64 Igor Stoppa 2018-02-04   94  					char *buf)
13e2be64 Igor Stoppa 2018-02-04   95  {
13e2be64 Igor Stoppa 2018-02-04   96  	struct pmalloc_data *data;
13e2be64 Igor Stoppa 2018-02-04   97  	unsigned long chunks_num = 0;
13e2be64 Igor Stoppa 2018-02-04   98  
13e2be64 Igor Stoppa 2018-02-04   99  	data = container_of(attr, struct pmalloc_data, attr_chunks);
13e2be64 Igor Stoppa 2018-02-04 @100  	gen_pool_for_each_chunk(data->pool, pool_chunk_number, &chunks_num);
13e2be64 Igor Stoppa 2018-02-04  101  	return sprintf(buf, "%lu\n", chunks_num);
13e2be64 Igor Stoppa 2018-02-04  102  }
13e2be64 Igor Stoppa 2018-02-04  103  
13e2be64 Igor Stoppa 2018-02-04  104  /**
13e2be64 Igor Stoppa 2018-02-04  105   * Exposes the pool and its attributes through sysfs.
13e2be64 Igor Stoppa 2018-02-04  106   */
13e2be64 Igor Stoppa 2018-02-04  107  static struct kobject *pmalloc_connect(struct pmalloc_data *data)
13e2be64 Igor Stoppa 2018-02-04  108  {
13e2be64 Igor Stoppa 2018-02-04  109  	const struct attribute *attrs[] = {
13e2be64 Igor Stoppa 2018-02-04  110  		&data->attr_protected.attr,
13e2be64 Igor Stoppa 2018-02-04  111  		&data->attr_avail.attr,
13e2be64 Igor Stoppa 2018-02-04  112  		&data->attr_size.attr,
13e2be64 Igor Stoppa 2018-02-04  113  		&data->attr_chunks.attr,
13e2be64 Igor Stoppa 2018-02-04  114  		NULL
13e2be64 Igor Stoppa 2018-02-04  115  	};
13e2be64 Igor Stoppa 2018-02-04  116  	struct kobject *kobj;
13e2be64 Igor Stoppa 2018-02-04  117  
13e2be64 Igor Stoppa 2018-02-04  118  	kobj = kobject_create_and_add(data->pool->name, pmalloc_kobject);
13e2be64 Igor Stoppa 2018-02-04  119  	if (unlikely(!kobj))
13e2be64 Igor Stoppa 2018-02-04  120  		return NULL;
13e2be64 Igor Stoppa 2018-02-04  121  
13e2be64 Igor Stoppa 2018-02-04  122  	if (unlikely(sysfs_create_files(kobj, attrs) < 0)) {
13e2be64 Igor Stoppa 2018-02-04  123  		kobject_put(kobj);
13e2be64 Igor Stoppa 2018-02-04  124  		kobj = NULL;
13e2be64 Igor Stoppa 2018-02-04  125  	}
13e2be64 Igor Stoppa 2018-02-04  126  	return kobj;
13e2be64 Igor Stoppa 2018-02-04  127  }
13e2be64 Igor Stoppa 2018-02-04  128  
13e2be64 Igor Stoppa 2018-02-04  129  /**
13e2be64 Igor Stoppa 2018-02-04  130   * Removes the pool and its attributes from sysfs.
13e2be64 Igor Stoppa 2018-02-04  131   */
13e2be64 Igor Stoppa 2018-02-04  132  static void pmalloc_disconnect(struct pmalloc_data *data,
13e2be64 Igor Stoppa 2018-02-04  133  			       struct kobject *kobj)
13e2be64 Igor Stoppa 2018-02-04  134  {
13e2be64 Igor Stoppa 2018-02-04  135  	const struct attribute *attrs[] = {
13e2be64 Igor Stoppa 2018-02-04  136  		&data->attr_protected.attr,
13e2be64 Igor Stoppa 2018-02-04  137  		&data->attr_avail.attr,
13e2be64 Igor Stoppa 2018-02-04  138  		&data->attr_size.attr,
13e2be64 Igor Stoppa 2018-02-04  139  		&data->attr_chunks.attr,
13e2be64 Igor Stoppa 2018-02-04  140  		NULL
13e2be64 Igor Stoppa 2018-02-04  141  	};
13e2be64 Igor Stoppa 2018-02-04  142  
13e2be64 Igor Stoppa 2018-02-04  143  	sysfs_remove_files(kobj, attrs);
13e2be64 Igor Stoppa 2018-02-04  144  	kobject_put(kobj);
13e2be64 Igor Stoppa 2018-02-04  145  }
13e2be64 Igor Stoppa 2018-02-04  146  
13e2be64 Igor Stoppa 2018-02-04  147  /**
13e2be64 Igor Stoppa 2018-02-04  148   * Declares an attribute of the pool.
13e2be64 Igor Stoppa 2018-02-04  149   */
13e2be64 Igor Stoppa 2018-02-04  150  
13e2be64 Igor Stoppa 2018-02-04  151  #define pmalloc_attr_init(data, attr_name) \
13e2be64 Igor Stoppa 2018-02-04  152  do { \
13e2be64 Igor Stoppa 2018-02-04  153  	sysfs_attr_init(&data->attr_##attr_name.attr); \
13e2be64 Igor Stoppa 2018-02-04  154  	data->attr_##attr_name.attr.name = #attr_name; \
13e2be64 Igor Stoppa 2018-02-04  155  	data->attr_##attr_name.attr.mode = VERIFY_OCTAL_PERMISSIONS(0400); \
13e2be64 Igor Stoppa 2018-02-04  156  	data->attr_##attr_name.show = pmalloc_pool_show_##attr_name; \
13e2be64 Igor Stoppa 2018-02-04  157  } while (0)
13e2be64 Igor Stoppa 2018-02-04  158  
13e2be64 Igor Stoppa 2018-02-04  159  struct gen_pool *pmalloc_create_pool(const char *name, int min_alloc_order)
13e2be64 Igor Stoppa 2018-02-04  160  {
13e2be64 Igor Stoppa 2018-02-04  161  	struct gen_pool *pool;
13e2be64 Igor Stoppa 2018-02-04  162  	const char *pool_name;
13e2be64 Igor Stoppa 2018-02-04  163  	struct pmalloc_data *data;
13e2be64 Igor Stoppa 2018-02-04  164  
13e2be64 Igor Stoppa 2018-02-04  165  	if (!name) {
13e2be64 Igor Stoppa 2018-02-04  166  		WARN_ON(1);
13e2be64 Igor Stoppa 2018-02-04  167  		return NULL;
13e2be64 Igor Stoppa 2018-02-04  168  	}
13e2be64 Igor Stoppa 2018-02-04  169  
13e2be64 Igor Stoppa 2018-02-04  170  	if (min_alloc_order < 0)
13e2be64 Igor Stoppa 2018-02-04  171  		min_alloc_order = ilog2(sizeof(unsigned long));
13e2be64 Igor Stoppa 2018-02-04  172  
13e2be64 Igor Stoppa 2018-02-04 @173  	pool = gen_pool_create(min_alloc_order, NUMA_NO_NODE);
13e2be64 Igor Stoppa 2018-02-04  174  	if (unlikely(!pool))
13e2be64 Igor Stoppa 2018-02-04  175  		return NULL;
13e2be64 Igor Stoppa 2018-02-04  176  
13e2be64 Igor Stoppa 2018-02-04  177  	mutex_lock(&pmalloc_mutex);
13e2be64 Igor Stoppa 2018-02-04  178  	list_for_each_entry(data, pmalloc_list, node)
13e2be64 Igor Stoppa 2018-02-04  179  		if (!strcmp(name, data->pool->name))
13e2be64 Igor Stoppa 2018-02-04  180  			goto same_name_err;
13e2be64 Igor Stoppa 2018-02-04  181  
13e2be64 Igor Stoppa 2018-02-04  182  	pool_name = kstrdup(name, GFP_KERNEL);
13e2be64 Igor Stoppa 2018-02-04  183  	if (unlikely(!pool_name))
13e2be64 Igor Stoppa 2018-02-04  184  		goto name_alloc_err;
13e2be64 Igor Stoppa 2018-02-04  185  
13e2be64 Igor Stoppa 2018-02-04  186  	data = kzalloc(sizeof(struct pmalloc_data), GFP_KERNEL);
13e2be64 Igor Stoppa 2018-02-04  187  	if (unlikely(!data))
13e2be64 Igor Stoppa 2018-02-04  188  		goto data_alloc_err;
13e2be64 Igor Stoppa 2018-02-04  189  
13e2be64 Igor Stoppa 2018-02-04  190  	data->protected = false;
13e2be64 Igor Stoppa 2018-02-04  191  	data->pool = pool;
13e2be64 Igor Stoppa 2018-02-04  192  	pmalloc_attr_init(data, protected);
13e2be64 Igor Stoppa 2018-02-04  193  	pmalloc_attr_init(data, avail);
13e2be64 Igor Stoppa 2018-02-04  194  	pmalloc_attr_init(data, size);
13e2be64 Igor Stoppa 2018-02-04  195  	pmalloc_attr_init(data, chunks);
13e2be64 Igor Stoppa 2018-02-04  196  	pool->data = data;
13e2be64 Igor Stoppa 2018-02-04  197  	pool->name = pool_name;
13e2be64 Igor Stoppa 2018-02-04  198  
13e2be64 Igor Stoppa 2018-02-04  199  	list_add(&data->node, pmalloc_list);
13e2be64 Igor Stoppa 2018-02-04  200  	if (pmalloc_list == &pmalloc_final_list)
13e2be64 Igor Stoppa 2018-02-04  201  		data->pool_kobject = pmalloc_connect(data);
13e2be64 Igor Stoppa 2018-02-04  202  	mutex_unlock(&pmalloc_mutex);
13e2be64 Igor Stoppa 2018-02-04  203  	return pool;
13e2be64 Igor Stoppa 2018-02-04  204  
13e2be64 Igor Stoppa 2018-02-04  205  data_alloc_err:
13e2be64 Igor Stoppa 2018-02-04  206  	kfree(pool_name);
13e2be64 Igor Stoppa 2018-02-04  207  name_alloc_err:
13e2be64 Igor Stoppa 2018-02-04  208  same_name_err:
13e2be64 Igor Stoppa 2018-02-04  209  	mutex_unlock(&pmalloc_mutex);
13e2be64 Igor Stoppa 2018-02-04 @210  	gen_pool_destroy(pool);
13e2be64 Igor Stoppa 2018-02-04  211  	return NULL;
13e2be64 Igor Stoppa 2018-02-04  212  }
13e2be64 Igor Stoppa 2018-02-04  213  

:::::: The code at line 100 was first introduced by commit
:::::: 13e2be64b34fce3c12159af55855eef7a8b4a54f Protectable Memory

:::::: TO: Igor Stoppa <igor.stoppa@huawei.com>
:::::: CC: 0day robot <fengguang.wu@intel.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Igor Stoppa Feb. 11, 2018, 1:28 a.m. UTC | #2
On 07/02/18 19:18, kbuild test robot wrote:
> Hi Igor,
> 
> Thank you for the patch! Yet something to improve:
> 
> [auto build test ERROR on kees/for-next/pstore]
> [also build test ERROR on v4.15]
> [cannot apply to linus/master mmotm/master next-20180207]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
> 
> url:    https://github.com/0day-ci/linux/commits/Igor-Stoppa/mm-security-ro-protection-for-dynamic-data/20180207-171252
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/pstore
> config: i386-randconfig-s1-201805+bisect_validate (attached as .config)
> compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026
> reproduce:
>         # save the attached .config to linux build tree
>         make ARCH=i386 
> 
> All errors (new ones prefixed by >>):
> 
>    mm/pmalloc.o: In function `pmalloc_pool_show_chunks':
>>> mm/pmalloc.c:100: undefined reference to `gen_pool_for_each_chunk'
>    mm/pmalloc.o: In function `pmalloc_pool_show_size':
>>> mm/pmalloc.c:81: undefined reference to `gen_pool_size'
>    mm/pmalloc.o: In function `pmalloc_pool_show_avail':
>>> mm/pmalloc.c:70: undefined reference to `gen_pool_avail'
>    mm/pmalloc.o: In function `pmalloc_chunk_free':
>>> mm/pmalloc.c:459: undefined reference to `gen_pool_flush_chunk'
>    mm/pmalloc.o: In function `pmalloc_create_pool':
>>> mm/pmalloc.c:173: undefined reference to `gen_pool_create'
>>> mm/pmalloc.c:210: undefined reference to `gen_pool_destroy'
>    mm/pmalloc.o: In function `gen_pool_add':
>>> include/linux/genalloc.h:115: undefined reference to `gen_pool_add_virt'
>    mm/pmalloc.o: In function `pmalloc':
>>> mm/pmalloc.c:357: undefined reference to `gen_pool_alloc'
>    mm/pmalloc.o: In function `gen_pool_add':
>>> include/linux/genalloc.h:115: undefined reference to `gen_pool_add_virt'
>    mm/pmalloc.o: In function `pmalloc':
>    mm/pmalloc.c:386: undefined reference to `gen_pool_alloc'
>    mm/pmalloc.o: In function `pmalloc_destroy_pool':
>    mm/pmalloc.c:484: undefined reference to `gen_pool_for_each_chunk'
>    mm/pmalloc.c:485: undefined reference to `gen_pool_destroy'

Wrong default value for the pmalloc Kconfig option, it must default to
true. Will fix it.

--
igor
diff mbox

Patch

diff --git a/mm/Kconfig b/mm/Kconfig
index 03ff7703d322..f5edfadd036a 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -765,3 +765,12 @@  config GUP_BENCHMARK
 	  performance of get_user_pages_fast().
 
 	  See tools/testing/selftests/vm/gup_benchmark.c
+
+config PROTECTABLE_MEMORY_SELFTEST
+	bool "Run self test for pmalloc memory allocator"
+	depends on ARCH_HAS_SET_MEMORY
+	select GENERIC_ALLOCATOR
+	default n
+	help
+	  Tries to verify that pmalloc works correctly and that the memory
+	  is effectively protected.
diff --git a/mm/Makefile b/mm/Makefile
index a6a47e1b6e66..1e76a9b96180 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -66,6 +66,7 @@  obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o
 obj-$(CONFIG_SLOB) += slob.o
 obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o
 obj-$(CONFIG_ARCH_HAS_SET_MEMORY) += pmalloc.o
+obj-$(CONFIG_PROTECTABLE_MEMORY_SELFTEST) += pmalloc-selftest.o
 obj-$(CONFIG_KSM) += ksm.o
 obj-$(CONFIG_PAGE_POISONING) += page_poison.o
 obj-$(CONFIG_SLAB) += slab.o
diff --git a/mm/pmalloc-selftest.c b/mm/pmalloc-selftest.c
new file mode 100644
index 000000000000..9f6401ebd8d1
--- /dev/null
+++ b/mm/pmalloc-selftest.c
@@ -0,0 +1,61 @@ 
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * pmalloc-selftest.c
+ *
+ * (C) Copyright 2018 Huawei Technologies Co. Ltd.
+ * Author: Igor Stoppa <igor.stoppa@huawei.com>
+ */
+
+#include <linux/pmalloc.h>
+#include <linux/mm.h>
+
+
+#define SIZE_1 (PAGE_SIZE * 3)
+#define SIZE_2 1000
+
+#define validate_alloc(expected, variable, size)	\
+	pr_notice("must be " expected ": %s",		\
+		  is_pmalloc_object(variable, size) > 0 ? "ok" : "no")
+
+#define is_alloc_ok(variable, size)	\
+	validate_alloc("ok", variable, size)
+
+#define is_alloc_no(variable, size)	\
+	validate_alloc("no", variable, size)
+
+void pmalloc_selftest(void)
+{
+	struct gen_pool *pool_unprot;
+	struct gen_pool *pool_prot;
+	void *var_prot, *var_unprot, *var_vmall;
+
+	pr_notice("pmalloc self-test");
+	pool_unprot = pmalloc_create_pool("unprotected", 0);
+	pool_prot = pmalloc_create_pool("protected", 0);
+	BUG_ON(!(pool_unprot && pool_prot));
+
+	var_unprot = pmalloc(pool_unprot,  SIZE_1 - 1, GFP_KERNEL);
+	var_prot = pmalloc(pool_prot,  SIZE_1, GFP_KERNEL);
+	var_vmall = vmalloc(SIZE_2);
+	is_alloc_ok(var_unprot, 10);
+	is_alloc_ok(var_unprot, SIZE_1);
+	is_alloc_ok(var_unprot, PAGE_SIZE);
+	is_alloc_no(var_unprot, SIZE_1 + 1);
+	is_alloc_no(var_vmall, 10);
+
+
+	pfree(pool_unprot, var_unprot);
+	vfree(var_vmall);
+
+	pmalloc_protect_pool(pool_prot);
+
+	/* This will intentionally trigger a WARN because the pool being
+	 * destroyed is not protected, which is unusual and should happen
+	 * on error paths only, where probably other warnings are already
+	 * displayed.
+	 */
+	pmalloc_destroy_pool(pool_unprot);
+
+	/* This must not cause WARNings */
+	pmalloc_destroy_pool(pool_prot);
+}
diff --git a/mm/pmalloc-selftest.h b/mm/pmalloc-selftest.h
new file mode 100644
index 000000000000..b34ac86e14a8
--- /dev/null
+++ b/mm/pmalloc-selftest.h
@@ -0,0 +1,26 @@ 
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * pmalloc-selftest.h
+ *
+ * (C) Copyright 2018 Huawei Technologies Co. Ltd.
+ * Author: Igor Stoppa <igor.stoppa@huawei.com>
+ */
+
+
+#ifndef __PMALLOC_SELFTEST_H__
+#define __PMALLOC_SELFTEST_H__
+
+
+#ifdef CONFIG_PROTECTABLE_MEMORY_SELFTEST
+
+#include <linux/pmalloc.h>
+
+void pmalloc_selftest(void);
+
+#else
+
+static inline void pmalloc_selftest(void){};
+
+#endif
+
+#endif