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