cvmx-bootmem.h revision 232812
1226584Sdim/***********************license start*************** 2226584Sdim * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3226584Sdim * reserved. 4226584Sdim * 5226584Sdim * 6226584Sdim * Redistribution and use in source and binary forms, with or without 7226584Sdim * modification, are permitted provided that the following conditions are 8226584Sdim * met: 9226584Sdim * 10226584Sdim * * Redistributions of source code must retain the above copyright 11226584Sdim * notice, this list of conditions and the following disclaimer. 12226584Sdim * 13226584Sdim * * Redistributions in binary form must reproduce the above 14226584Sdim * copyright notice, this list of conditions and the following 15226584Sdim * disclaimer in the documentation and/or other materials provided 16226584Sdim * with the distribution. 17226584Sdim 18226584Sdim * * Neither the name of Cavium Inc. nor the names of 19226584Sdim * its contributors may be used to endorse or promote products 20226584Sdim * derived from this software without specific prior written 21226584Sdim * permission. 22226584Sdim 23226584Sdim * This Software, including technical data, may be subject to U.S. export control 24226584Sdim * laws, including the U.S. Export Administration Act and its associated 25226584Sdim * regulations, and may be subject to export or import regulations in other 26226584Sdim * countries. 27226584Sdim 28226584Sdim * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29226584Sdim * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30226584Sdim * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31226584Sdim * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32226584Sdim * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33226584Sdim * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34226584Sdim * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35226584Sdim * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36226584Sdim * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37226584Sdim * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38226584Sdim ***********************license end**************************************/ 39226584Sdim 40226584Sdim 41226584Sdim 42226584Sdim 43226584Sdim 44226584Sdim 45226584Sdim/** 46226584Sdim * @file 47226584Sdim * Simple allocate only memory allocator. Used to allocate memory at application 48226584Sdim * start time. 49226584Sdim * 50226584Sdim * <hr>$Revision: 70030 $<hr> 51226584Sdim * 52226584Sdim */ 53226584Sdim 54226584Sdim#ifndef __CVMX_BOOTMEM_H__ 55226584Sdim#define __CVMX_BOOTMEM_H__ 56226584Sdim 57226584Sdim#ifdef __cplusplus 58226584Sdimextern "C" { 59226584Sdim#endif 60226584Sdim 61226584Sdim#define CVMX_BOOTMEM_NAME_LEN 128 /* Must be multiple of 8, changing breaks ABI */ 62226584Sdim#define CVMX_BOOTMEM_NUM_NAMED_BLOCKS 64 /* Can change without breaking ABI */ 63226584Sdim#define CVMX_BOOTMEM_ALIGNMENT_SIZE (16ull) /* minimum alignment of bootmem alloced blocks */ 64226584Sdim 65226584Sdim/* Flags for cvmx_bootmem_phy_mem* functions */ 66226584Sdim#define CVMX_BOOTMEM_FLAG_END_ALLOC (1 << 0) /* Allocate from end of block instead of beginning */ 67226584Sdim#define CVMX_BOOTMEM_FLAG_NO_LOCKING (1 << 1) /* Don't do any locking. */ 68226584Sdim 69226584Sdim/* Real physical addresses of memory regions */ 70226584Sdim#define OCTEON_DDR0_BASE (0x0ULL) 71226584Sdim#define OCTEON_DDR0_SIZE (0x010000000ULL) 72226584Sdim#define OCTEON_DDR1_BASE ((OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) ? 0x20000000ULL : 0x410000000ULL) 73226584Sdim#define OCTEON_DDR1_SIZE (0x010000000ULL) 74226584Sdim#define OCTEON_DDR2_BASE ((OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) ? 0x30000000ULL : 0x20000000ULL) 75226584Sdim#define OCTEON_DDR2_SIZE ((OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) ? 0x7d0000000ULL : 0x3e0000000ULL) 76226584Sdim#define OCTEON_MAX_PHY_MEM_SIZE ((OCTEON_IS_MODEL(OCTEON_CN68XX)) ? 128*1024*1024*1024ULL : (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) ? 32*1024*1024*1024ull : 16*1024*1024*1024ULL) 77226584Sdim 78226584Sdim/* First bytes of each free physical block of memory contain this structure, 79226584Sdim * which is used to maintain the free memory list. Since the bootloader is 80226584Sdim * only 32 bits, there is a union providing 64 and 32 bit versions. The 81226584Sdim * application init code converts addresses to 64 bit addresses before the 82226584Sdim * application starts. 83226584Sdim */ 84226584Sdimtypedef struct 85226584Sdim{ 86226584Sdim /* Note: these are referenced from assembly routines in the bootloader, so this structure 87226584Sdim ** should not be changed without changing those routines as well. */ 88226584Sdim uint64_t next_block_addr; 89226584Sdim uint64_t size; 90226584Sdim 91226584Sdim} cvmx_bootmem_block_header_t; 92226584Sdim 93226584Sdim 94226584Sdim/* Structure for named memory blocks 95226584Sdim** Number of descriptors 96226584Sdim** available can be changed without affecting compatiblity, 97226584Sdim** but name length changes require a bump in the bootmem 98226584Sdim** descriptor version 99226584Sdim** Note: This structure must be naturally 64 bit aligned, as a single 100226584Sdim** memory image will be used by both 32 and 64 bit programs. 101226584Sdim*/ 102226584Sdimstruct cvmx_bootmem_named_block_desc 103226584Sdim{ 104226584Sdim uint64_t base_addr; /**< Base address of named block */ 105226584Sdim uint64_t size; /**< Size actually allocated for named block (may differ from requested) */ 106226584Sdim char name[CVMX_BOOTMEM_NAME_LEN]; /**< name of named block */ 107226584Sdim}; 108226584Sdim 109226584Sdimtypedef struct cvmx_bootmem_named_block_desc cvmx_bootmem_named_block_desc_t; 110226584Sdim 111226584Sdim/* Current descriptor versions */ 112226584Sdim#define CVMX_BOOTMEM_DESC_MAJ_VER 3 /* CVMX bootmem descriptor major version */ 113226584Sdim#define CVMX_BOOTMEM_DESC_MIN_VER 0 /* CVMX bootmem descriptor minor version */ 114226584Sdim 115226584Sdim/* First three members of cvmx_bootmem_desc_t are left in original 116226584Sdim** positions for backwards compatibility. 117226584Sdim*/ 118226584Sdimtypedef struct 119226584Sdim{ 120226584Sdim uint32_t lock; /**< spinlock to control access to list */ 121226584Sdim uint32_t flags; /**< flags for indicating various conditions */ 122226584Sdim uint64_t head_addr; 123226584Sdim 124226584Sdim uint32_t major_version; /**< incremented changed when incompatible changes made */ 125 uint32_t minor_version; /**< incremented changed when compatible changes made, reset to zero when major incremented */ 126 uint64_t app_data_addr; 127 uint64_t app_data_size; 128 129 uint32_t named_block_num_blocks; /**< number of elements in named blocks array */ 130 uint32_t named_block_name_len; /**< length of name array in bootmem blocks */ 131 uint64_t named_block_array_addr; /**< address of named memory block descriptors */ 132 133} cvmx_bootmem_desc_t; 134 135 136/** 137 * Initialize the boot alloc memory structures. This is 138 * normally called inside of cvmx_user_app_init() 139 * 140 * @param mem_desc_addr Address of the free memory list 141 * @return 142 */ 143extern int cvmx_bootmem_init(uint64_t mem_desc_addr); 144 145 146/** 147 * Allocate a block of memory from the free list that was passed 148 * to the application by the bootloader. 149 * This is an allocate-only algorithm, so freeing memory is not possible. 150 * 151 * @param size Size in bytes of block to allocate 152 * @param alignment Alignment required - must be power of 2 153 * 154 * @return pointer to block of memory, NULL on error 155 */ 156extern void *cvmx_bootmem_alloc(uint64_t size, uint64_t alignment); 157 158/** 159 * Allocate a block of memory from the free list that was 160 * passed to the application by the bootloader at a specific 161 * address. This is an allocate-only algorithm, so 162 * freeing memory is not possible. Allocation will fail if 163 * memory cannot be allocated at the specified address. 164 * 165 * @param size Size in bytes of block to allocate 166 * @param address Physical address to allocate memory at. If this memory is not 167 * available, the allocation fails. 168 * @param alignment Alignment required - must be power of 2 169 * @return pointer to block of memory, NULL on error 170 */ 171extern void *cvmx_bootmem_alloc_address(uint64_t size, uint64_t address, uint64_t alignment); 172 173/** 174 * Allocate a block of memory from the free list that was 175 * passed to the application by the bootloader within a specified 176 * address range. This is an allocate-only algorithm, so 177 * freeing memory is not possible. Allocation will fail if 178 * memory cannot be allocated in the requested range. 179 * 180 * @param size Size in bytes of block to allocate 181 * @param min_addr defines the minimum address of the range 182 * @param max_addr defines the maximum address of the range 183 * @param alignment Alignment required - must be power of 2 184 * @param flags Flags to control options for the allocation. 185 * @return pointer to block of memory, NULL on error 186 */ 187extern void *cvmx_bootmem_alloc_range_flags(uint64_t size, uint64_t alignment, uint64_t min_addr, uint64_t max_addr, uint32_t flags); 188 189 190/** 191 * Allocate a block of memory from the free list that was 192 * passed to the application by the bootloader within a specified 193 * address range. This is an allocate-only algorithm, so 194 * freeing memory is not possible. Allocation will fail if 195 * memory cannot be allocated in the requested range. 196 * 197 * @param size Size in bytes of block to allocate 198 * @param min_addr defines the minimum address of the range 199 * @param max_addr defines the maximum address of the range 200 * @param alignment Alignment required - must be power of 2 201 * @return pointer to block of memory, NULL on error 202 */ 203extern void *cvmx_bootmem_alloc_range(uint64_t size, uint64_t alignment, uint64_t min_addr, uint64_t max_addr); 204 205 206/** 207 * Allocate a block of memory from the free list that was passed 208 * to the application by the bootloader, and assign it a name in the 209 * global named block table. (part of the cvmx_bootmem_descriptor_t structure) 210 * Named blocks can later be freed. 211 * 212 * @param size Size in bytes of block to allocate 213 * @param alignment Alignment required - must be power of 2 214 * @param name name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes 215 * 216 * @return pointer to block of memory, NULL on error 217 */ 218extern void *cvmx_bootmem_alloc_named(uint64_t size, uint64_t alignment, const char *name); 219 220/** 221 * Allocate a block of memory from the free list that was passed 222 * to the application by the bootloader, and assign it a name in the 223 * global named block table. (part of the cvmx_bootmem_descriptor_t structure) 224 * Named blocks can later be freed. 225 * 226 * @param size Size in bytes of block to allocate 227 * @param alignment Alignment required - must be power of 2 228 * @param name name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes 229 * @param flags Flags to control options for the allocation. 230 * 231 * @return pointer to block of memory, NULL on error 232 */ 233extern void *cvmx_bootmem_alloc_named_flags(uint64_t size, uint64_t alignment, const char *name, uint32_t flags); 234 235 236 237/** 238 * Allocate a block of memory from the free list that was passed 239 * to the application by the bootloader, and assign it a name in the 240 * global named block table. (part of the cvmx_bootmem_descriptor_t structure) 241 * Named blocks can later be freed. 242 * 243 * @param size Size in bytes of block to allocate 244 * @param address Physical address to allocate memory at. If this memory is not 245 * available, the allocation fails. 246 * @param name name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes 247 * 248 * @return pointer to block of memory, NULL on error 249 */ 250extern void *cvmx_bootmem_alloc_named_address(uint64_t size, uint64_t address, const char *name); 251 252 253 254/** 255 * Allocate a block of memory from a specific range of the free list that was passed 256 * to the application by the bootloader, and assign it a name in the 257 * global named block table. (part of the cvmx_bootmem_descriptor_t structure) 258 * Named blocks can later be freed. 259 * If request cannot be satisfied within the address range specified, NULL is returned 260 * 261 * @param size Size in bytes of block to allocate 262 * @param min_addr minimum address of range 263 * @param max_addr maximum address of range 264 * @param align Alignment of memory to be allocated. (must be a power of 2) 265 * @param name name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes 266 * 267 * @return pointer to block of memory, NULL on error 268 */ 269extern void *cvmx_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr, uint64_t max_addr, uint64_t align, const char *name); 270 271/** 272 * Allocate if needed a block of memory from a specific range of the free list that was passed 273 * to the application by the bootloader, and assign it a name in the 274 * global named block table. (part of the cvmx_bootmem_descriptor_t structure) 275 * Named blocks can later be freed. 276 * If the requested name block is already allocated, return the pointer to block of memory. 277 * If request cannot be satisfied within the address range specified, NULL is returned 278 * 279 * @param size Size in bytes of block to allocate 280 * @param min_addr minimum address of range 281 * @param max_addr maximum address of range 282 * @param align Alignment of memory to be allocated. (must be a power of 2) 283 * @param name name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes 284 * @param init Initialization function 285 * 286 * @return pointer to block of memory, NULL on error 287 */ 288extern void *cvmx_bootmem_alloc_named_range_once(uint64_t size, uint64_t min_addr, uint64_t max_addr, uint64_t align, const char *name, void (*init)(void*)); 289 290/** 291 * Frees a previously allocated named bootmem block. 292 * 293 * @param name name of block to free 294 * 295 * @return 0 on failure, 296 * !0 on success 297 */ 298extern int cvmx_bootmem_free_named(const char *name); 299 300 301/** 302 * Finds a named bootmem block by name. 303 * 304 * @param name name of block to free 305 * 306 * @return pointer to named block descriptor on success 307 * 0 on failure 308 */ 309const cvmx_bootmem_named_block_desc_t *cvmx_bootmem_find_named_block(const char *name); 310 311 312 313/** 314 * Returns the size of available memory in bytes, only 315 * counting blocks that are at least as big as the minimum block 316 * size. 317 * 318 * @param min_block_size 319 * Minimum block size to count in total. 320 * 321 * @return Number of bytes available for allocation that meet the block size requirement 322 */ 323uint64_t cvmx_bootmem_available_mem(uint64_t min_block_size); 324 325 326 327/** 328 * Prints out the list of named blocks that have been allocated 329 * along with their addresses and sizes. 330 * This is primarily used for debugging purposes 331 */ 332void cvmx_bootmem_print_named(void); 333 334 335/** 336 * Allocates a block of physical memory from the free list, at (optional) requested address and alignment. 337 * 338 * @param req_size size of region to allocate. All requests are rounded up to be a multiple CVMX_BOOTMEM_ALIGNMENT_SIZE bytes size 339 * @param address_min 340 * Minimum address that block can occupy. 341 * @param address_max 342 * Specifies the maximum address_min (inclusive) that the allocation can use. 343 * @param alignment Requested alignment of the block. If this alignment cannot be met, the allocation fails. 344 * This must be a power of 2. 345 * (Note: Alignment of CVMX_BOOTMEM_ALIGNMENT_SIZE bytes is required, and internally enforced. Requested alignments of 346 * less than CVMX_BOOTMEM_ALIGNMENT_SIZE are set to CVMX_BOOTMEM_ALIGNMENT_SIZE.) 347 * @param flags Flags to control options for the allocation. 348 * 349 * @return physical address of block allocated, or -1 on failure 350 */ 351int64_t cvmx_bootmem_phy_alloc(uint64_t req_size, uint64_t address_min, uint64_t address_max, uint64_t alignment, uint32_t flags); 352 353 354 355/** 356 * Allocates a named block of physical memory from the free list, at (optional) requested address and alignment. 357 * 358 * @param size size of region to allocate. All requests are rounded up to be a multiple CVMX_BOOTMEM_ALIGNMENT_SIZE bytes size 359 * @param min_addr 360 * Minimum address that block can occupy. 361 * @param max_addr 362 * Specifies the maximum address_min (inclusive) that the allocation can use. 363 * @param alignment Requested alignment of the block. If this alignment cannot be met, the allocation fails. 364 * This must be a power of 2. 365 * (Note: Alignment of CVMX_BOOTMEM_ALIGNMENT_SIZE bytes is required, and internally enforced. Requested alignments of 366 * less than CVMX_BOOTMEM_ALIGNMENT_SIZE are set to CVMX_BOOTMEM_ALIGNMENT_SIZE.) 367 * @param name name to assign to named block 368 * @param flags Flags to control options for the allocation. 369 * 370 * @return physical address of block allocated, or -1 on failure 371 */ 372int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr, uint64_t max_addr, uint64_t alignment, const char *name, uint32_t flags); 373 374 375/** 376 * Finds a named memory block by name. 377 * Also used for finding an unused entry in the named block table. 378 * 379 * @param name Name of memory block to find. 380 * If NULL pointer given, then finds unused descriptor, if available. 381 * @param flags Flags to control options for the allocation. 382 * 383 * @return Physical address of the memory block descriptor, zero if not 384 * found. If zero returned when name parameter is NULL, then no 385 * memory block descriptors are available. 386 */ 387uint64_t cvmx_bootmem_phy_named_block_find(const char *name, uint32_t flags); 388 389 390/** 391 * Returns the size of available memory in bytes, only 392 * counting blocks that are at least as big as the minimum block 393 * size. 394 * 395 * @param min_block_size 396 * Minimum block size to count in total. 397 * 398 * @return Number of bytes available for allocation that meet the block size requirement 399 */ 400uint64_t cvmx_bootmem_phy_available_mem(uint64_t min_block_size); 401 402/** 403 * Frees a named block. 404 * 405 * @param name name of block to free 406 * @param flags flags for passing options 407 * 408 * @return 0 on failure 409 * 1 on success 410 */ 411int cvmx_bootmem_phy_named_block_free(const char *name, uint32_t flags); 412 413/** 414 * Frees a block to the bootmem allocator list. This must 415 * be used with care, as the size provided must match the size 416 * of the block that was allocated, or the list will become 417 * corrupted. 418 * 419 * IMPORTANT: This is only intended to be used as part of named block 420 * frees and initial population of the free memory list. 421 * * 422 * 423 * @param phy_addr physical address of block 424 * @param size size of block in bytes. 425 * @param flags flags for passing options 426 * 427 * @return 1 on success, 428 * 0 on failure 429 */ 430int __cvmx_bootmem_phy_free(uint64_t phy_addr, uint64_t size, uint32_t flags); 431 432 433/** 434 * Prints the list of currently allocated named blocks 435 * 436 */ 437void cvmx_bootmem_phy_named_block_print(void); 438 439 440/** 441 * Prints the list of available memory. 442 * 443 */ 444void cvmx_bootmem_phy_list_print(void); 445 446 447 448/** 449 * This function initializes the free memory list used by cvmx_bootmem. 450 * This must be called before any allocations can be done. 451 * 452 * @param mem_size Total memory available, in bytes 453 * @param low_reserved_bytes 454 * Number of bytes to reserve (leave out of free list) at address 0x0. 455 * @param desc_buffer 456 * Buffer for the bootmem descriptor. This must be a 32 bit addressable 457 * address. 458 * 459 * @return 1 on success 460 * 0 on failure 461 */ 462int64_t cvmx_bootmem_phy_mem_list_init(uint64_t mem_size, uint32_t low_reserved_bytes, cvmx_bootmem_desc_t *desc_buffer); 463 464/** 465 * Locks the bootmem allocator. This is useful in certain situations 466 * where multiple allocations must be made without being interrupted. 467 * This should be used with the CVMX_BOOTMEM_FLAG_NO_LOCKING flag. 468 * 469 */ 470void cvmx_bootmem_lock(void); 471 472/** 473 * Unlocks the bootmem allocator. This is useful in certain situations 474 * where multiple allocations must be made without being interrupted. 475 * This should be used with the CVMX_BOOTMEM_FLAG_NO_LOCKING flag. 476 * 477 */ 478void cvmx_bootmem_unlock(void); 479 480/** 481 * Internal use function to get the current descriptor pointer */ 482void *__cvmx_bootmem_internal_get_desc_ptr(void); 483 484#ifdef __cplusplus 485} 486#endif 487 488#endif /* __CVMX_BOOTMEM_H__ */ 489