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 51772Sjl139090 * Common Development and Distribution License (the "License"). 61772Sjl139090 * 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 */ 21*11311SSurya.Prakki@Sun.COM 220Sstevel@tonic-gate /* 23*11311SSurya.Prakki@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24930Smathue * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #include <sys/types.h> 280Sstevel@tonic-gate #include <sys/cmn_err.h> 290Sstevel@tonic-gate #include <sys/param.h> /* for NULL */ 300Sstevel@tonic-gate #include <sys/sbd_ioctl.h> 310Sstevel@tonic-gate #include <sys/dr_util.h> 320Sstevel@tonic-gate #include <sys/varargs.h> 330Sstevel@tonic-gate #include <sys/sysmacros.h> 340Sstevel@tonic-gate #include <sys/systm.h> 350Sstevel@tonic-gate 360Sstevel@tonic-gate /* sbd_etab[] and sbd_etab_len provided by sbdgenerr.pl */ 370Sstevel@tonic-gate extern sbd_etab_t sbd_etab[]; 380Sstevel@tonic-gate extern int sbd_etab_len; 390Sstevel@tonic-gate 400Sstevel@tonic-gate sbd_error_t * 410Sstevel@tonic-gate sbd_err_new(int e_code, char *fmt, va_list args) 420Sstevel@tonic-gate { 430Sstevel@tonic-gate sbd_error_t *new; 440Sstevel@tonic-gate 450Sstevel@tonic-gate new = GETSTRUCT(sbd_error_t, 1); 460Sstevel@tonic-gate new->e_code = e_code; 470Sstevel@tonic-gate 480Sstevel@tonic-gate if (fmt) 490Sstevel@tonic-gate (void) vsnprintf(new->e_rsc, sizeof (new->e_rsc), fmt, args); 500Sstevel@tonic-gate 510Sstevel@tonic-gate return (new); 520Sstevel@tonic-gate } 530Sstevel@tonic-gate 540Sstevel@tonic-gate void 550Sstevel@tonic-gate sbd_err_log(sbd_error_t *ep, int ce) 560Sstevel@tonic-gate { 570Sstevel@tonic-gate char buf[32]; 580Sstevel@tonic-gate char *fmt; 590Sstevel@tonic-gate char *txt; 600Sstevel@tonic-gate int i; 610Sstevel@tonic-gate sbd_etab_t *tp; 620Sstevel@tonic-gate 630Sstevel@tonic-gate if (!ep) 640Sstevel@tonic-gate return; 650Sstevel@tonic-gate 660Sstevel@tonic-gate if (ep->e_rsc[0] == '\0') 670Sstevel@tonic-gate fmt = "%s"; 680Sstevel@tonic-gate else 690Sstevel@tonic-gate fmt = "%s: %s"; 700Sstevel@tonic-gate 710Sstevel@tonic-gate for (tp = sbd_etab, i = 0; i < sbd_etab_len; i++, tp++) 720Sstevel@tonic-gate if (ep->e_code >= tp->t_base && ep->e_code <= tp->t_bnd) 730Sstevel@tonic-gate break; 740Sstevel@tonic-gate 750Sstevel@tonic-gate if (i < sbd_etab_len) 760Sstevel@tonic-gate txt = tp->t_text[ep->e_code - tp->t_base]; 770Sstevel@tonic-gate else { 78*11311SSurya.Prakki@Sun.COM (void) snprintf(buf, sizeof (buf), "error %d", ep->e_code); 790Sstevel@tonic-gate txt = buf; 800Sstevel@tonic-gate } 810Sstevel@tonic-gate 820Sstevel@tonic-gate cmn_err(ce, fmt, txt, ep->e_rsc); 830Sstevel@tonic-gate } 840Sstevel@tonic-gate 850Sstevel@tonic-gate void 860Sstevel@tonic-gate sbd_err_clear(sbd_error_t **ep) 870Sstevel@tonic-gate { 880Sstevel@tonic-gate FREESTRUCT(*ep, sbd_error_t, 1); 890Sstevel@tonic-gate *ep = NULL; 900Sstevel@tonic-gate } 910Sstevel@tonic-gate 920Sstevel@tonic-gate void 930Sstevel@tonic-gate sbd_err_set_c(sbd_error_t **ep, int ce, int e_code, char *fmt, ...) 940Sstevel@tonic-gate { 950Sstevel@tonic-gate sbd_error_t *tmp; 960Sstevel@tonic-gate va_list args; 970Sstevel@tonic-gate 980Sstevel@tonic-gate va_start(args, fmt); 990Sstevel@tonic-gate 1000Sstevel@tonic-gate tmp = sbd_err_new(e_code, fmt, args); 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate sbd_err_log(tmp, ce); 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate if (*ep == NULL) 1050Sstevel@tonic-gate *ep = tmp; 1060Sstevel@tonic-gate else 1070Sstevel@tonic-gate sbd_err_clear(&tmp); 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate va_end(args); 1100Sstevel@tonic-gate } 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate void 1130Sstevel@tonic-gate sbd_err_set(sbd_error_t **ep, int ce, int e_code, char *fmt, ...) 1140Sstevel@tonic-gate { 1150Sstevel@tonic-gate sbd_error_t *tmp; 1160Sstevel@tonic-gate va_list args; 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate va_start(args, fmt); 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate tmp = sbd_err_new(e_code, fmt, args); 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate sbd_err_log(tmp, ce); 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate *ep = tmp; 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate va_end(args); 1270Sstevel@tonic-gate } 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate sbd_error_t * 1300Sstevel@tonic-gate drerr_new_v(int e_code, char *fmt, va_list args) 1310Sstevel@tonic-gate { 1320Sstevel@tonic-gate return (sbd_err_new(e_code, fmt, args)); 1330Sstevel@tonic-gate } 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate sbd_error_t * 1360Sstevel@tonic-gate drerr_new(int log, int e_code, char *fmt, ...) 1370Sstevel@tonic-gate { 1380Sstevel@tonic-gate sbd_error_t *ep; 1390Sstevel@tonic-gate va_list args; 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate va_start(args, fmt); 1420Sstevel@tonic-gate ep = sbd_err_new(e_code, fmt, args); 1430Sstevel@tonic-gate va_end(args); 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate if (log) 1460Sstevel@tonic-gate sbd_err_log(ep, CE_WARN); 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate return (ep); 1490Sstevel@tonic-gate } 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate void 1520Sstevel@tonic-gate drerr_set_c(int log, sbd_error_t **ep, int e_code, char *fmt, ...) 1530Sstevel@tonic-gate { 1540Sstevel@tonic-gate sbd_error_t *err; 1550Sstevel@tonic-gate va_list args; 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate va_start(args, fmt); 1580Sstevel@tonic-gate err = sbd_err_new(e_code, fmt, args); 1590Sstevel@tonic-gate va_end(args); 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate if (log) 1620Sstevel@tonic-gate sbd_err_log(err, CE_WARN); 1630Sstevel@tonic-gate 1640Sstevel@tonic-gate if (*ep == NULL) 1650Sstevel@tonic-gate *ep = err; 1660Sstevel@tonic-gate else 1670Sstevel@tonic-gate sbd_err_clear(&err); 1680Sstevel@tonic-gate } 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate 1710Sstevel@tonic-gate /* 1720Sstevel@tonic-gate * Memlist support. 1730Sstevel@tonic-gate */ 1740Sstevel@tonic-gate void 1751772Sjl139090 dr_memlist_delete(struct memlist *mlist) 1760Sstevel@tonic-gate { 1770Sstevel@tonic-gate register struct memlist *ml; 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate for (ml = mlist; ml; ml = mlist) { 1800Sstevel@tonic-gate mlist = ml->next; 1810Sstevel@tonic-gate FREESTRUCT(ml, struct memlist, 1); 1820Sstevel@tonic-gate } 1830Sstevel@tonic-gate } 1840Sstevel@tonic-gate 1850Sstevel@tonic-gate int 1861772Sjl139090 dr_memlist_intersect(struct memlist *al, struct memlist *bl) 1870Sstevel@tonic-gate { 1880Sstevel@tonic-gate uint64_t astart, aend, bstart, bend; 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate if ((al == NULL) || (bl == NULL)) 1910Sstevel@tonic-gate return (0); 1920Sstevel@tonic-gate 1930Sstevel@tonic-gate aend = al->address + al->size; 1940Sstevel@tonic-gate bstart = bl->address; 1950Sstevel@tonic-gate bend = bl->address + bl->size; 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate while (al && bl) { 1980Sstevel@tonic-gate while (al && (aend <= bstart)) 1990Sstevel@tonic-gate if ((al = al->next) != NULL) 2000Sstevel@tonic-gate aend = al->address + al->size; 2010Sstevel@tonic-gate if (al == NULL) 2020Sstevel@tonic-gate return (0); 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate if ((astart = al->address) <= bstart) 2050Sstevel@tonic-gate return (1); 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate while (bl && (bend <= astart)) 2080Sstevel@tonic-gate if ((bl = bl->next) != NULL) 2090Sstevel@tonic-gate bend = bl->address + bl->size; 2100Sstevel@tonic-gate if (bl == NULL) 2110Sstevel@tonic-gate return (0); 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate if ((bstart = bl->address) <= astart) 2140Sstevel@tonic-gate return (1); 2150Sstevel@tonic-gate } 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate return (0); 2180Sstevel@tonic-gate } 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate void 2211772Sjl139090 dr_memlist_coalesce(struct memlist *mlist) 2220Sstevel@tonic-gate { 2230Sstevel@tonic-gate uint64_t end, nend; 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate if ((mlist == NULL) || (mlist->next == NULL)) 2260Sstevel@tonic-gate return; 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate while (mlist->next) { 2290Sstevel@tonic-gate end = mlist->address + mlist->size; 2300Sstevel@tonic-gate if (mlist->next->address <= end) { 2310Sstevel@tonic-gate struct memlist *nl; 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate nend = mlist->next->address + mlist->next->size; 2340Sstevel@tonic-gate if (nend > end) 2350Sstevel@tonic-gate mlist->size += (nend - end); 2360Sstevel@tonic-gate nl = mlist->next; 2370Sstevel@tonic-gate mlist->next = mlist->next->next; 2380Sstevel@tonic-gate if (nl) { 2390Sstevel@tonic-gate FREESTRUCT(nl, struct memlist, 1); 2400Sstevel@tonic-gate } 2410Sstevel@tonic-gate if (mlist->next) 2420Sstevel@tonic-gate mlist->next->prev = mlist; 2430Sstevel@tonic-gate } else { 2440Sstevel@tonic-gate mlist = mlist->next; 2450Sstevel@tonic-gate } 2460Sstevel@tonic-gate } 2470Sstevel@tonic-gate } 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate #ifdef DEBUG 2500Sstevel@tonic-gate void 2510Sstevel@tonic-gate memlist_dump(struct memlist *mlist) 2520Sstevel@tonic-gate { 2530Sstevel@tonic-gate register struct memlist *ml; 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate if (mlist == NULL) 2560Sstevel@tonic-gate printf("memlist> EMPTY\n"); 2570Sstevel@tonic-gate else for (ml = mlist; ml; ml = ml->next) 258930Smathue printf("memlist> 0x%lx, 0x%lx\n", ml->address, ml->size); 2590Sstevel@tonic-gate } 2600Sstevel@tonic-gate #endif 2611772Sjl139090 2621772Sjl139090 struct memlist * 2631772Sjl139090 dr_memlist_dup(struct memlist *mlist) 2641772Sjl139090 { 2651772Sjl139090 struct memlist *hl = NULL, *tl, **mlp; 2661772Sjl139090 2671772Sjl139090 if (mlist == NULL) 2681772Sjl139090 return (NULL); 2691772Sjl139090 2701772Sjl139090 mlp = &hl; 2711772Sjl139090 tl = *mlp; 2721772Sjl139090 for (; mlist; mlist = mlist->next) { 2731772Sjl139090 *mlp = GETSTRUCT(struct memlist, 1); 2741772Sjl139090 (*mlp)->address = mlist->address; 2751772Sjl139090 (*mlp)->size = mlist->size; 2761772Sjl139090 (*mlp)->prev = tl; 2771772Sjl139090 tl = *mlp; 2781772Sjl139090 mlp = &((*mlp)->next); 2791772Sjl139090 } 2801772Sjl139090 *mlp = NULL; 2811772Sjl139090 2821772Sjl139090 return (hl); 2831772Sjl139090 } 2841772Sjl139090 2851772Sjl139090 struct memlist * 2861772Sjl139090 dr_memlist_add_span(struct memlist *mlist, uint64_t base, uint64_t len) 2871772Sjl139090 { 2881772Sjl139090 struct memlist *ml, *tl, *nl; 2891772Sjl139090 2901772Sjl139090 if (len == 0ull) 2911772Sjl139090 return (NULL); 2921772Sjl139090 2931772Sjl139090 if (mlist == NULL) { 2941772Sjl139090 mlist = GETSTRUCT(struct memlist, 1); 2951772Sjl139090 mlist->address = base; 2961772Sjl139090 mlist->size = len; 2971772Sjl139090 mlist->next = mlist->prev = NULL; 2981772Sjl139090 2991772Sjl139090 return (mlist); 3001772Sjl139090 } 3011772Sjl139090 3021772Sjl139090 for (tl = ml = mlist; ml; tl = ml, ml = ml->next) { 3031772Sjl139090 if (base < ml->address) { 3041772Sjl139090 if ((base + len) < ml->address) { 3051772Sjl139090 nl = GETSTRUCT(struct memlist, 1); 3061772Sjl139090 nl->address = base; 3071772Sjl139090 nl->size = len; 3081772Sjl139090 nl->next = ml; 3091772Sjl139090 if ((nl->prev = ml->prev) != NULL) 3101772Sjl139090 nl->prev->next = nl; 3111772Sjl139090 ml->prev = nl; 3121772Sjl139090 if (mlist == ml) 3131772Sjl139090 mlist = nl; 3141772Sjl139090 } else { 3151772Sjl139090 ml->size = MAX((base + len), 316*11311SSurya.Prakki@Sun.COM (ml->address + ml->size)) - base; 3171772Sjl139090 ml->address = base; 3181772Sjl139090 } 3191772Sjl139090 break; 3201772Sjl139090 3211772Sjl139090 } else if (base <= (ml->address + ml->size)) { 3221772Sjl139090 ml->size = MAX((base + len), 323*11311SSurya.Prakki@Sun.COM (ml->address + ml->size)) - 324*11311SSurya.Prakki@Sun.COM MIN(ml->address, base); 3251772Sjl139090 ml->address = MIN(ml->address, base); 3261772Sjl139090 break; 3271772Sjl139090 } 3281772Sjl139090 } 3291772Sjl139090 if (ml == NULL) { 3301772Sjl139090 nl = GETSTRUCT(struct memlist, 1); 3311772Sjl139090 nl->address = base; 3321772Sjl139090 nl->size = len; 3331772Sjl139090 nl->next = NULL; 3341772Sjl139090 nl->prev = tl; 3351772Sjl139090 tl->next = nl; 3361772Sjl139090 } 3371772Sjl139090 3381772Sjl139090 dr_memlist_coalesce(mlist); 3391772Sjl139090 3401772Sjl139090 return (mlist); 3411772Sjl139090 } 3421772Sjl139090 3431772Sjl139090 struct memlist * 3441772Sjl139090 dr_memlist_del_span(struct memlist *mlist, uint64_t base, uint64_t len) 3451772Sjl139090 { 3461772Sjl139090 uint64_t end; 3471772Sjl139090 struct memlist *ml, *tl, *nlp; 3481772Sjl139090 3491772Sjl139090 if (mlist == NULL) 3501772Sjl139090 return (NULL); 3511772Sjl139090 3521772Sjl139090 end = base + len; 3531772Sjl139090 if ((end <= mlist->address) || (base == end)) 3541772Sjl139090 return (mlist); 3551772Sjl139090 3561772Sjl139090 for (tl = ml = mlist; ml; tl = ml, ml = nlp) { 3571772Sjl139090 uint64_t mend; 3581772Sjl139090 3591772Sjl139090 nlp = ml->next; 3601772Sjl139090 3611772Sjl139090 if (end <= ml->address) 3621772Sjl139090 break; 3631772Sjl139090 3641772Sjl139090 mend = ml->address + ml->size; 3651772Sjl139090 if (base < mend) { 3661772Sjl139090 if (base <= ml->address) { 3671772Sjl139090 ml->address = end; 3681772Sjl139090 if (end >= mend) 3691772Sjl139090 ml->size = 0ull; 3701772Sjl139090 else 3711772Sjl139090 ml->size = mend - ml->address; 3721772Sjl139090 } else { 3731772Sjl139090 ml->size = base - ml->address; 3741772Sjl139090 if (end < mend) { 3751772Sjl139090 struct memlist *nl; 3761772Sjl139090 /* 3771772Sjl139090 * splitting an memlist entry. 3781772Sjl139090 */ 3791772Sjl139090 nl = GETSTRUCT(struct memlist, 1); 3801772Sjl139090 nl->address = end; 3811772Sjl139090 nl->size = mend - nl->address; 3821772Sjl139090 if ((nl->next = nlp) != NULL) 3831772Sjl139090 nlp->prev = nl; 3841772Sjl139090 nl->prev = ml; 3851772Sjl139090 ml->next = nl; 3861772Sjl139090 nlp = nl; 3871772Sjl139090 } 3881772Sjl139090 } 3891772Sjl139090 if (ml->size == 0ull) { 3901772Sjl139090 if (ml == mlist) { 3911772Sjl139090 if ((mlist = nlp) != NULL) 3921772Sjl139090 nlp->prev = NULL; 3931772Sjl139090 FREESTRUCT(ml, struct memlist, 1); 3941772Sjl139090 if (mlist == NULL) 3951772Sjl139090 break; 3961772Sjl139090 ml = nlp; 3971772Sjl139090 } else { 3981772Sjl139090 if ((tl->next = nlp) != NULL) 3991772Sjl139090 nlp->prev = tl; 4001772Sjl139090 FREESTRUCT(ml, struct memlist, 1); 4011772Sjl139090 ml = tl; 4021772Sjl139090 } 4031772Sjl139090 } 4041772Sjl139090 } 4051772Sjl139090 } 4061772Sjl139090 4071772Sjl139090 return (mlist); 4081772Sjl139090 } 4091772Sjl139090 4101772Sjl139090 /* 4111772Sjl139090 * add span without merging 4121772Sjl139090 */ 4131772Sjl139090 struct memlist * 4141772Sjl139090 dr_memlist_cat_span(struct memlist *mlist, uint64_t base, uint64_t len) 4151772Sjl139090 { 4161772Sjl139090 struct memlist *ml, *tl, *nl; 4171772Sjl139090 4181772Sjl139090 if (len == 0ull) 4191772Sjl139090 return (NULL); 4201772Sjl139090 4211772Sjl139090 if (mlist == NULL) { 4221772Sjl139090 mlist = GETSTRUCT(struct memlist, 1); 4231772Sjl139090 mlist->address = base; 4241772Sjl139090 mlist->size = len; 4251772Sjl139090 mlist->next = mlist->prev = NULL; 4261772Sjl139090 4271772Sjl139090 return (mlist); 4281772Sjl139090 } 4291772Sjl139090 4301772Sjl139090 for (tl = ml = mlist; ml; tl = ml, ml = ml->next) { 4311772Sjl139090 if (base < ml->address) { 4321772Sjl139090 nl = GETSTRUCT(struct memlist, 1); 4331772Sjl139090 nl->address = base; 4341772Sjl139090 nl->size = len; 4351772Sjl139090 nl->next = ml; 4361772Sjl139090 if ((nl->prev = ml->prev) != NULL) 4371772Sjl139090 nl->prev->next = nl; 4381772Sjl139090 ml->prev = nl; 4391772Sjl139090 if (mlist == ml) 4401772Sjl139090 mlist = nl; 4411772Sjl139090 break; 4421772Sjl139090 } 4431772Sjl139090 } 4441772Sjl139090 4451772Sjl139090 if (ml == NULL) { 4461772Sjl139090 nl = GETSTRUCT(struct memlist, 1); 4471772Sjl139090 nl->address = base; 4481772Sjl139090 nl->size = len; 4491772Sjl139090 nl->next = NULL; 4501772Sjl139090 nl->prev = tl; 4511772Sjl139090 tl->next = nl; 4521772Sjl139090 } 4531772Sjl139090 4541772Sjl139090 return (mlist); 4551772Sjl139090 } 456