debuggers.hg

view xen/common/perfc.c @ 10991:7924b6bd728a

Change DOM0_PERFCCONTROL: remove array limit.

Descriptors and values are passed by two distinct buffers.

Signed-off-by: Tristan Gingold <tristan.gingold@bull.net>
author kaf24@firebug.cl.cam.ac.uk
date Mon Aug 07 15:53:06 2006 +0100 (2006-08-07)
parents 808430428622
children 6289234304f1
line source
2 #include <xen/lib.h>
3 #include <xen/smp.h>
4 #include <xen/time.h>
5 #include <xen/perfc.h>
6 #include <xen/keyhandler.h>
7 #include <xen/spinlock.h>
8 #include <xen/mm.h>
9 #include <xen/guest_access.h>
10 #include <public/dom0_ops.h>
12 #undef PERFCOUNTER
13 #undef PERFCOUNTER_CPU
14 #undef PERFCOUNTER_ARRAY
15 #undef PERFSTATUS
16 #undef PERFSTATUS_CPU
17 #undef PERFSTATUS_ARRAY
18 #define PERFCOUNTER( var, name ) { name, TYPE_SINGLE, 0 },
19 #define PERFCOUNTER_CPU( var, name ) { name, TYPE_CPU, 0 },
20 #define PERFCOUNTER_ARRAY( var, name, size ) { name, TYPE_ARRAY, size },
21 #define PERFSTATUS( var, name ) { name, TYPE_S_SINGLE, 0 },
22 #define PERFSTATUS_CPU( var, name ) { name, TYPE_S_CPU, 0 },
23 #define PERFSTATUS_ARRAY( var, name, size ) { name, TYPE_S_ARRAY, size },
24 static struct {
25 char *name;
26 enum { TYPE_SINGLE, TYPE_CPU, TYPE_ARRAY,
27 TYPE_S_SINGLE, TYPE_S_CPU, TYPE_S_ARRAY
28 } type;
29 int nr_elements;
30 } perfc_info[] = {
31 #include <xen/perfc_defn.h>
32 };
34 #define NR_PERFCTRS (sizeof(perfc_info) / sizeof(perfc_info[0]))
36 struct perfcounter perfcounters;
38 void perfc_printall(unsigned char key)
39 {
40 unsigned int i, j, sum;
41 s_time_t now = NOW();
42 atomic_t *counters = (atomic_t *)&perfcounters;
44 printk("Xen performance counters SHOW (now = 0x%08X:%08X)\n",
45 (u32)(now>>32), (u32)now);
47 for ( i = 0; i < NR_PERFCTRS; i++ )
48 {
49 printk("%-32s ", perfc_info[i].name);
50 switch ( perfc_info[i].type )
51 {
52 case TYPE_SINGLE:
53 case TYPE_S_SINGLE:
54 printk("TOTAL[%10d]", atomic_read(&counters[0]));
55 counters += 1;
56 break;
57 case TYPE_CPU:
58 case TYPE_S_CPU:
59 sum = 0;
60 for_each_online_cpu ( j )
61 sum += atomic_read(&counters[j]);
62 printk("TOTAL[%10u]", sum);
63 if (sum)
64 {
65 for_each_online_cpu ( j )
66 printk(" CPU%02d[%10d]", j, atomic_read(&counters[j]));
67 }
68 counters += NR_CPUS;
69 break;
70 case TYPE_ARRAY:
71 case TYPE_S_ARRAY:
72 for ( j = sum = 0; j < perfc_info[i].nr_elements; j++ )
73 sum += atomic_read(&counters[j]);
74 printk("TOTAL[%10u]", sum);
75 #ifdef PERF_ARRAYS
76 if (sum)
77 {
78 for ( j = 0; j < perfc_info[i].nr_elements; j++ )
79 {
80 if ( (j % 4) == 0 )
81 printk("\n ");
82 printk(" ARR%02d[%10d]", j, atomic_read(&counters[j]));
83 }
84 }
85 #endif
86 counters += j;
87 break;
88 }
89 printk("\n");
90 }
92 #ifdef PERF_ARRAYS
93 ptwr_eip_stat_print();
94 #endif
95 }
97 void perfc_reset(unsigned char key)
98 {
99 unsigned int i, j;
100 s_time_t now = NOW();
101 atomic_t *counters = (atomic_t *)&perfcounters;
103 if ( key != '\0' )
104 printk("Xen performance counters RESET (now = 0x%08X:%08X)\n",
105 (u32)(now>>32), (u32)now);
107 /* leave STATUS counters alone -- don't reset */
109 for ( i = 0; i < NR_PERFCTRS; i++ )
110 {
111 switch ( perfc_info[i].type )
112 {
113 case TYPE_SINGLE:
114 atomic_set(&counters[0],0);
115 case TYPE_S_SINGLE:
116 counters += 1;
117 break;
118 case TYPE_CPU:
119 for ( j = 0; j < NR_CPUS; j++ )
120 atomic_set(&counters[j],0);
121 case TYPE_S_CPU:
122 counters += NR_CPUS;
123 break;
124 case TYPE_ARRAY:
125 for ( j = 0; j < perfc_info[i].nr_elements; j++ )
126 atomic_set(&counters[j],0);
127 case TYPE_S_ARRAY:
128 counters += perfc_info[i].nr_elements;
129 break;
130 }
131 }
133 #ifdef PERF_ARRAYS
134 ptwr_eip_stat_reset();
135 #endif
136 }
138 static dom0_perfc_desc_t perfc_d[NR_PERFCTRS];
139 static dom0_perfc_val_t *perfc_vals;
140 static int perfc_nbr_vals;
141 static int perfc_init = 0;
142 static int perfc_copy_info(XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc,
143 XEN_GUEST_HANDLE(dom0_perfc_val_t) val)
144 {
145 unsigned int i, j;
146 unsigned int v = 0;
147 atomic_t *counters = (atomic_t *)&perfcounters;
149 if ( guest_handle_is_null(desc) )
150 return 0;
152 /* We only copy the name and array-size information once. */
153 if ( !perfc_init )
154 {
155 for ( i = 0; i < NR_PERFCTRS; i++ )
156 {
157 strncpy(perfc_d[i].name, perfc_info[i].name,
158 sizeof(perfc_d[i].name));
159 perfc_d[i].name[sizeof(perfc_d[i].name)-1] = '\0';
161 switch ( perfc_info[i].type )
162 {
163 case TYPE_SINGLE:
164 case TYPE_S_SINGLE:
165 perfc_d[i].nr_vals = 1;
166 break;
167 case TYPE_CPU:
168 case TYPE_S_CPU:
169 perfc_d[i].nr_vals = num_online_cpus();
170 break;
171 case TYPE_ARRAY:
172 case TYPE_S_ARRAY:
173 perfc_d[i].nr_vals = perfc_info[i].nr_elements;
174 break;
175 }
176 perfc_nbr_vals += perfc_d[i].nr_vals;
177 }
178 perfc_vals = xmalloc_array(dom0_perfc_val_t, perfc_nbr_vals);
179 perfc_init = 1;
180 }
181 if (perfc_vals == NULL)
182 return -ENOMEM;
184 /* We gather the counts together every time. */
185 for ( i = 0; i < NR_PERFCTRS; i++ )
186 {
187 switch ( perfc_info[i].type )
188 {
189 case TYPE_SINGLE:
190 case TYPE_S_SINGLE:
191 perfc_vals[v++] = atomic_read(&counters[0]);
192 counters += 1;
193 break;
194 case TYPE_CPU:
195 case TYPE_S_CPU:
196 for ( j = 0; j < perfc_d[i].nr_vals; j++ )
197 perfc_vals[v++] = atomic_read(&counters[j]);
198 counters += NR_CPUS;
199 break;
200 case TYPE_ARRAY:
201 case TYPE_S_ARRAY:
202 for ( j = 0; j < perfc_d[i].nr_vals; j++ )
203 perfc_vals[v++] = atomic_read(&counters[j]);
204 counters += perfc_info[i].nr_elements;
205 break;
206 }
207 }
208 BUG_ON(v != perfc_nbr_vals);
210 if (copy_to_guest(desc, (dom0_perfc_desc_t *)perfc_d, NR_PERFCTRS))
211 return -EFAULT;
212 if (copy_to_guest(val, perfc_vals, perfc_nbr_vals))
213 return -EFAULT;
214 return 0;
215 }
217 /* Dom0 control of perf counters */
218 int perfc_control(dom0_perfccontrol_t *pc)
219 {
220 static DEFINE_SPINLOCK(lock);
221 u32 op = pc->op;
222 int rc;
224 spin_lock(&lock);
226 switch ( op )
227 {
228 case DOM0_PERFCCONTROL_OP_RESET:
229 perfc_copy_info(pc->desc, pc->val);
230 perfc_reset(0);
231 rc = 0;
232 break;
234 case DOM0_PERFCCONTROL_OP_QUERY:
235 perfc_copy_info(pc->desc, pc->val);
236 rc = 0;
237 break;
239 default:
240 rc = -EINVAL;
241 break;
242 }
244 spin_unlock(&lock);
246 pc->nr_counters = NR_PERFCTRS;
247 pc->nr_vals = perfc_nbr_vals;
249 return rc;
250 }
252 /*
253 * Local variables:
254 * mode: C
255 * c-set-style: "BSD"
256 * c-basic-offset: 4
257 * tab-width: 4
258 * indent-tabs-mode: nil
259 * End:
260 */