Message ID | 1346071331-28989-1-git-send-email-tmshlvck@gmail.com |
---|---|
State | RFC |
Delegated to: | Tom Rini |
Headers | show |
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@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@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 >
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
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
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@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@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 */ +
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