1 /* cfe_mem.c -- Replaceable memory management hooks for MIPS boards
2    running CFE.  */
3 
4 /*
5  * Copyright 2003
6  * Broadcom Corporation. All rights reserved.
7  *
8  * This software is furnished under license and may be used and copied only
9  * in accordance with the following terms and conditions.  Subject to these
10  * conditions, you may download, copy, install, use, modify and distribute
11  * modified or unmodified copies of this software in source and/or binary
12  * form. No title or ownership is transferred hereby.
13  *
14  * 1) Any source code used, modified or distributed must reproduce and
15  *    retain this copyright notice and list of conditions as they appear in
16  *    the source file.
17  *
18  * 2) No right is granted to use any trade name, trademark, or logo of
19  *    Broadcom Corporation.  The "Broadcom Corporation" name may not be
20  *    used to endorse or promote products derived from this software
21  *    without the prior written permission of Broadcom Corporation.
22  *
23  * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED
24  *    WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
25  *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
26  *    NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE
27  *    FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE
28  *    LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31  *    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32  */
33 
34 #include "cfe_api.h"
35 
36 /* Structure filled in by get_mem_info.  Only the size field is
37    actually used (by sbrk), so the others aren't even filled in.
38    Note that 'size' is the __size__ of the heap starting at _end!  */
39 struct s_mem {
40   unsigned int size;
41   unsigned int icsize;
42   unsigned int dcsize;
43 };
44 
45 void *get_mem_info (struct s_mem *);
46 
47 extern char _end[];
48 
49 /* Address immediately after available memory.  */
50 static unsigned long memtop;
51 
52 /* Program stack size.  */
53 static unsigned long stack_size;
54 
55 void
__libcfe_meminit(void)56 __libcfe_meminit (void)
57 {
58   /* If the user has provided a memory-limit function, use it to
59      determine the end of usable memory.  */
60   if (&__libcfe_mem_limit != NULL)
61     memtop = __libcfe_mem_limit ();
62   else
63     {
64       uint64_t start, length, type;
65       int i, rv;
66       long end_segbits, end_pa;
67 
68       /* Note that this only works if _end and the program live in kseg0
69          or kseg1.  Not a problem with the default linker script, but
70          if you're writing your own, keep it in mind.  For more complex
71          memory allocation needs, you're encouraged to copy this file
72          and syscalls.c (for sbrk()), and reimplement as appropriate.  */
73       end_segbits = (long)_end & ~ 0x1fffffffL;
74       end_pa = (long)_end & 0x1fffffffL;
75 
76       for (i = 0; ; i++)
77         {
78           rv = cfe_enummem(i, 0, &start, &length, &type);
79           if (rv < 0)
80             {
81               /* Did not find an available entry containing _end.
82                  Assume a minimal amount of memory (1MB).  */
83               memtop = _end + (1 * 1024 * 1024);
84               break;
85             }
86 
87           /* If not available, try the next.  */
88           if (type != CFE_MI_AVAILABLE)
89             continue;
90 
91           /* If end_pa is between start and (start + length) then we have
92 	     a winner.  */
93           if (end_pa >= start && end_pa < (start + length))
94             {
95               memtop = (start + length) | end_segbits;
96               break;
97             }
98         }
99     }
100 
101   /* If the user has provided a memory-limit function, use it to
102      determine the end of usable memory.  */
103   if (&__libcfe_stack_size != NULL)
104     stack_size = __libcfe_stack_size ();
105   else
106     stack_size = (32 * 1024);		/* Default = 32KB.  */
107 
108   /* Chop the top of memory to a 32-byte aligned location, and
109      round the stack size up to a 32-byte multiple.  */
110   memtop = memtop & ~(unsigned long)31;
111   stack_size = (stack_size + 31) & ~(unsigned long)31;
112 }
113 
114 void *
__libcfe_stack_top(void)115 __libcfe_stack_top (void)
116 {
117   /* Grow down from the top of available memory.  Obviously, if
118      code writes above this limit, problems could result!  */
119   return (void *) memtop;
120 }
121 
122 /* For compatibility, get_mem_info returns the top of memory
123    (i.e., the stack address).  Nothing actually uses that,
124    though.  */
125 void *
get_mem_info(struct s_mem * meminfo)126 get_mem_info (struct s_mem *meminfo)
127 {
128   meminfo->size = (char *)(memtop - stack_size) - _end;
129   return (void *) memtop;
130 }
131