ia64/xen-unstable

view xen/common/perfc.c @ 3894:ba1a314ce815

bitkeeper revision 1.1230.4.1 (421b7d70g_kPPMvAgkUMMU-R8G4RrA)

add perfcounters for pagetable update histograms

Signed-off-by: michael.fetterman@cl.cam.ac.uk
author rneugeba@wyvis.research.intel-research.net
date Tue Feb 22 18:44:00 2005 +0000 (2005-02-22)
parents 0a4b76b6b5a0
children b57a97bb65bd
line source
1 /* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
3 #include <xen/lib.h>
4 #include <xen/smp.h>
5 #include <xen/time.h>
6 #include <xen/perfc.h>
7 #include <xen/keyhandler.h>
8 #include <public/dom0_ops.h>
9 #include <asm/uaccess.h>
11 #undef PERFCOUNTER
12 #undef PERFCOUNTER_CPU
13 #undef PERFCOUNTER_ARRAY
14 #undef PERFSTATUS
15 #undef PERFSTATUS_CPU
16 #undef PERFSTATUS_ARRAY
17 #define PERFCOUNTER( var, name ) { name, TYPE_SINGLE, 0 },
18 #define PERFCOUNTER_CPU( var, name ) { name, TYPE_CPU, 0 },
19 #define PERFCOUNTER_ARRAY( var, name, size ) { name, TYPE_ARRAY, size },
20 #define PERFSTATUS( var, name ) { name, TYPE_S_SINGLE, 0 },
21 #define PERFSTATUS_CPU( var, name ) { name, TYPE_S_CPU, 0 },
22 #define PERFSTATUS_ARRAY( var, name, size ) { name, TYPE_S_ARRAY, size },
23 static struct {
24 char *name;
25 enum { TYPE_SINGLE, TYPE_CPU, TYPE_ARRAY,
26 TYPE_S_SINGLE, TYPE_S_CPU, TYPE_S_ARRAY
27 } type;
28 int nr_elements;
29 } perfc_info[] = {
30 #include <xen/perfc_defn.h>
31 };
33 #define NR_PERFCTRS (sizeof(perfc_info) / sizeof(perfc_info[0]))
35 struct perfcounter_t perfcounters;
37 void perfc_printall(unsigned char key)
38 {
39 int i, j, sum;
40 s_time_t now = NOW();
41 atomic_t *counters = (atomic_t *)&perfcounters;
43 printk("Xen performance counters SHOW (now = 0x%08X:%08X)\n",
44 (u32)(now>>32), (u32)now);
46 for ( i = 0; i < NR_PERFCTRS; i++ )
47 {
48 printk("%-32s ", perfc_info[i].name);
49 switch ( perfc_info[i].type )
50 {
51 case TYPE_SINGLE:
52 case TYPE_S_SINGLE:
53 printk("TOTAL[%10d]", atomic_read(&counters[0]));
54 counters += 1;
55 break;
56 case TYPE_CPU:
57 case TYPE_S_CPU:
58 for ( j = sum = 0; j < smp_num_cpus; j++ )
59 sum += atomic_read(&counters[j]);
60 printk("TOTAL[%10d] ", sum);
61 for ( j = 0; j < smp_num_cpus; j++ )
62 printk("CPU%02d[%10d] ", j, atomic_read(&counters[j]));
63 counters += NR_CPUS;
64 break;
65 case TYPE_ARRAY:
66 case TYPE_S_ARRAY:
67 for ( j = sum = 0; j < perfc_info[i].nr_elements; j++ )
68 sum += atomic_read(&counters[j]);
69 printk("TOTAL[%10d]\n ", sum);
70 for ( j = 0; j < perfc_info[i].nr_elements; j++ )
71 {
72 printk("A%02d[%10d] ", j, atomic_read(&counters[j]));
73 if ( !(j % 4) )
74 printk("\n ");
75 }
76 counters += j;
77 break;
78 }
79 printk("\n");
80 }
81 }
83 void perfc_reset(unsigned char key)
84 {
85 int i, j, sum;
86 s_time_t now = NOW();
87 atomic_t *counters = (atomic_t *)&perfcounters;
89 if ( key != '\0' )
90 printk("Xen performance counters RESET (now = 0x%08X:%08X)\n",
91 (u32)(now>>32), (u32)now);
93 /* leave STATUS counters alone -- don't reset */
95 for ( i = 0; i < NR_PERFCTRS; i++ )
96 {
97 switch ( perfc_info[i].type )
98 {
99 case TYPE_SINGLE:
100 atomic_set(&counters[0],0);
101 case TYPE_S_SINGLE:
102 counters += 1;
103 break;
104 case TYPE_CPU:
105 for ( j = sum = 0; j < smp_num_cpus; j++ )
106 atomic_set(&counters[j],0);
107 case TYPE_S_CPU:
108 counters += NR_CPUS;
109 break;
110 case TYPE_ARRAY:
111 for ( j = sum = 0; j < perfc_info[i].nr_elements; j++ )
112 atomic_set(&counters[j],0);
113 case TYPE_S_ARRAY:
114 counters += perfc_info[i].nr_elements;
115 break;
116 }
117 }
118 }
120 static dom0_perfc_desc_t perfc_d[NR_PERFCTRS];
121 static int perfc_init = 0;
122 static int perfc_copy_info(dom0_perfc_desc_t *desc)
123 {
124 unsigned int i, j;
125 atomic_t *counters = (atomic_t *)&perfcounters;
127 if ( desc == NULL )
128 return 0;
130 /* We only copy the name and array-size information once. */
131 if ( !perfc_init )
132 {
133 for ( i = 0; i < NR_PERFCTRS; i++ )
134 {
135 strncpy(perfc_d[i].name, perfc_info[i].name,
136 sizeof(perfc_d[i].name));
137 perfc_d[i].name[sizeof(perfc_d[i].name)-1] = '\0';
139 switch ( perfc_info[i].type )
140 {
141 case TYPE_SINGLE:
142 case TYPE_S_SINGLE:
143 perfc_d[i].nr_vals = 1;
144 break;
145 case TYPE_CPU:
146 case TYPE_S_CPU:
147 perfc_d[i].nr_vals = smp_num_cpus;
148 break;
149 case TYPE_ARRAY:
150 case TYPE_S_ARRAY:
151 perfc_d[i].nr_vals = perfc_info[i].nr_elements;
152 break;
153 }
155 if ( perfc_d[i].nr_vals > ARRAY_SIZE(perfc_d[i].vals) )
156 perfc_d[i].nr_vals = ARRAY_SIZE(perfc_d[i].vals);
157 }
159 perfc_init = 1;
160 }
162 /* We gather the counts together every time. */
163 for ( i = 0; i < NR_PERFCTRS; i++ )
164 {
165 switch ( perfc_info[i].type )
166 {
167 case TYPE_SINGLE:
168 case TYPE_S_SINGLE:
169 perfc_d[i].vals[0] = atomic_read(&counters[0]);
170 counters += 1;
171 break;
172 case TYPE_CPU:
173 case TYPE_S_CPU:
174 for ( j = 0; j < perfc_d[i].nr_vals; j++ )
175 perfc_d[i].vals[j] = atomic_read(&counters[j]);
176 counters += NR_CPUS;
177 break;
178 case TYPE_ARRAY:
179 case TYPE_S_ARRAY:
180 for ( j = 0; j < perfc_d[i].nr_vals; j++ )
181 perfc_d[i].vals[j] = atomic_read(&counters[j]);
182 counters += perfc_info[i].nr_elements;
183 break;
184 }
185 }
187 return (copy_to_user(desc, perfc_d, NR_PERFCTRS * sizeof(*desc)) ?
188 -EFAULT : 0);
189 }
191 /* Dom0 control of perf counters */
192 int perfc_control(dom0_perfccontrol_t *pc)
193 {
194 static spinlock_t lock = SPIN_LOCK_UNLOCKED;
195 u32 op = pc->op;
196 int rc;
198 pc->nr_counters = NR_PERFCTRS;
200 spin_lock(&lock);
202 switch ( op )
203 {
204 case DOM0_PERFCCONTROL_OP_RESET:
205 perfc_copy_info(pc->desc);
206 perfc_reset(0);
207 rc = 0;
208 break;
210 case DOM0_PERFCCONTROL_OP_QUERY:
211 perfc_copy_info(pc->desc);
212 rc = 0;
213 break;
215 default:
216 rc = -EINVAL;
217 break;
218 }
220 spin_unlock(&lock);
222 return rc;
223 }