[PATCH v2 0/5] rewritten memtest command

Sascha Hauer s.hauer at pengutronix.de
Tue Jun 26 14:44:21 EDT 2012


Hi Alexander,

On Thu, Jun 14, 2012 at 04:01:39PM +0200, Alexander Aring wrote:
> Rewritten memtest command.
> Added new section data which is between text and bss.
> Only tested on arm architecture.

It took a while until I found some time to have a closer look at this. I
was a bit concerned about the fact that the new memtest command depends
on some very lowlevel internal barebox APIs. Anyway, I gave it a try and
it actually works quite well. Thanks for working on it, the new memtest
seems much more trustworthy than the old test(s).

I found some problems with the calculation of used regions, so I would
like to add the following to your patch, if that's ok with you. It also
adds a progress bar and the possibility to interrupt the test during an
iteration.

Sascha

8<-------------------------------------------------------

memtest updates

- fix calculation of regions to test. When we use PAGE_ALIGN on
  size, size can be to high.
  - start address has to be aligned up
  - end address has to be aligned down
  - then size can be calculated as end - start + 1
- Add ctrlc() to the longer loops
- Add a progress bar to give some visual feedback that something is
  still going on.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 commands/memtest.c |  128 ++++++++++++++++++++++++++++++----------------------
 1 file changed, 74 insertions(+), 54 deletions(-)

diff --git a/commands/memtest.c b/commands/memtest.c
index ff7aac2..683765b 100644
--- a/commands/memtest.c
+++ b/commands/memtest.c
@@ -31,6 +31,8 @@
 #include <types.h>
 #include <getopt.h>
 #include <memory.h>
+#include <errno.h>
+#include <progress.h>
 #include <asm/mmu.h>
 
 static const vu_long bitpattern[] = {
@@ -69,12 +71,6 @@ static int mem_test(vu_long _start, vu_long _end,
 
 	num_words = (_end - _start)/sizeof(vu_long);
 
-	/* Exit if ctrl-c is pressed */
-	if (ctrlc()) {
-		printf("Memtest interrupted.\n");
-		return -1;
-	}
-
 	printf("Starting data line test.\n");
 
 	/*
@@ -311,53 +307,78 @@ static int mem_test(vu_long _start, vu_long _end,
 	/*
 	 * Fill memory with a known pattern.
 	 */
-	for (offset = 0; offset < (num_words); offset++) {
+	init_progression_bar(num_words);
+	for (offset = 0; offset < num_words; offset++) {
+		if (!(offset & 0xfff)) {
+			if (ctrlc())
+				return -EINTR;
+			show_progress(offset);
+		}
+
 		ret = address_in_sdram_regions((vu_long)&start[offset]);
 		if (ret)
 			continue;
 
-		start[offset] = offset+1;
+		start[offset] = offset + 1;
 	}
 
-	printf("Compare written patterns...\n");
+	show_progress(offset);
+
+	printf("\nCompare written patterns...\n");
 
 	/*
 	 * Check each location and invert it for the second pass.
 	 */
+	init_progression_bar(num_words - 1);
 	for (offset = 0; offset < num_words; offset++) {
+		if (!(offset & 0xfff)) {
+			if (ctrlc())
+				return -EINTR;
+			show_progress(offset);
+		}
+
 		ret = address_in_sdram_regions((vu_long)&start[offset]);
 		if (ret)
 			continue;
 
 		temp = start[offset];
-		if (temp != (offset+1)) {
-			printf("FAILURE (read/write) @ 0x%08lx:"
+		if (temp != (offset + 1)) {
+			printf("\nFAILURE (read/write) @ 0x%08lx:"
 					" expected 0x%08lx, actual 0x%08lx.\n",
 					(vu_long)&start[offset],
-					(offset+1), temp);
+					(offset + 1), temp);
 			return -1;
 		}
 
-		anti_pattern = ~(offset+1);
+		anti_pattern = ~(offset + 1);
 		start[offset] = anti_pattern;
 	}
 
-	printf("Filling ram with inverted pattern and compare it...\n");
+	show_progress(offset);
+
+	printf("\nFilling ram with inverted pattern and compare it...\n");
 
 	/*
 	 * Check each location for the inverted pattern and zero it.
 	 */
+	init_progression_bar(num_words - 1);
 	for (offset = 0; offset < num_words; offset++) {
+		if (!(offset & 0xfff)) {
+			if (ctrlc())
+				return -EINTR;
+			show_progress(offset);
+		}
+
 		ret = address_in_sdram_regions((vu_long)&start[offset]);
 		/* Step over barebox mem usage */
 		if (ret)
 			continue;
 
-		anti_pattern = ~(offset+1);
+		anti_pattern = ~(offset + 1);
 		temp = start[offset];
 
 		if (temp != anti_pattern) {
-			printf("FAILURE (read/write): @ 0x%08lx:"
+			printf("\nFAILURE (read/write): @ 0x%08lx:"
 					" expected 0x%08lx, actual 0x%08lx.\n",
 					(vu_long)&start[offset],
 					anti_pattern, temp);
@@ -367,6 +388,8 @@ static int mem_test(vu_long _start, vu_long _end,
 		start[offset] = 0;
 	}
 
+	show_progress(offset);
+
 	return 0;
 }
 
@@ -378,14 +401,12 @@ static void print_region(vu_long start, vu_long size, uint32_t flags)
 
 	switch (flags) {
 	case PTE_FLAGS_UNCACHED:
-		printf("Set non caching region at 0x%08lx until"
-				" 0x%08lx size 0x%08lx.\n", start,
-				start + size, size);
+		printf("Set non caching region at 0x%08lx - 0x%08lx size 0x%08lx.\n",
+				start, start + size - 1, size);
 		break;
 	case PTE_FLAGS_CACHED:
-		printf("Set caching region at 0x%08lx until"
-				" 0x%08lx size 0x%08lx.\n", start,
-				start + size, size);
+		printf("Set caching region at 0x%08lx - 0x%08lx size 0x%08lx.\n",
+				start, start + size - 1, size);
 		break;
 	default:
 		/* This should never happen. */
@@ -394,6 +415,8 @@ static void print_region(vu_long start, vu_long size, uint32_t flags)
 	}
 }
 
+#define PAGE_ALIGN_DOWN(x) ((x) & ~(PAGE_SIZE - 1))
+
 static void do_remap_range(struct memory_bank *bank, uint32_t flags)
 {
 	struct resource *r = NULL;
@@ -407,41 +430,37 @@ static void do_remap_range(struct memory_bank *bank, uint32_t flags)
 	list_for_each_entry(r, &bank->res->children, sibling) {
 		/* Do on head element for bank boundary */
 		if (r->sibling.prev == &bank->res->children) {
-			start = bank->start;
-			end = r->start;
-			size = end - start;
+			/* remember last used element */
+			r_prev = r;
 
-			size = PAGE_ALIGN(size);
-			start = PAGE_ALIGN(start);
+			start = PAGE_ALIGN(bank->start);
+			end = PAGE_ALIGN_DOWN(r->start) - 1;
+			if (start >= end)
+				continue;
+			size = end - start + 1;
 
 			print_region(start, size, flags);
 			remap_range((void *)start, size, flags);
 
-			/* remember last used element */
-			r_prev = r;
 			continue;
 		}
 		/* Between used regions */
-		start = r_prev->start + r_prev->size;
-		end = r->start;
-		size = end - start;
-
-
-		size = PAGE_ALIGN(size);
-		start = PAGE_ALIGN(start);
-
-		print_region(start, size, flags);
-		remap_range((void *)start, size, flags);
+		start = PAGE_ALIGN(r_prev->start + r_prev->size);
+		end = PAGE_ALIGN_DOWN(r->start) - 1;
+		if (start < end) {
+			size = end - start + 1;
+			print_region(start, size, flags);
+			remap_range((void *)start, size, flags);
+		}
 
 		r_prev = r;
 		/* Do on head element for bank boundary */
 		if (list_is_last(&r->sibling, &bank->res->children)) {
-			start = r->start + r->size;
-			end = bank->start + bank->size;
-			size = end - start;
-
-			size = PAGE_ALIGN(size);
-			start = PAGE_ALIGN(start);
+			start = PAGE_ALIGN(r->start + r->size);
+			end = PAGE_ALIGN_DOWN(bank->start + bank->size) - 1;
+			if (start >= end)
+				continue;
+			size = end - start + 1;
 
 			print_region(start, size, flags);
 			remap_range((void *)start, size, flags);
@@ -490,7 +509,7 @@ static int do_mem_memtest(int argc, char *argv[])
 
 	/* Error if no end address */
 	if (start && !end) {
-		printf("Please add a end address.\n");
+		printf("Please add an end address.\n");
 		return 1;
 	}
 
@@ -532,9 +551,8 @@ static int do_mem_memtest(int argc, char *argv[])
 
 	for_each_memory_bank(bank) {
 		list_for_each_entry(r, &bank->res->children, sibling)
-			printf("Will skipping region at 0x%08x"
-					" until 0x%08x size 0x%08x name %s.\n",
-					r->start, r->size + r->start,
+			printf("Skipping region at 0x%08x - 0x%08x, size 0x%08x (%s)\n",
+					r->start, r->size + r->start - 1,
 					r->size, r->name);
 #ifdef CONFIG_MMU
 		/* Disable caching */
@@ -544,8 +562,7 @@ static int do_mem_memtest(int argc, char *argv[])
 
 	/* Do test if we set a start or end address */
 	if (start && end) {
-		printf("Testing address range: 0x%08lx until "
-				"0x%08lx.\n",
+		printf("Testing address range: 0x%08lx - 0x%08lx.\n",
 				start, end);
 
 		for (i = 1; (i <= max_i) || !max_i; i++) {
@@ -553,6 +570,10 @@ static int do_mem_memtest(int argc, char *argv[])
 
 			/* Do the memtest */
 			err = mem_test(start, end, bus_only);
+			if (err == -EINTR) {
+				printf("Test interrupted\n");
+				goto err;
+			}
 
 			if (err < 0) {
 				printf("Test failed.\n");
@@ -577,8 +598,7 @@ static int do_mem_memtest(int argc, char *argv[])
 			start = bank->start;
 			end = bank->start + bank->size;
 
-			printf("Testing address range: 0x%08lx until "
-					"0x%08lx on bank /dev/%s.\n",
+			printf("Testing address range: 0x%08lx - 0x%08lx on bank /dev/%s.\n",
 					start, end, bank->res->name);
 
 			printf("Iteration: %u\n", i);
@@ -624,4 +644,4 @@ BAREBOX_CMD_START(memtest)
 	.cmd		= do_mem_memtest,
 	.usage		= "Memory Test",
 	BAREBOX_CMD_HELP(cmd_memtest_help)
-	BAREBOX_CMD_END
+BAREBOX_CMD_END
-- 
1.7.10


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



More information about the barebox mailing list