[U-Boot] [U-Boot-DM] [PATCH 1/1] early_malloc() introduced to ARM architecture
Marek Vasut
marex at denx.de
Sat Jul 28 22:36:58 CEST 2012
Dear Tomas Hlavacek,
I think we should still mark early patches as RFC.
> early_malloc() introduced to ARM architecture (it is a proof of concept).
> GD datastructure extended for holding early-heap.
> mem_malloc_init() in board_init_r() has been put up by few lines.
I take it was sent by the gmail webIF ? Like WD said, not a good idea, git send-
email is really the way. it's actually simple, we can discuss that tomorrow.
> Signed-off-by: Tomas Hlavacek <tmshlvck at gmail.com>
> ---
> arch/arm/include/asm/global_data.h | 4 +-
> arch/arm/lib/board.c | 32 +++++++++--
> common/Makefile | 1 +
> common/earlymalloc.c | 102
> ++++++++++++++++++++++++++++++++++++
> include/common.h | 1 +
> include/earlymalloc.h | 84 +++++++++++++++++++++++++++++
> lib/asm-offsets.c | 2 +-
> 7 files changed, 220 insertions(+), 6 deletions(-)
> 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..215212a 100644
> --- a/arch/arm/include/asm/global_data.h
> +++ b/arch/arm/include/asm/global_data.h
> @@ -30,7 +30,8 @@
> * global variables during system initialization (until we have set
> * up the memory controller so that we can use RAM).
> *
> - * Keep it *SMALL* and remember to set GENERATED_GBL_DATA_SIZE >
> sizeof(gd_t)
> + * Keep it *SMALL* and remember to set GENERATED_GBL_DATA_SIZE >
> + * sizeof(gd_t) + EARLY_HEAP_SIZE
> */
>
> typedef struct global_data {
> @@ -86,6 +87,7 @@ typedef struct global_data {
> #endif
> } gd_t;
>
> +
Ok well ... you know, this will need cleanup. But for RFC, this is OK.
> /*
> * Global Data Flags
> */
> diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
> index 500e216..81ee27b 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>
Do we need early_malloc.h at all? malloc.h won't cut it?
> #ifdef CONFIG_BITBANGMII
> #include <miiphy.h>
> @@ -273,6 +274,9 @@ void board_init_f(ulong bootflag)
>
> memset((void *)gd, 0, sizeof(gd_t));
>
> + early_malloc_init();
So this basically flips a bit, do it the other way and you don't need it.
> + debug("Early malloc initialized.\n");
> +
> gd->mon_len = _bss_end_ofs;
> #ifdef CONFIG_OF_EMBED
> /* Get a pointer to the FDT */
> @@ -452,12 +469,23 @@ void board_init_r(gd_t *id, ulong dest_addr)
> ulong flash_size;
> #endif
>
> + gd_t *old_gd = gd;
> +
> gd = id;
>
> gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
>
> monitor_flash_len = _end_ofs;
>
> + /* The Malloc area is immediately below the monitor copy in DRAM */
> + malloc_start = dest_addr - TOTAL_MALLOC_LEN;
> + mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN);
> +
> + // TODO: DM Cores relocation goes here.
> +
> + /* Disable early mallocator (effectively switch calls to the real
> malloc). */
> + early_malloc_disab((gde_t *)old_gd);
> +
> /* Enable caches */
> enable_caches();
>
> @@ -485,10 +513,6 @@ void board_init_r(gd_t *id, ulong dest_addr)
> post_output_backlog();
> #endif
>
> - /* The Malloc area is immediately below the monitor copy in DRAM */
> - malloc_start = dest_addr - TOTAL_MALLOC_LEN;
> - mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN);
> -
Can mem_malloc_init() not flip on the early_malloc bit for you here?
> #if !defined(CONFIG_SYS_NO_FLASH)
> puts("Flash: ");
>
[...]
> +
> +#include <asm/global_data.h> /* for gd_t and gd */
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static inline size_t early_malloc_align_up(phys_addr_t addr)
> +{
> + if(!EARLY_MALLOC_IS_ALIGNED(addr)) {
> + addr = EARLY_MALLOC_ALIGN_DOWN(addr);
> + addr += EARLY_MALLOC_ALIGN_MULTIPLE;
> + }
> +
> + return addr;
> +}
> +
> +void early_malloc_init(void)
> +{
> + ((gde_t *)gd)->em.flags = EARLY_MALLOC_INIT_FLAGS;
> + ((gde_t *)gd)->em.size = 0;
> +}
> +
> +
> +int early_malloc_isactive(void)
> +{
> + /* The early_malloc() is inactive after relocation or when the
> + flag says so. */
> + return ((EARLY_MALLOC_IS_ACTIVE(((gde_t *)gd)->em.flags)) ||
> + (gd->flags & GD_FLG_RELOC));
So ... gd->flags will be enough for the early malloc, you don't need any further
flags
> +}
> +
> +int early_free_isactive(void)
> +{
> + /* The early free is inactive when the flag says so. */
> + return (gd->flags & GD_FLG_RELOC);
> +}
> +
> +
> +void *early_malloc(size_t size)
No, we want this wrapped into malloc() call, so the drivers can be inited
indifferent of time.
> +{
> + em_spc_t *em = &((gde_t *)gd)->em;
> +
> + /* Check flag active. */
> + if(!EARLY_MALLOC_IS_ACTIVE(em->flags))
> + return NULL;
Indent with tab please ... tools/checkpatch.pl will help here.
> + /* Choose block beginning address. */
> + phys_addr_t addr =
> early_malloc_align_up(((phys_addr_t)&em->heap)+em->size);
> +
> + /* Check free space. */
> + if(addr + size >= ((phys_addr_t)(&(em->heap))) + EARLY_HEAP_SIZE)
> + return NULL;
> +
> + /* Calculate next free space. */
> + em->size+=early_malloc_align_up(size);
> +
> + return (void *)addr;
> +}
> +
> +
> +int early_malloc_isaddress(void *addr)
> +{
> + if((((phys_addr_t)addr) >= (phys_addr_t)(&(((gde_t *)gd)->em.heap)))&&
> + (((phys_addr_t)addr) < ((phys_addr_t)(&(((gde_t
> *)gd)->em.heap)))+EARLY_HEAP_SIZE))
See container_of() ... and you can really split the checks.
> + return 1;
> + else
> + return 0;
> +}
> +
> +void early_free(void *addr)
> +{
> + /* NOOP - Early malloc does not support free(). */
This goes to free() call ...
> +}
> +
> +void early_malloc_disab(gde_t *gd)
> +{
> + EARLY_MALLOC_DISABLE(gd->em.flags);
> +}
> diff --git a/include/common.h b/include/common.h
> index a2c6b27..486925f 100644
> --- a/include/common.h
> +++ b/include/common.h
> @@ -171,6 +171,7 @@ typedef void (interrupt_handler_t)(void *);
>
> #include <asm/u-boot.h> /* boot information for Linux kernel */
> #include <asm/global_data.h> /* global data used for startup functions
> */
> +#include <earlymalloc.h> /* Early mallocator data structure that extends
> global data. */
Drop this altogether.
[...]
> +
> +typedef struct early_malloc_spc {
> + char flags;
> + short size;
> + char heap[EARLY_HEAP_SIZE];
> +} em_spc_t;
Drop the typedef please.
> +/*
> + * Platform data extended for the early mallocator.
> + * This structure holds the original global data (and it starts at
> + * the very same address), but it is longer because it holds
> + * early malloc space in the end.
> + * This is a trick with data structures: This datastructure is
> + * pre-allocated by lib/asm-offsets.c but this structure is not to
> + * be relocated as whole because struct global_data is used during
> + * normal operations as well as during relocation phase.
> + */
> +typedef struct global_data_extended {
I'm not convinced about the typedef here either ... others?
> + gd_t gd; /* Original Global Data
> structure */
> + em_spc_t em; /* Early-malloc space.
> */
> +} gde_t;
> +
> +/* Initial flags block. Active flag set. */
> +#define EARLY_MALLOC_INIT_FLAGS 0x80
> +
> +/* Alignment size - number of bytes to align to it's mupliple. */
> +#define EARLY_MALLOC_ALIGN_MULTIPLE (sizeof(phys_addr_t))
> +#define EARLY_MALLOC_ALIGN_MASK (EARLY_MALLOC_ALIGN_MULTIPLE-1)
> +
> +
> +#define EARLY_MALLOC_ALIGN_DOWN(addr) ((phys_addr_t)addr &
> (~EARLY_MALLOC_ALIGN_MASK))
> +#define EARLY_MALLOC_IS_ALIGNED(addr) (!(((phys_addr_t)addr) &
> EARLY_MALLOC_ALIGN_MASK))
> +#define EARLY_MALLOC_FLAG_ACTIVE 0x80
> +#define EARLY_MALLOC_IS_ACTIVE(flags) (flags & EARLY_MALLOC_FLAG_ACTIVE)
> +#define EARLY_MALLOC_DISABLE(flags)
> (flags=(flags&(~EARLY_MALLOC_FLAG_ACTIVE)))
You won't need this whole file I think ...
> +
> +
> +void early_malloc_init(void);
> +int early_malloc_isactive(void);
> +int early_free_isactive(void);
> +void *early_malloc(size_t size);
> +void early_free(void *addr);
> +void early_malloc_disab(gde_t *gd);
> +int early_malloc_isaddress(void *);
> +
> +#endif
> diff --git a/lib/asm-offsets.c b/lib/asm-offsets.c
> index c88f5d4..6e39826 100644
> --- a/lib/asm-offsets.c
> +++ b/lib/asm-offsets.c
> @@ -23,7 +23,7 @@ int main(void)
> {
> /* Round up to make sure size gives nice stack alignment */
> DEFINE(GENERATED_GBL_DATA_SIZE,
> - (sizeof(struct global_data) + 15) & ~15);
> + (sizeof(struct global_data_extended) + 15) & ~15);
And if you adjusted the global data to be the "container of both, you won't need
this here either.
>
> DEFINE(GENERATED_BD_INFO_SIZE,
> (sizeof(struct bd_info) + 15) & ~15);
More information about the U-Boot
mailing list