1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/param.h> 28 #include <sys/sysmacros.h> 29 #include <sys/machparam.h> 30 #include <sys/promif.h> 31 #include <sys/bootconf.h> 32 #include <sys/salib.h> 33 34 extern caddr_t memlistpage; 35 36 /* Always pts to the next free link in the headtable */ 37 /* i.e. it is always memlistpage+tableoffset */ 38 caddr_t tablep = NULL; 39 static int table_freespace; 40 41 /* 42 * Function prototypes 43 */ 44 extern void reset_alloc(void); 45 46 void 47 print_memlist(struct memlist *av) 48 { 49 struct memlist *p = av; 50 51 while (p != NULL) { 52 printf("addr = 0x%x:0x%x, size = 0x%x:0x%x\n", 53 (uint_t)(p->ml_address >> 32), (uint_t)p->ml_address, 54 (uint_t)(p->ml_size >> 32), (uint_t)p->ml_size); 55 p = p->ml_next; 56 } 57 58 } 59 60 /* allocate room for n bytes, return 8-byte aligned address */ 61 void * 62 getlink(uint_t n) 63 { 64 void *p; 65 extern int pagesize; 66 67 if (memlistpage == NULL) 68 reset_alloc(); 69 70 if (tablep == NULL) { 71 /* 72 * Took the following 2 lines out of above test for 73 * memlistpage == null so we can initialize table_freespace 74 */ 75 table_freespace = pagesize - sizeof (struct bsys_mem); 76 tablep = memlistpage + sizeof (struct bsys_mem); 77 tablep = (caddr_t)roundup((uintptr_t)tablep, 8); 78 } 79 80 if (n == 0) 81 return (NULL); 82 83 n = roundup(n, 8); 84 p = tablep; 85 86 table_freespace -= n; 87 tablep += n; 88 if (table_freespace <= 0) { 89 char buf[80]; 90 91 (void) sprintf(buf, 92 "Boot getlink(): no memlist space (need %d)\n", n); 93 prom_panic(buf); 94 } 95 96 return (p); 97 } 98 99 100 /* 101 * This is the number of memlist structures allocated in one shot. kept 102 * to small number to reduce wastage of memory, it should not be too small 103 * to slow down boot. 104 */ 105 #define ALLOC_SZ 5 106 static struct memlist *free_memlist_ptr = NULL; 107 108 /* 109 * Free memory lists are maintained as simple single linked lists. 110 * get_memlist_struct returns a memlist structure without initializing 111 * any of the fields. It is caller's responsibility to do that. 112 */ 113 114 struct memlist * 115 get_memlist_struct(void) 116 { 117 struct memlist *ptr; 118 int i; 119 120 if (free_memlist_ptr == NULL) { 121 ptr = free_memlist_ptr = getlink(ALLOC_SZ * 122 sizeof (struct memlist)); 123 bzero(free_memlist_ptr, (ALLOC_SZ * sizeof (struct memlist))); 124 for (i = 0; i < ALLOC_SZ; i++) 125 ptr[i].ml_next = &ptr[i+1]; 126 ptr[i-1].ml_next = NULL; 127 } 128 ptr = free_memlist_ptr; 129 free_memlist_ptr = ptr->ml_next; 130 return (ptr); 131 } 132 133 /* 134 * Return memlist structure to free list. 135 */ 136 void 137 add_to_freelist(struct memlist *ptr) 138 { 139 struct memlist *tmp; 140 141 if (free_memlist_ptr == NULL) { 142 free_memlist_ptr = ptr; 143 } else { 144 for (tmp = free_memlist_ptr; tmp->ml_next; tmp = tmp->ml_next) 145 ; 146 tmp->ml_next = ptr; 147 } 148 } 149