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