10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*1772Sjl139090 * Common Development and Distribution License (the "License"). 6*1772Sjl139090 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*1772Sjl139090 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23930Smathue * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <sys/types.h> 290Sstevel@tonic-gate #include <sys/cmn_err.h> 300Sstevel@tonic-gate #include <sys/param.h> /* for NULL */ 310Sstevel@tonic-gate #include <sys/sbd_ioctl.h> 320Sstevel@tonic-gate #include <sys/dr_util.h> 330Sstevel@tonic-gate #include <sys/varargs.h> 340Sstevel@tonic-gate #include <sys/sysmacros.h> 350Sstevel@tonic-gate #include <sys/systm.h> 360Sstevel@tonic-gate 370Sstevel@tonic-gate /* sbd_etab[] and sbd_etab_len provided by sbdgenerr.pl */ 380Sstevel@tonic-gate extern sbd_etab_t sbd_etab[]; 390Sstevel@tonic-gate extern int sbd_etab_len; 400Sstevel@tonic-gate 410Sstevel@tonic-gate sbd_error_t * 420Sstevel@tonic-gate sbd_err_new(int e_code, char *fmt, va_list args) 430Sstevel@tonic-gate { 440Sstevel@tonic-gate sbd_error_t *new; 450Sstevel@tonic-gate 460Sstevel@tonic-gate new = GETSTRUCT(sbd_error_t, 1); 470Sstevel@tonic-gate new->e_code = e_code; 480Sstevel@tonic-gate 490Sstevel@tonic-gate if (fmt) 500Sstevel@tonic-gate (void) vsnprintf(new->e_rsc, sizeof (new->e_rsc), fmt, args); 510Sstevel@tonic-gate 520Sstevel@tonic-gate return (new); 530Sstevel@tonic-gate } 540Sstevel@tonic-gate 550Sstevel@tonic-gate void 560Sstevel@tonic-gate sbd_err_log(sbd_error_t *ep, int ce) 570Sstevel@tonic-gate { 580Sstevel@tonic-gate char buf[32]; 590Sstevel@tonic-gate char *fmt; 600Sstevel@tonic-gate char *txt; 610Sstevel@tonic-gate int i; 620Sstevel@tonic-gate sbd_etab_t *tp; 630Sstevel@tonic-gate 640Sstevel@tonic-gate if (!ep) 650Sstevel@tonic-gate return; 660Sstevel@tonic-gate 670Sstevel@tonic-gate if (ep->e_rsc[0] == '\0') 680Sstevel@tonic-gate fmt = "%s"; 690Sstevel@tonic-gate else 700Sstevel@tonic-gate fmt = "%s: %s"; 710Sstevel@tonic-gate 720Sstevel@tonic-gate for (tp = sbd_etab, i = 0; i < sbd_etab_len; i++, tp++) 730Sstevel@tonic-gate if (ep->e_code >= tp->t_base && ep->e_code <= tp->t_bnd) 740Sstevel@tonic-gate break; 750Sstevel@tonic-gate 760Sstevel@tonic-gate if (i < sbd_etab_len) 770Sstevel@tonic-gate txt = tp->t_text[ep->e_code - tp->t_base]; 780Sstevel@tonic-gate else { 790Sstevel@tonic-gate snprintf(buf, sizeof (buf), "error %d", ep->e_code); 800Sstevel@tonic-gate txt = buf; 810Sstevel@tonic-gate } 820Sstevel@tonic-gate 830Sstevel@tonic-gate cmn_err(ce, fmt, txt, ep->e_rsc); 840Sstevel@tonic-gate } 850Sstevel@tonic-gate 860Sstevel@tonic-gate void 870Sstevel@tonic-gate sbd_err_clear(sbd_error_t **ep) 880Sstevel@tonic-gate { 890Sstevel@tonic-gate FREESTRUCT(*ep, sbd_error_t, 1); 900Sstevel@tonic-gate *ep = NULL; 910Sstevel@tonic-gate } 920Sstevel@tonic-gate 930Sstevel@tonic-gate void 940Sstevel@tonic-gate sbd_err_set_c(sbd_error_t **ep, int ce, int e_code, char *fmt, ...) 950Sstevel@tonic-gate { 960Sstevel@tonic-gate sbd_error_t *tmp; 970Sstevel@tonic-gate va_list args; 980Sstevel@tonic-gate 990Sstevel@tonic-gate va_start(args, fmt); 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate tmp = sbd_err_new(e_code, fmt, args); 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate sbd_err_log(tmp, ce); 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate if (*ep == NULL) 1060Sstevel@tonic-gate *ep = tmp; 1070Sstevel@tonic-gate else 1080Sstevel@tonic-gate sbd_err_clear(&tmp); 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate va_end(args); 1110Sstevel@tonic-gate } 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate void 1140Sstevel@tonic-gate sbd_err_set(sbd_error_t **ep, int ce, int e_code, char *fmt, ...) 1150Sstevel@tonic-gate { 1160Sstevel@tonic-gate sbd_error_t *tmp; 1170Sstevel@tonic-gate va_list args; 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate va_start(args, fmt); 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate tmp = sbd_err_new(e_code, fmt, args); 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate sbd_err_log(tmp, ce); 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate *ep = tmp; 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate va_end(args); 1280Sstevel@tonic-gate } 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate sbd_error_t * 1310Sstevel@tonic-gate drerr_new_v(int e_code, char *fmt, va_list args) 1320Sstevel@tonic-gate { 1330Sstevel@tonic-gate return (sbd_err_new(e_code, fmt, args)); 1340Sstevel@tonic-gate } 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate sbd_error_t * 1370Sstevel@tonic-gate drerr_new(int log, int e_code, char *fmt, ...) 1380Sstevel@tonic-gate { 1390Sstevel@tonic-gate sbd_error_t *ep; 1400Sstevel@tonic-gate va_list args; 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate va_start(args, fmt); 1430Sstevel@tonic-gate ep = sbd_err_new(e_code, fmt, args); 1440Sstevel@tonic-gate va_end(args); 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate if (log) 1470Sstevel@tonic-gate sbd_err_log(ep, CE_WARN); 1480Sstevel@tonic-gate 1490Sstevel@tonic-gate return (ep); 1500Sstevel@tonic-gate } 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate void 1530Sstevel@tonic-gate drerr_set_c(int log, sbd_error_t **ep, int e_code, char *fmt, ...) 1540Sstevel@tonic-gate { 1550Sstevel@tonic-gate sbd_error_t *err; 1560Sstevel@tonic-gate va_list args; 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate va_start(args, fmt); 1590Sstevel@tonic-gate err = sbd_err_new(e_code, fmt, args); 1600Sstevel@tonic-gate va_end(args); 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate if (log) 1630Sstevel@tonic-gate sbd_err_log(err, CE_WARN); 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate if (*ep == NULL) 1660Sstevel@tonic-gate *ep = err; 1670Sstevel@tonic-gate else 1680Sstevel@tonic-gate sbd_err_clear(&err); 1690Sstevel@tonic-gate } 1700Sstevel@tonic-gate 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate /* 1730Sstevel@tonic-gate * Memlist support. 1740Sstevel@tonic-gate */ 1750Sstevel@tonic-gate void 176*1772Sjl139090 dr_memlist_delete(struct memlist *mlist) 1770Sstevel@tonic-gate { 1780Sstevel@tonic-gate register struct memlist *ml; 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate for (ml = mlist; ml; ml = mlist) { 1810Sstevel@tonic-gate mlist = ml->next; 1820Sstevel@tonic-gate FREESTRUCT(ml, struct memlist, 1); 1830Sstevel@tonic-gate } 1840Sstevel@tonic-gate } 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate int 187*1772Sjl139090 dr_memlist_intersect(struct memlist *al, struct memlist *bl) 1880Sstevel@tonic-gate { 1890Sstevel@tonic-gate uint64_t astart, aend, bstart, bend; 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate if ((al == NULL) || (bl == NULL)) 1920Sstevel@tonic-gate return (0); 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate aend = al->address + al->size; 1950Sstevel@tonic-gate bstart = bl->address; 1960Sstevel@tonic-gate bend = bl->address + bl->size; 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate while (al && bl) { 1990Sstevel@tonic-gate while (al && (aend <= bstart)) 2000Sstevel@tonic-gate if ((al = al->next) != NULL) 2010Sstevel@tonic-gate aend = al->address + al->size; 2020Sstevel@tonic-gate if (al == NULL) 2030Sstevel@tonic-gate return (0); 2040Sstevel@tonic-gate 2050Sstevel@tonic-gate if ((astart = al->address) <= bstart) 2060Sstevel@tonic-gate return (1); 2070Sstevel@tonic-gate 2080Sstevel@tonic-gate while (bl && (bend <= astart)) 2090Sstevel@tonic-gate if ((bl = bl->next) != NULL) 2100Sstevel@tonic-gate bend = bl->address + bl->size; 2110Sstevel@tonic-gate if (bl == NULL) 2120Sstevel@tonic-gate return (0); 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate if ((bstart = bl->address) <= astart) 2150Sstevel@tonic-gate return (1); 2160Sstevel@tonic-gate } 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate return (0); 2190Sstevel@tonic-gate } 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate void 222*1772Sjl139090 dr_memlist_coalesce(struct memlist *mlist) 2230Sstevel@tonic-gate { 2240Sstevel@tonic-gate uint64_t end, nend; 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate if ((mlist == NULL) || (mlist->next == NULL)) 2270Sstevel@tonic-gate return; 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate while (mlist->next) { 2300Sstevel@tonic-gate end = mlist->address + mlist->size; 2310Sstevel@tonic-gate if (mlist->next->address <= end) { 2320Sstevel@tonic-gate struct memlist *nl; 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate nend = mlist->next->address + mlist->next->size; 2350Sstevel@tonic-gate if (nend > end) 2360Sstevel@tonic-gate mlist->size += (nend - end); 2370Sstevel@tonic-gate nl = mlist->next; 2380Sstevel@tonic-gate mlist->next = mlist->next->next; 2390Sstevel@tonic-gate if (nl) { 2400Sstevel@tonic-gate FREESTRUCT(nl, struct memlist, 1); 2410Sstevel@tonic-gate } 2420Sstevel@tonic-gate if (mlist->next) 2430Sstevel@tonic-gate mlist->next->prev = mlist; 2440Sstevel@tonic-gate } else { 2450Sstevel@tonic-gate mlist = mlist->next; 2460Sstevel@tonic-gate } 2470Sstevel@tonic-gate } 2480Sstevel@tonic-gate } 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate #ifdef DEBUG 2510Sstevel@tonic-gate void 2520Sstevel@tonic-gate memlist_dump(struct memlist *mlist) 2530Sstevel@tonic-gate { 2540Sstevel@tonic-gate register struct memlist *ml; 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate if (mlist == NULL) 2570Sstevel@tonic-gate printf("memlist> EMPTY\n"); 2580Sstevel@tonic-gate else for (ml = mlist; ml; ml = ml->next) 259930Smathue printf("memlist> 0x%lx, 0x%lx\n", ml->address, ml->size); 2600Sstevel@tonic-gate } 2610Sstevel@tonic-gate #endif 262*1772Sjl139090 263*1772Sjl139090 struct memlist * 264*1772Sjl139090 dr_memlist_dup(struct memlist *mlist) 265*1772Sjl139090 { 266*1772Sjl139090 struct memlist *hl = NULL, *tl, **mlp; 267*1772Sjl139090 268*1772Sjl139090 if (mlist == NULL) 269*1772Sjl139090 return (NULL); 270*1772Sjl139090 271*1772Sjl139090 mlp = &hl; 272*1772Sjl139090 tl = *mlp; 273*1772Sjl139090 for (; mlist; mlist = mlist->next) { 274*1772Sjl139090 *mlp = GETSTRUCT(struct memlist, 1); 275*1772Sjl139090 (*mlp)->address = mlist->address; 276*1772Sjl139090 (*mlp)->size = mlist->size; 277*1772Sjl139090 (*mlp)->prev = tl; 278*1772Sjl139090 tl = *mlp; 279*1772Sjl139090 mlp = &((*mlp)->next); 280*1772Sjl139090 } 281*1772Sjl139090 *mlp = NULL; 282*1772Sjl139090 283*1772Sjl139090 return (hl); 284*1772Sjl139090 } 285*1772Sjl139090 286*1772Sjl139090 struct memlist * 287*1772Sjl139090 dr_memlist_add_span(struct memlist *mlist, uint64_t base, uint64_t len) 288*1772Sjl139090 { 289*1772Sjl139090 struct memlist *ml, *tl, *nl; 290*1772Sjl139090 291*1772Sjl139090 if (len == 0ull) 292*1772Sjl139090 return (NULL); 293*1772Sjl139090 294*1772Sjl139090 if (mlist == NULL) { 295*1772Sjl139090 mlist = GETSTRUCT(struct memlist, 1); 296*1772Sjl139090 mlist->address = base; 297*1772Sjl139090 mlist->size = len; 298*1772Sjl139090 mlist->next = mlist->prev = NULL; 299*1772Sjl139090 300*1772Sjl139090 return (mlist); 301*1772Sjl139090 } 302*1772Sjl139090 303*1772Sjl139090 for (tl = ml = mlist; ml; tl = ml, ml = ml->next) { 304*1772Sjl139090 if (base < ml->address) { 305*1772Sjl139090 if ((base + len) < ml->address) { 306*1772Sjl139090 nl = GETSTRUCT(struct memlist, 1); 307*1772Sjl139090 nl->address = base; 308*1772Sjl139090 nl->size = len; 309*1772Sjl139090 nl->next = ml; 310*1772Sjl139090 if ((nl->prev = ml->prev) != NULL) 311*1772Sjl139090 nl->prev->next = nl; 312*1772Sjl139090 ml->prev = nl; 313*1772Sjl139090 if (mlist == ml) 314*1772Sjl139090 mlist = nl; 315*1772Sjl139090 } else { 316*1772Sjl139090 ml->size = MAX((base + len), 317*1772Sjl139090 (ml->address + ml->size)) - 318*1772Sjl139090 base; 319*1772Sjl139090 ml->address = base; 320*1772Sjl139090 } 321*1772Sjl139090 break; 322*1772Sjl139090 323*1772Sjl139090 } else if (base <= (ml->address + ml->size)) { 324*1772Sjl139090 ml->size = MAX((base + len), 325*1772Sjl139090 (ml->address + ml->size)) - 326*1772Sjl139090 MIN(ml->address, base); 327*1772Sjl139090 ml->address = MIN(ml->address, base); 328*1772Sjl139090 break; 329*1772Sjl139090 } 330*1772Sjl139090 } 331*1772Sjl139090 if (ml == NULL) { 332*1772Sjl139090 nl = GETSTRUCT(struct memlist, 1); 333*1772Sjl139090 nl->address = base; 334*1772Sjl139090 nl->size = len; 335*1772Sjl139090 nl->next = NULL; 336*1772Sjl139090 nl->prev = tl; 337*1772Sjl139090 tl->next = nl; 338*1772Sjl139090 } 339*1772Sjl139090 340*1772Sjl139090 dr_memlist_coalesce(mlist); 341*1772Sjl139090 342*1772Sjl139090 return (mlist); 343*1772Sjl139090 } 344*1772Sjl139090 345*1772Sjl139090 struct memlist * 346*1772Sjl139090 dr_memlist_del_span(struct memlist *mlist, uint64_t base, uint64_t len) 347*1772Sjl139090 { 348*1772Sjl139090 uint64_t end; 349*1772Sjl139090 struct memlist *ml, *tl, *nlp; 350*1772Sjl139090 351*1772Sjl139090 if (mlist == NULL) 352*1772Sjl139090 return (NULL); 353*1772Sjl139090 354*1772Sjl139090 end = base + len; 355*1772Sjl139090 if ((end <= mlist->address) || (base == end)) 356*1772Sjl139090 return (mlist); 357*1772Sjl139090 358*1772Sjl139090 for (tl = ml = mlist; ml; tl = ml, ml = nlp) { 359*1772Sjl139090 uint64_t mend; 360*1772Sjl139090 361*1772Sjl139090 nlp = ml->next; 362*1772Sjl139090 363*1772Sjl139090 if (end <= ml->address) 364*1772Sjl139090 break; 365*1772Sjl139090 366*1772Sjl139090 mend = ml->address + ml->size; 367*1772Sjl139090 if (base < mend) { 368*1772Sjl139090 if (base <= ml->address) { 369*1772Sjl139090 ml->address = end; 370*1772Sjl139090 if (end >= mend) 371*1772Sjl139090 ml->size = 0ull; 372*1772Sjl139090 else 373*1772Sjl139090 ml->size = mend - ml->address; 374*1772Sjl139090 } else { 375*1772Sjl139090 ml->size = base - ml->address; 376*1772Sjl139090 if (end < mend) { 377*1772Sjl139090 struct memlist *nl; 378*1772Sjl139090 /* 379*1772Sjl139090 * splitting an memlist entry. 380*1772Sjl139090 */ 381*1772Sjl139090 nl = GETSTRUCT(struct memlist, 1); 382*1772Sjl139090 nl->address = end; 383*1772Sjl139090 nl->size = mend - nl->address; 384*1772Sjl139090 if ((nl->next = nlp) != NULL) 385*1772Sjl139090 nlp->prev = nl; 386*1772Sjl139090 nl->prev = ml; 387*1772Sjl139090 ml->next = nl; 388*1772Sjl139090 nlp = nl; 389*1772Sjl139090 } 390*1772Sjl139090 } 391*1772Sjl139090 if (ml->size == 0ull) { 392*1772Sjl139090 if (ml == mlist) { 393*1772Sjl139090 if ((mlist = nlp) != NULL) 394*1772Sjl139090 nlp->prev = NULL; 395*1772Sjl139090 FREESTRUCT(ml, struct memlist, 1); 396*1772Sjl139090 if (mlist == NULL) 397*1772Sjl139090 break; 398*1772Sjl139090 ml = nlp; 399*1772Sjl139090 } else { 400*1772Sjl139090 if ((tl->next = nlp) != NULL) 401*1772Sjl139090 nlp->prev = tl; 402*1772Sjl139090 FREESTRUCT(ml, struct memlist, 1); 403*1772Sjl139090 ml = tl; 404*1772Sjl139090 } 405*1772Sjl139090 } 406*1772Sjl139090 } 407*1772Sjl139090 } 408*1772Sjl139090 409*1772Sjl139090 return (mlist); 410*1772Sjl139090 } 411*1772Sjl139090 412*1772Sjl139090 /* 413*1772Sjl139090 * add span without merging 414*1772Sjl139090 */ 415*1772Sjl139090 struct memlist * 416*1772Sjl139090 dr_memlist_cat_span(struct memlist *mlist, uint64_t base, uint64_t len) 417*1772Sjl139090 { 418*1772Sjl139090 struct memlist *ml, *tl, *nl; 419*1772Sjl139090 420*1772Sjl139090 if (len == 0ull) 421*1772Sjl139090 return (NULL); 422*1772Sjl139090 423*1772Sjl139090 if (mlist == NULL) { 424*1772Sjl139090 mlist = GETSTRUCT(struct memlist, 1); 425*1772Sjl139090 mlist->address = base; 426*1772Sjl139090 mlist->size = len; 427*1772Sjl139090 mlist->next = mlist->prev = NULL; 428*1772Sjl139090 429*1772Sjl139090 return (mlist); 430*1772Sjl139090 } 431*1772Sjl139090 432*1772Sjl139090 for (tl = ml = mlist; ml; tl = ml, ml = ml->next) { 433*1772Sjl139090 if (base < ml->address) { 434*1772Sjl139090 nl = GETSTRUCT(struct memlist, 1); 435*1772Sjl139090 nl->address = base; 436*1772Sjl139090 nl->size = len; 437*1772Sjl139090 nl->next = ml; 438*1772Sjl139090 if ((nl->prev = ml->prev) != NULL) 439*1772Sjl139090 nl->prev->next = nl; 440*1772Sjl139090 ml->prev = nl; 441*1772Sjl139090 if (mlist == ml) 442*1772Sjl139090 mlist = nl; 443*1772Sjl139090 break; 444*1772Sjl139090 } 445*1772Sjl139090 } 446*1772Sjl139090 447*1772Sjl139090 if (ml == NULL) { 448*1772Sjl139090 nl = GETSTRUCT(struct memlist, 1); 449*1772Sjl139090 nl->address = base; 450*1772Sjl139090 nl->size = len; 451*1772Sjl139090 nl->next = NULL; 452*1772Sjl139090 nl->prev = tl; 453*1772Sjl139090 tl->next = nl; 454*1772Sjl139090 } 455*1772Sjl139090 456*1772Sjl139090 return (mlist); 457*1772Sjl139090 } 458