[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] xen: Make all performance counter per-cpu, avoiding the need to update
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1175009737 -3600 # Node ID 96f167771979734080bb0f45086f1d4f699fa50d # Parent 3375391fb0c901f4d3edb73c02a1169b6bd3d7b4 xen: Make all performance counter per-cpu, avoiding the need to update them with atomic (locked) ops. Conversion here isn't complete in the sense that many places still use the old per-CPU accessors (which are now redundant). Since the patch is already rather big, I'd prefer replacing those in a subsequent patch. While doing this, I also converted x86's multicall macros to no longer require inclusion of asm-offsets.h in the respective C file (on IA64 the use of asm-offsets.h in C sources seems more wide spread, hence there I rather used IA64_ prefixes for the otherwise conflicting performance counter indices). On x86, a few counter increments get moved a little, to avoid duplicate counting of preempted hypercalls. Also, a few counters are being added. IA64 changes only compile-tested, hence somebody doing active IA64 work may want to have a close look at those changes. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx> --- xen/arch/ia64/asm-offsets.c | 9 - xen/arch/ia64/xen/hyperprivop.S | 13 - xen/arch/ia64/xen/privop_stat.c | 86 +++++----- xen/arch/ia64/xen/vhpt.c | 8 xen/arch/x86/mm.c | 11 - xen/arch/x86/x86_32/asm-offsets.c | 14 - xen/arch/x86/x86_32/entry.S | 4 xen/arch/x86/x86_64/asm-offsets.c | 26 --- xen/arch/x86/x86_64/compat/entry.S | 2 xen/arch/x86/x86_64/entry.S | 4 xen/common/multicall.c | 5 xen/common/perfc.c | 223 +++++++++++++------------- xen/include/asm-ia64/linux-xen/asm/asmmacro.h | 4 xen/include/asm-ia64/perfc_defn.h | 4 xen/include/asm-ia64/privop_stat.h | 25 +- xen/include/asm-x86/multicall.h | 104 ++++++------ xen/include/asm-x86/perfc_defn.h | 8 xen/include/asm-x86/x86_32/asm_defns.h | 12 + xen/include/asm-x86/x86_64/asm_defns.h | 19 +- xen/include/xen/perfc.h | 120 ++++++------- xen/include/xen/perfc_defn.h | 3 21 files changed, 357 insertions(+), 347 deletions(-) diff -r 3375391fb0c9 -r 96f167771979 xen/arch/ia64/asm-offsets.c --- a/xen/arch/ia64/asm-offsets.c Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/arch/ia64/asm-offsets.c Tue Mar 27 16:35:37 2007 +0100 @@ -223,10 +223,11 @@ void foo(void) #ifdef PERF_COUNTERS BLANK(); - DEFINE(RECOVER_TO_PAGE_FAULT_PERFC_OFS, offsetof (struct perfcounter, recover_to_page_fault)); - DEFINE(RECOVER_TO_BREAK_FAULT_PERFC_OFS, offsetof (struct perfcounter, recover_to_break_fault)); - DEFINE(FAST_HYPERPRIVOP_PERFC_OFS, offsetof (struct perfcounter, fast_hyperprivop)); - DEFINE(FAST_REFLECT_PERFC_OFS, offsetof (struct perfcounter, fast_reflect)); + DEFINE(IA64_PERFC_recover_to_page_fault, PERFC_recover_to_page_fault); + DEFINE(IA64_PERFC_recover_to_break_fault, PERFC_recover_to_break_fault); + DEFINE(IA64_PERFC_fast_vhpt_translate, PERFC_fast_vhpt_translate); + DEFINE(IA64_PERFC_fast_hyperprivop, PERFC_fast_hyperprivop); + DEFINE(IA64_PERFC_fast_reflect, PERFC_fast_reflect); #endif BLANK(); diff -r 3375391fb0c9 -r 96f167771979 xen/arch/ia64/xen/hyperprivop.S --- a/xen/arch/ia64/xen/hyperprivop.S Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/arch/ia64/xen/hyperprivop.S Tue Mar 27 16:35:37 2007 +0100 @@ -26,8 +26,7 @@ # define FAST_HYPERPRIVOPS # ifdef PERF_COUNTERS # define FAST_HYPERPRIVOP_CNT -# define FAST_HYPERPRIVOP_PERFC(N) \ - (perfcounters + FAST_HYPERPRIVOP_PERFC_OFS + (4 * N)) +# define FAST_HYPERPRIVOP_PERFC(N) PERFC(fast_hyperprivop + N) # define FAST_REFLECT_CNT # endif @@ -364,7 +363,7 @@ GLOBAL_ENTRY(fast_tick_reflect) mov rp=r29;; mov cr.itm=r26;; // ensure next tick #ifdef FAST_REFLECT_CNT - movl r20=perfcounters+FAST_REFLECT_PERFC_OFS+((0x3000>>8)*4);; + movl r20=PERFC(fast_reflect + (0x3000>>8));; ld4 r21=[r20];; adds r21=1,r21;; st4 [r20]=r21;; @@ -597,7 +596,7 @@ END(fast_break_reflect) // r31 == pr ENTRY(fast_reflect) #ifdef FAST_REFLECT_CNT - movl r22=perfcounters+FAST_REFLECT_PERFC_OFS; + movl r22=PERFC(fast_reflect); shr r23=r20,8-2;; add r22=r22,r23;; ld4 r21=[r22];; @@ -938,7 +937,7 @@ 1: // check the guest VHPT (p7) br.cond.spnt.few page_not_present;; #ifdef FAST_REFLECT_CNT - movl r21=perfcounter+FAST_VHPT_TRANSLATE_PERFC_OFS;; + movl r21=PERFC(fast_vhpt_translate);; ld4 r22=[r21];; adds r22=1,r22;; st4 [r21]=r22;; @@ -968,7 +967,7 @@ END(fast_tlb_miss_reflect) // we get here if fast_insert fails (e.g. due to metaphysical lookup) ENTRY(recover_and_page_fault) #ifdef PERF_COUNTERS - movl r21=perfcounters + RECOVER_TO_PAGE_FAULT_PERFC_OFS;; + movl r21=PERFC(recover_to_page_fault);; ld4 r22=[r21];; adds r22=1,r22;; st4 [r21]=r22;; @@ -1832,7 +1831,7 @@ END(hyper_ptc_ga) // recovery block for hyper_itc metaphysical memory lookup ENTRY(recover_and_dispatch_break_fault) #ifdef PERF_COUNTERS - movl r21=perfcounters + RECOVER_TO_BREAK_FAULT_PERFC_OFS;; + movl r21=PERFC(recover_to_break_fault);; ld4 r22=[r21];; adds r22=1,r22;; st4 [r21]=r22;; diff -r 3375391fb0c9 -r 96f167771979 xen/arch/ia64/xen/privop_stat.c --- a/xen/arch/ia64/xen/privop_stat.c Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/arch/ia64/xen/privop_stat.c Tue Mar 27 16:35:37 2007 +0100 @@ -10,48 +10,39 @@ struct privop_addr_count { unsigned long addr[PRIVOP_COUNT_NADDRS]; unsigned int count[PRIVOP_COUNT_NADDRS]; unsigned int overflow; - atomic_t *perfc_addr; - atomic_t *perfc_count; - atomic_t *perfc_overflow; }; -#undef PERFCOUNTER +struct privop_addr_info { + enum perfcounter perfc_addr; + enum perfcounter perfc_count; + enum perfcounter perfc_overflow; +}; + #define PERFCOUNTER(var, name) - -#undef PERFCOUNTER_CPU -#define PERFCOUNTER_CPU(var, name) - -#undef PERFCOUNTER_ARRAY #define PERFCOUNTER_ARRAY(var, name, size) -#undef PERFSTATUS #define PERFSTATUS(var, name) - -#undef PERFSTATUS_CPU -#define PERFSTATUS_CPU(var, name) - -#undef PERFSTATUS_ARRAY #define PERFSTATUS_ARRAY(var, name, size) -#undef PERFPRIVOPADDR #define PERFPRIVOPADDR(name) \ { \ - { 0 }, { 0 }, 0, \ - perfcounters.privop_addr_##name##_addr, \ - perfcounters.privop_addr_##name##_count, \ - perfcounters.privop_addr_##name##_overflow \ + PERFC_privop_addr_##name##_addr, \ + PERFC_privop_addr_##name##_count, \ + PERFC_privop_addr_##name##_overflow \ }, -static struct privop_addr_count privop_addr_counter[] = { +static const struct privop_addr_info privop_addr_info[] = { #include <asm/perfc_defn.h> }; #define PRIVOP_COUNT_NINSTS \ - (sizeof(privop_addr_counter) / sizeof(privop_addr_counter[0])) + (sizeof(privop_addr_info) / sizeof(privop_addr_info[0])) + +static DEFINE_PER_CPU(struct privop_addr_count[PRIVOP_COUNT_NINSTS], privop_addr_counter); void privop_count_addr(unsigned long iip, enum privop_inst inst) { - struct privop_addr_count *v = &privop_addr_counter[inst]; + struct privop_addr_count *v = this_cpu(privop_addr_counter) + inst; int i; if (inst >= PRIVOP_COUNT_NINSTS) @@ -72,31 +63,44 @@ void privop_count_addr(unsigned long iip void gather_privop_addrs(void) { - int i, j; - atomic_t *v; - for (i = 0; i < PRIVOP_COUNT_NINSTS; i++) { - /* Note: addresses are truncated! */ - v = privop_addr_counter[i].perfc_addr; - for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) - atomic_set(&v[j], privop_addr_counter[i].addr[j]); + unsigned int cpu; - v = privop_addr_counter[i].perfc_count; - for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) - atomic_set(&v[j], privop_addr_counter[i].count[j]); + for_each_cpu ( cpu ) { + perfc_t *perfcounters = per_cpu(perfcounters, cpu); + struct privop_addr_count *s = per_cpu(privop_addr_counter, cpu); + int i, j; + + for (i = 0; i < PRIVOP_COUNT_NINSTS; i++, s++) { + perfc_t *d; + + /* Note: addresses are truncated! */ + d = perfcounters + privop_addr_info[i].perfc_addr; + for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) + d[j] = s->addr[j]; + + d = perfcounters + privop_addr_info[i].perfc_count; + for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) + d[j] = s->count[j]; - atomic_set(privop_addr_counter[i].perfc_overflow, - privop_addr_counter[i].overflow); + perfcounters[privop_addr_info[i].perfc_overflow] = + s->overflow; + } } } void reset_privop_addrs(void) { - int i, j; - for (i = 0; i < PRIVOP_COUNT_NINSTS; i++) { - struct privop_addr_count *v = &privop_addr_counter[i]; - for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) - v->addr[j] = v->count[j] = 0; - v->overflow = 0; + unsigned int cpu; + + for_each_cpu ( cpu ) { + struct privop_addr_count *v = per_cpu(privop_addr_counter, cpu); + int i, j; + + for (i = 0; i < PRIVOP_COUNT_NINSTS; i++, v++) { + for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) + v->addr[j] = v->count[j] = 0; + v->overflow = 0; + } } } #endif diff -r 3375391fb0c9 -r 96f167771979 xen/arch/ia64/xen/vhpt.c --- a/xen/arch/ia64/xen/vhpt.c Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/arch/ia64/xen/vhpt.c Tue Mar 27 16:35:37 2007 +0100 @@ -512,7 +512,7 @@ void gather_vhpt_stats(void) for (i = 0; i < VHPT_NUM_ENTRIES; i++, v++) if (!(v->ti_tag & INVALID_TI_TAG)) vhpt_valid++; - perfc_seta(vhpt_valid_entries, cpu, vhpt_valid); - } -} -#endif + per_cpu(perfcounters, cpu)[PERFC_vhpt_valid_entries] = vhpt_valid; + } +} +#endif diff -r 3375391fb0c9 -r 96f167771979 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/arch/x86/mm.c Tue Mar 27 16:35:37 2007 +0100 @@ -1969,6 +1969,8 @@ int do_mmuext_op( if ( unlikely(!guest_handle_is_null(pdone)) ) (void)copy_from_guest(&done, pdone, 1); } + else + perfc_incr(calls_to_mmuext_op); if ( unlikely(!guest_handle_okay(uops, count)) ) { @@ -2223,6 +2225,8 @@ int do_mmuext_op( UNLOCK_BIGLOCK(d); + perfc_add(num_mmuext_ops, i); + out: /* Add incremental work we have done to the @done output parameter. */ if ( unlikely(!guest_handle_is_null(pdone)) ) @@ -2257,6 +2261,8 @@ int do_mmu_update( if ( unlikely(!guest_handle_is_null(pdone)) ) (void)copy_from_guest(&done, pdone, 1); } + else + perfc_incr(calls_to_mmu_update); if ( unlikely(!guest_handle_okay(ureqs, count)) ) { @@ -2272,9 +2278,6 @@ int do_mmu_update( domain_mmap_cache_init(&mapcache); domain_mmap_cache_init(&sh_mapcache); - - perfc_incrc(calls_to_mmu_update); - perfc_addc(num_page_updates, count); LOCK_BIGLOCK(d); @@ -2438,6 +2441,8 @@ int do_mmu_update( domain_mmap_cache_destroy(&mapcache); domain_mmap_cache_destroy(&sh_mapcache); + perfc_add(num_page_updates, i); + out: /* Add incremental work we have done to the @done output parameter. */ if ( unlikely(!guest_handle_is_null(pdone)) ) diff -r 3375391fb0c9 -r 96f167771979 xen/arch/x86/x86_32/asm-offsets.c --- a/xen/arch/x86/x86_32/asm-offsets.c Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/arch/x86/x86_32/asm-offsets.c Tue Mar 27 16:35:37 2007 +0100 @@ -107,20 +107,10 @@ void __dummy__(void) BLANK(); #if PERF_COUNTERS - OFFSET(PERFC_hypercalls, struct perfcounter, hypercalls); - OFFSET(PERFC_exceptions, struct perfcounter, exceptions); + DEFINE(PERFC_hypercalls, PERFC_hypercalls); + DEFINE(PERFC_exceptions, PERFC_exceptions); BLANK(); #endif - - OFFSET(MULTICALL_op, struct multicall_entry, op); - OFFSET(MULTICALL_arg0, struct multicall_entry, args[0]); - OFFSET(MULTICALL_arg1, struct multicall_entry, args[1]); - OFFSET(MULTICALL_arg2, struct multicall_entry, args[2]); - OFFSET(MULTICALL_arg3, struct multicall_entry, args[3]); - OFFSET(MULTICALL_arg4, struct multicall_entry, args[4]); - OFFSET(MULTICALL_arg5, struct multicall_entry, args[5]); - OFFSET(MULTICALL_result, struct multicall_entry, result); - BLANK(); DEFINE(FIXMAP_apic_base, fix_to_virt(FIX_APIC_BASE)); BLANK(); diff -r 3375391fb0c9 -r 96f167771979 xen/arch/x86/x86_32/entry.S --- a/xen/arch/x86/x86_32/entry.S Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/arch/x86/x86_32/entry.S Tue Mar 27 16:35:37 2007 +0100 @@ -173,7 +173,7 @@ ENTRY(hypercall) GET_CURRENT(%ebx) cmpl $NR_hypercalls,%eax jae bad_hypercall - PERFC_INCR(PERFC_hypercalls, %eax) + PERFC_INCR(PERFC_hypercalls, %eax, %ebx) #ifndef NDEBUG /* Create shadow parameters and corrupt those not used by this call. */ pushl %eax @@ -429,7 +429,7 @@ 1: xorl %eax,%eax movl %esp,%edx pushl %edx # push the cpu_user_regs pointer GET_CURRENT(%ebx) - PERFC_INCR(PERFC_exceptions, %eax) + PERFC_INCR(PERFC_exceptions, %eax, %ebx) call *exception_table(,%eax,4) addl $4,%esp movl UREGS_eflags(%esp),%eax diff -r 3375391fb0c9 -r 96f167771979 xen/arch/x86/x86_64/asm-offsets.c --- a/xen/arch/x86/x86_64/asm-offsets.c Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/arch/x86/x86_64/asm-offsets.c Tue Mar 27 16:35:37 2007 +0100 @@ -121,30 +121,8 @@ void __dummy__(void) BLANK(); #if PERF_COUNTERS - OFFSET(PERFC_hypercalls, struct perfcounter, hypercalls); - OFFSET(PERFC_exceptions, struct perfcounter, exceptions); - BLANK(); -#endif - - OFFSET(MULTICALL_op, struct multicall_entry, op); - OFFSET(MULTICALL_arg0, struct multicall_entry, args[0]); - OFFSET(MULTICALL_arg1, struct multicall_entry, args[1]); - OFFSET(MULTICALL_arg2, struct multicall_entry, args[2]); - OFFSET(MULTICALL_arg3, struct multicall_entry, args[3]); - OFFSET(MULTICALL_arg4, struct multicall_entry, args[4]); - OFFSET(MULTICALL_arg5, struct multicall_entry, args[5]); - OFFSET(MULTICALL_result, struct multicall_entry, result); - BLANK(); - -#ifdef CONFIG_COMPAT - OFFSET(COMPAT_MULTICALL_op, struct compat_multicall_entry, op); - OFFSET(COMPAT_MULTICALL_arg0, struct compat_multicall_entry, args[0]); - OFFSET(COMPAT_MULTICALL_arg1, struct compat_multicall_entry, args[1]); - OFFSET(COMPAT_MULTICALL_arg2, struct compat_multicall_entry, args[2]); - OFFSET(COMPAT_MULTICALL_arg3, struct compat_multicall_entry, args[3]); - OFFSET(COMPAT_MULTICALL_arg4, struct compat_multicall_entry, args[4]); - OFFSET(COMPAT_MULTICALL_arg5, struct compat_multicall_entry, args[5]); - OFFSET(COMPAT_MULTICALL_result, struct compat_multicall_entry, result); + DEFINE(PERFC_hypercalls, PERFC_hypercalls); + DEFINE(PERFC_exceptions, PERFC_exceptions); BLANK(); #endif diff -r 3375391fb0c9 -r 96f167771979 xen/arch/x86/x86_64/compat/entry.S --- a/xen/arch/x86/x86_64/compat/entry.S Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/arch/x86/x86_64/compat/entry.S Tue Mar 27 16:35:37 2007 +0100 @@ -57,7 +57,7 @@ ENTRY(compat_hypercall) movl UREGS_rbx(%rsp),%edi /* Arg 1 */ #endif leaq compat_hypercall_table(%rip),%r10 - PERFC_INCR(PERFC_hypercalls, %rax) + PERFC_INCR(PERFC_hypercalls, %rax, %rbx) callq *(%r10,%rax,8) #ifndef NDEBUG /* Deliberately corrupt parameter regs used by this hypercall. */ diff -r 3375391fb0c9 -r 96f167771979 xen/arch/x86/x86_64/entry.S --- a/xen/arch/x86/x86_64/entry.S Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/arch/x86/x86_64/entry.S Tue Mar 27 16:35:37 2007 +0100 @@ -147,7 +147,7 @@ ENTRY(syscall_enter) pushq UREGS_rip+8(%rsp) #endif leaq hypercall_table(%rip),%r10 - PERFC_INCR(PERFC_hypercalls, %rax) + PERFC_INCR(PERFC_hypercalls, %rax, %rbx) callq *(%r10,%rax,8) #ifndef NDEBUG /* Deliberately corrupt parameter regs used by this hypercall. */ @@ -396,7 +396,7 @@ 1: movq %rsp,%rdi movl UREGS_entry_vector(%rsp),%eax leaq exception_table(%rip),%rdx GET_CURRENT(%rbx) - PERFC_INCR(PERFC_exceptions, %rax) + PERFC_INCR(PERFC_exceptions, %rax, %rbx) callq *(%rdx,%rax,8) testb $3,UREGS_cs(%rsp) jz restore_all_xen diff -r 3375391fb0c9 -r 96f167771979 xen/common/multicall.c --- a/xen/common/multicall.c Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/common/multicall.c Tue Mar 27 16:35:37 2007 +0100 @@ -10,6 +10,7 @@ #include <xen/event.h> #include <xen/multicall.h> #include <xen/guest_access.h> +#include <xen/perfc.h> #include <asm/current.h> #include <asm/hardirq.h> @@ -69,14 +70,18 @@ do_multicall( guest_handle_add_offset(call_list, 1); } + perfc_incr(calls_to_multicall); + perfc_add(calls_from_multicall, nr_calls); mcs->flags = 0; return 0; fault: + perfc_incr(calls_to_multicall); mcs->flags = 0; return -EFAULT; preempted: + perfc_add(calls_from_multicall, i); mcs->flags = 0; return hypercall_create_continuation( __HYPERVISOR_multicall, "hi", call_list, nr_calls-i); diff -r 3375391fb0c9 -r 96f167771979 xen/common/perfc.c --- a/xen/common/perfc.c Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/common/perfc.c Tue Mar 27 16:35:37 2007 +0100 @@ -10,81 +10,98 @@ #include <public/sysctl.h> #include <asm/perfc.h> -#undef PERFCOUNTER -#undef PERFCOUNTER_CPU -#undef PERFCOUNTER_ARRAY -#undef PERFSTATUS -#undef PERFSTATUS_CPU -#undef PERFSTATUS_ARRAY #define PERFCOUNTER( var, name ) { name, TYPE_SINGLE, 0 }, -#define PERFCOUNTER_CPU( var, name ) { name, TYPE_CPU, 0 }, #define PERFCOUNTER_ARRAY( var, name, size ) { name, TYPE_ARRAY, size }, #define PERFSTATUS( var, name ) { name, TYPE_S_SINGLE, 0 }, -#define PERFSTATUS_CPU( var, name ) { name, TYPE_S_CPU, 0 }, #define PERFSTATUS_ARRAY( var, name, size ) { name, TYPE_S_ARRAY, size }, -static struct { - char *name; - enum { TYPE_SINGLE, TYPE_CPU, TYPE_ARRAY, - TYPE_S_SINGLE, TYPE_S_CPU, TYPE_S_ARRAY +static const struct { + const char *name; + enum { TYPE_SINGLE, TYPE_ARRAY, + TYPE_S_SINGLE, TYPE_S_ARRAY } type; - int nr_elements; + unsigned int nr_elements; } perfc_info[] = { #include <xen/perfc_defn.h> }; #define NR_PERFCTRS (sizeof(perfc_info) / sizeof(perfc_info[0])) -struct perfcounter perfcounters; +DEFINE_PER_CPU(perfc_t[NUM_PERFCOUNTERS], perfcounters); void perfc_printall(unsigned char key) { - unsigned int i, j, sum; + unsigned int i, j; s_time_t now = NOW(); - atomic_t *counters = (atomic_t *)&perfcounters; printk("Xen performance counters SHOW (now = 0x%08X:%08X)\n", (u32)(now>>32), (u32)now); - for ( i = 0; i < NR_PERFCTRS; i++ ) - { + for ( i = j = 0; i < NR_PERFCTRS; i++ ) + { + unsigned int k, cpu; + unsigned long long sum = 0; + printk("%-32s ", perfc_info[i].name); switch ( perfc_info[i].type ) { case TYPE_SINGLE: case TYPE_S_SINGLE: - printk("TOTAL[%10d]", atomic_read(&counters[0])); - counters += 1; - break; - case TYPE_CPU: - case TYPE_S_CPU: - sum = 0; - for_each_online_cpu ( j ) - sum += atomic_read(&counters[j]); - printk("TOTAL[%10u]", sum); + for_each_online_cpu ( cpu ) + sum += per_cpu(perfcounters, cpu)[j]; + printk("TOTAL[%12Lu]", sum); + if ( sum ) + { + k = 0; + for_each_online_cpu ( cpu ) + { + if ( k > 0 && (k % 4) == 0 ) + printk("\n%46s", ""); + printk(" CPU%02u[%10"PRIperfc"u]", cpu, per_cpu(perfcounters, cpu)[j]); + ++k; + } + } + ++j; + break; + case TYPE_ARRAY: + case TYPE_S_ARRAY: + for_each_online_cpu ( cpu ) + { + perfc_t *counters = per_cpu(perfcounters, cpu) + j; + + for ( k = 0; k < perfc_info[i].nr_elements; k++ ) + sum += counters[k]; + } + printk("TOTAL[%12Lu]", sum); if (sum) { - for_each_online_cpu ( j ) - printk(" CPU%02d[%10d]", j, atomic_read(&counters[j])); - } - counters += NR_CPUS; - break; - case TYPE_ARRAY: - case TYPE_S_ARRAY: - for ( j = sum = 0; j < perfc_info[i].nr_elements; j++ ) - sum += atomic_read(&counters[j]); - printk("TOTAL[%10u]", sum); #ifdef PERF_ARRAYS - if (sum) - { - for ( j = 0; j < perfc_info[i].nr_elements; j++ ) - { - if ( (j % 4) == 0 ) - printk("\n "); - printk(" ARR%02d[%10d]", j, atomic_read(&counters[j])); - } - } + for ( k = 0; k < perfc_info[i].nr_elements; k++ ) + { + sum = 0; + for_each_online_cpu ( cpu ) + sum += per_cpu(perfcounters, cpu)[j + k]; + if ( (k % 4) == 0 ) + printk("\n%16s", ""); + printk(" ARR%02u[%10Lu]", k, sum); + } +#else + k = 0; + for_each_online_cpu ( cpu ) + { + perfc_t *counters = per_cpu(perfcounters, cpu) + j; + unsigned int n; + + sum = 0; + for ( n = 0; n < perfc_info[i].nr_elements; n++ ) + sum += counters[n]; + if ( k > 0 && (k % 4) == 0 ) + printk("\n%46s", ""); + printk(" CPU%02u[%10Lu]", cpu, sum); + ++k; + } #endif - counters += j; + } + j += perfc_info[i].nr_elements; break; } printk("\n"); @@ -97,7 +114,6 @@ void perfc_reset(unsigned char key) { unsigned int i, j; s_time_t now = NOW(); - atomic_t *counters = (atomic_t *)&perfcounters; if ( key != '\0' ) printk("Xen performance counters RESET (now = 0x%08X:%08X)\n", @@ -105,43 +121,39 @@ void perfc_reset(unsigned char key) /* leave STATUS counters alone -- don't reset */ - for ( i = 0; i < NR_PERFCTRS; i++ ) - { - switch ( perfc_info[i].type ) - { - case TYPE_SINGLE: - atomic_set(&counters[0],0); - case TYPE_S_SINGLE: - counters += 1; - break; - case TYPE_CPU: - for ( j = 0; j < NR_CPUS; j++ ) - atomic_set(&counters[j],0); - case TYPE_S_CPU: - counters += NR_CPUS; - break; - case TYPE_ARRAY: - for ( j = 0; j < perfc_info[i].nr_elements; j++ ) - atomic_set(&counters[j],0); - case TYPE_S_ARRAY: - counters += perfc_info[i].nr_elements; - break; - } - } - - arch_perfc_reset (); + for ( i = j = 0; i < NR_PERFCTRS; i++ ) + { + unsigned int cpu; + + switch ( perfc_info[i].type ) + { + case TYPE_SINGLE: + for_each_cpu ( cpu ) + per_cpu(perfcounters, cpu)[j] = 0; + case TYPE_S_SINGLE: + ++j; + break; + case TYPE_ARRAY: + for_each_cpu ( cpu ) + memset(per_cpu(perfcounters, cpu) + j, 0, + perfc_info[i].nr_elements * sizeof(perfc_t)); + case TYPE_S_ARRAY: + j += perfc_info[i].nr_elements; + break; + } + } + + arch_perfc_reset(); } static xen_sysctl_perfc_desc_t perfc_d[NR_PERFCTRS]; static xen_sysctl_perfc_val_t *perfc_vals; -static int perfc_nbr_vals; +static unsigned int perfc_nbr_vals; static int perfc_init = 0; static int perfc_copy_info(XEN_GUEST_HANDLE_64(xen_sysctl_perfc_desc_t) desc, XEN_GUEST_HANDLE_64(xen_sysctl_perfc_val_t) val) { - unsigned int i, j; - unsigned int v = 0; - atomic_t *counters = (atomic_t *)&perfcounters; + unsigned int i, j, v; /* We only copy the name and array-size information once. */ if ( !perfc_init ) @@ -154,11 +166,7 @@ static int perfc_copy_info(XEN_GUEST_HAN { case TYPE_SINGLE: case TYPE_S_SINGLE: - perfc_d[i].nr_vals = 1; - break; - case TYPE_CPU: - case TYPE_S_CPU: - perfc_d[i].nr_vals = num_online_cpus(); + perfc_d[i].nr_vals = num_possible_cpus(); break; case TYPE_ARRAY: case TYPE_S_ARRAY: @@ -181,26 +189,31 @@ static int perfc_copy_info(XEN_GUEST_HAN arch_perfc_gather(); /* We gather the counts together every time. */ - for ( i = 0; i < NR_PERFCTRS; i++ ) - { - switch ( perfc_info[i].type ) - { - case TYPE_SINGLE: - case TYPE_S_SINGLE: - perfc_vals[v++] = atomic_read(&counters[0]); - counters += 1; - break; - case TYPE_CPU: - case TYPE_S_CPU: - for ( j = 0; j < perfc_d[i].nr_vals; j++ ) - perfc_vals[v++] = atomic_read(&counters[j]); - counters += NR_CPUS; - break; - case TYPE_ARRAY: - case TYPE_S_ARRAY: - for ( j = 0; j < perfc_d[i].nr_vals; j++ ) - perfc_vals[v++] = atomic_read(&counters[j]); - counters += perfc_info[i].nr_elements; + for ( i = j = v = 0; i < NR_PERFCTRS; i++ ) + { + unsigned int cpu; + + switch ( perfc_info[i].type ) + { + case TYPE_SINGLE: + case TYPE_S_SINGLE: + for_each_cpu ( cpu ) + perfc_vals[v++] = per_cpu(perfcounters, cpu)[j]; + ++j; + break; + case TYPE_ARRAY: + case TYPE_S_ARRAY: + memset(perfc_vals + v, 0, perfc_d[i].nr_vals * sizeof(*perfc_vals)); + for_each_cpu ( cpu ) + { + perfc_t *counters = per_cpu(perfcounters, cpu) + j; + unsigned int k; + + for ( k = 0; k < perfc_d[i].nr_vals; k++ ) + perfc_vals[v + k] += counters[k]; + } + v += perfc_d[i].nr_vals; + j += perfc_info[i].nr_elements; break; } } @@ -224,14 +237,12 @@ int perfc_control(xen_sysctl_perfc_op_t switch ( pc->cmd ) { case XEN_SYSCTL_PERFCOP_reset: - perfc_copy_info(pc->desc, pc->val); + rc = perfc_copy_info(pc->desc, pc->val); perfc_reset(0); - rc = 0; break; case XEN_SYSCTL_PERFCOP_query: - perfc_copy_info(pc->desc, pc->val); - rc = 0; + rc = perfc_copy_info(pc->desc, pc->val); break; default: diff -r 3375391fb0c9 -r 96f167771979 xen/include/asm-ia64/linux-xen/asm/asmmacro.h --- a/xen/include/asm-ia64/linux-xen/asm/asmmacro.h Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/include/asm-ia64/linux-xen/asm/asmmacro.h Tue Mar 27 16:35:37 2007 +0100 @@ -116,4 +116,8 @@ 2:{ .mib; \ # define dv_serialize_instruction #endif +#ifdef PERF_COUNTERS +#define PERFC(n) (THIS_CPU(perfcounters) + (IA64_PERFC_ ## n) * 4) +#endif + #endif /* _ASM_IA64_ASMMACRO_H */ diff -r 3375391fb0c9 -r 96f167771979 xen/include/asm-ia64/perfc_defn.h --- a/xen/include/asm-ia64/perfc_defn.h Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/include/asm-ia64/perfc_defn.h Tue Mar 27 16:35:37 2007 +0100 @@ -84,7 +84,7 @@ PERFCOUNTER_ARRAY(fast_reflect, "f PERFCOUNTER_ARRAY(fast_reflect, "fast reflection", 0x80) PERFSTATUS(vhpt_nbr_entries, "nbr of entries per VHPT") -PERFSTATUS_CPU(vhpt_valid_entries, "nbr of valid entries in VHPT") +PERFSTATUS(vhpt_valid_entries, "nbr of valid entries in VHPT") PERFCOUNTER_ARRAY(vmx_mmio_access, "vmx_mmio_access", 8) PERFCOUNTER_CPU(vmx_pal_emul, "vmx_pal_emul") @@ -106,6 +106,8 @@ PERFSTATUS(privop_addr_##name##_overflow PERFPRIVOPADDR(get_ifa) PERFPRIVOPADDR(thash) + +#undef PERFPRIVOPADDR #endif // vhpt.c diff -r 3375391fb0c9 -r 96f167771979 xen/include/asm-ia64/privop_stat.h --- a/xen/include/asm-ia64/privop_stat.h Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/include/asm-ia64/privop_stat.h Tue Mar 27 16:35:37 2007 +0100 @@ -1,5 +1,5 @@ -#ifndef _XEN_UA64_PRIVOP_STAT_H -#define _XEN_UA64_PRIVOP_STAT_H +#ifndef _XEN_IA64_PRIVOP_STAT_H +#define _XEN_IA64_PRIVOP_STAT_H #include <asm/config.h> #include <xen/types.h> #include <public/xen.h> @@ -9,30 +9,23 @@ extern void gather_privop_addrs(void); extern void gather_privop_addrs(void); extern void reset_privop_addrs(void); -#undef PERFCOUNTER #define PERFCOUNTER(var, name) - -#undef PERFCOUNTER_CPU -#define PERFCOUNTER_CPU(var, name) - -#undef PERFCOUNTER_ARRAY #define PERFCOUNTER_ARRAY(var, name, size) -#undef PERFSTATUS #define PERFSTATUS(var, name) - -#undef PERFSTATUS_CPU -#define PERFSTATUS_CPU(var, name) - -#undef PERFSTATUS_ARRAY #define PERFSTATUS_ARRAY(var, name, size) -#undef PERFPRIVOPADDR #define PERFPRIVOPADDR(name) privop_inst_##name, enum privop_inst { #include <asm/perfc_defn.h> }; + +#undef PERFCOUNTER +#undef PERFCOUNTER_ARRAY + +#undef PERFSTATUS +#undef PERFSTATUS_ARRAY #undef PERFPRIVOPADDR @@ -45,4 +38,4 @@ extern void privop_count_addr(unsigned l #define reset_privop_addrs() do {} while (0) #endif -#endif /* _XEN_UA64_PRIVOP_STAT_H */ +#endif /* _XEN_IA64_PRIVOP_STAT_H */ diff -r 3375391fb0c9 -r 96f167771979 xen/include/asm-x86/multicall.h --- a/xen/include/asm-x86/multicall.h Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/include/asm-x86/multicall.h Tue Mar 27 16:35:37 2007 +0100 @@ -6,84 +6,94 @@ #define __ASM_X86_MULTICALL_H__ #include <xen/errno.h> -#include <asm/asm_defns.h> #ifdef __x86_64__ #define do_multicall_call(_call) \ do { \ __asm__ __volatile__ ( \ - " movq "STR(MULTICALL_op)"(%0),%%rax; " \ + " movq %c1(%0),%%rax; " \ + " leaq hypercall_table(%%rip),%%rdi; " \ " cmpq $("STR(NR_hypercalls)"),%%rax; " \ " jae 2f; " \ - " leaq hypercall_table(%%rip),%%rdi; " \ - " leaq (%%rdi,%%rax,8),%%rax; " \ - " movq "STR(MULTICALL_arg0)"(%0),%%rdi; " \ - " movq "STR(MULTICALL_arg1)"(%0),%%rsi; " \ - " movq "STR(MULTICALL_arg2)"(%0),%%rdx; " \ - " movq "STR(MULTICALL_arg3)"(%0),%%rcx; " \ - " movq "STR(MULTICALL_arg4)"(%0),%%r8; " \ - " callq *(%%rax); " \ - "1: movq %%rax,"STR(MULTICALL_result)"(%0)\n" \ + " movq (%%rdi,%%rax,8),%%rax; " \ + " movq %c2+0*%c3(%0),%%rdi; " \ + " movq %c2+1*%c3(%0),%%rsi; " \ + " movq %c2+2*%c3(%0),%%rdx; " \ + " movq %c2+3*%c3(%0),%%rcx; " \ + " movq %c2+4*%c3(%0),%%r8; " \ + " callq *%%rax; " \ + "1: movq %%rax,%c4(%0)\n" \ ".section .fixup,\"ax\"\n" \ "2: movq $-"STR(ENOSYS)",%%rax\n" \ " jmp 1b\n" \ ".previous\n" \ - : : "b" (_call) \ + : \ + : "b" (_call), \ + "i" (offsetof(__typeof__(*_call), op)), \ + "i" (offsetof(__typeof__(*_call), args)), \ + "i" (sizeof(*(_call)->args)), \ + "i" (offsetof(__typeof__(*_call), result)) \ /* all the caller-saves registers */ \ : "rax", "rcx", "rdx", "rsi", "rdi", \ "r8", "r9", "r10", "r11" ); \ } while ( 0 ) -#define compat_multicall_call(_call) \ - do { \ - __asm__ __volatile__ ( \ - " movl "STR(COMPAT_MULTICALL_op)"(%0),%%eax; " \ - " leaq compat_hypercall_table(%%rip),%%rdi; " \ - " cmpl $("STR(NR_hypercalls)"),%%eax; " \ - " jae 2f; " \ - " movq (%%rdi,%%rax,8),%%rax; " \ - " movl "STR(COMPAT_MULTICALL_arg0)"(%0),%%edi; " \ - " movl "STR(COMPAT_MULTICALL_arg1)"(%0),%%esi; " \ - " movl "STR(COMPAT_MULTICALL_arg2)"(%0),%%edx; " \ - " movl "STR(COMPAT_MULTICALL_arg3)"(%0),%%ecx; " \ - " movl "STR(COMPAT_MULTICALL_arg4)"(%0),%%r8d; " \ - " callq *%%rax; " \ - "1: movl %%eax,"STR(COMPAT_MULTICALL_result)"(%0)\n"\ - ".section .fixup,\"ax\"\n" \ - "2: movl $-"STR(ENOSYS)",%%eax\n" \ - " jmp 1b\n" \ - ".previous\n" \ - : : "b" (_call) \ - /* all the caller-saves registers */ \ - : "rax", "rcx", "rdx", "rsi", "rdi", \ - "r8", "r9", "r10", "r11" ); \ - } while ( 0 ) +#define compat_multicall_call(_call) \ + __asm__ __volatile__ ( \ + " movl %c1(%0),%%eax; " \ + " leaq compat_hypercall_table(%%rip),%%rdi; "\ + " cmpl $("STR(NR_hypercalls)"),%%eax; " \ + " jae 2f; " \ + " movq (%%rdi,%%rax,8),%%rax; " \ + " movl %c2+0*%c3(%0),%%edi; " \ + " movl %c2+1*%c3(%0),%%esi; " \ + " movl %c2+2*%c3(%0),%%edx; " \ + " movl %c2+3*%c3(%0),%%ecx; " \ + " movl %c2+4*%c3(%0),%%r8d; " \ + " callq *%%rax; " \ + "1: movl %%eax,%c4(%0)\n" \ + ".section .fixup,\"ax\"\n" \ + "2: movl $-"STR(ENOSYS)",%%eax\n" \ + " jmp 1b\n" \ + ".previous\n" \ + : \ + : "b" (_call), \ + "i" (offsetof(__typeof__(*_call), op)), \ + "i" (offsetof(__typeof__(*_call), args)), \ + "i" (sizeof(*(_call)->args)), \ + "i" (offsetof(__typeof__(*_call), result)) \ + /* all the caller-saves registers */ \ + : "rax", "rcx", "rdx", "rsi", "rdi", \ + "r8", "r9", "r10", "r11" ) \ #else #define do_multicall_call(_call) \ - do { \ __asm__ __volatile__ ( \ - " pushl "STR(MULTICALL_arg4)"(%0); " \ - " pushl "STR(MULTICALL_arg3)"(%0); " \ - " pushl "STR(MULTICALL_arg2)"(%0); " \ - " pushl "STR(MULTICALL_arg1)"(%0); " \ - " pushl "STR(MULTICALL_arg0)"(%0); " \ - " movl "STR(MULTICALL_op)"(%0),%%eax; " \ + " movl %c1(%0),%%eax; " \ + " pushl %c2+4*%c3(%0); " \ + " pushl %c2+3*%c3(%0); " \ + " pushl %c2+2*%c3(%0); " \ + " pushl %c2+1*%c3(%0); " \ + " pushl %c2+0*%c3(%0); " \ " cmpl $("STR(NR_hypercalls)"),%%eax; " \ " jae 2f; " \ " call *hypercall_table(,%%eax,4); " \ - "1: movl %%eax,"STR(MULTICALL_result)"(%0); " \ + "1: movl %%eax,%c4(%0); " \ " addl $20,%%esp\n" \ ".section .fixup,\"ax\"\n" \ "2: movl $-"STR(ENOSYS)",%%eax\n" \ " jmp 1b\n" \ ".previous\n" \ - : : "b" (_call) \ + : \ + : "bSD" (_call), \ + "i" (offsetof(__typeof__(*_call), op)), \ + "i" (offsetof(__typeof__(*_call), args)), \ + "i" (sizeof(*(_call)->args)), \ + "i" (offsetof(__typeof__(*_call), result)) \ /* all the caller-saves registers */ \ - : "eax", "ecx", "edx" ); \ - } while ( 0 ) + : "eax", "ecx", "edx" ) \ #endif diff -r 3375391fb0c9 -r 96f167771979 xen/include/asm-x86/perfc_defn.h --- a/xen/include/asm-x86/perfc_defn.h Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/include/asm-x86/perfc_defn.h Tue Mar 27 16:35:37 2007 +0100 @@ -18,9 +18,11 @@ PERFCOUNTER_CPU(apic_timer, PERFCOUNTER_CPU(domain_page_tlb_flush, "domain page tlb flushes") -PERFCOUNTER_CPU(calls_to_mmu_update, "calls_to_mmu_update") -PERFCOUNTER_CPU(num_page_updates, "num_page_updates") -PERFCOUNTER_CPU(calls_to_update_va, "calls_to_update_va_map") +PERFCOUNTER(calls_to_mmuext_op, "calls to mmuext_op") +PERFCOUNTER(num_mmuext_ops, "mmuext ops") +PERFCOUNTER(calls_to_mmu_update, "calls to mmu_update") +PERFCOUNTER(num_page_updates, "page updates") +PERFCOUNTER(calls_to_update_va, "calls to update_va_map") PERFCOUNTER_CPU(page_faults, "page faults") PERFCOUNTER_CPU(copy_user_faults, "copy_user faults") diff -r 3375391fb0c9 -r 96f167771979 xen/include/asm-x86/x86_32/asm_defns.h --- a/xen/include/asm-x86/x86_32/asm_defns.h Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/include/asm-x86/x86_32/asm_defns.h Tue Mar 27 16:35:37 2007 +0100 @@ -1,5 +1,7 @@ #ifndef __X86_32_ASM_DEFNS_H__ #define __X86_32_ASM_DEFNS_H__ + +#include <asm/percpu.h> #ifndef NDEBUG /* Indicate special exception stack frame by inverting the frame pointer. */ @@ -47,10 +49,14 @@ 1: #ifdef PERF_COUNTERS -#define PERFC_INCR(_name,_idx) \ - lock incl perfcounters+_name(,_idx,4) +#define PERFC_INCR(_name,_idx,_cur) \ + pushl _cur; \ + movl VCPU_processor(_cur),_cur; \ + shll $PERCPU_SHIFT,_cur; \ + incl per_cpu__perfcounters+_name*4(_cur,_idx,4);\ + popl _cur #else -#define PERFC_INCR(_name,_idx) +#define PERFC_INCR(_name,_idx,_cur) #endif #ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL diff -r 3375391fb0c9 -r 96f167771979 xen/include/asm-x86/x86_64/asm_defns.h --- a/xen/include/asm-x86/x86_64/asm_defns.h Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/include/asm-x86/x86_64/asm_defns.h Tue Mar 27 16:35:37 2007 +0100 @@ -1,5 +1,7 @@ #ifndef __X86_64_ASM_DEFNS_H__ #define __X86_64_ASM_DEFNS_H__ + +#include <asm/percpu.h> #ifndef NDEBUG /* Indicate special exception stack frame by inverting the frame pointer. */ @@ -47,13 +49,18 @@ popq %rdi; #ifdef PERF_COUNTERS -#define PERFC_INCR(_name,_idx) \ - pushq %rdx; \ - leaq perfcounters+_name(%rip),%rdx; \ - lock incl (%rdx,_idx,4); \ - popq %rdx; +#define PERFC_INCR(_name,_idx,_cur) \ + pushq _cur; \ + movslq VCPU_processor(_cur),_cur; \ + pushq %rdx; \ + leaq per_cpu__perfcounters(%rip),%rdx; \ + shlq $PERCPU_SHIFT,_cur; \ + addq %rdx,_cur; \ + popq %rdx; \ + incl _name*4(_cur,_idx,4); \ + popq _cur #else -#define PERFC_INCR(_name,_idx) +#define PERFC_INCR(_name,_idx,_cur) #endif /* Work around AMD erratum #88 */ diff -r 3375391fb0c9 -r 96f167771979 xen/include/xen/perfc.h --- a/xen/include/xen/perfc.h Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/include/xen/perfc.h Tue Mar 27 16:35:37 2007 +0100 @@ -6,102 +6,94 @@ #include <xen/lib.h> #include <xen/smp.h> -#include <asm/atomic.h> +#include <xen/percpu.h> /* * NOTE: new counters must be defined in perfc_defn.h * * PERFCOUNTER (counter, string) define a new performance counter - * PERFCOUNTER_CPU (counter, string, size) define a counter per CPU - * PERFCOUNTER_ARRY (counter, string, size) define an array of counters + * PERFCOUNTER_ARRAY (counter, string, size) define an array of counters * * unlike "COUNTERS", "STATUS" variables DO NOT RESET * PERFSTATUS (counter, string) define a new performance stauts - * PERFSTATUS_CPU (counter, string, size) define a status var per CPU - * PERFSTATUS_ARRY (counter, string, size) define an array of status vars + * PERFSTATUS_ARRAY (counter, string, size) define an array of status vars * * unsigned long perfc_value (counter) get value of a counter - * unsigned long perfc_valuec (counter) get value of a per CPU counter * unsigned long perfc_valuea (counter, index) get value of an array counter * unsigned long perfc_set (counter, val) set value of a counter - * unsigned long perfc_setc (counter, val) set value of a per CPU counter * unsigned long perfc_seta (counter, index, val) set value of an array counter * void perfc_incr (counter) increment a counter - * void perfc_incrc (counter, index) increment a per CPU counter + * void perfc_decr (counter) decrement a status * void perfc_incra (counter, index) increment an array counter * void perfc_add (counter, value) add a value to a counter - * void perfc_addc (counter, value) add a value to a per CPU counter * void perfc_adda (counter, index, value) add a value to array counter * void perfc_print (counter) print out the counter */ -#define PERFCOUNTER( var, name ) \ - atomic_t var[1]; -#define PERFCOUNTER_CPU( var, name ) \ - atomic_t var[NR_CPUS]; -#define PERFCOUNTER_ARRAY( var, name, size ) \ - atomic_t var[size]; -#define PERFSTATUS( var, name ) \ - atomic_t var[1]; -#define PERFSTATUS_CPU( var, name ) \ - atomic_t var[NR_CPUS]; -#define PERFSTATUS_ARRAY( var, name, size ) \ - atomic_t var[size]; +#define PERFCOUNTER( name, descr ) \ + PERFC_ ## name, +#define PERFCOUNTER_ARRAY( name, descr, size ) \ + PERFC_ ## name, \ + PERFC_LAST_ ## name = PERFC_ ## name + (size) - sizeof(char[2 * !!(size) - 1]), -struct perfcounter { +#define PERFSTATUS PERFCOUNTER +#define PERFSTATUS_ARRAY PERFCOUNTER_ARRAY + +/* Compatibility: This should go away once all users got converted. */ +#define PERFCOUNTER_CPU PERFCOUNTER + +enum perfcounter { #include <xen/perfc_defn.h> + NUM_PERFCOUNTERS }; -extern struct perfcounter perfcounters; +#undef PERFCOUNTER +#undef PERFCOUNTER_ARRAY +#undef PERFSTATUS +#undef PERFSTATUS_ARRAY -#define perfc_value(x) atomic_read(&perfcounters.x[0]) -#define perfc_valuec(x) atomic_read(&perfcounters.x[smp_processor_id()]) +typedef unsigned perfc_t; +#define PRIperfc "" + +DECLARE_PER_CPU(perfc_t[NUM_PERFCOUNTERS], perfcounters); + +#define perfc_value(x) this_cpu(perfcounters)[PERFC_ ## x] #define perfc_valuea(x,y) \ - ( (y) < (sizeof(perfcounters.x) / sizeof(*perfcounters.x)) ? \ - atomic_read(&perfcounters.x[y]) : 0 ) -#define perfc_set(x,v) atomic_set(&perfcounters.x[0], v) -#define perfc_setc(x,v) atomic_set(&perfcounters.x[smp_processor_id()], v) + ( (y) <= PERFC_LAST_ ## x - PERFC_ ## x ? \ + this_cpu(perfcounters)[PERFC_ ## x + (y)] : 0 ) +#define perfc_set(x,v) (this_cpu(perfcounters)[PERFC_ ## x] = (v)) #define perfc_seta(x,y,v) \ - do { \ - if ( (y) < (sizeof(perfcounters.x) / sizeof(*perfcounters.x)) ) \ - atomic_set(&perfcounters.x[y], v); \ - } while ( 0 ) -#define perfc_incr(x) atomic_inc(&perfcounters.x[0]) -#define perfc_decr(x) atomic_dec(&perfcounters.x[0]) -#define perfc_incrc(x) atomic_inc(&perfcounters.x[smp_processor_id()]) -#define perfc_decrc(x) atomic_dec(&perfcounters.x[smp_processor_id()]) + ( (y) <= PERFC_LAST_ ## x - PERFC_ ## x ? \ + this_cpu(perfcounters)[PERFC_ ## x + (y)] = (v) : (v) ) +#define perfc_incr(x) (++this_cpu(perfcounters)[PERFC_ ## x]) +#define perfc_decr(x) (--this_cpu(perfcounters)[PERFC_ ## x]) #define perfc_incra(x,y) \ - do { \ - if ( (y) < (sizeof(perfcounters.x) / sizeof(*perfcounters.x)) ) \ - atomic_inc(&perfcounters.x[y]); \ - } while ( 0 ) -#define perfc_add(x,y) atomic_add((y), &perfcounters.x[0]) -#define perfc_addc(x,y) atomic_add((y), &perfcounters.x[smp_processor_id()]) -#define perfc_adda(x,y,z) \ - do { \ - if ( (y) < (sizeof(perfcounters.x) / sizeof(*perfcounters.x)) ) \ - atomic_add((z), &perfcounters.x[y]); \ - } while ( 0 ) + ( (y) <= PERFC_LAST_ ## x - PERFC_ ## x ? \ + ++this_cpu(perfcounters)[PERFC_ ## x + (y)] : 0 ) +#define perfc_add(x,v) (this_cpu(perfcounters)[PERFC_ ## x] += (v)) +#define perfc_adda(x,y,v) \ + ( (y) <= PERFC_LAST_ ## x - PERFC_ ## x ? \ + this_cpu(perfcounters)[PERFC_ ## x + (y)] = (v) : (v) ) /* * Histogram: special treatment for 0 and 1 count. After that equally spaced * with last bucket taking the rest. */ #ifdef PERF_ARRAYS -#define perfc_incr_histo(_x,_v,_n) \ - do { \ - if ( (_v) == 0 ) \ - perfc_incra(_x, 0); \ - else if ( (_v) == 1 ) \ - perfc_incra(_x, 1); \ - else if ( (((_v)-2) / PERFC_ ## _n ## _BUCKET_SIZE) < \ - (PERFC_MAX_ ## _n - 3) ) \ - perfc_incra(_x, (((_v)-2) / PERFC_ ## _n ## _BUCKET_SIZE) + 2); \ - else \ - perfc_incra(_x, PERFC_MAX_ ## _n - 1); \ +#define perfc_incr_histo(x,v) \ + do { \ + if ( (v) == 0 ) \ + perfc_incra(x, 0); \ + else if ( (v) == 1 ) \ + perfc_incra(x, 1); \ + else if ( (((v) - 2) / PERFC_ ## x ## _BUCKET_SIZE) < \ + (PERFC_LAST_ ## x - PERFC_ ## x - 2) ) \ + perfc_incra(x, (((v) - 2) / PERFC_ ## x ## _BUCKET_SIZE) + 2); \ + else \ + perfc_incra(x, PERFC_LAST_ ## x - PERFC_ ## x); \ } while ( 0 ) #else -#define perfc_incr_histo(_x,_v,_n) ((void)0) +#define perfc_incr_histo(x,v) ((void)0) #endif struct xen_sysctl_perfc_op; @@ -110,22 +102,20 @@ int perfc_control(struct xen_sysctl_perf #else /* PERF_COUNTERS */ #define perfc_value(x) (0) -#define perfc_valuec(x) (0) #define perfc_valuea(x,y) (0) #define perfc_set(x,v) ((void)0) -#define perfc_setc(x,v) ((void)0) #define perfc_seta(x,y,v) ((void)0) #define perfc_incr(x) ((void)0) #define perfc_decr(x) ((void)0) -#define perfc_incrc(x) ((void)0) -#define perfc_decrc(x) ((void)0) #define perfc_incra(x,y) ((void)0) #define perfc_decra(x,y) ((void)0) #define perfc_add(x,y) ((void)0) -#define perfc_addc(x,y) ((void)0) #define perfc_adda(x,y,z) ((void)0) #define perfc_incr_histo(x,y,z) ((void)0) #endif /* PERF_COUNTERS */ +/* Compatibility: This should go away once all users got converted. */ +#define perfc_incrc perfc_incr + #endif /* __XEN_PERFC_H__ */ diff -r 3375391fb0c9 -r 96f167771979 xen/include/xen/perfc_defn.h --- a/xen/include/xen/perfc_defn.h Tue Mar 27 16:23:52 2007 +0100 +++ b/xen/include/xen/perfc_defn.h Tue Mar 27 16:35:37 2007 +0100 @@ -5,6 +5,9 @@ #include <asm/perfc_defn.h> PERFCOUNTER_ARRAY(hypercalls, "hypercalls", NR_hypercalls) + +PERFCOUNTER(calls_to_multicall, "calls to multicall") +PERFCOUNTER(calls_from_multicall, "calls from multicall") PERFCOUNTER_CPU(irqs, "#interrupts") PERFCOUNTER_CPU(ipis, "#IPIs") _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |