xref: /onnv-gate/usr/src/uts/i86pc/io/dr/dr_util.c (revision 12004:93f274d4a367)
1*12004Sjiang.liu@intel.com /*
2*12004Sjiang.liu@intel.com  * CDDL HEADER START
3*12004Sjiang.liu@intel.com  *
4*12004Sjiang.liu@intel.com  * The contents of this file are subject to the terms of the
5*12004Sjiang.liu@intel.com  * Common Development and Distribution License (the "License").
6*12004Sjiang.liu@intel.com  * You may not use this file except in compliance with the License.
7*12004Sjiang.liu@intel.com  *
8*12004Sjiang.liu@intel.com  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*12004Sjiang.liu@intel.com  * or http://www.opensolaris.org/os/licensing.
10*12004Sjiang.liu@intel.com  * See the License for the specific language governing permissions
11*12004Sjiang.liu@intel.com  * and limitations under the License.
12*12004Sjiang.liu@intel.com  *
13*12004Sjiang.liu@intel.com  * When distributing Covered Code, include this CDDL HEADER in each
14*12004Sjiang.liu@intel.com  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*12004Sjiang.liu@intel.com  * If applicable, add the following below this CDDL HEADER, with the
16*12004Sjiang.liu@intel.com  * fields enclosed by brackets "[]" replaced with your own identifying
17*12004Sjiang.liu@intel.com  * information: Portions Copyright [yyyy] [name of copyright owner]
18*12004Sjiang.liu@intel.com  *
19*12004Sjiang.liu@intel.com  * CDDL HEADER END
20*12004Sjiang.liu@intel.com  */
21*12004Sjiang.liu@intel.com 
22*12004Sjiang.liu@intel.com /*
23*12004Sjiang.liu@intel.com  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24*12004Sjiang.liu@intel.com  * Use is subject to license terms.
25*12004Sjiang.liu@intel.com  */
26*12004Sjiang.liu@intel.com 
27*12004Sjiang.liu@intel.com #include <sys/types.h>
28*12004Sjiang.liu@intel.com #include <sys/cmn_err.h>
29*12004Sjiang.liu@intel.com #include <sys/param.h>		/* for NULL */
30*12004Sjiang.liu@intel.com #include <sys/sbd_ioctl.h>
31*12004Sjiang.liu@intel.com #include <sys/dr_util.h>
32*12004Sjiang.liu@intel.com #include <sys/varargs.h>
33*12004Sjiang.liu@intel.com #include <sys/sysmacros.h>
34*12004Sjiang.liu@intel.com #include <sys/systm.h>
35*12004Sjiang.liu@intel.com 
36*12004Sjiang.liu@intel.com /* sbd_etab[] and sbd_etab_len provided by sbdgenerr.pl */
37*12004Sjiang.liu@intel.com extern sbd_etab_t sbd_etab[];
38*12004Sjiang.liu@intel.com extern int sbd_etab_len;
39*12004Sjiang.liu@intel.com 
40*12004Sjiang.liu@intel.com sbd_error_t *
sbd_err_new(int e_code,char * fmt,va_list args)41*12004Sjiang.liu@intel.com sbd_err_new(int e_code, char *fmt, va_list args)
42*12004Sjiang.liu@intel.com {
43*12004Sjiang.liu@intel.com 	sbd_error_t	*new;
44*12004Sjiang.liu@intel.com 
45*12004Sjiang.liu@intel.com 	new = GETSTRUCT(sbd_error_t, 1);
46*12004Sjiang.liu@intel.com 	new->e_code = e_code;
47*12004Sjiang.liu@intel.com 
48*12004Sjiang.liu@intel.com 	if (fmt)
49*12004Sjiang.liu@intel.com 		(void) vsnprintf(new->e_rsc, sizeof (new->e_rsc), fmt, args);
50*12004Sjiang.liu@intel.com 
51*12004Sjiang.liu@intel.com 	return (new);
52*12004Sjiang.liu@intel.com }
53*12004Sjiang.liu@intel.com 
54*12004Sjiang.liu@intel.com void
sbd_err_log(sbd_error_t * ep,int ce)55*12004Sjiang.liu@intel.com sbd_err_log(sbd_error_t *ep, int ce)
56*12004Sjiang.liu@intel.com {
57*12004Sjiang.liu@intel.com 	char		 buf[32];
58*12004Sjiang.liu@intel.com 	char		*fmt;
59*12004Sjiang.liu@intel.com 	char		*txt;
60*12004Sjiang.liu@intel.com 	int		 i;
61*12004Sjiang.liu@intel.com 	sbd_etab_t	*tp;
62*12004Sjiang.liu@intel.com 
63*12004Sjiang.liu@intel.com 	if (!ep)
64*12004Sjiang.liu@intel.com 		return;
65*12004Sjiang.liu@intel.com 
66*12004Sjiang.liu@intel.com 	if (ep->e_rsc[0] == '\0')
67*12004Sjiang.liu@intel.com 		fmt = "%s";
68*12004Sjiang.liu@intel.com 	else
69*12004Sjiang.liu@intel.com 		fmt = "%s: %s";
70*12004Sjiang.liu@intel.com 
71*12004Sjiang.liu@intel.com 	for (tp = sbd_etab, i = 0; i < sbd_etab_len; i++, tp++)
72*12004Sjiang.liu@intel.com 		if (ep->e_code >= tp->t_base && ep->e_code <= tp->t_bnd)
73*12004Sjiang.liu@intel.com 			break;
74*12004Sjiang.liu@intel.com 
75*12004Sjiang.liu@intel.com 	if (i < sbd_etab_len)
76*12004Sjiang.liu@intel.com 		txt = tp->t_text[ep->e_code - tp->t_base];
77*12004Sjiang.liu@intel.com 	else {
78*12004Sjiang.liu@intel.com 		(void) snprintf(buf, sizeof (buf), "error %d", ep->e_code);
79*12004Sjiang.liu@intel.com 		txt = buf;
80*12004Sjiang.liu@intel.com 	}
81*12004Sjiang.liu@intel.com 
82*12004Sjiang.liu@intel.com 	cmn_err(ce, fmt, txt, ep->e_rsc);
83*12004Sjiang.liu@intel.com }
84*12004Sjiang.liu@intel.com 
85*12004Sjiang.liu@intel.com void
sbd_err_clear(sbd_error_t ** ep)86*12004Sjiang.liu@intel.com sbd_err_clear(sbd_error_t **ep)
87*12004Sjiang.liu@intel.com {
88*12004Sjiang.liu@intel.com 	FREESTRUCT(*ep, sbd_error_t, 1);
89*12004Sjiang.liu@intel.com 	*ep = NULL;
90*12004Sjiang.liu@intel.com }
91*12004Sjiang.liu@intel.com 
92*12004Sjiang.liu@intel.com void
sbd_err_set_c(sbd_error_t ** ep,int ce,int e_code,char * fmt,...)93*12004Sjiang.liu@intel.com sbd_err_set_c(sbd_error_t **ep, int ce, int e_code, char *fmt, ...)
94*12004Sjiang.liu@intel.com {
95*12004Sjiang.liu@intel.com 	sbd_error_t	*tmp;
96*12004Sjiang.liu@intel.com 	va_list		args;
97*12004Sjiang.liu@intel.com 
98*12004Sjiang.liu@intel.com 	va_start(args, fmt);
99*12004Sjiang.liu@intel.com 
100*12004Sjiang.liu@intel.com 	tmp = sbd_err_new(e_code, fmt, args);
101*12004Sjiang.liu@intel.com 
102*12004Sjiang.liu@intel.com 	sbd_err_log(tmp, ce);
103*12004Sjiang.liu@intel.com 
104*12004Sjiang.liu@intel.com 	if (*ep == NULL)
105*12004Sjiang.liu@intel.com 		*ep = tmp;
106*12004Sjiang.liu@intel.com 	else
107*12004Sjiang.liu@intel.com 		sbd_err_clear(&tmp);
108*12004Sjiang.liu@intel.com 
109*12004Sjiang.liu@intel.com 	va_end(args);
110*12004Sjiang.liu@intel.com }
111*12004Sjiang.liu@intel.com 
112*12004Sjiang.liu@intel.com void
sbd_err_set(sbd_error_t ** ep,int ce,int e_code,char * fmt,...)113*12004Sjiang.liu@intel.com sbd_err_set(sbd_error_t **ep, int ce, int e_code, char *fmt, ...)
114*12004Sjiang.liu@intel.com {
115*12004Sjiang.liu@intel.com 	sbd_error_t	*tmp;
116*12004Sjiang.liu@intel.com 	va_list		args;
117*12004Sjiang.liu@intel.com 
118*12004Sjiang.liu@intel.com 	va_start(args, fmt);
119*12004Sjiang.liu@intel.com 
120*12004Sjiang.liu@intel.com 	tmp = sbd_err_new(e_code, fmt, args);
121*12004Sjiang.liu@intel.com 
122*12004Sjiang.liu@intel.com 	sbd_err_log(tmp, ce);
123*12004Sjiang.liu@intel.com 
124*12004Sjiang.liu@intel.com 	*ep = tmp;
125*12004Sjiang.liu@intel.com 
126*12004Sjiang.liu@intel.com 	va_end(args);
127*12004Sjiang.liu@intel.com }
128*12004Sjiang.liu@intel.com 
129*12004Sjiang.liu@intel.com sbd_error_t *
drerr_new_v(int e_code,char * fmt,va_list args)130*12004Sjiang.liu@intel.com drerr_new_v(int e_code, char *fmt, va_list args)
131*12004Sjiang.liu@intel.com {
132*12004Sjiang.liu@intel.com 	return (sbd_err_new(e_code, fmt, args));
133*12004Sjiang.liu@intel.com }
134*12004Sjiang.liu@intel.com 
135*12004Sjiang.liu@intel.com sbd_error_t *
drerr_new(int log,int e_code,char * fmt,...)136*12004Sjiang.liu@intel.com drerr_new(int log, int e_code, char *fmt, ...)
137*12004Sjiang.liu@intel.com {
138*12004Sjiang.liu@intel.com 	sbd_error_t	*ep;
139*12004Sjiang.liu@intel.com 	va_list		 args;
140*12004Sjiang.liu@intel.com 
141*12004Sjiang.liu@intel.com 	va_start(args, fmt);
142*12004Sjiang.liu@intel.com 	ep = sbd_err_new(e_code, fmt, args);
143*12004Sjiang.liu@intel.com 	va_end(args);
144*12004Sjiang.liu@intel.com 
145*12004Sjiang.liu@intel.com 	if (log)
146*12004Sjiang.liu@intel.com 		sbd_err_log(ep, CE_WARN);
147*12004Sjiang.liu@intel.com 
148*12004Sjiang.liu@intel.com 	return (ep);
149*12004Sjiang.liu@intel.com }
150*12004Sjiang.liu@intel.com 
151*12004Sjiang.liu@intel.com void
drerr_set_c(int log,sbd_error_t ** ep,int e_code,char * fmt,...)152*12004Sjiang.liu@intel.com drerr_set_c(int log, sbd_error_t **ep, int e_code, char *fmt, ...)
153*12004Sjiang.liu@intel.com {
154*12004Sjiang.liu@intel.com 	sbd_error_t	*err;
155*12004Sjiang.liu@intel.com 	va_list		 args;
156*12004Sjiang.liu@intel.com 
157*12004Sjiang.liu@intel.com 	va_start(args, fmt);
158*12004Sjiang.liu@intel.com 	err = sbd_err_new(e_code, fmt, args);
159*12004Sjiang.liu@intel.com 	va_end(args);
160*12004Sjiang.liu@intel.com 
161*12004Sjiang.liu@intel.com 	if (log)
162*12004Sjiang.liu@intel.com 		sbd_err_log(err, CE_WARN);
163*12004Sjiang.liu@intel.com 
164*12004Sjiang.liu@intel.com 	if (*ep == NULL)
165*12004Sjiang.liu@intel.com 		*ep = err;
166*12004Sjiang.liu@intel.com 	else
167*12004Sjiang.liu@intel.com 		sbd_err_clear(&err);
168*12004Sjiang.liu@intel.com }
169*12004Sjiang.liu@intel.com 
170*12004Sjiang.liu@intel.com 
171*12004Sjiang.liu@intel.com /*
172*12004Sjiang.liu@intel.com  * Memlist support.
173*12004Sjiang.liu@intel.com  */
174*12004Sjiang.liu@intel.com void
dr_memlist_delete(struct memlist * mlist)175*12004Sjiang.liu@intel.com dr_memlist_delete(struct memlist *mlist)
176*12004Sjiang.liu@intel.com {
177*12004Sjiang.liu@intel.com 	register struct memlist	*ml;
178*12004Sjiang.liu@intel.com 
179*12004Sjiang.liu@intel.com 	for (ml = mlist; ml; ml = mlist) {
180*12004Sjiang.liu@intel.com 		mlist = ml->ml_next;
181*12004Sjiang.liu@intel.com 		FREESTRUCT(ml, struct memlist, 1);
182*12004Sjiang.liu@intel.com 	}
183*12004Sjiang.liu@intel.com }
184*12004Sjiang.liu@intel.com 
185*12004Sjiang.liu@intel.com int
dr_memlist_intersect(struct memlist * al,struct memlist * bl)186*12004Sjiang.liu@intel.com dr_memlist_intersect(struct memlist *al, struct memlist *bl)
187*12004Sjiang.liu@intel.com {
188*12004Sjiang.liu@intel.com 	uint64_t	astart, aend, bstart, bend;
189*12004Sjiang.liu@intel.com 
190*12004Sjiang.liu@intel.com 	if ((al == NULL) || (bl == NULL))
191*12004Sjiang.liu@intel.com 		return (0);
192*12004Sjiang.liu@intel.com 
193*12004Sjiang.liu@intel.com 	aend = al->ml_address + al->ml_size;
194*12004Sjiang.liu@intel.com 	bstart = bl->ml_address;
195*12004Sjiang.liu@intel.com 	bend = bl->ml_address + bl->ml_size;
196*12004Sjiang.liu@intel.com 
197*12004Sjiang.liu@intel.com 	while (al && bl) {
198*12004Sjiang.liu@intel.com 		while (al && (aend <= bstart))
199*12004Sjiang.liu@intel.com 			if ((al = al->ml_next) != NULL)
200*12004Sjiang.liu@intel.com 				aend = al->ml_address + al->ml_size;
201*12004Sjiang.liu@intel.com 		if (al == NULL)
202*12004Sjiang.liu@intel.com 			return (0);
203*12004Sjiang.liu@intel.com 
204*12004Sjiang.liu@intel.com 		if ((astart = al->ml_address) <= bstart)
205*12004Sjiang.liu@intel.com 			return (1);
206*12004Sjiang.liu@intel.com 
207*12004Sjiang.liu@intel.com 		while (bl && (bend <= astart))
208*12004Sjiang.liu@intel.com 			if ((bl = bl->ml_next) != NULL)
209*12004Sjiang.liu@intel.com 				bend = bl->ml_address + bl->ml_size;
210*12004Sjiang.liu@intel.com 		if (bl == NULL)
211*12004Sjiang.liu@intel.com 			return (0);
212*12004Sjiang.liu@intel.com 
213*12004Sjiang.liu@intel.com 		if ((bstart = bl->ml_address) <= astart)
214*12004Sjiang.liu@intel.com 			return (1);
215*12004Sjiang.liu@intel.com 	}
216*12004Sjiang.liu@intel.com 
217*12004Sjiang.liu@intel.com 	return (0);
218*12004Sjiang.liu@intel.com }
219*12004Sjiang.liu@intel.com 
220*12004Sjiang.liu@intel.com void
dr_memlist_coalesce(struct memlist * mlist)221*12004Sjiang.liu@intel.com dr_memlist_coalesce(struct memlist *mlist)
222*12004Sjiang.liu@intel.com {
223*12004Sjiang.liu@intel.com 	uint64_t	end, nend;
224*12004Sjiang.liu@intel.com 
225*12004Sjiang.liu@intel.com 	if ((mlist == NULL) || (mlist->ml_next == NULL))
226*12004Sjiang.liu@intel.com 		return;
227*12004Sjiang.liu@intel.com 
228*12004Sjiang.liu@intel.com 	while (mlist->ml_next) {
229*12004Sjiang.liu@intel.com 		end = mlist->ml_address + mlist->ml_size;
230*12004Sjiang.liu@intel.com 		if (mlist->ml_next->ml_address <= end) {
231*12004Sjiang.liu@intel.com 			struct memlist 	*nl;
232*12004Sjiang.liu@intel.com 
233*12004Sjiang.liu@intel.com 			nend = mlist->ml_next->ml_address +
234*12004Sjiang.liu@intel.com 			    mlist->ml_next->ml_size;
235*12004Sjiang.liu@intel.com 			if (nend > end)
236*12004Sjiang.liu@intel.com 				mlist->ml_size += (nend - end);
237*12004Sjiang.liu@intel.com 			nl = mlist->ml_next;
238*12004Sjiang.liu@intel.com 			mlist->ml_next = mlist->ml_next->ml_next;
239*12004Sjiang.liu@intel.com 			if (nl) {
240*12004Sjiang.liu@intel.com 				FREESTRUCT(nl, struct memlist, 1);
241*12004Sjiang.liu@intel.com 			}
242*12004Sjiang.liu@intel.com 			if (mlist->ml_next)
243*12004Sjiang.liu@intel.com 				mlist->ml_next->ml_prev = mlist;
244*12004Sjiang.liu@intel.com 		} else {
245*12004Sjiang.liu@intel.com 			mlist = mlist->ml_next;
246*12004Sjiang.liu@intel.com 		}
247*12004Sjiang.liu@intel.com 	}
248*12004Sjiang.liu@intel.com }
249*12004Sjiang.liu@intel.com 
250*12004Sjiang.liu@intel.com #ifdef DEBUG
251*12004Sjiang.liu@intel.com void
memlist_dump(struct memlist * mlist)252*12004Sjiang.liu@intel.com memlist_dump(struct memlist *mlist)
253*12004Sjiang.liu@intel.com {
254*12004Sjiang.liu@intel.com 	register struct memlist *ml;
255*12004Sjiang.liu@intel.com 
256*12004Sjiang.liu@intel.com 	if (mlist == NULL)
257*12004Sjiang.liu@intel.com 		printf("memlist> EMPTY\n");
258*12004Sjiang.liu@intel.com 	else for (ml = mlist; ml; ml = ml->ml_next)
259*12004Sjiang.liu@intel.com 		printf("memlist> 0x%" PRIx64 ", 0x%" PRIx64 "\n",
260*12004Sjiang.liu@intel.com 		    ml->ml_address, ml->ml_size);
261*12004Sjiang.liu@intel.com }
262*12004Sjiang.liu@intel.com #endif
263*12004Sjiang.liu@intel.com 
264*12004Sjiang.liu@intel.com struct memlist *
dr_memlist_dup(struct memlist * mlist)265*12004Sjiang.liu@intel.com dr_memlist_dup(struct memlist *mlist)
266*12004Sjiang.liu@intel.com {
267*12004Sjiang.liu@intel.com 	struct memlist *hl = NULL, *tl, **mlp;
268*12004Sjiang.liu@intel.com 
269*12004Sjiang.liu@intel.com 	if (mlist == NULL)
270*12004Sjiang.liu@intel.com 		return (NULL);
271*12004Sjiang.liu@intel.com 
272*12004Sjiang.liu@intel.com 	mlp = &hl;
273*12004Sjiang.liu@intel.com 	tl = *mlp;
274*12004Sjiang.liu@intel.com 	for (; mlist; mlist = mlist->ml_next) {
275*12004Sjiang.liu@intel.com 		*mlp = GETSTRUCT(struct memlist, 1);
276*12004Sjiang.liu@intel.com 		(*mlp)->ml_address = mlist->ml_address;
277*12004Sjiang.liu@intel.com 		(*mlp)->ml_size = mlist->ml_size;
278*12004Sjiang.liu@intel.com 		(*mlp)->ml_prev = tl;
279*12004Sjiang.liu@intel.com 		tl = *mlp;
280*12004Sjiang.liu@intel.com 		mlp = &((*mlp)->ml_next);
281*12004Sjiang.liu@intel.com 	}
282*12004Sjiang.liu@intel.com 	*mlp = NULL;
283*12004Sjiang.liu@intel.com 
284*12004Sjiang.liu@intel.com 	return (hl);
285*12004Sjiang.liu@intel.com }
286*12004Sjiang.liu@intel.com 
287*12004Sjiang.liu@intel.com struct memlist *
dr_memlist_add_span(struct memlist * mlist,uint64_t base,uint64_t len)288*12004Sjiang.liu@intel.com dr_memlist_add_span(struct memlist *mlist, uint64_t base, uint64_t len)
289*12004Sjiang.liu@intel.com {
290*12004Sjiang.liu@intel.com 	struct memlist	*ml, *tl, *nl;
291*12004Sjiang.liu@intel.com 
292*12004Sjiang.liu@intel.com 	if (len == 0ull)
293*12004Sjiang.liu@intel.com 		return (NULL);
294*12004Sjiang.liu@intel.com 
295*12004Sjiang.liu@intel.com 	if (mlist == NULL) {
296*12004Sjiang.liu@intel.com 		mlist = GETSTRUCT(struct memlist, 1);
297*12004Sjiang.liu@intel.com 		mlist->ml_address = base;
298*12004Sjiang.liu@intel.com 		mlist->ml_size = len;
299*12004Sjiang.liu@intel.com 		mlist->ml_next = mlist->ml_prev = NULL;
300*12004Sjiang.liu@intel.com 
301*12004Sjiang.liu@intel.com 		return (mlist);
302*12004Sjiang.liu@intel.com 	}
303*12004Sjiang.liu@intel.com 
304*12004Sjiang.liu@intel.com 	for (tl = ml = mlist; ml; tl = ml, ml = ml->ml_next) {
305*12004Sjiang.liu@intel.com 		if (base < ml->ml_address) {
306*12004Sjiang.liu@intel.com 			if ((base + len) < ml->ml_address) {
307*12004Sjiang.liu@intel.com 				nl = GETSTRUCT(struct memlist, 1);
308*12004Sjiang.liu@intel.com 				nl->ml_address = base;
309*12004Sjiang.liu@intel.com 				nl->ml_size = len;
310*12004Sjiang.liu@intel.com 				nl->ml_next = ml;
311*12004Sjiang.liu@intel.com 				if ((nl->ml_prev = ml->ml_prev) != NULL)
312*12004Sjiang.liu@intel.com 					nl->ml_prev->ml_next = nl;
313*12004Sjiang.liu@intel.com 				ml->ml_prev = nl;
314*12004Sjiang.liu@intel.com 				if (mlist == ml)
315*12004Sjiang.liu@intel.com 					mlist = nl;
316*12004Sjiang.liu@intel.com 			} else {
317*12004Sjiang.liu@intel.com 				ml->ml_size = MAX((base + len),
318*12004Sjiang.liu@intel.com 				    (ml->ml_address + ml->ml_size)) - base;
319*12004Sjiang.liu@intel.com 				ml->ml_address = base;
320*12004Sjiang.liu@intel.com 			}
321*12004Sjiang.liu@intel.com 			break;
322*12004Sjiang.liu@intel.com 
323*12004Sjiang.liu@intel.com 		} else if (base <= (ml->ml_address + ml->ml_size)) {
324*12004Sjiang.liu@intel.com 			ml->ml_size = MAX((base + len),
325*12004Sjiang.liu@intel.com 			    (ml->ml_address + ml->ml_size)) -
326*12004Sjiang.liu@intel.com 			    MIN(ml->ml_address, base);
327*12004Sjiang.liu@intel.com 			ml->ml_address = MIN(ml->ml_address, base);
328*12004Sjiang.liu@intel.com 			break;
329*12004Sjiang.liu@intel.com 		}
330*12004Sjiang.liu@intel.com 	}
331*12004Sjiang.liu@intel.com 	if (ml == NULL) {
332*12004Sjiang.liu@intel.com 		nl = GETSTRUCT(struct memlist, 1);
333*12004Sjiang.liu@intel.com 		nl->ml_address = base;
334*12004Sjiang.liu@intel.com 		nl->ml_size = len;
335*12004Sjiang.liu@intel.com 		nl->ml_next = NULL;
336*12004Sjiang.liu@intel.com 		nl->ml_prev = tl;
337*12004Sjiang.liu@intel.com 		tl->ml_next = nl;
338*12004Sjiang.liu@intel.com 	}
339*12004Sjiang.liu@intel.com 
340*12004Sjiang.liu@intel.com 	dr_memlist_coalesce(mlist);
341*12004Sjiang.liu@intel.com 
342*12004Sjiang.liu@intel.com 	return (mlist);
343*12004Sjiang.liu@intel.com }
344*12004Sjiang.liu@intel.com 
345*12004Sjiang.liu@intel.com struct memlist *
dr_memlist_del_span(struct memlist * mlist,uint64_t base,uint64_t len)346*12004Sjiang.liu@intel.com dr_memlist_del_span(struct memlist *mlist, uint64_t base, uint64_t len)
347*12004Sjiang.liu@intel.com {
348*12004Sjiang.liu@intel.com 	uint64_t	end;
349*12004Sjiang.liu@intel.com 	struct memlist	*ml, *tl, *nlp;
350*12004Sjiang.liu@intel.com 
351*12004Sjiang.liu@intel.com 	if (mlist == NULL)
352*12004Sjiang.liu@intel.com 		return (NULL);
353*12004Sjiang.liu@intel.com 
354*12004Sjiang.liu@intel.com 	end = base + len;
355*12004Sjiang.liu@intel.com 	if ((end <= mlist->ml_address) || (base == end))
356*12004Sjiang.liu@intel.com 		return (mlist);
357*12004Sjiang.liu@intel.com 
358*12004Sjiang.liu@intel.com 	for (tl = ml = mlist; ml; tl = ml, ml = nlp) {
359*12004Sjiang.liu@intel.com 		uint64_t	mend;
360*12004Sjiang.liu@intel.com 
361*12004Sjiang.liu@intel.com 		nlp = ml->ml_next;
362*12004Sjiang.liu@intel.com 
363*12004Sjiang.liu@intel.com 		if (end <= ml->ml_address)
364*12004Sjiang.liu@intel.com 			break;
365*12004Sjiang.liu@intel.com 
366*12004Sjiang.liu@intel.com 		mend = ml->ml_address + ml->ml_size;
367*12004Sjiang.liu@intel.com 		if (base < mend) {
368*12004Sjiang.liu@intel.com 			if (base <= ml->ml_address) {
369*12004Sjiang.liu@intel.com 				ml->ml_address = end;
370*12004Sjiang.liu@intel.com 				if (end >= mend)
371*12004Sjiang.liu@intel.com 					ml->ml_size = 0ull;
372*12004Sjiang.liu@intel.com 				else
373*12004Sjiang.liu@intel.com 					ml->ml_size = mend - ml->ml_address;
374*12004Sjiang.liu@intel.com 			} else {
375*12004Sjiang.liu@intel.com 				ml->ml_size = base - ml->ml_address;
376*12004Sjiang.liu@intel.com 				if (end < mend) {
377*12004Sjiang.liu@intel.com 					struct memlist	*nl;
378*12004Sjiang.liu@intel.com 					/*
379*12004Sjiang.liu@intel.com 					 * splitting an memlist entry.
380*12004Sjiang.liu@intel.com 					 */
381*12004Sjiang.liu@intel.com 					nl = GETSTRUCT(struct memlist, 1);
382*12004Sjiang.liu@intel.com 					nl->ml_address = end;
383*12004Sjiang.liu@intel.com 					nl->ml_size = mend - nl->ml_address;
384*12004Sjiang.liu@intel.com 					if ((nl->ml_next = nlp) != NULL)
385*12004Sjiang.liu@intel.com 						nlp->ml_prev = nl;
386*12004Sjiang.liu@intel.com 					nl->ml_prev = ml;
387*12004Sjiang.liu@intel.com 					ml->ml_next = nl;
388*12004Sjiang.liu@intel.com 					nlp = nl;
389*12004Sjiang.liu@intel.com 				}
390*12004Sjiang.liu@intel.com 			}
391*12004Sjiang.liu@intel.com 			if (ml->ml_size == 0ull) {
392*12004Sjiang.liu@intel.com 				if (ml == mlist) {
393*12004Sjiang.liu@intel.com 					if ((mlist = nlp) != NULL)
394*12004Sjiang.liu@intel.com 						nlp->ml_prev = NULL;
395*12004Sjiang.liu@intel.com 					FREESTRUCT(ml, struct memlist, 1);
396*12004Sjiang.liu@intel.com 					if (mlist == NULL)
397*12004Sjiang.liu@intel.com 						break;
398*12004Sjiang.liu@intel.com 					ml = nlp;
399*12004Sjiang.liu@intel.com 				} else {
400*12004Sjiang.liu@intel.com 					if ((tl->ml_next = nlp) != NULL)
401*12004Sjiang.liu@intel.com 						nlp->ml_prev = tl;
402*12004Sjiang.liu@intel.com 					FREESTRUCT(ml, struct memlist, 1);
403*12004Sjiang.liu@intel.com 					ml = tl;
404*12004Sjiang.liu@intel.com 				}
405*12004Sjiang.liu@intel.com 			}
406*12004Sjiang.liu@intel.com 		}
407*12004Sjiang.liu@intel.com 	}
408*12004Sjiang.liu@intel.com 
409*12004Sjiang.liu@intel.com 	return (mlist);
410*12004Sjiang.liu@intel.com }
411*12004Sjiang.liu@intel.com 
412*12004Sjiang.liu@intel.com /*
413*12004Sjiang.liu@intel.com  * add span without merging
414*12004Sjiang.liu@intel.com  */
415*12004Sjiang.liu@intel.com struct memlist *
dr_memlist_cat_span(struct memlist * mlist,uint64_t base,uint64_t len)416*12004Sjiang.liu@intel.com dr_memlist_cat_span(struct memlist *mlist, uint64_t base, uint64_t len)
417*12004Sjiang.liu@intel.com {
418*12004Sjiang.liu@intel.com 	struct memlist	*ml, *tl, *nl;
419*12004Sjiang.liu@intel.com 
420*12004Sjiang.liu@intel.com 	if (len == 0ull)
421*12004Sjiang.liu@intel.com 		return (NULL);
422*12004Sjiang.liu@intel.com 
423*12004Sjiang.liu@intel.com 	if (mlist == NULL) {
424*12004Sjiang.liu@intel.com 		mlist = GETSTRUCT(struct memlist, 1);
425*12004Sjiang.liu@intel.com 		mlist->ml_address = base;
426*12004Sjiang.liu@intel.com 		mlist->ml_size = len;
427*12004Sjiang.liu@intel.com 		mlist->ml_next = mlist->ml_prev = NULL;
428*12004Sjiang.liu@intel.com 
429*12004Sjiang.liu@intel.com 		return (mlist);
430*12004Sjiang.liu@intel.com 	}
431*12004Sjiang.liu@intel.com 
432*12004Sjiang.liu@intel.com 	for (tl = ml = mlist; ml; tl = ml, ml = ml->ml_next) {
433*12004Sjiang.liu@intel.com 		if (base < ml->ml_address) {
434*12004Sjiang.liu@intel.com 			nl = GETSTRUCT(struct memlist, 1);
435*12004Sjiang.liu@intel.com 			nl->ml_address = base;
436*12004Sjiang.liu@intel.com 			nl->ml_size = len;
437*12004Sjiang.liu@intel.com 			nl->ml_next = ml;
438*12004Sjiang.liu@intel.com 			if ((nl->ml_prev = ml->ml_prev) != NULL)
439*12004Sjiang.liu@intel.com 				nl->ml_prev->ml_next = nl;
440*12004Sjiang.liu@intel.com 			ml->ml_prev = nl;
441*12004Sjiang.liu@intel.com 			if (mlist == ml)
442*12004Sjiang.liu@intel.com 				mlist = nl;
443*12004Sjiang.liu@intel.com 			break;
444*12004Sjiang.liu@intel.com 		}
445*12004Sjiang.liu@intel.com 	}
446*12004Sjiang.liu@intel.com 
447*12004Sjiang.liu@intel.com 	if (ml == NULL) {
448*12004Sjiang.liu@intel.com 		nl = GETSTRUCT(struct memlist, 1);
449*12004Sjiang.liu@intel.com 		nl->ml_address = base;
450*12004Sjiang.liu@intel.com 		nl->ml_size = len;
451*12004Sjiang.liu@intel.com 		nl->ml_next = NULL;
452*12004Sjiang.liu@intel.com 		nl->ml_prev = tl;
453*12004Sjiang.liu@intel.com 		tl->ml_next = nl;
454*12004Sjiang.liu@intel.com 	}
455*12004Sjiang.liu@intel.com 
456*12004Sjiang.liu@intel.com 	return (mlist);
457*12004Sjiang.liu@intel.com }
458