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
print_memlist(struct memlist * av)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 *
getlink(uint_t n)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 *
get_memlist_struct(void)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
add_to_freelist(struct memlist * ptr)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