Print this page
PANKOVs restructure
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/i86pc/io/acpi/acpidev/acpidev_cpu.c
+++ new/usr/src/uts/i86pc/io/acpi/acpidev/acpidev_cpu.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26 /*
27 27 * Copyright (c) 2009-2010, Intel Corporation.
28 28 * All rights reserved.
29 29 */
30 30
31 31 /*
32 32 * [Support of X2APIC]
33 33 * According to the ACPI Spec, when using the X2APIC interrupt model, logical
34 34 * processors with APIC ID values of 255 and greater are required to have a
35 35 * Processor Device object and must convey the Processor's APIC information to
36 36 * OSPM using the Processor Local X2APIC structure. Logical Processors with APIC
37 37 * ID values less than 255 must use the Processor Local XAPIC structure to
38 38 * convey their APIC information to OSPM.
39 39 */
40 40
↓ open down ↓ |
40 lines elided |
↑ open up ↑ |
41 41 #include <sys/types.h>
42 42 #include <sys/atomic.h>
43 43 #include <sys/bootconf.h>
44 44 #include <sys/cpuvar.h>
45 45 #include <sys/machsystm.h>
46 46 #include <sys/note.h>
47 47 #include <sys/psm_types.h>
48 48 #include <sys/x86_archext.h>
49 49 #include <sys/sunddi.h>
50 50 #include <sys/sunndi.h>
51 -#include <sys/acpi/acpi.h>
51 +#include <acpica/include/acpi.h>
52 52 #include <sys/acpica.h>
53 53 #include <sys/acpidev.h>
54 54 #include <sys/acpidev_impl.h>
55 55
56 56 struct acpidev_cpu_map_item {
57 57 uint32_t proc_id;
58 58 uint32_t apic_id;
59 59 };
60 60
61 61 struct acpidev_cpu_MAT_arg {
62 62 boolean_t found;
63 63 boolean_t enabled;
64 64 uint32_t proc_id;
65 65 uint32_t apic_id;
66 66 };
67 67
68 68 static ACPI_STATUS acpidev_cpu_pre_probe(acpidev_walk_info_t *infop);
69 69 static ACPI_STATUS acpidev_cpu_post_probe(acpidev_walk_info_t *infop);
70 70 static ACPI_STATUS acpidev_cpu_probe(acpidev_walk_info_t *infop);
71 71 static acpidev_filter_result_t acpidev_cpu_filter(acpidev_walk_info_t *infop,
72 72 char *devname, int maxlen);
73 73 static ACPI_STATUS acpidev_cpu_init(acpidev_walk_info_t *infop);
74 74 static void acpidev_cpu_fini(ACPI_HANDLE hdl, acpidev_data_handle_t dhdl,
75 75 acpidev_class_t *clsp);
76 76
77 77 static acpidev_filter_result_t acpidev_cpu_filter_func(
78 78 acpidev_walk_info_t *infop, ACPI_HANDLE hdl, acpidev_filter_rule_t *afrp,
79 79 char *devname, int len);
80 80 static int acpidev_cpu_create_dip(cpu_t *, dev_info_t **);
81 81 static int acpidev_cpu_get_dip(cpu_t *, dev_info_t **);
82 82
83 83 /*
84 84 * Default class driver for ACPI processor/CPU objects.
85 85 */
86 86 acpidev_class_t acpidev_class_cpu = {
87 87 0, /* adc_refcnt */
88 88 ACPIDEV_CLASS_REV1, /* adc_version */
89 89 ACPIDEV_CLASS_ID_CPU, /* adc_class_id */
90 90 "ACPI CPU", /* adc_class_name */
91 91 ACPIDEV_TYPE_CPU, /* adc_dev_type */
92 92 NULL, /* adc_private */
93 93 acpidev_cpu_pre_probe, /* adc_pre_probe */
94 94 acpidev_cpu_post_probe, /* adc_post_probe */
95 95 acpidev_cpu_probe, /* adc_probe */
96 96 acpidev_cpu_filter, /* adc_filter */
97 97 acpidev_cpu_init, /* adc_init */
98 98 acpidev_cpu_fini, /* adc_fini */
99 99 };
100 100
101 101 /*
102 102 * List of class drivers which will be called in order when handling
103 103 * children of ACPI cpu/processor objects.
104 104 */
105 105 acpidev_class_list_t *acpidev_class_list_cpu = NULL;
106 106
107 107 /* Filter rule table for the first probe at boot time. */
108 108 static acpidev_filter_rule_t acpidev_cpu_filters[] = {
109 109 { /* Skip all processors under root node, should be there. */
110 110 NULL,
111 111 0,
112 112 ACPIDEV_FILTER_SKIP,
113 113 NULL,
114 114 1,
115 115 1,
116 116 NULL,
117 117 NULL,
118 118 },
119 119 { /* Create and scan other processor objects */
120 120 acpidev_cpu_filter_func,
121 121 0,
122 122 ACPIDEV_FILTER_DEFAULT,
123 123 &acpidev_class_list_cpu,
124 124 2,
125 125 INT_MAX,
126 126 NULL,
127 127 ACPIDEV_NODE_NAME_CPU,
128 128 }
129 129 };
130 130
131 131 /* ACPI/PNP hardware id for processor. */
132 132 static char *acpidev_processor_device_ids[] = {
133 133 ACPIDEV_HID_CPU,
134 134 };
135 135
136 136 static char *acpidev_cpu_uid_formats[] = {
137 137 "SCK%x-CPU%x",
138 138 };
139 139
140 140 static ACPI_HANDLE acpidev_cpu_map_hdl;
141 141 static uint32_t acpidev_cpu_map_count;
142 142 static struct acpidev_cpu_map_item *acpidev_cpu_map;
143 143
144 144 extern int (*psm_cpu_create_devinfo)(cpu_t *, dev_info_t **);
145 145 static int (*psm_cpu_create_devinfo_old)(cpu_t *, dev_info_t **);
146 146 extern int (*psm_cpu_get_devinfo)(cpu_t *, dev_info_t **);
147 147 static int (*psm_cpu_get_devinfo_old)(cpu_t *, dev_info_t **);
148 148
149 149 /* Count how many enabled CPUs are in the MADT table. */
150 150 static ACPI_STATUS
151 151 acpidev_cpu_count_MADT(ACPI_SUBTABLE_HEADER *ap, void *context)
152 152 {
153 153 uint32_t *cntp;
154 154 ACPI_MADT_LOCAL_APIC *mpa;
155 155 ACPI_MADT_LOCAL_X2APIC *mpx2a;
156 156
157 157 cntp = (uint32_t *)context;
158 158 switch (ap->Type) {
159 159 case ACPI_MADT_TYPE_LOCAL_APIC:
160 160 mpa = (ACPI_MADT_LOCAL_APIC *)ap;
161 161 if (mpa->LapicFlags & ACPI_MADT_ENABLED) {
162 162 ASSERT(mpa->Id != 255);
163 163 (*cntp)++;
164 164 }
165 165 break;
166 166
167 167 case ACPI_MADT_TYPE_LOCAL_X2APIC:
168 168 mpx2a = (ACPI_MADT_LOCAL_X2APIC *)ap;
169 169 /* See comment at beginning about 255 limitation. */
170 170 if ((mpx2a->LapicFlags & ACPI_MADT_ENABLED) &&
171 171 (mpx2a->LocalApicId >= 255)) {
172 172 (*cntp)++;
173 173 }
174 174 break;
175 175
176 176 default:
177 177 break;
178 178 }
179 179
180 180 return (AE_OK);
181 181 }
182 182
183 183 /* Extract information from the enabled CPUs using the MADT table. */
184 184 static ACPI_STATUS
185 185 acpidev_cpu_parse_MADT(ACPI_SUBTABLE_HEADER *ap, void *context)
186 186 {
187 187 uint32_t *cntp;
188 188 ACPI_MADT_LOCAL_APIC *mpa;
189 189 ACPI_MADT_LOCAL_X2APIC *mpx2a;
190 190
191 191 cntp = (uint32_t *)context;
192 192 switch (ap->Type) {
193 193 case ACPI_MADT_TYPE_LOCAL_APIC:
194 194 mpa = (ACPI_MADT_LOCAL_APIC *)ap;
195 195 if (mpa->LapicFlags & ACPI_MADT_ENABLED) {
196 196 ASSERT(mpa->Id != 255);
197 197 ASSERT(*cntp < acpidev_cpu_map_count);
198 198 acpidev_cpu_map[*cntp].proc_id = mpa->ProcessorId;
199 199 acpidev_cpu_map[*cntp].apic_id = mpa->Id;
200 200 (*cntp)++;
201 201 }
202 202 break;
203 203
204 204 case ACPI_MADT_TYPE_LOCAL_X2APIC:
205 205 mpx2a = (ACPI_MADT_LOCAL_X2APIC *)ap;
206 206 /* See comment at beginning about 255 limitation. */
207 207 if (mpx2a->LocalApicId < 255) {
208 208 ACPIDEV_DEBUG(CE_WARN,
209 209 "!acpidev: encountered CPU with X2APIC Id < 255.");
210 210 } else if (mpx2a->LapicFlags & ACPI_MADT_ENABLED) {
211 211 ASSERT(*cntp < acpidev_cpu_map_count);
212 212 acpidev_cpu_map[*cntp].proc_id = mpx2a->Uid;
213 213 acpidev_cpu_map[*cntp].apic_id = mpx2a->LocalApicId;
214 214 (*cntp)++;
215 215 }
216 216 break;
217 217
218 218 default:
219 219 break;
220 220 }
221 221
222 222 return (AE_OK);
223 223 }
224 224
225 225 static ACPI_STATUS
226 226 acpidev_cpu_get_apicid(uint32_t procid, uint32_t *apicidp)
227 227 {
228 228 uint32_t i;
229 229
230 230 for (i = 0; i < acpidev_cpu_map_count; i++) {
231 231 if (acpidev_cpu_map[i].proc_id == procid) {
232 232 *apicidp = acpidev_cpu_map[i].apic_id;
233 233 return (AE_OK);
234 234 }
235 235 }
236 236
237 237 return (AE_NOT_FOUND);
238 238 }
239 239
240 240 /*
241 241 * Extract information for enabled CPUs from the buffer returned
242 242 * by the _MAT method.
243 243 */
244 244 static ACPI_STATUS
245 245 acpidev_cpu_query_MAT(ACPI_SUBTABLE_HEADER *ap, void *context)
246 246 {
247 247 ACPI_MADT_LOCAL_APIC *mpa;
248 248 ACPI_MADT_LOCAL_X2APIC *mpx2a;
249 249 struct acpidev_cpu_MAT_arg *rp;
250 250
251 251 rp = (struct acpidev_cpu_MAT_arg *)context;
252 252 switch (ap->Type) {
253 253 case ACPI_MADT_TYPE_LOCAL_APIC:
254 254 mpa = (ACPI_MADT_LOCAL_APIC *)ap;
255 255 ASSERT(mpa->Id != 255);
256 256 rp->found = B_TRUE;
257 257 rp->proc_id = mpa->ProcessorId;
258 258 rp->apic_id = mpa->Id;
259 259 if (mpa->LapicFlags & ACPI_MADT_ENABLED) {
260 260 rp->enabled = B_TRUE;
261 261 } else {
262 262 rp->enabled = B_FALSE;
263 263 }
264 264 return (AE_CTRL_TERMINATE);
265 265
266 266 case ACPI_MADT_TYPE_LOCAL_X2APIC:
267 267 mpx2a = (ACPI_MADT_LOCAL_X2APIC *)ap;
268 268 if (mpx2a->LocalApicId >= 255) {
269 269 rp->found = B_TRUE;
270 270 rp->proc_id = mpx2a->Uid;
271 271 rp->apic_id = mpx2a->LocalApicId;
272 272 if (mpx2a->LapicFlags & ACPI_MADT_ENABLED) {
273 273 rp->enabled = B_TRUE;
274 274 } else {
275 275 rp->enabled = B_FALSE;
276 276 }
277 277 return (AE_CTRL_TERMINATE);
278 278 } else {
279 279 ACPIDEV_DEBUG(CE_WARN, "!acpidev: encountered CPU "
280 280 "with X2APIC Id < 255 in _MAT.");
281 281 }
282 282 break;
283 283
284 284 case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
285 285 /* UNIMPLEMENTED */
286 286 break;
287 287
288 288 case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
289 289 /* UNIMPLEMENTED */
290 290 break;
291 291
292 292 default:
293 293 /*
294 294 * According to the ACPI Spec, the buffer returned by _MAT
295 295 * for a processor object should only contain Local APIC,
296 296 * Local SAPIC, and local APIC NMI entries.
297 297 * x2APIC Specification extends it to support Processor
298 298 * x2APIC and x2APIC NMI Structure.
299 299 */
300 300 ACPIDEV_DEBUG(CE_NOTE,
301 301 "!acpidev: unknown APIC entry type %u in _MAT.", ap->Type);
302 302 break;
303 303 }
304 304
305 305 return (AE_OK);
306 306 }
307 307
308 308 /*
309 309 * Query ACPI processor ID by evaluating ACPI _MAT, _UID, and PROCESSOR
310 310 * objects.
311 311 */
312 312 static ACPI_STATUS
313 313 acpidev_cpu_get_procid(acpidev_walk_info_t *infop, uint32_t *idp)
314 314 {
315 315 int id;
316 316 ACPI_HANDLE hdl;
317 317 struct acpidev_cpu_MAT_arg mat;
318 318
319 319 if (infop->awi_info->Type != ACPI_TYPE_PROCESSOR &&
320 320 infop->awi_info->Type != ACPI_TYPE_DEVICE) {
321 321 ACPIDEV_DEBUG(CE_WARN,
322 322 "!acpidev: object %s is not PROCESSOR or DEVICE.",
323 323 infop->awi_name);
324 324 return (AE_BAD_PARAMETER);
325 325 }
326 326 hdl = infop->awi_hdl;
327 327
328 328 /*
329 329 * First try to evaluate _MAT.
330 330 * According to the ACPI Spec3.0b, it's legal for ACPI PROCESSOR objects
331 331 * to have ACPI method objects.
332 332 */
333 333 bzero(&mat, sizeof (mat));
334 334 (void) acpidev_walk_apic(NULL, hdl, ACPIDEV_METHOD_NAME_MAT,
335 335 acpidev_cpu_query_MAT, &mat);
336 336 if (mat.found) {
337 337 *idp = mat.proc_id;
338 338 return (AE_OK);
339 339 }
340 340
341 341 /* Then evalute PROCESSOR object. */
342 342 if (infop->awi_info->Type == ACPI_TYPE_PROCESSOR) {
343 343 ACPI_BUFFER rb;
344 344
345 345 rb.Pointer = NULL;
346 346 rb.Length = ACPI_ALLOCATE_BUFFER;
347 347 if (ACPI_SUCCESS(AcpiEvaluateObjectTyped(hdl, NULL, NULL, &rb,
348 348 ACPI_TYPE_PROCESSOR))) {
349 349 *idp = ((ACPI_OBJECT *)rb.Pointer)->Processor.ProcId;
350 350 AcpiOsFree(rb.Pointer);
351 351 return (AE_OK);
352 352 } else {
353 353 ACPIDEV_DEBUG(CE_WARN,
354 354 "!acpidev: failed to evaluate ACPI object %s.",
355 355 infop->awi_name);
356 356 }
357 357 }
358 358
359 359 /*
360 360 * Finally, try to evalute the _UID method.
361 361 * According to the ACPI Spec3.0b, it's legal for ACPI PROCESSOR objects
362 362 * to have ACPI method objects.
363 363 * The CPU _UID method should return Processor Id as an integer on x86.
364 364 */
365 365 if (ACPI_SUCCESS(acpica_eval_int(hdl, METHOD_NAME__UID, &id))) {
366 366 *idp = id;
367 367 return (AE_OK);
368 368 }
369 369
370 370 return (AE_NOT_FOUND);
371 371 }
372 372
373 373 static ACPI_STATUS
374 374 acpidev_cpu_get_proximity_id(ACPI_HANDLE hdl, uint32_t apicid, uint32_t *pxmidp)
375 375 {
376 376 int len, off;
377 377 ACPI_SUBTABLE_HEADER *sp;
378 378 ACPI_SRAT_CPU_AFFINITY *xp;
379 379 ACPI_SRAT_X2APIC_CPU_AFFINITY *x2p;
380 380
381 381 ASSERT(hdl != NULL);
382 382 ASSERT(pxmidp != NULL);
383 383 *pxmidp = UINT32_MAX;
384 384
385 385 if (ACPI_SUCCESS(acpidev_eval_pxm(hdl, pxmidp))) {
386 386 return (AE_OK);
387 387 }
388 388 if (acpidev_srat_tbl_ptr == NULL) {
389 389 return (AE_NOT_FOUND);
390 390 }
391 391
392 392 /* Search the static ACPI SRAT table for proximity domain id. */
393 393 sp = (ACPI_SUBTABLE_HEADER *)(acpidev_srat_tbl_ptr + 1);
394 394 len = acpidev_srat_tbl_ptr->Header.Length;
395 395 off = sizeof (*acpidev_srat_tbl_ptr);
396 396 while (off < len) {
397 397 switch (sp->Type) {
398 398 case ACPI_SRAT_TYPE_CPU_AFFINITY:
399 399 xp = (ACPI_SRAT_CPU_AFFINITY *)sp;
400 400 if ((xp->Flags & ACPI_SRAT_CPU_ENABLED) &&
401 401 xp->ApicId == apicid) {
402 402 *pxmidp = xp->ProximityDomainLo;
403 403 *pxmidp |= xp->ProximityDomainHi[0] << 8;
404 404 *pxmidp |= xp->ProximityDomainHi[1] << 16;
405 405 *pxmidp |= xp->ProximityDomainHi[2] << 24;
406 406 return (AE_OK);
407 407 }
408 408 break;
409 409
410 410 case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
411 411 x2p = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)sp;
412 412 if ((x2p->Flags & ACPI_SRAT_CPU_ENABLED) &&
413 413 x2p->ApicId == apicid) {
414 414 *pxmidp = x2p->ProximityDomain;
415 415 return (AE_OK);
416 416 }
417 417 break;
418 418 }
419 419 off += sp->Length;
420 420 sp = (ACPI_SUBTABLE_HEADER *)(((char *)sp) + sp->Length);
421 421 }
422 422
423 423 return (AE_NOT_FOUND);
424 424 }
425 425
426 426 static ACPI_STATUS
427 427 acpidev_cpu_pre_probe(acpidev_walk_info_t *infop)
428 428 {
429 429 uint32_t count = 0;
430 430
431 431 /* Parse and cache APIC info in MADT on the first probe at boot time. */
432 432 ASSERT(infop != NULL);
433 433 if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE &&
434 434 acpidev_cpu_map_hdl == NULL) {
435 435 /* Parse CPU relative information in the ACPI MADT table. */
436 436 (void) acpidev_walk_apic(NULL, NULL, NULL,
437 437 acpidev_cpu_count_MADT, &acpidev_cpu_map_count);
438 438 acpidev_cpu_map = kmem_zalloc(sizeof (acpidev_cpu_map[0])
439 439 * acpidev_cpu_map_count, KM_SLEEP);
440 440 (void) acpidev_walk_apic(NULL, NULL, NULL,
441 441 acpidev_cpu_parse_MADT, &count);
442 442 ASSERT(count == acpidev_cpu_map_count);
443 443 acpidev_cpu_map_hdl = infop->awi_hdl;
444 444
445 445 /* Cache pointer to the ACPI SRAT table. */
446 446 if (ACPI_FAILURE(AcpiGetTable(ACPI_SIG_SRAT, 1,
447 447 (ACPI_TABLE_HEADER **)&acpidev_srat_tbl_ptr))) {
448 448 acpidev_srat_tbl_ptr = NULL;
449 449 }
450 450 }
451 451
452 452 return (AE_OK);
453 453 }
454 454
455 455 static ACPI_STATUS
456 456 acpidev_cpu_post_probe(acpidev_walk_info_t *infop)
457 457 {
458 458 /* Free cached APIC info on the second probe at boot time. */
459 459 ASSERT(infop != NULL);
460 460 if (infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE &&
461 461 acpidev_cpu_map_hdl != NULL &&
462 462 infop->awi_hdl == acpidev_cpu_map_hdl) {
463 463 if (acpidev_cpu_map != NULL && acpidev_cpu_map_count != 0) {
464 464 kmem_free(acpidev_cpu_map, sizeof (acpidev_cpu_map[0])
465 465 * acpidev_cpu_map_count);
466 466 }
467 467 acpidev_cpu_map = NULL;
468 468 acpidev_cpu_map_count = 0;
469 469 acpidev_cpu_map_hdl = NULL;
470 470
471 471 /* replace psm_cpu_create_devinfo with local implementation. */
472 472 psm_cpu_create_devinfo_old = psm_cpu_create_devinfo;
473 473 psm_cpu_create_devinfo = acpidev_cpu_create_dip;
474 474 psm_cpu_get_devinfo_old = psm_cpu_get_devinfo;
475 475 psm_cpu_get_devinfo = acpidev_cpu_get_dip;
476 476 }
477 477
478 478 return (AE_OK);
479 479 }
480 480
481 481 static ACPI_STATUS
482 482 acpidev_cpu_probe(acpidev_walk_info_t *infop)
483 483 {
484 484 ACPI_STATUS rc = AE_OK;
485 485 int flags;
486 486
487 487 ASSERT(infop != NULL);
488 488 ASSERT(infop->awi_hdl != NULL);
489 489 ASSERT(infop->awi_info != NULL);
490 490 ASSERT(infop->awi_class_curr == &acpidev_class_cpu);
491 491 if (infop->awi_info->Type != ACPI_TYPE_PROCESSOR &&
492 492 (infop->awi_info->Type != ACPI_TYPE_DEVICE ||
493 493 acpidev_match_device_id(infop->awi_info,
494 494 ACPIDEV_ARRAY_PARAM(acpidev_processor_device_ids)) == 0)) {
495 495 return (AE_OK);
496 496 }
497 497
498 498 flags = ACPIDEV_PROCESS_FLAG_SCAN;
499 499 switch (infop->awi_op_type) {
500 500 case ACPIDEV_OP_BOOT_PROBE:
501 501 /*
502 502 * Mark device as offline. It will be changed to online state
503 503 * when the corresponding CPU starts up.
504 504 */
505 505 if (acpica_get_devcfg_feature(ACPI_DEVCFG_CPU)) {
506 506 flags |= ACPIDEV_PROCESS_FLAG_CREATE |
507 507 ACPIDEV_PROCESS_FLAG_OFFLINE;
508 508 }
509 509 break;
510 510
511 511 case ACPIDEV_OP_BOOT_REPROBE:
512 512 break;
513 513
514 514 case ACPIDEV_OP_HOTPLUG_PROBE:
515 515 if (acpica_get_devcfg_feature(ACPI_DEVCFG_CPU)) {
516 516 flags |= ACPIDEV_PROCESS_FLAG_CREATE |
517 517 ACPIDEV_PROCESS_FLAG_OFFLINE |
518 518 ACPIDEV_PROCESS_FLAG_SYNCSTATUS |
519 519 ACPIDEV_PROCESS_FLAG_HOLDBRANCH;
520 520 }
521 521 break;
522 522
523 523 default:
524 524 ACPIDEV_DEBUG(CE_WARN, "!acpidev: unknown operation type %u in "
525 525 "acpidev_cpu_probe().", infop->awi_op_type);
526 526 rc = AE_BAD_PARAMETER;
527 527 break;
528 528 }
529 529
530 530 if (rc == AE_OK) {
531 531 rc = acpidev_process_object(infop, flags);
532 532 }
533 533 if (ACPI_FAILURE(rc) && rc != AE_NOT_EXIST && rc != AE_ALREADY_EXISTS) {
534 534 cmn_err(CE_WARN,
535 535 "!acpidev: failed to process processor object %s.",
536 536 infop->awi_name);
537 537 } else {
538 538 rc = AE_OK;
539 539 }
540 540
541 541 return (rc);
542 542 }
543 543
544 544 static acpidev_filter_result_t
545 545 acpidev_cpu_filter_func(acpidev_walk_info_t *infop, ACPI_HANDLE hdl,
546 546 acpidev_filter_rule_t *afrp, char *devname, int len)
547 547 {
548 548 acpidev_filter_result_t res;
549 549
550 550 ASSERT(afrp != NULL);
551 551 if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE ||
552 552 infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE) {
553 553 uint32_t procid;
554 554 uint32_t apicid;
555 555
556 556 if (acpidev_cpu_get_procid(infop, &procid) != 0) {
557 557 ACPIDEV_DEBUG(CE_WARN,
558 558 "!acpidev: failed to query processor id for %s.",
559 559 infop->awi_name);
560 560 return (ACPIDEV_FILTER_SKIP);
561 561 } else if (acpidev_cpu_get_apicid(procid, &apicid) != 0) {
562 562 ACPIDEV_DEBUG(CE_WARN,
563 563 "!acpidev: failed to query apic id for %s.",
564 564 infop->awi_name);
565 565 return (ACPIDEV_FILTER_SKIP);
566 566 }
567 567
568 568 infop->awi_scratchpad[0] = procid;
569 569 infop->awi_scratchpad[1] = apicid;
570 570 } else if (infop->awi_op_type == ACPIDEV_OP_HOTPLUG_PROBE) {
571 571 struct acpidev_cpu_MAT_arg mat;
572 572
573 573 bzero(&mat, sizeof (mat));
574 574 (void) acpidev_walk_apic(NULL, hdl, ACPIDEV_METHOD_NAME_MAT,
575 575 acpidev_cpu_query_MAT, &mat);
576 576 if (!mat.found) {
577 577 cmn_err(CE_WARN,
578 578 "!acpidev: failed to walk apic resource for %s.",
579 579 infop->awi_name);
580 580 return (ACPIDEV_FILTER_SKIP);
581 581 } else if (!mat.enabled) {
582 582 ACPIDEV_DEBUG(CE_NOTE,
583 583 "!acpidev: CPU %s has been disabled.",
584 584 infop->awi_name);
585 585 return (ACPIDEV_FILTER_SKIP);
586 586 }
587 587 /* Save processor id and APIC id in scratchpad memory. */
588 588 infop->awi_scratchpad[0] = mat.proc_id;
589 589 infop->awi_scratchpad[1] = mat.apic_id;
590 590 }
591 591
592 592 res = acpidev_filter_default(infop, hdl, afrp, devname, len);
593 593
594 594 return (res);
595 595 }
596 596
597 597 static acpidev_filter_result_t
598 598 acpidev_cpu_filter(acpidev_walk_info_t *infop, char *devname, int maxlen)
599 599 {
600 600 acpidev_filter_result_t res;
601 601
602 602 ASSERT(infop != NULL);
603 603 ASSERT(devname == NULL || maxlen >= ACPIDEV_MAX_NAMELEN);
604 604 if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE ||
605 605 infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE ||
606 606 infop->awi_op_type == ACPIDEV_OP_HOTPLUG_PROBE) {
607 607 res = acpidev_filter_device(infop, infop->awi_hdl,
608 608 ACPIDEV_ARRAY_PARAM(acpidev_cpu_filters), devname, maxlen);
609 609 } else {
610 610 res = ACPIDEV_FILTER_FAILED;
611 611 }
612 612
613 613 return (res);
614 614 }
615 615
616 616 static ACPI_STATUS
617 617 acpidev_cpu_init(acpidev_walk_info_t *infop)
618 618 {
619 619 int count;
620 620 uint32_t pxmid;
621 621 dev_info_t *dip;
622 622 ACPI_HANDLE hdl;
623 623 char unitaddr[64];
624 624 char **compatpp;
625 625 static char *compatible[] = {
626 626 ACPIDEV_HID_PROCESSOR,
627 627 ACPIDEV_TYPE_CPU,
628 628 "cpu"
629 629 };
630 630
631 631 ASSERT(infop != NULL);
632 632 dip = infop->awi_dip;
633 633 hdl = infop->awi_hdl;
634 634
635 635 /* Create "apic_id", "processor_id" and "proximity_id" properties. */
636 636 if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
637 637 ACPIDEV_PROP_NAME_PROCESSOR_ID, infop->awi_scratchpad[0]) !=
638 638 NDI_SUCCESS) {
639 639 cmn_err(CE_WARN,
640 640 "!acpidev: failed to set processor_id property for %s.",
641 641 infop->awi_name);
642 642 return (AE_ERROR);
643 643 }
644 644 if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
645 645 ACPIDEV_PROP_NAME_LOCALAPIC_ID, infop->awi_scratchpad[1]) !=
646 646 NDI_SUCCESS) {
647 647 cmn_err(CE_WARN,
648 648 "!acpidev: failed to set apic_id property for %s.",
649 649 infop->awi_name);
650 650 return (AE_ERROR);
651 651 }
652 652 if (ACPI_SUCCESS(acpidev_cpu_get_proximity_id(infop->awi_hdl,
653 653 infop->awi_scratchpad[1], &pxmid))) {
654 654 if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
655 655 ACPIDEV_PROP_NAME_PROXIMITY_ID, pxmid) != NDI_SUCCESS) {
656 656 cmn_err(CE_WARN, "!acpidev: failed to set proximity id "
657 657 "property for %s.", infop->awi_name);
658 658 return (AE_ERROR);
659 659 }
660 660 }
661 661
662 662 /* Set "compatible" property for CPU dip */
663 663 count = sizeof (compatible) / sizeof (compatible[0]);
664 664 if (infop->awi_info->Type == ACPI_TYPE_PROCESSOR) {
665 665 compatpp = compatible;
666 666 } else if (infop->awi_info->Type == ACPI_TYPE_DEVICE) {
667 667 /*
668 668 * skip first item for pseudo processor HID.
669 669 * acpidev_set_compatible() will handle HID/CID for CPU device.
670 670 */
671 671 compatpp = &compatible[1];
672 672 count--;
673 673 } else {
674 674 return (AE_BAD_PARAMETER);
675 675 }
676 676 if (ACPI_FAILURE(acpidev_set_compatible(infop, compatpp, count))) {
677 677 return (AE_ERROR);
678 678 }
679 679
680 680 /*
681 681 * Set device unit-address property.
682 682 * First try to generate meaningful unit address from _UID,
683 683 * then use Processor Id if that fails.
684 684 */
685 685 if ((infop->awi_info->Valid & ACPI_VALID_UID) == 0 ||
686 686 acpidev_generate_unitaddr(infop->awi_info->UniqueId.String,
687 687 ACPIDEV_ARRAY_PARAM(acpidev_cpu_uid_formats),
688 688 unitaddr, sizeof (unitaddr)) == NULL) {
689 689 (void) snprintf(unitaddr, sizeof (unitaddr), "%u",
690 690 (uint32_t)infop->awi_scratchpad[0]);
691 691 }
692 692 if (ACPI_FAILURE(acpidev_set_unitaddr(infop, NULL, 0, unitaddr))) {
693 693 return (AE_ERROR);
694 694 }
695 695
696 696 /*
697 697 * Build binding information for CPUs.
698 698 */
699 699 if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE ||
700 700 infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE ||
701 701 infop->awi_op_type == ACPIDEV_OP_HOTPLUG_PROBE) {
702 702 if (ACPI_FAILURE(acpica_add_processor_to_map(
703 703 infop->awi_scratchpad[0], hdl, infop->awi_scratchpad[1]))) {
704 704 cmn_err(CE_WARN, "!acpidev: failed to bind processor "
705 705 "id/object handle for %s.", infop->awi_name);
706 706 return (AE_ERROR);
707 707 }
708 708 } else {
709 709 ACPIDEV_DEBUG(CE_WARN,
710 710 "!acpidev: unknown operation type %u in acpidev_cpu_init.",
711 711 infop->awi_op_type);
712 712 return (AE_BAD_PARAMETER);
713 713 }
714 714
715 715 return (AE_OK);
716 716 }
717 717
718 718 static void
719 719 acpidev_cpu_fini(ACPI_HANDLE hdl, acpidev_data_handle_t dhdl,
720 720 acpidev_class_t *clsp)
721 721 {
722 722 _NOTE(ARGUNUSED(clsp, dhdl));
723 723
724 724 int rc;
725 725 uint32_t procid;
726 726
727 727 rc = acpica_get_procid_by_object(hdl, &procid);
728 728 ASSERT(ACPI_SUCCESS(rc));
729 729 if (ACPI_SUCCESS(rc)) {
730 730 rc = acpica_remove_processor_from_map(procid);
731 731 ASSERT(ACPI_SUCCESS(rc));
732 732 if (ACPI_FAILURE(rc)) {
733 733 cmn_err(CE_WARN, "!acpidev: failed to remove "
734 734 "processor from ACPICA.");
735 735 }
736 736 }
737 737 }
738 738
739 739 /*
740 740 * Lookup the dip for a CPU if ACPI CPU autoconfig is enabled.
741 741 */
742 742 static int
743 743 acpidev_cpu_lookup_dip(cpu_t *cp, dev_info_t **dipp)
744 744 {
745 745 uint32_t apicid;
746 746 ACPI_HANDLE hdl;
747 747 dev_info_t *dip = NULL;
748 748
749 749 *dipp = NULL;
750 750 if (acpica_get_devcfg_feature(ACPI_DEVCFG_CPU)) {
751 751 apicid = cpuid_get_apicid(cp);
752 752 if (acpica_get_cpu_object_by_cpuid(cp->cpu_id, &hdl) == 0 ||
753 753 (apicid != UINT32_MAX &&
754 754 acpica_get_cpu_object_by_apicid(apicid, &hdl) == 0)) {
755 755 ASSERT(hdl != NULL);
756 756 if (ACPI_SUCCESS(acpica_get_devinfo(hdl, &dip))) {
757 757 ASSERT(dip != NULL);
758 758 *dipp = dip;
759 759 return (PSM_SUCCESS);
760 760 }
761 761 }
762 762 ACPIDEV_DEBUG(CE_WARN,
763 763 "!acpidev: failed to lookup dip for cpu %d(%p).",
764 764 cp->cpu_id, (void *)cp);
765 765 }
766 766
767 767 return (PSM_FAILURE);
768 768 }
769 769
770 770 static int
771 771 acpidev_cpu_create_dip(cpu_t *cp, dev_info_t **dipp)
772 772 {
773 773 if (acpidev_cpu_lookup_dip(cp, dipp) == PSM_SUCCESS) {
774 774 ndi_hold_devi(*dipp);
775 775 return (PSM_SUCCESS);
776 776 }
777 777 if (psm_cpu_create_devinfo_old != NULL) {
778 778 return (psm_cpu_create_devinfo_old(cp, dipp));
779 779 } else {
780 780 return (PSM_FAILURE);
781 781 }
782 782 }
783 783
784 784 static int
785 785 acpidev_cpu_get_dip(cpu_t *cp, dev_info_t **dipp)
786 786 {
787 787 if (acpidev_cpu_lookup_dip(cp, dipp) == PSM_SUCCESS) {
788 788 return (PSM_SUCCESS);
789 789 }
790 790 if (psm_cpu_get_devinfo_old != NULL) {
791 791 return (psm_cpu_get_devinfo_old(cp, dipp));
792 792 } else {
793 793 return (PSM_FAILURE);
794 794 }
795 795 }
↓ open down ↓ |
734 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX