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 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <cma.h> 30 31 #include <strings.h> 32 #include <errno.h> 33 #include <time.h> 34 #include <fm/fmd_api.h> 35 #include <sys/fm/protocol.h> 36 #include <sys/systeminfo.h> 37 #include <sys/utsname.h> 38 39 #ifdef sun4v 40 #include <sys/fm/ldom.h> 41 42 static fmd_hdl_t *init_hdl; 43 ldom_hdl_t *cma_lhp; 44 #endif 45 46 extern const char *fmd_fmri_get_platform(); 47 48 cma_t cma; 49 50 cma_stats_t cma_stats = { 51 { "cpu_flts", FMD_TYPE_UINT64, "cpu faults resolved" }, 52 { "cpu_repairs", FMD_TYPE_UINT64, "cpu faults repaired" }, 53 { "cpu_fails", FMD_TYPE_UINT64, "cpu faults unresolveable" }, 54 { "cpu_blfails", FMD_TYPE_UINT64, "failed cpu blacklists" }, 55 { "cpu_supp", FMD_TYPE_UINT64, "cpu offlines suppressed" }, 56 { "cpu_blsupp", FMD_TYPE_UINT64, "cpu blacklists suppressed" }, 57 { "page_flts", FMD_TYPE_UINT64, "page faults resolved" }, 58 { "page_repairs", FMD_TYPE_UINT64, "page faults repaired" }, 59 { "page_fails", FMD_TYPE_UINT64, "page faults unresolveable" }, 60 { "page_supp", FMD_TYPE_UINT64, "page retires suppressed" }, 61 { "page_nonent", FMD_TYPE_UINT64, "retires for non-existent fmris" }, 62 { "page_retmax", FMD_TYPE_UINT64, "hit max retries for page retire" }, 63 { "bad_flts", FMD_TYPE_UINT64, "invalid fault events received" }, 64 { "nop_flts", FMD_TYPE_UINT64, "inapplicable fault events received" }, 65 { "auto_flts", FMD_TYPE_UINT64, "auto-close faults received" } 66 }; 67 68 typedef struct cma_subscriber { 69 const char *subr_class; 70 const char *subr_sname; 71 uint_t subr_svers; 72 int (*subr_func)(fmd_hdl_t *, nvlist_t *, nvlist_t *, const char *, 73 boolean_t); 74 } cma_subscriber_t; 75 76 static const cma_subscriber_t cma_subrs[] = { 77 #if defined(sun4v) 78 { "fault.memory.page", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 79 cma_page_retire }, 80 { "fault.memory.dimm", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 81 NULL }, 82 { "fault.memory.dimm_sb", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 83 NULL }, 84 { "fault.memory.dimm_ck", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 85 NULL }, 86 { "fault.memory.dimm_ue", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 87 NULL }, 88 { "fault.memory.bank", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 89 NULL }, 90 { "fault.memory.datapath", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 91 NULL }, 92 { "fault.memory.link-c", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 93 NULL }, 94 { "fault.memory.link-u", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 95 NULL }, 96 { "fault.memory.link-f", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 97 NULL }, 98 99 /* 100 * The following ultraSPARC-T1/T2 faults do NOT retire a cpu thread, 101 * and therefore must be intercepted before 102 * the default "fault.cpu.*" dispatch to cma_cpu_retire. 103 */ 104 { "fault.cpu.*.l2cachedata", FM_FMRI_SCHEME_CPU, 105 FM_CPU_SCHEME_VERSION, NULL }, 106 { "fault.cpu.*.l2cachetag", FM_FMRI_SCHEME_CPU, 107 FM_CPU_SCHEME_VERSION, NULL }, 108 { "fault.cpu.*.l2cachectl", FM_FMRI_SCHEME_CPU, 109 FM_CPU_SCHEME_VERSION, NULL }, 110 { "fault.cpu.*.l2data-c", FM_FMRI_SCHEME_CPU, 111 FM_CPU_SCHEME_VERSION, NULL }, 112 { "fault.cpu.*.l2data-u", FM_FMRI_SCHEME_CPU, 113 FM_CPU_SCHEME_VERSION, NULL }, 114 { "fault.cpu.*.mau", FM_FMRI_SCHEME_CPU, 115 FM_CPU_SCHEME_VERSION, NULL }, 116 { "fault.cpu.*.lfu-u", FM_FMRI_SCHEME_CPU, 117 FM_CPU_SCHEME_VERSION, NULL }, 118 { "fault.cpu.*.lfu-f", FM_FMRI_SCHEME_CPU, 119 FM_CPU_SCHEME_VERSION, NULL }, 120 { "fault.cpu.*.lfu-p", FM_FMRI_SCHEME_CPU, 121 FM_CPU_SCHEME_VERSION, NULL }, 122 { "fault.cpu.*", FM_FMRI_SCHEME_CPU, FM_CPU_SCHEME_VERSION, 123 cma_cpu_retire }, 124 #elif defined(opl) 125 { "fault.memory.page", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 126 cma_page_retire }, 127 { "fault.memory.dimm", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 128 NULL }, 129 { "fault.memory.bank", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 130 NULL }, 131 { "fault.cpu.SPARC64-VI.*", FM_FMRI_SCHEME_CPU, FM_CPU_SCHEME_VERSION, 132 cma_cpu_retire }, 133 { "fault.cpu.SPARC64-VII.*", FM_FMRI_SCHEME_CPU, FM_CPU_SCHEME_VERSION, 134 cma_cpu_retire }, 135 { "fault.chassis.SPARC-Enterprise.cpu.SPARC64-VI.core.se", 136 FM_FMRI_SCHEME_HC, FM_HC_SCHEME_VERSION, cma_cpu_hc_retire }, 137 { "fault.chassis.SPARC-Enterprise.cpu.SPARC64-VI.core.se-offlinereq", 138 FM_FMRI_SCHEME_HC, FM_HC_SCHEME_VERSION, cma_cpu_hc_retire }, 139 { "fault.chassis.SPARC-Enterprise.cpu.SPARC64-VI.core.ce", 140 FM_FMRI_SCHEME_HC, FM_HC_SCHEME_VERSION, cma_cpu_hc_retire }, 141 { "fault.chassis.SPARC-Enterprise.cpu.SPARC64-VI.core.ce-offlinereq", 142 FM_FMRI_SCHEME_HC, FM_HC_SCHEME_VERSION, cma_cpu_hc_retire }, 143 { "fault.chassis.SPARC-Enterprise.cpu.SPARC64-VII.core.se", 144 FM_FMRI_SCHEME_HC, FM_HC_SCHEME_VERSION, cma_cpu_hc_retire }, 145 { "fault.chassis.SPARC-Enterprise.cpu.SPARC64-VII.core.se-offlinereq", 146 FM_FMRI_SCHEME_HC, FM_HC_SCHEME_VERSION, cma_cpu_hc_retire }, 147 { "fault.chassis.SPARC-Enterprise.cpu.SPARC64-VII.core.ce", 148 FM_FMRI_SCHEME_HC, FM_HC_SCHEME_VERSION, cma_cpu_hc_retire }, 149 { "fault.chassis.SPARC-Enterprise.cpu.SPARC64-VII.core.ce-offlinereq", 150 FM_FMRI_SCHEME_HC, FM_HC_SCHEME_VERSION, cma_cpu_hc_retire }, 151 #else /* Generic */ 152 { "fault.memory.page", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 153 cma_page_retire }, 154 { "fault.memory.page_sb", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 155 cma_page_retire }, 156 { "fault.memory.page_ck", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 157 cma_page_retire }, 158 { "fault.memory.page_ue", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 159 cma_page_retire }, 160 { "fault.memory.generic-x86.page_ce", FM_FMRI_SCHEME_MEM, 161 FM_MEM_SCHEME_VERSION, cma_page_retire }, 162 { "fault.memory.generic-x86.page_ue", FM_FMRI_SCHEME_MEM, 163 FM_MEM_SCHEME_VERSION, cma_page_retire }, 164 { "fault.memory.intel.page_ce", FM_FMRI_SCHEME_MEM, 165 FM_MEM_SCHEME_VERSION, cma_page_retire }, 166 { "fault.memory.intel.page_ue", FM_FMRI_SCHEME_MEM, 167 FM_MEM_SCHEME_VERSION, cma_page_retire }, 168 { "fault.memory.dimm", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 169 NULL }, 170 { "fault.memory.dimm_sb", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 171 NULL }, 172 { "fault.memory.dimm_ck", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 173 NULL }, 174 { "fault.memory.dimm_ue", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 175 NULL }, 176 { "fault.memory.generic-x86.dimm_ce", FM_FMRI_SCHEME_MEM, 177 FM_MEM_SCHEME_VERSION, NULL }, 178 { "fault.memory.generic-x86.dimm_ue", FM_FMRI_SCHEME_MEM, 179 FM_MEM_SCHEME_VERSION, NULL }, 180 { "fault.memory.intel.dimm_ce", FM_FMRI_SCHEME_MEM, 181 FM_MEM_SCHEME_VERSION, NULL }, 182 { "fault.memory.intel.dimm_ue", FM_FMRI_SCHEME_MEM, 183 FM_MEM_SCHEME_VERSION, NULL }, 184 { "fault.memory.intel.fbd.*", FM_FMRI_SCHEME_HC, 185 FM_HC_SCHEME_VERSION, NULL }, 186 { "fault.memory.dimm_testfail", FM_FMRI_SCHEME_MEM, 187 FM_MEM_SCHEME_VERSION, NULL }, 188 { "fault.memory.bank", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 189 NULL }, 190 { "fault.memory.datapath", FM_FMRI_SCHEME_MEM, FM_MEM_SCHEME_VERSION, 191 NULL }, 192 193 /* 194 * The following faults do NOT retire a cpu thread, 195 * and therefore must be intercepted before 196 * the default "fault.cpu.*" dispatch to cma_cpu_retire. 197 */ 198 { "fault.cpu.ultraSPARC-T1.freg", FM_FMRI_SCHEME_CPU, 199 FM_CPU_SCHEME_VERSION, NULL }, 200 { "fault.cpu.ultraSPARC-T1.l2cachedata", FM_FMRI_SCHEME_CPU, 201 FM_CPU_SCHEME_VERSION, NULL }, 202 { "fault.cpu.ultraSPARC-T1.l2cachetag", FM_FMRI_SCHEME_CPU, 203 FM_CPU_SCHEME_VERSION, NULL }, 204 { "fault.cpu.ultraSPARC-T1.l2cachectl", FM_FMRI_SCHEME_CPU, 205 FM_CPU_SCHEME_VERSION, NULL }, 206 { "fault.cpu.ultraSPARC-T1.mau", FM_FMRI_SCHEME_CPU, 207 FM_CPU_SCHEME_VERSION, NULL }, 208 { "fault.cpu.amd.dramchannel", FM_FMRI_SCHEME_HC, FM_HC_SCHEME_VERSION, 209 NULL }, 210 { "fault.cpu.generic-x86.bus_interconnect_memory", FM_FMRI_SCHEME_CPU, 211 FM_CPU_SCHEME_VERSION, NULL }, 212 { "fault.cpu.generic-x86.bus_interconnect_io", FM_FMRI_SCHEME_CPU, 213 FM_CPU_SCHEME_VERSION, NULL }, 214 { "fault.cpu.generic-x86.bus_interconnect", FM_FMRI_SCHEME_CPU, 215 FM_CPU_SCHEME_VERSION, NULL }, 216 { "fault.cpu.intel.bus_interconnect_memory", FM_FMRI_SCHEME_CPU, 217 FM_CPU_SCHEME_VERSION, NULL }, 218 { "fault.cpu.intel.bus_interconnect_io", FM_FMRI_SCHEME_CPU, 219 FM_CPU_SCHEME_VERSION, NULL }, 220 { "fault.cpu.intel.bus_interconnect", FM_FMRI_SCHEME_CPU, 221 FM_CPU_SCHEME_VERSION, NULL }, 222 { "fault.cpu.intel.nb.*", FM_FMRI_SCHEME_HC, 223 FM_HC_SCHEME_VERSION, NULL }, 224 { "fault.cpu.intel.dma", FM_FMRI_SCHEME_HC, 225 FM_HC_SCHEME_VERSION, NULL }, 226 { "fault.cpu.intel.dma", FM_FMRI_SCHEME_CPU, 227 FM_CPU_SCHEME_VERSION, NULL }, 228 /* 229 * Default "fault.cpu.*" for "mem" scheme ASRU dispatch. 230 */ 231 { "fault.cpu.*", FM_FMRI_SCHEME_CPU, FM_CPU_SCHEME_VERSION, 232 cma_cpu_retire }, 233 #endif 234 { NULL, NULL, 0, NULL } 235 }; 236 237 static const cma_subscriber_t * 238 nvl2subr(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t **asrup) 239 { 240 const cma_subscriber_t *sp; 241 nvlist_t *asru; 242 char *scheme; 243 uint8_t version; 244 char *fltclass = "(unknown)"; 245 246 if (nvlist_lookup_nvlist(nvl, FM_FAULT_ASRU, &asru) != 0 || 247 nvlist_lookup_string(asru, FM_FMRI_SCHEME, &scheme) != 0 || 248 nvlist_lookup_uint8(asru, FM_VERSION, &version) != 0) { 249 cma_stats.bad_flts.fmds_value.ui64++; 250 return (NULL); 251 } 252 253 for (sp = cma_subrs; sp->subr_class != NULL; sp++) { 254 if (fmd_nvl_class_match(hdl, nvl, sp->subr_class) && 255 strcmp(scheme, sp->subr_sname) == 0 && 256 version <= sp->subr_svers) { 257 *asrup = asru; 258 return (sp); 259 } 260 } 261 262 (void) nvlist_lookup_string(nvl, FM_CLASS, &fltclass); 263 fmd_hdl_error(hdl, "No handling disposition for %s with asru in " 264 "scheme \"%s\"\n", fltclass, scheme); 265 cma_stats.nop_flts.fmds_value.ui64++; 266 return (NULL); 267 } 268 269 static void 270 cma_recv_list(fmd_hdl_t *hdl, nvlist_t *nvl, boolean_t repair) 271 { 272 char *uuid = NULL; 273 nvlist_t **nva; 274 uint_t nvc = 0; 275 uint_t keepopen; 276 int err = 0; 277 278 err |= nvlist_lookup_string(nvl, FM_SUSPECT_UUID, &uuid); 279 err |= nvlist_lookup_nvlist_array(nvl, FM_SUSPECT_FAULT_LIST, 280 &nva, &nvc); 281 if (err != 0) { 282 cma_stats.bad_flts.fmds_value.ui64++; 283 return; 284 } 285 286 keepopen = nvc; 287 while (nvc-- != 0 && (repair || !fmd_case_uuclosed(hdl, uuid))) { 288 nvlist_t *nvl = *nva++; 289 const cma_subscriber_t *subr; 290 nvlist_t *asru; 291 292 if ((subr = nvl2subr(hdl, nvl, &asru)) == NULL) 293 continue; 294 295 /* 296 * A handler returns CMA_RA_SUCCESS to indicate that 297 * from this suspects point-of-view the case may be 298 * closed, CMA_RA_FAILURE otherwise. 299 * A handler must not close the case itself. 300 */ 301 if (subr->subr_func != NULL) { 302 err = subr->subr_func(hdl, nvl, asru, uuid, repair); 303 304 if (err == CMA_RA_SUCCESS) 305 keepopen--; 306 } 307 } 308 309 if (!keepopen && !repair) 310 fmd_case_uuclose(hdl, uuid); 311 } 312 313 static void 314 cma_recv_one(fmd_hdl_t *hdl, nvlist_t *nvl) 315 { 316 const cma_subscriber_t *subr; 317 nvlist_t *asru; 318 319 if ((subr = nvl2subr(hdl, nvl, &asru)) == NULL) 320 return; 321 322 if (subr->subr_func != NULL) 323 (void) subr->subr_func(hdl, nvl, asru, NULL, 0); 324 } 325 326 /*ARGSUSED*/ 327 static void 328 cma_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class) 329 { 330 boolean_t repair = B_FALSE; 331 332 fmd_hdl_debug(hdl, "received %s\n", class); 333 334 if (strcmp(class, FM_LIST_SUSPECT_CLASS) == 0 || 335 (repair = (strcmp(class, FM_LIST_REPAIRED_CLASS) == 0))) 336 cma_recv_list(hdl, nvl, repair); 337 else 338 cma_recv_one(hdl, nvl); 339 } 340 341 /*ARGSUSED*/ 342 static void 343 cma_timeout(fmd_hdl_t *hdl, id_t id, void *arg) 344 { 345 if (id == cma.cma_page_timerid) 346 cma_page_retry(hdl); 347 #ifdef sun4v 348 /* 349 * cpu offline/online needs to be retried on sun4v because 350 * ldom request can be asynchronous. 351 */ 352 else if (id == cma.cma_cpu_timerid) 353 cma_cpu_retry(hdl); 354 #endif 355 } 356 357 #ifdef sun4v 358 static void * 359 cma_init_alloc(size_t size) 360 { 361 return (fmd_hdl_alloc(init_hdl, size, FMD_SLEEP)); 362 } 363 364 static void 365 cma_init_free(void *addr, size_t size) 366 { 367 fmd_hdl_free(init_hdl, addr, size); 368 } 369 #endif 370 371 static const fmd_hdl_ops_t fmd_ops = { 372 cma_recv, /* fmdo_recv */ 373 cma_timeout, /* fmdo_timeout */ 374 NULL, /* fmdo_close */ 375 NULL, /* fmdo_stats */ 376 NULL, /* fmdo_gc */ 377 }; 378 379 static const fmd_prop_t fmd_props[] = { 380 { "cpu_tries", FMD_TYPE_UINT32, "10" }, 381 { "cpu_delay", FMD_TYPE_TIME, "1sec" }, 382 #ifdef sun4v 383 { "cpu_ret_mindelay", FMD_TYPE_TIME, "5sec" }, 384 { "cpu_ret_maxdelay", FMD_TYPE_TIME, "5min" }, 385 #endif /* sun4v */ 386 { "cpu_offline_enable", FMD_TYPE_BOOL, "true" }, 387 { "cpu_online_enable", FMD_TYPE_BOOL, "true" }, 388 { "cpu_forced_offline", FMD_TYPE_BOOL, "true" }, 389 #ifdef opl 390 { "cpu_blacklist_enable", FMD_TYPE_BOOL, "false" }, 391 { "cpu_unblacklist_enable", FMD_TYPE_BOOL, "false" }, 392 #else 393 { "cpu_blacklist_enable", FMD_TYPE_BOOL, "true" }, 394 { "cpu_unblacklist_enable", FMD_TYPE_BOOL, "true" }, 395 #endif /* opl */ 396 { "page_ret_mindelay", FMD_TYPE_TIME, "1sec" }, 397 { "page_ret_maxdelay", FMD_TYPE_TIME, "5min" }, 398 { "page_retire_enable", FMD_TYPE_BOOL, "true" }, 399 { "page_unretire_enable", FMD_TYPE_BOOL, "true" }, 400 #ifdef i386 401 /* 402 * On i386, leaving cases open while we retry the 403 * retire can cause the eft module to use large amounts 404 * of memory. Until eft is fixed, we set a maximum number 405 * of retries on page retires, after which the case will 406 * be closed. 407 */ 408 { "page_retire_maxretries", FMD_TYPE_UINT32, "5" }, 409 #else 410 { "page_retire_maxretries", FMD_TYPE_UINT32, "0" }, 411 #endif /* i386 */ 412 { NULL, 0, NULL } 413 }; 414 415 static const fmd_hdl_info_t fmd_info = { 416 "CPU/Memory Retire Agent", CMA_VERSION, &fmd_ops, fmd_props 417 }; 418 419 void 420 _fmd_init(fmd_hdl_t *hdl) 421 { 422 hrtime_t nsec; 423 #ifdef i386 424 /* 425 * Abort the cpumem-retire module if Solaris is running under the Xen 426 * hypervisor. 427 */ 428 if (strcmp(fmd_fmri_get_platform(), "i86xpv") == 0) 429 return; 430 #endif 431 432 if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) 433 return; /* invalid data in configuration file */ 434 435 fmd_hdl_subscribe(hdl, "list.repaired"); 436 fmd_hdl_subscribe(hdl, "fault.cpu.*"); 437 fmd_hdl_subscribe(hdl, "fault.memory.*"); 438 #ifdef opl 439 fmd_hdl_subscribe(hdl, "fault.chassis.SPARC-Enterprise.cpu.*"); 440 #endif 441 442 (void) fmd_stat_create(hdl, FMD_STAT_NOALLOC, sizeof (cma_stats) / 443 sizeof (fmd_stat_t), (fmd_stat_t *)&cma_stats); 444 445 cma.cma_cpu_tries = fmd_prop_get_int32(hdl, "cpu_tries"); 446 447 nsec = fmd_prop_get_int64(hdl, "cpu_delay"); 448 cma.cma_cpu_delay.tv_sec = nsec / NANOSEC; 449 cma.cma_cpu_delay.tv_nsec = nsec % NANOSEC; 450 451 cma.cma_page_mindelay = fmd_prop_get_int64(hdl, "page_ret_mindelay"); 452 cma.cma_page_maxdelay = fmd_prop_get_int64(hdl, "page_ret_maxdelay"); 453 454 #ifdef sun4v 455 cma.cma_cpu_mindelay = fmd_prop_get_int64(hdl, "cpu_ret_mindelay"); 456 cma.cma_cpu_maxdelay = fmd_prop_get_int64(hdl, "cpu_ret_maxdelay"); 457 #endif 458 459 cma.cma_cpu_dooffline = fmd_prop_get_int32(hdl, "cpu_offline_enable"); 460 cma.cma_cpu_forcedoffline = fmd_prop_get_int32(hdl, 461 "cpu_forced_offline"); 462 cma.cma_cpu_doonline = fmd_prop_get_int32(hdl, "cpu_online_enable"); 463 cma.cma_cpu_doblacklist = fmd_prop_get_int32(hdl, 464 "cpu_blacklist_enable"); 465 cma.cma_cpu_dounblacklist = fmd_prop_get_int32(hdl, 466 "cpu_unblacklist_enable"); 467 cma.cma_page_doretire = fmd_prop_get_int32(hdl, "page_retire_enable"); 468 cma.cma_page_dounretire = fmd_prop_get_int32(hdl, 469 "page_unretire_enable"); 470 cma.cma_page_maxretries = 471 fmd_prop_get_int32(hdl, "page_retire_maxretries"); 472 473 if (cma.cma_page_maxdelay < cma.cma_page_mindelay) 474 fmd_hdl_abort(hdl, "page retirement delays conflict\n"); 475 476 #ifdef sun4v 477 init_hdl = hdl; 478 cma_lhp = ldom_init(cma_init_alloc, cma_init_free); 479 #endif 480 } 481 482 void 483 _fmd_fini(fmd_hdl_t *hdl) 484 { 485 #ifdef sun4v 486 ldom_fini(cma_lhp); 487 cma_cpu_fini(hdl); 488 #endif 489 cma_page_fini(hdl); 490 } 491