All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 1/1] [RFC] DM: early_malloc for DM added.
@ 2012-08-27 12:12 Tomas Hlavacek
  2012-08-27 12:18 ` Marek Vasut
                   ` (8 more replies)
  0 siblings, 9 replies; 48+ messages in thread
From: Tomas Hlavacek @ 2012-08-27 12:12 UTC (permalink / raw)
  To: u-boot

Modular early_malloc for DM with support for more heaps and lightweight
first heap on stack.

(RFC. Not intended for merging!)

Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
---
 arch/arm/include/asm/global_data.h        |    1 +
 arch/arm/lib/board.c                      |    5 ++
 arch/avr32/include/asm/global_data.h      |    1 +
 arch/avr32/lib/board.c                    |    4 ++
 arch/blackfin/include/asm/global_data.h   |    1 +
 arch/blackfin/lib/board.c                 |    4 ++
 arch/m68k/include/asm/global_data.h       |    1 +
 arch/m68k/lib/board.c                     |    4 ++
 arch/microblaze/include/asm/global_data.h |    1 +
 arch/microblaze/lib/board.c               |    5 ++
 arch/mips/include/asm/global_data.h       |    1 +
 arch/mips/lib/board.c                     |    4 ++
 arch/nds32/include/asm/global_data.h      |    1 +
 arch/nds32/lib/board.c                    |    4 ++
 arch/nios2/include/asm/global_data.h      |    1 +
 arch/nios2/lib/board.c                    |    4 ++
 arch/openrisc/include/asm/global_data.h   |    1 +
 arch/openrisc/lib/board.c                 |    4 ++
 arch/powerpc/include/asm/global_data.h    |    1 +
 arch/powerpc/lib/board.c                  |    4 ++
 arch/sandbox/include/asm/global_data.h    |    1 +
 arch/sandbox/lib/board.c                  |    4 ++
 arch/sh/include/asm/global_data.h         |    1 +
 arch/sparc/include/asm/global_data.h      |    1 +
 arch/sparc/lib/board.c                    |    4 ++
 arch/x86/include/asm/global_data.h        |    1 +
 arch/x86/lib/board.c                      |    4 ++
 common/Makefile                           |    1 +
 common/earlymalloc.c                      |   91 +++++++++++++++++++++++++++++
 include/earlymalloc.h                     |   48 +++++++++++++++
 30 files changed, 208 insertions(+)
 create mode 100644 common/earlymalloc.c
 create mode 100644 include/earlymalloc.h

diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index c3ff789..71ae6dc 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -84,6 +84,7 @@ typedef	struct	global_data {
 	unsigned long	post_log_res; /* success of POST test */
 	unsigned long	post_init_f_time; /* When post_init_f started */
 #endif
+	void 		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
index 500e216..ad124c6 100644
--- a/arch/arm/lib/board.c
+++ b/arch/arm/lib/board.c
@@ -52,6 +52,7 @@
 #include <fdtdec.h>
 #include <post.h>
 #include <logbuff.h>
+#include <earlymalloc.h>
 
 #ifdef CONFIG_BITBANGMII
 #include <miiphy.h>
@@ -273,6 +274,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	gd->mon_len = _bss_end_ofs;
 #ifdef CONFIG_OF_EMBED
 	/* Get a pointer to the FDT */
diff --git a/arch/avr32/include/asm/global_data.h b/arch/avr32/include/asm/global_data.h
index 5c654bd..5edb1f0 100644
--- a/arch/avr32/include/asm/global_data.h
+++ b/arch/avr32/include/asm/global_data.h
@@ -50,6 +50,7 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void 		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/avr32/lib/board.c b/arch/avr32/lib/board.c
index 63fe297..8cb56df 100644
--- a/arch/avr32/lib/board.c
+++ b/arch/avr32/lib/board.c
@@ -149,6 +149,10 @@ void board_init_f(ulong board_type)
 	memset(&gd_data, 0, sizeof(gd_data));
 	gd = &gd_data;
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	/* Perform initialization sequence */
 	board_early_init_f();
 	cpu_init();
diff --git a/arch/blackfin/include/asm/global_data.h b/arch/blackfin/include/asm/global_data.h
index 67aa30f..33d3cec 100644
--- a/arch/blackfin/include/asm/global_data.h
+++ b/arch/blackfin/include/asm/global_data.h
@@ -59,6 +59,7 @@ typedef struct global_data {
 
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+	void	*early_heap_first;	/* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c
index e3ee4cd..f8dade6 100644
--- a/arch/blackfin/lib/board.c
+++ b/arch/blackfin/lib/board.c
@@ -250,6 +250,10 @@ void board_init_f(ulong bootflag)
 	bd->bi_memstart = CONFIG_SYS_SDRAM_BASE;
 	bd->bi_memsize = CONFIG_SYS_MAX_RAM_SIZE;
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	/* Initialize */
 	serial_early_puts("IRQ init\n");
 	irq_init();
diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h
index 0ba2b43..ddd76f9 100644
--- a/arch/m68k/include/asm/global_data.h
+++ b/arch/m68k/include/asm/global_data.h
@@ -68,6 +68,7 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/m68k/lib/board.c b/arch/m68k/lib/board.c
index 1526967..a420d21 100644
--- a/arch/m68k/lib/board.c
+++ b/arch/m68k/lib/board.c
@@ -227,6 +227,10 @@ board_init_f (ulong bootflag)
 	/* Clear initial global data */
 	memset ((void *) gd, 0, sizeof (gd_t));
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0) {
 			hang ();
diff --git a/arch/microblaze/include/asm/global_data.h b/arch/microblaze/include/asm/global_data.h
index 6e8537c..4e340e6 100644
--- a/arch/microblaze/include/asm/global_data.h
+++ b/arch/microblaze/include/asm/global_data.h
@@ -47,6 +47,7 @@ typedef	struct	global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c
index 9828b76..302a323 100644
--- a/arch/microblaze/lib/board.c
+++ b/arch/microblaze/lib/board.c
@@ -101,6 +101,11 @@ void board_init (void)
 	asm ("nop");	/* FIXME gd is not initialize - wait */
 	memset ((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 	memset ((void *)bd, 0, GENERATED_BD_INFO_SIZE);
+
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	gd->bd = bd;
 	gd->baudrate = CONFIG_BAUDRATE;
 	bd->bi_baudrate = CONFIG_BAUDRATE;
diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h
index f6cf9fe..9656fd6 100644
--- a/arch/mips/include/asm/global_data.h
+++ b/arch/mips/include/asm/global_data.h
@@ -61,6 +61,7 @@ typedef	struct	global_data {
 	unsigned long	env_valid;	/* Checksum of Environment valid? */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/mips/lib/board.c b/arch/mips/lib/board.c
index d998f0e..f40258c 100644
--- a/arch/mips/lib/board.c
+++ b/arch/mips/lib/board.c
@@ -160,6 +160,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0)
 			hang();
diff --git a/arch/nds32/include/asm/global_data.h b/arch/nds32/include/asm/global_data.h
index de20a0a..313fecb 100644
--- a/arch/nds32/include/asm/global_data.h
+++ b/arch/nds32/include/asm/global_data.h
@@ -65,6 +65,7 @@ typedef	struct global_data {
 
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/nds32/lib/board.c b/arch/nds32/lib/board.c
index 074aabf..34fff30 100644
--- a/arch/nds32/lib/board.c
+++ b/arch/nds32/lib/board.c
@@ -190,6 +190,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	gd->mon_len = (unsigned int)(&__bss_end__) - (unsigned int)(&_start);
 
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
diff --git a/arch/nios2/include/asm/global_data.h b/arch/nios2/include/asm/global_data.h
index 4b86fbd..02f93d3 100644
--- a/arch/nios2/include/asm/global_data.h
+++ b/arch/nios2/include/asm/global_data.h
@@ -42,6 +42,7 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /* flags */
diff --git a/arch/nios2/lib/board.c b/arch/nios2/lib/board.c
index 65de26e..87e0559 100644
--- a/arch/nios2/lib/board.c
+++ b/arch/nios2/lib/board.c
@@ -97,6 +97,10 @@ void board_init (void)
 
 	memset( gd, 0, GENERATED_GBL_DATA_SIZE );
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	gd->bd = (bd_t *)(gd+1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/openrisc/include/asm/global_data.h b/arch/openrisc/include/asm/global_data.h
index 36de9d0..032b6b2 100644
--- a/arch/openrisc/include/asm/global_data.h
+++ b/arch/openrisc/include/asm/global_data.h
@@ -46,6 +46,7 @@ typedef struct global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/openrisc/lib/board.c b/arch/openrisc/lib/board.c
index 85aa189..2a92899 100644
--- a/arch/openrisc/lib/board.c
+++ b/arch/openrisc/lib/board.c
@@ -86,6 +86,10 @@ void board_init(void)
 
 	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	gd->bd = (bd_t *)(gd+1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h
index 01f1d4a..0839d03 100644
--- a/arch/powerpc/include/asm/global_data.h
+++ b/arch/powerpc/include/asm/global_data.h
@@ -184,6 +184,7 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
index 3f9af1d..ac88ae2 100644
--- a/arch/powerpc/lib/board.c
+++ b/arch/powerpc/lib/board.c
@@ -389,6 +389,10 @@ void board_init_f(ulong bootflag)
 	memset((void *) gd, 0, sizeof(gd_t));
 #endif
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)
 		if ((*init_fnc_ptr) () != 0)
 			hang();
diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h
index 8d47191..54342c0 100644
--- a/arch/sandbox/include/asm/global_data.h
+++ b/arch/sandbox/include/asm/global_data.h
@@ -47,6 +47,7 @@ typedef	struct global_data {
 	phys_size_t	ram_size;	/* RAM size */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/sandbox/lib/board.c b/arch/sandbox/lib/board.c
index b7997e9..3d06cfc 100644
--- a/arch/sandbox/lib/board.c
+++ b/arch/sandbox/lib/board.c
@@ -156,6 +156,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0)
 			hang();
diff --git a/arch/sh/include/asm/global_data.h b/arch/sh/include/asm/global_data.h
index 1b782fc..180f56e 100644
--- a/arch/sh/include/asm/global_data.h
+++ b/arch/sh/include/asm/global_data.h
@@ -42,6 +42,7 @@ typedef	struct global_data
 	unsigned long	env_valid;	/* Checksum of Environment valid */
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 #define	GD_FLG_RELOC		0x00001	/* Code was relocated to RAM		*/
diff --git a/arch/sparc/include/asm/global_data.h b/arch/sparc/include/asm/global_data.h
index 613e2d8..82ed56f 100644
--- a/arch/sparc/include/asm/global_data.h
+++ b/arch/sparc/include/asm/global_data.h
@@ -76,6 +76,7 @@ typedef struct global_data {
 #endif
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+	void	*early_heap_first;	/* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/sparc/lib/board.c b/arch/sparc/lib/board.c
index 519a4fb..86ee8db 100644
--- a/arch/sparc/lib/board.c
+++ b/arch/sparc/lib/board.c
@@ -179,6 +179,10 @@ void board_init_f(ulong bootflag)
 	/* Clear initial global data */
 	memset((void *)gd, 0, sizeof(gd_t));
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	gd->bd = (bd_t *) (gd + 1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 908a02c..171f85b 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -59,6 +59,7 @@ typedef	struct global_data {
 	unsigned long	reset_status;	/* reset status register at boot */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 static inline gd_t *get_fs_gd_ptr(void)
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
index 5f0b62c..5ff4f42 100644
--- a/arch/x86/lib/board.c
+++ b/arch/x86/lib/board.c
@@ -220,6 +220,10 @@ void board_init_f(ulong boot_flags)
 {
 	gd->flags = boot_flags;
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	do_init_loop(init_sequence_f);
 
 	/*
diff --git a/common/Makefile b/common/Makefile
index 2a31c62..744beb8 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -188,6 +188,7 @@ COBJS-y += console.o
 COBJS-y += dlmalloc.o
 COBJS-y += memsize.o
 COBJS-y += stdio.o
+COBJS-y += earlymalloc.o
 
 
 COBJS	:= $(sort $(COBJS-y))
diff --git a/common/earlymalloc.c b/common/earlymalloc.c
new file mode 100644
index 0000000..6ba4df6
--- /dev/null
+++ b/common/earlymalloc.c
@@ -0,0 +1,91 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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 <common.h> /* for ROUND_UP */
+#include <asm/u-boot.h>
+#include <asm/global_data.h> /* for gd_t and gd */
+#include <asm/types.h> /* for phys_addr_t and size_addt_t */
+
+#include <earlymalloc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+
+void early_heap_init(void *heap, size_t size)
+{
+	struct early_heap_header *h = heap;
+
+	h->free_space_pointer = (void *)(roundup((phys_addr_t)heap +
+				sizeof(struct early_heap_header),
+				sizeof(phys_addr_t)));
+	h->free_bytes = size - roundup(sizeof(struct early_heap_header),
+				sizeof(phys_addr_t));
+	h->next_early_heap = NULL;
+}
+
+void *early_malloc(size_t size)
+{
+	phys_addr_t addr;
+	struct early_heap_header *h;
+
+	/* Align size. */
+	size = roundup(size, sizeof(phys_addr_t));
+
+	/* Choose early_heap with enough space. */
+	h = gd->early_heap_first;
+	while ((h->free_bytes < size)&&(h->next_early_heap != NULL))
+		h = h->next_early_heap;
+
+	if(h->free_bytes < size) {
+		debug("Early heap overflow. Heap %08lX, free %d, required %d.",
+			h, h->free_bytes, size);
+		return NULL;
+	}
+
+	/* Choose block beginning address and mark next free space. */
+	addr = h->free_space_pointer;
+
+	h->free_space_pointer += size;
+	h->free_bytes -= size;
+
+	return (void *)addr;
+}
+
+
+int early_malloc_isaddress(void *addr)
+{
+	if ((phys_addr_t)addr < (phys_addr_t)gd->early_heap_first)
+		return 0;
+
+	if ((phys_addr_t)addr >= (phys_addr_t)gd->early_heap_first +
+			CONFIG_SYS_EARLY_HEAP_SIZE)
+		return 0;
+
+	return 1;
+}
+
+int early_malloc_finished(void)
+{
+	return gd->flags & GD_FLG_RELOC;
+}
+
diff --git a/include/earlymalloc.h b/include/earlymalloc.h
new file mode 100644
index 0000000..345bdef
--- /dev/null
+++ b/include/earlymalloc.h
@@ -0,0 +1,48 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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
+ */
+
+#ifndef __INCLUDE_EARLYMALLOC_H
+#define __INCLUDE_EARLYMALLOC_H
+
+#include <linux/stddef.h> /* for size_t */
+
+struct early_heap_header {
+	void *free_space_pointer;
+	size_t free_bytes;
+	void *next_early_heap;
+};
+
+void early_heap_init(void *heap, size_t size);
+void *early_malloc(size_t size);
+int early_malloc_isaddress(void *addr);
+int early_malloc_finished(void);
+
+#ifndef CONFIG_SYS_EARLY_HEAP_SIZE
+#define CONFIG_SYS_EARLY_HEAP_SIZE 256
+#endif /* CONFIG_SYS_EARLY_HEAP_SIZE */
+
+#define DECLARE_EARLY_HEAP_ON_STACK char __early_heap[CONFIG_SYS_EARLY_HEAP_SIZE]; \
+					gd->early_heap_first = (void *)__early_heap
+
+#endif /* __INCLUDE_EARLYMALLOC_H */
+
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH 1/1] [RFC] DM: early_malloc for DM added.
  2012-08-27 12:12 [U-Boot] [PATCH 1/1] [RFC] DM: early_malloc for DM added Tomas Hlavacek
@ 2012-08-27 12:18 ` Marek Vasut
  2012-08-27 12:37   ` Tomas Hlavacek
  2012-08-27 12:42 ` [U-Boot] [PATCHv2 " Tomas Hlavacek
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 48+ messages in thread
From: Marek Vasut @ 2012-08-27 12:18 UTC (permalink / raw)
  To: u-boot

Dear Tomas Hlavacek,

> Modular early_malloc for DM with support for more heaps and lightweight
> first heap on stack.
> 
> (RFC. Not intended for merging!)
> 
> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
[...]

CCing Graeme

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH 1/1] [RFC] DM: early_malloc for DM added.
  2012-08-27 12:18 ` Marek Vasut
@ 2012-08-27 12:37   ` Tomas Hlavacek
  0 siblings, 0 replies; 48+ messages in thread
From: Tomas Hlavacek @ 2012-08-27 12:37 UTC (permalink / raw)
  To: u-boot

Hello Marek and Greame!

Thanks.

I want to add that this patch contains only the early_malloc() backend
for prospective dm_malloc(). There are no relocation support or
helpers whatsoever yet.

The aim is to present the way of grabbing a chunk of stack and using
this memory as the early heap and collect the feedback.

Tomas

On Mon, Aug 27, 2012 at 2:18 PM, Marek Vasut <marek.vasut@gmail.com> wrote:
> Dear Tomas Hlavacek,
>
>> Modular early_malloc for DM with support for more heaps and lightweight
>> first heap on stack.
>>
>> (RFC. Not intended for merging!)
>>
>> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
> [...]
>
> CCing Graeme
>
> Best regards,
> Marek Vasut



-- 
Tom?? Hlav??ek <tmshlvck@gmail.com>

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCHv2 1/1] [RFC] DM: early_malloc for DM added.
  2012-08-27 12:12 [U-Boot] [PATCH 1/1] [RFC] DM: early_malloc for DM added Tomas Hlavacek
  2012-08-27 12:18 ` Marek Vasut
@ 2012-08-27 12:42 ` Tomas Hlavacek
  2012-08-27 23:02   ` Graeme Russ
  2012-09-18  7:13 ` [U-Boot] [PATCHv4] " Tomas Hlavacek
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 48+ messages in thread
From: Tomas Hlavacek @ 2012-08-27 12:42 UTC (permalink / raw)
  To: u-boot

Modular early_malloc for DM with support for more heaps and lightweight
first heap on stack.

(Not intended for merging!)

Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
---
 arch/arm/include/asm/global_data.h        |    1 +
 arch/arm/lib/board.c                      |    5 ++
 arch/avr32/include/asm/global_data.h      |    1 +
 arch/avr32/lib/board.c                    |    4 ++
 arch/blackfin/include/asm/global_data.h   |    1 +
 arch/blackfin/lib/board.c                 |    4 ++
 arch/m68k/include/asm/global_data.h       |    1 +
 arch/m68k/lib/board.c                     |    4 ++
 arch/microblaze/include/asm/global_data.h |    1 +
 arch/microblaze/lib/board.c               |    5 ++
 arch/mips/include/asm/global_data.h       |    1 +
 arch/mips/lib/board.c                     |    4 ++
 arch/nds32/include/asm/global_data.h      |    1 +
 arch/nds32/lib/board.c                    |    4 ++
 arch/nios2/include/asm/global_data.h      |    1 +
 arch/nios2/lib/board.c                    |    4 ++
 arch/openrisc/include/asm/global_data.h   |    1 +
 arch/openrisc/lib/board.c                 |    4 ++
 arch/powerpc/include/asm/global_data.h    |    1 +
 arch/powerpc/lib/board.c                  |    4 ++
 arch/sandbox/include/asm/global_data.h    |    1 +
 arch/sandbox/lib/board.c                  |    4 ++
 arch/sh/include/asm/global_data.h         |    1 +
 arch/sparc/include/asm/global_data.h      |    1 +
 arch/sparc/lib/board.c                    |    4 ++
 arch/x86/include/asm/global_data.h        |    1 +
 arch/x86/lib/board.c                      |    4 ++
 common/Makefile                           |    1 +
 common/earlymalloc.c                      |   91 +++++++++++++++++++++++++++++
 include/earlymalloc.h                     |   49 ++++++++++++++++
 30 files changed, 209 insertions(+)
 create mode 100644 common/earlymalloc.c
 create mode 100644 include/earlymalloc.h

diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index c3ff789..8563d49 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -84,6 +84,7 @@ typedef	struct	global_data {
 	unsigned long	post_log_res; /* success of POST test */
 	unsigned long	post_init_f_time; /* When post_init_f started */
 #endif
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
index 500e216..ad124c6 100644
--- a/arch/arm/lib/board.c
+++ b/arch/arm/lib/board.c
@@ -52,6 +52,7 @@
 #include <fdtdec.h>
 #include <post.h>
 #include <logbuff.h>
+#include <earlymalloc.h>
 
 #ifdef CONFIG_BITBANGMII
 #include <miiphy.h>
@@ -273,6 +274,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	gd->mon_len = _bss_end_ofs;
 #ifdef CONFIG_OF_EMBED
 	/* Get a pointer to the FDT */
diff --git a/arch/avr32/include/asm/global_data.h b/arch/avr32/include/asm/global_data.h
index 5c654bd..9ae7c5e 100644
--- a/arch/avr32/include/asm/global_data.h
+++ b/arch/avr32/include/asm/global_data.h
@@ -50,6 +50,7 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/avr32/lib/board.c b/arch/avr32/lib/board.c
index 63fe297..8cb56df 100644
--- a/arch/avr32/lib/board.c
+++ b/arch/avr32/lib/board.c
@@ -149,6 +149,10 @@ void board_init_f(ulong board_type)
 	memset(&gd_data, 0, sizeof(gd_data));
 	gd = &gd_data;
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	/* Perform initialization sequence */
 	board_early_init_f();
 	cpu_init();
diff --git a/arch/blackfin/include/asm/global_data.h b/arch/blackfin/include/asm/global_data.h
index 67aa30f..33d3cec 100644
--- a/arch/blackfin/include/asm/global_data.h
+++ b/arch/blackfin/include/asm/global_data.h
@@ -59,6 +59,7 @@ typedef struct global_data {
 
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+	void	*early_heap_first;	/* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c
index e3ee4cd..f8dade6 100644
--- a/arch/blackfin/lib/board.c
+++ b/arch/blackfin/lib/board.c
@@ -250,6 +250,10 @@ void board_init_f(ulong bootflag)
 	bd->bi_memstart = CONFIG_SYS_SDRAM_BASE;
 	bd->bi_memsize = CONFIG_SYS_MAX_RAM_SIZE;
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	/* Initialize */
 	serial_early_puts("IRQ init\n");
 	irq_init();
diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h
index 0ba2b43..ddd76f9 100644
--- a/arch/m68k/include/asm/global_data.h
+++ b/arch/m68k/include/asm/global_data.h
@@ -68,6 +68,7 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/m68k/lib/board.c b/arch/m68k/lib/board.c
index 1526967..a420d21 100644
--- a/arch/m68k/lib/board.c
+++ b/arch/m68k/lib/board.c
@@ -227,6 +227,10 @@ board_init_f (ulong bootflag)
 	/* Clear initial global data */
 	memset ((void *) gd, 0, sizeof (gd_t));
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0) {
 			hang ();
diff --git a/arch/microblaze/include/asm/global_data.h b/arch/microblaze/include/asm/global_data.h
index 6e8537c..4e340e6 100644
--- a/arch/microblaze/include/asm/global_data.h
+++ b/arch/microblaze/include/asm/global_data.h
@@ -47,6 +47,7 @@ typedef	struct	global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c
index 9828b76..302a323 100644
--- a/arch/microblaze/lib/board.c
+++ b/arch/microblaze/lib/board.c
@@ -101,6 +101,11 @@ void board_init (void)
 	asm ("nop");	/* FIXME gd is not initialize - wait */
 	memset ((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 	memset ((void *)bd, 0, GENERATED_BD_INFO_SIZE);
+
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	gd->bd = bd;
 	gd->baudrate = CONFIG_BAUDRATE;
 	bd->bi_baudrate = CONFIG_BAUDRATE;
diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h
index f6cf9fe..9656fd6 100644
--- a/arch/mips/include/asm/global_data.h
+++ b/arch/mips/include/asm/global_data.h
@@ -61,6 +61,7 @@ typedef	struct	global_data {
 	unsigned long	env_valid;	/* Checksum of Environment valid? */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/mips/lib/board.c b/arch/mips/lib/board.c
index d998f0e..f40258c 100644
--- a/arch/mips/lib/board.c
+++ b/arch/mips/lib/board.c
@@ -160,6 +160,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0)
 			hang();
diff --git a/arch/nds32/include/asm/global_data.h b/arch/nds32/include/asm/global_data.h
index de20a0a..313fecb 100644
--- a/arch/nds32/include/asm/global_data.h
+++ b/arch/nds32/include/asm/global_data.h
@@ -65,6 +65,7 @@ typedef	struct global_data {
 
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/nds32/lib/board.c b/arch/nds32/lib/board.c
index 074aabf..34fff30 100644
--- a/arch/nds32/lib/board.c
+++ b/arch/nds32/lib/board.c
@@ -190,6 +190,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	gd->mon_len = (unsigned int)(&__bss_end__) - (unsigned int)(&_start);
 
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
diff --git a/arch/nios2/include/asm/global_data.h b/arch/nios2/include/asm/global_data.h
index 4b86fbd..02f93d3 100644
--- a/arch/nios2/include/asm/global_data.h
+++ b/arch/nios2/include/asm/global_data.h
@@ -42,6 +42,7 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /* flags */
diff --git a/arch/nios2/lib/board.c b/arch/nios2/lib/board.c
index 65de26e..87e0559 100644
--- a/arch/nios2/lib/board.c
+++ b/arch/nios2/lib/board.c
@@ -97,6 +97,10 @@ void board_init (void)
 
 	memset( gd, 0, GENERATED_GBL_DATA_SIZE );
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	gd->bd = (bd_t *)(gd+1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/openrisc/include/asm/global_data.h b/arch/openrisc/include/asm/global_data.h
index 36de9d0..032b6b2 100644
--- a/arch/openrisc/include/asm/global_data.h
+++ b/arch/openrisc/include/asm/global_data.h
@@ -46,6 +46,7 @@ typedef struct global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/openrisc/lib/board.c b/arch/openrisc/lib/board.c
index 85aa189..2a92899 100644
--- a/arch/openrisc/lib/board.c
+++ b/arch/openrisc/lib/board.c
@@ -86,6 +86,10 @@ void board_init(void)
 
 	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	gd->bd = (bd_t *)(gd+1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h
index 01f1d4a..0839d03 100644
--- a/arch/powerpc/include/asm/global_data.h
+++ b/arch/powerpc/include/asm/global_data.h
@@ -184,6 +184,7 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
index 3f9af1d..ac88ae2 100644
--- a/arch/powerpc/lib/board.c
+++ b/arch/powerpc/lib/board.c
@@ -389,6 +389,10 @@ void board_init_f(ulong bootflag)
 	memset((void *) gd, 0, sizeof(gd_t));
 #endif
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)
 		if ((*init_fnc_ptr) () != 0)
 			hang();
diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h
index 8d47191..54342c0 100644
--- a/arch/sandbox/include/asm/global_data.h
+++ b/arch/sandbox/include/asm/global_data.h
@@ -47,6 +47,7 @@ typedef	struct global_data {
 	phys_size_t	ram_size;	/* RAM size */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/sandbox/lib/board.c b/arch/sandbox/lib/board.c
index b7997e9..3d06cfc 100644
--- a/arch/sandbox/lib/board.c
+++ b/arch/sandbox/lib/board.c
@@ -156,6 +156,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0)
 			hang();
diff --git a/arch/sh/include/asm/global_data.h b/arch/sh/include/asm/global_data.h
index 1b782fc..180f56e 100644
--- a/arch/sh/include/asm/global_data.h
+++ b/arch/sh/include/asm/global_data.h
@@ -42,6 +42,7 @@ typedef	struct global_data
 	unsigned long	env_valid;	/* Checksum of Environment valid */
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 #define	GD_FLG_RELOC		0x00001	/* Code was relocated to RAM		*/
diff --git a/arch/sparc/include/asm/global_data.h b/arch/sparc/include/asm/global_data.h
index 613e2d8..82ed56f 100644
--- a/arch/sparc/include/asm/global_data.h
+++ b/arch/sparc/include/asm/global_data.h
@@ -76,6 +76,7 @@ typedef struct global_data {
 #endif
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+	void	*early_heap_first;	/* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/sparc/lib/board.c b/arch/sparc/lib/board.c
index 519a4fb..86ee8db 100644
--- a/arch/sparc/lib/board.c
+++ b/arch/sparc/lib/board.c
@@ -179,6 +179,10 @@ void board_init_f(ulong bootflag)
 	/* Clear initial global data */
 	memset((void *)gd, 0, sizeof(gd_t));
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	gd->bd = (bd_t *) (gd + 1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 908a02c..171f85b 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -59,6 +59,7 @@ typedef	struct global_data {
 	unsigned long	reset_status;	/* reset status register at boot */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 static inline gd_t *get_fs_gd_ptr(void)
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
index 5f0b62c..5ff4f42 100644
--- a/arch/x86/lib/board.c
+++ b/arch/x86/lib/board.c
@@ -220,6 +220,10 @@ void board_init_f(ulong boot_flags)
 {
 	gd->flags = boot_flags;
 
+	/* Initialize early_malloc */
+	DECLARE_EARLY_HEAP_ON_STACK;
+	early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
+
 	do_init_loop(init_sequence_f);
 
 	/*
diff --git a/common/Makefile b/common/Makefile
index 2a31c62..744beb8 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -188,6 +188,7 @@ COBJS-y += console.o
 COBJS-y += dlmalloc.o
 COBJS-y += memsize.o
 COBJS-y += stdio.o
+COBJS-y += earlymalloc.o
 
 
 COBJS	:= $(sort $(COBJS-y))
diff --git a/common/earlymalloc.c b/common/earlymalloc.c
new file mode 100644
index 0000000..044b222
--- /dev/null
+++ b/common/earlymalloc.c
@@ -0,0 +1,91 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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 <common.h> /* for ROUND_UP */
+#include <asm/u-boot.h>
+#include <asm/global_data.h> /* for gd_t and gd */
+#include <asm/types.h> /* for phys_addr_t and size_addt_t */
+
+#include <earlymalloc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+
+void early_heap_init(void *heap, size_t size)
+{
+	struct early_heap_header *h = heap;
+
+	h->free_space_pointer = (void *)(roundup((phys_addr_t)heap +
+				sizeof(struct early_heap_header),
+				sizeof(phys_addr_t)));
+	h->free_bytes = size - roundup(sizeof(struct early_heap_header),
+				sizeof(phys_addr_t));
+	h->next_early_heap = NULL;
+}
+
+void *early_malloc(size_t size)
+{
+	phys_addr_t addr;
+	struct early_heap_header *h;
+
+	/* Align size. */
+	size = roundup(size, sizeof(phys_addr_t));
+
+	/* Choose early_heap with enough space. */
+	h = gd->early_heap_first;
+	while ((h->free_bytes < size) && (h->next_early_heap != NULL))
+		h = h->next_early_heap;
+
+	if (h->free_bytes < size) {
+		debug("Early heap overflow. Heap %08lX, free %d, required %d.",
+			h, h->free_bytes, size);
+		return NULL;
+	}
+
+	/* Choose block beginning address and mark next free space. */
+	addr = h->free_space_pointer;
+
+	h->free_space_pointer += size;
+	h->free_bytes -= size;
+
+	return (void *)addr;
+}
+
+
+int early_malloc_isaddress(void *addr)
+{
+	if ((phys_addr_t)addr < (phys_addr_t)gd->early_heap_first)
+		return 0;
+
+	if ((phys_addr_t)addr >= (phys_addr_t)gd->early_heap_first +
+			CONFIG_SYS_EARLY_HEAP_SIZE)
+		return 0;
+
+	return 1;
+}
+
+int early_malloc_finished(void)
+{
+	return gd->flags & GD_FLG_RELOC;
+}
+
diff --git a/include/earlymalloc.h b/include/earlymalloc.h
new file mode 100644
index 0000000..3b1fac2
--- /dev/null
+++ b/include/earlymalloc.h
@@ -0,0 +1,49 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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
+ */
+
+#ifndef __INCLUDE_EARLYMALLOC_H
+#define __INCLUDE_EARLYMALLOC_H
+
+#include <linux/stddef.h> /* for size_t */
+
+struct early_heap_header {
+	void *free_space_pointer;
+	size_t free_bytes;
+	void *next_early_heap;
+};
+
+void early_heap_init(void *heap, size_t size);
+void *early_malloc(size_t size);
+int early_malloc_isaddress(void *addr);
+int early_malloc_finished(void);
+
+#ifndef CONFIG_SYS_EARLY_HEAP_SIZE
+#define CONFIG_SYS_EARLY_HEAP_SIZE 256
+#endif /* CONFIG_SYS_EARLY_HEAP_SIZE */
+
+#define DECLARE_EARLY_HEAP_ON_STACK char \
+	__early_heap[CONFIG_SYS_EARLY_HEAP_SIZE]; \
+	gd->early_heap_first = (void *)__early_heap
+
+#endif /* __INCLUDE_EARLYMALLOC_H */
+
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCHv2 1/1] [RFC] DM: early_malloc for DM added.
  2012-08-27 12:42 ` [U-Boot] [PATCHv2 " Tomas Hlavacek
@ 2012-08-27 23:02   ` Graeme Russ
  2012-08-28  0:11     ` Graeme Russ
  2012-08-28  0:18     ` Graeme Russ
  0 siblings, 2 replies; 48+ messages in thread
From: Graeme Russ @ 2012-08-27 23:02 UTC (permalink / raw)
  To: u-boot

Hi Tomas,

None of my example code is compile tested...

Regards,

Graeme

On Mon, Aug 27, 2012 at 10:42 PM, Tomas Hlavacek <tmshlvck@gmail.com> wrote:
> Modular early_malloc for DM with support for more heaps and lightweight
> first heap on stack.
>
> (Not intended for merging!)
>

> diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
> index c3ff789..8563d49 100644
> --- a/arch/arm/include/asm/global_data.h
> +++ b/arch/arm/include/asm/global_data.h
> @@ -84,6 +84,7 @@ typedef       struct  global_data {
>         unsigned long   post_log_res; /* success of POST test */
>         unsigned long   post_init_f_time; /* When post_init_f started */
>  #endif
> +       void            *early_heap_first; /* early heap for early_malloc */
>  } gd_t;

Probably want to put an #ifdef CONFIG_SYS_EARLY_MALLOC around it. Also, it
is a struct early_heap_header *

>
>  /*
> diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
> index 500e216..ad124c6 100644
> --- a/arch/arm/lib/board.c
> +++ b/arch/arm/lib/board.c
> @@ -52,6 +52,7 @@
>  #include <fdtdec.h>
>  #include <post.h>
>  #include <logbuff.h>
> +#include <earlymalloc.h>
>
>  #ifdef CONFIG_BITBANGMII
>  #include <miiphy.h>
> @@ -273,6 +274,10 @@ void board_init_f(ulong bootflag)
>
>         memset((void *)gd, 0, sizeof(gd_t));
>
> +       /* Initialize early_malloc */
> +       DECLARE_EARLY_HEAP_ON_STACK;
> +       early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
> +

I'm not a fan of burying the initialiser in a #define, and we already have
a precedent of providing a hard-coded address for the chunk of memory
(CONFIG_PRE_CON_BUF_ADDR)


> diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
> index 5f0b62c..5ff4f42 100644
> --- a/arch/x86/lib/board.c
> +++ b/arch/x86/lib/board.c
> @@ -220,6 +220,10 @@ void board_init_f(ulong boot_flags)
>  {
>         gd->flags = boot_flags;
>
> +       /* Initialize early_malloc */
> +       DECLARE_EARLY_HEAP_ON_STACK;
> +       early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
> +
>         do_init_loop(init_sequence_f);
>
>         /*

early_heap_init() should be called via do_init_loop() - i.e. added to the
top of the list and added in init_helpers.c

> diff --git a/common/Makefile b/common/Makefile
> index 2a31c62..744beb8 100644
> --- a/common/Makefile
> +++ b/common/Makefile
> @@ -188,6 +188,7 @@ COBJS-y += console.o
>  COBJS-y += dlmalloc.o
>  COBJS-y += memsize.o
>  COBJS-y += stdio.o
> +COBJS-y += earlymalloc.o

Add the CONFIG_SYS_EARLY_MALLOC check here as well

>
>  COBJS  := $(sort $(COBJS-y))
> diff --git a/common/earlymalloc.c b/common/earlymalloc.c
> new file mode 100644
> index 0000000..044b222
> --- /dev/null
> +++ b/common/earlymalloc.c
> @@ -0,0 +1,91 @@
> +/*
> + * (C) Copyright 2012
> + * Tomas Hlavacek (tmshlvck at gmail.com)
> + *
> + * 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 <common.h> /* for ROUND_UP */
> +#include <asm/u-boot.h>
> +#include <asm/global_data.h> /* for gd_t and gd */
> +#include <asm/types.h> /* for phys_addr_t and size_addt_t */
> +
> +#include <earlymalloc.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +
> +void early_heap_init(void *heap, size_t size)
> +{
> +       struct early_heap_header *h = heap;
> +
> +       h->free_space_pointer = (void *)(roundup((phys_addr_t)heap +
> +                               sizeof(struct early_heap_header),
> +                               sizeof(phys_addr_t)));
> +       h->free_bytes = size - roundup(sizeof(struct early_heap_header),
> +                               sizeof(phys_addr_t));
> +       h->next_early_heap = NULL;
> +}

No need for this - see below for my prefered solution...

> +
> +void *early_malloc(size_t size)
> +{
> +       phys_addr_t addr;
> +       struct early_heap_header *h;
> +
> +       /* Align size. */
> +       size = roundup(size, sizeof(phys_addr_t));
> +
> +       /* Choose early_heap with enough space. */
> +       h = gd->early_heap_first;
> +       while ((h->free_bytes < size) && (h->next_early_heap != NULL))
> +               h = h->next_early_heap;
> +
> +       if (h->free_bytes < size) {
> +               debug("Early heap overflow. Heap %08lX, free %d, required %d.",
> +                       h, h->free_bytes, size);
> +               return NULL;
> +       }
> +
> +       /* Choose block beginning address and mark next free space. */
> +       addr = h->free_space_pointer;
> +
> +       h->free_space_pointer += size;
> +       h->free_bytes -= size;
> +
> +       return (void *)addr;
> +}

static struct early_heap_header *def_early_brk(size_t bytes)
{
        struct early_heap_header *h;

        if(gd->early_heap_first)
                return NULL;

        /* The default implementation allocates all of the reserved space */
        bytes = CONFIG_SYS_EARLY_HEAP_SIZE;
        gd->early_heap_first = bytes;

        h = gd->early_heap_first;

        h->free_space_pointer = (void *)(roundup((phys_addr_t)h +
                                sizeof(struct early_heap_header),
                                sizeof(phys_addr_t)));
        h->free_bytes = bytes - roundup(sizeof(struct early_heap_header),
                                sizeof(phys_addr_t));
        h->next_early_heap = NULL;

        return h;
}
struct early_brk *early_brk(size_t bytes)
        __attribute__((weak, alias("def_early_brk")));

void *early_malloc(size_t size)
{
        phys_addr_t addr;
        struct early_heap_header *h;

        /* Align size. */
        size = roundup(size, sizeof(phys_addr_t));


        /* Find an early heap chunk with enough space. */
        h = gd->early_heap_first;
        while (h && (h->free_bytes < size))
               h = h->next_early_heap;

        /* Initialise a new early heap chunk if required*/
        if(!h) {
                h = early_brk(bytes);

                if(!h) {
                        debug("Out of early heap\n");
                        return NULL;
                }
        }

        /* Choose block beginning address and mark next free space. */
        addr = h->free_space_pointer;

        h->free_space_pointer += size;
        h->free_bytes -= size;

        return (void *)addr;
}

> +
> +
> +int early_malloc_isaddress(void *addr)
> +{
> +       if ((phys_addr_t)addr < (phys_addr_t)gd->early_heap_first)
> +               return 0;
> +
> +       if ((phys_addr_t)addr >= (phys_addr_t)gd->early_heap_first +
> +                       CONFIG_SYS_EARLY_HEAP_SIZE)
> +               return 0;
> +
> +       return 1;
> +}

I asked about this function before - it does not seem to serve any useful
purpose. And even if it did, it does not scan through the chain of early
malloc chunks

> +
> +int early_malloc_finished(void)
> +{
> +       return gd->flags & GD_FLG_RELOC;
> +}

Again, is this needed? It's not used yet, if it is needed, add it when it
is and we can asses if this is the right approach then

> +
> diff --git a/include/earlymalloc.h b/include/earlymalloc.h
> new file mode 100644
> index 0000000..3b1fac2
> --- /dev/null
> +++ b/include/earlymalloc.h
> @@ -0,0 +1,49 @@
> +/*
> + * (C) Copyright 2012
> + * Tomas Hlavacek (tmshlvck at gmail.com)
> + *
> + * 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
> + */
> +
> +#ifndef __INCLUDE_EARLYMALLOC_H
> +#define __INCLUDE_EARLYMALLOC_H
> +
> +#include <linux/stddef.h> /* for size_t */
> +
> +struct early_heap_header {
> +       void *free_space_pointer;
> +       size_t free_bytes;
> +       void *next_early_heap;
> +};
> +
> +void early_heap_init(void *heap, size_t size);
> +void *early_malloc(size_t size);
> +int early_malloc_isaddress(void *addr);
> +int early_malloc_finished(void);
> +
> +#ifndef CONFIG_SYS_EARLY_HEAP_SIZE
> +#define CONFIG_SYS_EARLY_HEAP_SIZE 256
> +#endif /* CONFIG_SYS_EARLY_HEAP_SIZE */
> +
> +#define DECLARE_EARLY_HEAP_ON_STACK char \
> +       __early_heap[CONFIG_SYS_EARLY_HEAP_SIZE]; \
> +       gd->early_heap_first = (void *)__early_heap
> +
> +#endif /* __INCLUDE_EARLYMALLOC_H */
> +
> --
> 1.7.10.4
>

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCHv2 1/1] [RFC] DM: early_malloc for DM added.
  2012-08-27 23:02   ` Graeme Russ
@ 2012-08-28  0:11     ` Graeme Russ
  2012-08-28  0:18     ` Graeme Russ
  1 sibling, 0 replies; 48+ messages in thread
From: Graeme Russ @ 2012-08-28  0:11 UTC (permalink / raw)
  To: u-boot

Hi Tomas

> static struct early_heap_header *def_early_brk(size_t bytes)
> {
>         struct early_heap_header *h;
>
>         if(gd->early_heap_first)
>                 return NULL;
>
>         /* The default implementation allocates all of the reserved space */
>         bytes = CONFIG_SYS_EARLY_HEAP_SIZE;
>         gd->early_heap_first = bytes;

Oops

gd->early_heap_first = CONFIG_SYS_EARLY_HEAP_ADDR;

Regards,

Graeme

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCHv2 1/1] [RFC] DM: early_malloc for DM added.
  2012-08-27 23:02   ` Graeme Russ
  2012-08-28  0:11     ` Graeme Russ
@ 2012-08-28  0:18     ` Graeme Russ
  1 sibling, 0 replies; 48+ messages in thread
From: Graeme Russ @ 2012-08-28  0:18 UTC (permalink / raw)
  To: u-boot

Hi Tomas,

Another small correction...

On Tue, Aug 28, 2012 at 9:02 AM, Graeme Russ <graeme.russ@gmail.com> wrote:

> static struct early_heap_header *def_early_brk(size_t bytes)
> {
>         struct early_heap_header *h;
>
>         if(gd->early_heap_first)
>                 return NULL;
>
>         /* The default implementation allocates all of the reserved space */

        if (bytes > (CONFIG_SYS_EARLY_HEAP_SIZE -
                roundup(sizeof(struct early_heap_header), sizeof(phys_addr_t))
                return NULL;

>         bytes = CONFIG_SYS_EARLY_HEAP_SIZE;
>         gd->early_heap_first = bytes;
>
>         h = gd->early_heap_first;
>
>         h->free_space_pointer = (void *)(roundup((phys_addr_t)h +
>                                 sizeof(struct early_heap_header),
>                                 sizeof(phys_addr_t)));
>         h->free_bytes = bytes - roundup(sizeof(struct early_heap_header),
>                                 sizeof(phys_addr_t));
>         h->next_early_heap = NULL;
>
>         return h;
> }

Regards,

Graeme

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCHv4] [RFC] DM: early_malloc for DM added.
  2012-08-27 12:12 [U-Boot] [PATCH 1/1] [RFC] DM: early_malloc for DM added Tomas Hlavacek
  2012-08-27 12:18 ` Marek Vasut
  2012-08-27 12:42 ` [U-Boot] [PATCHv2 " Tomas Hlavacek
@ 2012-09-18  7:13 ` Tomas Hlavacek
  2012-09-18 10:57   ` Marek Vasut
  2012-09-18 23:25   ` Graeme Russ
  2012-09-22  0:25 ` [U-Boot] [PATCH v5] [RFC] " Tomas Hlavacek
                   ` (5 subsequent siblings)
  8 siblings, 2 replies; 48+ messages in thread
From: Tomas Hlavacek @ 2012-09-18  7:13 UTC (permalink / raw)
  To: u-boot

early_malloc for DM with support for more heaps and lightweight
first heap on stack.

Adaptation layer for seamless calling of early_malloc or dlmalloc from
DM based on init stage added (dmmalloc() and related functions).

Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
---
 arch/arm/include/asm/config.h             |    3 +
 arch/arm/include/asm/global_data.h        |    1 +
 arch/arm/lib/board.c                      |    7 ++
 arch/avr32/include/asm/global_data.h      |    1 +
 arch/avr32/lib/board.c                    |    6 ++
 arch/blackfin/include/asm/global_data.h   |    1 +
 arch/blackfin/lib/board.c                 |    7 ++
 arch/m68k/include/asm/global_data.h       |    1 +
 arch/m68k/lib/board.c                     |    7 ++
 arch/microblaze/include/asm/global_data.h |    1 +
 arch/microblaze/lib/board.c               |    8 ++
 arch/mips/include/asm/global_data.h       |    1 +
 arch/mips/lib/board.c                     |    7 ++
 arch/nds32/include/asm/global_data.h      |    1 +
 arch/nds32/lib/board.c                    |    6 ++
 arch/nios2/include/asm/global_data.h      |    1 +
 arch/nios2/lib/board.c                    |    6 ++
 arch/openrisc/include/asm/global_data.h   |    1 +
 arch/openrisc/lib/board.c                 |    6 ++
 arch/powerpc/include/asm/global_data.h    |    1 +
 arch/powerpc/lib/board.c                  |    6 ++
 arch/sandbox/include/asm/global_data.h    |    1 +
 arch/sandbox/lib/board.c                  |    6 ++
 arch/sh/include/asm/global_data.h         |    1 +
 arch/sh/lib/board.c                       |    6 ++
 arch/sparc/include/asm/global_data.h      |    1 +
 arch/sparc/lib/board.c                    |    6 ++
 arch/x86/include/asm/global_data.h        |    1 +
 arch/x86/lib/board.c                      |   14 ++++
 common/Makefile                           |    1 +
 common/dmmalloc.c                         |  128 +++++++++++++++++++++++++++++
 include/configs/zipitz2.h                 |   12 ++-
 include/dmmalloc.h                        |   51 ++++++++++++
 33 files changed, 306 insertions(+), 1 deletion(-)
 create mode 100644 common/dmmalloc.c
 create mode 100644 include/dmmalloc.h

diff --git a/arch/arm/include/asm/config.h b/arch/arm/include/asm/config.h
index c60dba2..8e2f67b 100644
--- a/arch/arm/include/asm/config.h
+++ b/arch/arm/include/asm/config.h
@@ -23,4 +23,7 @@
 
 #define CONFIG_LMB
 #define CONFIG_SYS_BOOT_RAMDISK_HIGH
+
+#define CONFIG_SYS_EARLY_MALLOC
 #endif
+
diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index c3ff789..8563d49 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -84,6 +84,7 @@ typedef	struct	global_data {
 	unsigned long	post_log_res; /* success of POST test */
 	unsigned long	post_init_f_time; /* When post_init_f started */
 #endif
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
index 500e216..33e74da 100644
--- a/arch/arm/lib/board.c
+++ b/arch/arm/lib/board.c
@@ -52,6 +52,7 @@
 #include <fdtdec.h>
 #include <post.h>
 #include <logbuff.h>
+#include <dmmalloc.h>
 
 #ifdef CONFIG_BITBANGMII
 #include <miiphy.h>
@@ -273,6 +274,12 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	/* Initialize early_malloc */
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->mon_len = _bss_end_ofs;
 #ifdef CONFIG_OF_EMBED
 	/* Get a pointer to the FDT */
diff --git a/arch/avr32/include/asm/global_data.h b/arch/avr32/include/asm/global_data.h
index 5c654bd..9ae7c5e 100644
--- a/arch/avr32/include/asm/global_data.h
+++ b/arch/avr32/include/asm/global_data.h
@@ -50,6 +50,7 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/avr32/lib/board.c b/arch/avr32/lib/board.c
index 63fe297..6c97ef7 100644
--- a/arch/avr32/lib/board.c
+++ b/arch/avr32/lib/board.c
@@ -25,6 +25,7 @@
 #include <stdio_dev.h>
 #include <version.h>
 #include <net.h>
+#include <dmmalloc.h>
 
 #ifdef CONFIG_BITBANGMII
 #include <miiphy.h>
@@ -149,6 +150,11 @@ void board_init_f(ulong board_type)
 	memset(&gd_data, 0, sizeof(gd_data));
 	gd = &gd_data;
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	/* Initialize early_malloc */
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	/* Perform initialization sequence */
 	board_early_init_f();
 	cpu_init();
diff --git a/arch/blackfin/include/asm/global_data.h b/arch/blackfin/include/asm/global_data.h
index 67aa30f..33d3cec 100644
--- a/arch/blackfin/include/asm/global_data.h
+++ b/arch/blackfin/include/asm/global_data.h
@@ -59,6 +59,7 @@ typedef struct global_data {
 
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+	void	*early_heap_first;	/* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c
index e3ee4cd..35257d7 100644
--- a/arch/blackfin/lib/board.c
+++ b/arch/blackfin/lib/board.c
@@ -24,6 +24,8 @@
 #include <asm/mach-common/bits/mpu.h>
 #include <kgdb.h>
 
+#include <dmmalloc.h>
+
 #ifdef CONFIG_CMD_NAND
 #include <nand.h>	/* cannot even include nand.h if it isnt configured */
 #endif
@@ -250,6 +252,11 @@ void board_init_f(ulong bootflag)
 	bd->bi_memstart = CONFIG_SYS_SDRAM_BASE;
 	bd->bi_memsize = CONFIG_SYS_MAX_RAM_SIZE;
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	/* Initialize early_malloc */
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	/* Initialize */
 	serial_early_puts("IRQ init\n");
 	irq_init();
diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h
index 0ba2b43..ddd76f9 100644
--- a/arch/m68k/include/asm/global_data.h
+++ b/arch/m68k/include/asm/global_data.h
@@ -68,6 +68,7 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/m68k/lib/board.c b/arch/m68k/lib/board.c
index 1526967..7ee7830 100644
--- a/arch/m68k/lib/board.c
+++ b/arch/m68k/lib/board.c
@@ -30,6 +30,8 @@
 #include <malloc.h>
 #include <stdio_dev.h>
 
+#include <dmmalloc.h>
+
 #include <asm/immap.h>
 
 #if defined(CONFIG_CMD_IDE)
@@ -227,6 +229,11 @@ board_init_f (ulong bootflag)
 	/* Clear initial global data */
 	memset ((void *) gd, 0, sizeof (gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	/* Initialize early_malloc */
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0) {
 			hang ();
diff --git a/arch/microblaze/include/asm/global_data.h b/arch/microblaze/include/asm/global_data.h
index 6e8537c..4e340e6 100644
--- a/arch/microblaze/include/asm/global_data.h
+++ b/arch/microblaze/include/asm/global_data.h
@@ -47,6 +47,7 @@ typedef	struct	global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c
index 9828b76..a60e36f 100644
--- a/arch/microblaze/lib/board.c
+++ b/arch/microblaze/lib/board.c
@@ -33,6 +33,8 @@
 #include <net.h>
 #include <asm/processor.h>
 
+#include <dmmalloc.h>
+
 DECLARE_GLOBAL_DATA_PTR;
 
 #ifdef CONFIG_SYS_GPIO_0
@@ -101,6 +103,12 @@ void board_init (void)
 	asm ("nop");	/* FIXME gd is not initialize - wait */
 	memset ((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 	memset ((void *)bd, 0, GENERATED_BD_INFO_SIZE);
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	/* Initialize early_malloc */
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = bd;
 	gd->baudrate = CONFIG_BAUDRATE;
 	bd->bi_baudrate = CONFIG_BAUDRATE;
diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h
index f6cf9fe..9656fd6 100644
--- a/arch/mips/include/asm/global_data.h
+++ b/arch/mips/include/asm/global_data.h
@@ -61,6 +61,7 @@ typedef	struct	global_data {
 	unsigned long	env_valid;	/* Checksum of Environment valid? */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/mips/lib/board.c b/arch/mips/lib/board.c
index d998f0e..d2349bf 100644
--- a/arch/mips/lib/board.c
+++ b/arch/mips/lib/board.c
@@ -32,6 +32,8 @@
 #include <onenand_uboot.h>
 #include <spi.h>
 
+#include <dmmalloc.h>
+
 #ifdef CONFIG_BITBANGMII
 #include <miiphy.h>
 #endif
@@ -160,6 +162,11 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	/* Initialize early_malloc */
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0)
 			hang();
diff --git a/arch/nds32/include/asm/global_data.h b/arch/nds32/include/asm/global_data.h
index de20a0a..313fecb 100644
--- a/arch/nds32/include/asm/global_data.h
+++ b/arch/nds32/include/asm/global_data.h
@@ -65,6 +65,7 @@ typedef	struct global_data {
 
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/nds32/lib/board.c b/arch/nds32/lib/board.c
index 074aabf..952fc1f 100644
--- a/arch/nds32/lib/board.c
+++ b/arch/nds32/lib/board.c
@@ -36,6 +36,7 @@
 #include <nand.h>
 #include <onenand_uboot.h>
 #include <mmc.h>
+#include <dmmalloc.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -190,6 +191,11 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	/* Initialize early_malloc */
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->mon_len = (unsigned int)(&__bss_end__) - (unsigned int)(&_start);
 
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
diff --git a/arch/nios2/include/asm/global_data.h b/arch/nios2/include/asm/global_data.h
index 4b86fbd..02f93d3 100644
--- a/arch/nios2/include/asm/global_data.h
+++ b/arch/nios2/include/asm/global_data.h
@@ -42,6 +42,7 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /* flags */
diff --git a/arch/nios2/lib/board.c b/arch/nios2/lib/board.c
index 65de26e..8a65c2e 100644
--- a/arch/nios2/lib/board.c
+++ b/arch/nios2/lib/board.c
@@ -30,6 +30,7 @@
 #include <malloc.h>
 #include <mmc.h>
 #include <net.h>
+#include <dmmalloc.h>
 #ifdef CONFIG_STATUS_LED
 #include <status_led.h>
 #endif
@@ -97,6 +98,11 @@ void board_init (void)
 
 	memset( gd, 0, GENERATED_GBL_DATA_SIZE );
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	/* Initialize early_malloc */
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = (bd_t *)(gd+1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/openrisc/include/asm/global_data.h b/arch/openrisc/include/asm/global_data.h
index 36de9d0..032b6b2 100644
--- a/arch/openrisc/include/asm/global_data.h
+++ b/arch/openrisc/include/asm/global_data.h
@@ -46,6 +46,7 @@ typedef struct global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/openrisc/lib/board.c b/arch/openrisc/lib/board.c
index 85aa189..30fca25 100644
--- a/arch/openrisc/lib/board.c
+++ b/arch/openrisc/lib/board.c
@@ -34,6 +34,7 @@
 #include <malloc.h>
 #include <mmc.h>
 #include <net.h>
+#include <dmmalloc.h>
 #ifdef CONFIG_STATUS_LED
 #include <status_led.h>
 #endif
@@ -86,6 +87,11 @@ void board_init(void)
 
 	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	/* Initialize early_malloc */
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = (bd_t *)(gd+1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h
index 01f1d4a..0839d03 100644
--- a/arch/powerpc/include/asm/global_data.h
+++ b/arch/powerpc/include/asm/global_data.h
@@ -184,6 +184,7 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
index 3f9af1d..41ee9db 100644
--- a/arch/powerpc/lib/board.c
+++ b/arch/powerpc/lib/board.c
@@ -26,6 +26,7 @@
 #include <command.h>
 #include <malloc.h>
 #include <stdio_dev.h>
+#include <dmmalloc.h>
 #ifdef CONFIG_8xx
 #include <mpc8xx.h>
 #endif
@@ -389,6 +390,11 @@ void board_init_f(ulong bootflag)
 	memset((void *) gd, 0, sizeof(gd_t));
 #endif
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	/* Initialize early_malloc */
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)
 		if ((*init_fnc_ptr) () != 0)
 			hang();
diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h
index 8d47191..54342c0 100644
--- a/arch/sandbox/include/asm/global_data.h
+++ b/arch/sandbox/include/asm/global_data.h
@@ -47,6 +47,7 @@ typedef	struct global_data {
 	phys_size_t	ram_size;	/* RAM size */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/sandbox/lib/board.c b/arch/sandbox/lib/board.c
index b7997e9..055e493 100644
--- a/arch/sandbox/lib/board.c
+++ b/arch/sandbox/lib/board.c
@@ -44,6 +44,7 @@
 #include <timestamp.h>
 #include <version.h>
 #include <serial.h>
+#include <dmmalloc.h>
 
 #include <os.h>
 
@@ -156,6 +157,11 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	/* Initialize early_malloc */
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0)
 			hang();
diff --git a/arch/sh/include/asm/global_data.h b/arch/sh/include/asm/global_data.h
index 1b782fc..180f56e 100644
--- a/arch/sh/include/asm/global_data.h
+++ b/arch/sh/include/asm/global_data.h
@@ -42,6 +42,7 @@ typedef	struct global_data
 	unsigned long	env_valid;	/* Checksum of Environment valid */
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 #define	GD_FLG_RELOC		0x00001	/* Code was relocated to RAM		*/
diff --git a/arch/sh/lib/board.c b/arch/sh/lib/board.c
index d9c0c22..7d334f4 100644
--- a/arch/sh/lib/board.c
+++ b/arch/sh/lib/board.c
@@ -26,6 +26,7 @@
 #include <watchdog.h>
 #include <net.h>
 #include <environment.h>
+#include <dmmalloc.h>
 
 #ifdef CONFIG_BITBANGMII
 #include <miiphy.h>
@@ -160,6 +161,11 @@ void sh_generic_init(void)
 
 	memset(gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	/* Initialize early_malloc */
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
 
 	gd->bd = (bd_t *)(gd + 1);	/* At end of global data */
diff --git a/arch/sparc/include/asm/global_data.h b/arch/sparc/include/asm/global_data.h
index 613e2d8..82ed56f 100644
--- a/arch/sparc/include/asm/global_data.h
+++ b/arch/sparc/include/asm/global_data.h
@@ -76,6 +76,7 @@ typedef struct global_data {
 #endif
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+	void	*early_heap_first;	/* early heap for early_malloc */
 } gd_t;
 
 /*
diff --git a/arch/sparc/lib/board.c b/arch/sparc/lib/board.c
index 519a4fb..3421412 100644
--- a/arch/sparc/lib/board.c
+++ b/arch/sparc/lib/board.c
@@ -30,6 +30,7 @@
 #include <malloc.h>
 #include <stdio_dev.h>
 #include <config.h>
+#include <dmmalloc.h>
 #if defined(CONFIG_CMD_IDE)
 #include <ide.h>
 #endif
@@ -179,6 +180,11 @@ void board_init_f(ulong bootflag)
 	/* Clear initial global data */
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	/* Initialize early_malloc */
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = (bd_t *) (gd + 1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 908a02c..171f85b 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -59,6 +59,7 @@ typedef	struct global_data {
 	unsigned long	reset_status;	/* reset status register at boot */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+	void		*early_heap_first; /* early heap for early_malloc */
 } gd_t;
 
 static inline gd_t *get_fs_gd_ptr(void)
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
index 5f0b62c..b609dbe 100644
--- a/arch/x86/lib/board.c
+++ b/arch/x86/lib/board.c
@@ -40,6 +40,8 @@
 #include <asm/init_helpers.h>
 #include <asm/init_wrappers.h>
 
+#include <dmmalloc.h>
+
 /*
  * Breath some life into the board...
  *
@@ -85,6 +87,17 @@
 typedef int (init_fnc_t) (void);
 
 /*
+ * Initialize early heap (when enabled by config).
+ */
+static void early_malloc_init(void)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	/* Initialize early_malloc */
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+}
+
+/*
  * init_sequence_f is the list of init functions which are run when U-Boot
  * is executing from Flash with a limited 'C' environment. The following
  * limitations must be considered when implementing an '_f' function:
@@ -99,6 +112,7 @@ init_fnc_t *init_sequence_f[] = {
 	cpu_init_f,
 	board_early_init_f,
 	env_init,
+	early_malloc_init,
 	init_baudrate_f,
 	serial_init,
 	console_init_f,
diff --git a/common/Makefile b/common/Makefile
index 2a31c62..dfea4e8 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -188,6 +188,7 @@ COBJS-y += console.o
 COBJS-y += dlmalloc.o
 COBJS-y += memsize.o
 COBJS-y += stdio.o
+COBJS-y += dmmalloc.o
 
 
 COBJS	:= $(sort $(COBJS-y))
diff --git a/common/dmmalloc.c b/common/dmmalloc.c
new file mode 100644
index 0000000..18f2d95
--- /dev/null
+++ b/common/dmmalloc.c
@@ -0,0 +1,128 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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 <common.h> /* for ROUND_UP */
+#include <asm/u-boot.h>
+#include <asm/global_data.h> /* for gd_t and gd */
+#include <asm/types.h> /* for phys_addr_t and size_addt_t */
+
+#include <dmmalloc.h>
+#include <malloc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+static struct early_heap_header *def_early_brk(size_t size)
+{
+	struct early_heap_header *h =
+		(struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
+
+	h->free_space_pointer = (void *)(roundup(
+				(phys_addr_t)CONFIG_SYS_EARLY_HEAP_ADDR +
+				sizeof(struct early_heap_header),
+				sizeof(phys_addr_t)));
+	h->free_bytes = size - roundup(sizeof(struct early_heap_header),
+				sizeof(phys_addr_t));
+	h->next_early_heap = NULL;
+
+	return h;
+}
+
+struct early_heap_header *early_brk(size_t size)
+	__attribute__((weak, alias("def_early_brk")));
+
+
+void *early_malloc(size_t size)
+{
+	phys_addr_t addr;
+	struct early_heap_header *h;
+
+	/* Align size. */
+	size = roundup(size, sizeof(phys_addr_t));
+
+	/* Choose early_heap with enough space. */
+	h = gd->early_heap_first;
+	while ((h->free_bytes < size) && (h->next_early_heap != NULL))
+		h = h->next_early_heap;
+
+	if (h->free_bytes < size) {
+		debug("Early heap overflow. Heap %p, free %d, required %d.",
+			h, h->free_bytes, size);
+		return NULL;
+	}
+
+	/* Choose block beginning address and mark next free space. */
+	addr = (phys_addr_t)h->free_space_pointer;
+
+	h->free_space_pointer += size;
+	h->free_bytes -= size;
+
+	return (void *)addr;
+}
+
+static int is_early_malloc_active(void)
+{
+	if (gd->flags & GD_FLG_RELOC)
+		return 0;
+
+	return 1;
+}
+
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+void *dmmalloc(size_t size)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (is_early_malloc_active())
+		return early_malloc(size);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return malloc(size);
+}
+
+void dmfree(void *ptr)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (is_early_malloc_active())
+		return;
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	free(ptr);
+}
+
+void *dmcalloc(size_t n, size_t elem_size)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (is_early_malloc_active())
+		return NULL;
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return calloc(n, elem_size);
+}
+
+void *dmrealloc(void *oldmem, size_t bytes)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (is_early_malloc_active())
+		return NULL;
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return dmrealloc(oldmem, bytes);
+}
+
diff --git a/include/configs/zipitz2.h b/include/configs/zipitz2.h
index 26204af..5cd0dcb 100644
--- a/include/configs/zipitz2.h
+++ b/include/configs/zipitz2.h
@@ -176,8 +176,13 @@ unsigned char zipitz2_spi_read(void);
 
 #define	CONFIG_SYS_LOAD_ADDR		CONFIG_SYS_DRAM_BASE
 
+#define CONFIG_SYS_EARLY_HEAP_ADDR     (GENERATED_GBL_DATA_SIZE + \
+	PHYS_SDRAM_1)
+#define CONFIG_SYS_EARLY_HEAP_SIZE     256
+
 #define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
-#define	CONFIG_SYS_INIT_SP_ADDR		(GENERATED_GBL_DATA_SIZE + PHYS_SDRAM_1 + 2048)
+#define CONFIG_SYS_INIT_SP_ADDR		(GENERATED_GBL_DATA_SIZE + \
+	CONFIG_SYS_EARLY_HEAP_SIZE + PHYS_SDRAM_1 + 2048)
 
 /*
  * NOR FLASH
@@ -260,4 +265,9 @@ unsigned char zipitz2_spi_read(void);
 #define CONFIG_SYS_MCIO0_VAL	0x0001430f
 #define CONFIG_SYS_MCIO1_VAL	0x0001430f
 
+/*
+ * DM components
+ */
+#define CONFIG_SYS_EARLY_MALLOC
+
 #endif	/* __CONFIG_H */
diff --git a/include/dmmalloc.h b/include/dmmalloc.h
new file mode 100644
index 0000000..01beea7
--- /dev/null
+++ b/include/dmmalloc.h
@@ -0,0 +1,51 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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
+ */
+
+#ifndef __INCLUDE_DMMALLOC_H
+#define __INCLUDE_DMMALLOC_H
+
+#include <config.h>
+#include <linux/stddef.h> /* for size_t */
+
+#if (!defined(CONFIG_SYS_EARLY_HEAP_ADDR)) || \
+	(!defined(CONFIG_SYS_EARLY_HEAP_SIZE))
+#undef CONFIG_SYS_EARLY_MALLOC
+#endif /* CONFIG_SYS_EARLY_HEAP_ADDR */
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+struct early_heap_header {
+	void *free_space_pointer;
+	size_t free_bytes;
+	void *next_early_heap;
+};
+
+struct early_heap_header *early_brk(size_t size);
+void *early_malloc(size_t size);
+
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+void *dmmalloc(size_t size);
+void dmfree(void *ptr);
+
+#endif /* __INCLUDE_DMMALLOC_H */
+
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCHv4] [RFC] DM: early_malloc for DM added.
  2012-09-18  7:13 ` [U-Boot] [PATCHv4] " Tomas Hlavacek
@ 2012-09-18 10:57   ` Marek Vasut
  2012-09-18 23:29     ` Graeme Russ
  2012-09-18 23:25   ` Graeme Russ
  1 sibling, 1 reply; 48+ messages in thread
From: Marek Vasut @ 2012-09-18 10:57 UTC (permalink / raw)
  To: u-boot

Dear Tomas Hlavacek,

> early_malloc for DM with support for more heaps and lightweight
> first heap on stack.
> 
> Adaptation layer for seamless calling of early_malloc or dlmalloc from
> DM based on init stage added (dmmalloc() and related functions).
> 
> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
> ---

It looks mostly OK, few comments

I'd say, pull out the modification of global data into separate patch and put it 
before this patch. That'd make review of the core code much easier.

[...]

> +
> +#include <common.h> /* for ROUND_UP */
> +#include <asm/u-boot.h>
> +#include <asm/global_data.h> /* for gd_t and gd */
> +#include <asm/types.h> /* for phys_addr_t and size_addt_t */
> +
> +#include <dmmalloc.h>
> +#include <malloc.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +static struct early_heap_header *def_early_brk(size_t size)
> +{
> +	struct early_heap_header *h =
> +		(struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
> +
> +	h->free_space_pointer = (void *)(roundup(
> +				(phys_addr_t)CONFIG_SYS_EARLY_HEAP_ADDR +
> +				sizeof(struct early_heap_header),
> +				sizeof(phys_addr_t)));
> +	h->free_bytes = size - roundup(sizeof(struct early_heap_header),
> +				sizeof(phys_addr_t));
> +	h->next_early_heap = NULL;
> +
> +	return h;
> +}
> +
> +struct early_heap_header *early_brk(size_t size)
> +	__attribute__((weak, alias("def_early_brk")));

what about using (it needs <linux/compiler.h>):

__weak struct early_heap_header *early_brk(size_t size)
{
...
body
...
}

> +void *early_malloc(size_t size)
> +{
> +	phys_addr_t addr;
> +	struct early_heap_header *h;
> +
> +	/* Align size. */
> +	size = roundup(size, sizeof(phys_addr_t));
> +
> +	/* Choose early_heap with enough space. */
> +	h = gd->early_heap_first;
> +	while ((h->free_bytes < size) && (h->next_early_heap != NULL))
> +		h = h->next_early_heap;
> +
> +	if (h->free_bytes < size) {
> +		debug("Early heap overflow. Heap %p, free %d, required %d.",
> +			h, h->free_bytes, size);
> +		return NULL;
> +	}
> +
> +	/* Choose block beginning address and mark next free space. */
> +	addr = (phys_addr_t)h->free_space_pointer;
> +
> +	h->free_space_pointer += size;
> +	h->free_bytes -= size;
> +
> +	return (void *)addr;
> +}
> +
> +static int is_early_malloc_active(void)
> +{
> +	if (gd->flags & GD_FLG_RELOC)
> +		return 0;
> +
> +	return 1;
> +}
> +
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
> +void *dmmalloc(size_t size)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	if (is_early_malloc_active())
> +		return early_malloc(size);
> +#endif /* CONFIG_SYS_EARLY_MALLOC */

Or you can implement empty prototypes for these functions in case CONFIG_SYS ... 
isn't defined to punt this preprocessor bloat.

> +	return malloc(size);
> +}

[...]

> diff --git a/include/configs/zipitz2.h b/include/configs/zipitz2.h
> index 26204af..5cd0dcb 100644
> --- a/include/configs/zipitz2.h
> +++ b/include/configs/zipitz2.h
> @@ -176,8 +176,13 @@ unsigned char zipitz2_spi_read(void);
> 
>  #define	CONFIG_SYS_LOAD_ADDR		CONFIG_SYS_DRAM_BASE
> 
> +#define CONFIG_SYS_EARLY_HEAP_ADDR     (GENERATED_GBL_DATA_SIZE + \
> +	PHYS_SDRAM_1)
> +#define CONFIG_SYS_EARLY_HEAP_SIZE     256
> +

1) Pull this file into separate patch and order it afterwards this patch.
2) You're putting your early thingie into SDRAM, which works on PXA (sadly) ... 
looking through the PXA init code, it needs cleanup, damn

... there's no real hint so far, just a rant.

>  #define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
> -#define	CONFIG_SYS_INIT_SP_ADDR		(GENERATED_GBL_DATA_SIZE + 
PHYS_SDRAM_1 +
> 2048) +#define CONFIG_SYS_INIT_SP_ADDR		(GENERATED_GBL_DATA_SIZE 
+ \
> +	CONFIG_SYS_EARLY_HEAP_SIZE + PHYS_SDRAM_1 + 2048)
> 
>  /*
>   * NOR FLASH
> @@ -260,4 +265,9 @@ unsigned char zipitz2_spi_read(void);
>  #define CONFIG_SYS_MCIO0_VAL	0x0001430f
>  #define CONFIG_SYS_MCIO1_VAL	0x0001430f

[...]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCHv4] [RFC] DM: early_malloc for DM added.
  2012-09-18  7:13 ` [U-Boot] [PATCHv4] " Tomas Hlavacek
  2012-09-18 10:57   ` Marek Vasut
@ 2012-09-18 23:25   ` Graeme Russ
  1 sibling, 0 replies; 48+ messages in thread
From: Graeme Russ @ 2012-09-18 23:25 UTC (permalink / raw)
  To: u-boot

Hi Tomas

On Tue, Sep 18, 2012 at 5:13 PM, Tomas Hlavacek <tmshlvck@gmail.com> wrote:
> early_malloc for DM with support for more heaps and lightweight
> first heap on stack.

Technically, you are not putting the first heap on the stack - you are
sacrificing some early stack space to create the early heap

>
> Adaptation layer for seamless calling of early_malloc or dlmalloc from
> DM based on init stage added (dmmalloc() and related functions).
>
> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
> ---
>  arch/arm/include/asm/config.h             |    3 +
>  arch/arm/include/asm/global_data.h        |    1 +
>  arch/arm/lib/board.c                      |    7 ++
>  arch/avr32/include/asm/global_data.h      |    1 +
>  arch/avr32/lib/board.c                    |    6 ++
>  arch/blackfin/include/asm/global_data.h   |    1 +
>  arch/blackfin/lib/board.c                 |    7 ++
>  arch/m68k/include/asm/global_data.h       |    1 +
>  arch/m68k/lib/board.c                     |    7 ++
>  arch/microblaze/include/asm/global_data.h |    1 +
>  arch/microblaze/lib/board.c               |    8 ++
>  arch/mips/include/asm/global_data.h       |    1 +
>  arch/mips/lib/board.c                     |    7 ++
>  arch/nds32/include/asm/global_data.h      |    1 +
>  arch/nds32/lib/board.c                    |    6 ++
>  arch/nios2/include/asm/global_data.h      |    1 +
>  arch/nios2/lib/board.c                    |    6 ++
>  arch/openrisc/include/asm/global_data.h   |    1 +
>  arch/openrisc/lib/board.c                 |    6 ++
>  arch/powerpc/include/asm/global_data.h    |    1 +
>  arch/powerpc/lib/board.c                  |    6 ++
>  arch/sandbox/include/asm/global_data.h    |    1 +
>  arch/sandbox/lib/board.c                  |    6 ++
>  arch/sh/include/asm/global_data.h         |    1 +
>  arch/sh/lib/board.c                       |    6 ++
>  arch/sparc/include/asm/global_data.h      |    1 +
>  arch/sparc/lib/board.c                    |    6 ++
>  arch/x86/include/asm/global_data.h        |    1 +
>  arch/x86/lib/board.c                      |   14 ++++
>  common/Makefile                           |    1 +
>  common/dmmalloc.c                         |  128 +++++++++++++++++++++++++++++
>  include/configs/zipitz2.h                 |   12 ++-

WTF! - Move this out into another patch

>  include/dmmalloc.h                        |   51 ++++++++++++
>  33 files changed, 306 insertions(+), 1 deletion(-)
>  create mode 100644 common/dmmalloc.c
>  create mode 100644 include/dmmalloc.h
>
> diff --git a/arch/arm/include/asm/config.h b/arch/arm/include/asm/config.h
> index c60dba2..8e2f67b 100644
> --- a/arch/arm/include/asm/config.h
> +++ b/arch/arm/include/asm/config.h
> @@ -23,4 +23,7 @@
>
>  #define CONFIG_LMB
>  #define CONFIG_SYS_BOOT_RAMDISK_HIGH
> +
> +#define CONFIG_SYS_EARLY_MALLOC
>  #endif
> +

Why are you adding this define to ARM and nothing else? Shouldn't it be an
all-in or none-in proposition?

(and why the stray eol white-space?)

> diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
> index c3ff789..8563d49 100644
> --- a/arch/arm/include/asm/global_data.h
> +++ b/arch/arm/include/asm/global_data.h
> @@ -84,6 +84,7 @@ typedef       struct  global_data {
>         unsigned long   post_log_res; /* success of POST test */
>         unsigned long   post_init_f_time; /* When post_init_f started */
>  #endif
> +       void            *early_heap_first; /* early heap for early_malloc */
>  } gd_t;

early_heap_first is only used if CONFIG_SYS_EARLY_MALLOC is defined, so
wrap a #ifdef around it. This will also help to detect unintended usage
if CONFIG_SYS_EARLY_MALLOC is not defined.

>
>  /*
> diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
> index 500e216..33e74da 100644
> --- a/arch/arm/lib/board.c
> +++ b/arch/arm/lib/board.c
> @@ -52,6 +52,7 @@
>  #include <fdtdec.h>
>  #include <post.h>
>  #include <logbuff.h>
> +#include <dmmalloc.h>
>
>  #ifdef CONFIG_BITBANGMII
>  #include <miiphy.h>
> @@ -273,6 +274,12 @@ void board_init_f(ulong bootflag)
>
>         memset((void *)gd, 0, sizeof(gd_t));
>
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +       /* Initialize early_malloc */
> +       gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +

Did you checkpatch? You've added an additional blank line (for a total of
two)

[snip]

> diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
> index 5f0b62c..b609dbe 100644
> --- a/arch/x86/lib/board.c
> +++ b/arch/x86/lib/board.c
> @@ -40,6 +40,8 @@
>  #include <asm/init_helpers.h>
>  #include <asm/init_wrappers.h>
>
> +#include <dmmalloc.h>
> +
>  /*
>   * Breath some life into the board...
>   *
> @@ -85,6 +87,17 @@
>  typedef int (init_fnc_t) (void);
>
>  /*
> + * Initialize early heap (when enabled by config).
> + */
> +static void early_malloc_init(void)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +       /* Initialize early_malloc */
> +       gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +}
> +
> +/*
>   * init_sequence_f is the list of init functions which are run when U-Boot
>   * is executing from Flash with a limited 'C' environment. The following
>   * limitations must be considered when implementing an '_f' function:
> @@ -99,6 +112,7 @@ init_fnc_t *init_sequence_f[] = {
>         cpu_init_f,
>         board_early_init_f,
>         env_init,
> +       early_malloc_init,

Put the #ifdef here - gc_sections will clean up the unused function

>         init_baudrate_f,
>         serial_init,
>         console_init_f,
> diff --git a/common/Makefile b/common/Makefile
> index 2a31c62..dfea4e8 100644
> --- a/common/Makefile
> +++ b/common/Makefile
> @@ -188,6 +188,7 @@ COBJS-y += console.o
>  COBJS-y += dlmalloc.o
>  COBJS-y += memsize.o
>  COBJS-y += stdio.o
> +COBJS-y += dmmalloc.o

COBJS-$(CONFIG_SYS_EARLY_MALLOC)

or

COBJS-$(CONFIG_SYS_DM)

If DM mandates early_malloc (which I think it will) then we need to tie the
#defines together somehow

>  COBJS  := $(sort $(COBJS-y))
> diff --git a/common/dmmalloc.c b/common/dmmalloc.c
> new file mode 100644
> index 0000000..18f2d95
> --- /dev/null
> +++ b/common/dmmalloc.c
> @@ -0,0 +1,128 @@
> +/*
> + * (C) Copyright 2012
> + * Tomas Hlavacek (tmshlvck at gmail.com)
> + *
> + * 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 <common.h> /* for ROUND_UP */
> +#include <asm/u-boot.h>
> +#include <asm/global_data.h> /* for gd_t and gd */
> +#include <asm/types.h> /* for phys_addr_t and size_addt_t */

Drop the comments - they are ugly

> +
> +#include <dmmalloc.h>
> +#include <malloc.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +static struct early_heap_header *def_early_brk(size_t size)
> +{
> +       struct early_heap_header *h =
> +               (struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
> +
> +       h->free_space_pointer = (void *)(roundup(
> +                               (phys_addr_t)CONFIG_SYS_EARLY_HEAP_ADDR +
> +                               sizeof(struct early_heap_header),
> +                               sizeof(phys_addr_t)));
> +       h->free_bytes = size - roundup(sizeof(struct early_heap_header),
> +                               sizeof(phys_addr_t));
> +       h->next_early_heap = NULL;
> +
> +       return h;
> +}
> +
> +struct early_heap_header *early_brk(size_t size)
> +       __attribute__((weak, alias("def_early_brk")));
> +
> +
> +void *early_malloc(size_t size)
> +{
> +       phys_addr_t addr;
> +       struct early_heap_header *h;
> +
> +       /* Align size. */
> +       size = roundup(size, sizeof(phys_addr_t));
> +
> +       /* Choose early_heap with enough space. */
> +       h = gd->early_heap_first;
> +       while ((h->free_bytes < size) && (h->next_early_heap != NULL))
> +               h = h->next_early_heap;
> +
> +       if (h->free_bytes < size) {

You will get a NULL-pointer exception if no early heap has enough space

You also need to add some logic to allocate an additional early heap by
calling early_brk. If that call fails (returns NULL) then bail out

> +               debug("Early heap overflow. Heap %p, free %d, required %d.",
> +                       h, h->free_bytes, size);
> +               return NULL;
> +       }
> +
> +       /* Choose block beginning address and mark next free space. */
> +       addr = (phys_addr_t)h->free_space_pointer;
> +
> +       h->free_space_pointer += size;
> +       h->free_bytes -= size;
> +
> +       return (void *)addr;
> +}
> +
> +static int is_early_malloc_active(void)
> +{
> +       if (gd->flags & GD_FLG_RELOC)
> +               return 0;
> +
> +       return 1;

Hmmm, return ((gd->flags & GD_FLG_RELOC) == GD_FLG_RELOC); ?

I also prefer the semantics of not having 'is_'. "if blah" reads better
to me than "if is blah" - YMMV

> +}
> +
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
> +void *dmmalloc(size_t size)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +       if (is_early_malloc_active())
> +               return early_malloc(size);
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +       return malloc(size);
> +}

The argument over dmmalloc() versus transparent malloc() is far from over
IMNSHO, but for now, this will have to do :)

> +
> +void dmfree(void *ptr)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +       if (is_early_malloc_active())
> +               return;
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +       free(ptr);
> +}
> +
> +void *dmcalloc(size_t n, size_t elem_size)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +       if (is_early_malloc_active())
> +               return NULL;
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +       return calloc(n, elem_size);
> +}
> +
> +void *dmrealloc(void *oldmem, size_t bytes)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +       if (is_early_malloc_active())
> +               return NULL;
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +       return dmrealloc(oldmem, bytes);
> +}
> +

[snip]

Regards,

Graeme

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCHv4] [RFC] DM: early_malloc for DM added.
  2012-09-18 10:57   ` Marek Vasut
@ 2012-09-18 23:29     ` Graeme Russ
  2012-09-18 23:33       ` Marek Vasut
                         ` (2 more replies)
  0 siblings, 3 replies; 48+ messages in thread
From: Graeme Russ @ 2012-09-18 23:29 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On Tue, Sep 18, 2012 at 8:57 PM, Marek Vasut <marex@denx.de> wrote:
> Dear Tomas Hlavacek,
>
>> early_malloc for DM with support for more heaps and lightweight
>> first heap on stack.
>>
>> Adaptation layer for seamless calling of early_malloc or dlmalloc from
>> DM based on init stage added (dmmalloc() and related functions).
>>
>> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
>> ---
>
> It looks mostly OK, few comments
>
> I'd say, pull out the modification of global data into separate patch and put it
> before this patch. That'd make review of the core code much easier.

NAK - The addition of the global data member is intrinsic to the early
malloc implmentaion. Keep them together

>
> [...]
>
>> +
>> +#include <common.h> /* for ROUND_UP */
>> +#include <asm/u-boot.h>
>> +#include <asm/global_data.h> /* for gd_t and gd */
>> +#include <asm/types.h> /* for phys_addr_t and size_addt_t */
>> +
>> +#include <dmmalloc.h>
>> +#include <malloc.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> +static struct early_heap_header *def_early_brk(size_t size)
>> +{
>> +     struct early_heap_header *h =
>> +             (struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
>> +
>> +     h->free_space_pointer = (void *)(roundup(
>> +                             (phys_addr_t)CONFIG_SYS_EARLY_HEAP_ADDR +
>> +                             sizeof(struct early_heap_header),
>> +                             sizeof(phys_addr_t)));
>> +     h->free_bytes = size - roundup(sizeof(struct early_heap_header),
>> +                             sizeof(phys_addr_t));
>> +     h->next_early_heap = NULL;
>> +
>> +     return h;
>> +}
>> +
>> +struct early_heap_header *early_brk(size_t size)
>> +     __attribute__((weak, alias("def_early_brk")));
>
> what about using (it needs <linux/compiler.h>):
>
> __weak struct early_heap_header *early_brk(size_t size)
> {
> ...
> body
> ...
> }

We already have a lot of the former - I prefer not to add additional
semantics (unless you want to do a wholesale search/replace ;))


>> +void *dmmalloc(size_t size)
>> +{
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> +     if (is_early_malloc_active())
>> +             return early_malloc(size);
>> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>
> Or you can implement empty prototypes for these functions in case CONFIG_SYS ...
> isn't defined to punt this preprocessor bloat.

Agree

>
>> +     return malloc(size);
>> +}
>
> [...]
>
>> diff --git a/include/configs/zipitz2.h b/include/configs/zipitz2.h
>> index 26204af..5cd0dcb 100644
>> --- a/include/configs/zipitz2.h
>> +++ b/include/configs/zipitz2.h
>> @@ -176,8 +176,13 @@ unsigned char zipitz2_spi_read(void);
>>
>>  #define      CONFIG_SYS_LOAD_ADDR            CONFIG_SYS_DRAM_BASE
>>
>> +#define CONFIG_SYS_EARLY_HEAP_ADDR     (GENERATED_GBL_DATA_SIZE + \
>> +     PHYS_SDRAM_1)
>> +#define CONFIG_SYS_EARLY_HEAP_SIZE     256
>> +
>
> 1) Pull this file into separate patch and order it afterwards this patch.

Already agreed :)

Regards,

Graeme

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCHv4] [RFC] DM: early_malloc for DM added.
  2012-09-18 23:29     ` Graeme Russ
@ 2012-09-18 23:33       ` Marek Vasut
  2012-09-18 23:44         ` Graeme Russ
  2012-09-19 18:29       ` Tom Rini
  2012-09-22  0:37       ` Tomas Hlavacek
  2 siblings, 1 reply; 48+ messages in thread
From: Marek Vasut @ 2012-09-18 23:33 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,

> Hi Marek,
> 
> On Tue, Sep 18, 2012 at 8:57 PM, Marek Vasut <marex@denx.de> wrote:
> > Dear Tomas Hlavacek,
> > 
> >> early_malloc for DM with support for more heaps and lightweight
> >> first heap on stack.
> >> 
> >> Adaptation layer for seamless calling of early_malloc or dlmalloc from
> >> DM based on init stage added (dmmalloc() and related functions).
> >> 
> >> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
> >> ---
> > 
> > It looks mostly OK, few comments
> > 
> > I'd say, pull out the modification of global data into separate patch and
> > put it before this patch. That'd make review of the core code much
> > easier.
> 
> NAK - The addition of the global data member is intrinsic to the early
> malloc implmentaion. Keep them together

Very pleasant to review too, I almost didn't manage to find the core dmmalloc 
code in all that bloat.

> > [...]
> > 
> >> +
> >> +#include <common.h> /* for ROUND_UP */
> >> +#include <asm/u-boot.h>
> >> +#include <asm/global_data.h> /* for gd_t and gd */
> >> +#include <asm/types.h> /* for phys_addr_t and size_addt_t */
> >> +
> >> +#include <dmmalloc.h>
> >> +#include <malloc.h>
> >> +
> >> +DECLARE_GLOBAL_DATA_PTR;
> >> +
> >> +#ifdef CONFIG_SYS_EARLY_MALLOC
> >> +static struct early_heap_header *def_early_brk(size_t size)
> >> +{
> >> +     struct early_heap_header *h =
> >> +             (struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
> >> +
> >> +     h->free_space_pointer = (void *)(roundup(
> >> +                             (phys_addr_t)CONFIG_SYS_EARLY_HEAP_ADDR +
> >> +                             sizeof(struct early_heap_header),
> >> +                             sizeof(phys_addr_t)));
> >> +     h->free_bytes = size - roundup(sizeof(struct early_heap_header),
> >> +                             sizeof(phys_addr_t));
> >> +     h->next_early_heap = NULL;
> >> +
> >> +     return h;
> >> +}
> >> +
> >> +struct early_heap_header *early_brk(size_t size)
> >> +     __attribute__((weak, alias("def_early_brk")));
> > 
> > what about using (it needs <linux/compiler.h>):
> > 
> > __weak struct early_heap_header *early_brk(size_t size)
> > {
> > ...
> > body
> > ...
> > }
> 
> We already have a lot of the former - I prefer not to add additional
> semantics (unless you want to do a wholesale search/replace ;))

The former looks like shit and the later is more linux-friendly. I'd say stick 
with the later to avoid this insane __attribute__(()) construct.

> >> +void *dmmalloc(size_t size)
> >> +{
> >> +#ifdef CONFIG_SYS_EARLY_MALLOC
> >> +     if (is_early_malloc_active())
> >> +             return early_malloc(size);
> >> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> > 
> > Or you can implement empty prototypes for these functions in case
> > CONFIG_SYS ... isn't defined to punt this preprocessor bloat.
> 
> Agree
> 
> >> +     return malloc(size);
> >> +}
> > 
> > [...]
> > 
> >> diff --git a/include/configs/zipitz2.h b/include/configs/zipitz2.h
> >> index 26204af..5cd0dcb 100644
> >> --- a/include/configs/zipitz2.h
> >> +++ b/include/configs/zipitz2.h
> >> @@ -176,8 +176,13 @@ unsigned char zipitz2_spi_read(void);
> >> 
> >>  #define      CONFIG_SYS_LOAD_ADDR            CONFIG_SYS_DRAM_BASE
> >> 
> >> +#define CONFIG_SYS_EARLY_HEAP_ADDR     (GENERATED_GBL_DATA_SIZE + \
> >> +     PHYS_SDRAM_1)
> >> +#define CONFIG_SYS_EARLY_HEAP_SIZE     256
> >> +
> > 
> > 1) Pull this file into separate patch and order it afterwards this patch.
> 
> Already agreed :)
> 
> Regards,
> 
> Graeme

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCHv4] [RFC] DM: early_malloc for DM added.
  2012-09-18 23:33       ` Marek Vasut
@ 2012-09-18 23:44         ` Graeme Russ
  2012-09-18 23:53           ` Marek Vasut
  0 siblings, 1 reply; 48+ messages in thread
From: Graeme Russ @ 2012-09-18 23:44 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On Wed, Sep 19, 2012 at 9:33 AM, Marek Vasut <marex@denx.de> wrote:
> Dear Graeme Russ,
>

[snip]

>> >> +struct early_heap_header *early_brk(size_t size)
>> >> +     __attribute__((weak, alias("def_early_brk")));
>> >
>> > what about using (it needs <linux/compiler.h>):
>> >
>> > __weak struct early_heap_header *early_brk(size_t size)
>> > {
>> > ...
>> > body
>> > ...
>> > }
>>
>> We already have a lot of the former - I prefer not to add additional
>> semantics (unless you want to do a wholesale search/replace ;))
>
> The former looks like shit and the later is more linux-friendly. I'd say stick
> with the later to avoid this insane __attribute__(()) construct.

I agree, but, consistently bad is worse than inconsistently bad :)

I'm look forward to reviewing a cleanup patch ;)

Regards,

Graeme

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCHv4] [RFC] DM: early_malloc for DM added.
  2012-09-18 23:44         ` Graeme Russ
@ 2012-09-18 23:53           ` Marek Vasut
  0 siblings, 0 replies; 48+ messages in thread
From: Marek Vasut @ 2012-09-18 23:53 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,

> Hi Marek,
> 
> On Wed, Sep 19, 2012 at 9:33 AM, Marek Vasut <marex@denx.de> wrote:
> > Dear Graeme Russ,
> 
> [snip]
> 
> >> >> +struct early_heap_header *early_brk(size_t size)
> >> >> +     __attribute__((weak, alias("def_early_brk")));
> >> > 
> >> > what about using (it needs <linux/compiler.h>):
> >> > 
> >> > __weak struct early_heap_header *early_brk(size_t size)
> >> > {
> >> > ...
> >> > body
> >> > ...
> >> > }
> >> 
> >> We already have a lot of the former - I prefer not to add additional
> >> semantics (unless you want to do a wholesale search/replace ;))
> > 
> > The former looks like shit and the later is more linux-friendly. I'd say
> > stick with the later to avoid this insane __attribute__(()) construct.
> 
> I agree, but, consistently bad is worse than inconsistently bad :)

To weed out the old crap, we need linux/compiler.h enabled across whole uboot 
... it's in the todo.

> I'm look forward to reviewing a cleanup patch ;)

Wait until I get it completely built. linux/compiler.h causes breakage on some 
ancient PPC crap.

> Regards,
> 
> Graeme

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCHv4] [RFC] DM: early_malloc for DM added.
  2012-09-18 23:29     ` Graeme Russ
  2012-09-18 23:33       ` Marek Vasut
@ 2012-09-19 18:29       ` Tom Rini
  2012-09-22  0:37       ` Tomas Hlavacek
  2 siblings, 0 replies; 48+ messages in thread
From: Tom Rini @ 2012-09-19 18:29 UTC (permalink / raw)
  To: u-boot

On Wed, Sep 19, 2012 at 09:29:04AM +1000, Graeme Russ wrote:
> Hi Marek,
> 
> On Tue, Sep 18, 2012 at 8:57 PM, Marek Vasut <marex@denx.de> wrote:
> > Dear Tomas Hlavacek,
[snip]
> >> +struct early_heap_header *early_brk(size_t size)
> >> +     __attribute__((weak, alias("def_early_brk")));
> >
> > what about using (it needs <linux/compiler.h>):
> >
> > __weak struct early_heap_header *early_brk(size_t size)
> > {
> > ...
> > body
> > ...
> > }
> 
> We already have a lot of the former - I prefer not to add additional
> semantics (unless you want to do a wholesale search/replace ;))

Migrating everyone but the real tricky uses (alias >=2 functions to one
weak dummy) to the <linux/compiler.h> semantics is something on my TODO
list from ages ago.  So yes please, unless it's a complex case, find and
use the __shortform that <linux/compiler.h> and company provide (and a
git grep for your attribute when in doubt, sometimes it's in
<linux/compiler-gcc.h or so).

And a general I know everyone should know but please, checkpatch.pl your
work before posting.  Getting everyone doing DM series patches to use
patman might be a little bit more overhead (sorry!) but it'll help with
a lot of the little things like formatting and some of the bigger things
like changelog tracking.  Don't have to switch but it might make your
lives easier.

-- 
Tom

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v5] [RFC] early_malloc for DM added.
  2012-08-27 12:12 [U-Boot] [PATCH 1/1] [RFC] DM: early_malloc for DM added Tomas Hlavacek
                   ` (2 preceding siblings ...)
  2012-09-18  7:13 ` [U-Boot] [PATCHv4] " Tomas Hlavacek
@ 2012-09-22  0:25 ` Tomas Hlavacek
  2012-09-22  0:28   ` Marek Vasut
  2012-09-22 22:09 ` [U-Boot] [PATCH v6] " Tomas Hlavacek
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 48+ messages in thread
From: Tomas Hlavacek @ 2012-09-22  0:25 UTC (permalink / raw)
  To: u-boot

early_malloc for DM with support for more heaps and lightweight
first heap in the same memory as an early stack.

Adaptation layer for seamless calling of early_malloc or dlmalloc from
DM based on init stage added (dmmalloc() and related functions).

Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
---
 arch/arm/include/asm/global_data.h        |    3 +
 arch/arm/lib/board.c                      |    8 ++
 arch/avr32/include/asm/global_data.h      |    3 +
 arch/avr32/lib/board.c                    |    9 ++
 arch/blackfin/include/asm/global_data.h   |    3 +
 arch/blackfin/lib/board.c                 |    8 ++
 arch/m68k/include/asm/global_data.h       |    3 +
 arch/m68k/lib/board.c                     |    8 ++
 arch/microblaze/include/asm/global_data.h |    3 +
 arch/microblaze/lib/board.c               |    9 ++
 arch/mips/include/asm/global_data.h       |    3 +
 arch/mips/lib/board.c                     |    8 ++
 arch/nds32/include/asm/global_data.h      |    3 +
 arch/nds32/lib/board.c                    |    8 ++
 arch/nios2/include/asm/global_data.h      |    3 +
 arch/nios2/lib/board.c                    |    8 ++
 arch/openrisc/include/asm/global_data.h   |    3 +
 arch/openrisc/lib/board.c                 |    8 ++
 arch/powerpc/include/asm/global_data.h    |    3 +
 arch/powerpc/lib/board.c                  |    8 ++
 arch/sandbox/include/asm/global_data.h    |    3 +
 arch/sandbox/lib/board.c                  |    8 ++
 arch/sh/include/asm/global_data.h         |    3 +
 arch/sh/lib/board.c                       |    8 ++
 arch/sparc/include/asm/global_data.h      |    3 +
 arch/sparc/lib/board.c                    |    8 ++
 arch/x86/include/asm/global_data.h        |    3 +
 arch/x86/lib/board.c                      |   18 ++++
 common/Makefile                           |    1 +
 common/dmmalloc.c                         |  140 +++++++++++++++++++++++++++++
 include/dmmalloc.h                        |   56 ++++++++++++
 31 files changed, 363 insertions(+)
 create mode 100644 common/dmmalloc.c
 create mode 100644 include/dmmalloc.h

diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index f8088fe..ef727b0 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -82,6 +82,9 @@ typedef	struct	global_data {
 	unsigned long	post_log_res; /* success of POST test */
 	unsigned long	post_init_f_time; /* When post_init_f started */
 #endif
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
index f1951e8..2157a5d 100644
--- a/arch/arm/lib/board.c
+++ b/arch/arm/lib/board.c
@@ -53,6 +53,10 @@
 #include <post.h>
 #include <logbuff.h>
 
+#ifdef CONFIG_SYS_DM
+#include <dmmalloc.h>
+#endif
+
 #ifdef CONFIG_BITBANGMII
 #include <miiphy.h>
 #endif
@@ -281,6 +285,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->mon_len = _bss_end_ofs;
 #ifdef CONFIG_OF_EMBED
 	/* Get a pointer to the FDT */
diff --git a/arch/avr32/include/asm/global_data.h b/arch/avr32/include/asm/global_data.h
index 7878bb1..0654a61 100644
--- a/arch/avr32/include/asm/global_data.h
+++ b/arch/avr32/include/asm/global_data.h
@@ -48,6 +48,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/avr32/lib/board.c b/arch/avr32/lib/board.c
index d7a64b4..14ec278 100644
--- a/arch/avr32/lib/board.c
+++ b/arch/avr32/lib/board.c
@@ -42,6 +42,11 @@
 #ifdef CONFIG_GENERIC_ATMEL_MCI
 #include <mmc.h>
 #endif
+
+#ifdef CONFIG_SYS_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 unsigned long monitor_flash_len;
@@ -161,6 +166,10 @@ void board_init_f(ulong board_type)
 	memset(&gd_data, 0, sizeof(gd_data));
 	gd = &gd_data;
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	/* Perform initialization sequence */
 	board_early_init_f();
 	cpu_init();
diff --git a/arch/blackfin/include/asm/global_data.h b/arch/blackfin/include/asm/global_data.h
index 290a9e7..2ae395c 100644
--- a/arch/blackfin/include/asm/global_data.h
+++ b/arch/blackfin/include/asm/global_data.h
@@ -57,6 +57,9 @@ typedef struct global_data {
 
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c
index c380d27..bb19bdd 100644
--- a/arch/blackfin/lib/board.c
+++ b/arch/blackfin/lib/board.c
@@ -37,6 +37,10 @@
 int post_flag;
 #endif
 
+#ifdef CONFIG_SYS_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 __attribute__((always_inline))
@@ -267,6 +271,10 @@ void board_init_f(ulong bootflag)
 	watchdog_init();
 #endif
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 #ifdef DEBUG
 	if (GENERATED_GBL_DATA_SIZE < sizeof(*gd))
 		hang();
diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h
index cd55b83..bd30435 100644
--- a/arch/m68k/include/asm/global_data.h
+++ b/arch/m68k/include/asm/global_data.h
@@ -66,6 +66,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/m68k/lib/board.c b/arch/m68k/lib/board.c
index 65a8595..8815605 100644
--- a/arch/m68k/lib/board.c
+++ b/arch/m68k/lib/board.c
@@ -69,6 +69,10 @@
 
 #include <nand.h>
 
+#ifdef CONFIG_SYS_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static char *failed = "*** failed ***\n";
@@ -227,6 +231,10 @@ board_init_f (ulong bootflag)
 	/* Clear initial global data */
 	memset ((void *) gd, 0, sizeof (gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0) {
 			hang ();
diff --git a/arch/microblaze/include/asm/global_data.h b/arch/microblaze/include/asm/global_data.h
index de3b8db..6f4066d 100644
--- a/arch/microblaze/include/asm/global_data.h
+++ b/arch/microblaze/include/asm/global_data.h
@@ -46,6 +46,9 @@ typedef	struct	global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c
index 674b573..869a3ea 100644
--- a/arch/microblaze/lib/board.c
+++ b/arch/microblaze/lib/board.c
@@ -37,6 +37,10 @@
 #include <asm/microblaze_intc.h>
 #include <fdtdec.h>
 
+#ifdef CONFIG_SYS_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
@@ -81,6 +85,11 @@ void board_init_f(ulong not_used)
 	asm ("nop");	/* FIXME gd is not initialize - wait */
 	memset ((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 	memset ((void *)bd, 0, GENERATED_BD_INFO_SIZE);
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = bd;
 	gd->baudrate = CONFIG_BAUDRATE;
 	bd->bi_baudrate = CONFIG_BAUDRATE;
diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h
index 6e2cdc7..ac24e3f 100644
--- a/arch/mips/include/asm/global_data.h
+++ b/arch/mips/include/asm/global_data.h
@@ -59,6 +59,9 @@ typedef	struct	global_data {
 	unsigned long	env_valid;	/* Checksum of Environment valid? */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/mips/lib/board.c b/arch/mips/lib/board.c
index 62d47a8..d9ae49f 100644
--- a/arch/mips/lib/board.c
+++ b/arch/mips/lib/board.c
@@ -36,6 +36,10 @@
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_SYS_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
@@ -153,6 +157,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0)
 			hang();
diff --git a/arch/nds32/include/asm/global_data.h b/arch/nds32/include/asm/global_data.h
index 94bd4c2..d0e2606 100644
--- a/arch/nds32/include/asm/global_data.h
+++ b/arch/nds32/include/asm/global_data.h
@@ -63,6 +63,9 @@ typedef	struct global_data {
 
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/nds32/lib/board.c b/arch/nds32/lib/board.c
index 2164a50..9c9be4e 100644
--- a/arch/nds32/lib/board.c
+++ b/arch/nds32/lib/board.c
@@ -37,6 +37,10 @@
 #include <onenand_uboot.h>
 #include <mmc.h>
 
+#ifdef CONFIG_SYS_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
@@ -192,6 +196,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->mon_len = (unsigned int)(&__bss_end__) - (unsigned int)(&_start);
 
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
diff --git a/arch/nios2/include/asm/global_data.h b/arch/nios2/include/asm/global_data.h
index 3b0d9e6..44373f4 100644
--- a/arch/nios2/include/asm/global_data.h
+++ b/arch/nios2/include/asm/global_data.h
@@ -42,6 +42,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/nios2/lib/board.c b/arch/nios2/lib/board.c
index 1e495d4..96d3827 100644
--- a/arch/nios2/lib/board.c
+++ b/arch/nios2/lib/board.c
@@ -40,6 +40,10 @@
 #include <nand.h>	/* cannot even include nand.h if it isnt configured */
 #endif
 
+#ifdef CONFIG_SYS_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
@@ -95,6 +99,10 @@ void board_init (void)
 	/* compiler optimization barrier needed for GCC >= 3.4 */
 	__asm__ __volatile__("": : :"memory");
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = &bd_data;
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/openrisc/include/asm/global_data.h b/arch/openrisc/include/asm/global_data.h
index 6a0c0cc..ec2220a 100644
--- a/arch/openrisc/include/asm/global_data.h
+++ b/arch/openrisc/include/asm/global_data.h
@@ -44,6 +44,9 @@ typedef struct global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/openrisc/lib/board.c b/arch/openrisc/lib/board.c
index 85aa189..527de09 100644
--- a/arch/openrisc/lib/board.c
+++ b/arch/openrisc/lib/board.c
@@ -44,6 +44,10 @@
 #include <timestamp.h>
 #include <version.h>
 
+#ifdef CONFIG_SYS_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
@@ -86,6 +90,10 @@ void board_init(void)
 
 	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = (bd_t *)(gd+1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h
index 5a5877f..38b63f9 100644
--- a/arch/powerpc/include/asm/global_data.h
+++ b/arch/powerpc/include/asm/global_data.h
@@ -182,6 +182,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
index fea310e..dbf0520 100644
--- a/arch/powerpc/lib/board.c
+++ b/arch/powerpc/lib/board.c
@@ -87,6 +87,10 @@
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_SYS_DM
+#include <dmmalloc.h>
+#endif
+
 #ifdef CONFIG_SYS_UPDATE_FLASH_SIZE
 extern int update_flash_size(int flash_size);
 #endif
@@ -389,6 +393,10 @@ void board_init_f(ulong bootflag)
 	memset((void *) gd, 0, sizeof(gd_t));
 #endif
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)
 		if ((*init_fnc_ptr) () != 0)
 			hang();
diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h
index 581fd2f..00c7c10 100644
--- a/arch/sandbox/include/asm/global_data.h
+++ b/arch/sandbox/include/asm/global_data.h
@@ -46,6 +46,9 @@ typedef	struct global_data {
 	const void	*fdt_blob;	/* Our device tree, NULL if none */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sandbox/lib/board.c b/arch/sandbox/lib/board.c
index c173bf9..da4e3ea 100644
--- a/arch/sandbox/lib/board.c
+++ b/arch/sandbox/lib/board.c
@@ -47,6 +47,10 @@
 
 #include <os.h>
 
+#ifdef CONFIG_SYS_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static gd_t gd_mem;
@@ -157,6 +161,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 #if defined(CONFIG_OF_EMBED)
 	/* Get a pointer to the FDT */
 	gd->fdt_blob = _binary_dt_dtb_start;
diff --git a/arch/sh/include/asm/global_data.h b/arch/sh/include/asm/global_data.h
index 6e534ad..441fecd 100644
--- a/arch/sh/include/asm/global_data.h
+++ b/arch/sh/include/asm/global_data.h
@@ -42,6 +42,9 @@ typedef	struct global_data
 	unsigned long	env_valid;	/* Checksum of Environment valid */
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sh/lib/board.c b/arch/sh/lib/board.c
index 34d7881..2cf94d3 100644
--- a/arch/sh/lib/board.c
+++ b/arch/sh/lib/board.c
@@ -32,6 +32,10 @@
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_SYS_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 extern int cpu_init(void);
@@ -150,6 +154,10 @@ void sh_generic_init(void)
 
 	memset(gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
 
 	gd->bd = (bd_t *)(gd + 1);	/* At end of global data */
diff --git a/arch/sparc/include/asm/global_data.h b/arch/sparc/include/asm/global_data.h
index 93d3cc0..537e09a 100644
--- a/arch/sparc/include/asm/global_data.h
+++ b/arch/sparc/include/asm/global_data.h
@@ -74,6 +74,9 @@ typedef struct global_data {
 #endif
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sparc/lib/board.c b/arch/sparc/lib/board.c
index 6f33666..5a45d7c 100644
--- a/arch/sparc/lib/board.c
+++ b/arch/sparc/lib/board.c
@@ -53,6 +53,10 @@
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_SYS_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* Debug options
@@ -178,6 +182,10 @@ void board_init_f(ulong bootflag)
 	/* Clear initial global data */
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = (bd_t *) (gd + 1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 6d29c0b..920a805 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -57,6 +57,9 @@ typedef	struct global_data {
 	unsigned long	reset_status;	/* reset status register at boot */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 static inline gd_t *get_fs_gd_ptr(void)
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
index 90cf7fc..e21c9af 100644
--- a/arch/x86/lib/board.c
+++ b/arch/x86/lib/board.c
@@ -40,6 +40,10 @@
 #include <asm/init_helpers.h>
 #include <asm/init_wrappers.h>
 
+#ifdef CONFIG_SYS_DM
+#include <dmmalloc.h>
+#endif
+
 /*
  * Breath some life into the board...
  *
@@ -85,6 +89,17 @@
 typedef int (init_fnc_t) (void);
 
 /*
+ * Initialize early heap (when enabled by config).
+ */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+static void early_malloc_init(void)
+{
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+}
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+
+/*
  * init_sequence_f is the list of init functions which are run when U-Boot
  * is executing from Flash with a limited 'C' environment. The following
  * limitations must be considered when implementing an '_f' function:
@@ -99,6 +114,9 @@ init_fnc_t *init_sequence_f[] = {
 	cpu_init_f,
 	board_early_init_f,
 	env_init,
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	early_malloc_init,
+#endif /* CONFIG_SYS_EARLY_MALLOC */
 	init_baudrate_f,
 	serial_init,
 	console_init_f,
diff --git a/common/Makefile b/common/Makefile
index 22e8a6f..e0bea58 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -201,6 +201,7 @@ COBJS-y += dlmalloc.o
 COBJS-y += image.o
 COBJS-y += memsize.o
 COBJS-y += stdio.o
+COBJS-$(CONFIG_SYS_DM) += dmmalloc.o
 
 
 COBJS	:= $(sort $(COBJS-y))
diff --git a/common/dmmalloc.c b/common/dmmalloc.c
new file mode 100644
index 0000000..b5957f4
--- /dev/null
+++ b/common/dmmalloc.c
@@ -0,0 +1,140 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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 <common.h> /* for ROUND_UP */
+#include <asm/u-boot.h>
+#include <asm/global_data.h> /* for gd_t and gd */
+#include <asm/types.h> /* for phys_addr_t and size_addt_t */
+
+#include <dmmalloc.h>
+#include <malloc.h>
+
+#include <linux/compiler.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+__weak struct early_heap_header *early_brk(size_t size)
+{
+	struct early_heap_header *h =
+		(struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
+	struct early_heap_header *ehp = gd->early_heap_first;
+
+	while (ehp != NULL) {
+		if (ehp == h)
+			return NULL;
+
+		ehp = ehp->next_early_heap;
+	}
+
+	h->free_space_pointer = (void *)(roundup(
+				(phys_addr_t)CONFIG_SYS_EARLY_HEAP_ADDR +
+				sizeof(struct early_heap_header),
+				sizeof(phys_addr_t)));
+	h->free_bytes = size - roundup(sizeof(struct early_heap_header),
+				sizeof(phys_addr_t));
+	h->next_early_heap = NULL;
+
+	return h;
+}
+
+void *early_malloc(size_t size)
+{
+	phys_addr_t addr;
+	struct early_heap_header *h;
+
+	size = roundup(size, sizeof(phys_addr_t));
+
+	h = gd->early_heap_first;
+	while ((h->free_bytes < size) && (h->next_early_heap != NULL))
+		h = h->next_early_heap;
+
+	if (h->free_bytes < size) {
+		h->next_early_heap = early_brk(size);
+		if (h->next_early_heap == NULL)
+			debug("EH overflow. Can not early_brk. required %d B.",
+			size);
+		return NULL;
+	}
+
+	addr = (phys_addr_t)h->free_space_pointer;
+
+	h->free_space_pointer += size;
+	h->free_bytes -= size;
+
+	return (void *)addr;
+}
+
+static int early_malloc_active(void)
+{
+	if ((gd->flags & GD_FLG_RELOC) == GD_FLG_RELOC)
+		return 0;
+
+	return 1;
+}
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+void *dmmalloc(size_t size)
+{
+	if (early_malloc_active())
+		return early_malloc(size);
+	return malloc(size);
+}
+#else /* CONFIG_SYS_EARLY_MALLOC */
+#define dmmalloc malloc
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+void dmfree(void *ptr)
+{
+	if (early_malloc_active())
+		return;
+	free(ptr);
+}
+#else /* CONFIG_SYS_EARLY_MALLOC */
+#define dmfree free
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+void *dmcalloc(size_t n, size_t elem_size)
+{
+	if (early_malloc_active())
+		return NULL;
+	return calloc(n, elem_size);
+}
+#else /* CONFIG_SYS_EARLY_MALLOC */
+#define dmcalloc calloc
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+void *dmrealloc(void *oldmem, size_t bytes)
+{
+	if (early_malloc_active())
+		return NULL;
+	return dmrealloc(oldmem, bytes);
+}
+#else /* CONFIG_SYS_EARLY_MALLOC */
+#define dmrealloc realloc
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
diff --git a/include/dmmalloc.h b/include/dmmalloc.h
new file mode 100644
index 0000000..726c6c9
--- /dev/null
+++ b/include/dmmalloc.h
@@ -0,0 +1,56 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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
+ */
+
+#ifndef __INCLUDE_DMMALLOC_H
+#define __INCLUDE_DMMALLOC_H
+
+#include <config.h>
+#include <linux/stddef.h> /* for size_t */
+
+#if (!defined(CONFIG_SYS_EARLY_HEAP_ADDR)) || \
+	(!defined(CONFIG_SYS_EARLY_HEAP_SIZE))
+#undef CONFIG_SYS_EARLY_MALLOC
+#endif /* CONFIG_SYS_EARLY_HEAP_ADDR */
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+struct early_heap_header {
+	void *free_space_pointer;
+	size_t free_bytes;
+	void *next_early_heap;
+};
+
+struct early_heap_header *early_brk(size_t size);
+void *early_malloc(size_t size);
+
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+#ifdef CONFIG_SYS_DM
+void *dmmalloc(size_t size);
+void dmfree(void *ptr);
+void *dmcalloc(size_t n, size_t elem_size);
+void *dmrealloc(void *oldmem, size_t bytes);
+#endif /* CONFIG_SYS_DM */
+
+
+#endif /* __INCLUDE_DMMALLOC_H */
+
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v5] [RFC] early_malloc for DM added.
  2012-09-22  0:25 ` [U-Boot] [PATCH v5] [RFC] " Tomas Hlavacek
@ 2012-09-22  0:28   ` Marek Vasut
  2012-09-22  7:52     ` Tomas Hlavacek
  0 siblings, 1 reply; 48+ messages in thread
From: Marek Vasut @ 2012-09-22  0:28 UTC (permalink / raw)
  To: u-boot

Dear Tomas Hlavacek,

> early_malloc for DM with support for more heaps and lightweight
> first heap in the same memory as an early stack.
> 
> Adaptation layer for seamless calling of early_malloc or dlmalloc from
> DM based on init stage added (dmmalloc() and related functions).
> 
> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
[...]
>  31 files changed, 363 insertions(+)
>  create mode 100644 common/dmmalloc.c
>  create mode 100644 include/dmmalloc.h

What exactly changed in this version? Changelog is missing.

[...]

> +static int early_malloc_active(void)
> +{
> +	if ((gd->flags & GD_FLG_RELOC) == GD_FLG_RELOC)
> +		return 0;

Did you completely ignore the comments?

> +	return 1;
> +}
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +void *dmmalloc(size_t size)
> +{
> +	if (early_malloc_active())
> +		return early_malloc(size);
> +	return malloc(size);
> +}
> +#else /* CONFIG_SYS_EARLY_MALLOC */
> +#define dmmalloc malloc

How is this actually supposed to work?

> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +void dmfree(void *ptr)
> +{
> +	if (early_malloc_active())
> +		return;
> +	free(ptr);
> +}
> +#else /* CONFIG_SYS_EARLY_MALLOC */
> +#define dmfree free
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +void *dmcalloc(size_t n, size_t elem_size)
> +{
> +	if (early_malloc_active())
> +		return NULL;
> +	return calloc(n, elem_size);
> +}
> +#else /* CONFIG_SYS_EARLY_MALLOC */
> +#define dmcalloc calloc
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +void *dmrealloc(void *oldmem, size_t bytes)
> +{
> +	if (early_malloc_active())
> +		return NULL;
> +	return dmrealloc(oldmem, bytes);
> +}
> +#else /* CONFIG_SYS_EARLY_MALLOC */
> +#define dmrealloc realloc
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
> diff --git a/include/dmmalloc.h b/include/dmmalloc.h
> new file mode 100644
> index 0000000..726c6c9
> --- /dev/null
> +++ b/include/dmmalloc.h
> @@ -0,0 +1,56 @@
> +/*
> + * (C) Copyright 2012
> + * Tomas Hlavacek (tmshlvck at gmail.com)
> + *
> + * 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
> + */
> +
> +#ifndef __INCLUDE_DMMALLOC_H
> +#define __INCLUDE_DMMALLOC_H
> +
> +#include <config.h>
> +#include <linux/stddef.h> /* for size_t */
> +
> +#if (!defined(CONFIG_SYS_EARLY_HEAP_ADDR)) || \
> +	(!defined(CONFIG_SYS_EARLY_HEAP_SIZE))
> +#undef CONFIG_SYS_EARLY_MALLOC
> +#endif /* CONFIG_SYS_EARLY_HEAP_ADDR */
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +struct early_heap_header {
> +	void *free_space_pointer;
> +	size_t free_bytes;
> +	void *next_early_heap;
> +};
> +
> +struct early_heap_header *early_brk(size_t size);
> +void *early_malloc(size_t size);
> +
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
> +#ifdef CONFIG_SYS_DM

Isn't it CONFIG_DM ?

> +void *dmmalloc(size_t size);
> +void dmfree(void *ptr);
> +void *dmcalloc(size_t n, size_t elem_size);
> +void *dmrealloc(void *oldmem, size_t bytes);
> +#endif /* CONFIG_SYS_DM */
> +
> +
> +#endif /* __INCLUDE_DMMALLOC_H */
> +

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCHv4] [RFC] DM: early_malloc for DM added.
  2012-09-18 23:29     ` Graeme Russ
  2012-09-18 23:33       ` Marek Vasut
  2012-09-19 18:29       ` Tom Rini
@ 2012-09-22  0:37       ` Tomas Hlavacek
  2 siblings, 0 replies; 48+ messages in thread
From: Tomas Hlavacek @ 2012-09-22  0:37 UTC (permalink / raw)
  To: u-boot

Hello all,

I have sent a new version. Although I tried to take into account all
the opinions and comments I might have missed something.

On Wed, Sep 19, 2012 at 1:29 AM, Graeme Russ <graeme.russ@gmail.com> wrote:
>>
>> I'd say, pull out the modification of global data into separate patch and put it
>> before this patch. That'd make review of the core code much easier.
>
> NAK - The addition of the global data member is intrinsic to the early
> malloc implmentaion. Keep them together

Yes, I think that in this case one does not make sense with the other.
I kept them rather together.

>
>>> +
>>> +struct early_heap_header *early_brk(size_t size)
>>> +     __attribute__((weak, alias("def_early_brk")));
>>
>> what about using (it needs <linux/compiler.h>):
>>
>> __weak struct early_heap_header *early_brk(size_t size)
>> {
>> ...
>> body
>> ...
>> }
>
> We already have a lot of the former - I prefer not to add additional
> semantics (unless you want to do a wholesale search/replace ;))

This time I used the shorter / newer variant. Hope this would be better.

Tomas

-- 
Tom?? Hlav??ek <tmshlvck@gmail.com>

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v5] [RFC] early_malloc for DM added.
  2012-09-22  0:28   ` Marek Vasut
@ 2012-09-22  7:52     ` Tomas Hlavacek
  2012-09-22 13:19       ` Marek Vasut
  0 siblings, 1 reply; 48+ messages in thread
From: Tomas Hlavacek @ 2012-09-22  7:52 UTC (permalink / raw)
  To: u-boot

Hello Marek,

On Sat, Sep 22, 2012 at 2:28 AM, Marek Vasut <marex@denx.de> wrote:
> Dear Tomas Hlavacek,
>
>> early_malloc for DM with support for more heaps and lightweight
>> first heap in the same memory as an early stack.
>>
>> Adaptation layer for seamless calling of early_malloc or dlmalloc from
>> DM based on init stage added (dmmalloc() and related functions).
>>
>> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
> [...]
>>  31 files changed, 363 insertions(+)
>>  create mode 100644 common/dmmalloc.c
>>  create mode 100644 include/dmmalloc.h
>
> What exactly changed in this version? Changelog is missing.

Preprocessor config-dependent (ifdef ... endif) blocks are different.
early_brk call from early_malloc when the heaps are full.
default early_brk checks existing heap for before setting.

>
> [...]
>
>> +static int early_malloc_active(void)
>> +{
>> +     if ((gd->flags & GD_FLG_RELOC) == GD_FLG_RELOC)
>> +             return 0;
>
> Did you completely ignore the comments?

Yes, this is ugly and I did not notice the point of (your?) comment
while reworking this tiny part again and again... Sorry.

>
>> +     return 1;
>> +}
>> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>> +
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> +void *dmmalloc(size_t size)
>> +{
>> +     if (early_malloc_active())
>> +             return early_malloc(size);
>> +     return malloc(size);
>> +}
>> +#else /* CONFIG_SYS_EARLY_MALLOC */
>> +#define dmmalloc malloc
>
> How is this actually supposed to work?

Of course, this have to be in the header file dmmalloc.h. Just ignore
the #else ... #endif part.

>
>> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>> +
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> +void dmfree(void *ptr)
>> +{
>> +     if (early_malloc_active())
>> +             return;
>> +     free(ptr);
>> +}
>> +#else /* CONFIG_SYS_EARLY_MALLOC */
>> +#define dmfree free
>> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>> +
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> +void *dmcalloc(size_t n, size_t elem_size)
>> +{
>> +     if (early_malloc_active())
>> +             return NULL;
>> +     return calloc(n, elem_size);
>> +}
>> +#else /* CONFIG_SYS_EARLY_MALLOC */
>> +#define dmcalloc calloc
>> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>> +
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> +void *dmrealloc(void *oldmem, size_t bytes)
>> +{
>> +     if (early_malloc_active())
>> +             return NULL;
>> +     return dmrealloc(oldmem, bytes);
>> +}
>> +#else /* CONFIG_SYS_EARLY_MALLOC */
>> +#define dmrealloc realloc
>> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>> +
>> diff --git a/include/dmmalloc.h b/include/dmmalloc.h
>> new file mode 100644
>> index 0000000..726c6c9
>> --- /dev/null
>> +++ b/include/dmmalloc.h
>> @@ -0,0 +1,56 @@
>> +/*
>> + * (C) Copyright 2012
>> + * Tomas Hlavacek (tmshlvck at gmail.com)
>> + *
>> + * 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
>> + */
>> +
>> +#ifndef __INCLUDE_DMMALLOC_H
>> +#define __INCLUDE_DMMALLOC_H
>> +
>> +#include <config.h>
>> +#include <linux/stddef.h> /* for size_t */
>> +
>> +#if (!defined(CONFIG_SYS_EARLY_HEAP_ADDR)) || \
>> +     (!defined(CONFIG_SYS_EARLY_HEAP_SIZE))
>> +#undef CONFIG_SYS_EARLY_MALLOC
>> +#endif /* CONFIG_SYS_EARLY_HEAP_ADDR */
>> +
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> +struct early_heap_header {
>> +     void *free_space_pointer;
>> +     size_t free_bytes;
>> +     void *next_early_heap;
>> +};
>> +
>> +struct early_heap_header *early_brk(size_t size);
>> +void *early_malloc(size_t size);
>> +
>> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>> +
>> +#ifdef CONFIG_SYS_DM
>
> Isn't it CONFIG_DM ?

I will change that. (Is it consistent with the naming convention? I
mean: What the "_SYS_" exactly means?)

Tomas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v5] [RFC] early_malloc for DM added.
  2012-09-22  7:52     ` Tomas Hlavacek
@ 2012-09-22 13:19       ` Marek Vasut
  0 siblings, 0 replies; 48+ messages in thread
From: Marek Vasut @ 2012-09-22 13:19 UTC (permalink / raw)
  To: u-boot

Dear Tomas Hlavacek,

> Hello Marek,
> 
> On Sat, Sep 22, 2012 at 2:28 AM, Marek Vasut <marex@denx.de> wrote:
> > Dear Tomas Hlavacek,
> > 
> >> early_malloc for DM with support for more heaps and lightweight
> >> first heap in the same memory as an early stack.
> >> 
> >> Adaptation layer for seamless calling of early_malloc or dlmalloc from
> >> DM based on init stage added (dmmalloc() and related functions).
> >> 
> >> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
> > 
> > [...]
> > 
> >>  31 files changed, 363 insertions(+)
> >>  create mode 100644 common/dmmalloc.c
> >>  create mode 100644 include/dmmalloc.h
> > 
> > What exactly changed in this version? Changelog is missing.
> 
> Preprocessor config-dependent (ifdef ... endif) blocks are different.
> early_brk call from early_malloc when the heaps are full.
> default early_brk checks existing heap for before setting.
> 
> > [...]
> > 
> >> +static int early_malloc_active(void)
> >> +{
> >> +     if ((gd->flags & GD_FLG_RELOC) == GD_FLG_RELOC)
> >> +             return 0;
> > 
> > Did you completely ignore the comments?
> 
> Yes, this is ugly and I did not notice the point of (your?) comment
> while reworking this tiny part again and again... Sorry.

I think it was GR.

> >> +     return 1;
> >> +}
> >> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> >> +
> >> +#ifdef CONFIG_SYS_EARLY_MALLOC
> >> +void *dmmalloc(size_t size)
> >> +{
> >> +     if (early_malloc_active())
> >> +             return early_malloc(size);
> >> +     return malloc(size);
> >> +}
> >> +#else /* CONFIG_SYS_EARLY_MALLOC */
> >> +#define dmmalloc malloc
> > 
> > How is this actually supposed to work?
> 
> Of course, this have to be in the header file dmmalloc.h. Just ignore
> the #else ... #endif part.

That won't work well either ... I'd say make the wrapper static inline for 
typechecking, no ?

> >> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> >> +
> >> +#ifdef CONFIG_SYS_EARLY_MALLOC
> >> +void dmfree(void *ptr)
> >> +{
> >> +     if (early_malloc_active())
> >> +             return;
> >> +     free(ptr);
> >> +}
> >> +#else /* CONFIG_SYS_EARLY_MALLOC */
> >> +#define dmfree free
> >> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> >> +
> >> +#ifdef CONFIG_SYS_EARLY_MALLOC
> >> +void *dmcalloc(size_t n, size_t elem_size)
> >> +{
> >> +     if (early_malloc_active())
> >> +             return NULL;
> >> +     return calloc(n, elem_size);
> >> +}
> >> +#else /* CONFIG_SYS_EARLY_MALLOC */
> >> +#define dmcalloc calloc
> >> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> >> +
> >> +#ifdef CONFIG_SYS_EARLY_MALLOC
> >> +void *dmrealloc(void *oldmem, size_t bytes)
> >> +{
> >> +     if (early_malloc_active())
> >> +             return NULL;
> >> +     return dmrealloc(oldmem, bytes);
> >> +}
> >> +#else /* CONFIG_SYS_EARLY_MALLOC */
> >> +#define dmrealloc realloc
> >> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> >> +
> >> diff --git a/include/dmmalloc.h b/include/dmmalloc.h
> >> new file mode 100644
> >> index 0000000..726c6c9
> >> --- /dev/null
> >> +++ b/include/dmmalloc.h
> >> @@ -0,0 +1,56 @@
> >> +/*
> >> + * (C) Copyright 2012
> >> + * Tomas Hlavacek (tmshlvck at gmail.com)
> >> + *
> >> + * 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
> >> + */
> >> +
> >> +#ifndef __INCLUDE_DMMALLOC_H
> >> +#define __INCLUDE_DMMALLOC_H
> >> +
> >> +#include <config.h>
> >> +#include <linux/stddef.h> /* for size_t */
> >> +
> >> +#if (!defined(CONFIG_SYS_EARLY_HEAP_ADDR)) || \
> >> +     (!defined(CONFIG_SYS_EARLY_HEAP_SIZE))
> >> +#undef CONFIG_SYS_EARLY_MALLOC
> >> +#endif /* CONFIG_SYS_EARLY_HEAP_ADDR */
> >> +
> >> +#ifdef CONFIG_SYS_EARLY_MALLOC
> >> +struct early_heap_header {
> >> +     void *free_space_pointer;
> >> +     size_t free_bytes;
> >> +     void *next_early_heap;
> >> +};
> >> +
> >> +struct early_heap_header *early_brk(size_t size);
> >> +void *early_malloc(size_t size);
> >> +
> >> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> >> +
> >> +#ifdef CONFIG_SYS_DM
> > 
> > Isn't it CONFIG_DM ?
> 
> I will change that. (Is it consistent with the naming convention? I
> mean: What the "_SYS_" exactly means?)
> 
> Tomas

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v6] [RFC] early_malloc for DM added.
  2012-08-27 12:12 [U-Boot] [PATCH 1/1] [RFC] DM: early_malloc for DM added Tomas Hlavacek
                   ` (3 preceding siblings ...)
  2012-09-22  0:25 ` [U-Boot] [PATCH v5] [RFC] " Tomas Hlavacek
@ 2012-09-22 22:09 ` Tomas Hlavacek
  2012-09-23 13:06   ` Graeme Russ
  2012-09-23 15:38 ` [U-Boot] [PATCH v7] " Tomas Hlavacek
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 48+ messages in thread
From: Tomas Hlavacek @ 2012-09-22 22:09 UTC (permalink / raw)
  To: u-boot

early_malloc for DM with support for more heaps and lightweight
first heap in the same memory as an early stack.

Adaptation layer for seamless calling of early_malloc or dlmalloc from
DM based on init stage added (dmmalloc() and related functions).

Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
---

Changelog since v5:
dmmalloc() and all dm* functions has been moved to header, made static
inline and preprocessor-dependent blocks are reworked.
early_malloc_active() corrected and made not static.
s/CONFIG_SYS_DM/CONFIG_DM/ applied.

 arch/arm/include/asm/global_data.h        |    3 +
 arch/arm/lib/board.c                      |    8 +++
 arch/avr32/include/asm/global_data.h      |    3 +
 arch/avr32/lib/board.c                    |    9 +++
 arch/blackfin/include/asm/global_data.h   |    3 +
 arch/blackfin/lib/board.c                 |    8 +++
 arch/m68k/include/asm/global_data.h       |    3 +
 arch/m68k/lib/board.c                     |    8 +++
 arch/microblaze/include/asm/global_data.h |    3 +
 arch/microblaze/lib/board.c               |    9 +++
 arch/mips/include/asm/global_data.h       |    3 +
 arch/mips/lib/board.c                     |    8 +++
 arch/nds32/include/asm/global_data.h      |    3 +
 arch/nds32/lib/board.c                    |    8 +++
 arch/nios2/include/asm/global_data.h      |    3 +
 arch/nios2/lib/board.c                    |    8 +++
 arch/openrisc/include/asm/global_data.h   |    3 +
 arch/openrisc/lib/board.c                 |    8 +++
 arch/powerpc/include/asm/global_data.h    |    3 +
 arch/powerpc/lib/board.c                  |    8 +++
 arch/sandbox/include/asm/global_data.h    |    3 +
 arch/sandbox/lib/board.c                  |    8 +++
 arch/sh/include/asm/global_data.h         |    3 +
 arch/sh/lib/board.c                       |    8 +++
 arch/sparc/include/asm/global_data.h      |    3 +
 arch/sparc/lib/board.c                    |    8 +++
 arch/x86/include/asm/global_data.h        |    3 +
 arch/x86/lib/board.c                      |   18 ++++++
 common/Makefile                           |    1 +
 common/dmmalloc.c                         |   93 +++++++++++++++++++++++++++++
 include/dmmalloc.h                        |   89 +++++++++++++++++++++++++++
 31 files changed, 349 insertions(+)
 create mode 100644 common/dmmalloc.c
 create mode 100644 include/dmmalloc.h

diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index f8088fe..ef727b0 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -82,6 +82,9 @@ typedef	struct	global_data {
 	unsigned long	post_log_res; /* success of POST test */
 	unsigned long	post_init_f_time; /* When post_init_f started */
 #endif
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
index f1951e8..f73d8b2 100644
--- a/arch/arm/lib/board.c
+++ b/arch/arm/lib/board.c
@@ -53,6 +53,10 @@
 #include <post.h>
 #include <logbuff.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 #ifdef CONFIG_BITBANGMII
 #include <miiphy.h>
 #endif
@@ -281,6 +285,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->mon_len = _bss_end_ofs;
 #ifdef CONFIG_OF_EMBED
 	/* Get a pointer to the FDT */
diff --git a/arch/avr32/include/asm/global_data.h b/arch/avr32/include/asm/global_data.h
index 7878bb1..0654a61 100644
--- a/arch/avr32/include/asm/global_data.h
+++ b/arch/avr32/include/asm/global_data.h
@@ -48,6 +48,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/avr32/lib/board.c b/arch/avr32/lib/board.c
index d7a64b4..f1bd946 100644
--- a/arch/avr32/lib/board.c
+++ b/arch/avr32/lib/board.c
@@ -42,6 +42,11 @@
 #ifdef CONFIG_GENERIC_ATMEL_MCI
 #include <mmc.h>
 #endif
+
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 unsigned long monitor_flash_len;
@@ -161,6 +166,10 @@ void board_init_f(ulong board_type)
 	memset(&gd_data, 0, sizeof(gd_data));
 	gd = &gd_data;
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	/* Perform initialization sequence */
 	board_early_init_f();
 	cpu_init();
diff --git a/arch/blackfin/include/asm/global_data.h b/arch/blackfin/include/asm/global_data.h
index 290a9e7..2ae395c 100644
--- a/arch/blackfin/include/asm/global_data.h
+++ b/arch/blackfin/include/asm/global_data.h
@@ -57,6 +57,9 @@ typedef struct global_data {
 
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c
index c380d27..96b7d76 100644
--- a/arch/blackfin/lib/board.c
+++ b/arch/blackfin/lib/board.c
@@ -37,6 +37,10 @@
 int post_flag;
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 __attribute__((always_inline))
@@ -267,6 +271,10 @@ void board_init_f(ulong bootflag)
 	watchdog_init();
 #endif
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 #ifdef DEBUG
 	if (GENERATED_GBL_DATA_SIZE < sizeof(*gd))
 		hang();
diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h
index cd55b83..bd30435 100644
--- a/arch/m68k/include/asm/global_data.h
+++ b/arch/m68k/include/asm/global_data.h
@@ -66,6 +66,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/m68k/lib/board.c b/arch/m68k/lib/board.c
index 65a8595..1b9312c 100644
--- a/arch/m68k/lib/board.c
+++ b/arch/m68k/lib/board.c
@@ -69,6 +69,10 @@
 
 #include <nand.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static char *failed = "*** failed ***\n";
@@ -227,6 +231,10 @@ board_init_f (ulong bootflag)
 	/* Clear initial global data */
 	memset ((void *) gd, 0, sizeof (gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0) {
 			hang ();
diff --git a/arch/microblaze/include/asm/global_data.h b/arch/microblaze/include/asm/global_data.h
index de3b8db..6f4066d 100644
--- a/arch/microblaze/include/asm/global_data.h
+++ b/arch/microblaze/include/asm/global_data.h
@@ -46,6 +46,9 @@ typedef	struct	global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c
index 674b573..eeb8441 100644
--- a/arch/microblaze/lib/board.c
+++ b/arch/microblaze/lib/board.c
@@ -37,6 +37,10 @@
 #include <asm/microblaze_intc.h>
 #include <fdtdec.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
@@ -81,6 +85,11 @@ void board_init_f(ulong not_used)
 	asm ("nop");	/* FIXME gd is not initialize - wait */
 	memset ((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 	memset ((void *)bd, 0, GENERATED_BD_INFO_SIZE);
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = bd;
 	gd->baudrate = CONFIG_BAUDRATE;
 	bd->bi_baudrate = CONFIG_BAUDRATE;
diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h
index 6e2cdc7..ac24e3f 100644
--- a/arch/mips/include/asm/global_data.h
+++ b/arch/mips/include/asm/global_data.h
@@ -59,6 +59,9 @@ typedef	struct	global_data {
 	unsigned long	env_valid;	/* Checksum of Environment valid? */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/mips/lib/board.c b/arch/mips/lib/board.c
index 62d47a8..4657046 100644
--- a/arch/mips/lib/board.c
+++ b/arch/mips/lib/board.c
@@ -36,6 +36,10 @@
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
@@ -153,6 +157,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0)
 			hang();
diff --git a/arch/nds32/include/asm/global_data.h b/arch/nds32/include/asm/global_data.h
index 94bd4c2..d0e2606 100644
--- a/arch/nds32/include/asm/global_data.h
+++ b/arch/nds32/include/asm/global_data.h
@@ -63,6 +63,9 @@ typedef	struct global_data {
 
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/nds32/lib/board.c b/arch/nds32/lib/board.c
index 2164a50..97193b0 100644
--- a/arch/nds32/lib/board.c
+++ b/arch/nds32/lib/board.c
@@ -37,6 +37,10 @@
 #include <onenand_uboot.h>
 #include <mmc.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
@@ -192,6 +196,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->mon_len = (unsigned int)(&__bss_end__) - (unsigned int)(&_start);
 
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
diff --git a/arch/nios2/include/asm/global_data.h b/arch/nios2/include/asm/global_data.h
index 3b0d9e6..44373f4 100644
--- a/arch/nios2/include/asm/global_data.h
+++ b/arch/nios2/include/asm/global_data.h
@@ -42,6 +42,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/nios2/lib/board.c b/arch/nios2/lib/board.c
index 1e495d4..866dc12 100644
--- a/arch/nios2/lib/board.c
+++ b/arch/nios2/lib/board.c
@@ -40,6 +40,10 @@
 #include <nand.h>	/* cannot even include nand.h if it isnt configured */
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
@@ -95,6 +99,10 @@ void board_init (void)
 	/* compiler optimization barrier needed for GCC >= 3.4 */
 	__asm__ __volatile__("": : :"memory");
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = &bd_data;
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/openrisc/include/asm/global_data.h b/arch/openrisc/include/asm/global_data.h
index 6a0c0cc..ec2220a 100644
--- a/arch/openrisc/include/asm/global_data.h
+++ b/arch/openrisc/include/asm/global_data.h
@@ -44,6 +44,9 @@ typedef struct global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/openrisc/lib/board.c b/arch/openrisc/lib/board.c
index 85aa189..f1199d6 100644
--- a/arch/openrisc/lib/board.c
+++ b/arch/openrisc/lib/board.c
@@ -44,6 +44,10 @@
 #include <timestamp.h>
 #include <version.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
@@ -86,6 +90,10 @@ void board_init(void)
 
 	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = (bd_t *)(gd+1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h
index 5a5877f..38b63f9 100644
--- a/arch/powerpc/include/asm/global_data.h
+++ b/arch/powerpc/include/asm/global_data.h
@@ -182,6 +182,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
index fea310e..39af242 100644
--- a/arch/powerpc/lib/board.c
+++ b/arch/powerpc/lib/board.c
@@ -87,6 +87,10 @@
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 #ifdef CONFIG_SYS_UPDATE_FLASH_SIZE
 extern int update_flash_size(int flash_size);
 #endif
@@ -389,6 +393,10 @@ void board_init_f(ulong bootflag)
 	memset((void *) gd, 0, sizeof(gd_t));
 #endif
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)
 		if ((*init_fnc_ptr) () != 0)
 			hang();
diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h
index 581fd2f..00c7c10 100644
--- a/arch/sandbox/include/asm/global_data.h
+++ b/arch/sandbox/include/asm/global_data.h
@@ -46,6 +46,9 @@ typedef	struct global_data {
 	const void	*fdt_blob;	/* Our device tree, NULL if none */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sandbox/lib/board.c b/arch/sandbox/lib/board.c
index c173bf9..d384481 100644
--- a/arch/sandbox/lib/board.c
+++ b/arch/sandbox/lib/board.c
@@ -47,6 +47,10 @@
 
 #include <os.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static gd_t gd_mem;
@@ -157,6 +161,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 #if defined(CONFIG_OF_EMBED)
 	/* Get a pointer to the FDT */
 	gd->fdt_blob = _binary_dt_dtb_start;
diff --git a/arch/sh/include/asm/global_data.h b/arch/sh/include/asm/global_data.h
index 6e534ad..441fecd 100644
--- a/arch/sh/include/asm/global_data.h
+++ b/arch/sh/include/asm/global_data.h
@@ -42,6 +42,9 @@ typedef	struct global_data
 	unsigned long	env_valid;	/* Checksum of Environment valid */
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sh/lib/board.c b/arch/sh/lib/board.c
index 34d7881..eb04ed2 100644
--- a/arch/sh/lib/board.c
+++ b/arch/sh/lib/board.c
@@ -32,6 +32,10 @@
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 extern int cpu_init(void);
@@ -150,6 +154,10 @@ void sh_generic_init(void)
 
 	memset(gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
 
 	gd->bd = (bd_t *)(gd + 1);	/* At end of global data */
diff --git a/arch/sparc/include/asm/global_data.h b/arch/sparc/include/asm/global_data.h
index 93d3cc0..537e09a 100644
--- a/arch/sparc/include/asm/global_data.h
+++ b/arch/sparc/include/asm/global_data.h
@@ -74,6 +74,9 @@ typedef struct global_data {
 #endif
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sparc/lib/board.c b/arch/sparc/lib/board.c
index 6f33666..2ced0a7 100644
--- a/arch/sparc/lib/board.c
+++ b/arch/sparc/lib/board.c
@@ -53,6 +53,10 @@
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* Debug options
@@ -178,6 +182,10 @@ void board_init_f(ulong bootflag)
 	/* Clear initial global data */
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = (bd_t *) (gd + 1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 6d29c0b..920a805 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -57,6 +57,9 @@ typedef	struct global_data {
 	unsigned long	reset_status;	/* reset status register at boot */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 static inline gd_t *get_fs_gd_ptr(void)
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
index 90cf7fc..a670f9e 100644
--- a/arch/x86/lib/board.c
+++ b/arch/x86/lib/board.c
@@ -40,6 +40,10 @@
 #include <asm/init_helpers.h>
 #include <asm/init_wrappers.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 /*
  * Breath some life into the board...
  *
@@ -85,6 +89,17 @@
 typedef int (init_fnc_t) (void);
 
 /*
+ * Initialize early heap (when enabled by config).
+ */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+static void early_malloc_init(void)
+{
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+}
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+
+/*
  * init_sequence_f is the list of init functions which are run when U-Boot
  * is executing from Flash with a limited 'C' environment. The following
  * limitations must be considered when implementing an '_f' function:
@@ -99,6 +114,9 @@ init_fnc_t *init_sequence_f[] = {
 	cpu_init_f,
 	board_early_init_f,
 	env_init,
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	early_malloc_init,
+#endif /* CONFIG_SYS_EARLY_MALLOC */
 	init_baudrate_f,
 	serial_init,
 	console_init_f,
diff --git a/common/Makefile b/common/Makefile
index 22e8a6f..5862d34 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -201,6 +201,7 @@ COBJS-y += dlmalloc.o
 COBJS-y += image.o
 COBJS-y += memsize.o
 COBJS-y += stdio.o
+COBJS-$(CONFIG_DM) += dmmalloc.o
 
 
 COBJS	:= $(sort $(COBJS-y))
diff --git a/common/dmmalloc.c b/common/dmmalloc.c
new file mode 100644
index 0000000..3db0d7b
--- /dev/null
+++ b/common/dmmalloc.c
@@ -0,0 +1,93 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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 <common.h> /* for ROUND_UP */
+#include <asm/u-boot.h>
+#include <asm/global_data.h> /* for gd_t and gd */
+#include <asm/types.h> /* for phys_addr_t and size_addt_t */
+
+#include <dmmalloc.h>
+#include <malloc.h>
+
+#include <linux/compiler.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+__weak struct early_heap_header *early_brk(size_t size)
+{
+	struct early_heap_header *h =
+		(struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
+	struct early_heap_header *ehp = gd->early_heap_first;
+
+	while (ehp != NULL) {
+		if (ehp == h)
+			return NULL;
+
+		ehp = ehp->next_early_heap;
+	}
+
+	h->free_space_pointer = (void *)(roundup(
+				(phys_addr_t)CONFIG_SYS_EARLY_HEAP_ADDR +
+				sizeof(struct early_heap_header),
+				sizeof(phys_addr_t)));
+	h->free_bytes = size - roundup(sizeof(struct early_heap_header),
+				sizeof(phys_addr_t));
+	h->next_early_heap = NULL;
+
+	return h;
+}
+
+void *early_malloc(size_t size)
+{
+	phys_addr_t addr;
+	struct early_heap_header *h;
+
+	size = roundup(size, sizeof(phys_addr_t));
+
+	h = gd->early_heap_first;
+	while ((h->free_bytes < size) && (h->next_early_heap != NULL))
+		h = h->next_early_heap;
+
+	if (h->free_bytes < size) {
+		h->next_early_heap = early_brk(size);
+		if (h->next_early_heap == NULL)
+			debug("EH overflow. Can not early_brk. required %d B.",
+			size);
+		return NULL;
+	}
+
+	addr = (phys_addr_t)h->free_space_pointer;
+
+	h->free_space_pointer += size;
+	h->free_bytes -= size;
+
+	return (void *)addr;
+}
+
+int early_malloc_active(void)
+{
+	return ((gd->flags & GD_FLG_RELOC) != GD_FLG_RELOC);
+}
+
+#endif /* CONFIG_SYS_EARLY_MALLOC */
diff --git a/include/dmmalloc.h b/include/dmmalloc.h
new file mode 100644
index 0000000..a5ce2ec
--- /dev/null
+++ b/include/dmmalloc.h
@@ -0,0 +1,89 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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
+ */
+
+#ifndef __INCLUDE_DMMALLOC_H
+#define __INCLUDE_DMMALLOC_H
+
+#include <config.h>
+#include <linux/stddef.h> /* for size_t */
+#include <malloc.h>
+
+#if (!defined(CONFIG_SYS_EARLY_HEAP_ADDR)) || \
+	(!defined(CONFIG_SYS_EARLY_HEAP_SIZE))
+#undef CONFIG_SYS_EARLY_MALLOC
+#endif /* CONFIG_SYS_EARLY_HEAP_ADDR */
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+struct early_heap_header {
+	void *free_space_pointer;
+	size_t free_bytes;
+	void *next_early_heap;
+};
+
+struct early_heap_header *early_brk(size_t size);
+void *early_malloc(size_t size);
+int early_malloc_active(void);
+
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+#ifdef CONFIG_DM
+
+static inline void *dmmalloc(size_t size)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active())
+		return early_malloc(size);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return malloc(size);
+}
+
+static inline void dmfree(void *ptr)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active())
+		return;
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	free(ptr);
+}
+
+static inline void *dmcalloc(size_t n, size_t elem_size)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active())
+		return NULL;
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return calloc(n, elem_size);
+}
+
+static inline void *dmrealloc(void *oldmem, size_t bytes)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active())
+		return NULL;
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return dmrealloc(oldmem, bytes);
+}
+
+#endif /* CONFIG_DM */
+#endif /* __INCLUDE_DMMALLOC_H */
+
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v6] [RFC] early_malloc for DM added.
  2012-09-22 22:09 ` [U-Boot] [PATCH v6] " Tomas Hlavacek
@ 2012-09-23 13:06   ` Graeme Russ
  2012-09-23 15:30     ` Tomas Hlavacek
  0 siblings, 1 reply; 48+ messages in thread
From: Graeme Russ @ 2012-09-23 13:06 UTC (permalink / raw)
  To: u-boot

On Sep 23, 2012 8:09 AM, "Tomas Hlavacek" <tmshlvck@gmail.com> wrote:
>
> early_malloc for DM with support for more heaps and lightweight
> first heap in the same memory as an early stack.
>
> Adaptation layer for seamless calling of early_malloc or dlmalloc from
> DM based on init stage added (dmmalloc() and related functions).
>
> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
> ---

[snip]

> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +__weak struct early_heap_header *early_brk(size_t size)
> +{
> +       struct early_heap_header *h =
> +               (struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
> +       struct early_heap_header *ehp = gd->early_heap_first;
> +
> +       while (ehp != NULL) {
> +               if (ehp == h)
> +                       return NULL;
> +
> +               ehp = ehp->next_early_heap;
> +       }

if (g->early_heap_first == NULL)
    h = CONFIF_SYS_EARLY_HEAP_ADDR);
else
    return NULL;

> +
> +       h->free_space_pointer = (void *)(roundup(
> +                               (phys_addr_t)CONFIG_SYS_EARLY_HEAP_ADDR +
> +                               sizeof(struct early_heap_header),
> +                               sizeof(phys_addr_t)));
> +       h->free_bytes = size - roundup(sizeof(struct early_heap_header),
> +                               sizeof(phys_addr_t));
> +       h->next_early_heap = NULL;
> +
> +       return h;
> +}

Regards,

Graeme

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v6] [RFC] early_malloc for DM added.
  2012-09-23 13:06   ` Graeme Russ
@ 2012-09-23 15:30     ` Tomas Hlavacek
  0 siblings, 0 replies; 48+ messages in thread
From: Tomas Hlavacek @ 2012-09-23 15:30 UTC (permalink / raw)
  To: u-boot

Hello!

On Sun, Sep 23, 2012 at 3:06 PM, Graeme Russ <graeme.russ@gmail.com> wrote:
>
> On Sep 23, 2012 8:09 AM, "Tomas Hlavacek" <tmshlvck@gmail.com> wrote:
>>
>> early_malloc for DM with support for more heaps and lightweight
>> first heap in the same memory as an early stack.
>>
>> Adaptation layer for seamless calling of early_malloc or dlmalloc from
>> DM based on init stage added (dmmalloc() and related functions).
>>
>> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
>> ---
>
> [snip]
>
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> +__weak struct early_heap_header *early_brk(size_t size)
>> +{
>> +       struct early_heap_header *h =
>> +               (struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
>> +       struct early_heap_header *ehp = gd->early_heap_first;
>> +
>> +       while (ehp != NULL) {
>> +               if (ehp == h)
>> +                       return NULL;
>> +
>> +               ehp = ehp->next_early_heap;
>> +       }
>
> if (g->early_heap_first == NULL)
>     h = CONFIF_SYS_EARLY_HEAP_ADDR);
> else
>     return NULL;

Yes, I was too paranoid. What about:

if (g->early_heap_first != NULL)
                return NULL;

>
>> +
>> +       h->free_space_pointer = (void *)(roundup(
>> +                               (phys_addr_t)CONFIG_SYS_EARLY_HEAP_ADDR +
>> +                               sizeof(struct early_heap_header),
>> +                               sizeof(phys_addr_t)));
>> +       h->free_bytes = size - roundup(sizeof(struct early_heap_header),
>> +                               sizeof(phys_addr_t));
>> +       h->next_early_heap = NULL;
>> +
>> +       return h;
>> +}
>

Tomas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v7] [RFC] early_malloc for DM added.
  2012-08-27 12:12 [U-Boot] [PATCH 1/1] [RFC] DM: early_malloc for DM added Tomas Hlavacek
                   ` (4 preceding siblings ...)
  2012-09-22 22:09 ` [U-Boot] [PATCH v6] " Tomas Hlavacek
@ 2012-09-23 15:38 ` Tomas Hlavacek
  2012-09-23 16:15 ` [U-Boot] [PATCH v8] " Tomas Hlavacek
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 48+ messages in thread
From: Tomas Hlavacek @ 2012-09-23 15:38 UTC (permalink / raw)
  To: u-boot

early_malloc for DM with support for more heaps and lightweight
first heap in the same memory as an early stack.

Adaptation layer for seamless calling of early_malloc or dlmalloc from
DM based on init stage added (dmmalloc() and related functions).

Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
---
Changelog since v5:
dmmalloc() and all dm* functions has been moved to header, made static
inline and preprocessor-dependent blocks are reworked.
early_malloc_active() corrected and made not static.
s/CONFIG_SYS_DM/CONFIG_DM/ applied.

Changelog sice v6:
Check of first heap emptyness in early_brk() has been simplified.

 arch/arm/include/asm/global_data.h        |    3 +
 arch/arm/lib/board.c                      |    8 +++
 arch/avr32/include/asm/global_data.h      |    3 +
 arch/avr32/lib/board.c                    |    9 +++
 arch/blackfin/include/asm/global_data.h   |    3 +
 arch/blackfin/lib/board.c                 |    8 +++
 arch/m68k/include/asm/global_data.h       |    3 +
 arch/m68k/lib/board.c                     |    8 +++
 arch/microblaze/include/asm/global_data.h |    3 +
 arch/microblaze/lib/board.c               |    9 +++
 arch/mips/include/asm/global_data.h       |    3 +
 arch/mips/lib/board.c                     |    8 +++
 arch/nds32/include/asm/global_data.h      |    3 +
 arch/nds32/lib/board.c                    |    8 +++
 arch/nios2/include/asm/global_data.h      |    3 +
 arch/nios2/lib/board.c                    |    8 +++
 arch/openrisc/include/asm/global_data.h   |    3 +
 arch/openrisc/lib/board.c                 |    8 +++
 arch/powerpc/include/asm/global_data.h    |    3 +
 arch/powerpc/lib/board.c                  |    8 +++
 arch/sandbox/include/asm/global_data.h    |    3 +
 arch/sandbox/lib/board.c                  |    8 +++
 arch/sh/include/asm/global_data.h         |    3 +
 arch/sh/lib/board.c                       |    8 +++
 arch/sparc/include/asm/global_data.h      |    3 +
 arch/sparc/lib/board.c                    |    8 +++
 arch/x86/include/asm/global_data.h        |    3 +
 arch/x86/lib/board.c                      |   18 ++++++
 common/Makefile                           |    1 +
 common/dmmalloc.c                         |   88 ++++++++++++++++++++++++++++
 include/dmmalloc.h                        |   89 +++++++++++++++++++++++++++++
 31 files changed, 344 insertions(+)
 create mode 100644 common/dmmalloc.c
 create mode 100644 include/dmmalloc.h

diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index f8088fe..ef727b0 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -82,6 +82,9 @@ typedef	struct	global_data {
 	unsigned long	post_log_res; /* success of POST test */
 	unsigned long	post_init_f_time; /* When post_init_f started */
 #endif
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
index f1951e8..f73d8b2 100644
--- a/arch/arm/lib/board.c
+++ b/arch/arm/lib/board.c
@@ -53,6 +53,10 @@
 #include <post.h>
 #include <logbuff.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 #ifdef CONFIG_BITBANGMII
 #include <miiphy.h>
 #endif
@@ -281,6 +285,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->mon_len = _bss_end_ofs;
 #ifdef CONFIG_OF_EMBED
 	/* Get a pointer to the FDT */
diff --git a/arch/avr32/include/asm/global_data.h b/arch/avr32/include/asm/global_data.h
index 7878bb1..0654a61 100644
--- a/arch/avr32/include/asm/global_data.h
+++ b/arch/avr32/include/asm/global_data.h
@@ -48,6 +48,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/avr32/lib/board.c b/arch/avr32/lib/board.c
index d7a64b4..f1bd946 100644
--- a/arch/avr32/lib/board.c
+++ b/arch/avr32/lib/board.c
@@ -42,6 +42,11 @@
 #ifdef CONFIG_GENERIC_ATMEL_MCI
 #include <mmc.h>
 #endif
+
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 unsigned long monitor_flash_len;
@@ -161,6 +166,10 @@ void board_init_f(ulong board_type)
 	memset(&gd_data, 0, sizeof(gd_data));
 	gd = &gd_data;
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	/* Perform initialization sequence */
 	board_early_init_f();
 	cpu_init();
diff --git a/arch/blackfin/include/asm/global_data.h b/arch/blackfin/include/asm/global_data.h
index 290a9e7..2ae395c 100644
--- a/arch/blackfin/include/asm/global_data.h
+++ b/arch/blackfin/include/asm/global_data.h
@@ -57,6 +57,9 @@ typedef struct global_data {
 
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c
index c380d27..96b7d76 100644
--- a/arch/blackfin/lib/board.c
+++ b/arch/blackfin/lib/board.c
@@ -37,6 +37,10 @@
 int post_flag;
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 __attribute__((always_inline))
@@ -267,6 +271,10 @@ void board_init_f(ulong bootflag)
 	watchdog_init();
 #endif
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 #ifdef DEBUG
 	if (GENERATED_GBL_DATA_SIZE < sizeof(*gd))
 		hang();
diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h
index cd55b83..bd30435 100644
--- a/arch/m68k/include/asm/global_data.h
+++ b/arch/m68k/include/asm/global_data.h
@@ -66,6 +66,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/m68k/lib/board.c b/arch/m68k/lib/board.c
index 65a8595..1b9312c 100644
--- a/arch/m68k/lib/board.c
+++ b/arch/m68k/lib/board.c
@@ -69,6 +69,10 @@
 
 #include <nand.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static char *failed = "*** failed ***\n";
@@ -227,6 +231,10 @@ board_init_f (ulong bootflag)
 	/* Clear initial global data */
 	memset ((void *) gd, 0, sizeof (gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0) {
 			hang ();
diff --git a/arch/microblaze/include/asm/global_data.h b/arch/microblaze/include/asm/global_data.h
index de3b8db..6f4066d 100644
--- a/arch/microblaze/include/asm/global_data.h
+++ b/arch/microblaze/include/asm/global_data.h
@@ -46,6 +46,9 @@ typedef	struct	global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c
index 674b573..eeb8441 100644
--- a/arch/microblaze/lib/board.c
+++ b/arch/microblaze/lib/board.c
@@ -37,6 +37,10 @@
 #include <asm/microblaze_intc.h>
 #include <fdtdec.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
@@ -81,6 +85,11 @@ void board_init_f(ulong not_used)
 	asm ("nop");	/* FIXME gd is not initialize - wait */
 	memset ((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 	memset ((void *)bd, 0, GENERATED_BD_INFO_SIZE);
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = bd;
 	gd->baudrate = CONFIG_BAUDRATE;
 	bd->bi_baudrate = CONFIG_BAUDRATE;
diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h
index 6e2cdc7..ac24e3f 100644
--- a/arch/mips/include/asm/global_data.h
+++ b/arch/mips/include/asm/global_data.h
@@ -59,6 +59,9 @@ typedef	struct	global_data {
 	unsigned long	env_valid;	/* Checksum of Environment valid? */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/mips/lib/board.c b/arch/mips/lib/board.c
index 62d47a8..4657046 100644
--- a/arch/mips/lib/board.c
+++ b/arch/mips/lib/board.c
@@ -36,6 +36,10 @@
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
@@ -153,6 +157,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0)
 			hang();
diff --git a/arch/nds32/include/asm/global_data.h b/arch/nds32/include/asm/global_data.h
index 94bd4c2..d0e2606 100644
--- a/arch/nds32/include/asm/global_data.h
+++ b/arch/nds32/include/asm/global_data.h
@@ -63,6 +63,9 @@ typedef	struct global_data {
 
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/nds32/lib/board.c b/arch/nds32/lib/board.c
index 2164a50..97193b0 100644
--- a/arch/nds32/lib/board.c
+++ b/arch/nds32/lib/board.c
@@ -37,6 +37,10 @@
 #include <onenand_uboot.h>
 #include <mmc.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
@@ -192,6 +196,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->mon_len = (unsigned int)(&__bss_end__) - (unsigned int)(&_start);
 
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
diff --git a/arch/nios2/include/asm/global_data.h b/arch/nios2/include/asm/global_data.h
index 3b0d9e6..44373f4 100644
--- a/arch/nios2/include/asm/global_data.h
+++ b/arch/nios2/include/asm/global_data.h
@@ -42,6 +42,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/nios2/lib/board.c b/arch/nios2/lib/board.c
index 1e495d4..866dc12 100644
--- a/arch/nios2/lib/board.c
+++ b/arch/nios2/lib/board.c
@@ -40,6 +40,10 @@
 #include <nand.h>	/* cannot even include nand.h if it isnt configured */
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
@@ -95,6 +99,10 @@ void board_init (void)
 	/* compiler optimization barrier needed for GCC >= 3.4 */
 	__asm__ __volatile__("": : :"memory");
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = &bd_data;
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/openrisc/include/asm/global_data.h b/arch/openrisc/include/asm/global_data.h
index 6a0c0cc..ec2220a 100644
--- a/arch/openrisc/include/asm/global_data.h
+++ b/arch/openrisc/include/asm/global_data.h
@@ -44,6 +44,9 @@ typedef struct global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/openrisc/lib/board.c b/arch/openrisc/lib/board.c
index 85aa189..f1199d6 100644
--- a/arch/openrisc/lib/board.c
+++ b/arch/openrisc/lib/board.c
@@ -44,6 +44,10 @@
 #include <timestamp.h>
 #include <version.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
@@ -86,6 +90,10 @@ void board_init(void)
 
 	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = (bd_t *)(gd+1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h
index 5a5877f..38b63f9 100644
--- a/arch/powerpc/include/asm/global_data.h
+++ b/arch/powerpc/include/asm/global_data.h
@@ -182,6 +182,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
index fea310e..39af242 100644
--- a/arch/powerpc/lib/board.c
+++ b/arch/powerpc/lib/board.c
@@ -87,6 +87,10 @@
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 #ifdef CONFIG_SYS_UPDATE_FLASH_SIZE
 extern int update_flash_size(int flash_size);
 #endif
@@ -389,6 +393,10 @@ void board_init_f(ulong bootflag)
 	memset((void *) gd, 0, sizeof(gd_t));
 #endif
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)
 		if ((*init_fnc_ptr) () != 0)
 			hang();
diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h
index 581fd2f..00c7c10 100644
--- a/arch/sandbox/include/asm/global_data.h
+++ b/arch/sandbox/include/asm/global_data.h
@@ -46,6 +46,9 @@ typedef	struct global_data {
 	const void	*fdt_blob;	/* Our device tree, NULL if none */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sandbox/lib/board.c b/arch/sandbox/lib/board.c
index c173bf9..d384481 100644
--- a/arch/sandbox/lib/board.c
+++ b/arch/sandbox/lib/board.c
@@ -47,6 +47,10 @@
 
 #include <os.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static gd_t gd_mem;
@@ -157,6 +161,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 #if defined(CONFIG_OF_EMBED)
 	/* Get a pointer to the FDT */
 	gd->fdt_blob = _binary_dt_dtb_start;
diff --git a/arch/sh/include/asm/global_data.h b/arch/sh/include/asm/global_data.h
index 6e534ad..441fecd 100644
--- a/arch/sh/include/asm/global_data.h
+++ b/arch/sh/include/asm/global_data.h
@@ -42,6 +42,9 @@ typedef	struct global_data
 	unsigned long	env_valid;	/* Checksum of Environment valid */
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sh/lib/board.c b/arch/sh/lib/board.c
index 34d7881..eb04ed2 100644
--- a/arch/sh/lib/board.c
+++ b/arch/sh/lib/board.c
@@ -32,6 +32,10 @@
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 extern int cpu_init(void);
@@ -150,6 +154,10 @@ void sh_generic_init(void)
 
 	memset(gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
 
 	gd->bd = (bd_t *)(gd + 1);	/* At end of global data */
diff --git a/arch/sparc/include/asm/global_data.h b/arch/sparc/include/asm/global_data.h
index 93d3cc0..537e09a 100644
--- a/arch/sparc/include/asm/global_data.h
+++ b/arch/sparc/include/asm/global_data.h
@@ -74,6 +74,9 @@ typedef struct global_data {
 #endif
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sparc/lib/board.c b/arch/sparc/lib/board.c
index 6f33666..2ced0a7 100644
--- a/arch/sparc/lib/board.c
+++ b/arch/sparc/lib/board.c
@@ -53,6 +53,10 @@
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* Debug options
@@ -178,6 +182,10 @@ void board_init_f(ulong bootflag)
 	/* Clear initial global data */
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = (bd_t *) (gd + 1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 6d29c0b..920a805 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -57,6 +57,9 @@ typedef	struct global_data {
 	unsigned long	reset_status;	/* reset status register at boot */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 static inline gd_t *get_fs_gd_ptr(void)
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
index 90cf7fc..a670f9e 100644
--- a/arch/x86/lib/board.c
+++ b/arch/x86/lib/board.c
@@ -40,6 +40,10 @@
 #include <asm/init_helpers.h>
 #include <asm/init_wrappers.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 /*
  * Breath some life into the board...
  *
@@ -85,6 +89,17 @@
 typedef int (init_fnc_t) (void);
 
 /*
+ * Initialize early heap (when enabled by config).
+ */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+static void early_malloc_init(void)
+{
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+}
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+
+/*
  * init_sequence_f is the list of init functions which are run when U-Boot
  * is executing from Flash with a limited 'C' environment. The following
  * limitations must be considered when implementing an '_f' function:
@@ -99,6 +114,9 @@ init_fnc_t *init_sequence_f[] = {
 	cpu_init_f,
 	board_early_init_f,
 	env_init,
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	early_malloc_init,
+#endif /* CONFIG_SYS_EARLY_MALLOC */
 	init_baudrate_f,
 	serial_init,
 	console_init_f,
diff --git a/common/Makefile b/common/Makefile
index 22e8a6f..5862d34 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -201,6 +201,7 @@ COBJS-y += dlmalloc.o
 COBJS-y += image.o
 COBJS-y += memsize.o
 COBJS-y += stdio.o
+COBJS-$(CONFIG_DM) += dmmalloc.o
 
 
 COBJS	:= $(sort $(COBJS-y))
diff --git a/common/dmmalloc.c b/common/dmmalloc.c
new file mode 100644
index 0000000..cde8800
--- /dev/null
+++ b/common/dmmalloc.c
@@ -0,0 +1,88 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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 <common.h> /* for ROUND_UP */
+#include <asm/u-boot.h>
+#include <asm/global_data.h> /* for gd_t and gd */
+#include <asm/types.h> /* for phys_addr_t and size_addt_t */
+
+#include <dmmalloc.h>
+#include <malloc.h>
+
+#include <linux/compiler.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+__weak struct early_heap_header *early_brk(size_t size)
+{
+	struct early_heap_header *h =
+		(struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
+
+	if (g->early_heap_first != NULL)
+		return NULL;
+
+	h->free_space_pointer = (void *)(roundup(
+				(phys_addr_t)CONFIG_SYS_EARLY_HEAP_ADDR +
+				sizeof(struct early_heap_header),
+				sizeof(phys_addr_t)));
+	h->free_bytes = size - roundup(sizeof(struct early_heap_header),
+				sizeof(phys_addr_t));
+	h->next_early_heap = NULL;
+
+	return h;
+}
+
+void *early_malloc(size_t size)
+{
+	phys_addr_t addr;
+	struct early_heap_header *h;
+
+	size = roundup(size, sizeof(phys_addr_t));
+
+	h = gd->early_heap_first;
+	while ((h->free_bytes < size) && (h->next_early_heap != NULL))
+		h = h->next_early_heap;
+
+	if (h->free_bytes < size) {
+		h->next_early_heap = early_brk(size);
+		if (h->next_early_heap == NULL)
+			debug("EH overflow. Can not early_brk. required %d B.",
+			size);
+		return NULL;
+	}
+
+	addr = (phys_addr_t)h->free_space_pointer;
+
+	h->free_space_pointer += size;
+	h->free_bytes -= size;
+
+	return (void *)addr;
+}
+
+int early_malloc_active(void)
+{
+	return ((gd->flags & GD_FLG_RELOC) != GD_FLG_RELOC);
+}
+
+#endif /* CONFIG_SYS_EARLY_MALLOC */
diff --git a/include/dmmalloc.h b/include/dmmalloc.h
new file mode 100644
index 0000000..a5ce2ec
--- /dev/null
+++ b/include/dmmalloc.h
@@ -0,0 +1,89 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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
+ */
+
+#ifndef __INCLUDE_DMMALLOC_H
+#define __INCLUDE_DMMALLOC_H
+
+#include <config.h>
+#include <linux/stddef.h> /* for size_t */
+#include <malloc.h>
+
+#if (!defined(CONFIG_SYS_EARLY_HEAP_ADDR)) || \
+	(!defined(CONFIG_SYS_EARLY_HEAP_SIZE))
+#undef CONFIG_SYS_EARLY_MALLOC
+#endif /* CONFIG_SYS_EARLY_HEAP_ADDR */
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+struct early_heap_header {
+	void *free_space_pointer;
+	size_t free_bytes;
+	void *next_early_heap;
+};
+
+struct early_heap_header *early_brk(size_t size);
+void *early_malloc(size_t size);
+int early_malloc_active(void);
+
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+#ifdef CONFIG_DM
+
+static inline void *dmmalloc(size_t size)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active())
+		return early_malloc(size);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return malloc(size);
+}
+
+static inline void dmfree(void *ptr)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active())
+		return;
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	free(ptr);
+}
+
+static inline void *dmcalloc(size_t n, size_t elem_size)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active())
+		return NULL;
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return calloc(n, elem_size);
+}
+
+static inline void *dmrealloc(void *oldmem, size_t bytes)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active())
+		return NULL;
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return dmrealloc(oldmem, bytes);
+}
+
+#endif /* CONFIG_DM */
+#endif /* __INCLUDE_DMMALLOC_H */
+
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v8] [RFC] early_malloc for DM added.
  2012-08-27 12:12 [U-Boot] [PATCH 1/1] [RFC] DM: early_malloc for DM added Tomas Hlavacek
                   ` (5 preceding siblings ...)
  2012-09-23 15:38 ` [U-Boot] [PATCH v7] " Tomas Hlavacek
@ 2012-09-23 16:15 ` Tomas Hlavacek
  2012-09-23 16:32   ` Wolfgang Denk
                     ` (2 more replies)
  2012-10-24 23:49 ` [U-Boot] [PATCH v9] [RFC] Add dmmalloc module for DM Tomas Hlavacek
  2012-10-28 23:20 ` [U-Boot] [PATCH v10] " Tomas Hlavacek
  8 siblings, 3 replies; 48+ messages in thread
From: Tomas Hlavacek @ 2012-09-23 16:15 UTC (permalink / raw)
  To: u-boot

early_malloc for DM with support for more heaps and lightweight
first heap in the same memory as an early stack.

Adaptation layer for seamless calling of early_malloc or dlmalloc from
DM based on init stage added (dmmalloc() and related functions).

Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
---
Changelog since v5:
dmmalloc() and all dm* functions has been moved to header, made static
inline and preprocessor-dependent blocks are reworked.
early_malloc_active() corrected and made not static.
s/CONFIG_SYS_DM/CONFIG_DM/ applied.

Changelog sice v6:
Check of first heap emptyness in early_brk() has been simplified.

Changelog since v7:
dmcalloc() implmentation added.
Comments added to header.

 arch/arm/include/asm/global_data.h        |    3 +
 arch/arm/lib/board.c                      |    8 ++
 arch/avr32/include/asm/global_data.h      |    3 +
 arch/avr32/lib/board.c                    |    9 +++
 arch/blackfin/include/asm/global_data.h   |    3 +
 arch/blackfin/lib/board.c                 |    8 ++
 arch/m68k/include/asm/global_data.h       |    3 +
 arch/m68k/lib/board.c                     |    8 ++
 arch/microblaze/include/asm/global_data.h |    3 +
 arch/microblaze/lib/board.c               |    9 +++
 arch/mips/include/asm/global_data.h       |    3 +
 arch/mips/lib/board.c                     |    8 ++
 arch/nds32/include/asm/global_data.h      |    3 +
 arch/nds32/lib/board.c                    |    8 ++
 arch/nios2/include/asm/global_data.h      |    3 +
 arch/nios2/lib/board.c                    |    8 ++
 arch/openrisc/include/asm/global_data.h   |    3 +
 arch/openrisc/lib/board.c                 |    8 ++
 arch/powerpc/include/asm/global_data.h    |    3 +
 arch/powerpc/lib/board.c                  |    8 ++
 arch/sandbox/include/asm/global_data.h    |    3 +
 arch/sandbox/lib/board.c                  |    8 ++
 arch/sh/include/asm/global_data.h         |    3 +
 arch/sh/lib/board.c                       |    8 ++
 arch/sparc/include/asm/global_data.h      |    3 +
 arch/sparc/lib/board.c                    |    8 ++
 arch/x86/include/asm/global_data.h        |    3 +
 arch/x86/lib/board.c                      |   18 +++++
 common/Makefile                           |    1 +
 common/dmmalloc.c                         |   88 ++++++++++++++++++++++
 include/dmmalloc.h                        |  117 +++++++++++++++++++++++++++++
 31 files changed, 372 insertions(+)
 create mode 100644 common/dmmalloc.c
 create mode 100644 include/dmmalloc.h

diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index f8088fe..ef727b0 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -82,6 +82,9 @@ typedef	struct	global_data {
 	unsigned long	post_log_res; /* success of POST test */
 	unsigned long	post_init_f_time; /* When post_init_f started */
 #endif
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
index f1951e8..f73d8b2 100644
--- a/arch/arm/lib/board.c
+++ b/arch/arm/lib/board.c
@@ -53,6 +53,10 @@
 #include <post.h>
 #include <logbuff.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 #ifdef CONFIG_BITBANGMII
 #include <miiphy.h>
 #endif
@@ -281,6 +285,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->mon_len = _bss_end_ofs;
 #ifdef CONFIG_OF_EMBED
 	/* Get a pointer to the FDT */
diff --git a/arch/avr32/include/asm/global_data.h b/arch/avr32/include/asm/global_data.h
index 7878bb1..0654a61 100644
--- a/arch/avr32/include/asm/global_data.h
+++ b/arch/avr32/include/asm/global_data.h
@@ -48,6 +48,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/avr32/lib/board.c b/arch/avr32/lib/board.c
index d7a64b4..f1bd946 100644
--- a/arch/avr32/lib/board.c
+++ b/arch/avr32/lib/board.c
@@ -42,6 +42,11 @@
 #ifdef CONFIG_GENERIC_ATMEL_MCI
 #include <mmc.h>
 #endif
+
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 unsigned long monitor_flash_len;
@@ -161,6 +166,10 @@ void board_init_f(ulong board_type)
 	memset(&gd_data, 0, sizeof(gd_data));
 	gd = &gd_data;
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	/* Perform initialization sequence */
 	board_early_init_f();
 	cpu_init();
diff --git a/arch/blackfin/include/asm/global_data.h b/arch/blackfin/include/asm/global_data.h
index 290a9e7..2ae395c 100644
--- a/arch/blackfin/include/asm/global_data.h
+++ b/arch/blackfin/include/asm/global_data.h
@@ -57,6 +57,9 @@ typedef struct global_data {
 
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c
index c380d27..96b7d76 100644
--- a/arch/blackfin/lib/board.c
+++ b/arch/blackfin/lib/board.c
@@ -37,6 +37,10 @@
 int post_flag;
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 __attribute__((always_inline))
@@ -267,6 +271,10 @@ void board_init_f(ulong bootflag)
 	watchdog_init();
 #endif
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 #ifdef DEBUG
 	if (GENERATED_GBL_DATA_SIZE < sizeof(*gd))
 		hang();
diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h
index cd55b83..bd30435 100644
--- a/arch/m68k/include/asm/global_data.h
+++ b/arch/m68k/include/asm/global_data.h
@@ -66,6 +66,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/m68k/lib/board.c b/arch/m68k/lib/board.c
index 65a8595..1b9312c 100644
--- a/arch/m68k/lib/board.c
+++ b/arch/m68k/lib/board.c
@@ -69,6 +69,10 @@
 
 #include <nand.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static char *failed = "*** failed ***\n";
@@ -227,6 +231,10 @@ board_init_f (ulong bootflag)
 	/* Clear initial global data */
 	memset ((void *) gd, 0, sizeof (gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0) {
 			hang ();
diff --git a/arch/microblaze/include/asm/global_data.h b/arch/microblaze/include/asm/global_data.h
index de3b8db..6f4066d 100644
--- a/arch/microblaze/include/asm/global_data.h
+++ b/arch/microblaze/include/asm/global_data.h
@@ -46,6 +46,9 @@ typedef	struct	global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c
index 674b573..eeb8441 100644
--- a/arch/microblaze/lib/board.c
+++ b/arch/microblaze/lib/board.c
@@ -37,6 +37,10 @@
 #include <asm/microblaze_intc.h>
 #include <fdtdec.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
@@ -81,6 +85,11 @@ void board_init_f(ulong not_used)
 	asm ("nop");	/* FIXME gd is not initialize - wait */
 	memset ((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 	memset ((void *)bd, 0, GENERATED_BD_INFO_SIZE);
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = bd;
 	gd->baudrate = CONFIG_BAUDRATE;
 	bd->bi_baudrate = CONFIG_BAUDRATE;
diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h
index 6e2cdc7..ac24e3f 100644
--- a/arch/mips/include/asm/global_data.h
+++ b/arch/mips/include/asm/global_data.h
@@ -59,6 +59,9 @@ typedef	struct	global_data {
 	unsigned long	env_valid;	/* Checksum of Environment valid? */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/mips/lib/board.c b/arch/mips/lib/board.c
index 62d47a8..4657046 100644
--- a/arch/mips/lib/board.c
+++ b/arch/mips/lib/board.c
@@ -36,6 +36,10 @@
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
@@ -153,6 +157,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		if ((*init_fnc_ptr)() != 0)
 			hang();
diff --git a/arch/nds32/include/asm/global_data.h b/arch/nds32/include/asm/global_data.h
index 94bd4c2..d0e2606 100644
--- a/arch/nds32/include/asm/global_data.h
+++ b/arch/nds32/include/asm/global_data.h
@@ -63,6 +63,9 @@ typedef	struct global_data {
 
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/nds32/lib/board.c b/arch/nds32/lib/board.c
index 2164a50..97193b0 100644
--- a/arch/nds32/lib/board.c
+++ b/arch/nds32/lib/board.c
@@ -37,6 +37,10 @@
 #include <onenand_uboot.h>
 #include <mmc.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
@@ -192,6 +196,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->mon_len = (unsigned int)(&__bss_end__) - (unsigned int)(&_start);
 
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
diff --git a/arch/nios2/include/asm/global_data.h b/arch/nios2/include/asm/global_data.h
index 3b0d9e6..44373f4 100644
--- a/arch/nios2/include/asm/global_data.h
+++ b/arch/nios2/include/asm/global_data.h
@@ -42,6 +42,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/nios2/lib/board.c b/arch/nios2/lib/board.c
index 1e495d4..866dc12 100644
--- a/arch/nios2/lib/board.c
+++ b/arch/nios2/lib/board.c
@@ -40,6 +40,10 @@
 #include <nand.h>	/* cannot even include nand.h if it isnt configured */
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
@@ -95,6 +99,10 @@ void board_init (void)
 	/* compiler optimization barrier needed for GCC >= 3.4 */
 	__asm__ __volatile__("": : :"memory");
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = &bd_data;
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/openrisc/include/asm/global_data.h b/arch/openrisc/include/asm/global_data.h
index 6a0c0cc..ec2220a 100644
--- a/arch/openrisc/include/asm/global_data.h
+++ b/arch/openrisc/include/asm/global_data.h
@@ -44,6 +44,9 @@ typedef struct global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/openrisc/lib/board.c b/arch/openrisc/lib/board.c
index 85aa189..f1199d6 100644
--- a/arch/openrisc/lib/board.c
+++ b/arch/openrisc/lib/board.c
@@ -44,6 +44,10 @@
 #include <timestamp.h>
 #include <version.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
@@ -86,6 +90,10 @@ void board_init(void)
 
 	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = (bd_t *)(gd+1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h
index 5a5877f..38b63f9 100644
--- a/arch/powerpc/include/asm/global_data.h
+++ b/arch/powerpc/include/asm/global_data.h
@@ -182,6 +182,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
index fea310e..39af242 100644
--- a/arch/powerpc/lib/board.c
+++ b/arch/powerpc/lib/board.c
@@ -87,6 +87,10 @@
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 #ifdef CONFIG_SYS_UPDATE_FLASH_SIZE
 extern int update_flash_size(int flash_size);
 #endif
@@ -389,6 +393,10 @@ void board_init_f(ulong bootflag)
 	memset((void *) gd, 0, sizeof(gd_t));
 #endif
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)
 		if ((*init_fnc_ptr) () != 0)
 			hang();
diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h
index 581fd2f..00c7c10 100644
--- a/arch/sandbox/include/asm/global_data.h
+++ b/arch/sandbox/include/asm/global_data.h
@@ -46,6 +46,9 @@ typedef	struct global_data {
 	const void	*fdt_blob;	/* Our device tree, NULL if none */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sandbox/lib/board.c b/arch/sandbox/lib/board.c
index c173bf9..d384481 100644
--- a/arch/sandbox/lib/board.c
+++ b/arch/sandbox/lib/board.c
@@ -47,6 +47,10 @@
 
 #include <os.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static gd_t gd_mem;
@@ -157,6 +161,10 @@ void board_init_f(ulong bootflag)
 
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 #if defined(CONFIG_OF_EMBED)
 	/* Get a pointer to the FDT */
 	gd->fdt_blob = _binary_dt_dtb_start;
diff --git a/arch/sh/include/asm/global_data.h b/arch/sh/include/asm/global_data.h
index 6e534ad..441fecd 100644
--- a/arch/sh/include/asm/global_data.h
+++ b/arch/sh/include/asm/global_data.h
@@ -42,6 +42,9 @@ typedef	struct global_data
 	unsigned long	env_valid;	/* Checksum of Environment valid */
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sh/lib/board.c b/arch/sh/lib/board.c
index 34d7881..eb04ed2 100644
--- a/arch/sh/lib/board.c
+++ b/arch/sh/lib/board.c
@@ -32,6 +32,10 @@
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 extern int cpu_init(void);
@@ -150,6 +154,10 @@ void sh_generic_init(void)
 
 	memset(gd, 0, GENERATED_GBL_DATA_SIZE);
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
 
 	gd->bd = (bd_t *)(gd + 1);	/* At end of global data */
diff --git a/arch/sparc/include/asm/global_data.h b/arch/sparc/include/asm/global_data.h
index 93d3cc0..537e09a 100644
--- a/arch/sparc/include/asm/global_data.h
+++ b/arch/sparc/include/asm/global_data.h
@@ -74,6 +74,9 @@ typedef struct global_data {
 #endif
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sparc/lib/board.c b/arch/sparc/lib/board.c
index 6f33666..2ced0a7 100644
--- a/arch/sparc/lib/board.c
+++ b/arch/sparc/lib/board.c
@@ -53,6 +53,10 @@
 #include <miiphy.h>
 #endif
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* Debug options
@@ -178,6 +182,10 @@ void board_init_f(ulong bootflag)
 	/* Clear initial global data */
 	memset((void *)gd, 0, sizeof(gd_t));
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 	gd->bd = (bd_t *) (gd + 1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
 	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 6d29c0b..920a805 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -57,6 +57,9 @@ typedef	struct global_data {
 	unsigned long	reset_status;	/* reset status register at boot */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap_first;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 static inline gd_t *get_fs_gd_ptr(void)
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
index 90cf7fc..a670f9e 100644
--- a/arch/x86/lib/board.c
+++ b/arch/x86/lib/board.c
@@ -40,6 +40,10 @@
 #include <asm/init_helpers.h>
 #include <asm/init_wrappers.h>
 
+#ifdef CONFIG_DM
+#include <dmmalloc.h>
+#endif
+
 /*
  * Breath some life into the board...
  *
@@ -85,6 +89,17 @@
 typedef int (init_fnc_t) (void);
 
 /*
+ * Initialize early heap (when enabled by config).
+ */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+static void early_malloc_init(void)
+{
+	gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+}
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+
+/*
  * init_sequence_f is the list of init functions which are run when U-Boot
  * is executing from Flash with a limited 'C' environment. The following
  * limitations must be considered when implementing an '_f' function:
@@ -99,6 +114,9 @@ init_fnc_t *init_sequence_f[] = {
 	cpu_init_f,
 	board_early_init_f,
 	env_init,
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	early_malloc_init,
+#endif /* CONFIG_SYS_EARLY_MALLOC */
 	init_baudrate_f,
 	serial_init,
 	console_init_f,
diff --git a/common/Makefile b/common/Makefile
index 22e8a6f..5862d34 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -201,6 +201,7 @@ COBJS-y += dlmalloc.o
 COBJS-y += image.o
 COBJS-y += memsize.o
 COBJS-y += stdio.o
+COBJS-$(CONFIG_DM) += dmmalloc.o
 
 
 COBJS	:= $(sort $(COBJS-y))
diff --git a/common/dmmalloc.c b/common/dmmalloc.c
new file mode 100644
index 0000000..6dbb622
--- /dev/null
+++ b/common/dmmalloc.c
@@ -0,0 +1,88 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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 <common.h> /* for ROUND_UP */
+#include <asm/u-boot.h>
+#include <asm/global_data.h> /* for gd_t and gd */
+#include <asm/types.h> /* for phys_addr_t and size_addt_t */
+
+#include <dmmalloc.h>
+#include <malloc.h>
+
+#include <linux/compiler.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+__weak struct early_heap_header *early_brk(size_t size)
+{
+	struct early_heap_header *h =
+		(struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
+
+	if (gd->early_heap_first != NULL)
+		return NULL;
+
+	h->free_space_pointer = (void *)(roundup(
+				(phys_addr_t)CONFIG_SYS_EARLY_HEAP_ADDR +
+				sizeof(struct early_heap_header),
+				sizeof(phys_addr_t)));
+	h->free_bytes = size - roundup(sizeof(struct early_heap_header),
+				sizeof(phys_addr_t));
+	h->next_early_heap = NULL;
+
+	return h;
+}
+
+void *early_malloc(size_t size)
+{
+	phys_addr_t addr;
+	struct early_heap_header *h;
+
+	size = roundup(size, sizeof(phys_addr_t));
+
+	h = gd->early_heap_first;
+	while ((h->free_bytes < size) && (h->next_early_heap != NULL))
+		h = h->next_early_heap;
+
+	if (h->free_bytes < size) {
+		h->next_early_heap = early_brk(size);
+		if (h->next_early_heap == NULL)
+			debug("EH overflow. Can not early_brk. required %d B.",
+			size);
+		return NULL;
+	}
+
+	addr = (phys_addr_t)h->free_space_pointer;
+
+	h->free_space_pointer += size;
+	h->free_bytes -= size;
+
+	return (void *)addr;
+}
+
+int early_malloc_active(void)
+{
+	return ((gd->flags & GD_FLG_RELOC) != GD_FLG_RELOC);
+}
+
+#endif /* CONFIG_SYS_EARLY_MALLOC */
diff --git a/include/dmmalloc.h b/include/dmmalloc.h
new file mode 100644
index 0000000..7bef0eb
--- /dev/null
+++ b/include/dmmalloc.h
@@ -0,0 +1,117 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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
+ */
+
+#ifndef __INCLUDE_DMMALLOC_H
+#define __INCLUDE_DMMALLOC_H
+
+#include <config.h>
+#include <linux/stddef.h> /* for size_t */
+#include <malloc.h>
+
+#if (!defined(CONFIG_SYS_EARLY_HEAP_ADDR)) || \
+	(!defined(CONFIG_SYS_EARLY_HEAP_SIZE))
+#undef CONFIG_SYS_EARLY_MALLOC
+#endif /* CONFIG_SYS_EARLY_HEAP_ADDR */
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+struct early_heap_header {
+	void *free_space_pointer;
+	size_t free_bytes;
+	void *next_early_heap;
+};
+
+/*
+ * Function to perfrom early break. This function can be platform dependent 
+ * or board dependent but sensible default is provided.
+ * @size: size of the new early heap to be allocated and set up.
+ * Returns the new heap pointer.
+ */
+struct early_heap_header *early_brk(size_t size);
+
+/*
+ * malloc-like function operating on the early_heap(s).
+ */
+void *early_malloc(size_t size);
+
+/*
+ * Check whether the early mallocator is active.
+ */
+int early_malloc_active(void);
+
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+#ifdef CONFIG_DM
+
+/* 
+ * DM versions of malloc* fuctions. In early init it calls early_malloc.
+ * It wraps around normal malloc* functions afterwards.
+ */
+
+static inline void *dmmalloc(size_t size)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active())
+		return early_malloc(size);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return malloc(size);
+}
+
+static inline void dmfree(void *ptr)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active())
+		return;
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	free(ptr);
+}
+
+static inline void *dmcalloc(size_t n, size_t elem_size)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	char *addr;
+	int size = elem_size * n;
+	int i;
+
+	if (early_malloc_active()) {
+		addr = early_malloc(size);
+		for (i=0; i<size; i++)
+			addr[i] = 0;
+
+		return addr;
+	}
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return calloc(n, elem_size);
+}
+
+static inline void *dmrealloc(void *oldmem, size_t bytes)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active())
+		return NULL;
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return dmrealloc(oldmem, bytes);
+}
+
+#endif /* CONFIG_DM */
+#endif /* __INCLUDE_DMMALLOC_H */
+
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v8] [RFC] early_malloc for DM added.
  2012-09-23 16:15 ` [U-Boot] [PATCH v8] " Tomas Hlavacek
@ 2012-09-23 16:32   ` Wolfgang Denk
  2012-09-23 16:47     ` Tomas Hlavacek
  2012-09-23 23:11   ` Marek Vasut
  2012-09-24  0:00   ` Graeme Russ
  2 siblings, 1 reply; 48+ messages in thread
From: Wolfgang Denk @ 2012-09-23 16:32 UTC (permalink / raw)
  To: u-boot

Dear Tomas Hlavacek,

In message <1348416940-20319-1-git-send-email-tmshlvck@gmail.com> you wrote:
> early_malloc for DM with support for more heaps and lightweight
> first heap in the same memory as an early stack.
> 
> Adaptation layer for seamless calling of early_malloc or dlmalloc from
> DM based on init stage added (dmmalloc() and related functions).
> 
> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
> ---
> Changelog since v5:
> dmmalloc() and all dm* functions has been moved to header, made static
> inline and preprocessor-dependent blocks are reworked.
> early_malloc_active() corrected and made not static.
> s/CONFIG_SYS_DM/CONFIG_DM/ applied.
> 
> Changelog sice v6:
> Check of first heap emptyness in early_brk() has been simplified.
> 
> Changelog since v7:
> dmcalloc() implmentation added.
> Comments added to header.

Your change log does not make much sense to me.  It appears there has
been some dmcalloc() implementation already in v5 (and eearlier?), as
you write there you moved it into the header file.  Now you add it
again?

This changelog is intended to desccribe the difference between the
patch versions, to allow a reviewer to recognize which comments you
addressed, and where you decided otherwise.

Your log does not provide any such information.


Also, please re-read the recommendations for the commit message.
"FOO added" is considered bad; please use something like "add FOO"
instead (i. e. describe what this commit actually does).


Also, please make sure tu run ALL patches through checkpatch before
submitting; your patch throws 4 errors that all need fixing.

Finally, you might want to consult a spell checker every now and then
(see for example "implmentation", "perfrom", etc.).

Thanks.

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"I'm not a god, I was misquoted."                 - Lister, Red Dwarf

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v8] [RFC] early_malloc for DM added.
  2012-09-23 16:32   ` Wolfgang Denk
@ 2012-09-23 16:47     ` Tomas Hlavacek
  2012-09-24 21:48       ` Tom Rini
  0 siblings, 1 reply; 48+ messages in thread
From: Tomas Hlavacek @ 2012-09-23 16:47 UTC (permalink / raw)
  To: u-boot

Dear Wolfgang Denk,

On Sun, Sep 23, 2012 at 6:32 PM, Wolfgang Denk <wd@denx.de> wrote:
>>
>> Changelog since v7:
>> dmcalloc() implmentation added.
>> Comments added to header.
>
> Your change log does not make much sense to me.  It appears there has
> been some dmcalloc() implementation already in v5 (and eearlier?), as
> you write there you moved it into the header file.  Now you add it
> again?

Well no. The dmcalloc function returned always NULL in the early stage
in the previous versions. The current version of dmcalloc simulates
calloc also in the early_mallocator stage.

>
> Also, please re-read the recommendations for the commit message.
> "FOO added" is considered bad; please use something like "add FOO"
> instead (i. e. describe what this commit actually does).

I will do that.

Tomas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v8] [RFC] early_malloc for DM added.
  2012-09-23 16:15 ` [U-Boot] [PATCH v8] " Tomas Hlavacek
  2012-09-23 16:32   ` Wolfgang Denk
@ 2012-09-23 23:11   ` Marek Vasut
  2012-09-24 14:16     ` Tomas Hlavacek
  2012-09-24  0:00   ` Graeme Russ
  2 siblings, 1 reply; 48+ messages in thread
From: Marek Vasut @ 2012-09-23 23:11 UTC (permalink / raw)
  To: u-boot

Dear Tomas Hlavacek,

[..]
> +
> +	if (early_malloc_active()) {
> +		addr = early_malloc(size);
> +		for (i=0; i<size; i++)
> +			addr[i] = 0;

memset() ?

> +
> +		return addr;
> +	}
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +	return calloc(n, elem_size);
> +}
> +
> +static inline void *dmrealloc(void *oldmem, size_t bytes)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	if (early_malloc_active())
> +		return NULL;

I wonder how should this be implemented ... maybe early_malloc + standard 
memcpy()

> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +	return dmrealloc(oldmem, bytes);
> +}
> +
> +#endif /* CONFIG_DM */
> +#endif /* __INCLUDE_DMMALLOC_H */
> +

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v8] [RFC] early_malloc for DM added.
  2012-09-23 16:15 ` [U-Boot] [PATCH v8] " Tomas Hlavacek
  2012-09-23 16:32   ` Wolfgang Denk
  2012-09-23 23:11   ` Marek Vasut
@ 2012-09-24  0:00   ` Graeme Russ
  2012-09-24  0:35     ` Tomas Hlavacek
  2 siblings, 1 reply; 48+ messages in thread
From: Graeme Russ @ 2012-09-24  0:00 UTC (permalink / raw)
  To: u-boot

Hi Tomas,

On Mon, Sep 24, 2012 at 2:15 AM, Tomas Hlavacek <tmshlvck@gmail.com> wrote:
> early_malloc for DM with support for more heaps and lightweight
> first heap in the same memory as an early stack.
>
> Adaptation layer for seamless calling of early_malloc or dlmalloc from
> DM based on init stage added (dmmalloc() and related functions).
>
> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
> ---
> Changelog since v5:
> dmmalloc() and all dm* functions has been moved to header, made static
> inline and preprocessor-dependent blocks are reworked.
> early_malloc_active() corrected and made not static.
> s/CONFIG_SYS_DM/CONFIG_DM/ applied.
>
> Changelog sice v6:
> Check of first heap emptyness in early_brk() has been simplified.
>
> Changelog since v7:
> dmcalloc() implmentation added.
> Comments added to header.
>
>  arch/arm/include/asm/global_data.h        |    3 +
>  arch/arm/lib/board.c                      |    8 ++
>  arch/avr32/include/asm/global_data.h      |    3 +
>  arch/avr32/lib/board.c                    |    9 +++
>  arch/blackfin/include/asm/global_data.h   |    3 +
>  arch/blackfin/lib/board.c                 |    8 ++
>  arch/m68k/include/asm/global_data.h       |    3 +
>  arch/m68k/lib/board.c                     |    8 ++
>  arch/microblaze/include/asm/global_data.h |    3 +
>  arch/microblaze/lib/board.c               |    9 +++
>  arch/mips/include/asm/global_data.h       |    3 +
>  arch/mips/lib/board.c                     |    8 ++
>  arch/nds32/include/asm/global_data.h      |    3 +
>  arch/nds32/lib/board.c                    |    8 ++
>  arch/nios2/include/asm/global_data.h      |    3 +
>  arch/nios2/lib/board.c                    |    8 ++
>  arch/openrisc/include/asm/global_data.h   |    3 +
>  arch/openrisc/lib/board.c                 |    8 ++
>  arch/powerpc/include/asm/global_data.h    |    3 +
>  arch/powerpc/lib/board.c                  |    8 ++
>  arch/sandbox/include/asm/global_data.h    |    3 +
>  arch/sandbox/lib/board.c                  |    8 ++
>  arch/sh/include/asm/global_data.h         |    3 +
>  arch/sh/lib/board.c                       |    8 ++
>  arch/sparc/include/asm/global_data.h      |    3 +
>  arch/sparc/lib/board.c                    |    8 ++
>  arch/x86/include/asm/global_data.h        |    3 +
>  arch/x86/lib/board.c                      |   18 +++++
>  common/Makefile                           |    1 +
>  common/dmmalloc.c                         |   88 ++++++++++++++++++++++
>  include/dmmalloc.h                        |  117 +++++++++++++++++++++++++++++
>  31 files changed, 372 insertions(+)
>  create mode 100644 common/dmmalloc.c
>  create mode 100644 include/dmmalloc.h
>
> diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
> index f8088fe..ef727b0 100644
> --- a/arch/arm/include/asm/global_data.h
> +++ b/arch/arm/include/asm/global_data.h
> @@ -82,6 +82,9 @@ typedef       struct  global_data {
>         unsigned long   post_log_res; /* success of POST test */
>         unsigned long   post_init_f_time; /* When post_init_f started */
>  #endif
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +       void    *early_heap_first;      /* heap for early_malloc */
> +#endif
>  } gd_t;
>
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
> index f1951e8..f73d8b2 100644
> --- a/arch/arm/lib/board.c
> +++ b/arch/arm/lib/board.c
> @@ -53,6 +53,10 @@
>  #include <post.h>
>  #include <logbuff.h>
>
> +#ifdef CONFIG_DM
> +#include <dmmalloc.h>
> +#endif
> +
>  #ifdef CONFIG_BITBANGMII
>  #include <miiphy.h>
>  #endif
> @@ -281,6 +285,10 @@ void board_init_f(ulong bootflag)
>
>         memset((void *)gd, 0, sizeof(gd_t));
>
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +       gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +

I just realised that all these initialisers can be dumped - early_brk()
will be called when early_malloc() is first called

[snip]

> diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
> index 90cf7fc..a670f9e 100644
> --- a/arch/x86/lib/board.c
> +++ b/arch/x86/lib/board.c
> @@ -40,6 +40,10 @@
>  #include <asm/init_helpers.h>
>  #include <asm/init_wrappers.h>
>
> +#ifdef CONFIG_DM
> +#include <dmmalloc.h>
> +#endif
> +
>  /*
>   * Breath some life into the board...
>   *
> @@ -85,6 +89,17 @@
>  typedef int (init_fnc_t) (void);
>
>  /*
> + * Initialize early heap (when enabled by config).
> + */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +static void early_malloc_init(void)
> +{
> +       gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
> +}
> +#endif /* CONFIG_SYS_EARLY_MALLOC */

So this uglyness goes

> +
> +
> +/*
>   * init_sequence_f is the list of init functions which are run when U-Boot
>   * is executing from Flash with a limited 'C' environment. The following
>   * limitations must be considered when implementing an '_f' function:
> @@ -99,6 +114,9 @@ init_fnc_t *init_sequence_f[] = {
>         cpu_init_f,
>         board_early_init_f,
>         env_init,
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +       early_malloc_init,
> +#endif /* CONFIG_SYS_EARLY_MALLOC */

And this one as well

>  COBJS  := $(sort $(COBJS-y))
> diff --git a/common/dmmalloc.c b/common/dmmalloc.c
> new file mode 100644
> index 0000000..6dbb622
> --- /dev/null
> +++ b/common/dmmalloc.c
> @@ -0,0 +1,88 @@
> +/*
> + * (C) Copyright 2012
> + * Tomas Hlavacek (tmshlvck at gmail.com)
> + *
> + * 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 <common.h> /* for ROUND_UP */
> +#include <asm/u-boot.h>
> +#include <asm/global_data.h> /* for gd_t and gd */
> +#include <asm/types.h> /* for phys_addr_t and size_addt_t */
> +
> +#include <dmmalloc.h>
> +#include <malloc.h>
> +
> +#include <linux/compiler.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +__weak struct early_heap_header *early_brk(size_t size)
> +{
> +       struct early_heap_header *h =
> +               (struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
> +
> +       if (gd->early_heap_first != NULL)
> +               return NULL;


       if (gd->early_heap_first != NULL) {
               debug("Early Heap: Failed to allocate %d byte block of
early heap.\n",
                     size);
               return NULL;
       }


> +
> +       h->free_space_pointer = (void *)(roundup(
> +                               (phys_addr_t)CONFIG_SYS_EARLY_HEAP_ADDR +
> +                               sizeof(struct early_heap_header),
> +                               sizeof(phys_addr_t)));
> +       h->free_bytes = size - roundup(sizeof(struct early_heap_header),
> +                               sizeof(phys_addr_t));
> +       h->next_early_heap = NULL;
> +
> +       return h;
> +}
> +
> +void *early_malloc(size_t size)
> +{
> +       phys_addr_t addr;
> +       struct early_heap_header *h;
> +
> +       size = roundup(size, sizeof(phys_addr_t));
> +
> +       h = gd->early_heap_first;
> +       while ((h->free_bytes < size) && (h->next_early_heap != NULL))
> +               h = h->next_early_heap;
> +
> +       if (h->free_bytes < size) {
> +               h->next_early_heap = early_brk(size);
> +               if (h->next_early_heap == NULL)
> +                       debug("EH overflow. Can not early_brk. required %d B.",
> +                       size);
> +               return NULL;

Missing brace and not using the newly allocated block

> +       }
> +
> +       addr = (phys_addr_t)h->free_space_pointer;
> +
> +       h->free_space_pointer += size;
> +       h->free_bytes -= size;
> +
> +       return (void *)addr;
> +}

This is still NULL pointer exception prone, for example calling dmmalloc()
before the initialisation function in board.c is called.

void *early_malloc(size_t size)
{
       phys_addr_t addr;
       struct early_heap_header *h;

       size = roundup(size, sizeof(phys_addr_t));

       /* Initialise first block of early heap (if not already done) */
       if (!gd->early_heap_first) {
               gd->early_heap_first = early_brk(size);

               if (!gd->early_heap_first)
                       return NULL;
       }

       /* Find an early heap block with enough free space */
       h = gd->early_heap_first;

       while ((h->free_bytes < size) && (h->next_early_heap != NULL))
               h = h->next_early_heap;

       /* Initialise another block of early heap if neccessary */
       if (h->free_bytes < size) {
               h->next_early_heap = early_brk(size);

               if (!h->next_early_heap)
                       return NULL;

               /* Use the newly allocated block */
               h = h->next_early_heap;
       }

       addr = (phys_addr_t)h->free_space_pointer;

       h->free_space_pointer += size;
       h->free_bytes -= size;

       return (void *)addr;
}

Regards,

Graeme

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v8] [RFC] early_malloc for DM added.
  2012-09-24  0:00   ` Graeme Russ
@ 2012-09-24  0:35     ` Tomas Hlavacek
  2012-09-24  0:46       ` Graeme Russ
  0 siblings, 1 reply; 48+ messages in thread
From: Tomas Hlavacek @ 2012-09-24  0:35 UTC (permalink / raw)
  To: u-boot

Hi Graeme!

On Mon, Sep 24, 2012 at 2:00 AM, Graeme Russ <graeme.russ@gmail.com> wrote:
> Hi Tomas,
>
> On Mon, Sep 24, 2012 at 2:15 AM, Tomas Hlavacek <tmshlvck@gmail.com> wrote:
>> early_malloc for DM with support for more heaps and lightweight
>> first heap in the same memory as an early stack.
>>
>> Adaptation layer for seamless calling of early_malloc or dlmalloc from
>> DM based on init stage added (dmmalloc() and related functions).
>>
>> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
>> ---
>> Changelog since v5:
>> dmmalloc() and all dm* functions has been moved to header, made static
>> inline and preprocessor-dependent blocks are reworked.
>> early_malloc_active() corrected and made not static.
>> s/CONFIG_SYS_DM/CONFIG_DM/ applied.
>>
>> Changelog sice v6:
>> Check of first heap emptyness in early_brk() has been simplified.
>>
>> Changelog since v7:
>> dmcalloc() implmentation added.
>> Comments added to header.
>>
>>  arch/arm/include/asm/global_data.h        |    3 +
>>  arch/arm/lib/board.c                      |    8 ++
>>  arch/avr32/include/asm/global_data.h      |    3 +
>>  arch/avr32/lib/board.c                    |    9 +++
>>  arch/blackfin/include/asm/global_data.h   |    3 +
>>  arch/blackfin/lib/board.c                 |    8 ++
>>  arch/m68k/include/asm/global_data.h       |    3 +
>>  arch/m68k/lib/board.c                     |    8 ++
>>  arch/microblaze/include/asm/global_data.h |    3 +
>>  arch/microblaze/lib/board.c               |    9 +++
>>  arch/mips/include/asm/global_data.h       |    3 +
>>  arch/mips/lib/board.c                     |    8 ++
>>  arch/nds32/include/asm/global_data.h      |    3 +
>>  arch/nds32/lib/board.c                    |    8 ++
>>  arch/nios2/include/asm/global_data.h      |    3 +
>>  arch/nios2/lib/board.c                    |    8 ++
>>  arch/openrisc/include/asm/global_data.h   |    3 +
>>  arch/openrisc/lib/board.c                 |    8 ++
>>  arch/powerpc/include/asm/global_data.h    |    3 +
>>  arch/powerpc/lib/board.c                  |    8 ++
>>  arch/sandbox/include/asm/global_data.h    |    3 +
>>  arch/sandbox/lib/board.c                  |    8 ++
>>  arch/sh/include/asm/global_data.h         |    3 +
>>  arch/sh/lib/board.c                       |    8 ++
>>  arch/sparc/include/asm/global_data.h      |    3 +
>>  arch/sparc/lib/board.c                    |    8 ++
>>  arch/x86/include/asm/global_data.h        |    3 +
>>  arch/x86/lib/board.c                      |   18 +++++
>>  common/Makefile                           |    1 +
>>  common/dmmalloc.c                         |   88 ++++++++++++++++++++++
>>  include/dmmalloc.h                        |  117 +++++++++++++++++++++++++++++
>>  31 files changed, 372 insertions(+)
>>  create mode 100644 common/dmmalloc.c
>>  create mode 100644 include/dmmalloc.h
>>
>> diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
>> index f8088fe..ef727b0 100644
>> --- a/arch/arm/include/asm/global_data.h
>> +++ b/arch/arm/include/asm/global_data.h
>> @@ -82,6 +82,9 @@ typedef       struct  global_data {
>>         unsigned long   post_log_res; /* success of POST test */
>>         unsigned long   post_init_f_time; /* When post_init_f started */
>>  #endif
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> +       void    *early_heap_first;      /* heap for early_malloc */
>> +#endif
>>  } gd_t;
>>
>>  #include <asm-generic/global_data_flags.h>
>> diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
>> index f1951e8..f73d8b2 100644
>> --- a/arch/arm/lib/board.c
>> +++ b/arch/arm/lib/board.c
>> @@ -53,6 +53,10 @@
>>  #include <post.h>
>>  #include <logbuff.h>
>>
>> +#ifdef CONFIG_DM
>> +#include <dmmalloc.h>
>> +#endif
>> +
>>  #ifdef CONFIG_BITBANGMII
>>  #include <miiphy.h>
>>  #endif
>> @@ -281,6 +285,10 @@ void board_init_f(ulong bootflag)
>>
>>         memset((void *)gd, 0, sizeof(gd_t));
>>
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> +       gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
>> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>> +
>
> I just realised that all these initialisers can be dumped - early_brk()
> will be called when early_malloc() is first called
>

Yes, but how can I determine the size of the new heap which the
early_brk gives out? When I have CONFIG_SYS_EARLY_HEAP_SIZE macro in
board configuration I can ignore the size passed to the "default"
early_brk and return the full-sized heap as configuration says (when
the requested size is lower than configured heap size and NULL
otherwise). But what if somebody implements at some point a dynamic
early_brk capable of returning multiple heaps? Should I safely assume
that the future dynamic early_brk would give out multiples of page
size or so?

All other comments understood and agreed.

Thanks,
Tomas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v8] [RFC] early_malloc for DM added.
  2012-09-24  0:35     ` Tomas Hlavacek
@ 2012-09-24  0:46       ` Graeme Russ
  0 siblings, 0 replies; 48+ messages in thread
From: Graeme Russ @ 2012-09-24  0:46 UTC (permalink / raw)
  To: u-boot

Hi Thomas,

On Mon, Sep 24, 2012 at 10:35 AM, Tomas Hlavacek <tmshlvck@gmail.com> wrote:
> Hi Graeme!
>
> On Mon, Sep 24, 2012 at 2:00 AM, Graeme Russ <graeme.russ@gmail.com> wrote:
>> Hi Tomas,
>>
>> On Mon, Sep 24, 2012 at 2:15 AM, Tomas Hlavacek <tmshlvck@gmail.com> wrote:
>>> early_malloc for DM with support for more heaps and lightweight
>>> first heap in the same memory as an early stack.
>>>
>>> Adaptation layer for seamless calling of early_malloc or dlmalloc from
>>> DM based on init stage added (dmmalloc() and related functions).
>>>
>>> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
>>> ---
>>> Changelog since v5:
>>> dmmalloc() and all dm* functions has been moved to header, made static
>>> inline and preprocessor-dependent blocks are reworked.
>>> early_malloc_active() corrected and made not static.
>>> s/CONFIG_SYS_DM/CONFIG_DM/ applied.
>>>
>>> Changelog sice v6:
>>> Check of first heap emptyness in early_brk() has been simplified.
>>>
>>> Changelog since v7:
>>> dmcalloc() implmentation added.
>>> Comments added to header.
>>>
>>>  arch/arm/include/asm/global_data.h        |    3 +
>>>  arch/arm/lib/board.c                      |    8 ++
>>>  arch/avr32/include/asm/global_data.h      |    3 +
>>>  arch/avr32/lib/board.c                    |    9 +++
>>>  arch/blackfin/include/asm/global_data.h   |    3 +
>>>  arch/blackfin/lib/board.c                 |    8 ++
>>>  arch/m68k/include/asm/global_data.h       |    3 +
>>>  arch/m68k/lib/board.c                     |    8 ++
>>>  arch/microblaze/include/asm/global_data.h |    3 +
>>>  arch/microblaze/lib/board.c               |    9 +++
>>>  arch/mips/include/asm/global_data.h       |    3 +
>>>  arch/mips/lib/board.c                     |    8 ++
>>>  arch/nds32/include/asm/global_data.h      |    3 +
>>>  arch/nds32/lib/board.c                    |    8 ++
>>>  arch/nios2/include/asm/global_data.h      |    3 +
>>>  arch/nios2/lib/board.c                    |    8 ++
>>>  arch/openrisc/include/asm/global_data.h   |    3 +
>>>  arch/openrisc/lib/board.c                 |    8 ++
>>>  arch/powerpc/include/asm/global_data.h    |    3 +
>>>  arch/powerpc/lib/board.c                  |    8 ++
>>>  arch/sandbox/include/asm/global_data.h    |    3 +
>>>  arch/sandbox/lib/board.c                  |    8 ++
>>>  arch/sh/include/asm/global_data.h         |    3 +
>>>  arch/sh/lib/board.c                       |    8 ++
>>>  arch/sparc/include/asm/global_data.h      |    3 +
>>>  arch/sparc/lib/board.c                    |    8 ++
>>>  arch/x86/include/asm/global_data.h        |    3 +
>>>  arch/x86/lib/board.c                      |   18 +++++
>>>  common/Makefile                           |    1 +
>>>  common/dmmalloc.c                         |   88 ++++++++++++++++++++++
>>>  include/dmmalloc.h                        |  117 +++++++++++++++++++++++++++++
>>>  31 files changed, 372 insertions(+)
>>>  create mode 100644 common/dmmalloc.c
>>>  create mode 100644 include/dmmalloc.h
>>>
>>> diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
>>> index f8088fe..ef727b0 100644
>>> --- a/arch/arm/include/asm/global_data.h
>>> +++ b/arch/arm/include/asm/global_data.h
>>> @@ -82,6 +82,9 @@ typedef       struct  global_data {
>>>         unsigned long   post_log_res; /* success of POST test */
>>>         unsigned long   post_init_f_time; /* When post_init_f started */
>>>  #endif
>>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>>> +       void    *early_heap_first;      /* heap for early_malloc */
>>> +#endif
>>>  } gd_t;
>>>
>>>  #include <asm-generic/global_data_flags.h>
>>> diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
>>> index f1951e8..f73d8b2 100644
>>> --- a/arch/arm/lib/board.c
>>> +++ b/arch/arm/lib/board.c
>>> @@ -53,6 +53,10 @@
>>>  #include <post.h>
>>>  #include <logbuff.h>
>>>
>>> +#ifdef CONFIG_DM
>>> +#include <dmmalloc.h>
>>> +#endif
>>> +
>>>  #ifdef CONFIG_BITBANGMII
>>>  #include <miiphy.h>
>>>  #endif
>>> @@ -281,6 +285,10 @@ void board_init_f(ulong bootflag)
>>>
>>>         memset((void *)gd, 0, sizeof(gd_t));
>>>
>>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>>> +       gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
>>> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>>> +
>>
>> I just realised that all these initialisers can be dumped - early_brk()
>> will be called when early_malloc() is first called
>>
>
> Yes, but how can I determine the size of the new heap which the
> early_brk gives out? When I have CONFIG_SYS_EARLY_HEAP_SIZE macro in
> board configuration I can ignore the size passed to the "default"
> early_brk and return the full-sized heap as configuration says (when
> the requested size is lower than configured heap size and NULL

default early_brk() should always use CONFIG_SYS_EARLY_HEAP_SIZE

> otherwise). But what if somebody implements at some point a dynamic
> early_brk capable of returning multiple heaps? Should I safely assume
> that the future dynamic early_brk would give out multiples of page
> size or so?

Very good point. I would assume early_brk() will always return the
largest possible chunk of memory it can. These sizes might be
specified as multiple #defines in the board config or may be
dynamically determined via hardware probing. Either way, that is a
problem for the implementer to deal with :)

Regards,

Graeme

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v8] [RFC] early_malloc for DM added.
  2012-09-23 23:11   ` Marek Vasut
@ 2012-09-24 14:16     ` Tomas Hlavacek
  2012-09-24 14:19       ` Marek Vasut
  0 siblings, 1 reply; 48+ messages in thread
From: Tomas Hlavacek @ 2012-09-24 14:16 UTC (permalink / raw)
  To: u-boot

Hello Marek,

On Mon, Sep 24, 2012 at 1:11 AM, Marek Vasut <marex@denx.de> wrote:
> Dear Tomas Hlavacek,
>
> [..]
>> +
>> +     if (early_malloc_active()) {
>> +             addr = early_malloc(size);
>> +             for (i=0; i<size; i++)
>> +                     addr[i] = 0;
>
> memset() ?

Yes, sure. Thanks.

>
>> +
>> +             return addr;
>> +     }
>> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>> +     return calloc(n, elem_size);
>> +}
>> +
>> +static inline void *dmrealloc(void *oldmem, size_t bytes)
>> +{
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> +     if (early_malloc_active())
>> +             return NULL;
>
> I wonder how should this be implemented ... maybe early_malloc + standard
> memcpy()

How do you want me to fix all the pointers to the memcpyied part of
heap then? I think this will not work unless I make some reservations
for eventual growth for each and every early_mallocated area. And I
think this is not good idea at all for early_malloc.

I think there are two straight-forward possibilities: a) keep the
empty implementation of dmrealloc() in early stage and avoid using it
in code which might run in early stage, but retain the dm* version of
the symbol. b) remove the dmrealloc() entirely which may have certain
negative consequences, because it might be tempting to mix dmmalloc()
and (non-dm*) realloc() calls which is obviously wrong.

Tomas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v8] [RFC] early_malloc for DM added.
  2012-09-24 14:16     ` Tomas Hlavacek
@ 2012-09-24 14:19       ` Marek Vasut
  2012-09-25  0:37         ` Graeme Russ
  0 siblings, 1 reply; 48+ messages in thread
From: Marek Vasut @ 2012-09-24 14:19 UTC (permalink / raw)
  To: u-boot

Dear Tomas Hlavacek,

[...]

> >> +static inline void *dmrealloc(void *oldmem, size_t bytes)
> >> +{
> >> +#ifdef CONFIG_SYS_EARLY_MALLOC
> >> +     if (early_malloc_active())
> >> +             return NULL;
> > 
> > I wonder how should this be implemented ... maybe early_malloc + standard
> > memcpy()
> 
> How do you want me to fix all the pointers to the memcpyied part of
> heap then? I think this will not work unless I make some reservations
> for eventual growth for each and every early_mallocated area. And I
> think this is not good idea at all for early_malloc.

What exactly would you need to fix ? It's only a matter of allocating new block, 
copying the existing data there and returning the pointer to the new block, no?

> I think there are two straight-forward possibilities: a) keep the
> empty implementation of dmrealloc() in early stage and avoid using it
> in code which might run in early stage, but retain the dm* version of
> the symbol. b) remove the dmrealloc() entirely which may have certain
> negative consequences, because it might be tempting to mix dmmalloc()
> and (non-dm*) realloc() calls which is obviously wrong.
> 
> Tomas

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v8] [RFC] early_malloc for DM added.
  2012-09-23 16:47     ` Tomas Hlavacek
@ 2012-09-24 21:48       ` Tom Rini
  0 siblings, 0 replies; 48+ messages in thread
From: Tom Rini @ 2012-09-24 21:48 UTC (permalink / raw)
  To: u-boot

On Sun, Sep 23, 2012 at 06:47:34PM +0200, Tomas Hlavacek wrote:
> Dear Wolfgang Denk,
> 
> On Sun, Sep 23, 2012 at 6:32 PM, Wolfgang Denk <wd@denx.de> wrote:
> >>
> >> Changelog since v7:
> >> dmcalloc() implmentation added.
> >> Comments added to header.
> >
> > Your change log does not make much sense to me.  It appears there has
> > been some dmcalloc() implementation already in v5 (and eearlier?), as
> > you write there you moved it into the header file.  Now you add it
> > again?
> 
> Well no. The dmcalloc function returned always NULL in the early stage
> in the previous versions. The current version of dmcalloc simulates
> calloc also in the early_mallocator stage.
> 
> >
> > Also, please re-read the recommendations for the commit message.
> > "FOO added" is considered bad; please use something like "add FOO"
> > instead (i. e. describe what this commit actually does).
> 
> I will do that.

I would strongly recommend and especially as the DM work moves on you
try using patman to manage the series as it will help you to keep track
of, and format properly, changelogs , run checkpatch and otherwise
encourage you to have the other good habits that help us to focus on
reviewing the changes themselves.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120924/cacb0309/attachment.pgp>

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v8] [RFC] early_malloc for DM added.
  2012-09-24 14:19       ` Marek Vasut
@ 2012-09-25  0:37         ` Graeme Russ
  2012-09-25  8:43           ` Tomas Hlavacek
  0 siblings, 1 reply; 48+ messages in thread
From: Graeme Russ @ 2012-09-25  0:37 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On Tue, Sep 25, 2012 at 12:19 AM, Marek Vasut <marex@denx.de> wrote:
> Dear Tomas Hlavacek,
>
> [...]
>
>> >> +static inline void *dmrealloc(void *oldmem, size_t bytes)
>> >> +{
>> >> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> >> +     if (early_malloc_active())
>> >> +             return NULL;
>> >
>> > I wonder how should this be implemented ... maybe early_malloc + standard
>> > memcpy()
>>
>> How do you want me to fix all the pointers to the memcpyied part of
>> heap then? I think this will not work unless I make some reservations
>> for eventual growth for each and every early_mallocated area. And I
>> think this is not good idea at all for early_malloc.
>
> What exactly would you need to fix ? It's only a matter of allocating new block,
> copying the existing data there and returning the pointer to the new block, no?
>
>> I think there are two straight-forward possibilities: a) keep the
>> empty implementation of dmrealloc() in early stage and avoid using it
>> in code which might run in early stage, but retain the dm* version of
>> the symbol. b) remove the dmrealloc() entirely which may have certain
>> negative consequences, because it might be tempting to mix dmmalloc()
>> and (non-dm*) realloc() calls which is obviously wrong.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v8] [RFC] early_malloc for DM added.
  2012-09-25  0:37         ` Graeme Russ
@ 2012-09-25  8:43           ` Tomas Hlavacek
  2012-09-25  9:09             ` Graeme Russ
  0 siblings, 1 reply; 48+ messages in thread
From: Tomas Hlavacek @ 2012-09-25  8:43 UTC (permalink / raw)
  To: u-boot

Hello Graeme!

On Tue, Sep 25, 2012 at 2:37 AM, Graeme Russ <graeme.russ@gmail.com> wrote:
> Hi Marek,

[...]

> The last two are NOPs for early heap as we have no way to track free'd blocks
>
> Keep in mind that 'real' realloc() has access to information providing
> the size of the source block of allocated memory, so it can do a
> memcpy using (at least a good guess of) the size of the source block.
> In the early heap case, we do not have that data, so we would need to
> memcpy the entire size of the destination block - this will likely
> bring in garbage (no problem as we there is nothing in the spec to
> forbid that) and _might_ have some interesting boundary conditions
> (what happens if we memcpy past the end of an early heap block into
> ga-ga land?)

I was thinking about such simple implementation:

static inline void *dmrealloc(void *oldaddr, size_t bytes)
{
#ifdef CONFIG_SYS_EARLY_MALLOC
        char *addr;
        if (early_malloc_active()) {
                addr = dmalloc(bytes);
                memcpy(addr, oldaddr, bytes);
                return addr;
        }
#endif /* CONFIG_SYS_EARLY_MALLOC */
        return dmrealloc(oldmem, bytes);
}

But then the fun comes: I can not distinguish the case when you have
100 B char *x allocated and you called dmrealloc(x, 99). And I can hit
some boundaries as

But yes, we can have such a stupid implementation. Or I can use
early_malloc frame header which would contain magic (to detect wrong
dmrealloc calls on arbitrary pointer) and size, so I would be able to
do free and realloc. Then I would need new free-space enumeration
mechanism to reuse free space (let's say that I can create a linked
list of free headers), so the frame header is going to be 12 B total.
Or we can have no implementation of dmrealloc at all.

Tomas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v8] [RFC] early_malloc for DM added.
  2012-09-25  8:43           ` Tomas Hlavacek
@ 2012-09-25  9:09             ` Graeme Russ
  2012-09-25 23:04               ` Graeme Russ
  0 siblings, 1 reply; 48+ messages in thread
From: Graeme Russ @ 2012-09-25  9:09 UTC (permalink / raw)
  To: u-boot

Hi Thomas,

On Sep 25, 2012 6:43 PM, "Tomas Hlavacek" <tmshlvck@gmail.com> wrote:
>
> Hello Graeme!
>
> On Tue, Sep 25, 2012 at 2:37 AM, Graeme Russ <graeme.russ@gmail.com>
wrote:
> > Hi Marek,
>
> [...]
>
> > The last two are NOPs for early heap as we have no way to track free'd
blocks
> >
> > Keep in mind that 'real' realloc() has access to information providing
> > the size of the source block of allocated memory, so it can do a
> > memcpy using (at least a good guess of) the size of the source block.
> > In the early heap case, we do not have that data, so we would need to
> > memcpy the entire size of the destination block - this will likely
> > bring in garbage (no problem as we there is nothing in the spec to
> > forbid that) and _might_ have some interesting boundary conditions
> > (what happens if we memcpy past the end of an early heap block into
> > ga-ga land?)
>
> I was thinking about such simple implementation:
>
> static inline void *dmrealloc(void *oldaddr, size_t bytes)
> {
> #ifdef CONFIG_SYS_EARLY_MALLOC
>         char *addr;
>         if (early_malloc_active()) {
>                 addr = dmalloc(bytes);
>                 memcpy(addr, oldaddr, bytes);
>                 return addr;
>         }
> #endif /* CONFIG_SYS_EARLY_MALLOC */
>         return dmrealloc(oldmem, bytes);
> }
>
> But then the fun comes: I can not distinguish the case when you have
> 100 B char *x allocated and you called dmrealloc(x, 99). And I can hit
> some boundaries as
>
> But yes, we can have such a stupid implementation. Or I can use
> early_malloc frame header which would contain magic (to detect wrong
> dmrealloc calls on arbitrary pointer) and size, so I would be able to
> do free and realloc. Then I would need new free-space enumeration
> mechanism to reuse free space (let's say that I can create a linked
> list of free headers), so the frame header is going to be 12 B total.
> Or we can have no implementation of dmrealloc at all.

We should implement each of malloc(), free(), calloc(), and realloc().

Don't worry about reclaiming and reusing space with a proper free()
implementation. Remember, all memory allocated on the early heap must be
relocated anyway.

Maybe if you add a size_t value immediately before the allocated space
which stores the block size. So:

size_t *bytes_ptr = ptr;
bytes_ptr--;
size_t bytes = *bytes_ptr;

gives you the block size

Regards,

Graeme

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v8] [RFC] early_malloc for DM added.
  2012-09-25  9:09             ` Graeme Russ
@ 2012-09-25 23:04               ` Graeme Russ
  2012-09-26 10:16                 ` Tomas Hlavacek
  0 siblings, 1 reply; 48+ messages in thread
From: Graeme Russ @ 2012-09-25 23:04 UTC (permalink / raw)
  To: u-boot

Hi Tomas

On Tue, Sep 25, 2012 at 7:09 PM, Graeme Russ <graeme.russ@gmail.com> wrote:

> We should implement each of malloc(), free(), calloc(), and realloc().
>
> Don't worry about reclaiming and reusing space with a proper free()
> implementation. Remember, all memory allocated on the early heap must be
> relocated anyway.
>
> Maybe if you add a size_t value immediately before the allocated space which
> stores the block size. So:
>
> size_t *bytes_ptr = ptr;
> bytes_ptr--;
> size_t bytes = *bytes_ptr;
>
> gives you the block size

I've been thinking about this a bit more, and for the sake of 4 bytes,
this additional 'size' member could be quite handy:
 - We effectively end up with a linked-list of allocated blocks
 - free() could set the high bit to tag the block as 'de-allocated'
 - When a block is relocated into the permanent heap, free() should be
   called on the source (early heap) block
 - We can call a 'cleanup' function after early heap is no longer needed
   and check that every block has the high bit set
 - We can re-use blocks by scanning for a tagged block with the same size
   (usefull for drivers that allocate temporary buffers which are always
   the same size)
 - If there are no early heaps with enough space for a given malloc
   operation, but there is a tagged block that is larger than the
   requested size, we can split tagged blocks

Remebering back to when I suggested a list of relocation helpers (one for
each allocated block), I think we can implement that as an additional field
in the block header (stretching the header to 8 bytes). This can come later.

Regards,

Graeme

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v8] [RFC] early_malloc for DM added.
  2012-09-25 23:04               ` Graeme Russ
@ 2012-09-26 10:16                 ` Tomas Hlavacek
  2012-09-26 23:03                   ` Graeme Russ
  0 siblings, 1 reply; 48+ messages in thread
From: Tomas Hlavacek @ 2012-09-26 10:16 UTC (permalink / raw)
  To: u-boot

Hello Graeme,

On Wed, Sep 26, 2012 at 1:04 AM, Graeme Russ <graeme.russ@gmail.com> wrote:
> Hi Tomas
>
> On Tue, Sep 25, 2012 at 7:09 PM, Graeme Russ <graeme.russ@gmail.com> wrote:
>
>> We should implement each of malloc(), free(), calloc(), and realloc().
>>
>> Don't worry about reclaiming and reusing space with a proper free()
>> implementation. Remember, all memory allocated on the early heap must be
>> relocated anyway.
>>
>> Maybe if you add a size_t value immediately before the allocated space which
>> stores the block size. So:
>>
>> size_t *bytes_ptr = ptr;
>> bytes_ptr--;
>> size_t bytes = *bytes_ptr;
>>
>> gives you the block size
>
> I've been thinking about this a bit more, and for the sake of 4 bytes,
> this additional 'size' member could be quite handy:
>  - We effectively end up with a linked-list of allocated blocks

Yes, this makes sense. Knowing size of allocated blocks enables the
early_malloc to do the whole set of malloc* functions.

Do you think it would be also useful to have a basic check that the
pointer passed to new early_free() and/or early_realloc() is valid? I
mean check that the pointer really points at the start of the block
and there is a valid header preceding the block. We can have a magic
number in the header for example. Or I can store a list of allocated
blocks as a variable-sized array in the early_heap_header.

>  - free() could set the high bit to tag the block as 'de-allocated'

Well, we would end up with malloc doing:

1) scan through all heaps to find best fit into previously free()-ed block
2) scan through all heaps to find enough free space using the heap header
3) call early_brk to obtain more space

Data structures would be:

The scanning two different header types for free space seems to me
being a bit redundant. What do you think about replacing point (2) and
using block headers instead of free space pointer in the heap header
and just split the block when there is not exact size match. I mean:

1) scan through all heaps to find best fit block
2) scan through all heaps to find greater block and split it
3) call early_brk to obtain more space

Data structures would be:

struct early_heap_header {
    int heap_size;
    phys_addr_t reloc_addr_old;
}

struct early_block_header {
    int magic;
    int size;
}

The brand new early_heap right after it's creation would consist of a
early_heap_header followed by a early_block_header with the free bit
set to true.

>  - When a block is relocated into the permanent heap, free() should be
>    called on the source (early heap) block

Well, that time we would have only a copy of the early_heap on certain
platforms. Assuming that first we set off drivers and DM using
early_heap(s), then we would copy each early_heap to some computed
address and jump to board_init_r. In board_init_r we would access the
early_heap copy via translation function using the address offset
(early_heap_copy - early_heap_copy->reloc_addr_old).

To do the early_free correctly in this mid-relocation state I would
have to allow early_* code to operate during this period. It is not
that hard to do, but maybe it is conceptually wrong because it means
operating early_malloc/realloc/free code on a copy of it's own data
after relocation.

>  - We can call a 'cleanup' function after early heap is no longer needed
>    and check that every block has the high bit set

Yes, it would help. When each block has to be free()-ed or relocated
and then free()-ed, it could help find memory leaks during early init.

>  - We can re-use blocks by scanning for a tagged block with the same size
>    (usefull for drivers that allocate temporary buffers which are always
>    the same size)
>  - If there are no early heaps with enough space for a given malloc
>    operation, but there is a tagged block that is larger than the
>    requested size, we can split tagged blocks
>
> Remebering back to when I suggested a list of relocation helpers (one for
> each allocated block), I think we can implement that as an additional field
> in the block header (stretching the header to 8 bytes). This can come later.

Do you mean we should place a pointer pointing at a relocation
function into each block header? I think it would end up in situation
like: Somebody is allocating a tree for example, he would set the
helper function into the root element and NULL pointers to other
nodes, because it makes more sense to relocate tree recursively from
the root.

Tomas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v8] [RFC] early_malloc for DM added.
  2012-09-26 10:16                 ` Tomas Hlavacek
@ 2012-09-26 23:03                   ` Graeme Russ
  0 siblings, 0 replies; 48+ messages in thread
From: Graeme Russ @ 2012-09-26 23:03 UTC (permalink / raw)
  To: u-boot

Hi Tomas,

On Wed, Sep 26, 2012 at 8:16 PM, Tomas Hlavacek <tmshlvck@gmail.com> wrote:
> Hello Graeme,
>
> On Wed, Sep 26, 2012 at 1:04 AM, Graeme Russ <graeme.russ@gmail.com> wrote:
>> Hi Tomas
>>
>> On Tue, Sep 25, 2012 at 7:09 PM, Graeme Russ <graeme.russ@gmail.com> wrote:
>>
>>> We should implement each of malloc(), free(), calloc(), and realloc().
>>>
>>> Don't worry about reclaiming and reusing space with a proper free()
>>> implementation. Remember, all memory allocated on the early heap must be
>>> relocated anyway.
>>>
>>> Maybe if you add a size_t value immediately before the allocated space which
>>> stores the block size. So:
>>>
>>> size_t *bytes_ptr = ptr;
>>> bytes_ptr--;
>>> size_t bytes = *bytes_ptr;
>>>
>>> gives you the block size
>>
>> I've been thinking about this a bit more, and for the sake of 4 bytes,
>> this additional 'size' member could be quite handy:
>>  - We effectively end up with a linked-list of allocated blocks
>
> Yes, this makes sense. Knowing size of allocated blocks enables the
> early_malloc to do the whole set of malloc* functions.
>
> Do you think it would be also useful to have a basic check that the
> pointer passed to new early_free() and/or early_realloc() is valid? I
> mean check that the pointer really points at the start of the block
> and there is a valid header preceding the block. We can have a magic
> number in the header for example. Or I can store a list of allocated
> blocks as a variable-sized array in the early_heap_header.

The goal of early_malloc is to be lightweight and fast, not bullet-proof.

>>  - free() could set the high bit to tag the block as 'de-allocated'
>
> Well, we would end up with malloc doing:
>
> 1) scan through all heaps to find best fit into previously free()-ed block
> 2) scan through all heaps to find enough free space using the heap header
> 3) call early_brk to obtain more space
>
> Data structures would be:
>
> The scanning two different header types for free space seems to me
> being a bit redundant. What do you think about replacing point (2) and
> using block headers instead of free space pointer in the heap header
> and just split the block when there is not exact size match. I mean:
>
> 1) scan through all heaps to find best fit block
> 2) scan through all heaps to find greater block and split it
> 3) call early_brk to obtain more space
>
> Data structures would be:
>
> struct early_heap_header {
>     int heap_size;
>     phys_addr_t reloc_addr_old;
> }

Hmm, what is reloc_addr_old all about?

> struct early_block_header {
>     int magic;
>     int size;
> }

NAK on the magic - waste of space

> The brand new early_heap right after it's creation would consist of a
> early_heap_header followed by a early_block_header with the free bit
> set to true.

Hmm, I think you may be on to something:

struct early_heap_header {
        struct early_heap_header *next_heap;
};

struch early_block {
        size_t size;
        unsigned char *data;
}

We could reserve the upper, say, 8 bits of size as flags. This leaves 24
bits as usable 'size' value (if anyone needs to allocate a 16M chunck of
memory early then we have a problem)

So the early heap starts out with an early_heap_header and an early_block
with size set to the size of the early heap (minus headers) with the
'free' and 'last block' flags set. The first call to early_malloc() would:
 - Split the block
 - Set the size to the appropriate value
 - Clear the 'free' and 'last block' flags
 - Create a new early_block after the allocated space
 - Set the size of the new block to the size of the remaining space
 - Set the 'free' and 'last block' flags of the new block

When calling early_malloc(), search through the list. If you find a free
block of exactly the right size, use it. If not, then while you are
scanning, keep a reference to the smallest free block larger than the
requested size. That leave a decision:
 - Do we always split the first 'smallest free block', or;
 - Do we always split the last block?

If there are no free blocks that can be split, call early_brk()

>>  - When a block is relocated into the permanent heap, free() should be
>>    called on the source (early heap) block
>
> Well, that time we would have only a copy of the early_heap on certain
> platforms. Assuming that first we set off drivers and DM using
> early_heap(s), then we would copy each early_heap to some computed
> address and jump to board_init_r. In board_init_r we would access the
> early_heap copy via translation function using the address offset
> (early_heap_copy - early_heap_copy->reloc_addr_old).

Me == 100% lost :)

Looks like you are still clinging onto the double-copy. If so, I'm still
not convinced.

> To do the early_free correctly in this mid-relocation state I would
> have to allow early_* code to operate during this period. It is not
> that hard to do, but maybe it is conceptually wrong because it means
> operating early_malloc/realloc/free code on a copy of it's own data
> after relocation.

Me == 110% lost :(

>>  - We can call a 'cleanup' function after early heap is no longer needed
>>    and check that every block has the high bit set
>
> Yes, it would help. When each block has to be free()-ed or relocated
> and then free()-ed, it could help find memory leaks during early init.

That's the idea - find poorly written drivers that assumed they would never
be initialised pre-relocation and don't handle relocation correctly.

>>  - We can re-use blocks by scanning for a tagged block with the same size
>>    (usefull for drivers that allocate temporary buffers which are always
>>    the same size)
>>  - If there are no early heaps with enough space for a given malloc
>>    operation, but there is a tagged block that is larger than the
>>    requested size, we can split tagged blocks
>>
>> Remebering back to when I suggested a list of relocation helpers (one for
>> each allocated block), I think we can implement that as an additional field
>> in the block header (stretching the header to 8 bytes). This can come later.
>
> Do you mean we should place a pointer pointing at a relocation
> function into each block header? I think it would end up in situation
> like: Somebody is allocating a tree for example, he would set the
> helper function into the root element and NULL pointers to other
> nodes, because it makes more sense to relocate tree recursively from
> the root.

Exactly - One of the flags could be 'no relocate' or some such

Regards,

Graeme

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v9] [RFC] Add dmmalloc module for DM.
  2012-08-27 12:12 [U-Boot] [PATCH 1/1] [RFC] DM: early_malloc for DM added Tomas Hlavacek
                   ` (6 preceding siblings ...)
  2012-09-23 16:15 ` [U-Boot] [PATCH v8] " Tomas Hlavacek
@ 2012-10-24 23:49 ` Tomas Hlavacek
  2012-10-25  1:40   ` Graeme Russ
  2012-10-28 23:20 ` [U-Boot] [PATCH v10] " Tomas Hlavacek
  8 siblings, 1 reply; 48+ messages in thread
From: Tomas Hlavacek @ 2012-10-24 23:49 UTC (permalink / raw)
  To: u-boot

Add pointer to the first early heap into GD structure.
Implement simple early_malloc and early_free functions.
Prepare for additional heaps and automated heap initialization.
Add temporary early_malloc_active function (to be replaced in future by
more coarse DM init flags).
Add DM specific malloc calls - dmmalloc, dmfree, dmrealloc and dmcalloc.

Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
---
Changes in v9:
    - Rework early_malloc to keep track of allocated block size.
    - Add early_free and dmfree functions.
    - Rework dmrealloc.
    - Add kerneldoc comments to dmmalloc.h.

Changes in v8:
    - Add dmcalloc() implmentation.
    - Add comments to function prototypes in dmmalloc.h.

Changes in v7:
    - Rework check of first heap in early_brk().

Changes in v6:
    - Move dmmalloc() and all dm* functions to dmmalloc.h.
    - Fix bool expression in early_malloc_active().

 arch/arm/include/asm/global_data.h        |    3 +
 arch/avr32/include/asm/global_data.h      |    3 +
 arch/blackfin/include/asm/global_data.h   |    3 +
 arch/m68k/include/asm/global_data.h       |    3 +
 arch/microblaze/include/asm/global_data.h |    3 +
 arch/mips/include/asm/global_data.h       |    3 +
 arch/nds32/include/asm/global_data.h      |    3 +
 arch/nios2/include/asm/global_data.h      |    3 +
 arch/openrisc/include/asm/global_data.h   |    3 +
 arch/powerpc/include/asm/global_data.h    |    3 +
 arch/sandbox/include/asm/global_data.h    |    3 +
 arch/sh/include/asm/global_data.h         |    3 +
 arch/sparc/include/asm/global_data.h      |    3 +
 arch/x86/include/asm/global_data.h        |    3 +
 common/Makefile                           |    1 +
 common/dmmalloc.c                         |  188 ++++++++++++++++++++++++++++
 include/dmmalloc.h                        |  194 +++++++++++++++++++++++++++++
 17 files changed, 425 insertions(+)
 create mode 100644 common/dmmalloc.c
 create mode 100644 include/dmmalloc.h

diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index 2b9af93..9045829 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -82,6 +82,9 @@ typedef	struct	global_data {
 	unsigned long	post_log_res; /* success of POST test */
 	unsigned long	post_init_f_time; /* When post_init_f started */
 #endif
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void		*early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/avr32/include/asm/global_data.h b/arch/avr32/include/asm/global_data.h
index bf661e2..f18f480 100644
--- a/arch/avr32/include/asm/global_data.h
+++ b/arch/avr32/include/asm/global_data.h
@@ -48,6 +48,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void		*early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/blackfin/include/asm/global_data.h b/arch/blackfin/include/asm/global_data.h
index d91e5a4..0725d55 100644
--- a/arch/blackfin/include/asm/global_data.h
+++ b/arch/blackfin/include/asm/global_data.h
@@ -57,6 +57,9 @@ typedef struct global_data {
 
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap;		/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h
index 0cdb11c..ab73499 100644
--- a/arch/m68k/include/asm/global_data.h
+++ b/arch/m68k/include/asm/global_data.h
@@ -66,6 +66,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void		*early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/microblaze/include/asm/global_data.h b/arch/microblaze/include/asm/global_data.h
index 2111c7c..f991e5d 100644
--- a/arch/microblaze/include/asm/global_data.h
+++ b/arch/microblaze/include/asm/global_data.h
@@ -46,6 +46,9 @@ typedef	struct	global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void		*early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h
index a735a8a..8167d39 100644
--- a/arch/mips/include/asm/global_data.h
+++ b/arch/mips/include/asm/global_data.h
@@ -59,6 +59,9 @@ typedef	struct	global_data {
 	unsigned long	env_valid;	/* Checksum of Environment valid? */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void		*early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/nds32/include/asm/global_data.h b/arch/nds32/include/asm/global_data.h
index b1feb2c..f7480e9 100644
--- a/arch/nds32/include/asm/global_data.h
+++ b/arch/nds32/include/asm/global_data.h
@@ -63,6 +63,9 @@ typedef	struct global_data {
 
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void		*early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/nios2/include/asm/global_data.h b/arch/nios2/include/asm/global_data.h
index 413b485..8881e31 100644
--- a/arch/nios2/include/asm/global_data.h
+++ b/arch/nios2/include/asm/global_data.h
@@ -42,6 +42,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void		*early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/openrisc/include/asm/global_data.h b/arch/openrisc/include/asm/global_data.h
index 96f3f1c..6ed6a15 100644
--- a/arch/openrisc/include/asm/global_data.h
+++ b/arch/openrisc/include/asm/global_data.h
@@ -44,6 +44,9 @@ typedef struct global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void		*early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h
index 374fc6d..f8d440b 100644
--- a/arch/powerpc/include/asm/global_data.h
+++ b/arch/powerpc/include/asm/global_data.h
@@ -182,6 +182,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void		*early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h
index 78a751d..6ee20e2 100644
--- a/arch/sandbox/include/asm/global_data.h
+++ b/arch/sandbox/include/asm/global_data.h
@@ -46,6 +46,9 @@ typedef	struct global_data {
 	const void	*fdt_blob;	/* Our device tree, NULL if none */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void		*early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sh/include/asm/global_data.h b/arch/sh/include/asm/global_data.h
index 9a2c193..6e0ae54 100644
--- a/arch/sh/include/asm/global_data.h
+++ b/arch/sh/include/asm/global_data.h
@@ -42,6 +42,9 @@ typedef	struct global_data
 	unsigned long	env_valid;	/* Checksum of Environment valid */
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void		*early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sparc/include/asm/global_data.h b/arch/sparc/include/asm/global_data.h
index aa63b35..9be8f27 100644
--- a/arch/sparc/include/asm/global_data.h
+++ b/arch/sparc/include/asm/global_data.h
@@ -74,6 +74,9 @@ typedef struct global_data {
 #endif
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void	*early_heap;		/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index bce999f..60384a5 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -57,6 +57,9 @@ typedef	struct global_data {
 	unsigned long	reset_status;	/* reset status register at boot */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	void		*early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 static inline gd_t *get_fs_gd_ptr(void)
diff --git a/common/Makefile b/common/Makefile
index fdfead7..bfb4d7a 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -209,6 +209,7 @@ COBJS-y += dlmalloc.o
 COBJS-y += image.o
 COBJS-y += memsize.o
 COBJS-y += stdio.o
+COBJS-$(CONFIG_DM) += dmmalloc.o
 
 
 COBJS	:= $(sort $(COBJS-y))
diff --git a/common/dmmalloc.c b/common/dmmalloc.c
new file mode 100644
index 0000000..41589dd
--- /dev/null
+++ b/common/dmmalloc.c
@@ -0,0 +1,188 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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 <common.h> /* for ROUND_UP */
+#include <asm/u-boot.h>
+#include <asm/global_data.h> /* for gd_t and gd */
+#include <asm/types.h> /* for phys_addr_t and size_addt_t */
+
+#include <dmmalloc.h>
+#include <malloc.h>
+
+#include <linux/compiler.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+__weak struct early_heap_header *early_brk(size_t size)
+{
+	struct early_heap_header *h;
+	struct early_block_header *b;
+
+	if (gd->early_heap != NULL)
+		return NULL;
+
+	h = (struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
+	b = (struct early_block_header *)(h + 1);
+
+	size = CONFIG_SYS_EARLY_HEAP_SIZE;
+	h->size = size;
+	h->early_heap_next = NULL;
+	b->size = size - sizeof(struct early_heap_header) -
+			sizeof(struct early_block_header);
+	b->size = BLOCK_SET_FREE(b->size);
+
+	return h;
+}
+
+static struct early_block_header *find_free_space(struct early_heap_header *h,
+							size_t size)
+{
+	struct early_block_header *b;
+
+	b = (struct early_block_header *)(h+1);
+	while ((phys_addr_t)b + sizeof(struct early_block_header)
+			< (phys_addr_t)h + h->size) {
+		if (BLOCK_FREE(b->size) && (BLOCK_SIZE(b->size) >= size))
+			return b;
+		b = (struct early_block_header *)((phys_addr_t)b +
+				sizeof(struct early_block_header) +
+				BLOCK_SIZE(b->size));
+	}
+
+	return NULL;
+}
+
+static struct early_block_header *split_block(struct early_block_header *b,
+	       size_t size)
+{
+	struct early_block_header *nb;
+
+	if ((BLOCK_SIZE(b->size) < size) || (BLOCK_USED(b->size)))
+		return NULL;
+
+	if (BLOCK_SIZE(b->size) <= (size + sizeof(struct early_block_header)))
+		return b;
+
+	nb = (struct early_block_header *)((phys_addr_t)b +
+		sizeof(struct early_block_header) + size);
+	nb->size = b->size - size - sizeof(struct early_block_header);
+	b->size = size;
+
+	return b;
+}
+
+void *early_malloc(size_t size)
+{
+	struct early_heap_header *h;
+	struct early_block_header *b;
+
+	size = roundup(size, sizeof(phys_addr_t));
+	if (size == 0)
+		return NULL;
+
+	if (gd->early_heap == NULL)
+		gd->early_heap = early_brk(size);
+
+	if (gd->early_heap == NULL) {
+		debug("early_brk failed to initialize heap\n");
+		return NULL;
+	}
+
+	h = gd->early_heap;
+	while (1) {
+		b = find_free_space(h, size);
+		if (b != NULL)
+			break;
+
+		if (h->early_heap_next != NULL)
+			h = h->early_heap_next;
+		else
+			break;
+	}
+
+	if (b == NULL) {
+		h->early_heap_next = early_brk(size+
+				sizeof(struct early_heap_header)+
+				sizeof(struct early_block_header));
+		h = h->early_heap_next;
+		if (h == NULL) {
+			debug("early_brk failed to extend heap by %d B\n",
+					size);
+			return NULL;
+		}
+
+		b = find_free_space(h, size);
+		if (b == NULL) {
+			debug("early_malloc failed to extend heap by %d B\n",
+					size);
+			return NULL;
+		}
+	}
+
+	if (b->size != size)
+		b = split_block(b, size);
+	if (b == NULL) {
+		debug("early_malloc failed to split block to %d B\n", size);
+		return NULL;
+	}
+
+	b->size = BLOCK_SET_USED(b->size);
+
+	return BLOCK_DATA(b);
+}
+
+void early_free(void *addr)
+{
+	struct early_block_header *h = BLOCK_HEADER(addr);
+	assert(BLOCK_USED(h->size));
+	h->size = BLOCK_SET_FREE(h->size);
+}
+
+int early_malloc_active(void)
+{
+	return ((gd->flags & GD_FLG_RELOC) != GD_FLG_RELOC);
+}
+
+void early_heap_dump(struct early_heap_header *h)
+{
+	struct early_block_header *b;
+
+	debug("heap: h=%p, h->size=%d\n", h, h->size);
+
+	b = (struct early_block_header *)(h+1);
+	while ((phys_addr_t)b + sizeof(struct early_block_header)
+			< (phys_addr_t)h + h->size) {
+		debug("block: h=%p h->size=%d b=%p b->size=%d b->(used)=%d\n",
+				h, h->size, b, BLOCK_SIZE(b->size),
+				BLOCK_USED(b->size));
+		assert(BLOCK_SIZE(b->size) > 0);
+		b = (struct early_block_header *)((phys_addr_t)b +
+				sizeof(struct early_block_header) +
+				BLOCK_SIZE(b->size));
+	}
+	debug("--- heap dump end ---\n");
+}
+
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
diff --git a/include/dmmalloc.h b/include/dmmalloc.h
new file mode 100644
index 0000000..a241e19
--- /dev/null
+++ b/include/dmmalloc.h
@@ -0,0 +1,194 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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
+ */
+
+#ifndef __INCLUDE_DMMALLOC_H
+#define __INCLUDE_DMMALLOC_H
+
+#include <config.h>
+#include <linux/stddef.h> /* for size_t */
+#include <malloc.h>
+
+#if (!defined(CONFIG_SYS_EARLY_HEAP_ADDR)) || \
+	(!defined(CONFIG_SYS_EARLY_HEAP_SIZE))
+#undef CONFIG_SYS_EARLY_MALLOC
+#endif /* CONFIG_SYS_EARLY_HEAP_ADDR */
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+struct early_heap_header {
+	size_t size;
+	void *early_heap_next;
+};
+
+struct early_block_header {
+	size_t size;
+};
+
+#define BLOCK_DATA(header) ((void *)(((struct early_block_header *)header)+1))
+#define BLOCK_HEADER(addr) (((struct early_block_header *)addr)-1)
+#define BLOCK_USED_FLAG 0x80000000
+#define BLOCK_SIZE(size) (size & (~BLOCK_USED_FLAG))
+#define BLOCK_USED(size) ((size & BLOCK_USED_FLAG) == BLOCK_USED_FLAG)
+#define BLOCK_FREE(size) (!BLOCK_USED(size))
+#define BLOCK_SET_FREE(size) BLOCK_SIZE(size)
+#define BLOCK_SET_USED(size) (size | BLOCK_USED_FLAG)
+
+/**
+ * early_brk() - obtain address of the heap
+ * @size:	Minimal size of the new early heap to be allocated.
+ *
+ * Function returns a new heap pointer.
+ *
+ * Allocate and initialize early_heap at least size bytes long.
+ * This function can be platform dependent or board dependent but sensible
+ * default is provided.
+ */
+struct early_heap_header *early_brk(size_t size);
+
+/**
+ * early_malloc() - malloc operating on the early_heap(s)
+ * @size:	Size in bytes.
+ *
+ * Function returns a pointer to the allocated block.
+ */
+void *early_malloc(size_t size);
+
+/**
+ * early_free() - free operating on the early_heap(s)
+ * @addr:	Pointer to the allocated block to be released.
+ */
+void early_free(void *addr);
+
+/**
+ * early_malloc_active() - indicate if the early mallocator is active
+ *
+ * Function returns true when the early_malloc and early_free are used and
+ * false otherwise.
+ */
+int early_malloc_active(void);
+
+/**
+ * early_heap_dump() - print blocks contained in an early_heap
+ * @h:		Address of the early heap.
+ */
+void early_heap_dump(struct early_heap_header *h);
+
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+#ifdef CONFIG_DM
+
+/*
+ * DM versions of malloc* functions. In early init it calls early_malloc.
+ * It wraps around normal malloc* functions afterwards.
+ */
+
+/**
+ * dmmalloc() - malloc working seamlessly in early as well as in RAM stages
+ * @size:	Size of the block to be allocated.
+ *
+ * Function returns an address of the newly allocated block when successful
+ * or NULL otherwise.
+ */
+static inline void *dmmalloc(size_t size)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active())
+		return early_malloc(size);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return malloc(size);
+}
+
+/**
+ * dmfree() - free working seamlessly in early as well as in RAM stages
+ * @ptr:	Pointer to the allocated block to be released.
+ */
+static inline void dmfree(void *ptr)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active()) {
+		early_free(ptr);
+		return;
+	}
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	free(ptr);
+}
+
+/**
+ * dmcalloc() - calloc working seamlessly in early as well as in RAM stages
+ * @n:		Number of elements to be allocated.
+ * @elem_size:	Size of elements to be allocated.
+ *
+ * Function returns a pointer to newly the allocated area (n*elem_size) long.
+ */
+static inline void *dmcalloc(size_t n, size_t elem_size)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	char *addr;
+	int size = elem_size * n;
+
+	if (early_malloc_active()) {
+		addr = early_malloc(size);
+		memset(addr, 0, size);
+		return addr;
+	}
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return calloc(n, elem_size);
+}
+
+/**
+ * dmrealloc() - realloc working seamlessly in early as well as in RAM stages
+ * @oldaddr:	Pointer to the old memory block.
+ * @bytes:	New size to of the block to be reallocated.
+ *
+ * Function returns an address of the newly allocated block when successful
+ * or NULL otherwise.
+ *
+ * Data are copied from the block specified by oldaddr to the new block.
+ */
+static inline void *dmrealloc(void *oldaddr, size_t bytes)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	char *addr;
+	struct early_block_header *h;
+	if (early_malloc_active()) {
+		addr = dmmalloc(bytes);
+		if (addr == NULL)
+			return NULL;
+
+		h = BLOCK_HEADER(oldaddr);
+		if (BLOCK_FREE(h->size))
+			return NULL;
+
+		if (bytes > BLOCK_SIZE(h->size))
+			bytes = BLOCK_SIZE(h->size);
+
+		memcpy(addr, oldaddr, bytes);
+		dmfree(oldaddr);
+		return addr;
+	}
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return realloc(oldaddr, bytes);
+}
+
+#endif /* CONFIG_DM */
+#endif /* __INCLUDE_DMMALLOC_H */
+
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v9] [RFC] Add dmmalloc module for DM.
  2012-10-24 23:49 ` [U-Boot] [PATCH v9] [RFC] Add dmmalloc module for DM Tomas Hlavacek
@ 2012-10-25  1:40   ` Graeme Russ
  2012-10-25 19:16     ` Tomas Hlavacek
  0 siblings, 1 reply; 48+ messages in thread
From: Graeme Russ @ 2012-10-25  1:40 UTC (permalink / raw)
  To: u-boot

Hi Tomas,

Overall impression - Very nice indeed :)

A couple of nit-picks (some of which may be wrong on my part) and one
lingering question around the switch over from early to late heap...

On Thu, Oct 25, 2012 at 10:49 AM, Tomas Hlavacek <tmshlvck@gmail.com> wrote:
> Add pointer to the first early heap into GD structure.
> Implement simple early_malloc and early_free functions.
> Prepare for additional heaps and automated heap initialization.
> Add temporary early_malloc_active function (to be replaced in future by
> more coarse DM init flags).
> Add DM specific malloc calls - dmmalloc, dmfree, dmrealloc and dmcalloc.
>
> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
> ---
> Changes in v9:
>     - Rework early_malloc to keep track of allocated block size.
>     - Add early_free and dmfree functions.
>     - Rework dmrealloc.
>     - Add kerneldoc comments to dmmalloc.h.
>
> Changes in v8:
>     - Add dmcalloc() implmentation.
>     - Add comments to function prototypes in dmmalloc.h.
>
> Changes in v7:
>     - Rework check of first heap in early_brk().
>
> Changes in v6:
>     - Move dmmalloc() and all dm* functions to dmmalloc.h.
>     - Fix bool expression in early_malloc_active().
>
>  arch/arm/include/asm/global_data.h        |    3 +
>  arch/avr32/include/asm/global_data.h      |    3 +
>  arch/blackfin/include/asm/global_data.h   |    3 +
>  arch/m68k/include/asm/global_data.h       |    3 +
>  arch/microblaze/include/asm/global_data.h |    3 +
>  arch/mips/include/asm/global_data.h       |    3 +
>  arch/nds32/include/asm/global_data.h      |    3 +
>  arch/nios2/include/asm/global_data.h      |    3 +
>  arch/openrisc/include/asm/global_data.h   |    3 +
>  arch/powerpc/include/asm/global_data.h    |    3 +
>  arch/sandbox/include/asm/global_data.h    |    3 +
>  arch/sh/include/asm/global_data.h         |    3 +
>  arch/sparc/include/asm/global_data.h      |    3 +
>  arch/x86/include/asm/global_data.h        |    3 +
>  common/Makefile                           |    1 +
>  common/dmmalloc.c                         |  188 ++++++++++++++++++++++++++++
>  include/dmmalloc.h                        |  194 +++++++++++++++++++++++++++++
>  17 files changed, 425 insertions(+)
>  create mode 100644 common/dmmalloc.c
>  create mode 100644 include/dmmalloc.h
>
> diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
> index 2b9af93..9045829 100644
> --- a/arch/arm/include/asm/global_data.h
> +++ b/arch/arm/include/asm/global_data.h
> @@ -82,6 +82,9 @@ typedef       struct  global_data {
>         unsigned long   post_log_res; /* success of POST test */
>         unsigned long   post_init_f_time; /* When post_init_f started */
>  #endif
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +       void            *early_heap;    /* heap for early_malloc */
> +#endif

Why not early_heap_header *early_heap; ?

 diff --git a/common/Makefile b/common/Makefile
> index fdfead7..bfb4d7a 100644
> --- a/common/Makefile
> +++ b/common/Makefile
> @@ -209,6 +209,7 @@ COBJS-y += dlmalloc.o
>  COBJS-y += image.o
>  COBJS-y += memsize.o
>  COBJS-y += stdio.o
> +COBJS-$(CONFIG_DM) += dmmalloc.o

COBJS-$(CONFIG_SYS_EARLY_MALLOC) += dmmalloc.o ?

>  COBJS  := $(sort $(COBJS-y))
> diff --git a/common/dmmalloc.c b/common/dmmalloc.c
> new file mode 100644
> index 0000000..41589dd
> --- /dev/null
> +++ b/common/dmmalloc.c
> @@ -0,0 +1,188 @@
> +/*
> + * (C) Copyright 2012
> + * Tomas Hlavacek (tmshlvck at gmail.com)
> + *
> + * 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 <common.h> /* for ROUND_UP */
> +#include <asm/u-boot.h>
> +#include <asm/global_data.h> /* for gd_t and gd */
> +#include <asm/types.h> /* for phys_addr_t and size_addt_t */
> +
> +#include <dmmalloc.h>
> +#include <malloc.h>
> +
> +#include <linux/compiler.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC

If you use COBJS-$(CONFIG_SYS_EARLY_MALLOC) += dmmalloc.o in the Makefile,
you can drop this #ifdef

> +__weak struct early_heap_header *early_brk(size_t size)
> +{
> +       struct early_heap_header *h;
> +       struct early_block_header *b;
> +
> +       if (gd->early_heap != NULL)
> +               return NULL;
> +
> +       h = (struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
> +       b = (struct early_block_header *)(h + 1);

Hmmm, does this really work? I would have thought:

b = (struct early_block_header *)(h + sizeof(struct early_heap_header));

but I could be mistaken

> +
> +       size = CONFIG_SYS_EARLY_HEAP_SIZE;
> +       h->size = size;
> +       h->early_heap_next = NULL;
> +       b->size = size - sizeof(struct early_heap_header) -
> +                       sizeof(struct early_block_header);
> +       b->size = BLOCK_SET_FREE(b->size);
> +
> +       return h;
> +}
> +
> +static struct early_block_header *find_free_space(struct early_heap_header *h,
> +                                                       size_t size)
> +{
> +       struct early_block_header *b;
> +
> +       b = (struct early_block_header *)(h+1);
> +       while ((phys_addr_t)b + sizeof(struct early_block_header)
> +                       < (phys_addr_t)h + h->size) {
> +               if (BLOCK_FREE(b->size) && (BLOCK_SIZE(b->size) >= size))
> +                       return b;
> +               b = (struct early_block_header *)((phys_addr_t)b +
> +                               sizeof(struct early_block_header) +
> +                               BLOCK_SIZE(b->size));
> +       }
> +
> +       return NULL;
> +}
> +
> +static struct early_block_header *split_block(struct early_block_header *b,
> +              size_t size)
> +{
> +       struct early_block_header *nb;
> +
> +       if ((BLOCK_SIZE(b->size) < size) || (BLOCK_USED(b->size)))
> +               return NULL;
> +
> +       if (BLOCK_SIZE(b->size) <= (size + sizeof(struct early_block_header)))
> +               return b;
> +
> +       nb = (struct early_block_header *)((phys_addr_t)b +
> +               sizeof(struct early_block_header) + size);
> +       nb->size = b->size - size - sizeof(struct early_block_header);
> +       b->size = size;
> +
> +       return b;
> +}
> +
> +void *early_malloc(size_t size)
> +{
> +       struct early_heap_header *h;
> +       struct early_block_header *b;
> +
> +       size = roundup(size, sizeof(phys_addr_t));
> +       if (size == 0)
> +               return NULL;
> +
> +       if (gd->early_heap == NULL)
> +               gd->early_heap = early_brk(size);
> +
> +       if (gd->early_heap == NULL) {
> +               debug("early_brk failed to initialize heap\n");
> +               return NULL;
> +       }
> +
> +       h = gd->early_heap;
> +       while (1) {
> +               b = find_free_space(h, size);
> +               if (b != NULL)
> +                       break;
> +
> +               if (h->early_heap_next != NULL)
> +                       h = h->early_heap_next;
> +               else
> +                       break;
> +       }
> +
> +       if (b == NULL) {
> +               h->early_heap_next = early_brk(size+
> +                               sizeof(struct early_heap_header)+
> +                               sizeof(struct early_block_header));
> +               h = h->early_heap_next;
> +               if (h == NULL) {
> +                       debug("early_brk failed to extend heap by %d B\n",
> +                                       size);
> +                       return NULL;
> +               }
> +
> +               b = find_free_space(h, size);
> +               if (b == NULL) {
> +                       debug("early_malloc failed to extend heap by %d B\n",
> +                                       size);
> +                       return NULL;
> +               }
> +       }
> +
> +       if (b->size != size)
> +               b = split_block(b, size);
> +       if (b == NULL) {
> +               debug("early_malloc failed to split block to %d B\n", size);
> +               return NULL;
> +       }
> +
> +       b->size = BLOCK_SET_USED(b->size);
> +
> +       return BLOCK_DATA(b);
> +}
> +
> +void early_free(void *addr)
> +{
> +       struct early_block_header *h = BLOCK_HEADER(addr);
> +       assert(BLOCK_USED(h->size));
> +       h->size = BLOCK_SET_FREE(h->size);
> +}
> +
> +int early_malloc_active(void)
> +{
> +       return ((gd->flags & GD_FLG_RELOC) != GD_FLG_RELOC);
> +}

I think we need another flag - GD_FLG_RELOC gets set before the permanent
heap is initialised, so there is a window of opportunity where things may
break

> +
> +void early_heap_dump(struct early_heap_header *h)
> +{
> +       struct early_block_header *b;
> +
> +       debug("heap: h=%p, h->size=%d\n", h, h->size);
> +
> +       b = (struct early_block_header *)(h+1);
> +       while ((phys_addr_t)b + sizeof(struct early_block_header)
> +                       < (phys_addr_t)h + h->size) {
> +               debug("block: h=%p h->size=%d b=%p b->size=%d b->(used)=%d\n",
> +                               h, h->size, b, BLOCK_SIZE(b->size),
> +                               BLOCK_USED(b->size));
> +               assert(BLOCK_SIZE(b->size) > 0);
> +               b = (struct early_block_header *)((phys_addr_t)b +
> +                               sizeof(struct early_block_header) +
> +                               BLOCK_SIZE(b->size));
> +       }
> +       debug("--- heap dump end ---\n");
> +}

Nice touch, but could we just iterate through all ealry heap chunks starting
from gd->early_heap?

> +
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
> diff --git a/include/dmmalloc.h b/include/dmmalloc.h
> new file mode 100644
> index 0000000..a241e19
> --- /dev/null
> +++ b/include/dmmalloc.h
> @@ -0,0 +1,194 @@
> +/*
> + * (C) Copyright 2012
> + * Tomas Hlavacek (tmshlvck at gmail.com)
> + *
> + * 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
> + */
> +
> +#ifndef __INCLUDE_DMMALLOC_H
> +#define __INCLUDE_DMMALLOC_H
> +
> +#include <config.h>
> +#include <linux/stddef.h> /* for size_t */
> +#include <malloc.h>
> +
> +#if (!defined(CONFIG_SYS_EARLY_HEAP_ADDR)) || \
> +       (!defined(CONFIG_SYS_EARLY_HEAP_SIZE))
> +#undef CONFIG_SYS_EARLY_MALLOC
> +#endif /* CONFIG_SYS_EARLY_HEAP_ADDR */

If a board implements early_brk() using non-fixed a address and/or size
then this is going to cause trouble

> +#ifdef CONFIG_SYS_EARLY_MALLOC

I see no need for the #ifdef

> +struct early_heap_header {
> +       size_t size;
> +       void *early_heap_next;
> +};
> +
> +struct early_block_header {
> +       size_t size;
> +};
> +
> +#define BLOCK_DATA(header) ((void *)(((struct early_block_header *)header)+1))
> +#define BLOCK_HEADER(addr) (((struct early_block_header *)addr)-1)

Again, not sure if this is correct. I would have thought:

(struct early_block_header *)(addr - sizeof(struct early_block_header)

And again, not sure if I'm right

> +#define BLOCK_USED_FLAG 0x80000000
> +#define BLOCK_SIZE(size) (size & (~BLOCK_USED_FLAG))
> +#define BLOCK_USED(size) ((size & BLOCK_USED_FLAG) == BLOCK_USED_FLAG)
> +#define BLOCK_FREE(size) (!BLOCK_USED(size))
> +#define BLOCK_SET_FREE(size) BLOCK_SIZE(size)
> +#define BLOCK_SET_USED(size) (size | BLOCK_USED_FLAG)

Hmmm, I'm not sure what the general policy is about where to put 'stuff'
that is only used by the implementation and does not 'need' to be made
publically available. i.e. I don't know if these #defines and the
early_block_header struct belong here or in the .c file...

> +
> +/**
> + * early_brk() - obtain address of the heap
> + * @size:      Minimal size of the new early heap to be allocated.
> + *
> + * Function returns a new heap pointer.
> + *
> + * Allocate and initialize early_heap at least size bytes long.
> + * This function can be platform dependent or board dependent but sensible
> + * default is provided.
> + */
> +struct early_heap_header *early_brk(size_t size);
> +
> +/**
> + * early_malloc() - malloc operating on the early_heap(s)
> + * @size:      Size in bytes.
> + *
> + * Function returns a pointer to the allocated block.
> + */
> +void *early_malloc(size_t size);
> +
> +/**
> + * early_free() - free operating on the early_heap(s)
> + * @addr:      Pointer to the allocated block to be released.
> + */
> +void early_free(void *addr);
> +
> +/**
> + * early_malloc_active() - indicate if the early mallocator is active
> + *
> + * Function returns true when the early_malloc and early_free are used and
> + * false otherwise.
> + */
> +int early_malloc_active(void);
> +
> +/**
> + * early_heap_dump() - print blocks contained in an early_heap
> + * @h:         Address of the early heap.
> + */
> +void early_heap_dump(struct early_heap_header *h);
> +
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
> +#ifdef CONFIG_DM
> +
> +/*
> + * DM versions of malloc* functions. In early init it calls early_malloc.
> + * It wraps around normal malloc* functions afterwards.
> + */

I don't think these _need_ to be inline functions - The compiler should be
smart enough no (non-)inline them as appropriate.

> +
> +/**
> + * dmmalloc() - malloc working seamlessly in early as well as in RAM stages
> + * @size:      Size of the block to be allocated.
> + *
> + * Function returns an address of the newly allocated block when successful
> + * or NULL otherwise.
> + */
> +static inline void *dmmalloc(size_t size)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +       if (early_malloc_active())
> +               return early_malloc(size);
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +       return malloc(size);
> +}
> +
> +/**
> + * dmfree() - free working seamlessly in early as well as in RAM stages
> + * @ptr:       Pointer to the allocated block to be released.
> + */
> +static inline void dmfree(void *ptr)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +       if (early_malloc_active()) {
> +               early_free(ptr);
> +               return;
> +       }
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +       free(ptr);
> +}
> +
> +/**
> + * dmcalloc() - calloc working seamlessly in early as well as in RAM stages
> + * @n:         Number of elements to be allocated.
> + * @elem_size: Size of elements to be allocated.
> + *
> + * Function returns a pointer to newly the allocated area (n*elem_size) long.
> + */
> +static inline void *dmcalloc(size_t n, size_t elem_size)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +       char *addr;
> +       int size = elem_size * n;
> +
> +       if (early_malloc_active()) {
> +               addr = early_malloc(size);
> +               memset(addr, 0, size);
> +               return addr;
> +       }
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +       return calloc(n, elem_size);
> +}
> +
> +/**
> + * dmrealloc() - realloc working seamlessly in early as well as in RAM stages
> + * @oldaddr:   Pointer to the old memory block.
> + * @bytes:     New size to of the block to be reallocated.
> + *
> + * Function returns an address of the newly allocated block when successful
> + * or NULL otherwise.
> + *
> + * Data are copied from the block specified by oldaddr to the new block.
> + */
> +static inline void *dmrealloc(void *oldaddr, size_t bytes)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +       char *addr;
> +       struct early_block_header *h;
> +       if (early_malloc_active()) {
> +               addr = dmmalloc(bytes);
> +               if (addr == NULL)
> +                       return NULL;
> +
> +               h = BLOCK_HEADER(oldaddr);
> +               if (BLOCK_FREE(h->size))
> +                       return NULL;
> +
> +               if (bytes > BLOCK_SIZE(h->size))
> +                       bytes = BLOCK_SIZE(h->size);
> +
> +               memcpy(addr, oldaddr, bytes);
> +               dmfree(oldaddr);
> +               return addr;
> +       }
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +       return realloc(oldaddr, bytes);
> +}

Hmmm, we have a very intersting corner case to deal with. What if we use
dmrealloc() to move allocated data from the early malloc pool to the final
malloc pool?

At some point, we need to assume the developer is only ever going to pass
early malloc'd memory to dmrealloc()

The other option is to use the gd->flags...

Define two flags - something like:

GD_FLG_HEAP_INIT -> Final heap has been initialised
GD_FLG_EH_DONE    -> free(), realloc() refer to final heap

(I don't like the names, I'm just not up to thinking of anything better)

This way we can use dmalloc() prior to the heap being initialised and then
set GD_FLG_HEAP_INIT. Once GD_FLG_HEAP_INIT has been set, do a bunch of
dmrealloc() calls to essentially move the data into the permanent heap (of
course pointers int the structures need to be fixed up by the drivers) and
finally set GD_FLG_EH_DONE (and call early_heap_dump)

One problem I see is what happens of you call malloc() and free() on the
same block between the setting of GD_FLG_HEAP_INIT and GD_FLG_EH_DONE? The
code will try to reference the block as if it is in the early heap, but it
won't be.

One solution is, on detection of GD_FLG_HEAP_INIT being set, dmfree() and
dmrealloc() could search the early heap chunks instead of just assuming
that the referenced block is in the early heap (if GD_FLG_HEAP_INIT has not
been set, it will be safe to assume the memory is on the early heap)

> +
> +#endif /* CONFIG_DM */
> +#endif /* __INCLUDE_DMMALLOC_H */
> +
> --
> 1.7.10.4
>

Regards,

Graeme

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v9] [RFC] Add dmmalloc module for DM.
  2012-10-25  1:40   ` Graeme Russ
@ 2012-10-25 19:16     ` Tomas Hlavacek
  2012-10-25 23:04       ` Graeme Russ
  0 siblings, 1 reply; 48+ messages in thread
From: Tomas Hlavacek @ 2012-10-25 19:16 UTC (permalink / raw)
  To: u-boot

Hello Graeme,

On Thu, Oct 25, 2012 at 3:40 AM, Graeme Russ <graeme.russ@gmail.com> wrote:

>> diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
>> index 2b9af93..9045829 100644
>> --- a/arch/arm/include/asm/global_data.h
>> +++ b/arch/arm/include/asm/global_data.h
>> @@ -82,6 +82,9 @@ typedef       struct  global_data {
>>         unsigned long   post_log_res; /* success of POST test */
>>         unsigned long   post_init_f_time; /* When post_init_f started */
>>  #endif
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> +       void            *early_heap;    /* heap for early_malloc */
>> +#endif
>
> Why not early_heap_header *early_heap; ?
>

It might be.

Actually it is a good point because I am using 3 different ways of
dealing with addresses: 1) struct early_heap header * or struct
early_block_header * - I am using this when I want to access members
of the stucture or compute address past the structure (which is where
the heap or block starts); 2) phys_addr_t - which is plain integer and
I use this for simple computations when I do not want to worry about
pointer arithmetic; 3) void * when I have just plain address,
especially when I want to pass an addres among logical parts of the
mallocator or outside. This may a bit controversial and perhaps I
should replace it by specific strucutre pointers internally.

I am unable to decide: Should I remove struct early_heap_header from
dmmalloc.h making it publicly unavailable or should I rather change
the void * to struct early_heap_header * in the GD structure? What do
you think is better?

>  diff --git a/common/Makefile b/common/Makefile
>> index fdfead7..bfb4d7a 100644
>> --- a/common/Makefile
>> +++ b/common/Makefile
>> @@ -209,6 +209,7 @@ COBJS-y += dlmalloc.o
>>  COBJS-y += image.o
>>  COBJS-y += memsize.o
>>  COBJS-y += stdio.o
>> +COBJS-$(CONFIG_DM) += dmmalloc.o
>
> COBJS-$(CONFIG_SYS_EARLY_MALLOC) += dmmalloc.o ?

Oh yes, now it is redundant to #ifdef CONFIG_SYS_EARLY_MALLOC inside
the dmmalloc.c file. I had a plan to extend the dmmalloc.c file by
relocation routines and then it would make sense. But I will shufle
the code a bit in the v10 anyway and we will see if the #ifdefs can
still be reduced.

>> +
>> +#include <common.h> /* for ROUND_UP */
>> +#include <asm/u-boot.h>
>> +#include <asm/global_data.h> /* for gd_t and gd */
>> +#include <asm/types.h> /* for phys_addr_t and size_addt_t */
>> +
>> +#include <dmmalloc.h>
>> +#include <malloc.h>
>> +
>> +#include <linux/compiler.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>
> If you use COBJS-$(CONFIG_SYS_EARLY_MALLOC) += dmmalloc.o in the Makefile,
> you can drop this #ifdef

Yes, that is redundant now.

>
>> +__weak struct early_heap_header *early_brk(size_t size)
>> +{
>> +       struct early_heap_header *h;
>> +       struct early_block_header *b;
>> +
>> +       if (gd->early_heap != NULL)
>> +               return NULL;
>> +
>> +       h = (struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
>> +       b = (struct early_block_header *)(h + 1);
>
> Hmmm, does this really work? I would have thought:
>
> b = (struct early_block_header *)(h + sizeof(struct early_heap_header));
>
> but I could be mistaken

It seems that it works as it is (at least I wrote bunch of tests and I
inspected resulting heaps and it was all right). I believe that since
h is a pointer to the struct early_heap_header then pointer arithmetic
is in effect and h+1 actually means "next element in the array of
struct early_heap_header". Which is the address past the header that
equals beginning of the heap data block. (?)


>> +int early_malloc_active(void)
>> +{
>> +       return ((gd->flags & GD_FLG_RELOC) != GD_FLG_RELOC);
>> +}
>
> I think we need another flag - GD_FLG_RELOC gets set before the permanent
> heap is initialised, so there is a window of opportunity where things may
> break

Well, as I wrote in the commit message - this is only a temporary
implementation. I suppose I am going to change this when we have more
coarse initialization flags wired into DM (which I believe we are
going to have it anyway). So now I am just working around "forward
dependency" here.

>
>> +
>> +void early_heap_dump(struct early_heap_header *h)
>> +{
>> +       struct early_block_header *b;
>> +
>> +       debug("heap: h=%p, h->size=%d\n", h, h->size);
>> +
>> +       b = (struct early_block_header *)(h+1);
>> +       while ((phys_addr_t)b + sizeof(struct early_block_header)
>> +                       < (phys_addr_t)h + h->size) {
>> +               debug("block: h=%p h->size=%d b=%p b->size=%d b->(used)=%d\n",
>> +                               h, h->size, b, BLOCK_SIZE(b->size),
>> +                               BLOCK_USED(b->size));
>> +               assert(BLOCK_SIZE(b->size) > 0);
>> +               b = (struct early_block_header *)((phys_addr_t)b +
>> +                               sizeof(struct early_block_header) +
>> +                               BLOCK_SIZE(b->size));
>> +       }
>> +       debug("--- heap dump end ---\n");
>> +}
>
> Nice touch, but could we just iterate through all ealry heap chunks starting
> from gd->early_heap?

Or I can have two functions. One heap specific and one for all heaps.
I think both might be useful when somebody needs to debug early_malloc
or memory usage etc. in the early stage. Thanks.

>> +
>> +#ifndef __INCLUDE_DMMALLOC_H
>> +#define __INCLUDE_DMMALLOC_H
>> +
>> +#include <config.h>
>> +#include <linux/stddef.h> /* for size_t */
>> +#include <malloc.h>
>> +
>> +#if (!defined(CONFIG_SYS_EARLY_HEAP_ADDR)) || \
>> +       (!defined(CONFIG_SYS_EARLY_HEAP_SIZE))
>> +#undef CONFIG_SYS_EARLY_MALLOC
>> +#endif /* CONFIG_SYS_EARLY_HEAP_ADDR */
>
> If a board implements early_brk() using non-fixed a address and/or size
> then this is going to cause trouble

Right, I will drop this.

>
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>
> I see no need for the #ifdef
>
>> +struct early_heap_header {
>> +       size_t size;
>> +       void *early_heap_next;
>> +};
>> +
>> +struct early_block_header {
>> +       size_t size;
>> +};
>> +
>
>> +#define BLOCK_USED_FLAG 0x80000000
>> +#define BLOCK_SIZE(size) (size & (~BLOCK_USED_FLAG))
>> +#define BLOCK_USED(size) ((size & BLOCK_USED_FLAG) == BLOCK_USED_FLAG)
>> +#define BLOCK_FREE(size) (!BLOCK_USED(size))
>> +#define BLOCK_SET_FREE(size) BLOCK_SIZE(size)
>> +#define BLOCK_SET_USED(size) (size | BLOCK_USED_FLAG)
>
> Hmmm, I'm not sure what the general policy is about where to put 'stuff'
> that is only used by the implementation and does not 'need' to be made
> publically available. i.e. I don't know if these #defines and the
> early_block_header struct belong here or in the .c file...

You are right, I will put it to the .c.

>
>> +
>> +/**
>> + * early_brk() - obtain address of the heap
>> + * @size:      Minimal size of the new early heap to be allocated.
>> + *
>> + * Function returns a new heap pointer.
>> + *
>> + * Allocate and initialize early_heap at least size bytes long.
>> + * This function can be platform dependent or board dependent but sensible
>> + * default is provided.
>> + */
>> +struct early_heap_header *early_brk(size_t size);
>> +
>> +/**
>> + * early_malloc() - malloc operating on the early_heap(s)
>> + * @size:      Size in bytes.
>> + *
>> + * Function returns a pointer to the allocated block.
>> + */
>> +void *early_malloc(size_t size);
>> +
>> +/**
>> + * early_free() - free operating on the early_heap(s)
>> + * @addr:      Pointer to the allocated block to be released.
>> + */
>> +void early_free(void *addr);
>> +
>> +/**
>> + * early_malloc_active() - indicate if the early mallocator is active
>> + *
>> + * Function returns true when the early_malloc and early_free are used and
>> + * false otherwise.
>> + */
>> +int early_malloc_active(void);
>> +
>> +/**
>> + * early_heap_dump() - print blocks contained in an early_heap
>> + * @h:         Address of the early heap.
>> + */
>> +void early_heap_dump(struct early_heap_header *h);
>> +
>> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>> +
>> +#ifdef CONFIG_DM
>> +
>> +/*
>> + * DM versions of malloc* functions. In early init it calls early_malloc.
>> + * It wraps around normal malloc* functions afterwards.
>> + */
>
> I don't think these _need_ to be inline functions - The compiler should be
> smart enough no (non-)inline them as appropriate.

Yes. Now I am thinking about pulling all this into the .c file and
making the functions non-static. Actually, this "static inline"
evolved from really simple "if(...) early_malloc() else malloc()", but
now it is not always straight-forward and even more future extensions
are expected to these functions due to relocation-related code.

>
>> +
>> +/**
>> + * dmmalloc() - malloc working seamlessly in early as well as in RAM stages
>> + * @size:      Size of the block to be allocated.
>> + *
>> + * Function returns an address of the newly allocated block when successful
>> + * or NULL otherwise.
>> + */
>> +static inline void *dmmalloc(size_t size)
>> +{
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> +       if (early_malloc_active())
>> +               return early_malloc(size);
>> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>> +       return malloc(size);
>> +}
>> +
>> +/**
>> + * dmfree() - free working seamlessly in early as well as in RAM stages
>> + * @ptr:       Pointer to the allocated block to be released.
>> + */
>> +static inline void dmfree(void *ptr)
>> +{
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> +       if (early_malloc_active()) {
>> +               early_free(ptr);
>> +               return;
>> +       }
>> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>> +       free(ptr);
>> +}
>> +
>> +/**
>> + * dmcalloc() - calloc working seamlessly in early as well as in RAM stages
>> + * @n:         Number of elements to be allocated.
>> + * @elem_size: Size of elements to be allocated.
>> + *
>> + * Function returns a pointer to newly the allocated area (n*elem_size) long.
>> + */
>> +static inline void *dmcalloc(size_t n, size_t elem_size)
>> +{
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> +       char *addr;
>> +       int size = elem_size * n;
>> +
>> +       if (early_malloc_active()) {
>> +               addr = early_malloc(size);
>> +               memset(addr, 0, size);
>> +               return addr;
>> +       }
>> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>> +       return calloc(n, elem_size);
>> +}
>> +
>> +/**
>> + * dmrealloc() - realloc working seamlessly in early as well as in RAM stages
>> + * @oldaddr:   Pointer to the old memory block.
>> + * @bytes:     New size to of the block to be reallocated.
>> + *
>> + * Function returns an address of the newly allocated block when successful
>> + * or NULL otherwise.
>> + *
>> + * Data are copied from the block specified by oldaddr to the new block.
>> + */
>> +static inline void *dmrealloc(void *oldaddr, size_t bytes)
>> +{
>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>> +       char *addr;
>> +       struct early_block_header *h;
>> +       if (early_malloc_active()) {
>> +               addr = dmmalloc(bytes);
>> +               if (addr == NULL)
>> +                       return NULL;
>> +
>> +               h = BLOCK_HEADER(oldaddr);
>> +               if (BLOCK_FREE(h->size))
>> +                       return NULL;
>> +
>> +               if (bytes > BLOCK_SIZE(h->size))
>> +                       bytes = BLOCK_SIZE(h->size);
>> +
>> +               memcpy(addr, oldaddr, bytes);
>> +               dmfree(oldaddr);
>> +               return addr;
>> +       }
>> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>> +       return realloc(oldaddr, bytes);
>> +}
>
> Hmmm, we have a very intersting corner case to deal with. What if we use
> dmrealloc() to move allocated data from the early malloc pool to the final
> malloc pool?
>
> At some point, we need to assume the developer is only ever going to pass
> early malloc'd memory to dmrealloc()

Good point! The current code would do the job assuming that the
early_malloc can still access the proper early_heap (or a copy, but in
that case some additional magic is needed) and the real malloc is
already initialized.

As you can see I am still sticking with the double-copy method. It is
maybe due to lack of insight. But the discussion here was not
absolutely conclusive last time. I have even some experimental code
(not ready for submitting at all) for double copy method but I would
prefer to discuss it separately when the early_malloc() is done.

>
> The other option is to use the gd->flags...
>
> Define two flags - something like:
>
> GD_FLG_HEAP_INIT -> Final heap has been initialised
> GD_FLG_EH_DONE    -> free(), realloc() refer to final heap
>
> (I don't like the names, I'm just not up to thinking of anything better)
>
> This way we can use dmalloc() prior to the heap being initialised and then
> set GD_FLG_HEAP_INIT. Once GD_FLG_HEAP_INIT has been set, do a bunch of
> dmrealloc() calls to essentially move the data into the permanent heap (of
> course pointers int the structures need to be fixed up by the drivers) and
> finally set GD_FLG_EH_DONE (and call early_heap_dump)
>
> One problem I see is what happens of you call malloc() and free() on the
> same block between the setting of GD_FLG_HEAP_INIT and GD_FLG_EH_DONE? The
> code will try to reference the block as if it is in the early heap, but it
> won't be.
>
> One solution is, on detection of GD_FLG_HEAP_INIT being set, dmfree() and
> dmrealloc() could search the early heap chunks instead of just assuming
> that the referenced block is in the early heap (if GD_FLG_HEAP_INIT has not
> been set, it will be safe to assume the memory is on the early heap)

Sure we will have that flags. But I think we can use them as well for
switching from DM driver instance list to tree for example. Or other
way around: I can use DM flags for early_malloc. Therefore I would
like to synchronize with DM cores for PCI and another low-level things
which are certainly going to start in early stage. It would be best to
use the same flags and switch on/off early_malloc based on DM internal
state.

Best regards,
Tomas

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v9] [RFC] Add dmmalloc module for DM.
  2012-10-25 19:16     ` Tomas Hlavacek
@ 2012-10-25 23:04       ` Graeme Russ
  0 siblings, 0 replies; 48+ messages in thread
From: Graeme Russ @ 2012-10-25 23:04 UTC (permalink / raw)
  To: u-boot

Hi Tomas,

On Fri, Oct 26, 2012 at 6:16 AM, Tomas Hlavacek <tmshlvck@gmail.com> wrote:
> Hello Graeme,
>
> On Thu, Oct 25, 2012 at 3:40 AM, Graeme Russ <graeme.russ@gmail.com> wrote:
>
>>> diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
>>> index 2b9af93..9045829 100644
>>> --- a/arch/arm/include/asm/global_data.h
>>> +++ b/arch/arm/include/asm/global_data.h
>>> @@ -82,6 +82,9 @@ typedef       struct  global_data {
>>>         unsigned long   post_log_res; /* success of POST test */
>>>         unsigned long   post_init_f_time; /* When post_init_f started */
>>>  #endif
>>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>>> +       void            *early_heap;    /* heap for early_malloc */
>>> +#endif
>>
>> Why not early_heap_header *early_heap; ?
>>
>
> It might be.
>
> Actually it is a good point because I am using 3 different ways of
> dealing with addresses: 1) struct early_heap header * or struct
> early_block_header * - I am using this when I want to access members
> of the stucture or compute address past the structure (which is where
> the heap or block starts); 2) phys_addr_t - which is plain integer and
> I use this for simple computations when I do not want to worry about
> pointer arithmetic; 3) void * when I have just plain address,
> especially when I want to pass an addres among logical parts of the
> mallocator or outside. This may a bit controversial and perhaps I
> should replace it by specific strucutre pointers internally.
>
> I am unable to decide: Should I remove struct early_heap_header from
> dmmalloc.h making it publicly unavailable or should I rather change
> the void * to struct early_heap_header * in the GD structure? What do
> you think is better?

I think struct early_heap_header * in the GD structure is the better way to
go as that is exactly what it is.

[snip]

>>> +       h = (struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
>>> +       b = (struct early_block_header *)(h + 1);
>>
>> Hmmm, does this really work? I would have thought:
>>
>> b = (struct early_block_header *)(h + sizeof(struct early_heap_header));
>>
>> but I could be mistaken
>
> It seems that it works as it is (at least I wrote bunch of tests and I
> inspected resulting heaps and it was all right). I believe that since
> h is a pointer to the struct early_heap_header then pointer arithmetic
> is in effect and h+1 actually means "next element in the array of
> struct early_heap_header". Which is the address past the header that
> equals beginning of the heap data block. (?)

As I said, I could be mistaken - it appears I am :)

>>> +int early_malloc_active(void)
>>> +{
>>> +       return ((gd->flags & GD_FLG_RELOC) != GD_FLG_RELOC);
>>> +}
>>
>> I think we need another flag - GD_FLG_RELOC gets set before the permanent
>> heap is initialised, so there is a window of opportunity where things may
>> break
>
> Well, as I wrote in the commit message - this is only a temporary
> implementation. I suppose I am going to change this when we have more
> coarse initialization flags wired into DM (which I believe we are
> going to have it anyway). So now I am just working around "forward
> dependency" here.
>
>>
>>> +
>>> +void early_heap_dump(struct early_heap_header *h)
>>> +{
>>> +       struct early_block_header *b;
>>> +
>>> +       debug("heap: h=%p, h->size=%d\n", h, h->size);
>>> +
>>> +       b = (struct early_block_header *)(h+1);
>>> +       while ((phys_addr_t)b + sizeof(struct early_block_header)
>>> +                       < (phys_addr_t)h + h->size) {
>>> +               debug("block: h=%p h->size=%d b=%p b->size=%d b->(used)=%d\n",
>>> +                               h, h->size, b, BLOCK_SIZE(b->size),
>>> +                               BLOCK_USED(b->size));
>>> +               assert(BLOCK_SIZE(b->size) > 0);
>>> +               b = (struct early_block_header *)((phys_addr_t)b +
>>> +                               sizeof(struct early_block_header) +
>>> +                               BLOCK_SIZE(b->size));
>>> +       }
>>> +       debug("--- heap dump end ---\n");
>>> +}
>>
>> Nice touch, but could we just iterate through all ealry heap chunks starting
>> from gd->early_heap?
>
> Or I can have two functions. One heap specific and one for all heaps.
> I think both might be useful when somebody needs to debug early_malloc
> or memory usage etc. in the early stage. Thanks.

True, just adding another function which iterates through the heaps and
calls this function would be fine.

[snip]

>>> +static inline void *dmrealloc(void *oldaddr, size_t bytes)
>>> +{
>>> +#ifdef CONFIG_SYS_EARLY_MALLOC
>>> +       char *addr;
>>> +       struct early_block_header *h;
>>> +       if (early_malloc_active()) {
>>> +               addr = dmmalloc(bytes);
>>> +               if (addr == NULL)
>>> +                       return NULL;
>>> +
>>> +               h = BLOCK_HEADER(oldaddr);
>>> +               if (BLOCK_FREE(h->size))
>>> +                       return NULL;
>>> +
>>> +               if (bytes > BLOCK_SIZE(h->size))
>>> +                       bytes = BLOCK_SIZE(h->size);
>>> +
>>> +               memcpy(addr, oldaddr, bytes);
>>> +               dmfree(oldaddr);
>>> +               return addr;
>>> +       }
>>> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>>> +       return realloc(oldaddr, bytes);
>>> +}
>>
>> Hmmm, we have a very intersting corner case to deal with. What if we use
>> dmrealloc() to move allocated data from the early malloc pool to the final
>> malloc pool?
>>
>> At some point, we need to assume the developer is only ever going to pass
>> early malloc'd memory to dmrealloc()
>
> Good point! The current code would do the job assuming that the
> early_malloc can still access the proper early_heap (or a copy, but in
> that case some additional magic is needed) and the real malloc is
> already initialized.
>
> As you can see I am still sticking with the double-copy method. It is
> maybe due to lack of insight. But the discussion here was not
> absolutely conclusive last time. I have even some experimental code
> (not ready for submitting at all) for double copy method but I would
> prefer to discuss it separately when the early_malloc() is done.

Well the double-copy approach to reallocating early-malloc'd memory and
how dmrealloc() is implemented are tightly coupled.

I understand the reason for the double copy is performance related (getting
into a position to enable cache as early as possible), but I wonder how
much will really be gained. It seems to me that the only performance gain
will be for the execution of the driver 'relocation fixup' code wich, I
assume, would not really consume that many CPU cycles.

There is a point where code simplicity outweighs performance gains.

>> The other option is to use the gd->flags...
>>
>> Define two flags - something like:
>>
>> GD_FLG_HEAP_INIT -> Final heap has been initialised
>> GD_FLG_EH_DONE    -> free(), realloc() refer to final heap
>>
>> (I don't like the names, I'm just not up to thinking of anything better)
>>
>> This way we can use dmalloc() prior to the heap being initialised and then
>> set GD_FLG_HEAP_INIT. Once GD_FLG_HEAP_INIT has been set, do a bunch of
>> dmrealloc() calls to essentially move the data into the permanent heap (of
>> course pointers int the structures need to be fixed up by the drivers) and
>> finally set GD_FLG_EH_DONE (and call early_heap_dump)
>>
>> One problem I see is what happens of you call malloc() and free() on the
>> same block between the setting of GD_FLG_HEAP_INIT and GD_FLG_EH_DONE? The
>> code will try to reference the block as if it is in the early heap, but it
>> won't be.
>>
>> One solution is, on detection of GD_FLG_HEAP_INIT being set, dmfree() and
>> dmrealloc() could search the early heap chunks instead of just assuming
>> that the referenced block is in the early heap (if GD_FLG_HEAP_INIT has not
>> been set, it will be safe to assume the memory is on the early heap)
>
> Sure we will have that flags. But I think we can use them as well for
> switching from DM driver instance list to tree for example. Or other
> way around: I can use DM flags for early_malloc. Therefore I would
> like to synchronize with DM cores for PCI and another low-level things
> which are certainly going to start in early stage. It would be best to
> use the same flags and switch on/off early_malloc based on DM internal
> state.

Ah, I see where more performance gains are to be made by switching on cache
earlier - During the reallocation phase, you are switching from the list
based structure (fast for the small number of pre-SDRAM drivers) into the
final tree based structure.

I'm looking at this early malloc code from a much more generic point of
view - I think there are use-cases outside the driver model, so I don't
see a need (rather the opposite) to tie early malloc to the driver model

Regards,

Graeme

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v10] Add dmmalloc module for DM.
  2012-08-27 12:12 [U-Boot] [PATCH 1/1] [RFC] DM: early_malloc for DM added Tomas Hlavacek
                   ` (7 preceding siblings ...)
  2012-10-24 23:49 ` [U-Boot] [PATCH v9] [RFC] Add dmmalloc module for DM Tomas Hlavacek
@ 2012-10-28 23:20 ` Tomas Hlavacek
  2013-11-05 15:26   ` Mateusz Zalega
  8 siblings, 1 reply; 48+ messages in thread
From: Tomas Hlavacek @ 2012-10-28 23:20 UTC (permalink / raw)
  To: u-boot

Add pointer to the first early heap into GD structure.
Implement simple early_malloc and early_free functions.
Prepare for additional heaps and automated heap initialization.
Add temporary early_malloc_active function (to be replaced in future by
more coarse DM init flags).
Add DM specific malloc calls - dmmalloc, dmfree, dmrealloc and dmcalloc.

Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
---
Changes in v10:
   - Change GD type to struct early_heap_header *.
   - Move dmmalloc, dmfree, ... function from .h to dmmalloc.c .
   - Rework early_malloc_active() to use new GD_FLG_HEAP_INIT flag.
   - Add early_heap_active() and GD_FLG_EARLY_HEAP_DONE flag.
   - Rework dmrealloc() and dmfree() to use new flags and support relocation.
   - Rename early_heap_dump() to early_malloc_heap_dump().
   - Add early_malloc_dump.
   - Drop conditional undef CONFIG_SYS_EARLY_MALLOC in dmmalloc.h.
   - Moved struct early_block_header and macros to dmmalloc.c.

Changes in v9:
   - Rework early_malloc to keep track of allocated block size.
   - Add early_free and dmfree functions.
   - Rework dmrealloc.

Changes in v8:
   - Add dmcalloc() implementation.
   - Add comments to function prototypes in dmmalloc.h.

Changes in v7:
   - Rework check of first heap in early_brk().

Changes in v6:
   - Move dmmalloc() and all dm* functions to dmmalloc.h.
   - Fix bool expression in early_malloc_active().

 arch/arm/include/asm/global_data.h        |    8 +
 arch/avr32/include/asm/global_data.h      |    7 +
 arch/blackfin/include/asm/global_data.h   |    6 +
 arch/m68k/include/asm/global_data.h       |    8 +
 arch/microblaze/include/asm/global_data.h |    8 +
 arch/mips/include/asm/global_data.h       |    6 +
 arch/nds32/include/asm/global_data.h      |    8 +
 arch/nios2/include/asm/global_data.h      |    7 +
 arch/openrisc/include/asm/global_data.h   |    8 +
 arch/powerpc/include/asm/global_data.h    |    6 +
 arch/sandbox/include/asm/global_data.h    |    7 +
 arch/sh/include/asm/global_data.h         |    7 +
 arch/sparc/include/asm/global_data.h      |    6 +
 arch/x86/include/asm/global_data.h        |    8 +
 common/Makefile                           |    1 +
 common/dmmalloc.c                         |  297 +++++++++++++++++++++++++++++
 include/asm-generic/global_data_flags.h   |    6 +-
 include/dmmalloc.h                        |  132 +++++++++++++
 18 files changed, 534 insertions(+), 2 deletions(-)
 create mode 100644 common/dmmalloc.c
 create mode 100644 include/dmmalloc.h

diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index 2b9af93..01075dc 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -23,6 +23,11 @@
 
 #ifndef	__ASM_GBL_DATA_H
 #define __ASM_GBL_DATA_H
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+#include <dmmalloc.h>
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 /*
  * The following data structure is placed in some memory which is
  * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
@@ -82,6 +87,9 @@ typedef	struct	global_data {
 	unsigned long	post_log_res; /* success of POST test */
 	unsigned long	post_init_f_time; /* When post_init_f started */
 #endif
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	struct early_heap_header *early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/avr32/include/asm/global_data.h b/arch/avr32/include/asm/global_data.h
index bf661e2..ba9cf0e 100644
--- a/arch/avr32/include/asm/global_data.h
+++ b/arch/avr32/include/asm/global_data.h
@@ -22,6 +22,10 @@
 #ifndef __ASM_GLOBAL_DATA_H__
 #define __ASM_GLOBAL_DATA_H__
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+#include <dmmalloc.h>
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 /*
  * The following data structure is placed in some memory wich is
  * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
@@ -48,6 +52,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	struct early_heap_header *early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/blackfin/include/asm/global_data.h b/arch/blackfin/include/asm/global_data.h
index d91e5a4..daeb314 100644
--- a/arch/blackfin/include/asm/global_data.h
+++ b/arch/blackfin/include/asm/global_data.h
@@ -29,6 +29,9 @@
 #define __ASM_GBL_DATA_H
 
 #include <asm/u-boot.h>
+#ifdef CONFIG_SYS_EARLY_MALLOC
+#include <dmmalloc.h>
+#endif /* CONFIG_SYS_EARLY_MALLOC */
 
 /*
  * The following data structure is placed in some memory wich is
@@ -57,6 +60,9 @@ typedef struct global_data {
 
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	struct early_heap_header *early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h
index 0cdb11c..dad2ba5 100644
--- a/arch/m68k/include/asm/global_data.h
+++ b/arch/m68k/include/asm/global_data.h
@@ -23,6 +23,11 @@
 
 #ifndef	__ASM_GBL_DATA_H
 #define __ASM_GBL_DATA_H
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+#include <dmmalloc.h>
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 /*
  * The following data structure is placed in some memory wich is
  * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
@@ -66,6 +71,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	struct early_heap_header *early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/microblaze/include/asm/global_data.h b/arch/microblaze/include/asm/global_data.h
index 2111c7c..f6609b8 100644
--- a/arch/microblaze/include/asm/global_data.h
+++ b/arch/microblaze/include/asm/global_data.h
@@ -24,6 +24,11 @@
 
 #ifndef	__ASM_GBL_DATA_H
 #define __ASM_GBL_DATA_H
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+#include <dmmalloc.h>
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 /*
  * The following data structure is placed in some memory wich is
  * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
@@ -46,6 +51,9 @@ typedef	struct	global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	struct early_heap_header *early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h
index a735a8a..c9b76f6 100644
--- a/arch/mips/include/asm/global_data.h
+++ b/arch/mips/include/asm/global_data.h
@@ -25,6 +25,9 @@
 #define __ASM_GBL_DATA_H
 
 #include <asm/regdef.h>
+#ifdef CONFIG_SYS_EARLY_MALLOC
+#include <dmmalloc.h>
+#endif /* CONFIG_SYS_EARLY_MALLOC */
 
 /*
  * The following data structure is placed in some memory wich is
@@ -59,6 +62,9 @@ typedef	struct	global_data {
 	unsigned long	env_valid;	/* Checksum of Environment valid? */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	struct early_heap_header *early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/nds32/include/asm/global_data.h b/arch/nds32/include/asm/global_data.h
index b1feb2c..6d972c2 100644
--- a/arch/nds32/include/asm/global_data.h
+++ b/arch/nds32/include/asm/global_data.h
@@ -33,6 +33,11 @@
 
 #ifndef	__ASM_GBL_DATA_H
 #define __ASM_GBL_DATA_H
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+#include <dmmalloc.h>
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 /*
  * The following data structure is placed in some memory wich is
  * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
@@ -63,6 +68,9 @@ typedef	struct global_data {
 
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	struct early_heap_header *early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/nios2/include/asm/global_data.h b/arch/nios2/include/asm/global_data.h
index 413b485..441e566 100644
--- a/arch/nios2/include/asm/global_data.h
+++ b/arch/nios2/include/asm/global_data.h
@@ -23,6 +23,10 @@
 #ifndef	__ASM_NIOS2_GLOBALDATA_H_
 #define __ASM_NIOS2_GLOBALDATA_H_
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+#include <dmmalloc.h>
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 typedef	struct	global_data {
 	bd_t		*bd;
 	unsigned long	flags;
@@ -42,6 +46,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	struct early_heap_header *early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/openrisc/include/asm/global_data.h b/arch/openrisc/include/asm/global_data.h
index 96f3f1c..94fcef1 100644
--- a/arch/openrisc/include/asm/global_data.h
+++ b/arch/openrisc/include/asm/global_data.h
@@ -24,6 +24,11 @@
 
 #ifndef __ASM_GBL_DATA_H
 #define __ASM_GBL_DATA_H
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+#include <dmmalloc.h>
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 /*
  * The following data structure is placed in some memory wich is
  * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
@@ -44,6 +49,9 @@ typedef struct global_data {
 	unsigned long	fb_base;	/* base address of frame buffer */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	struct early_heap_header *early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h
index 374fc6d..ed67bfd 100644
--- a/arch/powerpc/include/asm/global_data.h
+++ b/arch/powerpc/include/asm/global_data.h
@@ -26,6 +26,9 @@
 
 #include "config.h"
 #include "asm/types.h"
+#ifdef CONFIG_SYS_EARLY_MALLOC
+#include <dmmalloc.h>
+#endif /* CONFIG_SYS_EARLY_MALLOC */
 
 /*
  * The following data structure is placed in some memory wich is
@@ -182,6 +185,9 @@ typedef	struct	global_data {
 #endif
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	struct early_heap_header *early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h
index 78a751d..0d4b4b0 100644
--- a/arch/sandbox/include/asm/global_data.h
+++ b/arch/sandbox/include/asm/global_data.h
@@ -33,6 +33,10 @@
  * up the memory controller so that we can use RAM).
  */
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+#include <dmmalloc.h>
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 typedef	struct global_data {
 	bd_t		*bd;
 	unsigned long	flags;
@@ -46,6 +50,9 @@ typedef	struct global_data {
 	const void	*fdt_blob;	/* Our device tree, NULL if none */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	struct early_heap_header *early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sh/include/asm/global_data.h b/arch/sh/include/asm/global_data.h
index 9a2c193..acacae7 100644
--- a/arch/sh/include/asm/global_data.h
+++ b/arch/sh/include/asm/global_data.h
@@ -27,6 +27,10 @@
 #ifndef	__ASM_SH_GLOBALDATA_H_
 #define __ASM_SH_GLOBALDATA_H_
 
+#ifdef CONFIG_SYS_EARLY_MALLOC
+#include <dmmalloc.h>
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 typedef	struct global_data
 {
 	bd_t		*bd;
@@ -42,6 +46,9 @@ typedef	struct global_data
 	unsigned long	env_valid;	/* Checksum of Environment valid */
 	void		**jt;		/* Standalone app jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	struct early_heap_header *early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/sparc/include/asm/global_data.h b/arch/sparc/include/asm/global_data.h
index aa63b35..aad97e1 100644
--- a/arch/sparc/include/asm/global_data.h
+++ b/arch/sparc/include/asm/global_data.h
@@ -28,6 +28,9 @@
 #define __ASM_GBL_DATA_H
 
 #include "asm/types.h"
+#ifdef CONFIG_SYS_EARLY_MALLOC
+#include <dmmalloc.h>
+#endif /* CONFIG_SYS_EARLY_MALLOC */
 
 /*
  * The following data structure is placed in some memory wich is
@@ -74,6 +77,9 @@ typedef struct global_data {
 #endif
 	void	**jt;			/* jump table */
 	char	env_buf[32];		/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	struct early_heap_header *early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 #include <asm-generic/global_data_flags.h>
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index bce999f..9eff403 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -23,6 +23,11 @@
 
 #ifndef	__ASM_GBL_DATA_H
 #define __ASM_GBL_DATA_H
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+#include <dmmalloc.h>
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
 /*
  * The following data structure is placed in some memory wich is
  * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
@@ -57,6 +62,9 @@ typedef	struct global_data {
 	unsigned long	reset_status;	/* reset status register at boot */
 	void		**jt;		/* jump table */
 	char		env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	struct early_heap_header *early_heap;	/* heap for early_malloc */
+#endif
 } gd_t;
 
 static inline gd_t *get_fs_gd_ptr(void)
diff --git a/common/Makefile b/common/Makefile
index fdfead7..bfb4d7a 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -209,6 +209,7 @@ COBJS-y += dlmalloc.o
 COBJS-y += image.o
 COBJS-y += memsize.o
 COBJS-y += stdio.o
+COBJS-$(CONFIG_DM) += dmmalloc.o
 
 
 COBJS	:= $(sort $(COBJS-y))
diff --git a/common/dmmalloc.c b/common/dmmalloc.c
new file mode 100644
index 0000000..4a1a241
--- /dev/null
+++ b/common/dmmalloc.c
@@ -0,0 +1,297 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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 <common.h> /* for ROUND_UP */
+#include <asm/u-boot.h>
+#include <asm/global_data.h> /* for gd_t and gd */
+#include <asm/types.h> /* for phys_addr_t and size_addt_t */
+
+#include <dmmalloc.h>
+#include <malloc.h>
+
+#include <linux/compiler.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+
+struct early_block_header {
+	size_t size;
+};
+
+#define BLOCK_DATA(header) ((void *)(((struct early_block_header *)header)+1))
+#define BLOCK_HEADER(addr) (((struct early_block_header *)addr)-1)
+#define BLOCK_USED_FLAG 0x80000000
+#define BLOCK_SIZE(size) (size & (~BLOCK_USED_FLAG))
+#define BLOCK_USED(size) ((size & BLOCK_USED_FLAG) == BLOCK_USED_FLAG)
+#define BLOCK_FREE(size) (!BLOCK_USED(size))
+#define BLOCK_SET_FREE(size) BLOCK_SIZE(size)
+#define BLOCK_SET_USED(size) (size | BLOCK_USED_FLAG)
+
+
+__weak struct early_heap_header *early_brk(size_t size)
+{
+	struct early_heap_header *h;
+	struct early_block_header *b;
+
+	if (gd->early_heap != NULL)
+		return NULL;
+
+	h = (struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
+	b = (struct early_block_header *)(h + 1);
+
+	size = CONFIG_SYS_EARLY_HEAP_SIZE;
+	h->size = size;
+	h->early_heap_next = NULL;
+	b->size = size - sizeof(struct early_heap_header) -
+			sizeof(struct early_block_header);
+	b->size = BLOCK_SET_FREE(b->size);
+
+	return h;
+}
+
+static struct early_block_header *find_free_space(struct early_heap_header *h,
+							size_t size)
+{
+	struct early_block_header *b;
+
+	b = (struct early_block_header *)(h+1);
+	while ((phys_addr_t)b + sizeof(struct early_block_header)
+			< (phys_addr_t)h + h->size) {
+		if (BLOCK_FREE(b->size) && (BLOCK_SIZE(b->size) >= size))
+			return b;
+		b = (struct early_block_header *)((phys_addr_t)b +
+				sizeof(struct early_block_header) +
+				BLOCK_SIZE(b->size));
+	}
+
+	return NULL;
+}
+
+static struct early_block_header *split_block(struct early_block_header *b,
+	       size_t size)
+{
+	struct early_block_header *nb;
+
+	if ((BLOCK_SIZE(b->size) < size) || (BLOCK_USED(b->size)))
+		return NULL;
+
+	if (BLOCK_SIZE(b->size) <= (size + sizeof(struct early_block_header)))
+		return b;
+
+	nb = (struct early_block_header *)((phys_addr_t)b +
+		sizeof(struct early_block_header) + size);
+	nb->size = b->size - size - sizeof(struct early_block_header);
+	b->size = size;
+
+	return b;
+}
+
+void *early_malloc(size_t size)
+{
+	struct early_heap_header *h;
+	struct early_block_header *b;
+
+	size = roundup(size, sizeof(phys_addr_t));
+	if (size == 0)
+		return NULL;
+
+	if (gd->early_heap == NULL)
+		gd->early_heap = early_brk(size);
+
+	if (gd->early_heap == NULL) {
+		debug("early_brk failed to initialize heap\n");
+		return NULL;
+	}
+
+	h = gd->early_heap;
+	while (1) {
+		b = find_free_space(h, size);
+		if (b != NULL)
+			break;
+
+		if (h->early_heap_next != NULL)
+			h = h->early_heap_next;
+		else
+			break;
+	}
+
+	if (b == NULL) {
+		h->early_heap_next = early_brk(size+
+				sizeof(struct early_heap_header)+
+				sizeof(struct early_block_header));
+		h = h->early_heap_next;
+		if (h == NULL) {
+			debug("early_brk failed to extend heap by %d B\n",
+					size);
+			return NULL;
+		}
+
+		b = find_free_space(h, size);
+		if (b == NULL) {
+			debug("early_malloc failed to extend heap by %d B\n",
+					size);
+			return NULL;
+		}
+	}
+
+	if (b->size != size)
+		b = split_block(b, size);
+	if (b == NULL) {
+		debug("early_malloc failed to split block to %d B\n", size);
+		return NULL;
+	}
+
+	b->size = BLOCK_SET_USED(b->size);
+
+	return BLOCK_DATA(b);
+}
+
+void early_free(void *addr)
+{
+	struct early_block_header *h = BLOCK_HEADER(addr);
+	assert(BLOCK_USED(h->size));
+	h->size = BLOCK_SET_FREE(h->size);
+}
+
+void early_malloc_heap_dump(struct early_heap_header *h)
+{
+	struct early_block_header *b;
+
+	debug("heap: h=%p, h->size=%d\n", h, h->size);
+
+	b = (struct early_block_header *)(h+1);
+	while ((phys_addr_t)b + sizeof(struct early_block_header)
+			< (phys_addr_t)h + h->size) {
+		debug("block: h=%p h->size=%d b=%p b->size=%d b->(used)=%d\n",
+				h, h->size, b, BLOCK_SIZE(b->size),
+				BLOCK_USED(b->size));
+		assert(BLOCK_SIZE(b->size) > 0);
+		b = (struct early_block_header *)((phys_addr_t)b +
+				sizeof(struct early_block_header) +
+				BLOCK_SIZE(b->size));
+	}
+	debug("--- heap dump end ---\n");
+}
+
+void early_malloc_dump(void)
+{
+	struct early_heap_header *h = gd->early_heap;
+	while (h != NULL) {
+		early_malloc_heap_dump(h);
+		h = h->early_heap_next;
+	}
+}
+
+static int early_malloc_active(void)
+{
+	return ((gd->flags & GD_FLG_HEAP_INIT) != GD_FLG_HEAP_INIT);
+}
+
+static int early_heap_active(void)
+{
+	return ((gd->flags & GD_FLG_EARLY_HEAP_DONE) !=
+			GD_FLG_EARLY_HEAP_DONE);
+}
+
+static int early_address(void *ptr)
+{
+	struct early_heap_header *h = gd->early_heap;
+	while (h != NULL) {
+		if (((phys_addr_t)ptr >= (phys_addr_t)h) &&
+				((phys_addr_t)ptr < (phys_addr_t)h + h->size))
+			return 1;
+
+		h = h->early_heap_next;
+	}
+
+	return 0;
+}
+
+
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+
+void *dmmalloc(size_t size)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_malloc_active())
+		return early_malloc(size);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return malloc(size);
+}
+
+void dmfree(void *ptr)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	if (early_heap_active()) {
+		if (early_address(ptr))
+			early_free(ptr);
+		return;
+	}
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	free(ptr);
+}
+
+void *dmcalloc(size_t n, size_t elem_size)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	char *addr;
+	int size = elem_size * n;
+
+	if (early_malloc_active()) {
+		addr = early_malloc(size);
+		memset(addr, 0, size);
+		return addr;
+	}
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return calloc(n, elem_size);
+}
+
+void *dmrealloc(void *oldaddr, size_t bytes)
+{
+#ifdef CONFIG_SYS_EARLY_MALLOC
+	char *addr;
+	struct early_block_header *h;
+
+	if (early_heap_active() && early_address(oldaddr)) {
+		addr = dmmalloc(bytes);
+		if (addr == NULL)
+			return NULL;
+
+		h = BLOCK_HEADER(oldaddr);
+		if (BLOCK_FREE(h->size))
+			return NULL;
+
+		if (bytes > BLOCK_SIZE(h->size))
+			bytes = BLOCK_SIZE(h->size);
+
+		memcpy(addr, oldaddr, bytes);
+		dmfree(oldaddr);
+		return addr;
+	}
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+	return realloc(oldaddr, bytes);
+}
+
diff --git a/include/asm-generic/global_data_flags.h b/include/asm-generic/global_data_flags.h
index bb57fb6..97db2c2 100644
--- a/include/asm-generic/global_data_flags.h
+++ b/include/asm-generic/global_data_flags.h
@@ -13,8 +13,8 @@
 /*
  * Global Data Flags
  *
- * Note: The low 16 bits are expected for common code.  If your arch
- *       really needs to add your own, use the high 16bits.
+ * Note: The low 18 bits are expected for common code.  If your arch
+ *       really needs to add your own, use the high 14 bits.
  */
 #define GD_FLG_RELOC		0x0001	/* Code was relocated to RAM */
 #define GD_FLG_DEVINIT		0x0002	/* Devices have been initialized */
@@ -24,5 +24,7 @@
 #define GD_FLG_LOGINIT		0x0020	/* Log Buffer has been initialized */
 #define GD_FLG_DISABLE_CONSOLE	0x0040	/* Disable console (in & out) */
 #define GD_FLG_ENV_READY	0x0080	/* Environment imported into hash table */
+#define GD_FLG_HEAP_INIT	0x0100	/* malloc() in RAM is available */
+#define GD_FLG_EARLY_HEAP_DONE	0x0200	/* early_malloc() heap relocated. */
 
 #endif
diff --git a/include/dmmalloc.h b/include/dmmalloc.h
new file mode 100644
index 0000000..c99f423
--- /dev/null
+++ b/include/dmmalloc.h
@@ -0,0 +1,132 @@
+/*
+ * (C) Copyright 2012
+ * Tomas Hlavacek (tmshlvck at gmail.com)
+ *
+ * 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
+ */
+
+#ifndef __INCLUDE_DMMALLOC_H
+#define __INCLUDE_DMMALLOC_H
+
+#include <config.h>
+#include <linux/stddef.h> /* for size_t */
+#include <malloc.h>
+
+#ifdef CONFIG_SYS_EARLY_MALLOC
+
+/**
+ * struct early_heap_header - header preceding an early heap
+ * @size - length of the heap in bytes (including the heap header).
+ * @early_heap_next - pointer to the following heap.
+ *
+ * Heaps are organized in the single direction linked list. Each heap
+ * contains own size. Pointer to the first (left-most) heap is
+ * contained in global data.
+ */
+struct early_heap_header {
+	size_t size;
+	void *early_heap_next;
+};
+
+/**
+ * early_brk() - obtain address of the heap
+ * @size:	Minimal size of the new early heap to be allocated.
+ *
+ * Function returns a new heap pointer.
+ *
+ * Allocate and initialize early_heap at least size bytes long.
+ * This function can be platform dependent or board dependent but sensible
+ * default is provided.
+ */
+struct early_heap_header *early_brk(size_t size);
+
+/**
+ * early_malloc() - malloc operating on the early_heap(s)
+ * @size:	Size in bytes.
+ *
+ * Function returns a pointer to the allocated block.
+ */
+void *early_malloc(size_t size);
+
+/**
+ * early_free() - free operating on the early_heap(s)
+ * @addr:	Pointer to the allocated block to be released.
+ */
+void early_free(void *addr);
+
+/**
+ * early_malloc_heap_dump() - print blocks contained in an early_heap
+ * @h:		Address of the early heap.
+ */
+void early_malloc_heap_dump(struct early_heap_header *h);
+
+/**
+ * early_malloc_dump() - print blocks contained in all early_heaps
+ */
+void early_malloc_dump(void);
+
+
+#endif /* CONFIG_SYS_EARLY_MALLOC */
+
+#ifdef CONFIG_DM
+
+/*
+ * DM versions of malloc* functions. In early init it calls early_malloc.
+ * It wraps around normal malloc* functions afterwards.
+ */
+
+/**
+ * dmmalloc() - malloc working seamlessly in early as well as in RAM stages
+ * @size:	Size of the block to be allocated.
+ *
+ * Function returns an address of the newly allocated block when successful
+ * or NULL otherwise.
+ */
+void *dmmalloc(size_t size);
+
+/**
+ * dmfree() - free working seamlessly in early as well as in RAM stages
+ * @ptr:	Pointer to the allocated block to be released.
+ */
+void dmfree(void *ptr);
+
+/**
+ * dmcalloc() - calloc working seamlessly in early as well as in RAM stages
+ * @n:		Number of elements to be allocated.
+ * @elem_size:	Size of elements to be allocated.
+ *
+ * Function returns a pointer to newly the allocated area (n*elem_size) long.
+ */
+void *dmcalloc(size_t n, size_t elem_size);
+
+/**
+ * dmrealloc() - realloc working seamlessly in early as well as in RAM stages
+ * @oldaddr:	Pointer to the old memory block.
+ * @bytes:	New size to of the block to be reallocated.
+ *
+ * Function returns an address of the newly allocated block when successful
+ * or NULL otherwise.
+ *
+ * Data are copied from the block specified by oldaddr to the new block.
+ */
+void *dmrealloc(void *oldaddr, size_t bytes);
+
+#endif /* CONFIG_DM */
+#endif /* __INCLUDE_DMMALLOC_H */
+
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v10] Add dmmalloc module for DM.
  2012-10-28 23:20 ` [U-Boot] [PATCH v10] " Tomas Hlavacek
@ 2013-11-05 15:26   ` Mateusz Zalega
  2013-11-05 17:17     ` Tom Rini
  0 siblings, 1 reply; 48+ messages in thread
From: Mateusz Zalega @ 2013-11-05 15:26 UTC (permalink / raw)
  To: u-boot

On 10/29/12 00:20, Tomas Hlavacek wrote:
> Add pointer to the first early heap into GD structure.
> Implement simple early_malloc and early_free functions.
> Prepare for additional heaps and automated heap initialization.
> Add temporary early_malloc_active function (to be replaced in future by
> more coarse DM init flags).
> Add DM specific malloc calls - dmmalloc, dmfree, dmrealloc and dmcalloc.
> 
> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
> ---
> Changes in v10:
>    - Change GD type to struct early_heap_header *.
>    - Move dmmalloc, dmfree, ... function from .h to dmmalloc.c .
>    - Rework early_malloc_active() to use new GD_FLG_HEAP_INIT flag.
>    - Add early_heap_active() and GD_FLG_EARLY_HEAP_DONE flag.
>    - Rework dmrealloc() and dmfree() to use new flags and support relocation.
>    - Rename early_heap_dump() to early_malloc_heap_dump().
>    - Add early_malloc_dump.
>    - Drop conditional undef CONFIG_SYS_EARLY_MALLOC in dmmalloc.h.
>    - Moved struct early_block_header and macros to dmmalloc.c.
> 
> Changes in v9:
>    - Rework early_malloc to keep track of allocated block size.
>    - Add early_free and dmfree functions.
>    - Rework dmrealloc.
> 
> Changes in v8:
>    - Add dmcalloc() implementation.
>    - Add comments to function prototypes in dmmalloc.h.
> 
> Changes in v7:
>    - Rework check of first heap in early_brk().
> 
> Changes in v6:
>    - Move dmmalloc() and all dm* functions to dmmalloc.h.
>    - Fix bool expression in early_malloc_active().
> 
>  arch/arm/include/asm/global_data.h        |    8 +
>  arch/avr32/include/asm/global_data.h      |    7 +
>  arch/blackfin/include/asm/global_data.h   |    6 +
>  arch/m68k/include/asm/global_data.h       |    8 +
>  arch/microblaze/include/asm/global_data.h |    8 +
>  arch/mips/include/asm/global_data.h       |    6 +
>  arch/nds32/include/asm/global_data.h      |    8 +
>  arch/nios2/include/asm/global_data.h      |    7 +
>  arch/openrisc/include/asm/global_data.h   |    8 +
>  arch/powerpc/include/asm/global_data.h    |    6 +
>  arch/sandbox/include/asm/global_data.h    |    7 +
>  arch/sh/include/asm/global_data.h         |    7 +
>  arch/sparc/include/asm/global_data.h      |    6 +
>  arch/x86/include/asm/global_data.h        |    8 +
>  common/Makefile                           |    1 +
>  common/dmmalloc.c                         |  297 +++++++++++++++++++++++++++++
>  include/asm-generic/global_data_flags.h   |    6 +-
>  include/dmmalloc.h                        |  132 +++++++++++++
>  18 files changed, 534 insertions(+), 2 deletions(-)
>  create mode 100644 common/dmmalloc.c
>  create mode 100644 include/dmmalloc.h
> 
> diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
> index 2b9af93..01075dc 100644
> --- a/arch/arm/include/asm/global_data.h
> +++ b/arch/arm/include/asm/global_data.h
> @@ -23,6 +23,11 @@
>  
>  #ifndef	__ASM_GBL_DATA_H
>  #define __ASM_GBL_DATA_H
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  /*
>   * The following data structure is placed in some memory which is
>   * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
> @@ -82,6 +87,9 @@ typedef	struct	global_data {
>  	unsigned long	post_log_res; /* success of POST test */
>  	unsigned long	post_init_f_time; /* When post_init_f started */
>  #endif
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/avr32/include/asm/global_data.h b/arch/avr32/include/asm/global_data.h
> index bf661e2..ba9cf0e 100644
> --- a/arch/avr32/include/asm/global_data.h
> +++ b/arch/avr32/include/asm/global_data.h
> @@ -22,6 +22,10 @@
>  #ifndef __ASM_GLOBAL_DATA_H__
>  #define __ASM_GLOBAL_DATA_H__
>  
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  /*
>   * The following data structure is placed in some memory wich is
>   * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
> @@ -48,6 +52,9 @@ typedef	struct	global_data {
>  #endif
>  	void		**jt;		/* jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/blackfin/include/asm/global_data.h b/arch/blackfin/include/asm/global_data.h
> index d91e5a4..daeb314 100644
> --- a/arch/blackfin/include/asm/global_data.h
> +++ b/arch/blackfin/include/asm/global_data.h
> @@ -29,6 +29,9 @@
>  #define __ASM_GBL_DATA_H
>  
>  #include <asm/u-boot.h>
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>  
>  /*
>   * The following data structure is placed in some memory wich is
> @@ -57,6 +60,9 @@ typedef struct global_data {
>  
>  	void	**jt;			/* jump table */
>  	char	env_buf[32];		/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h
> index 0cdb11c..dad2ba5 100644
> --- a/arch/m68k/include/asm/global_data.h
> +++ b/arch/m68k/include/asm/global_data.h
> @@ -23,6 +23,11 @@
>  
>  #ifndef	__ASM_GBL_DATA_H
>  #define __ASM_GBL_DATA_H
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  /*
>   * The following data structure is placed in some memory wich is
>   * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
> @@ -66,6 +71,9 @@ typedef	struct	global_data {
>  #endif
>  	void		**jt;		/* Standalone app jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/microblaze/include/asm/global_data.h b/arch/microblaze/include/asm/global_data.h
> index 2111c7c..f6609b8 100644
> --- a/arch/microblaze/include/asm/global_data.h
> +++ b/arch/microblaze/include/asm/global_data.h
> @@ -24,6 +24,11 @@
>  
>  #ifndef	__ASM_GBL_DATA_H
>  #define __ASM_GBL_DATA_H
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  /*
>   * The following data structure is placed in some memory wich is
>   * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
> @@ -46,6 +51,9 @@ typedef	struct	global_data {
>  	unsigned long	fb_base;	/* base address of frame buffer */
>  	void		**jt;		/* jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h
> index a735a8a..c9b76f6 100644
> --- a/arch/mips/include/asm/global_data.h
> +++ b/arch/mips/include/asm/global_data.h
> @@ -25,6 +25,9 @@
>  #define __ASM_GBL_DATA_H
>  
>  #include <asm/regdef.h>
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>  
>  /*
>   * The following data structure is placed in some memory wich is
> @@ -59,6 +62,9 @@ typedef	struct	global_data {
>  	unsigned long	env_valid;	/* Checksum of Environment valid? */
>  	void		**jt;		/* jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/nds32/include/asm/global_data.h b/arch/nds32/include/asm/global_data.h
> index b1feb2c..6d972c2 100644
> --- a/arch/nds32/include/asm/global_data.h
> +++ b/arch/nds32/include/asm/global_data.h
> @@ -33,6 +33,11 @@
>  
>  #ifndef	__ASM_GBL_DATA_H
>  #define __ASM_GBL_DATA_H
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  /*
>   * The following data structure is placed in some memory wich is
>   * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
> @@ -63,6 +68,9 @@ typedef	struct global_data {
>  
>  	void		**jt;		/* jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/nios2/include/asm/global_data.h b/arch/nios2/include/asm/global_data.h
> index 413b485..441e566 100644
> --- a/arch/nios2/include/asm/global_data.h
> +++ b/arch/nios2/include/asm/global_data.h
> @@ -23,6 +23,10 @@
>  #ifndef	__ASM_NIOS2_GLOBALDATA_H_
>  #define __ASM_NIOS2_GLOBALDATA_H_
>  
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  typedef	struct	global_data {
>  	bd_t		*bd;
>  	unsigned long	flags;
> @@ -42,6 +46,9 @@ typedef	struct	global_data {
>  #endif
>  	void		**jt;		/* Standalone app jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/openrisc/include/asm/global_data.h b/arch/openrisc/include/asm/global_data.h
> index 96f3f1c..94fcef1 100644
> --- a/arch/openrisc/include/asm/global_data.h
> +++ b/arch/openrisc/include/asm/global_data.h
> @@ -24,6 +24,11 @@
>  
>  #ifndef __ASM_GBL_DATA_H
>  #define __ASM_GBL_DATA_H
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  /*
>   * The following data structure is placed in some memory wich is
>   * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
> @@ -44,6 +49,9 @@ typedef struct global_data {
>  	unsigned long	fb_base;	/* base address of frame buffer */
>  	void		**jt;		/* jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h
> index 374fc6d..ed67bfd 100644
> --- a/arch/powerpc/include/asm/global_data.h
> +++ b/arch/powerpc/include/asm/global_data.h
> @@ -26,6 +26,9 @@
>  
>  #include "config.h"
>  #include "asm/types.h"
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>  
>  /*
>   * The following data structure is placed in some memory wich is
> @@ -182,6 +185,9 @@ typedef	struct	global_data {
>  #endif
>  	void		**jt;		/* jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h
> index 78a751d..0d4b4b0 100644
> --- a/arch/sandbox/include/asm/global_data.h
> +++ b/arch/sandbox/include/asm/global_data.h
> @@ -33,6 +33,10 @@
>   * up the memory controller so that we can use RAM).
>   */
>  
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  typedef	struct global_data {
>  	bd_t		*bd;
>  	unsigned long	flags;
> @@ -46,6 +50,9 @@ typedef	struct global_data {
>  	const void	*fdt_blob;	/* Our device tree, NULL if none */
>  	void		**jt;		/* jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/sh/include/asm/global_data.h b/arch/sh/include/asm/global_data.h
> index 9a2c193..acacae7 100644
> --- a/arch/sh/include/asm/global_data.h
> +++ b/arch/sh/include/asm/global_data.h
> @@ -27,6 +27,10 @@
>  #ifndef	__ASM_SH_GLOBALDATA_H_
>  #define __ASM_SH_GLOBALDATA_H_
>  
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  typedef	struct global_data
>  {
>  	bd_t		*bd;
> @@ -42,6 +46,9 @@ typedef	struct global_data
>  	unsigned long	env_valid;	/* Checksum of Environment valid */
>  	void		**jt;		/* Standalone app jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/sparc/include/asm/global_data.h b/arch/sparc/include/asm/global_data.h
> index aa63b35..aad97e1 100644
> --- a/arch/sparc/include/asm/global_data.h
> +++ b/arch/sparc/include/asm/global_data.h
> @@ -28,6 +28,9 @@
>  #define __ASM_GBL_DATA_H
>  
>  #include "asm/types.h"
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>  
>  /*
>   * The following data structure is placed in some memory wich is
> @@ -74,6 +77,9 @@ typedef struct global_data {
>  #endif
>  	void	**jt;			/* jump table */
>  	char	env_buf[32];		/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
> index bce999f..9eff403 100644
> --- a/arch/x86/include/asm/global_data.h
> +++ b/arch/x86/include/asm/global_data.h
> @@ -23,6 +23,11 @@
>  
>  #ifndef	__ASM_GBL_DATA_H
>  #define __ASM_GBL_DATA_H
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  /*
>   * The following data structure is placed in some memory wich is
>   * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
> @@ -57,6 +62,9 @@ typedef	struct global_data {
>  	unsigned long	reset_status;	/* reset status register at boot */
>  	void		**jt;		/* jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  static inline gd_t *get_fs_gd_ptr(void)
> diff --git a/common/Makefile b/common/Makefile
> index fdfead7..bfb4d7a 100644
> --- a/common/Makefile
> +++ b/common/Makefile
> @@ -209,6 +209,7 @@ COBJS-y += dlmalloc.o
>  COBJS-y += image.o
>  COBJS-y += memsize.o
>  COBJS-y += stdio.o
> +COBJS-$(CONFIG_DM) += dmmalloc.o
>  
>  
>  COBJS	:= $(sort $(COBJS-y))
> diff --git a/common/dmmalloc.c b/common/dmmalloc.c
> new file mode 100644
> index 0000000..4a1a241
> --- /dev/null
> +++ b/common/dmmalloc.c
> @@ -0,0 +1,297 @@
> +/*
> + * (C) Copyright 2012
> + * Tomas Hlavacek (tmshlvck at gmail.com)
> + *
> + * 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 <common.h> /* for ROUND_UP */
> +#include <asm/u-boot.h>
> +#include <asm/global_data.h> /* for gd_t and gd */
> +#include <asm/types.h> /* for phys_addr_t and size_addt_t */
> +
> +#include <dmmalloc.h>
> +#include <malloc.h>
> +
> +#include <linux/compiler.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +
> +struct early_block_header {
> +	size_t size;
> +};
> +
> +#define BLOCK_DATA(header) ((void *)(((struct early_block_header *)header)+1))
> +#define BLOCK_HEADER(addr) (((struct early_block_header *)addr)-1)
> +#define BLOCK_USED_FLAG 0x80000000
> +#define BLOCK_SIZE(size) (size & (~BLOCK_USED_FLAG))
> +#define BLOCK_USED(size) ((size & BLOCK_USED_FLAG) == BLOCK_USED_FLAG)
> +#define BLOCK_FREE(size) (!BLOCK_USED(size))
> +#define BLOCK_SET_FREE(size) BLOCK_SIZE(size)
> +#define BLOCK_SET_USED(size) (size | BLOCK_USED_FLAG)
> +
> +
> +__weak struct early_heap_header *early_brk(size_t size)
> +{
> +	struct early_heap_header *h;
> +	struct early_block_header *b;
> +
> +	if (gd->early_heap != NULL)
> +		return NULL;
> +
> +	h = (struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
> +	b = (struct early_block_header *)(h + 1);
> +
> +	size = CONFIG_SYS_EARLY_HEAP_SIZE;
> +	h->size = size;
> +	h->early_heap_next = NULL;
> +	b->size = size - sizeof(struct early_heap_header) -
> +			sizeof(struct early_block_header);
> +	b->size = BLOCK_SET_FREE(b->size);
> +
> +	return h;
> +}
> +
> +static struct early_block_header *find_free_space(struct early_heap_header *h,
> +							size_t size)
> +{
> +	struct early_block_header *b;
> +
> +	b = (struct early_block_header *)(h+1);
> +	while ((phys_addr_t)b + sizeof(struct early_block_header)
> +			< (phys_addr_t)h + h->size) {
> +		if (BLOCK_FREE(b->size) && (BLOCK_SIZE(b->size) >= size))
> +			return b;
> +		b = (struct early_block_header *)((phys_addr_t)b +
> +				sizeof(struct early_block_header) +
> +				BLOCK_SIZE(b->size));
> +	}
> +
> +	return NULL;
> +}
> +
> +static struct early_block_header *split_block(struct early_block_header *b,
> +	       size_t size)
> +{
> +	struct early_block_header *nb;
> +
> +	if ((BLOCK_SIZE(b->size) < size) || (BLOCK_USED(b->size)))
> +		return NULL;
> +
> +	if (BLOCK_SIZE(b->size) <= (size + sizeof(struct early_block_header)))
> +		return b;
> +
> +	nb = (struct early_block_header *)((phys_addr_t)b +
> +		sizeof(struct early_block_header) + size);
> +	nb->size = b->size - size - sizeof(struct early_block_header);
> +	b->size = size;
> +
> +	return b;
> +}
> +
> +void *early_malloc(size_t size)
> +{
> +	struct early_heap_header *h;
> +	struct early_block_header *b;
> +
> +	size = roundup(size, sizeof(phys_addr_t));
> +	if (size == 0)
> +		return NULL;
> +
> +	if (gd->early_heap == NULL)
> +		gd->early_heap = early_brk(size);
> +
> +	if (gd->early_heap == NULL) {
> +		debug("early_brk failed to initialize heap\n");
> +		return NULL;
> +	}
> +
> +	h = gd->early_heap;
> +	while (1) {
> +		b = find_free_space(h, size);
> +		if (b != NULL)
> +			break;
> +
> +		if (h->early_heap_next != NULL)
> +			h = h->early_heap_next;
> +		else
> +			break;
> +	}
> +
> +	if (b == NULL) {
> +		h->early_heap_next = early_brk(size+
> +				sizeof(struct early_heap_header)+
> +				sizeof(struct early_block_header));
> +		h = h->early_heap_next;
> +		if (h == NULL) {
> +			debug("early_brk failed to extend heap by %d B\n",
> +					size);
> +			return NULL;
> +		}
> +
> +		b = find_free_space(h, size);
> +		if (b == NULL) {
> +			debug("early_malloc failed to extend heap by %d B\n",
> +					size);
> +			return NULL;
> +		}
> +	}
> +
> +	if (b->size != size)
> +		b = split_block(b, size);
> +	if (b == NULL) {
> +		debug("early_malloc failed to split block to %d B\n", size);
> +		return NULL;
> +	}
> +
> +	b->size = BLOCK_SET_USED(b->size);
> +
> +	return BLOCK_DATA(b);
> +}
> +
> +void early_free(void *addr)
> +{
> +	struct early_block_header *h = BLOCK_HEADER(addr);
> +	assert(BLOCK_USED(h->size));
> +	h->size = BLOCK_SET_FREE(h->size);
> +}
> +
> +void early_malloc_heap_dump(struct early_heap_header *h)
> +{
> +	struct early_block_header *b;
> +
> +	debug("heap: h=%p, h->size=%d\n", h, h->size);
> +
> +	b = (struct early_block_header *)(h+1);
> +	while ((phys_addr_t)b + sizeof(struct early_block_header)
> +			< (phys_addr_t)h + h->size) {
> +		debug("block: h=%p h->size=%d b=%p b->size=%d b->(used)=%d\n",
> +				h, h->size, b, BLOCK_SIZE(b->size),
> +				BLOCK_USED(b->size));
> +		assert(BLOCK_SIZE(b->size) > 0);
> +		b = (struct early_block_header *)((phys_addr_t)b +
> +				sizeof(struct early_block_header) +
> +				BLOCK_SIZE(b->size));
> +	}
> +	debug("--- heap dump end ---\n");
> +}
> +
> +void early_malloc_dump(void)
> +{
> +	struct early_heap_header *h = gd->early_heap;
> +	while (h != NULL) {
> +		early_malloc_heap_dump(h);
> +		h = h->early_heap_next;
> +	}
> +}
> +
> +static int early_malloc_active(void)
> +{
> +	return ((gd->flags & GD_FLG_HEAP_INIT) != GD_FLG_HEAP_INIT);
> +}
> +
> +static int early_heap_active(void)
> +{
> +	return ((gd->flags & GD_FLG_EARLY_HEAP_DONE) !=
> +			GD_FLG_EARLY_HEAP_DONE);
> +}
> +
> +static int early_address(void *ptr)
> +{
> +	struct early_heap_header *h = gd->early_heap;
> +	while (h != NULL) {
> +		if (((phys_addr_t)ptr >= (phys_addr_t)h) &&
> +				((phys_addr_t)ptr < (phys_addr_t)h + h->size))
> +			return 1;
> +
> +		h = h->early_heap_next;
> +	}
> +
> +	return 0;
> +}
> +
> +
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
> +
> +void *dmmalloc(size_t size)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	if (early_malloc_active())
> +		return early_malloc(size);
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +	return malloc(size);
> +}
> +
> +void dmfree(void *ptr)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	if (early_heap_active()) {
> +		if (early_address(ptr))
> +			early_free(ptr);
> +		return;
> +	}
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +	free(ptr);
> +}
> +
> +void *dmcalloc(size_t n, size_t elem_size)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	char *addr;
> +	int size = elem_size * n;
> +
> +	if (early_malloc_active()) {
> +		addr = early_malloc(size);
> +		memset(addr, 0, size);
> +		return addr;
> +	}
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +	return calloc(n, elem_size);
> +}
> +
> +void *dmrealloc(void *oldaddr, size_t bytes)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	char *addr;
> +	struct early_block_header *h;
> +
> +	if (early_heap_active() && early_address(oldaddr)) {
> +		addr = dmmalloc(bytes);
> +		if (addr == NULL)
> +			return NULL;
> +
> +		h = BLOCK_HEADER(oldaddr);
> +		if (BLOCK_FREE(h->size))
> +			return NULL;
> +
> +		if (bytes > BLOCK_SIZE(h->size))
> +			bytes = BLOCK_SIZE(h->size);
> +
> +		memcpy(addr, oldaddr, bytes);
> +		dmfree(oldaddr);
> +		return addr;
> +	}
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +	return realloc(oldaddr, bytes);
> +}
> +
> diff --git a/include/asm-generic/global_data_flags.h b/include/asm-generic/global_data_flags.h
> index bb57fb6..97db2c2 100644
> --- a/include/asm-generic/global_data_flags.h
> +++ b/include/asm-generic/global_data_flags.h
> @@ -13,8 +13,8 @@
>  /*
>   * Global Data Flags
>   *
> - * Note: The low 16 bits are expected for common code.  If your arch
> - *       really needs to add your own, use the high 16bits.
> + * Note: The low 18 bits are expected for common code.  If your arch
> + *       really needs to add your own, use the high 14 bits.
>   */
>  #define GD_FLG_RELOC		0x0001	/* Code was relocated to RAM */
>  #define GD_FLG_DEVINIT		0x0002	/* Devices have been initialized */
> @@ -24,5 +24,7 @@
>  #define GD_FLG_LOGINIT		0x0020	/* Log Buffer has been initialized */
>  #define GD_FLG_DISABLE_CONSOLE	0x0040	/* Disable console (in & out) */
>  #define GD_FLG_ENV_READY	0x0080	/* Environment imported into hash table */
> +#define GD_FLG_HEAP_INIT	0x0100	/* malloc() in RAM is available */
> +#define GD_FLG_EARLY_HEAP_DONE	0x0200	/* early_malloc() heap relocated. */
>  
>  #endif
> diff --git a/include/dmmalloc.h b/include/dmmalloc.h
> new file mode 100644
> index 0000000..c99f423
> --- /dev/null
> +++ b/include/dmmalloc.h
> @@ -0,0 +1,132 @@
> +/*
> + * (C) Copyright 2012
> + * Tomas Hlavacek (tmshlvck at gmail.com)
> + *
> + * 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
> + */
> +
> +#ifndef __INCLUDE_DMMALLOC_H
> +#define __INCLUDE_DMMALLOC_H
> +
> +#include <config.h>
> +#include <linux/stddef.h> /* for size_t */
> +#include <malloc.h>
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +
> +/**
> + * struct early_heap_header - header preceding an early heap
> + * @size - length of the heap in bytes (including the heap header).
> + * @early_heap_next - pointer to the following heap.
> + *
> + * Heaps are organized in the single direction linked list. Each heap
> + * contains own size. Pointer to the first (left-most) heap is
> + * contained in global data.
> + */
> +struct early_heap_header {
> +	size_t size;
> +	void *early_heap_next;
> +};
> +
> +/**
> + * early_brk() - obtain address of the heap
> + * @size:	Minimal size of the new early heap to be allocated.
> + *
> + * Function returns a new heap pointer.
> + *
> + * Allocate and initialize early_heap at least size bytes long.
> + * This function can be platform dependent or board dependent but sensible
> + * default is provided.
> + */
> +struct early_heap_header *early_brk(size_t size);
> +
> +/**
> + * early_malloc() - malloc operating on the early_heap(s)
> + * @size:	Size in bytes.
> + *
> + * Function returns a pointer to the allocated block.
> + */
> +void *early_malloc(size_t size);
> +
> +/**
> + * early_free() - free operating on the early_heap(s)
> + * @addr:	Pointer to the allocated block to be released.
> + */
> +void early_free(void *addr);
> +
> +/**
> + * early_malloc_heap_dump() - print blocks contained in an early_heap
> + * @h:		Address of the early heap.
> + */
> +void early_malloc_heap_dump(struct early_heap_header *h);
> +
> +/**
> + * early_malloc_dump() - print blocks contained in all early_heaps
> + */
> +void early_malloc_dump(void);
> +
> +
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
> +#ifdef CONFIG_DM
> +
> +/*
> + * DM versions of malloc* functions. In early init it calls early_malloc.
> + * It wraps around normal malloc* functions afterwards.
> + */
> +
> +/**
> + * dmmalloc() - malloc working seamlessly in early as well as in RAM stages
> + * @size:	Size of the block to be allocated.
> + *
> + * Function returns an address of the newly allocated block when successful
> + * or NULL otherwise.
> + */
> +void *dmmalloc(size_t size);
> +
> +/**
> + * dmfree() - free working seamlessly in early as well as in RAM stages
> + * @ptr:	Pointer to the allocated block to be released.
> + */
> +void dmfree(void *ptr);
> +
> +/**
> + * dmcalloc() - calloc working seamlessly in early as well as in RAM stages
> + * @n:		Number of elements to be allocated.
> + * @elem_size:	Size of elements to be allocated.
> + *
> + * Function returns a pointer to newly the allocated area (n*elem_size) long.
> + */
> +void *dmcalloc(size_t n, size_t elem_size);
> +
> +/**
> + * dmrealloc() - realloc working seamlessly in early as well as in RAM stages
> + * @oldaddr:	Pointer to the old memory block.
> + * @bytes:	New size to of the block to be reallocated.
> + *
> + * Function returns an address of the newly allocated block when successful
> + * or NULL otherwise.
> + *
> + * Data are copied from the block specified by oldaddr to the new block.
> + */
> +void *dmrealloc(void *oldaddr, size_t bytes);
> +
> +#endif /* CONFIG_DM */
> +#endif /* __INCLUDE_DMMALLOC_H */
> +
> 

*you may stop your scrolling now*

Hello,
does it ring a bell? I need to get it (or an equivalent solution) to
work before implementing a working DM2-I2C uclass. I don't see any
replies to the original v10 e-mail. Why wasn't it accepted into U-Boot?
Should I work on top of this patch, or start from scratch?

Regards,

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v10] Add dmmalloc module for DM.
  2013-11-05 15:26   ` Mateusz Zalega
@ 2013-11-05 17:17     ` Tom Rini
  2013-11-05 17:26       ` Mateusz Zalega
  0 siblings, 1 reply; 48+ messages in thread
From: Tom Rini @ 2013-11-05 17:17 UTC (permalink / raw)
  To: u-boot

On Tue, Nov 05, 2013 at 04:26:25PM +0100, Mateusz Zalega wrote:

> On 10/29/12 00:20, Tomas Hlavacek wrote:
> > Add pointer to the first early heap into GD structure.
> > Implement simple early_malloc and early_free functions.
> > Prepare for additional heaps and automated heap initialization.
> > Add temporary early_malloc_active function (to be replaced in future by
> > more coarse DM init flags).
> > Add DM specific malloc calls - dmmalloc, dmfree, dmrealloc and dmcalloc.
> > 
> > Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
[snip]
> does it ring a bell? I need to get it (or an equivalent solution) to
> work before implementing a working DM2-I2C uclass. I don't see any
> replies to the original v10 e-mail. Why wasn't it accepted into U-Boot?
> Should I work on top of this patch, or start from scratch?

The patch itself was OK, but the rest of the DM work did not end up
going in, so there was no user of this change.  If you have a user,
please re-use his patch (and it'll need a v11 to apply again on top of
tree and comply with SPDX licenisng tags) and push it forward, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20131105/33377baa/attachment.pgp>

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [U-Boot] [PATCH v10] Add dmmalloc module for DM.
  2013-11-05 17:17     ` Tom Rini
@ 2013-11-05 17:26       ` Mateusz Zalega
  0 siblings, 0 replies; 48+ messages in thread
From: Mateusz Zalega @ 2013-11-05 17:26 UTC (permalink / raw)
  To: u-boot

>>> Add pointer to the first early heap into GD structure.
>>> Implement simple early_malloc and early_free functions.
>>> Prepare for additional heaps and automated heap initialization.
>>> Add temporary early_malloc_active function (to be replaced in future by
>>> more coarse DM init flags).
>>> Add DM specific malloc calls - dmmalloc, dmfree, dmrealloc and dmcalloc.
>>>
>>> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
> [snip]
>> does it ring a bell? I need to get it (or an equivalent solution) to
>> work before implementing a working DM2-I2C uclass. I don't see any
>> replies to the original v10 e-mail. Why wasn't it accepted into U-Boot?
>> Should I work on top of this patch, or start from scratch?
> 
> The patch itself was OK, but the rest of the DM work did not end up
> going in, so there was no user of this change.  If you have a user,
> please re-use his patch (and it'll need a v11 to apply again on top of
> tree and comply with SPDX licenisng tags) and push it forward, thanks!
> 

will do, thx!

-- 
Mateusz Zalega
Samsung R&D Institute Poland

^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2013-11-05 17:26 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-27 12:12 [U-Boot] [PATCH 1/1] [RFC] DM: early_malloc for DM added Tomas Hlavacek
2012-08-27 12:18 ` Marek Vasut
2012-08-27 12:37   ` Tomas Hlavacek
2012-08-27 12:42 ` [U-Boot] [PATCHv2 " Tomas Hlavacek
2012-08-27 23:02   ` Graeme Russ
2012-08-28  0:11     ` Graeme Russ
2012-08-28  0:18     ` Graeme Russ
2012-09-18  7:13 ` [U-Boot] [PATCHv4] " Tomas Hlavacek
2012-09-18 10:57   ` Marek Vasut
2012-09-18 23:29     ` Graeme Russ
2012-09-18 23:33       ` Marek Vasut
2012-09-18 23:44         ` Graeme Russ
2012-09-18 23:53           ` Marek Vasut
2012-09-19 18:29       ` Tom Rini
2012-09-22  0:37       ` Tomas Hlavacek
2012-09-18 23:25   ` Graeme Russ
2012-09-22  0:25 ` [U-Boot] [PATCH v5] [RFC] " Tomas Hlavacek
2012-09-22  0:28   ` Marek Vasut
2012-09-22  7:52     ` Tomas Hlavacek
2012-09-22 13:19       ` Marek Vasut
2012-09-22 22:09 ` [U-Boot] [PATCH v6] " Tomas Hlavacek
2012-09-23 13:06   ` Graeme Russ
2012-09-23 15:30     ` Tomas Hlavacek
2012-09-23 15:38 ` [U-Boot] [PATCH v7] " Tomas Hlavacek
2012-09-23 16:15 ` [U-Boot] [PATCH v8] " Tomas Hlavacek
2012-09-23 16:32   ` Wolfgang Denk
2012-09-23 16:47     ` Tomas Hlavacek
2012-09-24 21:48       ` Tom Rini
2012-09-23 23:11   ` Marek Vasut
2012-09-24 14:16     ` Tomas Hlavacek
2012-09-24 14:19       ` Marek Vasut
2012-09-25  0:37         ` Graeme Russ
2012-09-25  8:43           ` Tomas Hlavacek
2012-09-25  9:09             ` Graeme Russ
2012-09-25 23:04               ` Graeme Russ
2012-09-26 10:16                 ` Tomas Hlavacek
2012-09-26 23:03                   ` Graeme Russ
2012-09-24  0:00   ` Graeme Russ
2012-09-24  0:35     ` Tomas Hlavacek
2012-09-24  0:46       ` Graeme Russ
2012-10-24 23:49 ` [U-Boot] [PATCH v9] [RFC] Add dmmalloc module for DM Tomas Hlavacek
2012-10-25  1:40   ` Graeme Russ
2012-10-25 19:16     ` Tomas Hlavacek
2012-10-25 23:04       ` Graeme Russ
2012-10-28 23:20 ` [U-Boot] [PATCH v10] " Tomas Hlavacek
2013-11-05 15:26   ` Mateusz Zalega
2013-11-05 17:17     ` Tom Rini
2013-11-05 17:26       ` Mateusz Zalega

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.