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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2016 Nexenta Systems, Inc.
28 * Copyright (c) 2009-2010, Intel Corporation.
29 * All rights reserved.
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.
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
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>
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>
61 struct acpidev_cpu_map_item
{
66 struct acpidev_cpu_MAT_arg
{
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
);
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
**);
89 * Default class driver for ACPI processor/CPU objects.
91 acpidev_class_t acpidev_class_cpu
= {
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 */
107 * List of class drivers which will be called in order when handling
108 * children of ACPI cpu/processor objects.
110 acpidev_class_list_t
*acpidev_class_list_cpu
= NULL
;
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. */
124 { /* Create and scan other processor objects */
125 acpidev_cpu_filter_func
,
127 ACPIDEV_FILTER_DEFAULT
,
128 &acpidev_class_list_cpu
,
132 ACPIDEV_NODE_NAME_CPU
,
136 /* ACPI/PNP hardware id for processor. */
137 static char *acpidev_processor_device_ids
[] = {
141 static char *acpidev_cpu_uid_formats
[] = {
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
;
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
**);
154 /* Count how many enabled CPUs are in the MADT table. */
156 acpidev_cpu_count_MADT(ACPI_SUBTABLE_HEADER
*ap
, void *context
)
159 ACPI_MADT_LOCAL_APIC
*mpa
;
160 ACPI_MADT_LOCAL_X2APIC
*mpx2a
;
162 cntp
= (uint32_t *)context
;
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);
172 case ACPI_MADT_TYPE_LOCAL_X2APIC
:
173 mpx2a
= (ACPI_MADT_LOCAL_X2APIC
*)ap
;
174 if ((mpx2a
->LapicFlags
& ACPI_MADT_ENABLED
)) {
186 /* Extract information from the enabled CPUs using the MADT table. */
188 acpidev_cpu_parse_MADT(ACPI_SUBTABLE_HEADER
*ap
, void *context
)
191 ACPI_MADT_LOCAL_APIC
*mpa
;
192 ACPI_MADT_LOCAL_X2APIC
*mpx2a
;
194 cntp
= (uint32_t *)context
;
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
;
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.");
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
;
230 acpidev_cpu_get_apicid(uint32_t procid
, uint32_t *apicidp
)
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
;
241 return (AE_NOT_FOUND
);
245 * Extract information for enabled CPUs from the buffer returned
246 * by the _MAT method.
249 acpidev_cpu_query_MAT(ACPI_SUBTABLE_HEADER
*ap
, void *context
)
251 ACPI_MADT_LOCAL_APIC
*mpa
;
252 ACPI_MADT_LOCAL_X2APIC
*mpx2a
;
253 struct acpidev_cpu_MAT_arg
*rp
;
255 rp
= (struct acpidev_cpu_MAT_arg
*)context
;
257 case ACPI_MADT_TYPE_LOCAL_APIC
:
258 mpa
= (ACPI_MADT_LOCAL_APIC
*)ap
;
260 rp
->proc_id
= mpa
->ProcessorId
;
261 rp
->apic_id
= mpa
->Id
;
262 if (mpa
->LapicFlags
& ACPI_MADT_ENABLED
) {
263 ASSERT(mpa
->Id
!= 255);
264 rp
->enabled
= B_TRUE
;
266 rp
->enabled
= B_FALSE
;
268 return (AE_CTRL_TERMINATE
);
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.");
277 rp
->proc_id
= mpx2a
->Uid
;
278 rp
->apic_id
= mpx2a
->LocalApicId
;
279 if (mpx2a
->LapicFlags
& ACPI_MADT_ENABLED
) {
280 rp
->enabled
= B_TRUE
;
282 rp
->enabled
= B_FALSE
;
284 return (AE_CTRL_TERMINATE
);
286 case ACPI_MADT_TYPE_LOCAL_APIC_NMI
:
290 case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI
:
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.
302 ACPIDEV_DEBUG(CE_NOTE
,
303 "!acpidev: unknown APIC entry type %u in _MAT.", ap
->Type
);
311 * Query ACPI processor ID by evaluating ACPI _MAT, _UID, and PROCESSOR
315 acpidev_cpu_get_procid(acpidev_walk_info_t
*infop
, uint32_t *idp
)
319 struct acpidev_cpu_MAT_arg mat
;
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.",
326 return (AE_BAD_PARAMETER
);
328 hdl
= infop
->awi_hdl
;
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.
335 bzero(&mat
, sizeof (mat
));
336 (void) acpidev_walk_apic(NULL
, hdl
, ACPIDEV_METHOD_NAME_MAT
,
337 acpidev_cpu_query_MAT
, &mat
);
343 /* Then evalute PROCESSOR object. */
344 if (infop
->awi_info
->Type
== ACPI_TYPE_PROCESSOR
) {
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
);
355 ACPIDEV_DEBUG(CE_WARN
,
356 "!acpidev: failed to evaluate ACPI object %s.",
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.
367 if (ACPI_SUCCESS(acpica_eval_int(hdl
, METHOD_NAME__UID
, &id
))) {
372 return (AE_NOT_FOUND
);
376 acpidev_cpu_get_proximity_id(ACPI_HANDLE hdl
, uint32_t apicid
, uint32_t *pxmidp
)
379 ACPI_SUBTABLE_HEADER
*sp
;
380 ACPI_SRAT_CPU_AFFINITY
*xp
;
381 ACPI_SRAT_X2APIC_CPU_AFFINITY
*x2p
;
384 ASSERT(pxmidp
!= NULL
);
385 *pxmidp
= UINT32_MAX
;
387 if (ACPI_SUCCESS(acpidev_eval_pxm(hdl
, pxmidp
))) {
390 if (acpidev_srat_tbl_ptr
== NULL
) {
391 return (AE_NOT_FOUND
);
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
);
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;
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
;
422 sp
= (ACPI_SUBTABLE_HEADER
*)(((char *)sp
) + sp
->Length
);
425 return (AE_NOT_FOUND
);
429 acpidev_cpu_pre_probe(acpidev_walk_info_t
*infop
)
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
;
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
;
458 acpidev_cpu_post_probe(acpidev_walk_info_t
*infop
)
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
);
469 acpidev_cpu_map
= NULL
;
470 acpidev_cpu_map_count
= 0;
471 acpidev_cpu_map_hdl
= NULL
;
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
;
484 acpidev_cpu_probe(acpidev_walk_info_t
*infop
)
486 ACPI_STATUS rc
= AE_OK
;
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)) {
500 flags
= ACPIDEV_PROCESS_FLAG_SCAN
;
501 switch (infop
->awi_op_type
) {
502 case ACPIDEV_OP_BOOT_PROBE
:
504 * Mark device as offline. It will be changed to online state
505 * when the corresponding CPU starts up.
507 if (acpica_get_devcfg_feature(ACPI_DEVCFG_CPU
)) {
508 flags
|= ACPIDEV_PROCESS_FLAG_CREATE
|
509 ACPIDEV_PROCESS_FLAG_OFFLINE
;
513 case ACPIDEV_OP_BOOT_REPROBE
:
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
;
526 ACPIDEV_DEBUG(CE_WARN
, "!acpidev: unknown operation type %u in "
527 "acpidev_cpu_probe().", infop
->awi_op_type
);
528 rc
= AE_BAD_PARAMETER
;
533 rc
= acpidev_process_object(infop
, flags
);
535 if (ACPI_FAILURE(rc
) && rc
!= AE_NOT_EXIST
&& rc
!= AE_ALREADY_EXISTS
) {
537 "!acpidev: failed to process processor object %s.",
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
)
550 acpidev_filter_result_t res
;
552 ASSERT(afrp
!= NULL
);
553 if (infop
->awi_op_type
== ACPIDEV_OP_BOOT_PROBE
||
554 infop
->awi_op_type
== ACPIDEV_OP_BOOT_REPROBE
) {
558 if (acpidev_cpu_get_procid(infop
, &procid
) != 0) {
559 ACPIDEV_DEBUG(CE_WARN
,
560 "!acpidev: failed to query processor id for %s.",
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.",
567 return (ACPIDEV_FILTER_SKIP
);
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
;
575 bzero(&mat
, sizeof (mat
));
576 (void) acpidev_walk_apic(NULL
, hdl
, ACPIDEV_METHOD_NAME_MAT
,
577 acpidev_cpu_query_MAT
, &mat
);
580 "!acpidev: failed to walk apic resource for %s.",
582 return (ACPIDEV_FILTER_SKIP
);
583 } else if (!mat
.enabled
) {
584 ACPIDEV_DEBUG(CE_NOTE
,
585 "!acpidev: CPU %s has been disabled.",
587 return (ACPIDEV_FILTER_SKIP
);
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
;
594 res
= acpidev_filter_default(infop
, hdl
, afrp
, devname
, len
);
599 static acpidev_filter_result_t
600 acpidev_cpu_filter(acpidev_walk_info_t
*infop
, char *devname
, int maxlen
)
602 acpidev_filter_result_t res
;
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
);
612 res
= ACPIDEV_FILTER_FAILED
;
619 acpidev_cpu_init(acpidev_walk_info_t
*infop
)
627 static char *compatible
[] = {
628 ACPIDEV_HID_PROCESSOR
,
633 ASSERT(infop
!= NULL
);
634 dip
= infop
->awi_dip
;
635 hdl
= infop
->awi_hdl
;
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]) !=
642 "!acpidev: failed to set processor_id property for %s.",
646 if (ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
647 ACPIDEV_PROP_NAME_LOCALAPIC_ID
, infop
->awi_scratchpad
[1]) !=
650 "!acpidev: failed to set apic_id property for %s.",
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
);
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
) {
670 * skip first item for pseudo processor HID.
671 * acpidev_set_compatible() will handle HID/CID for CPU device.
673 compatpp
= &compatible
[1];
676 return (AE_BAD_PARAMETER
);
678 if (ACPI_FAILURE(acpidev_set_compatible(infop
, compatpp
, count
))) {
683 * Set device unit-address property.
684 * First try to generate meaningful unit address from _UID,
685 * then use Processor Id if that fails.
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]);
694 if (ACPI_FAILURE(acpidev_set_unitaddr(infop
, NULL
, 0, unitaddr
))) {
699 * Build binding information for CPUs.
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
);
711 ACPIDEV_DEBUG(CE_WARN
,
712 "!acpidev: unknown operation type %u in acpidev_cpu_init.",
714 return (AE_BAD_PARAMETER
);
721 acpidev_cpu_fini(ACPI_HANDLE hdl
, acpidev_data_handle_t dhdl
,
722 acpidev_class_t
*clsp
)
724 _NOTE(ARGUNUSED(clsp
, dhdl
));
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.");
742 * Lookup the dip for a CPU if ACPI CPU autoconfig is enabled.
745 acpidev_cpu_lookup_dip(cpu_t
*cp
, dev_info_t
**dipp
)
749 dev_info_t
*dip
= 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)) {
758 if (ACPI_SUCCESS(acpica_get_devinfo(hdl
, &dip
))) {
761 return (PSM_SUCCESS
);
764 ACPIDEV_DEBUG(CE_WARN
,
765 "!acpidev: failed to lookup dip for cpu %d(%p).",
766 cp
->cpu_id
, (void *)cp
);
769 return (PSM_FAILURE
);
773 acpidev_cpu_create_dip(cpu_t
*cp
, dev_info_t
**dipp
)
775 if (acpidev_cpu_lookup_dip(cp
, dipp
) == PSM_SUCCESS
) {
776 ndi_hold_devi(*dipp
);
777 return (PSM_SUCCESS
);
779 if (psm_cpu_create_devinfo_old
!= NULL
) {
780 return (psm_cpu_create_devinfo_old(cp
, dipp
));
782 return (PSM_FAILURE
);
787 acpidev_cpu_get_dip(cpu_t
*cp
, dev_info_t
**dipp
)
789 if (acpidev_cpu_lookup_dip(cp
, dipp
) == PSM_SUCCESS
) {
790 return (PSM_SUCCESS
);
792 if (psm_cpu_get_devinfo_old
!= NULL
) {
793 return (psm_cpu_get_devinfo_old(cp
, dipp
));
795 return (PSM_FAILURE
);