xref: /haiku/src/add-ons/kernel/drivers/power/x86_cpuidle/acpi_cpuidle.cpp (revision 83b1a68c52ba3e0e8796282759f694b7fdddf06d)
1 /*
2  * Copyright 2012, Haiku, Inc. All Rights Reserved.
3  *
4  * Distributed under the terms of the MIT License.
5  *
6  * Authors:
7  *		Yongcong Du <ycdu.vmcore@gmail.com>
8  */
9 
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include <ACPI.h>
16 #include <Drivers.h>
17 #include <Errors.h>
18 #include <KernelExport.h>
19 
20 #include <arch_system_info.h>
21 #include <cpu.h>
22 #include <cpuidle.h>
23 #include <smp.h>
24 
25 #include "x86_cpuidle.h"
26 
27 
28 #define ACPI_PDC_REVID		0x1
29 #define ACPI_OSC_QUERY		(1 << 0)
30 
31 #define ACPI_PDC_P_FFH		(1 << 0)
32 #define ACPI_PDC_C_C1_HALT	(1 << 1)
33 #define ACPI_PDC_T_FFH		(1 << 2)
34 #define ACPI_PDC_SMP_C1PT	(1 << 3)
35 #define ACPI_PDC_SMP_C2C3	(1 << 4)
36 #define ACPI_PDC_SMP_P_SW	(1 << 5)
37 #define ACPI_PDC_SMP_C_SW	(1 << 6)
38 #define ACPI_PDC_SMP_T_SW	(1 << 7)
39 #define ACPI_PDC_C_C1_FFH	(1 << 8)
40 #define ACPI_PDC_C_C2C3_FFH	(1 << 9)
41 #define ACPI_PDC_P_HWCOORD	(1 << 11)
42 
43 // Bus Master check required
44 #define ACPI_PDC_GAS_BM		(1 << 1)
45 
46 #define ACPI_CSTATE_HALT	0x1
47 #define ACPI_CSTATE_SYSIO	0x2
48 #define ACPI_CSTATE_FFH		0x3
49 
50 // Bus Master Check
51 #define ACPI_FLAG_C_BM		(1 << 0)
52 // Bus master arbitration
53 #define ACPI_FLAG_C_ARB		(1 << 1)
54 
55 // Copied from acpica's actypes.h, where's the best place to put?
56 #define ACPI_BITREG_BUS_MASTER_STATUS           0x01
57 #define ACPI_BITREG_BUS_MASTER_RLD              0x0F
58 #define ACPI_BITREG_ARB_DISABLE                 0x13
59 
60 #define ACPI_STATE_C0                   (uint8) 0
61 #define ACPI_STATE_C1                   (uint8) 1
62 #define ACPI_STATE_C2                   (uint8) 2
63 #define ACPI_STATE_C3                   (uint8) 3
64 #define ACPI_C_STATES_MAX               ACPI_STATE_C3
65 #define ACPI_C_STATE_COUNT              4
66 
67 
68 #define ACPI_CPUIDLE_MODULE_NAME "drivers/power/x86_cpuidle/acpi/driver_v1"
69 
70 
71 struct acpicpu_reg {
72 	uint8	reg_desc;
73 	uint16	reg_reslen;
74 	uint8	reg_spaceid;
75 	uint8	reg_bitwidth;
76 	uint8	reg_bitoffset;
77 	uint8	reg_accesssize;
78 	uint64	reg_addr;
79 } __attribute__((packed));
80 
81 struct acpi_cpuidle_driver_info {
82 	device_node *node;
83 	acpi_device_module_info *acpi;
84 	acpi_device acpi_cookie;
85 	uint32 flags;
86 	int32 cpuIndex;
87 };
88 
89 struct acpi_cstate_info {
90 	uint32 address;
91 	uint8 skip_bm_sts;
92 	uint8 method;
93 	uint8 type;
94 };
95 
96 
97 static acpi_cpuidle_driver_info *sAcpiProcessor[B_MAX_CPU_COUNT];
98 static CpuidleDevice sAcpiDevice;
99 static device_manager_info *sDeviceManager;
100 static acpi_module_info *sAcpi;
101 
102 CpuidleModuleInfo *gIdle;
103 
104 
105 static status_t
106 acpi_eval_pdc(acpi_cpuidle_driver_info *device)
107 {
108 	acpi_objects arg;
109 	acpi_object_type obj;
110 	uint32 cap[3];
111 
112 	arg.count = 1;
113 	arg.pointer = &obj;
114 	cap[0] = 1;
115 	cap[1] = 1;
116 	cap[2] = ACPI_PDC_C_C1_HALT | ACPI_PDC_SMP_C1PT | ACPI_PDC_SMP_C2C3;
117 	cap[2] |= ACPI_PDC_SMP_P_SW | ACPI_PDC_SMP_C_SW | ACPI_PDC_SMP_T_SW;
118 	cap[2] |= ACPI_PDC_C_C1_FFH | ACPI_PDC_C_C2C3_FFH;
119 	cap[2] |= ACPI_PDC_SMP_T_SW | ACPI_PDC_P_FFH | ACPI_PDC_P_HWCOORD
120 		| ACPI_PDC_T_FFH;
121 	obj.object_type = ACPI_TYPE_BUFFER;
122 	obj.data.buffer.length = sizeof(cap);
123 	obj.data.buffer.buffer = cap;
124 	status_t status = device->acpi->evaluate_method(device->acpi_cookie, "_PDC",
125 		&arg, NULL);
126 	return status;
127 }
128 
129 
130 static status_t
131 acpi_eval_osc(acpi_cpuidle_driver_info *device)
132 {
133 	// guid for intel platform
134 	dprintf("%s@%p\n", __func__, device->acpi_cookie);
135 	static uint8 uuid[] = {
136 		0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
137 		0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
138 	};
139 	uint32 cap[2];
140 	cap[0] = 0;
141 	cap[1] = ACPI_PDC_C_C1_HALT | ACPI_PDC_SMP_C1PT | ACPI_PDC_SMP_C2C3;
142 	cap[1] |= ACPI_PDC_SMP_P_SW | ACPI_PDC_SMP_C_SW | ACPI_PDC_SMP_T_SW;
143 	cap[1] |= ACPI_PDC_C_C1_FFH | ACPI_PDC_C_C2C3_FFH;
144 	cap[1] |= ACPI_PDC_SMP_T_SW | ACPI_PDC_P_FFH | ACPI_PDC_P_HWCOORD
145 		| ACPI_PDC_T_FFH;
146 
147 	acpi_objects arg;
148 	acpi_object_type obj[4];
149 
150 	arg.count = 4;
151 	arg.pointer = obj;
152 
153 	obj[0].object_type = ACPI_TYPE_BUFFER;
154 	obj[0].data.buffer.length = sizeof(uuid);
155 	obj[0].data.buffer.buffer = uuid;
156 	obj[1].object_type = ACPI_TYPE_INTEGER;
157 	obj[1].data.integer = ACPI_PDC_REVID;
158 	obj[2].object_type = ACPI_TYPE_INTEGER;
159 	obj[2].data.integer = sizeof(cap)/sizeof(cap[0]);
160 	obj[3].object_type = ACPI_TYPE_BUFFER;
161 	obj[3].data.buffer.length = sizeof(cap);
162 	obj[3].data.buffer.buffer = (void *)cap;
163 
164 	acpi_data buf;
165 	buf.pointer = NULL;
166 	buf.length = ACPI_ALLOCATE_LOCAL_BUFFER;
167 	status_t status = device->acpi->evaluate_method(device->acpi_cookie, "_OSC",
168 		&arg, &buf);
169 	if (status != B_OK)
170 		return status;
171 	acpi_object_type *osc = (acpi_object_type *)buf.pointer;
172 	if (osc->object_type != ACPI_TYPE_BUFFER)
173 		return B_BAD_TYPE;
174 	if (osc->data.buffer.length != sizeof(cap))
175 		return B_BUFFER_OVERFLOW;
176 	return status;
177 }
178 
179 
180 static inline bool
181 acpi_cstate_bm_check(void)
182 {
183 	uint32 val;
184 	sAcpi->read_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, &val);
185 	if (!val)
186 		return false;
187 	sAcpi->write_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
188 
189 	return true;
190 }
191 
192 
193 static inline void
194 acpi_cstate_ffh_enter(CpuidleCstate *cState)
195 {
196 	cpu_ent *cpu = get_cpu_struct();
197 	if (cpu->invoke_scheduler)
198 		return;
199 
200 	x86_monitor((void *)&cpu->invoke_scheduler, 0, 0);
201 	if (!cpu->invoke_scheduler)
202 		x86_mwait((unsigned long)cState->pData, 1);
203 }
204 
205 
206 static inline void
207 acpi_cstate_halt(void)
208 {
209 	cpu_ent *cpu = get_cpu_struct();
210 	if (cpu->invoke_scheduler)
211 		return;
212 	asm("hlt");
213 }
214 
215 
216 static void
217 acpi_cstate_enter(CpuidleCstate *cState)
218 {
219 	acpi_cstate_info *ci = (acpi_cstate_info *)cState->pData;
220 	if (ci->method == ACPI_CSTATE_FFH)
221 		acpi_cstate_ffh_enter(cState);
222 	else if (ci->method == ACPI_CSTATE_SYSIO)
223 		in8(ci->address);
224 	else
225 		acpi_cstate_halt();
226 }
227 
228 
229 static int32
230 acpi_cstate_idle(int32 state, CpuidleDevice *device)
231 {
232 	CpuidleCstate *cState = &device->cStates[state];
233 	acpi_cstate_info *ci = (acpi_cstate_info *)cState->pData;
234 	if (!ci->skip_bm_sts) {
235 		// we fall back to C1 if there's bus master activity
236 		if (acpi_cstate_bm_check())
237 			state = 1;
238 	}
239 	if (ci->type != ACPI_STATE_C3)
240 		acpi_cstate_enter(cState);
241 
242 	// set BM_RLD for Bus Master to activity to wake the system from C3
243 	// With Newer chipsets BM_RLD is a NOP Since DMA is automatically handled
244 	// during C3 State
245 	acpi_cpuidle_driver_info *pi = sAcpiProcessor[smp_get_current_cpu()];
246 	if (pi->flags & ACPI_FLAG_C_BM)
247 		sAcpi->write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
248 
249 	// disable bus master arbitration during C3
250 	if (pi->flags & ACPI_FLAG_C_ARB)
251 		sAcpi->write_bit_register(ACPI_BITREG_ARB_DISABLE, 1);
252 
253 	acpi_cstate_enter(cState);
254 
255 	// clear BM_RLD and re-enable the arbiter
256 	if (pi->flags & ACPI_FLAG_C_BM)
257 		sAcpi->write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
258 
259 	if (pi->flags & ACPI_FLAG_C_ARB)
260 		sAcpi->write_bit_register(ACPI_BITREG_ARB_DISABLE, 0);
261 
262 	return state;
263 }
264 
265 
266 static status_t
267 acpi_cstate_add(acpi_object_type *object, CpuidleCstate *cState)
268 {
269 	acpi_cstate_info *ci = (acpi_cstate_info *)malloc(sizeof(acpi_cstate_info));
270 	if (!ci)
271 		return B_NO_MEMORY;
272 
273 	if (object->object_type != ACPI_TYPE_PACKAGE) {
274 		dprintf("invalid _CST object\n");
275 		return B_ERROR;
276 	}
277 
278 	if (object->data.package.count != 4) {
279 		dprintf("invalid _CST number\n");
280 		return B_ERROR;
281 	}
282 
283 	// type
284 	acpi_object_type * pointer = &object->data.package.objects[1];
285 	if (pointer->object_type != ACPI_TYPE_INTEGER) {
286 		dprintf("invalid _CST elem type\n");
287 		return B_ERROR;
288 	}
289 	uint32 n = pointer->data.integer;
290 	if (n < 1 || n > 3) {
291 		dprintf("invalid _CST elem value\n");
292 		return B_ERROR;
293 	}
294 	ci->type = n;
295 	dprintf("C%" B_PRId32 "\n", n);
296 	snprintf(cState->name, sizeof(cState->name), "C%" B_PRId32, n);
297 
298 	// Latency
299 	pointer = &object->data.package.objects[2];
300 	if (pointer->object_type != ACPI_TYPE_INTEGER) {
301 		dprintf("invalid _CST elem type\n");
302 		return B_ERROR;
303 	}
304 	n = pointer->data.integer;
305 	cState->latency = n;
306 	dprintf("Latency: %" B_PRId32 "\n", n);
307 
308 	// power
309 	pointer = &object->data.package.objects[3];
310 	if (pointer->object_type != ACPI_TYPE_INTEGER) {
311 		dprintf("invalid _CST elem type\n");
312 		return B_ERROR;
313 	}
314 	n = pointer->data.integer;
315 	dprintf("power: %" B_PRId32 "\n", n);
316 
317 	// register
318 	pointer = &object->data.package.objects[0];
319 	if (pointer->object_type != ACPI_TYPE_BUFFER) {
320 		dprintf("invalid _CST elem type\n");
321 		return B_ERROR;
322 	}
323 	if (pointer->data.buffer.length < 15) {
324 		dprintf("invalid _CST elem length\n");
325 		return B_ERROR;
326 	}
327 
328 	struct acpicpu_reg *reg = (struct acpicpu_reg *)pointer->data.buffer.buffer;
329 	switch (reg->reg_spaceid) {
330 		case ACPI_ADR_SPACE_SYSTEM_IO:
331 			dprintf("IO method\n");
332 			if (reg->reg_addr == 0) {
333 				dprintf("illegal address\n");
334 				return B_ERROR;
335 			}
336 			if (reg->reg_bitwidth != 8) {
337 				dprintf("invalid source length\n");
338 				return B_ERROR;
339 			}
340 			ci->address = reg->reg_addr;
341 			ci->method = ACPI_CSTATE_SYSIO;
342 			break;
343 		case ACPI_ADR_SPACE_FIXED_HARDWARE:
344 		{
345 			dprintf("FFH method\n");
346 			ci->method = ACPI_CSTATE_FFH;
347 			ci->address = reg->reg_addr;
348 
349 			// skip checking BM_STS if ACPI_PDC_GAS_BM is cleared
350 			cpu_ent *cpu = get_cpu_struct();
351 			if ((cpu->arch.vendor == VENDOR_INTEL) &&
352 				!(reg->reg_accesssize & ACPI_PDC_GAS_BM))
353 				ci->skip_bm_sts = 1;
354 			break;
355 		}
356 		default:
357 			dprintf("invalid spaceid %" B_PRId8 "\n", reg->reg_spaceid);
358 			break;
359 	}
360 	cState->pData = ci;
361 	cState->EnterIdle = acpi_cstate_idle;
362 
363 	return B_OK;
364 }
365 
366 
367 static void
368 acpi_cstate_quirks(acpi_cpuidle_driver_info *device)
369 {
370 	cpu_ent *cpu = get_cpu_struct();
371 	// Calculated Model Value: M = (Extended Model << 4) + Model
372 	uint32 model = (cpu->arch.extended_model << 4) + cpu->arch.model;
373 
374 	// On all recent Intel platforms, ARB_DIS is not necessary
375 	if (cpu->arch.vendor != VENDOR_INTEL)
376 		return;
377 	if (cpu->arch.family > 0xf || (cpu->arch.family == 6 && model >= 0xf))
378 		device->flags &= ~ACPI_FLAG_C_ARB;
379 }
380 
381 
382 static status_t
383 acpi_cpuidle_setup(acpi_cpuidle_driver_info *device)
384 {
385 	// _PDC is deprecated in the ACPI 3.0, we will try _OSC firstly
386 	// and fall back to _PDC if _OSC fail
387 	status_t status = acpi_eval_osc(device);
388 	if (status != B_OK)
389 		status = acpi_eval_pdc(device);
390 	if (status != B_OK) {
391 		dprintf("failed to eval _OSC and _PDC\n");
392 		return status;
393 	}
394 
395 	acpi_data buffer;
396 	buffer.pointer = NULL;
397 	buffer.length = ACPI_ALLOCATE_BUFFER;
398 
399 	dprintf("evaluate _CST @%p\n", device->acpi_cookie);
400 	status = device->acpi->evaluate_method(device->acpi_cookie, "_CST", NULL,
401 		&buffer);
402 	if (status != B_OK) {
403 		dprintf("failed to get _CST\n");
404 		return B_IO_ERROR;
405 	}
406 
407 	acpi_object_type *object = (acpi_object_type *)buffer.pointer;
408 	if (object->object_type != ACPI_TYPE_PACKAGE)
409 		dprintf("invalid _CST type\n");
410 	if (object->data.package.count < 2)
411 		dprintf("invalid _CST count\n");
412 
413 	acpi_object_type *pointer = object->data.package.objects;
414 	if (pointer[0].object_type != ACPI_TYPE_INTEGER)
415 		dprintf("invalid _CST type 2\n");
416 	uint32 n = pointer[0].data.integer;
417 	if (n != object->data.package.count - 1)
418 		dprintf("invalid _CST count 2\n");
419 	if (n > 8)
420 		dprintf("_CST has too many states\n");
421 	dprintf("cpuidle found %" B_PRId32 " cstates\n", n);
422 	uint32 count = 1;
423 	for (uint32 i = 1; i <= n; i++) {
424 		pointer = &object->data.package.objects[i];
425 		if (acpi_cstate_add(pointer, &sAcpiDevice.cStates[count]) == B_OK)
426 			++count;
427 	}
428 	sAcpiDevice.cStateCount = count;
429 	free(buffer.pointer);
430 
431 	// TODO we assume BM is a must and ARB_DIS is always available
432 	device->flags |= ACPI_FLAG_C_ARB | ACPI_FLAG_C_BM;
433 
434 	acpi_cstate_quirks(device);
435 
436 	return B_OK;
437 }
438 
439 
440 static status_t
441 acpi_cpuidle_init(void)
442 {
443 	dprintf("acpi_cpuidle_init\n");
444 
445 	for (int32 i = 0; i < smp_get_num_cpus(); i++)
446 		if (acpi_cpuidle_setup(sAcpiProcessor[i]) != B_OK)
447 			return B_ERROR;
448 
449 	status_t status = gIdle->AddDevice(&sAcpiDevice);
450 	if (status == B_OK)
451 		dprintf("using acpi idle\n");
452 	return status;
453 }
454 
455 
456 static status_t
457 acpi_processor_init(acpi_cpuidle_driver_info *device)
458 {
459 	// get the CPU index
460 	dprintf("get acpi processor @%p\n", device->acpi_cookie);
461 
462 	acpi_data buffer;
463 	buffer.pointer = NULL;
464 	buffer.length = ACPI_ALLOCATE_BUFFER;
465 	status_t status = device->acpi->evaluate_method(device->acpi_cookie, NULL,
466 		NULL, &buffer);
467 	if (status != B_OK) {
468 		dprintf("failed to get processor obj\n");
469 		return status;
470 	}
471 
472 	acpi_object_type *object = (acpi_object_type *)buffer.pointer;
473 	dprintf("acpi cpu%" B_PRId32 ": P_BLK at %#x/%lu\n",
474 		object->data.processor.cpu_id,
475 		object->data.processor.pblk_address,
476 		object->data.processor.pblk_length);
477 
478 	int32 cpuIndex = object->data.processor.cpu_id;
479 	free(buffer.pointer);
480 
481 	if (cpuIndex < 0 || cpuIndex >= smp_get_num_cpus())
482 		return B_ERROR;
483 
484 	device->cpuIndex = cpuIndex;
485 	sAcpiProcessor[cpuIndex] = device;
486 
487 	// If nodes for all processors have been registered, init the idle callback.
488 	for (int32 i = smp_get_num_cpus() - 1; i >= 0; i--) {
489 		if (sAcpiProcessor[i] == NULL)
490 			return B_OK;
491 	}
492 
493 	if (intel_cpuidle_init() == B_OK)
494 		return B_OK;
495 
496 	status = acpi_cpuidle_init();
497 	if (status != B_OK)
498 		sAcpiProcessor[cpuIndex] = NULL;
499 
500 	return status;
501 }
502 
503 
504 static float
505 acpi_cpuidle_support(device_node *parent)
506 {
507 	const char *bus;
508 	uint32 device_type;
509 
510 	dprintf("acpi_cpuidle_support\n");
511 	// make sure parent is really the ACPI bus manager
512 	if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
513 		return -1;
514 
515 	if (strcmp(bus, "acpi") != 0)
516 		return 0.0;
517 
518 	// check whether it's really a cpu Device
519 	if (sDeviceManager->get_attr_uint32(parent, ACPI_DEVICE_TYPE_ITEM,
520 			&device_type, false) != B_OK
521 		|| device_type != ACPI_TYPE_PROCESSOR) {
522 		return 0.0;
523 	}
524 
525 	return 0.6;
526 }
527 
528 
529 static status_t
530 acpi_cpuidle_register_device(device_node *node)
531 {
532 	device_attr attrs[] = {
533 		{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "ACPI CPU IDLE" }},
534 		{ NULL }
535 	};
536 
537 	dprintf("acpi_cpuidle_register_device\n");
538 	return sDeviceManager->register_node(node, ACPI_CPUIDLE_MODULE_NAME, attrs,
539 		NULL, NULL);
540 }
541 
542 
543 static status_t
544 acpi_cpuidle_init_driver(device_node *node, void **driverCookie)
545 {
546 	dprintf("acpi_cpuidle_init_driver\n");
547 	acpi_cpuidle_driver_info *device;
548 	device = (acpi_cpuidle_driver_info *)calloc(1, sizeof(*device));
549 	if (device == NULL)
550 		return B_NO_MEMORY;
551 
552 	device->node = node;
553 
554 	device_node *parent;
555 	parent = sDeviceManager->get_parent_node(node);
556 	sDeviceManager->get_driver(parent, (driver_module_info **)&device->acpi,
557 		(void **)&device->acpi_cookie);
558 	sDeviceManager->put_node(parent);
559 
560 	status_t status = acpi_processor_init(device);
561 	if (status != B_OK) {
562 		free(device);
563 		return status;
564 	}
565 
566 	*driverCookie = device;
567 	return B_OK;
568 }
569 
570 
571 static void
572 acpi_cpuidle_uninit_driver(void *driverCookie)
573 {
574 	dprintf("acpi_cpuidle_uninit_driver");
575 	acpi_cpuidle_driver_info *device = (acpi_cpuidle_driver_info *)driverCookie;
576 	// TODO: When the first device to be unregistered, we'd need to balance the
577 	// gIdle->AddDevice() call, but ATM isn't any API for that.
578 	sAcpiProcessor[device->cpuIndex] = NULL;
579 	free(device);
580 }
581 
582 
583 module_dependency module_dependencies[] = {
584 	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager },
585 	{ B_ACPI_MODULE_NAME, (module_info **)&sAcpi},
586 	{ B_CPUIDLE_MODULE_NAME, (module_info **)&gIdle },
587 	{}
588 };
589 
590 
591 static driver_module_info sAcpiidleModule = {
592 	{
593 		ACPI_CPUIDLE_MODULE_NAME,
594 		0,
595 		NULL
596 	},
597 
598 	acpi_cpuidle_support,
599 	acpi_cpuidle_register_device,
600 	acpi_cpuidle_init_driver,
601 	acpi_cpuidle_uninit_driver,
602 	NULL,
603 	NULL,	// rescan
604 	NULL,	// removed
605 };
606 
607 
608 module_info *modules[] = {
609 	(module_info *)&sAcpiidleModule,
610 	NULL
611 };
612