ia64/xen-unstable

view xen/arch/x86/acpi/cpu_idle.c @ 19316:658b7ca5d4ed

cpuidle: remove BM_RLD access from idle entry path

Port below linux patch into xen to reduce overhead from idle entry path.

commit 31878dd86b7df9a147f5e6cc6e07092b4308782b
Author: Len Brown <len.brown@intel.com>
Date: Wed Jan 28 18:28:09 2009 -0500

ACPI: remove BM_RLD access from idle entry path

It is true that BM_RLD needs to be set to enable
bus master activity to wake an older chipset (eg PIIX4) from C3.

This is contrary to the erroneous wording the ACPI 2.0, 3.0
specifications that suggests that BM_RLD is an indicator
rather than a control bit.

ACPI 1.0's correct wording should be restored in ACPI 4.0:
http://www.acpica.org/bugzilla/show_bug.cgi?id=3D689

But the kernel should not have to clear BM_RLD
when entering a non C3-type state just to set
it again when entering a C3-type C-state.

We should be able to set BM_RLD at boot time
and leave it alone -- removing the overhead of
accessing this IO register from the idle entry path.

Signed-off-by: Len Brown <len.brown@intel.com>

Signed-off-by: Wei Gang <gang.wei@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Mar 11 10:15:06 2009 +0000 (2009-03-11)
parents 35baf43f2713
children 09253da8f1c1
line source
1 /*
2 * cpu_idle - xen idle state module derived from Linux
3 * drivers/acpi/processor_idle.c &
4 * arch/x86/kernel/acpi/cstate.c
5 *
6 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
7 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
8 * Copyright (C) 2004, 2005 Dominik Brodowski <linux@brodo.de>
9 * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
10 * - Added processor hotplug support
11 * Copyright (C) 2005 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
12 * - Added support for C3 on SMP
13 * Copyright (C) 2007, 2008 Intel Corporation
14 *
15 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or (at
20 * your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License along
28 * with this program; if not, write to the Free Software Foundation, Inc.,
29 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
30 *
31 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
32 */
34 #include <xen/config.h>
35 #include <xen/errno.h>
36 #include <xen/lib.h>
37 #include <xen/types.h>
38 #include <xen/acpi.h>
39 #include <xen/smp.h>
40 #include <xen/guest_access.h>
41 #include <xen/keyhandler.h>
42 #include <xen/cpuidle.h>
43 #include <xen/trace.h>
44 #include <asm/cache.h>
45 #include <asm/io.h>
46 #include <asm/hpet.h>
47 #include <asm/processor.h>
48 #include <public/platform.h>
49 #include <public/sysctl.h>
51 #define DEBUG_PM_CX
53 static void (*lapic_timer_off)(void);
54 static void (*lapic_timer_on)(void);
56 extern u32 pmtmr_ioport;
57 extern void (*pm_idle) (void);
58 extern void (*dead_idle) (void);
60 static void (*pm_idle_save) (void) __read_mostly;
61 unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER - 1;
62 integer_param("max_cstate", max_cstate);
63 static int local_apic_timer_c2_ok __read_mostly = 0;
64 boolean_param("lapic_timer_c2_ok", local_apic_timer_c2_ok);
66 static struct acpi_processor_power *__read_mostly processor_powers[NR_CPUS];
68 static void print_acpi_power(uint32_t cpu, struct acpi_processor_power *power)
69 {
70 uint32_t i, idle_usage = 0;
71 uint64_t res, idle_res = 0;
73 printk("==cpu%d==\n", cpu);
74 printk("active state:\t\tC%d\n",
75 power->last_state ? power->last_state->idx : -1);
76 printk("max_cstate:\t\tC%d\n", max_cstate);
77 printk("states:\n");
79 for ( i = 1; i < power->count; i++ )
80 {
81 res = acpi_pm_tick_to_ns(power->states[i].time);
82 idle_usage += power->states[i].usage;
83 idle_res += res;
85 printk((power->last_state && power->last_state->idx == i) ?
86 " *" : " ");
87 printk("C%d:\t", i);
88 printk("type[C%d] ", power->states[i].type);
89 printk("latency[%03d] ", power->states[i].latency);
90 printk("usage[%08d] ", power->states[i].usage);
91 printk("duration[%"PRId64"]\n", res);
92 }
93 printk(" C0:\tusage[%08d] duration[%"PRId64"]\n",
94 idle_usage, NOW() - idle_res);
96 }
98 static void dump_cx(unsigned char key)
99 {
100 unsigned int cpu;
102 for_each_online_cpu ( cpu )
103 if (processor_powers[cpu])
104 print_acpi_power(cpu, processor_powers[cpu]);
105 }
107 static int __init cpu_idle_key_init(void)
108 {
109 register_keyhandler(
110 'c', dump_cx, "dump cx structures");
111 return 0;
112 }
113 __initcall(cpu_idle_key_init);
115 static inline u32 ticks_elapsed(u32 t1, u32 t2)
116 {
117 if ( t2 >= t1 )
118 return (t2 - t1);
119 else if ( !(acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) )
120 return (((0x00FFFFFF - t1) + t2) & 0x00FFFFFF);
121 else
122 return ((0xFFFFFFFF - t1) + t2);
123 }
125 static void acpi_safe_halt(void)
126 {
127 smp_mb__after_clear_bit();
128 safe_halt();
129 }
131 #define MWAIT_ECX_INTERRUPT_BREAK (0x1)
133 static void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
134 {
135 __monitor((void *)current, 0, 0);
136 smp_mb();
137 __mwait(eax, ecx);
138 }
140 static void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)
141 {
142 mwait_idle_with_hints(cx->address, MWAIT_ECX_INTERRUPT_BREAK);
143 }
145 static void acpi_idle_do_entry(struct acpi_processor_cx *cx)
146 {
147 int unused;
149 switch ( cx->entry_method )
150 {
151 case ACPI_CSTATE_EM_FFH:
152 /* Call into architectural FFH based C-state */
153 acpi_processor_ffh_cstate_enter(cx);
154 return;
155 case ACPI_CSTATE_EM_SYSIO:
156 /* IO port based C-state */
157 inb(cx->address);
158 /* Dummy wait op - must do something useless after P_LVL2 read
159 because chipsets cannot guarantee that STPCLK# signal
160 gets asserted in time to freeze execution properly. */
161 unused = inl(pmtmr_ioport);
162 return;
163 case ACPI_CSTATE_EM_HALT:
164 acpi_safe_halt();
165 local_irq_disable();
166 return;
167 }
168 }
170 static int acpi_idle_bm_check(void)
171 {
172 u32 bm_status = 0;
174 acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status);
175 if ( bm_status )
176 acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
177 /*
178 * TBD: PIIX4 Erratum #18: Note that BM_STS doesn't always reflect
179 * the true state of bus mastering activity; forcing us to
180 * manually check the BMIDEA bit of each IDE channel.
181 */
182 return bm_status;
183 }
185 static struct {
186 spinlock_t lock;
187 unsigned int count;
188 } c3_cpu_status = { .lock = SPIN_LOCK_UNLOCKED };
190 static void acpi_processor_idle(void)
191 {
192 struct acpi_processor_power *power = processor_powers[smp_processor_id()];
193 struct acpi_processor_cx *cx = NULL;
194 int next_state;
195 int sleep_ticks = 0;
196 u32 t1, t2 = 0;
198 /*
199 * Interrupts must be disabled during bus mastering calculations and
200 * for C2/C3 transitions.
201 */
202 local_irq_disable();
204 if ( softirq_pending(smp_processor_id()) )
205 {
206 local_irq_enable();
207 return;
208 }
210 next_state = power ? cpuidle_current_governor->select(power) : -1;
211 if ( next_state > 0 )
212 {
213 cx = &power->states[next_state];
214 if ( power->flags.bm_check && acpi_idle_bm_check()
215 && cx->type == ACPI_STATE_C3 )
216 cx = power->safe_state;
217 if ( cx->idx > max_cstate )
218 cx = &power->states[max_cstate];
219 }
220 if ( !cx )
221 {
222 if ( pm_idle_save )
223 {
224 printk(XENLOG_DEBUG "call pm_idle_save()\n");
225 pm_idle_save();
226 }
227 else
228 {
229 printk(XENLOG_DEBUG "call acpi_safe_halt()\n");
230 acpi_safe_halt();
231 }
232 return;
233 }
235 power->last_state = cx;
237 /*
238 * Sleep:
239 * ------
240 * Invoke the current Cx state to put the processor to sleep.
241 */
242 switch ( cx->type )
243 {
244 case ACPI_STATE_C1:
245 case ACPI_STATE_C2:
246 if ( cx->type == ACPI_STATE_C1 || local_apic_timer_c2_ok )
247 {
248 /* Trace cpu idle entry */
249 TRACE_1D(TRC_PM_IDLE_ENTRY, cx->idx);
250 /* Get start time (ticks) */
251 t1 = inl(pmtmr_ioport);
252 /* Invoke C2 */
253 acpi_idle_do_entry(cx);
254 /* Get end time (ticks) */
255 t2 = inl(pmtmr_ioport);
256 /* Trace cpu idle exit */
257 TRACE_1D(TRC_PM_IDLE_EXIT, cx->idx);
259 /* Re-enable interrupts */
260 local_irq_enable();
261 /* Compute time (ticks) that we were actually asleep */
262 sleep_ticks = ticks_elapsed(t1, t2);
263 break;
264 }
266 case ACPI_STATE_C3:
267 /*
268 * disable bus master
269 * bm_check implies we need ARB_DIS
270 * !bm_check implies we need cache flush
271 * bm_control implies whether we can do ARB_DIS
272 *
273 * That leaves a case where bm_check is set and bm_control is
274 * not set. In that case we cannot do much, we enter C3
275 * without doing anything.
276 */
277 if ( power->flags.bm_check && power->flags.bm_control )
278 {
279 spin_lock(&c3_cpu_status.lock);
280 if ( ++c3_cpu_status.count == num_online_cpus() )
281 {
282 /*
283 * All CPUs are trying to go to C3
284 * Disable bus master arbitration
285 */
286 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1);
287 }
288 spin_unlock(&c3_cpu_status.lock);
289 }
290 else if ( !power->flags.bm_check )
291 {
292 /* SMP with no shared cache... Invalidate cache */
293 ACPI_FLUSH_CPU_CACHE();
294 }
296 /* Trace cpu idle entry */
297 TRACE_1D(TRC_PM_IDLE_ENTRY, cx->idx);
298 /*
299 * Before invoking C3, be aware that TSC/APIC timer may be
300 * stopped by H/W. Without carefully handling of TSC/APIC stop issues,
301 * deep C state can't work correctly.
302 */
303 /* preparing APIC stop */
304 lapic_timer_off();
306 /* Get start time (ticks) */
307 t1 = inl(pmtmr_ioport);
308 /* Invoke C3 */
309 acpi_idle_do_entry(cx);
310 /* Get end time (ticks) */
311 t2 = inl(pmtmr_ioport);
313 /* recovering TSC */
314 cstate_restore_tsc();
315 /* Trace cpu idle exit */
316 TRACE_1D(TRC_PM_IDLE_EXIT, cx->idx);
318 if ( power->flags.bm_check && power->flags.bm_control )
319 {
320 /* Enable bus master arbitration */
321 spin_lock(&c3_cpu_status.lock);
322 if ( c3_cpu_status.count-- == num_online_cpus() )
323 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
324 spin_unlock(&c3_cpu_status.lock);
325 }
327 /* Re-enable interrupts */
328 local_irq_enable();
329 /* recovering APIC */
330 lapic_timer_on();
331 /* Compute time (ticks) that we were actually asleep */
332 sleep_ticks = ticks_elapsed(t1, t2);
334 break;
336 default:
337 local_irq_enable();
338 return;
339 }
341 cx->usage++;
342 if ( sleep_ticks > 0 )
343 {
344 power->last_residency = acpi_pm_tick_to_ns(sleep_ticks) / 1000UL;
345 cx->time += sleep_ticks;
346 }
348 if ( cpuidle_current_governor->reflect )
349 cpuidle_current_governor->reflect(power);
350 }
352 static void acpi_dead_idle(void)
353 {
354 struct acpi_processor_power *power;
355 struct acpi_processor_cx *cx;
356 int unused;
358 if ( (power = processor_powers[smp_processor_id()]) == NULL )
359 goto default_halt;
361 if ( (cx = &power->states[power->count-1]) == NULL )
362 goto default_halt;
364 for ( ; ; )
365 {
366 if ( !power->flags.bm_check && cx->type == ACPI_STATE_C3 )
367 ACPI_FLUSH_CPU_CACHE();
369 switch ( cx->entry_method )
370 {
371 case ACPI_CSTATE_EM_FFH:
372 /* Not treat interrupt as break event */
373 mwait_idle_with_hints(cx->address, 0);
374 break;
375 case ACPI_CSTATE_EM_SYSIO:
376 inb(cx->address);
377 unused = inl(pmtmr_ioport);
378 break;
379 default:
380 goto default_halt;
381 }
382 }
384 default_halt:
385 for ( ; ; )
386 halt();
387 }
389 static int init_cx_pminfo(struct acpi_processor_power *acpi_power)
390 {
391 int i;
393 memset(acpi_power, 0, sizeof(*acpi_power));
395 for ( i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++ )
396 acpi_power->states[i].idx = i;
398 acpi_power->states[ACPI_STATE_C1].type = ACPI_STATE_C1;
399 acpi_power->states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_EM_HALT;
401 acpi_power->states[ACPI_STATE_C0].valid = 1;
402 acpi_power->states[ACPI_STATE_C1].valid = 1;
404 acpi_power->count = 2;
406 return 0;
407 }
409 #define CPUID_MWAIT_LEAF (5)
410 #define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
411 #define CPUID5_ECX_INTERRUPT_BREAK (0x2)
413 #define MWAIT_ECX_INTERRUPT_BREAK (0x1)
415 #define MWAIT_SUBSTATE_MASK (0xf)
416 #define MWAIT_SUBSTATE_SIZE (4)
418 static int acpi_processor_ffh_cstate_probe(xen_processor_cx_t *cx)
419 {
420 struct cpuinfo_x86 *c = &current_cpu_data;
421 unsigned int eax, ebx, ecx, edx;
422 unsigned int edx_part;
423 unsigned int cstate_type; /* C-state type and not ACPI C-state type */
424 unsigned int num_cstate_subtype;
426 if ( c->cpuid_level < CPUID_MWAIT_LEAF )
427 {
428 printk(XENLOG_INFO "MWAIT leaf not supported by cpuid\n");
429 return -EFAULT;
430 }
432 cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &edx);
433 printk(XENLOG_DEBUG "cpuid.MWAIT[.eax=%x, .ebx=%x, .ecx=%x, .edx=%x]\n",
434 eax, ebx, ecx, edx);
436 /* Check whether this particular cx_type (in CST) is supported or not */
437 cstate_type = (cx->reg.address >> MWAIT_SUBSTATE_SIZE) + 1;
438 edx_part = edx >> (cstate_type * MWAIT_SUBSTATE_SIZE);
439 num_cstate_subtype = edx_part & MWAIT_SUBSTATE_MASK;
441 if ( num_cstate_subtype < (cx->reg.address & MWAIT_SUBSTATE_MASK) )
442 return -EFAULT;
444 /* mwait ecx extensions INTERRUPT_BREAK should be supported for C2/C3 */
445 if ( !(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
446 !(ecx & CPUID5_ECX_INTERRUPT_BREAK) )
447 return -EFAULT;
449 printk(XENLOG_INFO "Monitor-Mwait will be used to enter C-%d state\n", cx->type);
450 return 0;
451 }
453 /*
454 * Initialize bm_flags based on the CPU cache properties
455 * On SMP it depends on cache configuration
456 * - When cache is not shared among all CPUs, we flush cache
457 * before entering C3.
458 * - When cache is shared among all CPUs, we use bm_check
459 * mechanism as in UP case
460 *
461 * This routine is called only after all the CPUs are online
462 */
463 static void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags)
464 {
465 struct cpuinfo_x86 *c = &current_cpu_data;
467 flags->bm_check = 0;
468 if ( num_online_cpus() == 1 )
469 flags->bm_check = 1;
470 else if ( c->x86_vendor == X86_VENDOR_INTEL )
471 {
472 /*
473 * Today all CPUs that support C3 share cache.
474 * TBD: This needs to look at cache shared map, once
475 * multi-core detection patch makes to the base.
476 */
477 flags->bm_check = 1;
478 }
479 }
481 #define VENDOR_INTEL (1)
482 #define NATIVE_CSTATE_BEYOND_HALT (2)
484 static int check_cx(struct acpi_processor_power *power, xen_processor_cx_t *cx)
485 {
486 static int bm_check_flag;
488 switch ( cx->reg.space_id )
489 {
490 case ACPI_ADR_SPACE_SYSTEM_IO:
491 if ( cx->reg.address == 0 )
492 return -EINVAL;
493 break;
495 case ACPI_ADR_SPACE_FIXED_HARDWARE:
496 if ( cx->reg.bit_width != VENDOR_INTEL ||
497 cx->reg.bit_offset != NATIVE_CSTATE_BEYOND_HALT )
498 return -EINVAL;
500 /* assume all logical cpu has the same support for mwait */
501 if ( acpi_processor_ffh_cstate_probe(cx) )
502 return -EINVAL;
503 break;
505 default:
506 return -ENODEV;
507 }
509 switch ( cx->type )
510 {
511 case ACPI_STATE_C2:
512 if ( local_apic_timer_c2_ok )
513 break;
514 case ACPI_STATE_C3:
515 /* We must be able to use HPET in place of LAPIC timers. */
516 if ( hpet_broadcast_is_available() )
517 {
518 lapic_timer_off = hpet_broadcast_enter;
519 lapic_timer_on = hpet_broadcast_exit;
520 }
521 else if ( pit_broadcast_is_available() )
522 {
523 lapic_timer_off = pit_broadcast_enter;
524 lapic_timer_on = pit_broadcast_exit;
525 }
526 else
527 {
528 return -EINVAL;
529 }
531 /* All the logic here assumes flags.bm_check is same across all CPUs */
532 if ( !bm_check_flag )
533 {
534 /* Determine whether bm_check is needed based on CPU */
535 acpi_processor_power_init_bm_check(&(power->flags));
536 bm_check_flag = power->flags.bm_check;
537 }
538 else
539 {
540 power->flags.bm_check = bm_check_flag;
541 }
543 if ( power->flags.bm_check )
544 {
545 if ( !power->flags.bm_control )
546 {
547 if ( power->flags.has_cst != 1 )
548 {
549 /* bus mastering control is necessary */
550 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
551 "C3 support requires BM control\n"));
552 return -EINVAL;
553 }
554 else
555 {
556 /* Here we enter C3 without bus mastering */
557 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
558 "C3 support without BM control\n"));
559 }
560 }
561 /*
562 * On older chipsets, BM_RLD needs to be set
563 * in order for Bus Master activity to wake the
564 * system from C3. Newer chipsets handle DMA
565 * during C3 automatically and BM_RLD is a NOP.
566 * In either case, the proper way to
567 * handle BM_RLD is to set it and leave it set.
568 */
569 acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
570 }
571 else
572 {
573 /*
574 * WBINVD should be set in fadt, for C3 state to be
575 * supported on when bm_check is not required.
576 */
577 if ( !(acpi_gbl_FADT.flags & ACPI_FADT_WBINVD) )
578 {
579 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
580 "Cache invalidation should work properly"
581 " for C3 to be enabled on SMP systems\n"));
582 return -EINVAL;
583 }
584 acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
585 }
587 break;
588 }
590 return 0;
591 }
593 static unsigned int latency_factor = 2;
595 static void set_cx(
596 struct acpi_processor_power *acpi_power,
597 xen_processor_cx_t *xen_cx)
598 {
599 struct acpi_processor_cx *cx;
601 if ( check_cx(acpi_power, xen_cx) != 0 )
602 return;
604 if ( xen_cx->type == ACPI_STATE_C1 )
605 cx = &acpi_power->states[1];
606 else
607 cx = &acpi_power->states[acpi_power->count];
609 if ( !cx->valid )
610 acpi_power->count++;
612 cx->valid = 1;
613 cx->type = xen_cx->type;
614 cx->address = xen_cx->reg.address;
616 switch ( xen_cx->reg.space_id )
617 {
618 case ACPI_ADR_SPACE_FIXED_HARDWARE:
619 if ( xen_cx->reg.bit_width == VENDOR_INTEL &&
620 xen_cx->reg.bit_offset == NATIVE_CSTATE_BEYOND_HALT )
621 cx->entry_method = ACPI_CSTATE_EM_FFH;
622 else
623 cx->entry_method = ACPI_CSTATE_EM_HALT;
624 break;
625 case ACPI_ADR_SPACE_SYSTEM_IO:
626 cx->entry_method = ACPI_CSTATE_EM_SYSIO;
627 break;
628 default:
629 cx->entry_method = ACPI_CSTATE_EM_NONE;
630 }
632 cx->latency = xen_cx->latency;
633 cx->power = xen_cx->power;
635 cx->latency_ticks = ns_to_acpi_pm_tick(cx->latency * 1000UL);
636 cx->target_residency = cx->latency * latency_factor;
637 if ( cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2 )
638 acpi_power->safe_state = cx;
639 }
641 int get_cpu_id(u8 acpi_id)
642 {
643 int i;
644 u8 apic_id;
646 apic_id = x86_acpiid_to_apicid[acpi_id];
647 if ( apic_id == 0xff )
648 return -1;
650 for ( i = 0; i < NR_CPUS; i++ )
651 {
652 if ( apic_id == x86_cpu_to_apicid[i] )
653 return i;
654 }
656 return -1;
657 }
659 #ifdef DEBUG_PM_CX
660 static void print_cx_pminfo(uint32_t cpu, struct xen_processor_power *power)
661 {
662 XEN_GUEST_HANDLE(xen_processor_cx_t) states;
663 xen_processor_cx_t state;
664 XEN_GUEST_HANDLE(xen_processor_csd_t) csd;
665 xen_processor_csd_t dp;
666 uint32_t i;
668 printk("cpu%d cx acpi info:\n", cpu);
669 printk("\tcount = %d\n", power->count);
670 printk("\tflags: bm_cntl[%d], bm_chk[%d], has_cst[%d],\n"
671 "\t pwr_setup_done[%d], bm_rld_set[%d]\n",
672 power->flags.bm_control, power->flags.bm_check, power->flags.has_cst,
673 power->flags.power_setup_done, power->flags.bm_rld_set);
675 states = power->states;
677 for ( i = 0; i < power->count; i++ )
678 {
679 if ( unlikely(copy_from_guest_offset(&state, states, i, 1)) )
680 return;
682 printk("\tstates[%d]:\n", i);
683 printk("\t\treg.space_id = 0x%x\n", state.reg.space_id);
684 printk("\t\treg.bit_width = 0x%x\n", state.reg.bit_width);
685 printk("\t\treg.bit_offset = 0x%x\n", state.reg.bit_offset);
686 printk("\t\treg.access_size = 0x%x\n", state.reg.access_size);
687 printk("\t\treg.address = 0x%"PRIx64"\n", state.reg.address);
688 printk("\t\ttype = %d\n", state.type);
689 printk("\t\tlatency = %d\n", state.latency);
690 printk("\t\tpower = %d\n", state.power);
692 csd = state.dp;
693 printk("\t\tdp(@0x%p)\n", csd.p);
695 if ( csd.p != NULL )
696 {
697 if ( unlikely(copy_from_guest(&dp, csd, 1)) )
698 return;
699 printk("\t\t\tdomain = %d\n", dp.domain);
700 printk("\t\t\tcoord_type = %d\n", dp.coord_type);
701 printk("\t\t\tnum = %d\n", dp.num);
702 }
703 }
704 }
705 #else
706 #define print_cx_pminfo(c, p)
707 #endif
709 long set_cx_pminfo(uint32_t cpu, struct xen_processor_power *power)
710 {
711 XEN_GUEST_HANDLE(xen_processor_cx_t) states;
712 xen_processor_cx_t xen_cx;
713 struct acpi_processor_power *acpi_power;
714 int cpu_id, i;
716 if ( unlikely(!guest_handle_okay(power->states, power->count)) )
717 return -EFAULT;
719 print_cx_pminfo(cpu, power);
721 /* map from acpi_id to cpu_id */
722 cpu_id = get_cpu_id((u8)cpu);
723 if ( cpu_id == -1 )
724 {
725 printk(XENLOG_ERR "no cpu_id for acpi_id %d\n", cpu);
726 return -EFAULT;
727 }
729 acpi_power = processor_powers[cpu_id];
730 if ( !acpi_power )
731 {
732 acpi_power = xmalloc(struct acpi_processor_power);
733 if ( !acpi_power )
734 return -ENOMEM;
735 memset(acpi_power, 0, sizeof(*acpi_power));
736 processor_powers[cpu_id] = acpi_power;
737 }
739 init_cx_pminfo(acpi_power);
741 acpi_power->cpu = cpu_id;
742 acpi_power->flags.bm_check = power->flags.bm_check;
743 acpi_power->flags.bm_control = power->flags.bm_control;
744 acpi_power->flags.has_cst = power->flags.has_cst;
746 states = power->states;
748 for ( i = 0; i < power->count; i++ )
749 {
750 if ( unlikely(copy_from_guest_offset(&xen_cx, states, i, 1)) )
751 return -EFAULT;
753 set_cx(acpi_power, &xen_cx);
754 }
756 if ( cpuidle_current_governor->enable &&
757 cpuidle_current_governor->enable(acpi_power) )
758 return -EFAULT;
760 /* FIXME: C-state dependency is not supported by far */
762 print_acpi_power(cpu_id, acpi_power);
764 if ( cpu_id == 0 && pm_idle_save == NULL )
765 {
766 pm_idle_save = pm_idle;
767 pm_idle = acpi_processor_idle;
768 }
770 if ( cpu_id == 0 )
771 {
772 dead_idle = acpi_dead_idle;
773 }
775 return 0;
776 }
778 uint32_t pmstat_get_cx_nr(uint32_t cpuid)
779 {
780 return processor_powers[cpuid] ? processor_powers[cpuid]->count : 0;
781 }
783 int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat)
784 {
785 const struct acpi_processor_power *power = processor_powers[cpuid];
786 uint64_t usage, res, idle_usage = 0, idle_res = 0;
787 int i;
789 if ( power == NULL )
790 {
791 stat->last = 0;
792 stat->nr = 0;
793 stat->idle_time = 0;
794 return 0;
795 }
797 stat->last = power->last_state ? power->last_state->idx : 0;
798 stat->nr = power->count;
799 stat->idle_time = get_cpu_idle_time(cpuid);
801 for ( i = power->count - 1; i >= 0; i-- )
802 {
803 if ( i != 0 )
804 {
805 usage = power->states[i].usage;
806 res = acpi_pm_tick_to_ns(power->states[i].time);
807 idle_usage += usage;
808 idle_res += res;
809 }
810 else
811 {
812 usage = idle_usage;
813 res = NOW() - idle_res;
814 }
815 if ( copy_to_guest_offset(stat->triggers, i, &usage, 1) ||
816 copy_to_guest_offset(stat->residencies, i, &res, 1) )
817 return -EFAULT;
818 }
820 return 0;
821 }
823 int pmstat_reset_cx_stat(uint32_t cpuid)
824 {
825 return 0;
826 }