1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  Physical Memory (arena) manager		File: cfe_mem.c
5    *
6    *  This module describes the physical memory available to the
7    *  firmware.
8    *
9    *  Author:  Mitch Lichtenberg (mpl@broadcom.com)
10    *
11    *********************************************************************
12    *
13    *  Copyright 2000,2001,2002,2003
14    *  Broadcom Corporation. All rights reserved.
15    *
16    *  This software is furnished under license and may be used and
17    *  copied only in accordance with the following terms and
18    *  conditions.  Subject to these conditions, you may download,
19    *  copy, install, use, modify and distribute modified or unmodified
20    *  copies of this software in source and/or binary form.  No title
21    *  or ownership is transferred hereby.
22    *
23    *  1) Any source code used, modified or distributed must reproduce
24    *     and retain this copyright notice and list of conditions
25    *     as they appear in the source file.
26    *
27    *  2) No right is granted to use any trade name, trademark, or
28    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
29    *     name may not be used to endorse or promote products derived
30    *     from this software without the prior written permission of
31    *     Broadcom Corporation.
32    *
33    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
34    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
35    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
37    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
38    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
39    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
43    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
45    *     THE POSSIBILITY OF SUCH DAMAGE.
46    ********************************************************************* */
47
48
49#include "lib_types.h"
50#include "lib_string.h"
51#include "lib_queue.h"
52#include "lib_malloc.h"
53#include "lib_printf.h"
54#include "lib_arena.h"
55
56#include "cfe_error.h"
57
58#include "cfe.h"
59#include "cfe_mem.h"
60
61#include "initdata.h"
62
63#define _NOPROTOS_
64#include "cfe_boot.h"
65#undef _NOPROTOS_
66
67#include "cpu_config.h"		/* for definition of CPUCFG_ARENAINIT */
68
69#include "addrspace.h"		/* for macros dealing with addresses */
70
71
72/*  *********************************************************************
73    *  Macros
74    ********************************************************************* */
75
76#define ARENA_RANGE(bottom,top,type) arena_markrange(&cfe_arena,(uint64_t)(bottom), \
77                                     (uint64_t)(top)-(uint64_t)bottom+1,(type),NULL)
78
79#define MEG	(1024*1024)
80#define KB      1024
81#define PAGESIZE 4096
82#define CFE_BOOTAREA_SIZE (256*KB)
83#define CFE_BOOTAREA_ADDR 0x20000000
84
85/*  *********************************************************************
86    *  Globals
87    ********************************************************************* */
88
89arena_t cfe_arena;
90extern void _setcontext(int64_t);
91
92unsigned int mem_bootarea_start;
93unsigned int mem_bootarea_size;
94
95extern void CPUCFG_ARENAINIT(void);
96extern void cfe_bootarea_init(void);
97extern void CPUCFG_PAGETBLINIT(uint64_t *ptaddr,unsigned int ptstart);
98
99
100
101/*  *********************************************************************
102    *  cfe_arena_init()
103    *
104    *  Create the initial map of physical memory
105    *
106    *  Input parameters:
107    *  	   nothing
108    *
109    *  Return value:
110    *  	   nothing
111    ********************************************************************* */
112
113void cfe_arena_init(void)
114{
115    uint64_t memlo,memhi;
116
117    /*
118     * This macro expands via cpu_config.h to an appropriate function
119     * name for creating an empty arena appropriately for our CPU
120     */
121
122    CPUCFG_ARENAINIT();
123
124    /*
125     * Round the area used by the firmware to a page boundary and
126     * mark it in use
127     */
128
129    memhi = PHYSADDR((mem_topofmem + 4095) & ~4095);
130    memlo = PHYSADDR(mem_bottomofmem) & ~4095;
131
132    ARENA_RANGE(memlo,memhi-1,MEMTYPE_DRAM_USEDBYFIRMWARE);
133
134    /*
135     * Create the initial page table
136     */
137
138    cfe_bootarea_init();
139
140}
141
142
143/*  *********************************************************************
144    *  cfe_arena_enum(idx,type,start,size)
145    *
146    *  Enumerate available memory.  This is called by the user
147    *  API dispatcher so that operating systems can determine what
148    *  memory regions are available to them.
149    *
150    *  Input parameters:
151    *  	   idx - index.  Start at zero and increment until an error
152    *  	         is returned.
153    *  	   type,start,size: pointers to variables to receive the
154    *  	         arena entry's information
155    *	   allrecs - true to retrieve all records, false to retrieve
156    * 		 only available DRAM
157    *
158    *  Return value:
159    *  	   0 if ok
160    *  	   CFE_ERR_NOMORE if idx is beyond the last entry
161    ********************************************************************* */
162
163int cfe_arena_enum(int idx,int *type,uint64_t *start,uint64_t *size,int allrecs)
164{
165    arena_node_t *node;
166    queue_t *qb;
167    arena_t *arena = &cfe_arena;
168
169
170    for (qb = (arena->arena_list.q_next); qb != &(arena->arena_list);
171	 qb = qb->q_next) {
172	node = (arena_node_t *) qb;
173
174	if (allrecs || (!allrecs && (node->an_type == MEMTYPE_DRAM_AVAILABLE))) {
175	    if (idx == 0) {
176		*type = node->an_type;
177		*start = node->an_address;
178		*size = node->an_length;
179		return 0;
180		}
181	    idx--;
182	    }
183	}
184
185    return CFE_ERR_NOMORE;
186
187}
188
189/*  *********************************************************************
190    *  cfe_arena_loadcheck(start,size)
191    *
192    *  Determine if the specified memory area is within the available
193    *  DRAM.  This is used while loading executables to be sure we
194    *  don't trash the firmware.
195    *
196    *  Input parameters:
197    *  	   start - starting physical address
198    *  	   size - size of requested region
199    *
200    *  Return value:
201    *  	   true - ok to copy memory here
202    *  	   false - not ok, memory overlaps firmware
203    ********************************************************************* */
204
205int cfe_arena_loadcheck(uintptr_t start,unsigned int size)
206{
207    arena_node_t *node;
208    queue_t *qb;
209    arena_t *arena = &cfe_arena;
210
211    /*
212     * If the address is in our boot area, it's okay
213     * for it to be a virtual address.
214     */
215
216    if ((start >= BOOT_START_ADDRESS) &&
217	((start+size) <= (BOOT_START_ADDRESS+BOOT_AREA_SIZE))) {
218	return TRUE;
219	}
220
221    /*
222     * Otherwise, make a physical address.
223     */
224
225    start = PHYSADDR(start);
226
227    /*
228     * Because all of the arena nodes of the same type are
229     * coalesced together, all we need to do is determine if the
230     * requested region is entirely within an arena node,
231     * so there's no need to look for things that span nodes.
232     */
233
234    for (qb = (arena->arena_list.q_next); qb != &(arena->arena_list);
235	 qb = qb->q_next) {
236	node = (arena_node_t *) qb;
237
238	/* If the memory is available, the region is OK. */
239
240	if ((start >= node->an_address) &&
241	    ((start+size) <= (node->an_address+node->an_length)) &&
242	    (node->an_type == MEMTYPE_DRAM_AVAILABLE)) {
243	    return TRUE;
244	    }
245	}
246
247    /*
248     * Otherwise, it's not.  We could go through the arena again and
249     * look for regions of other types that intersect the requested
250     * region, to get a more detailed error, but this'll do.
251     */
252
253    return FALSE;
254
255}
256
257