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 }