ia64/xen-unstable

view xen/common/perfc.c @ 12028:3d347263e5d8

[XEN] perf counters: Fix NULL-pointer check. Should happen later.
Signed-of-by: Kouya Shimura <kouya@jp.fujitsu.com>
author kaf24@localhost.localdomain
date Fri Oct 27 18:10:37 2006 +0100 (2006-10-27)
parents 6a974a3f32a4
children 1abb694a52df
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/sysctl.h>
11 #include <asm/perfc.h>
13 #undef PERFCOUNTER
14 #undef PERFCOUNTER_CPU
15 #undef PERFCOUNTER_ARRAY
16 #undef PERFSTATUS
17 #undef PERFSTATUS_CPU
18 #undef PERFSTATUS_ARRAY
19 #define PERFCOUNTER( var, name ) { name, TYPE_SINGLE, 0 },
20 #define PERFCOUNTER_CPU( var, name ) { name, TYPE_CPU, 0 },
21 #define PERFCOUNTER_ARRAY( var, name, size ) { name, TYPE_ARRAY, size },
22 #define PERFSTATUS( var, name ) { name, TYPE_S_SINGLE, 0 },
23 #define PERFSTATUS_CPU( var, name ) { name, TYPE_S_CPU, 0 },
24 #define PERFSTATUS_ARRAY( var, name, size ) { name, TYPE_S_ARRAY, size },
25 static struct {
26 char *name;
27 enum { TYPE_SINGLE, TYPE_CPU, TYPE_ARRAY,
28 TYPE_S_SINGLE, TYPE_S_CPU, TYPE_S_ARRAY
29 } type;
30 int nr_elements;
31 } perfc_info[] = {
32 #include <xen/perfc_defn.h>
33 };
35 #define NR_PERFCTRS (sizeof(perfc_info) / sizeof(perfc_info[0]))
37 struct perfcounter perfcounters;
39 void perfc_printall(unsigned char key)
40 {
41 unsigned int i, j, sum;
42 s_time_t now = NOW();
43 atomic_t *counters = (atomic_t *)&perfcounters;
45 printk("Xen performance counters SHOW (now = 0x%08X:%08X)\n",
46 (u32)(now>>32), (u32)now);
48 for ( i = 0; i < NR_PERFCTRS; i++ )
49 {
50 printk("%-32s ", perfc_info[i].name);
51 switch ( perfc_info[i].type )
52 {
53 case TYPE_SINGLE:
54 case TYPE_S_SINGLE:
55 printk("TOTAL[%10d]", atomic_read(&counters[0]));
56 counters += 1;
57 break;
58 case TYPE_CPU:
59 case TYPE_S_CPU:
60 sum = 0;
61 for_each_online_cpu ( j )
62 sum += atomic_read(&counters[j]);
63 printk("TOTAL[%10u]", sum);
64 if (sum)
65 {
66 for_each_online_cpu ( j )
67 printk(" CPU%02d[%10d]", j, atomic_read(&counters[j]));
68 }
69 counters += NR_CPUS;
70 break;
71 case TYPE_ARRAY:
72 case TYPE_S_ARRAY:
73 for ( j = sum = 0; j < perfc_info[i].nr_elements; j++ )
74 sum += atomic_read(&counters[j]);
75 printk("TOTAL[%10u]", sum);
76 #ifdef PERF_ARRAYS
77 if (sum)
78 {
79 for ( j = 0; j < perfc_info[i].nr_elements; j++ )
80 {
81 if ( (j % 4) == 0 )
82 printk("\n ");
83 printk(" ARR%02d[%10d]", j, atomic_read(&counters[j]));
84 }
85 }
86 #endif
87 counters += j;
88 break;
89 }
90 printk("\n");
91 }
93 arch_perfc_printall();
94 }
96 void perfc_reset(unsigned char key)
97 {
98 unsigned int i, j;
99 s_time_t now = NOW();
100 atomic_t *counters = (atomic_t *)&perfcounters;
102 if ( key != '\0' )
103 printk("Xen performance counters RESET (now = 0x%08X:%08X)\n",
104 (u32)(now>>32), (u32)now);
106 /* leave STATUS counters alone -- don't reset */
108 for ( i = 0; i < NR_PERFCTRS; i++ )
109 {
110 switch ( perfc_info[i].type )
111 {
112 case TYPE_SINGLE:
113 atomic_set(&counters[0],0);
114 case TYPE_S_SINGLE:
115 counters += 1;
116 break;
117 case TYPE_CPU:
118 for ( j = 0; j < NR_CPUS; j++ )
119 atomic_set(&counters[j],0);
120 case TYPE_S_CPU:
121 counters += NR_CPUS;
122 break;
123 case TYPE_ARRAY:
124 for ( j = 0; j < perfc_info[i].nr_elements; j++ )
125 atomic_set(&counters[j],0);
126 case TYPE_S_ARRAY:
127 counters += perfc_info[i].nr_elements;
128 break;
129 }
130 }
132 arch_perfc_reset ();
133 }
135 static xen_sysctl_perfc_desc_t perfc_d[NR_PERFCTRS];
136 static xen_sysctl_perfc_val_t *perfc_vals;
137 static int perfc_nbr_vals;
138 static int perfc_init = 0;
139 static int perfc_copy_info(XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t) desc,
140 XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t) val)
141 {
142 unsigned int i, j;
143 unsigned int v = 0;
144 atomic_t *counters = (atomic_t *)&perfcounters;
146 /* We only copy the name and array-size information once. */
147 if ( !perfc_init )
148 {
149 for ( i = 0; i < NR_PERFCTRS; i++ )
150 {
151 strncpy(perfc_d[i].name, perfc_info[i].name,
152 sizeof(perfc_d[i].name));
153 perfc_d[i].name[sizeof(perfc_d[i].name)-1] = '\0';
155 switch ( perfc_info[i].type )
156 {
157 case TYPE_SINGLE:
158 case TYPE_S_SINGLE:
159 perfc_d[i].nr_vals = 1;
160 break;
161 case TYPE_CPU:
162 case TYPE_S_CPU:
163 perfc_d[i].nr_vals = num_online_cpus();
164 break;
165 case TYPE_ARRAY:
166 case TYPE_S_ARRAY:
167 perfc_d[i].nr_vals = perfc_info[i].nr_elements;
168 break;
169 }
170 perfc_nbr_vals += perfc_d[i].nr_vals;
171 }
172 perfc_vals = xmalloc_array(xen_sysctl_perfc_val_t, perfc_nbr_vals);
173 perfc_init = 1;
174 }
176 if ( guest_handle_is_null(desc) )
177 return 0;
179 if ( perfc_vals == NULL )
180 return -ENOMEM;
182 /* Architecture may fill counters from hardware. */
183 arch_perfc_gather();
185 /* We gather the counts together every time. */
186 for ( i = 0; i < NR_PERFCTRS; i++ )
187 {
188 switch ( perfc_info[i].type )
189 {
190 case TYPE_SINGLE:
191 case TYPE_S_SINGLE:
192 perfc_vals[v++] = atomic_read(&counters[0]);
193 counters += 1;
194 break;
195 case TYPE_CPU:
196 case TYPE_S_CPU:
197 for ( j = 0; j < perfc_d[i].nr_vals; j++ )
198 perfc_vals[v++] = atomic_read(&counters[j]);
199 counters += NR_CPUS;
200 break;
201 case TYPE_ARRAY:
202 case TYPE_S_ARRAY:
203 for ( j = 0; j < perfc_d[i].nr_vals; j++ )
204 perfc_vals[v++] = atomic_read(&counters[j]);
205 counters += perfc_info[i].nr_elements;
206 break;
207 }
208 }
209 BUG_ON(v != perfc_nbr_vals);
211 if ( copy_to_guest(desc, (xen_sysctl_perfc_desc_t *)perfc_d, NR_PERFCTRS) )
212 return -EFAULT;
213 if ( copy_to_guest(val, perfc_vals, perfc_nbr_vals) )
214 return -EFAULT;
215 return 0;
216 }
218 /* Dom0 control of perf counters */
219 int perfc_control(xen_sysctl_perfc_op_t *pc)
220 {
221 static DEFINE_SPINLOCK(lock);
222 int rc;
224 spin_lock(&lock);
226 switch ( pc->cmd )
227 {
228 case XEN_SYSCTL_PERFCOP_reset:
229 perfc_copy_info(pc->desc, pc->val);
230 perfc_reset(0);
231 rc = 0;
232 break;
234 case XEN_SYSCTL_PERFCOP_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 */