[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] RE: [PATCH 1/2] cpuidle: initialize default Cstate information
> 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |