[PATCH 10/10] ARM: pbl: Add an option to validate DRAM
Andrey Smirnov
andrew.smirnov at gmail.com
Wed May 13 19:54:27 PDT 2015
Add an option to perform DRAM region validation before using it. The
framework allows individual boards to set up a memory validaion hook
that would be called prior to Barebox using that region of memory.
Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
arch/arm/cpu/start.c | 14 +-----------
arch/arm/cpu/uncompress.c | 32 ++++++++++++++++++++++++---
arch/arm/include/asm/barebox-arm.h | 28 ++++++++++++++++++++++++
common/Kconfig | 8 +++++++
common/Makefile | 2 +-
include/common.h | 1 +
include/memtest.h | 19 ++++++++++++++++
lib/Makefile | 6 ++++++
pbl/misc.c | 44 ++++++++++++++++++++++++++++++++++++++
9 files changed, 137 insertions(+), 17 deletions(-)
diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
index 304ed0c..ee7eb00 100644
--- a/arch/arm/cpu/start.c
+++ b/arch/arm/cpu/start.c
@@ -105,19 +105,7 @@ static noinline __noreturn void __start(unsigned long membase,
else
malloc_end = (unsigned long)_text;
- /*
- * Maximum malloc space is the Kconfig value if given
- * or 1GB.
- */
- if (MALLOC_SIZE > 0) {
- malloc_start = malloc_end - MALLOC_SIZE;
- if (malloc_start < membase)
- malloc_start = membase;
- } else {
- malloc_start = malloc_end - (malloc_end - membase) / 2;
- if (malloc_end - malloc_start > SZ_1G)
- malloc_start = malloc_end - SZ_1G;
- }
+ malloc_start = arm_get_malloc_start(membase, malloc_end);
pr_debug("initializing malloc pool at 0x%08lx (size 0x%08lx)\n",
malloc_start, malloc_end - malloc_start);
diff --git a/arch/arm/cpu/uncompress.c b/arch/arm/cpu/uncompress.c
index b0b7c6d..853d2a3 100644
--- a/arch/arm/cpu/uncompress.c
+++ b/arch/arm/cpu/uncompress.c
@@ -20,6 +20,7 @@
#define pr_fmt(fmt) "uncompress.c: " fmt
#include <common.h>
+#include <memtest.h>
#include <init.h>
#include <linux/sizes.h>
#include <pbl.h>
@@ -47,6 +48,7 @@ static void __noreturn noinline uncompress_start_payload(unsigned long membase,
uint32_t pg_len;
void __noreturn (*barebox)(unsigned long, unsigned long, void *);
uint32_t endmem = membase + memsize;
+ unsigned long malloc_start, malloc_end;
unsigned long barebox_base;
uint32_t *image_end;
void *pg_start;
@@ -64,10 +66,14 @@ static void __noreturn noinline uncompress_start_payload(unsigned long membase,
* to the current address. Otherwise it may be a readonly location.
* Copy and relocate to the start of the memory in this case.
*/
- if (pc > membase && pc < membase + memsize)
+ if (pc > membase && pc < membase + memsize) {
relocate_to_current_adr();
- else
+ } else {
+ validate_memory_range("validating pbl relocation area",
+ membase,
+ membase + arm_barebox_image_size() - 1);
relocate_to_adr(membase);
+ }
}
if (IS_ENABLED(CONFIG_RELOCATABLE))
@@ -77,6 +83,21 @@ static void __noreturn noinline uncompress_start_payload(unsigned long membase,
setup_c();
+ validate_memory_range("validating barebox decompression area",
+ barebox_base, endmem - 1);
+
+ /*
+ We know that when we give control to __start function of
+ uncompressed image _text would be within the boundaries of
+ (membase, membase + memsize) so the malloc_end variable
+ would be set to _text
+ */
+ malloc_end = barebox_base;
+ malloc_start = arm_get_malloc_start(membase, malloc_end);
+
+ validate_memory_range("validating malloc area",
+ malloc_start, malloc_end - 1);
+
pr_debug("memory at 0x%08lx, size 0x%08lx\n", membase, memsize);
if (IS_ENABLED(CONFIG_MMU_EARLY)) {
@@ -122,7 +143,12 @@ static void __noreturn noinline uncompress_start_payload(unsigned long membase,
void __naked __noreturn barebox_arm_entry(unsigned long membase,
unsigned long memsize, void *boarddata)
{
- arm_setup_stack(membase + memsize - 16);
+ unsigned long stack_end = membase + memsize - 16;
+
+ validate_memory_range("validating stack area",
+ membase + memsize - STACK_SIZE, stack_end);
+
+ arm_setup_stack(stack_end);
uncompress_start_payload(membase, memsize, boarddata);
}
diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h
index dbc8aaa..f577df7 100644
--- a/arch/arm/include/asm/barebox-arm.h
+++ b/arch/arm/include/asm/barebox-arm.h
@@ -83,6 +83,34 @@ static inline unsigned long arm_barebox_image_place(unsigned long endmem)
return endmem;
}
+static inline unsigned long arm_barebox_image_size(void)
+{
+ /* We assume that 1G is significantly more that Barebox will
+ * ever try to reserve */
+ return SZ_1G - arm_barebox_image_place(SZ_1G);
+}
+
+static inline unsigned long arm_get_malloc_start(unsigned long membase,
+ unsigned long malloc_end)
+{
+ unsigned long malloc_start;
+ /*
+ * Maximum malloc space is the Kconfig value if given
+ * or 1GB.
+ */
+ if (MALLOC_SIZE > 0) {
+ malloc_start = malloc_end - MALLOC_SIZE;
+ if (malloc_start < membase)
+ malloc_start = membase;
+ } else {
+ malloc_start = malloc_end - (malloc_end - membase) / 2;
+ if (malloc_end - malloc_start > SZ_1G)
+ malloc_start = malloc_end - SZ_1G;
+ }
+
+ return malloc_start;
+}
+
#define ENTRY_FUNCTION(name, arg0, arg1, arg2) \
static void __##name(uint32_t, uint32_t, uint32_t); \
\
diff --git a/common/Kconfig b/common/Kconfig
index 4032dcd..5d40dee 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -246,6 +246,14 @@ config MALLOC_SIZE
prompt "malloc area size"
endmenu
+config MEMORY_VALIDATION
+ bool "Validate regions of memory prior to using them"
+ select PBL_CONSOLE
+ help
+ select this option if you want Barebox to perform memory test
+ on regions of DRAM memory that it is about to use for the
+ first time
+
config BROKEN
bool
diff --git a/common/Makefile b/common/Makefile
index 2738238..a634f0d 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_BLSPEC) += blspec.o
obj-$(CONFIG_BOOTM) += bootm.o
obj-$(CONFIG_CMD_LOADS) += s_record.o
obj-$(CONFIG_CMD_MEMTEST) += memtest.o
+pbl-$(CONFIG_MEMORY_VALIDATION) += memtest.o
obj-$(CONFIG_COMMAND_SUPPORT) += command.o
obj-$(CONFIG_CONSOLE_FULL) += console.o
obj-$(CONFIG_CONSOLE_SIMPLE) += console_simple.o
@@ -90,4 +91,3 @@ include/generated/compile.h: FORCE
@$($(quiet)chk_compile.h)
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \
"$(UTS_MACHINE)" "$(CC) $(KBUILD_CFLAGS)"
-
diff --git a/include/common.h b/include/common.h
index 86e755d..021637a 100644
--- a/include/common.h
+++ b/include/common.h
@@ -209,6 +209,7 @@ static inline void *get_true_address(const void *ptr)
return (void *)address;
}
#else
+
static inline void *get_true_address(const void *ptr)
{
return (void *)ptr;
diff --git a/include/memtest.h b/include/memtest.h
index a337be8..4a426c3 100644
--- a/include/memtest.h
+++ b/include/memtest.h
@@ -8,7 +8,26 @@ struct mem_test_resource {
struct list_head list;
};
+typedef int (*mem_test_handler_t)(resource_size_t _start, resource_size_t _end);
+
int mem_test(resource_size_t _start,
resource_size_t _end, int bus_only);
+#ifdef CONFIG_MEMORY_VALIDATION
+void validate_memory_range(const char *message,
+ resource_size_t start,
+ resource_size_t end);
+void set_memory_validation_handler(mem_test_handler_t handler);
+#else
+static inline void validate_memory_range(const char *message,
+ resource_size_t start,
+ resource_size_t end)
+{
+}
+
+static inline void set_memory_validation_handler(mem_test_handler_t handler)
+{
+}
+#endif
+
#endif /* __MEMTEST_H */
diff --git a/lib/Makefile b/lib/Makefile
index 6a3e9fd..3da2c27 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -35,6 +35,12 @@ obj-y += random.o
obj-y += lzo/
obj-$(CONFIG_LZ4_DECOMPRESS) += lz4/
obj-y += show_progress.o
+pbl-$(CONFIG_MEMORY_VALIDATION) += show_progress.o
+# The code is going to be used before MMU is set up and unaligned
+# access will cause an exception(there is an unaligned access to the
+# contenst of 'spinchr' in show_progress())
+CFLAGS_pbl-show_progress.o = -mno-unaligned-access
+
obj-$(CONFIG_LZO_DECOMPRESS) += decompress_unlzo.o
obj-$(CONFIG_LZ4_DECOMPRESS) += decompress_unlz4.o
obj-$(CONFIG_PROCESS_ESCAPE_SEQUENCE) += process_escape_sequence.o
diff --git a/pbl/misc.c b/pbl/misc.c
index 3d5a881..2b446f5 100644
--- a/pbl/misc.c
+++ b/pbl/misc.c
@@ -1,8 +1,10 @@
#include <common.h>
#include <init.h>
+#include <memtest.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/ctype.h>
+#include <debug_ll.h>
void __noreturn __hang(void)
{
@@ -26,6 +28,48 @@ void set_hang_handler(hang_handler_t handler)
*__hang_handler_p = handler;
}
+#ifdef CONFIG_MEMORY_VALIDATION
+
+static mem_test_handler_t mem_test_handler = NULL;
+
+void validate_memory_range(const char *message,
+ resource_size_t start,
+ resource_size_t end)
+{
+ int ret;
+ mem_test_handler_t *__mem_test_handler_p = get_true_address(&mem_test_handler);
+ mem_test_handler_t __mem_test_handler = get_true_address(*__mem_test_handler_p);
+
+ if (__mem_test_handler) {
+ message = get_true_address(message);
+
+ puts_ll(message);
+ putc_ll(' ');
+ putc_ll('[');
+ puthex_ll(start);
+ putc_ll(' ');
+ putc_ll('-');
+ putc_ll(' ');
+ puthex_ll(end);
+ putc_ll(']');
+ putc_ll('\r');
+ putc_ll('\n');
+
+ ret = __mem_test_handler(start, end);
+
+ if (ret < 0)
+ hang();
+ }
+}
+
+void set_memory_validation_handler(mem_test_handler_t handler)
+{
+ mem_test_handler_t *__mem_test_handler_p = get_true_address(&mem_test_handler);
+
+ *__mem_test_handler_p = handler;
+}
+#endif
+
void __noreturn panic(const char *fmt, ...)
{
while(1);
--
2.1.4
More information about the barebox
mailing list