[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86, pm: provide core/package cstate residencies
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1278955826 -3600 # Node ID c41211b25b44a9df6ca9c62c22200a0df3be69a7 # Parent f12837d7a50e3e5f843bd1a7113bb329661c7dd0 x86, pm: provide core/package cstate residencies According to Intel 64 and IA32 Architectures SDM 3B Appendix B, Intel Nehalem/Westmere processors provide h/w MSR to report the core/package cstate residencies. Extend sysctl_get_pmstat interface to pass the core/package cstate residencies. Signed-off-by: Wei Gang <gang.wei@xxxxxxxxx> --- xen/arch/x86/acpi/cpu_idle.c | 75 +++++++++++++++++++++++++++++++++++++++++++ xen/arch/x86/time.c | 7 ++++ xen/include/asm-x86/time.h | 2 + xen/include/public/sysctl.h | 5 ++ 4 files changed, 89 insertions(+) diff -r f12837d7a50e -r c41211b25b44 xen/arch/x86/acpi/cpu_idle.c --- a/xen/arch/x86/acpi/cpu_idle.c Mon Jul 12 10:48:34 2010 +0100 +++ b/xen/arch/x86/acpi/cpu_idle.c Mon Jul 12 18:30:26 2010 +0100 @@ -55,6 +55,14 @@ /*#define DEBUG_PM_CX*/ +#define GET_HW_RES_IN_NS(msr, val) \ + do { rdmsrl(msr, val); val = tsc_ticks2ns(val); } while( 0 ) +#define GET_PC3_RES(val) GET_HW_RES_IN_NS(0x3F8, val) +#define GET_PC6_RES(val) GET_HW_RES_IN_NS(0x3F9, val) +#define GET_PC7_RES(val) GET_HW_RES_IN_NS(0x3FA, val) +#define GET_CC3_RES(val) GET_HW_RES_IN_NS(0x3FC, val) +#define GET_CC6_RES(val) GET_HW_RES_IN_NS(0x3FD, val) + static void lapic_timer_nop(void) { } static void (*lapic_timer_off)(void); static void (*lapic_timer_on)(void); @@ -75,6 +83,63 @@ boolean_param("lapic_timer_c2_ok", local boolean_param("lapic_timer_c2_ok", local_apic_timer_c2_ok); static struct acpi_processor_power *__read_mostly processor_powers[NR_CPUS]; + +struct hw_residencies +{ + uint64_t pc3; + uint64_t pc6; + uint64_t pc7; + uint64_t cc3; + uint64_t cc6; +}; + +static void do_get_hw_residencies(void *arg) +{ + struct cpuinfo_x86 *c = ¤t_cpu_data; + struct hw_residencies *hw_res = (struct hw_residencies *)arg; + + if ( c->x86_vendor != X86_VENDOR_INTEL || c->x86 != 6 ) + return; + + switch ( c->x86_model ) + { + /* Nehalem */ + case 0x1A: + case 0x1E: + case 0x1F: + case 0x2E: + /* Westmere */ + case 0x25: + case 0x2C: + GET_PC3_RES(hw_res->pc3); + GET_PC6_RES(hw_res->pc6); + GET_PC7_RES(hw_res->pc7); + GET_CC3_RES(hw_res->cc3); + GET_CC6_RES(hw_res->cc6); + break; + } +} + +static void get_hw_residencies(uint32_t cpu, struct hw_residencies *hw_res) +{ + if ( smp_processor_id() == cpu ) + do_get_hw_residencies((void *)hw_res); + else + on_selected_cpus(cpumask_of(cpu), + do_get_hw_residencies, (void *)hw_res, 1); +} + +static void print_hw_residencies(uint32_t cpu) +{ + struct hw_residencies hw_res = {0}; + + get_hw_residencies(cpu, &hw_res); + + printk("PC3[%"PRId64"] PC6[%"PRId64"] PC7[%"PRId64"]\n", + hw_res.pc3, hw_res.pc6, hw_res.pc7); + printk("CC3[%"PRId64"] CC6[%"PRId64"]\n", + hw_res.cc3, hw_res.cc6); +} static char* acpi_cstate_method_name[] = { @@ -113,6 +178,7 @@ static void print_acpi_power(uint32_t cp printk(" C0:\tusage[%08d] duration[%"PRId64"]\n", idle_usage, NOW() - idle_res); + print_hw_residencies(cpu); } static void dump_cx(unsigned char key) @@ -933,6 +999,7 @@ int pmstat_get_cx_stat(uint32_t cpuid, s const 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}; if ( power == NULL ) { @@ -965,6 +1032,14 @@ int pmstat_get_cx_stat(uint32_t cpuid, s return -EFAULT; } + get_hw_residencies(cpuid, &hw_res); + + stat->pc3 = hw_res.pc3; + stat->pc6 = hw_res.pc6; + stat->pc7 = hw_res.pc7; + stat->cc3 = hw_res.cc3; + stat->cc6 = hw_res.cc6; + return 0; } diff -r f12837d7a50e -r c41211b25b44 xen/arch/x86/time.c --- a/xen/arch/x86/time.c Mon Jul 12 10:48:34 2010 +0100 +++ b/xen/arch/x86/time.c Mon Jul 12 18:30:26 2010 +0100 @@ -785,6 +785,13 @@ s_time_t get_s_time(void) now = t->stime_local_stamp + scale_delta(delta, &t->tsc_scale); return now; +} + +uint64_t tsc_ticks2ns(uint64_t ticks) +{ + struct cpu_time *t = &this_cpu(cpu_time); + + return scale_delta(ticks, &t->tsc_scale); } /* Explicitly OR with 1 just in case version number gets out of sync. */ diff -r f12837d7a50e -r c41211b25b44 xen/include/asm-x86/time.h --- a/xen/include/asm-x86/time.h Mon Jul 12 10:48:34 2010 +0100 +++ b/xen/include/asm-x86/time.h Mon Jul 12 18:30:26 2010 +0100 @@ -56,6 +56,8 @@ uint64_t acpi_pm_tick_to_ns(uint64_t tic uint64_t acpi_pm_tick_to_ns(uint64_t ticks); uint64_t ns_to_acpi_pm_tick(uint64_t ns); +uint64_t tsc_ticks2ns(uint64_t ticks); + void pv_soft_rdtsc(struct vcpu *v, struct cpu_user_regs *regs, int rdtscp); u64 gtime_to_gtsc(struct domain *d, u64 tsc); diff -r f12837d7a50e -r c41211b25b44 xen/include/public/sysctl.h --- a/xen/include/public/sysctl.h Mon Jul 12 10:48:34 2010 +0100 +++ b/xen/include/public/sysctl.h Mon Jul 12 18:30:26 2010 +0100 @@ -223,6 +223,11 @@ struct pm_cx_stat { uint64_aligned_t idle_time; /* idle time from boot */ XEN_GUEST_HANDLE_64(uint64) triggers; /* Cx trigger counts */ XEN_GUEST_HANDLE_64(uint64) residencies; /* Cx residencies */ + uint64_aligned_t pc3; + uint64_aligned_t pc6; + uint64_aligned_t pc7; + uint64_aligned_t cc3; + uint64_aligned_t cc6; }; struct xen_sysctl_get_pmstat { _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |