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