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 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 object.
  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 head of class drivers which will be called in order when handling
  99  * children of ACPI cpu/processor object.
 100  */
 101 acpidev_class_list_t *acpidev_class_list_cpu = NULL;
 102 
 103 /* Filter rule table for first probe at boot time. */
 104 static acpidev_filter_rule_t acpidev_cpu_filters[] = {
 105         {       /* Skip all processor 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 in 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 of enabled CPUs from 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: encounter 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 /* Extract information of enabled CPUs from buffer returned by _MAT method. */
 235 static ACPI_STATUS
 236 acpidev_cpu_query_MAT(ACPI_SUBTABLE_HEADER *ap, void *context)
 237 {
 238         ACPI_MADT_LOCAL_APIC *mpa;
 239         ACPI_MADT_LOCAL_X2APIC *mpx2a;
 240         struct acpidev_cpu_MAT_arg *rp;
 241 
 242         rp = (struct acpidev_cpu_MAT_arg *)context;
 243         switch (ap->Type) {
 244         case ACPI_MADT_TYPE_LOCAL_APIC:
 245                 mpa = (ACPI_MADT_LOCAL_APIC *)ap;
 246                 ASSERT(mpa->Id != 255);
 247                 rp->found = B_TRUE;
 248                 rp->proc_id = mpa->ProcessorId;
 249                 rp->apic_id = mpa->Id;
 250                 if (mpa->LapicFlags & ACPI_MADT_ENABLED) {
 251                         rp->enabled = B_TRUE;
 252                 } else {
 253                         rp->enabled = B_FALSE;
 254                 }
 255                 return (AE_CTRL_TERMINATE);
 256 
 257         case ACPI_MADT_TYPE_LOCAL_X2APIC:
 258                 mpx2a = (ACPI_MADT_LOCAL_X2APIC *)ap;
 259                 if (mpx2a->LocalApicId >= 255) {
 260                         rp->found = B_TRUE;
 261                         rp->proc_id = mpx2a->Uid;
 262                         rp->apic_id = mpx2a->LocalApicId;
 263                         if (mpx2a->LapicFlags & ACPI_MADT_ENABLED) {
 264                                 rp->enabled = B_TRUE;
 265                         } else {
 266                                 rp->enabled = B_FALSE;
 267                         }
 268                         return (AE_CTRL_TERMINATE);
 269                 } else {
 270                         ACPIDEV_DEBUG(CE_WARN, "acpidev: encounter CPU "
 271                             "with X2APIC Id < 255 in _MAT.");
 272                 }
 273                 break;
 274 
 275         case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
 276                 /* UNIMPLEMENTED */
 277                 break;
 278 
 279         case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
 280                 /* UNIMPLEMENTED */
 281                 break;
 282 
 283         default:
 284                 /*
 285                  * According to ACPI Spec, buffer return by _MAT under
 286                  * processor object should only contain Local APIC,
 287                  * Local SAPIC, local APIC NMI entries.
 288                  * x2APIC Specification extends it to support Processor
 289                  * x2APIC and x2APIC NMI Structure.
 290                  */
 291                 ACPIDEV_DEBUG(CE_NOTE,
 292                     "acpidev: unknown APIC entry type %u in _MAT.", ap->Type);
 293                 break;
 294         }
 295 
 296         return (AE_OK);
 297 }
 298 
 299 /* Query ACPI processor id by evaluating ACPI _MAT, _UID, PROCESSOR object. */
 300 static ACPI_STATUS
 301 acpidev_cpu_get_procid(acpidev_walk_info_t *infop, uint32_t *idp)
 302 {
 303         int id;
 304         ACPI_HANDLE hdl;
 305         struct acpidev_cpu_MAT_arg mat;
 306 
 307         if (infop->awi_info->Type != ACPI_TYPE_PROCESSOR &&
 308             infop->awi_info->Type != ACPI_TYPE_DEVICE) {
 309                 ACPIDEV_DEBUG(CE_WARN,
 310                     "acpidev: object %s is not PROCESSOR or DEVICE.",
 311                     infop->awi_name);
 312                 return (AE_BAD_PARAMETER);
 313         }
 314         hdl = infop->awi_hdl;
 315 
 316         /*
 317          * First try to evaluate _MAT.
 318          * According to ACPI Spec3.0b, it's legal for ACPI PROCESSOR object
 319          * to have ACPI method objects.
 320          */
 321         bzero(&mat, sizeof (mat));
 322         (void) acpidev_walk_apic(NULL, hdl, ACPIDEV_METHOD_NAME_MAT,
 323             acpidev_cpu_query_MAT, &mat);
 324         if (mat.found) {
 325                 *idp = mat.proc_id;
 326                 return (AE_OK);
 327         }
 328 
 329         /* Then evalute PROCESSOR object. */
 330         if (infop->awi_info->Type == ACPI_TYPE_PROCESSOR) {
 331                 ACPI_BUFFER rb;
 332 
 333                 rb.Pointer = NULL;
 334                 rb.Length = ACPI_ALLOCATE_BUFFER;
 335                 if (ACPI_SUCCESS(AcpiEvaluateObjectTyped(hdl, NULL, NULL, &rb,
 336                     ACPI_TYPE_PROCESSOR))) {
 337                         *idp = ((ACPI_OBJECT *)rb.Pointer)->Processor.ProcId;
 338                         AcpiOsFree(rb.Pointer);
 339                         return (AE_OK);
 340                 } else {
 341                         ACPIDEV_DEBUG(CE_WARN,
 342                             "acpidev: failed to evaluate ACPI object %s.",
 343                             infop->awi_name);
 344                 }
 345         }
 346 
 347         /*
 348          * Last try to evalute _UID method.
 349          * According to ACPI Spec3.0b, it's legal for ACPI PROCESSOR object
 350          * to have ACPI method objects.
 351          * CPU _UID method should return Processor Id as integer on x86.
 352          */
 353         if (ACPI_SUCCESS(acpica_eval_int(hdl, METHOD_NAME__UID, &id))) {
 354                 *idp = id;
 355                 return (AE_OK);
 356         }
 357 
 358         return (AE_NOT_FOUND);
 359 }
 360 
 361 static ACPI_STATUS
 362 acpidev_cpu_pre_probe(acpidev_walk_info_t *infop)
 363 {
 364         uint32_t count = 0;
 365 
 366         /* Parse and cache APIC info in MADT on first probe at boot time. */
 367         ASSERT(infop != NULL);
 368         if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE &&
 369             acpidev_cpu_map_hdl == NULL) {
 370                 (void) acpidev_walk_apic(NULL, NULL, NULL,
 371                     acpidev_cpu_count_MADT, &acpidev_cpu_map_count);
 372                 acpidev_cpu_map = kmem_zalloc(sizeof (acpidev_cpu_map[0])
 373                     * acpidev_cpu_map_count, KM_SLEEP);
 374                 (void) acpidev_walk_apic(NULL, NULL, NULL,
 375                     acpidev_cpu_parse_MADT, &count);
 376                 ASSERT(count == acpidev_cpu_map_count);
 377                 acpidev_cpu_map_hdl = infop->awi_hdl;
 378 
 379                 /* replace psm_cpu_create_devinfo with local implementation. */
 380                 psm_cpu_create_devinfo_old = psm_cpu_create_devinfo;
 381                 psm_cpu_create_devinfo = acpidev_cpu_query_dip;
 382         }
 383 
 384         return (AE_OK);
 385 }
 386 
 387 static ACPI_STATUS
 388 acpidev_cpu_post_probe(acpidev_walk_info_t *infop)
 389 {
 390         /* Free cached APIC info on second probe at boot time. */
 391         ASSERT(infop != NULL);
 392         if (infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE &&
 393             acpidev_cpu_map_hdl != NULL &&
 394             infop->awi_hdl == acpidev_cpu_map_hdl) {
 395                 if (acpidev_cpu_map != NULL && acpidev_cpu_map_count != 0) {
 396                         kmem_free(acpidev_cpu_map, sizeof (acpidev_cpu_map[0])
 397                             * acpidev_cpu_map_count);
 398                 }
 399                 acpidev_cpu_map = NULL;
 400                 acpidev_cpu_map_count = 0;
 401                 acpidev_cpu_map_hdl = NULL;
 402         }
 403 
 404         return (AE_OK);
 405 }
 406 
 407 static ACPI_STATUS
 408 acpidev_cpu_probe(acpidev_walk_info_t *infop)
 409 {
 410         ACPI_STATUS rc = AE_OK;
 411         int flags;
 412 
 413         ASSERT(infop != NULL);
 414         ASSERT(infop->awi_hdl != NULL);
 415         ASSERT(infop->awi_info != NULL);
 416         ASSERT(infop->awi_class_curr == &acpidev_class_cpu);
 417         if (infop->awi_info->Type != ACPI_TYPE_PROCESSOR &&
 418             (infop->awi_info->Type != ACPI_TYPE_DEVICE ||
 419             acpidev_match_device_id(infop->awi_info,
 420             ACPIDEV_ARRAY_PARAM(acpidev_processor_device_ids)) == 0)) {
 421                 return (AE_OK);
 422         }
 423 
 424         /*
 425          * Mark device as offline. It will be changed to online state
 426          * when corresponding CPU starts up.
 427          */
 428         if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE) {
 429                 flags = ACPIDEV_PROCESS_FLAG_SCAN |
 430                     ACPIDEV_PROCESS_FLAG_CREATE |
 431                     ACPIDEV_PROCESS_FLAG_OFFLINE;
 432                 rc = acpidev_process_object(infop, flags);
 433         } else if (infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE) {
 434                 flags = ACPIDEV_PROCESS_FLAG_SCAN;
 435                 rc = acpidev_process_object(infop, flags);
 436         } else if (infop->awi_op_type == ACPIDEV_OP_HOTPLUG_PROBE) {
 437                 flags = ACPIDEV_PROCESS_FLAG_SCAN |
 438                     ACPIDEV_PROCESS_FLAG_CREATE |
 439                     ACPIDEV_PROCESS_FLAG_OFFLINE;
 440                 rc = acpidev_process_object(infop, flags);
 441         } else {
 442                 ACPIDEV_DEBUG(CE_WARN,
 443                     "acpidev: unknown operation type %u in cpu_probe().",
 444                     infop->awi_op_type);
 445                 rc = AE_BAD_PARAMETER;
 446         }
 447         if (ACPI_FAILURE(rc) && rc != AE_NOT_EXIST && rc != AE_ALREADY_EXISTS) {
 448                 cmn_err(CE_CONT,
 449                     "?acpidev: failed to process processor object %s.\n",
 450                     infop->awi_name);
 451         } else {
 452                 rc = AE_OK;
 453         }
 454 
 455         return (rc);
 456 }
 457 
 458 static acpidev_filter_result_t
 459 acpidev_cpu_filter_func(acpidev_walk_info_t *infop, ACPI_HANDLE hdl,
 460     acpidev_filter_rule_t *afrp, char *devname, int len)
 461 {
 462         acpidev_filter_result_t res;
 463 
 464         ASSERT(afrp != NULL);
 465         if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE ||
 466             infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE) {
 467                 uint32_t procid;
 468                 uint32_t apicid;
 469 
 470                 if (acpidev_cpu_get_procid(infop, &procid) != 0) {
 471                         ACPIDEV_DEBUG(CE_WARN,
 472                             "acpidev: failed to query processor id for %s.",
 473                             infop->awi_name);
 474                         return (ACPIDEV_FILTER_SKIP);
 475                 } else if (acpidev_cpu_get_apicid(procid, &apicid) != 0) {
 476                         ACPIDEV_DEBUG(CE_WARN,
 477                             "acpidev: failed to query apic id for %s.",
 478                             infop->awi_name);
 479                         return (ACPIDEV_FILTER_SKIP);
 480                 }
 481 
 482                 infop->awi_scratchpad[0] = procid;
 483                 infop->awi_scratchpad[1] = apicid;
 484         } else if (infop->awi_op_type == ACPIDEV_OP_HOTPLUG_PROBE) {
 485                 struct acpidev_cpu_MAT_arg mat;
 486 
 487                 bzero(&mat, sizeof (mat));
 488                 (void) acpidev_walk_apic(NULL, hdl, ACPIDEV_METHOD_NAME_MAT,
 489                     acpidev_cpu_query_MAT, &mat);
 490                 if (!mat.found) {
 491                         cmn_err(CE_WARN,
 492                             "acpidev: failed to walk apic resource for %s.",
 493                             infop->awi_name);
 494                         return (ACPIDEV_FILTER_SKIP);
 495                 } else if (!mat.enabled) {
 496                         ACPIDEV_DEBUG(CE_NOTE,
 497                             "acpidev: cpu %s has been disabled.",
 498                             infop->awi_name);
 499                         return (ACPIDEV_FILTER_SKIP);
 500                 }
 501                 /* Save processor id and APIC id in scratchpad memory. */
 502                 infop->awi_scratchpad[0] = mat.proc_id;
 503                 infop->awi_scratchpad[1] = mat.apic_id;
 504         }
 505 
 506         res = acpidev_filter_default(infop, hdl, afrp, devname, len);
 507 
 508         return (res);
 509 }
 510 
 511 static acpidev_filter_result_t
 512 acpidev_cpu_filter(acpidev_walk_info_t *infop, char *devname, int maxlen)
 513 {
 514         acpidev_filter_result_t res;
 515 
 516         ASSERT(infop != NULL);
 517         ASSERT(devname == NULL || maxlen >= ACPIDEV_MAX_NAMELEN);
 518         if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE ||
 519             infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE ||
 520             infop->awi_op_type == ACPIDEV_OP_HOTPLUG_PROBE) {
 521                 res = acpidev_filter_device(infop, infop->awi_hdl,
 522                     ACPIDEV_ARRAY_PARAM(acpidev_cpu_filters), devname, maxlen);
 523         } else {
 524                 res = ACPIDEV_FILTER_FAILED;
 525         }
 526 
 527         return (res);
 528 }
 529 
 530 static ACPI_STATUS
 531 acpidev_cpu_init(acpidev_walk_info_t *infop)
 532 {
 533         int count;
 534         dev_info_t *dip;
 535         ACPI_HANDLE hdl;
 536         char unitaddr[64];
 537         char **compatpp;
 538         static char *compatibles[] = {
 539                 ACPIDEV_HID_PROCESSOR,
 540                 ACPIDEV_TYPE_CPU,
 541                 "cpu"
 542         };
 543 
 544         ASSERT(infop != NULL);
 545         dip = infop->awi_dip;
 546         hdl = infop->awi_hdl;
 547 
 548         /* Create "apic_id" and "processor_id" properties. */
 549         if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
 550             ACPIDEV_PROP_NAME_PROCESSOR_ID, infop->awi_scratchpad[0]) !=
 551             NDI_SUCCESS) {
 552                 cmn_err(CE_CONT,
 553                     "?acpidev: failed to set processor id property for %s.\n",
 554                     infop->awi_name);
 555                 return (AE_ERROR);
 556         }
 557         if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
 558             ACPIDEV_PROP_NAME_LOCALAPIC_ID, infop->awi_scratchpad[1]) !=
 559             NDI_SUCCESS) {
 560                 cmn_err(CE_CONT,
 561                     "?acpidev: failed to set apic id property for %s.\n",
 562                     infop->awi_name);
 563                 return (AE_ERROR);
 564         }
 565 
 566         /* Set "compatibles" property for CPU dip */
 567         count = sizeof (compatibles) / sizeof (compatibles[0]);
 568         if (infop->awi_info->Type == ACPI_TYPE_PROCESSOR) {
 569                 compatpp = compatibles;
 570         } else if (infop->awi_info->Type == ACPI_TYPE_DEVICE) {
 571                 /*
 572                  * skip first item for pseudo processor HID.
 573                  * acpidev_set_compatibles() will handle HID/CID for CPU device.
 574                  */
 575                 compatpp = &compatibles[1];
 576                 count--;
 577         } else {
 578                 return (AE_BAD_PARAMETER);
 579         }
 580         if (ACPI_FAILURE(acpidev_set_compatibles(infop, compatpp, count))) {
 581                 return (AE_ERROR);
 582         }
 583 
 584         /*
 585          * Set device unit-address property.
 586          * First try to generate meaningful unit address from _UID,
 587          * then use Processor Id if fails.
 588          */
 589         if ((infop->awi_info->Valid & ACPI_VALID_UID) == 0 ||
 590             acpidev_generate_unitaddr(infop->awi_info->UniqueId.Value,
 591             ACPIDEV_ARRAY_PARAM(acpidev_cpu_uid_formats),
 592             unitaddr, sizeof (unitaddr)) == NULL) {
 593                 (void) snprintf(unitaddr, sizeof (unitaddr), "%u",
 594                     (uint32_t)infop->awi_scratchpad[0]);
 595         }
 596         if (ACPI_FAILURE(acpidev_set_unitaddr(infop, NULL, 0, unitaddr))) {
 597                 return (AE_ERROR);
 598         }
 599 
 600         /*
 601          * Build binding information for cpus.
 602          */
 603         if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE ||
 604             infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE ||
 605             infop->awi_op_type == ACPIDEV_OP_HOTPLUG_PROBE) {
 606                 if (ACPI_FAILURE(acpica_add_processor_to_map(
 607                     infop->awi_scratchpad[0], hdl, infop->awi_scratchpad[1]))) {
 608                         cmn_err(CE_CONT, "?acpidev: binding proc id/object "
 609                             "handle for %s failed.\n",
 610                             infop->awi_name);
 611                         return (AE_ERROR);
 612                 }
 613         } else {
 614                 ACPIDEV_DEBUG(CE_WARN,
 615                     "acpidev: unknown operation type %u in cpu_init.",
 616                     infop->awi_op_type);
 617                 return (AE_BAD_PARAMETER);
 618         }
 619 
 620         return (AE_OK);
 621 }
 622 
 623 static int
 624 acpidev_cpu_query_dip(cpu_t *cp, dev_info_t **dipp)
 625 {
 626         uint32_t apicid;
 627         ACPI_HANDLE hdl;
 628         dev_info_t *dip = NULL;
 629 
 630         *dipp = NULL;
 631         /* Try to get dip for cpu if ACPI_DEVCFG_CPU is enabled. */
 632         if (acpica_get_devcfg_feature(ACPI_DEVCFG_CPU)) {
 633                 apicid = cpuid_get_apicid(cp);
 634                 if (acpica_get_cpu_object_by_cpuid(cp->cpu_id, &hdl) == 0 ||
 635                     (apicid != UINT32_MAX &&
 636                     acpica_get_cpu_object_by_apicid(apicid, &hdl) == 0)) {
 637                         ASSERT(hdl != NULL);
 638                         if (ACPI_SUCCESS(acpica_get_devinfo(hdl, &dip))) {
 639                                 ASSERT(dip != NULL);
 640                                 ndi_hold_devi(dip);
 641                                 *dipp = dip;
 642                                 return (PSM_SUCCESS);
 643                         }
 644                 }
 645         }
 646 
 647         ACPIDEV_DEBUG(CE_WARN, "acpidev: failed to get dip for cpu %d(%p).",
 648             cp->cpu_id, (void *)cp);
 649         if (psm_cpu_create_devinfo_old != NULL) {
 650                 return (psm_cpu_create_devinfo_old(cp, dipp));
 651         } else {
 652                 return (PSM_FAILURE);
 653         }
 654 }