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