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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 /* 27 * Copyright (c) 2009, Intel Corporation. 28 * All rights reserved. 29 */ 30 31 /* 32 * [Support of X2APIC] 33 * According to the ACPI Spec, when using the X2APIC interrupt model, logical 34 * processors with APIC ID values of 255 and greater are required to have a 35 * Processor Device object and must convey the Processor's APIC information to 36 * OSPM using the Processor Local X2APIC structure. Logical Processors with APIC 37 * ID values less than 255 must use the Processor Local XAPIC structure to 38 * convey their APIC information to OSPM. 39 */ 40 41 #include <sys/types.h> 42 #include <sys/atomic.h> 43 #include <sys/bootconf.h> 44 #include <sys/cpuvar.h> 45 #include <sys/machsystm.h> 46 #include <sys/psm_types.h> 47 #include <sys/x86_archext.h> 48 #include <sys/sunddi.h> 49 #include <sys/sunndi.h> 50 #include <sys/acpi/acpi.h> 51 #include <sys/acpica.h> 52 #include <sys/acpidev.h> 53 #include <sys/acpidev_impl.h> 54 55 struct acpidev_cpu_map_item { 56 uint32_t proc_id; 57 uint32_t apic_id; 58 }; 59 60 struct acpidev_cpu_MAT_arg { 61 boolean_t found; 62 boolean_t enabled; 63 uint32_t proc_id; 64 uint32_t apic_id; 65 }; 66 67 static ACPI_STATUS acpidev_cpu_pre_probe(acpidev_walk_info_t *infop); 68 static ACPI_STATUS acpidev_cpu_post_probe(acpidev_walk_info_t *infop); 69 static ACPI_STATUS acpidev_cpu_probe(acpidev_walk_info_t *infop); 70 static acpidev_filter_result_t acpidev_cpu_filter(acpidev_walk_info_t *infop, 71 char *devname, int maxlen); 72 static ACPI_STATUS acpidev_cpu_init(acpidev_walk_info_t *infop); 73 74 static acpidev_filter_result_t acpidev_cpu_filter_func( 75 acpidev_walk_info_t *infop, ACPI_HANDLE hdl, acpidev_filter_rule_t *afrp, 76 char *devname, int len); 77 static int acpidev_cpu_query_dip(cpu_t *, dev_info_t **); 78 79 /* 80 * Default class driver for ACPI processor/CPU objects. 81 */ 82 acpidev_class_t acpidev_class_cpu = { 83 0, /* adc_refcnt */ 84 ACPIDEV_CLASS_REV1, /* adc_version */ 85 ACPIDEV_CLASS_ID_CPU, /* adc_class_id */ 86 "ACPI CPU", /* adc_class_name */ 87 ACPIDEV_TYPE_CPU, /* adc_dev_type */ 88 NULL, /* adc_private */ 89 acpidev_cpu_pre_probe, /* adc_pre_probe */ 90 acpidev_cpu_post_probe, /* adc_post_probe */ 91 acpidev_cpu_probe, /* adc_probe */ 92 acpidev_cpu_filter, /* adc_filter */ 93 acpidev_cpu_init, /* adc_init */ 94 NULL, /* adc_fini */ 95 }; 96 97 /* 98 * List of class drivers which will be called in order when handling 99 * children of ACPI cpu/processor objects. 100 */ 101 acpidev_class_list_t *acpidev_class_list_cpu = NULL; 102 103 /* Filter rule table for the first probe at boot time. */ 104 static acpidev_filter_rule_t acpidev_cpu_filters[] = { 105 { /* Skip all processors under root node, should be there. */ 106 NULL, 107 0, 108 ACPIDEV_FILTER_SKIP, 109 NULL, 110 1, 111 1, 112 NULL, 113 NULL, 114 }, 115 { /* Create and scan other processor objects */ 116 acpidev_cpu_filter_func, 117 0, 118 ACPIDEV_FILTER_DEFAULT, 119 &acpidev_class_list_cpu, 120 2, 121 INT_MAX, 122 NULL, 123 ACPIDEV_NODE_NAME_CPU, 124 } 125 }; 126 127 /* ACPI/PNP hardware id for processor. */ 128 static char *acpidev_processor_device_ids[] = { 129 ACPIDEV_HID_CPU, 130 }; 131 132 static char *acpidev_cpu_uid_formats[] = { 133 "SCK%x-CPU%x", 134 }; 135 136 static ACPI_HANDLE acpidev_cpu_map_hdl = NULL; 137 static uint32_t acpidev_cpu_map_count = 0; 138 static struct acpidev_cpu_map_item *acpidev_cpu_map = NULL; 139 140 extern int (*psm_cpu_create_devinfo)(cpu_t *, dev_info_t **); 141 static int (*psm_cpu_create_devinfo_old)(cpu_t *, dev_info_t **) = NULL; 142 143 /* Count how many enabled CPUs are in the MADT table. */ 144 static ACPI_STATUS 145 acpidev_cpu_count_MADT(ACPI_SUBTABLE_HEADER *ap, void *context) 146 { 147 uint32_t *cntp; 148 ACPI_MADT_LOCAL_APIC *mpa; 149 ACPI_MADT_LOCAL_X2APIC *mpx2a; 150 151 cntp = (uint32_t *)context; 152 switch (ap->Type) { 153 case ACPI_MADT_TYPE_LOCAL_APIC: 154 mpa = (ACPI_MADT_LOCAL_APIC *)ap; 155 if (mpa->LapicFlags & ACPI_MADT_ENABLED) { 156 ASSERT(mpa->Id != 255); 157 (*cntp)++; 158 } 159 break; 160 161 case ACPI_MADT_TYPE_LOCAL_X2APIC: 162 mpx2a = (ACPI_MADT_LOCAL_X2APIC *)ap; 163 /* See comment at beginning about 255 limitation. */ 164 if ((mpx2a->LapicFlags & ACPI_MADT_ENABLED) && 165 (mpx2a->LocalApicId >= 255)) { 166 (*cntp)++; 167 } 168 break; 169 170 default: 171 break; 172 } 173 174 return (AE_OK); 175 } 176 177 /* Extract information from the enabled CPUs using the MADT table. */ 178 static ACPI_STATUS 179 acpidev_cpu_parse_MADT(ACPI_SUBTABLE_HEADER *ap, void *context) 180 { 181 uint32_t *cntp; 182 ACPI_MADT_LOCAL_APIC *mpa; 183 ACPI_MADT_LOCAL_X2APIC *mpx2a; 184 185 cntp = (uint32_t *)context; 186 switch (ap->Type) { 187 case ACPI_MADT_TYPE_LOCAL_APIC: 188 mpa = (ACPI_MADT_LOCAL_APIC *)ap; 189 if (mpa->LapicFlags & ACPI_MADT_ENABLED) { 190 ASSERT(mpa->Id != 255); 191 ASSERT(*cntp < acpidev_cpu_map_count); 192 acpidev_cpu_map[*cntp].proc_id = mpa->ProcessorId; 193 acpidev_cpu_map[*cntp].apic_id = mpa->Id; 194 (*cntp)++; 195 } 196 break; 197 198 case ACPI_MADT_TYPE_LOCAL_X2APIC: 199 mpx2a = (ACPI_MADT_LOCAL_X2APIC *)ap; 200 /* See comment at beginning about 255 limitation. */ 201 if (mpx2a->LocalApicId < 255) { 202 ACPIDEV_DEBUG(CE_WARN, 203 "acpidev: encountered CPU with X2APIC Id < 255."); 204 } else if (mpx2a->LapicFlags & ACPI_MADT_ENABLED) { 205 ASSERT(*cntp < acpidev_cpu_map_count); 206 acpidev_cpu_map[*cntp].proc_id = mpx2a->Uid; 207 acpidev_cpu_map[*cntp].apic_id = mpx2a->LocalApicId; 208 (*cntp)++; 209 } 210 break; 211 212 default: 213 break; 214 } 215 216 return (AE_OK); 217 } 218 219 static ACPI_STATUS 220 acpidev_cpu_get_apicid(uint32_t procid, uint32_t *apicidp) 221 { 222 uint32_t i; 223 224 for (i = 0; i < acpidev_cpu_map_count; i++) { 225 if (acpidev_cpu_map[i].proc_id == procid) { 226 *apicidp = acpidev_cpu_map[i].apic_id; 227 return (AE_OK); 228 } 229 } 230 231 return (AE_NOT_FOUND); 232 } 233 234 /* 235 * Extract information for enabled CPUs from the buffer returned 236 * by the _MAT method. 237 */ 238 static ACPI_STATUS 239 acpidev_cpu_query_MAT(ACPI_SUBTABLE_HEADER *ap, void *context) 240 { 241 ACPI_MADT_LOCAL_APIC *mpa; 242 ACPI_MADT_LOCAL_X2APIC *mpx2a; 243 struct acpidev_cpu_MAT_arg *rp; 244 245 rp = (struct acpidev_cpu_MAT_arg *)context; 246 switch (ap->Type) { 247 case ACPI_MADT_TYPE_LOCAL_APIC: 248 mpa = (ACPI_MADT_LOCAL_APIC *)ap; 249 ASSERT(mpa->Id != 255); 250 rp->found = B_TRUE; 251 rp->proc_id = mpa->ProcessorId; 252 rp->apic_id = mpa->Id; 253 if (mpa->LapicFlags & ACPI_MADT_ENABLED) { 254 rp->enabled = B_TRUE; 255 } else { 256 rp->enabled = B_FALSE; 257 } 258 return (AE_CTRL_TERMINATE); 259 260 case ACPI_MADT_TYPE_LOCAL_X2APIC: 261 mpx2a = (ACPI_MADT_LOCAL_X2APIC *)ap; 262 if (mpx2a->LocalApicId >= 255) { 263 rp->found = B_TRUE; 264 rp->proc_id = mpx2a->Uid; 265 rp->apic_id = mpx2a->LocalApicId; 266 if (mpx2a->LapicFlags & ACPI_MADT_ENABLED) { 267 rp->enabled = B_TRUE; 268 } else { 269 rp->enabled = B_FALSE; 270 } 271 return (AE_CTRL_TERMINATE); 272 } else { 273 ACPIDEV_DEBUG(CE_WARN, "acpidev: encountered CPU " 274 "with X2APIC Id < 255 in _MAT."); 275 } 276 break; 277 278 case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 279 /* UNIMPLEMENTED */ 280 break; 281 282 case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI: 283 /* UNIMPLEMENTED */ 284 break; 285 286 default: 287 /* 288 * According to the ACPI Spec, the buffer returned by _MAT 289 * for a processor object should only contain Local APIC, 290 * Local SAPIC, and local APIC NMI entries. 291 * x2APIC Specification extends it to support Processor 292 * x2APIC and x2APIC NMI Structure. 293 */ 294 ACPIDEV_DEBUG(CE_NOTE, 295 "acpidev: unknown APIC entry type %u in _MAT.", ap->Type); 296 break; 297 } 298 299 return (AE_OK); 300 } 301 302 /* 303 * Query ACPI processor ID by evaluating ACPI _MAT, _UID, and PROCESSOR 304 * objects. 305 */ 306 static ACPI_STATUS 307 acpidev_cpu_get_procid(acpidev_walk_info_t *infop, uint32_t *idp) 308 { 309 int id; 310 ACPI_HANDLE hdl; 311 struct acpidev_cpu_MAT_arg mat; 312 313 if (infop->awi_info->Type != ACPI_TYPE_PROCESSOR && 314 infop->awi_info->Type != ACPI_TYPE_DEVICE) { 315 ACPIDEV_DEBUG(CE_WARN, 316 "acpidev: object %s is not PROCESSOR or DEVICE.", 317 infop->awi_name); 318 return (AE_BAD_PARAMETER); 319 } 320 hdl = infop->awi_hdl; 321 322 /* 323 * First try to evaluate _MAT. 324 * According to the ACPI Spec3.0b, it's legal for ACPI PROCESSOR objects 325 * to have ACPI method objects. 326 */ 327 bzero(&mat, sizeof (mat)); 328 (void) acpidev_walk_apic(NULL, hdl, ACPIDEV_METHOD_NAME_MAT, 329 acpidev_cpu_query_MAT, &mat); 330 if (mat.found) { 331 *idp = mat.proc_id; 332 return (AE_OK); 333 } 334 335 /* Then evalute PROCESSOR object. */ 336 if (infop->awi_info->Type == ACPI_TYPE_PROCESSOR) { 337 ACPI_BUFFER rb; 338 339 rb.Pointer = NULL; 340 rb.Length = ACPI_ALLOCATE_BUFFER; 341 if (ACPI_SUCCESS(AcpiEvaluateObjectTyped(hdl, NULL, NULL, &rb, 342 ACPI_TYPE_PROCESSOR))) { 343 *idp = ((ACPI_OBJECT *)rb.Pointer)->Processor.ProcId; 344 AcpiOsFree(rb.Pointer); 345 return (AE_OK); 346 } else { 347 ACPIDEV_DEBUG(CE_WARN, 348 "acpidev: failed to evaluate ACPI object %s.", 349 infop->awi_name); 350 } 351 } 352 353 /* 354 * Finally, try to evalute the _UID method. 355 * According to the ACPI Spec3.0b, it's legal for ACPI PROCESSOR objects 356 * to have ACPI method objects. 357 * The CPU _UID method should return Processor Id as an integer on x86. 358 */ 359 if (ACPI_SUCCESS(acpica_eval_int(hdl, METHOD_NAME__UID, &id))) { 360 *idp = id; 361 return (AE_OK); 362 } 363 364 return (AE_NOT_FOUND); 365 } 366 367 static ACPI_STATUS 368 acpidev_cpu_pre_probe(acpidev_walk_info_t *infop) 369 { 370 uint32_t count = 0; 371 372 /* Parse and cache APIC info in MADT on the first probe at boot time. */ 373 ASSERT(infop != NULL); 374 if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE && 375 acpidev_cpu_map_hdl == NULL) { 376 (void) acpidev_walk_apic(NULL, NULL, NULL, 377 acpidev_cpu_count_MADT, &acpidev_cpu_map_count); 378 acpidev_cpu_map = kmem_zalloc(sizeof (acpidev_cpu_map[0]) 379 * acpidev_cpu_map_count, KM_SLEEP); 380 (void) acpidev_walk_apic(NULL, NULL, NULL, 381 acpidev_cpu_parse_MADT, &count); 382 ASSERT(count == acpidev_cpu_map_count); 383 acpidev_cpu_map_hdl = infop->awi_hdl; 384 } 385 386 return (AE_OK); 387 } 388 389 static ACPI_STATUS 390 acpidev_cpu_post_probe(acpidev_walk_info_t *infop) 391 { 392 /* Free cached APIC info on the second probe at boot time. */ 393 ASSERT(infop != NULL); 394 if (infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE && 395 acpidev_cpu_map_hdl != NULL && 396 infop->awi_hdl == acpidev_cpu_map_hdl) { 397 if (acpidev_cpu_map != NULL && acpidev_cpu_map_count != 0) { 398 kmem_free(acpidev_cpu_map, sizeof (acpidev_cpu_map[0]) 399 * acpidev_cpu_map_count); 400 } 401 acpidev_cpu_map = NULL; 402 acpidev_cpu_map_count = 0; 403 acpidev_cpu_map_hdl = NULL; 404 405 /* replace psm_cpu_create_devinfo with local implementation. */ 406 psm_cpu_create_devinfo_old = psm_cpu_create_devinfo; 407 psm_cpu_create_devinfo = acpidev_cpu_query_dip; 408 } 409 410 return (AE_OK); 411 } 412 413 static ACPI_STATUS 414 acpidev_cpu_probe(acpidev_walk_info_t *infop) 415 { 416 ACPI_STATUS rc = AE_OK; 417 int flags; 418 419 ASSERT(infop != NULL); 420 ASSERT(infop->awi_hdl != NULL); 421 ASSERT(infop->awi_info != NULL); 422 ASSERT(infop->awi_class_curr == &acpidev_class_cpu); 423 if (infop->awi_info->Type != ACPI_TYPE_PROCESSOR && 424 (infop->awi_info->Type != ACPI_TYPE_DEVICE || 425 acpidev_match_device_id(infop->awi_info, 426 ACPIDEV_ARRAY_PARAM(acpidev_processor_device_ids)) == 0)) { 427 return (AE_OK); 428 } 429 430 /* 431 * Mark device as offline. It will be changed to online state 432 * when the corresponding CPU starts up. 433 */ 434 if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE) { 435 flags = ACPIDEV_PROCESS_FLAG_SCAN | 436 ACPIDEV_PROCESS_FLAG_CREATE | 437 ACPIDEV_PROCESS_FLAG_OFFLINE; 438 rc = acpidev_process_object(infop, flags); 439 } else if (infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE) { 440 flags = ACPIDEV_PROCESS_FLAG_SCAN; 441 rc = acpidev_process_object(infop, flags); 442 } else if (infop->awi_op_type == ACPIDEV_OP_HOTPLUG_PROBE) { 443 flags = ACPIDEV_PROCESS_FLAG_SCAN | 444 ACPIDEV_PROCESS_FLAG_CREATE | 445 ACPIDEV_PROCESS_FLAG_OFFLINE; 446 rc = acpidev_process_object(infop, flags); 447 } else { 448 ACPIDEV_DEBUG(CE_WARN, "acpidev: unknown operation type %u in " 449 "acpidev_cpu_probe().", infop->awi_op_type); 450 rc = AE_BAD_PARAMETER; 451 } 452 if (ACPI_FAILURE(rc) && rc != AE_NOT_EXIST && rc != AE_ALREADY_EXISTS) { 453 cmn_err(CE_WARN, 454 "!acpidev: failed to process processor object %s.", 455 infop->awi_name); 456 } else { 457 rc = AE_OK; 458 } 459 460 return (rc); 461 } 462 463 static acpidev_filter_result_t 464 acpidev_cpu_filter_func(acpidev_walk_info_t *infop, ACPI_HANDLE hdl, 465 acpidev_filter_rule_t *afrp, char *devname, int len) 466 { 467 acpidev_filter_result_t res; 468 469 ASSERT(afrp != NULL); 470 if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE || 471 infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE) { 472 uint32_t procid; 473 uint32_t apicid; 474 475 if (acpidev_cpu_get_procid(infop, &procid) != 0) { 476 ACPIDEV_DEBUG(CE_WARN, 477 "acpidev: failed to query processor id for %s.", 478 infop->awi_name); 479 return (ACPIDEV_FILTER_SKIP); 480 } else if (acpidev_cpu_get_apicid(procid, &apicid) != 0) { 481 ACPIDEV_DEBUG(CE_WARN, 482 "acpidev: failed to query apic id for %s.", 483 infop->awi_name); 484 return (ACPIDEV_FILTER_SKIP); 485 } 486 487 infop->awi_scratchpad[0] = procid; 488 infop->awi_scratchpad[1] = apicid; 489 } else if (infop->awi_op_type == ACPIDEV_OP_HOTPLUG_PROBE) { 490 struct acpidev_cpu_MAT_arg mat; 491 492 bzero(&mat, sizeof (mat)); 493 (void) acpidev_walk_apic(NULL, hdl, ACPIDEV_METHOD_NAME_MAT, 494 acpidev_cpu_query_MAT, &mat); 495 if (!mat.found) { 496 cmn_err(CE_WARN, 497 "!acpidev: failed to walk apic resource for %s.", 498 infop->awi_name); 499 return (ACPIDEV_FILTER_SKIP); 500 } else if (!mat.enabled) { 501 ACPIDEV_DEBUG(CE_NOTE, 502 "acpidev: CPU %s has been disabled.", 503 infop->awi_name); 504 return (ACPIDEV_FILTER_SKIP); 505 } 506 /* Save processor id and APIC id in scratchpad memory. */ 507 infop->awi_scratchpad[0] = mat.proc_id; 508 infop->awi_scratchpad[1] = mat.apic_id; 509 } 510 511 res = acpidev_filter_default(infop, hdl, afrp, devname, len); 512 513 return (res); 514 } 515 516 static acpidev_filter_result_t 517 acpidev_cpu_filter(acpidev_walk_info_t *infop, char *devname, int maxlen) 518 { 519 acpidev_filter_result_t res; 520 521 ASSERT(infop != NULL); 522 ASSERT(devname == NULL || maxlen >= ACPIDEV_MAX_NAMELEN); 523 if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE || 524 infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE || 525 infop->awi_op_type == ACPIDEV_OP_HOTPLUG_PROBE) { 526 res = acpidev_filter_device(infop, infop->awi_hdl, 527 ACPIDEV_ARRAY_PARAM(acpidev_cpu_filters), devname, maxlen); 528 } else { 529 res = ACPIDEV_FILTER_FAILED; 530 } 531 532 return (res); 533 } 534 535 static ACPI_STATUS 536 acpidev_cpu_init(acpidev_walk_info_t *infop) 537 { 538 int count; 539 dev_info_t *dip; 540 ACPI_HANDLE hdl; 541 char unitaddr[64]; 542 char **compatpp; 543 static char *compatible[] = { 544 ACPIDEV_HID_PROCESSOR, 545 ACPIDEV_TYPE_CPU, 546 "cpu" 547 }; 548 549 ASSERT(infop != NULL); 550 dip = infop->awi_dip; 551 hdl = infop->awi_hdl; 552 553 /* Create "apic_id" and "processor_id" properties. */ 554 if (ndi_prop_update_int(DDI_DEV_T_NONE, dip, 555 ACPIDEV_PROP_NAME_PROCESSOR_ID, infop->awi_scratchpad[0]) != 556 NDI_SUCCESS) { 557 cmn_err(CE_WARN, 558 "!acpidev: failed to set processor_id property for %s.", 559 infop->awi_name); 560 return (AE_ERROR); 561 } 562 if (ndi_prop_update_int(DDI_DEV_T_NONE, dip, 563 ACPIDEV_PROP_NAME_LOCALAPIC_ID, infop->awi_scratchpad[1]) != 564 NDI_SUCCESS) { 565 cmn_err(CE_WARN, 566 "!acpidev: failed to set apic_id property for %s.", 567 infop->awi_name); 568 return (AE_ERROR); 569 } 570 571 /* Set "compatible" property for CPU dip */ 572 count = sizeof (compatible) / sizeof (compatible[0]); 573 if (infop->awi_info->Type == ACPI_TYPE_PROCESSOR) { 574 compatpp = compatible; 575 } else if (infop->awi_info->Type == ACPI_TYPE_DEVICE) { 576 /* 577 * skip first item for pseudo processor HID. 578 * acpidev_set_compatible() will handle HID/CID for CPU device. 579 */ 580 compatpp = &compatible[1]; 581 count--; 582 } else { 583 return (AE_BAD_PARAMETER); 584 } 585 if (ACPI_FAILURE(acpidev_set_compatible(infop, compatpp, count))) { 586 return (AE_ERROR); 587 } 588 589 /* 590 * Set device unit-address property. 591 * First try to generate meaningful unit address from _UID, 592 * then use Processor Id if that fails. 593 */ 594 if ((infop->awi_info->Valid & ACPI_VALID_UID) == 0 || 595 acpidev_generate_unitaddr(infop->awi_info->UniqueId.Value, 596 ACPIDEV_ARRAY_PARAM(acpidev_cpu_uid_formats), 597 unitaddr, sizeof (unitaddr)) == NULL) { 598 (void) snprintf(unitaddr, sizeof (unitaddr), "%u", 599 (uint32_t)infop->awi_scratchpad[0]); 600 } 601 if (ACPI_FAILURE(acpidev_set_unitaddr(infop, NULL, 0, unitaddr))) { 602 return (AE_ERROR); 603 } 604 605 /* 606 * Build binding information for CPUs. 607 */ 608 if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE || 609 infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE || 610 infop->awi_op_type == ACPIDEV_OP_HOTPLUG_PROBE) { 611 if (ACPI_FAILURE(acpica_add_processor_to_map( 612 infop->awi_scratchpad[0], hdl, infop->awi_scratchpad[1]))) { 613 cmn_err(CE_WARN, "!acpidev: failed to bind processor " 614 "id/object handle for %s.", infop->awi_name); 615 return (AE_ERROR); 616 } 617 } else { 618 ACPIDEV_DEBUG(CE_WARN, 619 "acpidev: unknown operation type %u in acpidev_cpu_init.", 620 infop->awi_op_type); 621 return (AE_BAD_PARAMETER); 622 } 623 624 return (AE_OK); 625 } 626 627 static int 628 acpidev_cpu_query_dip(cpu_t *cp, dev_info_t **dipp) 629 { 630 uint32_t apicid; 631 ACPI_HANDLE hdl; 632 dev_info_t *dip = NULL; 633 634 *dipp = NULL; 635 /* 636 * Try to get the dip associated with the CPU if ACPI_DEVCFG_CPU is 637 * enabled. 638 */ 639 if (acpica_get_devcfg_feature(ACPI_DEVCFG_CPU)) { 640 apicid = cpuid_get_apicid(cp); 641 if (acpica_get_cpu_object_by_cpuid(cp->cpu_id, &hdl) == 0 || 642 (apicid != UINT32_MAX && 643 acpica_get_cpu_object_by_apicid(apicid, &hdl) == 0)) { 644 ASSERT(hdl != NULL); 645 if (ACPI_SUCCESS(acpica_get_devinfo(hdl, &dip))) { 646 ASSERT(dip != NULL); 647 ndi_hold_devi(dip); 648 *dipp = dip; 649 return (PSM_SUCCESS); 650 } 651 } 652 } 653 654 ACPIDEV_DEBUG(CE_WARN, "acpidev: failed to get dip for cpu %d(%p).", 655 cp->cpu_id, (void *)cp); 656 if (psm_cpu_create_devinfo_old != NULL) { 657 return (psm_cpu_create_devinfo_old(cp, dipp)); 658 } else { 659 return (PSM_FAILURE); 660 } 661 } 662