CPUIDLE: adjust cstate statistic interface 1. change unit of residency, PM ticks -> ns. 2. output C0 usage & residency. Signed-off-by: Wei Gang diff -r a76b4e00e186 tools/misc/xenpm.c --- a/tools/misc/xenpm.c Tue Dec 16 13:14:25 2008 +0000 +++ b/tools/misc/xenpm.c Fri Dec 19 09:44:13 2008 +0800 @@ -108,7 +108,7 @@ static int show_cx_cpuid(int xc_fd, int printf("C%d : transition [%020"PRIu64"]\n", i, cxstat->triggers[i]); printf(" residency [%020"PRIu64" ms]\n", - cxstat->residencies[i]*1000000UL/3579/1000000UL); + cxstat->residencies[i]/1000000UL); } free(cxstat->triggers); diff -r a76b4e00e186 xen/arch/x86/acpi/cpu_idle.c --- a/xen/arch/x86/acpi/cpu_idle.c Tue Dec 16 13:14:25 2008 +0000 +++ b/xen/arch/x86/acpi/cpu_idle.c Fri Dec 19 09:44:14 2008 +0800 @@ -71,7 +71,8 @@ static struct acpi_processor_power *__re static void print_acpi_power(uint32_t cpu, struct acpi_processor_power *power) { - uint32_t i; + uint32_t i, idle_usage = 0; + uint64_t res, idle_res = 0; printk("==cpu%d==\n", cpu); printk("active state:\t\tC%d\n", @@ -81,14 +82,21 @@ static void print_acpi_power(uint32_t cp for ( i = 1; i < power->count; i++ ) { + res = pm_tick2ns(power->states[i].time); + idle_usage += power->states[i].usage; + idle_res += res; + printk((power->last_state && power->last_state->idx == i) ? " *" : " "); printk("C%d:\t", i); printk("type[C%d] ", power->states[i].type); printk("latency[%03d] ", power->states[i].latency); printk("usage[%08d] ", power->states[i].usage); - printk("duration[%"PRId64"]\n", power->states[i].time); + printk("duration[%"PRId64"]\n", res); } + printk(" C0:\tusage[%08d] duration[%"PRId64"]\n", + idle_usage, NOW() - idle_res); + } static void dump_cx(unsigned char key) @@ -749,7 +757,7 @@ int pmstat_get_cx_stat(uint32_t cpuid, s int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat) { const struct acpi_processor_power *power = processor_powers[cpuid]; - uint64_t usage; + uint64_t usage, res, idle_usage = 0, idle_res = 0; int i; if ( power == NULL ) @@ -764,16 +772,24 @@ int pmstat_get_cx_stat(uint32_t cpuid, s stat->nr = power->count; stat->idle_time = get_cpu_idle_time(cpuid); - for ( i = 0; i < power->count; i++ ) + for ( i = power->count - 1; i >= 0; i-- ) { - usage = power->states[i].usage; - if ( copy_to_guest_offset(stat->triggers, i, &usage, 1) ) + if ( i != 0 ) + { + usage = power->states[i].usage; + res = pm_tick2ns(power->states[i].time); + idle_usage += usage; + idle_res += res; + } + else + { + usage = idle_usage; + res = NOW() - idle_res; + } + if ( copy_to_guest_offset(stat->triggers, i, &usage, 1) || + copy_to_guest_offset(stat->residencies, i, &res, 1) ) return -EFAULT; } - for ( i = 0; i < power->count; i++ ) - if ( copy_to_guest_offset(stat->residencies, i, - &power->states[i].time, 1) ) - return -EFAULT; return 0; } diff -r a76b4e00e186 xen/arch/x86/time.c --- a/xen/arch/x86/time.c Tue Dec 16 13:14:25 2008 +0000 +++ b/xen/arch/x86/time.c Fri Dec 19 09:44:14 2008 +0800 @@ -1342,6 +1342,20 @@ struct tm wallclock_time(void) return gmtime(seconds); } +static struct time_scale pmt_scale; +static __init int init_pmtmr_scale(void) +{ + set_time_scale(&pmt_scale, ACPI_PM_FREQUENCY); + return 0; +} + +__initcall(init_pmtmr_scale); + +uint64_t pm_tick2ns(uint64_t ticks) +{ + return scale_delta(ticks, &pmt_scale); +} + /* * Local variables: * mode: C diff -r a76b4e00e186 xen/include/xen/time.h --- a/xen/include/xen/time.h Tue Dec 16 13:14:25 2008 +0000 +++ b/xen/include/xen/time.h Fri Dec 19 09:44:14 2008 +0800 @@ -14,6 +14,7 @@ extern int init_xen_time(void); extern void cstate_restore_tsc(void); +extern uint64_t pm_tick2ns(uint64_t ticks); extern unsigned long cpu_khz;