From: Alexander Aring <alex.aring@gmail.com>
To: barebox@lists.infradead.org
Subject: [PATCH 5/5] commands: add new memtest command
Date: Tue, 4 Jun 2013 01:13:52 +0200 [thread overview]
Message-ID: <1370301232-12962-6-git-send-email-alex.aring@gmail.com> (raw)
In-Reply-To: <1370301232-12962-1-git-send-email-alex.aring@gmail.com>
This new memtest can test the whole unused memory. The new memtest
command try to request the whole unused sdram regions on all banks and
run the mem_test routine from common/memtest.c on it.
The memtest command has only two parameters;
-i Amount of iterations, default 1, iteration of 0 is endless.
-b Set this to skip integrity check.(Do only a fast test for bus lines)
If MMU support is enable, memtest try to run memtest twice. The first with
cache enabled, the second with cache disabled.
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
commands/Kconfig | 10 +++
commands/Makefile | 1 +
commands/memtest.c | 250 +++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 261 insertions(+)
create mode 100644 commands/memtest.c
diff --git a/commands/Kconfig b/commands/Kconfig
index add547f..9135f5d 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -561,6 +561,16 @@ config CMD_NANDTEST
select PARTITION_NEED_MTD
prompt "nandtest"
+config CMD_MEMTEST
+ tristate
+ prompt "memtest"
+ help
+ The memtest command can test the registered barebox memory.
+ During this test barebox memory regions like heap, stack, ...
+ will be skipped. If the tested architecture has MMU with PTE
+ flags support, the memtest is running twice with cache enabled
+ and with cache disabled
+
endmenu
menu "video command"
diff --git a/commands/Makefile b/commands/Makefile
index 9d34a56..0ae01a5 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_CMD_SAVEENV) += saveenv.o
obj-$(CONFIG_CMD_LOADENV) += loadenv.o
obj-$(CONFIG_CMD_NAND) += nand.o
obj-$(CONFIG_CMD_NANDTEST) += nandtest.o
+obj-$(CONFIG_CMD_MEMTEST) += memtest.o
obj-$(CONFIG_CMD_TRUE) += true.o
obj-$(CONFIG_CMD_FALSE) += false.o
obj-$(CONFIG_CMD_VERSION) += version.o
diff --git a/commands/memtest.c b/commands/memtest.c
new file mode 100644
index 0000000..a67d868
--- /dev/null
+++ b/commands/memtest.c
@@ -0,0 +1,250 @@
+/*
+ * memtest - Perform a memory test
+ *
+ * (C) Copyright 2013
+ * Alexander Aring <aar@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <command.h>
+#include <getopt.h>
+#include <asm/mmu.h>
+#include <memory.h>
+
+#include <memtest.h>
+
+static int alloc_memtest_region(struct list_head *list,
+ resource_size_t start, resource_size_t size)
+{
+ struct resource *r_new;
+ struct mem_test_resource *r;
+
+ r = xzalloc(sizeof(struct mem_test_resource));
+ r_new = request_sdram_region("memtest", start, size);
+ if (!r_new)
+ return -EINVAL;
+
+ r->r = r_new;
+ list_add_tail(&r->list, list);
+
+ return 0;
+}
+
+static int request_memtest_regions(struct list_head *list)
+{
+ int ret;
+ struct memory_bank *bank;
+ struct resource *r, *r_prev = NULL;
+ resource_size_t start, end, size;
+
+ for_each_memory_bank(bank) {
+ /*
+ * If we don't have any allocated region on bank,
+ * we use the whole bank boundary
+ */
+ if (list_empty(&bank->res->children)) {
+ start = PAGE_ALIGN(bank->res->start);
+ end = PAGE_ALIGN_DOWN(bank->res->end) - 1;
+ size = end - start + 1;
+
+ ret = alloc_memtest_region(list, start, size);
+ if (ret < 0)
+ return ret;
+
+ continue;
+ }
+
+ /*
+ * We assume that the regions are sorted in this list
+ * So the first element has start boundary on bank->res->start
+ * and the last element hast end boundary on bank->res->end
+ */
+ list_for_each_entry(r, &bank->res->children, sibling) {
+ /*
+ * Do on head element for bank boundary
+ */
+ if (r->sibling.prev == &bank->res->children) {
+ /*
+ * remember last used element
+ */
+ start = PAGE_ALIGN(bank->res->start);
+ end = PAGE_ALIGN_DOWN(r->start) - 1;
+ size = end - start + 1;
+ r_prev = r;
+ if (start >= end)
+ continue;
+
+ ret = alloc_memtest_region(list, start, size);
+ if (ret < 0)
+ return ret;
+ continue;
+ }
+ /*
+ * Between used regions
+ */
+ start = PAGE_ALIGN(r_prev->end);
+ end = PAGE_ALIGN_DOWN(r->start) - 1;
+ size = end - start + 1;
+ r_prev = r;
+ if (start >= end)
+ continue;
+
+ ret = alloc_memtest_region(list, start, size);
+ if (ret < 0)
+ return ret;
+
+ if (list_is_last(&r->sibling, &bank->res->children)) {
+ /*
+ * Do on head element for bank boundary
+ */
+ start = PAGE_ALIGN(r->end);
+ end = PAGE_ALIGN_DOWN(bank->res->end) - 1;
+ size = end - start + 1;
+ if (start >= end)
+ continue;
+
+ ret = alloc_memtest_region(list, start, size);
+ if (ret < 0)
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int __do_memtest(struct list_head *memtest_regions,
+ int bus_only, uint32_t cache_flag)
+{
+ struct mem_test_resource *r;
+ int ret;
+
+ list_for_each_entry(r, memtest_regions, list) {
+ printf("Testing memory space: "
+ "0x%08x -> 0x%08x:\n",
+ r->r->start, r->r->end);
+ remap_range((void *)r->r->start, r->r->end -
+ r->r->start + 1, cache_flag);
+
+ ret = mem_test(r->r->start, r->r->end, bus_only);
+ if (ret < 0)
+ return ret;
+ printf("done.\n\n");
+ }
+
+ return 0;
+}
+
+static int do_memtest(int argc, char *argv[])
+{
+ int bus_only = 0, ret, opt;
+ uint32_t i, max_i = 1, pte_flags_cached, pte_flags_uncached;
+ struct mem_test_resource *r, *r_tmp;
+ struct list_head memtest_used_regions;
+
+ while ((opt = getopt(argc, argv, "i:b")) > 0) {
+ switch (opt) {
+ case 'i':
+ max_i = simple_strtoul(optarg, NULL, 0);
+ break;
+ case 'b':
+ bus_only = 1;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ if (optind > argc)
+ return COMMAND_ERROR_USAGE;
+
+ /*
+ * Get pte flags for enable and disable cache support on page.
+ */
+ pte_flags_cached = mmu_get_pte_cached_flags();
+ pte_flags_uncached = mmu_get_pte_uncached_flags();
+
+ INIT_LIST_HEAD(&memtest_used_regions);
+
+ ret = request_memtest_regions(&memtest_used_regions);
+ if (ret < 0)
+ goto out;
+
+ for (i = 1; (i <= max_i) || !max_i; i++) {
+ if (max_i)
+ printf("Start iteration %u of %u.\n", i, max_i);
+ /*
+ * First try a memtest with caching enabled.
+ */
+ if (IS_ENABLED(CONFIG_MMU)) {
+ printf("Do memtest with caching enabled.\n");
+ ret = __do_memtest(&memtest_used_regions,
+ bus_only, pte_flags_cached);
+ if (ret < 0)
+ goto out;
+ }
+ /*
+ * Second try a memtest with caching disabled.
+ */
+ printf("Do memtest with caching disabled.\n");
+ ret = __do_memtest(&memtest_used_regions,
+ bus_only, pte_flags_uncached);
+ if (ret < 0)
+ goto out;
+ }
+
+out:
+ list_for_each_entry_safe(r, r_tmp, &memtest_used_regions, list) {
+ /*
+ * Ensure to leave with a cached on non used sdram regions.
+ */
+ remap_range((void *)r->r->start, r->r->end -
+ r->r->start + 1, pte_flags_cached);
+ release_sdram_region(r->r);
+ free(r);
+ }
+
+ if (ret < 0) {
+ /*
+ * Set cursor to newline, because mem_test failed at
+ * drawing of progressbar.
+ */
+ if (ret == -EINTR)
+ printf("\n");
+
+ printf("Memtest failed.\n");
+ return 1;
+ } else {
+ printf("Memtest successful.\n");
+ return 1;
+ }
+}
+
+static const __maybe_unused char cmd_memtest_help[] =
+"Usage: memtest [OPTION]...\n"
+"memtest related commands\n"
+" -i <iterations> iterations [default=1, endless=0].\n"
+" -b perform only a test on buslines.";
+
+BAREBOX_CMD_START(memtest)
+ .cmd = do_memtest,
+ .usage = "Memory Test",
+ BAREBOX_CMD_HELP(cmd_memtest_help)
+BAREBOX_CMD_END
--
1.8.3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2013-06-03 23:11 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-03 23:13 [PATCH/RFC 0/5] Another try for a new memtest implementation Alexander Aring
2013-06-03 23:13 ` [PATCH 1/5] common: fix codestyle in ALIGN macros Alexander Aring
2013-06-03 23:13 ` [PATCH 2/5] common: add ALIGN_DOWN macro Alexander Aring
2013-06-03 23:13 ` [PATCH 3/5] memtest: remove memtest command Alexander Aring
2013-06-03 23:13 ` [PATCH 4/5] common: add memtest.c with mem_test routine Alexander Aring
2013-06-03 23:13 ` Alexander Aring [this message]
2013-06-05 21:15 ` [PATCH/RFC 0/5] Another try for a new memtest implementation Sascha Hauer
2013-06-06 7:52 ` antonynpavlov
2013-06-06 17:52 ` Alexander Aring
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1370301232-12962-6-git-send-email-alex.aring@gmail.com \
--to=alex.aring@gmail.com \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox