> From: Carsten Schiers [mailto:carsten@xxxxxxxxxx]
> Sent: Monday, July 18, 2011 4:56 AM
>
> Hi,
>
> applying the patcht to Xen 4.1.1 will now result in the output below.
> Seems to work well, although no transitions
the statistics is collected in ACPI cpuidle path. In below scenario where no
valid C2/C3 states are available, there's no need to go through ACPI cpuidle
path which is a little bit more overhead than simple 'sti;hlt'. In the latter
case the transition count between C0/C1 is not that important when
you already know the total 'idle_time'. :-)
> are counted. I also wonder, why we have Max possible C-state: C7, but
> this is a major step forward...
"Max possible C-states" is the number of states that Xen can support, not
the one exported by the platform.
Thanks
Kevin
>
> Thnx, Carsten.
>
> data:/# xenpm get-cpuidle-states
> Max possible C-state: C7
>
> cpu id : 0
> total C-states : 2
> idle time(ms) : 247846
> C0 : transition [00000000000000000001]
> residency [00000000000000081314 ms]
> C1 : transition [00000000000000000001]
> residency [00000000000000247846 ms]
> pc3 : [00000000000000000000 ms]
> pc6 : [00000000000000000000 ms]
> pc7 : [00000000000000000000 ms]
> cc3 : [00000000000000000000 ms]
> cc6 : [00000000000000000000 ms]
>
> cpu id : 1
> total C-states : 2
> idle time(ms) : 195083
> C0 : transition [00000000000000000001]
> residency [00000000000000134077 ms]
> C1 : transition [00000000000000000001]
> residency [00000000000000195083 ms]
> pc3 : [00000000000000000000 ms]
> pc6 : [00000000000000000000 ms]
> pc7 : [00000000000000000000 ms]
> cc3 : [00000000000000000000 ms]
> cc6 : [00000000000000000000 ms]
>
> cpu id : 2
> total C-states : 2
> idle time(ms) : 303233
> C0 : transition [00000000000000000001]
> residency [00000000000000025927 ms]
> C1 : transition [00000000000000000001]
> residency [00000000000000303233 ms]
> pc3 : [00000000000000000000 ms]
> pc6 : [00000000000000000000 ms]
> pc7 : [00000000000000000000 ms]
> cc3 : [00000000000000000000 ms]
> cc6 : [00000000000000000000 ms]
>
>
>
> -----Ursprüngliche Nachricht-----
> Von: Tian, Kevin [mailto:kevin.tian@xxxxxxxxx]
> Gesendet: Dienstag, 5. Juli 2011 09:20
> An: xen-devel@xxxxxxxxxxxxxxxxxxx
> Cc: Carsten Schiers
> Betreff: [PATCH 1/2] cpuidle: initialize default Cstate information
>
> cpuidle: initialize default Cstate information
>
> C0/C1 should be always available when cpuidle is enabled in Xen.
> When there's case that Dom0 doesn't register ACPI Cstate information,
> e.g. due to BIOS issue or acpi processor module is not installed,
> this patch provides basic C0/C1 information available to xenpm tool.
>
> Signed-off-by Kevin Tian <kevin.tian@xxxxxxxxx>
>
> diff -r 33717472f37e xen/arch/x86/acpi/cpu_idle.c
> --- a/xen/arch/x86/acpi/cpu_idle.c Tue Jun 28 18:15:44 2011 +0100
> +++ b/xen/arch/x86/acpi/cpu_idle.c Tue Jul 05 14:36:04 2011 +0800
> @@ -53,6 +53,8 @@
> #include <public/sysctl.h>
> #include <acpi/cpufreq/cpufreq.h>
> #include <asm/apic.h>
> +#include <xen/notifier.h>
> +#include <xen/cpu.h>
>
> /*#define DEBUG_PM_CX*/
>
> @@ -592,23 +594,51 @@ default_halt:
> halt();
> }
>
> -static int init_cx_pminfo(struct acpi_processor_power *acpi_power)
> +static int cpuidle_init_cpu(int cpu)
> {
> - int i;
> + struct acpi_processor_power *acpi_power;
>
> - memset(acpi_power, 0, sizeof(*acpi_power));
> + acpi_power = processor_powers[cpu];
> + if ( !acpi_power )
> + {
> + int i;
> + acpi_power = xmalloc(struct acpi_processor_power);
> + if ( !acpi_power )
> + return -ENOMEM;
> + memset(acpi_power, 0, sizeof(*acpi_power));
>
> - for ( i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++ )
> - acpi_power->states[i].idx = i;
> + for ( i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++ )
> + acpi_power->states[i].idx = i;
> +
> + acpi_power->states[ACPI_STATE_C1].type = ACPI_STATE_C1;
> + acpi_power->states[ACPI_STATE_C1].entry_method =
> ACPI_CSTATE_EM_HALT;
> +
> + acpi_power->states[ACPI_STATE_C0].valid = 1;
> + acpi_power->states[ACPI_STATE_C1].valid = 1;
> +
> + acpi_power->count = 2;
> + acpi_power->safe_state = &acpi_power->states[ACPI_STATE_C1];
> + acpi_power->cpu = cpu;
> + processor_powers[cpu] = acpi_power;
> + }
>
> - acpi_power->states[ACPI_STATE_C1].type = ACPI_STATE_C1;
> - acpi_power->states[ACPI_STATE_C1].entry_method =
> ACPI_CSTATE_EM_HALT;
> -
> - acpi_power->states[ACPI_STATE_C0].valid = 1;
> - acpi_power->states[ACPI_STATE_C1].valid = 1;
> -
> - acpi_power->count = 2;
> - acpi_power->safe_state = &acpi_power->states[ACPI_STATE_C1];
> + if ( cpu == 0 )
> + {
> + if ( boot_cpu_has(X86_FEATURE_NONSTOP_TSC) )
> + {
> + get_tick = get_stime_tick;
> + ticks_elapsed = stime_ticks_elapsed;
> + tick_to_ns = stime_tick_to_ns;
> + ns_to_tick = ns_to_stime_tick;
> + }
> + else
> + {
> + get_tick = get_acpi_pm_tick;
> + ticks_elapsed = acpi_pm_ticks_elapsed;
> + tick_to_ns = acpi_pm_tick_to_ns;
> + ns_to_tick = ns_to_acpi_pm_tick;
> + }
> + }
>
> return 0;
> }
> @@ -938,7 +968,7 @@ long set_cx_pminfo(uint32_t cpu, struct
> XEN_GUEST_HANDLE(xen_processor_cx_t) states;
> xen_processor_cx_t xen_cx;
> struct acpi_processor_power *acpi_power;
> - int cpu_id, i;
> + int cpu_id, i, ret;
>
> if ( unlikely(!guest_handle_okay(power->states, power->count)) )
> return -EFAULT;
> @@ -950,46 +980,19 @@ long set_cx_pminfo(uint32_t cpu, struct
> if ( cpu_id == -1 )
> {
> printk(XENLOG_ERR "no cpu_id for acpi_id %d\n", cpu);
> - return -EFAULT;
> + return -EINVAL;
> }
>
> - if ( cpu_id == 0 )
> - {
> - if ( boot_cpu_has(X86_FEATURE_NONSTOP_TSC) )
> - {
> - get_tick = get_stime_tick;
> - ticks_elapsed = stime_ticks_elapsed;
> - tick_to_ns = stime_tick_to_ns;
> - ns_to_tick = ns_to_stime_tick;
> - }
> - else
> - {
> - get_tick = get_acpi_pm_tick;
> - ticks_elapsed = acpi_pm_ticks_elapsed;
> - tick_to_ns = acpi_pm_tick_to_ns;
> - ns_to_tick = ns_to_acpi_pm_tick;
> - }
> - }
> -
> + ret = cpuidle_init_cpu(cpu_id);
> + if ( ret < 0 )
> + return ret;
> +
> acpi_power = processor_powers[cpu_id];
> - if ( !acpi_power )
> - {
> - acpi_power = xmalloc(struct acpi_processor_power);
> - if ( !acpi_power )
> - return -ENOMEM;
> - memset(acpi_power, 0, sizeof(*acpi_power));
> - processor_powers[cpu_id] = acpi_power;
> - }
> -
> - init_cx_pminfo(acpi_power);
> -
> - acpi_power->cpu = cpu_id;
> acpi_power->flags.bm_check = power->flags.bm_check;
> acpi_power->flags.bm_control = power->flags.bm_control;
> acpi_power->flags.has_cst = power->flags.has_cst;
>
> states = power->states;
> -
> for ( i = 0; i < power->count; i++ )
> {
> if ( unlikely(copy_from_guest_offset(&xen_cx, states, i, 1)) )
> @@ -1004,19 +1007,17 @@ long set_cx_pminfo(uint32_t cpu, struct
>
> /* FIXME: C-state dependency is not supported by far */
>
> - /*print_acpi_power(cpu_id, acpi_power);*/
> -
> - if ( cpu_id == 0 && pm_idle_save == NULL )
> - {
> - pm_idle_save = pm_idle;
> - pm_idle = acpi_processor_idle;
> - }
> -
> if ( cpu_id == 0 )
> {
> + if ( pm_idle_save == NULL )
> + {
> + pm_idle_save = pm_idle;
> + pm_idle = acpi_processor_idle;
> + }
> +
> dead_idle = acpi_dead_idle;
> }
> -
> +
> return 0;
> }
>
> @@ -1027,7 +1028,7 @@ uint32_t pmstat_get_cx_nr(uint32_t cpuid
>
> int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat)
> {
> - const struct acpi_processor_power *power = processor_powers[cpuid];
> + struct acpi_processor_power *power = processor_powers[cpuid];
> uint64_t usage, res, idle_usage = 0, idle_res = 0;
> int i;
> struct hw_residencies hw_res = {0};
> @@ -1044,6 +1045,30 @@ int pmstat_get_cx_stat(uint32_t cpuid, s
> stat->nr = power->count;
> stat->idle_time = get_cpu_idle_time(cpuid);
>
> + /* mimic the stat when detail info hasn't been registered by dom0
> */
> + if ( pm_idle_save == NULL )
> + {
> + /* C1 */
> + usage = 1;
> + res = stat->idle_time;
> + if ( copy_to_guest_offset(stat->triggers, 1, &usage, 1) ||
> + copy_to_guest_offset(stat->residencies, 1, &res, 1) )
> + return -EFAULT;
> +
> + /* C0 */
> + res = NOW() - res;
> + if ( copy_to_guest_offset(stat->triggers, 0, &usage, 1) ||
> + copy_to_guest_offset(stat->residencies, 0, &res, 1) )
> + return -EFAULT;
> +
> + stat->pc3 = 0;
> + stat->pc6 = 0;
> + stat->pc7 = 0;
> + stat->cc3 = 0;
> + stat->cc6 = 0;
> + return 0;
> + }
> +
> for ( i = power->count - 1; i >= 0; i-- )
> {
> if ( i != 0 )
> @@ -1098,3 +1123,36 @@ bool_t cpuidle_using_deep_cstate(void)
> {
> return xen_cpuidle && max_cstate > (local_apic_timer_c2_ok ? 2 :
> 1);
> }
> +
> +static int cpu_callback(
> + struct notifier_block *nfb, unsigned long action, void *hcpu)
> +{
> + unsigned int cpu = (unsigned long)hcpu;
> +
> + /* Only hook on CPU_ONLINE because a dead cpu may utilize the info
> to
> + * to enter deep C-state */
> + switch ( action )
> + {
> + case CPU_ONLINE:
> + (void)cpuidle_init_cpu(cpu);
> + break;
> + default:
> + break;
> + }
> +
> + return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block cpu_nfb = {
> + .notifier_call = cpu_callback
> +};
> +
> +static int __init cpuidle_presmp_init(void)
> +{
> + void *cpu = (void *)(long)smp_processor_id();
> + cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
> + register_cpu_notifier(&cpu_nfb);
> + return 0;
> +}
> +presmp_initcall(cpuidle_presmp_init);
> +
> diff -r 33717472f37e xen/arch/x86/smpboot.c
> --- a/xen/arch/x86/smpboot.c Tue Jun 28 18:15:44 2011 +0100
> +++ b/xen/arch/x86/smpboot.c Tue Jul 05 14:36:04 2011 +0800
> @@ -45,7 +45,6 @@
> #include <mach_apic.h>
> #include <mach_wakecpu.h>
> #include <smpboot_hooks.h>
> -#include <acpi/cpufreq/processor_perf.h>
>
> #define setup_trampoline() (bootsym_phys(trampoline_realmode_entry))
>
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|