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 }