1 |
148 |
jeremybenn |
/* 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
|
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 *
|
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 *
|
126 |
|
|
get_mem_info (struct s_mem *meminfo)
|
127 |
|
|
{
|
128 |
|
|
meminfo->size = (char *)(memtop - stack_size) - _end;
|
129 |
|
|
return (void *) memtop;
|
130 |
|
|
}
|