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