ia64/xen-unstable

view xen/common/perfc.c @ 17062:0769835cf50f

x86 shadow: Reduce scope of shadow lock.

emulate_map_dest doesn't require holding lock, since
only shadow related operation possibly involved is to
remove shadow which is less frequent and can acquire
lock inside. Rest are either guest table walk or
per-vcpu monitor table manipulation

Signed-off-by Kevin Tian <kevin.tian@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Feb 14 10:33:12 2008 +0000 (2008-02-14)
parents 45a44a9cbe8d
children
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 #define PERFCOUNTER( var, name ) { name, TYPE_SINGLE, 0 },
14 #define PERFCOUNTER_ARRAY( var, name, size ) { name, TYPE_ARRAY, size },
15 #define PERFSTATUS( var, name ) { name, TYPE_S_SINGLE, 0 },
16 #define PERFSTATUS_ARRAY( var, name, size ) { name, TYPE_S_ARRAY, size },
17 static const struct {
18 const char *name;
19 enum { TYPE_SINGLE, TYPE_ARRAY,
20 TYPE_S_SINGLE, TYPE_S_ARRAY
21 } type;
22 unsigned int nr_elements;
23 } perfc_info[] = {
24 #include <xen/perfc_defn.h>
25 };
27 #define NR_PERFCTRS (sizeof(perfc_info) / sizeof(perfc_info[0]))
29 DEFINE_PER_CPU(perfc_t[NUM_PERFCOUNTERS], perfcounters);
31 void perfc_printall(unsigned char key)
32 {
33 unsigned int i, j;
34 s_time_t now = NOW();
36 printk("Xen performance counters SHOW (now = 0x%08X:%08X)\n",
37 (u32)(now>>32), (u32)now);
39 for ( i = j = 0; i < NR_PERFCTRS; i++ )
40 {
41 unsigned int k, cpu;
42 unsigned long long sum = 0;
44 printk("%-32s ", perfc_info[i].name);
45 switch ( perfc_info[i].type )
46 {
47 case TYPE_SINGLE:
48 case TYPE_S_SINGLE:
49 for_each_online_cpu ( cpu )
50 sum += per_cpu(perfcounters, cpu)[j];
51 if ( perfc_info[i].type == TYPE_S_SINGLE )
52 sum = (perfc_t) sum;
53 printk("TOTAL[%12Lu]", sum);
54 if ( sum )
55 {
56 k = 0;
57 for_each_online_cpu ( cpu )
58 {
59 if ( k > 0 && (k % 4) == 0 )
60 printk("\n%46s", "");
61 printk(" CPU%02u[%10"PRIperfc"u]", cpu, per_cpu(perfcounters, cpu)[j]);
62 ++k;
63 }
64 }
65 ++j;
66 break;
67 case TYPE_ARRAY:
68 case TYPE_S_ARRAY:
69 for_each_online_cpu ( cpu )
70 {
71 perfc_t *counters = per_cpu(perfcounters, cpu) + j;
73 for ( k = 0; k < perfc_info[i].nr_elements; k++ )
74 sum += counters[k];
75 }
76 if ( perfc_info[i].type == TYPE_S_ARRAY )
77 sum = (perfc_t) sum;
78 printk("TOTAL[%12Lu]", sum);
79 if (sum)
80 {
81 #ifdef PERF_ARRAYS
82 for ( k = 0; k < perfc_info[i].nr_elements; k++ )
83 {
84 sum = 0;
85 for_each_online_cpu ( cpu )
86 sum += per_cpu(perfcounters, cpu)[j + k];
87 if ( perfc_info[i].type == TYPE_S_ARRAY )
88 sum = (perfc_t) sum;
89 if ( (k % 4) == 0 )
90 printk("\n%16s", "");
91 printk(" ARR%02u[%10Lu]", k, sum);
92 }
93 #else
94 k = 0;
95 for_each_online_cpu ( cpu )
96 {
97 perfc_t *counters = per_cpu(perfcounters, cpu) + j;
98 unsigned int n;
100 sum = 0;
101 for ( n = 0; n < perfc_info[i].nr_elements; n++ )
102 sum += counters[n];
103 if ( perfc_info[i].type == TYPE_S_ARRAY )
104 sum = (perfc_t) sum;
105 if ( k > 0 && (k % 4) == 0 )
106 printk("\n%46s", "");
107 printk(" CPU%02u[%10Lu]", cpu, sum);
108 ++k;
109 }
110 #endif
111 }
112 j += perfc_info[i].nr_elements;
113 break;
114 }
115 printk("\n");
116 }
118 arch_perfc_printall();
119 }
121 void perfc_reset(unsigned char key)
122 {
123 unsigned int i, j;
124 s_time_t now = NOW();
126 if ( key != '\0' )
127 printk("Xen performance counters RESET (now = 0x%08X:%08X)\n",
128 (u32)(now>>32), (u32)now);
130 /* leave STATUS counters alone -- don't reset */
132 for ( i = j = 0; i < NR_PERFCTRS; i++ )
133 {
134 unsigned int cpu;
136 switch ( perfc_info[i].type )
137 {
138 case TYPE_SINGLE:
139 for_each_cpu ( cpu )
140 per_cpu(perfcounters, cpu)[j] = 0;
141 case TYPE_S_SINGLE:
142 ++j;
143 break;
144 case TYPE_ARRAY:
145 for_each_cpu ( cpu )
146 memset(per_cpu(perfcounters, cpu) + j, 0,
147 perfc_info[i].nr_elements * sizeof(perfc_t));
148 case TYPE_S_ARRAY:
149 j += perfc_info[i].nr_elements;
150 break;
151 }
152 }
154 arch_perfc_reset();
155 }
157 static xen_sysctl_perfc_desc_t perfc_d[NR_PERFCTRS];
158 static xen_sysctl_perfc_val_t *perfc_vals;
159 static unsigned int perfc_nbr_vals;
160 static int perfc_init = 0;
161 static int perfc_copy_info(XEN_GUEST_HANDLE_64(xen_sysctl_perfc_desc_t) desc,
162 XEN_GUEST_HANDLE_64(xen_sysctl_perfc_val_t) val)
163 {
164 unsigned int i, j, v;
166 /* We only copy the name and array-size information once. */
167 if ( !perfc_init )
168 {
169 for ( i = 0; i < NR_PERFCTRS; i++ )
170 {
171 safe_strcpy(perfc_d[i].name, perfc_info[i].name);
173 switch ( perfc_info[i].type )
174 {
175 case TYPE_SINGLE:
176 case TYPE_S_SINGLE:
177 perfc_d[i].nr_vals = num_possible_cpus();
178 break;
179 case TYPE_ARRAY:
180 case TYPE_S_ARRAY:
181 perfc_d[i].nr_vals = perfc_info[i].nr_elements;
182 break;
183 }
184 perfc_nbr_vals += perfc_d[i].nr_vals;
185 }
186 perfc_vals = xmalloc_array(xen_sysctl_perfc_val_t, perfc_nbr_vals);
187 perfc_init = 1;
188 }
190 if ( guest_handle_is_null(desc) )
191 return 0;
193 if ( perfc_vals == NULL )
194 return -ENOMEM;
196 /* Architecture may fill counters from hardware. */
197 arch_perfc_gather();
199 /* We gather the counts together every time. */
200 for ( i = j = v = 0; i < NR_PERFCTRS; i++ )
201 {
202 unsigned int cpu;
204 switch ( perfc_info[i].type )
205 {
206 case TYPE_SINGLE:
207 case TYPE_S_SINGLE:
208 for_each_cpu ( cpu )
209 perfc_vals[v++] = per_cpu(perfcounters, cpu)[j];
210 ++j;
211 break;
212 case TYPE_ARRAY:
213 case TYPE_S_ARRAY:
214 memset(perfc_vals + v, 0, perfc_d[i].nr_vals * sizeof(*perfc_vals));
215 for_each_cpu ( cpu )
216 {
217 perfc_t *counters = per_cpu(perfcounters, cpu) + j;
218 unsigned int k;
220 for ( k = 0; k < perfc_d[i].nr_vals; k++ )
221 perfc_vals[v + k] += counters[k];
222 }
223 v += perfc_d[i].nr_vals;
224 j += perfc_info[i].nr_elements;
225 break;
226 }
227 }
228 BUG_ON(v != perfc_nbr_vals);
230 if ( copy_to_guest(desc, perfc_d, NR_PERFCTRS) )
231 return -EFAULT;
232 if ( copy_to_guest(val, perfc_vals, perfc_nbr_vals) )
233 return -EFAULT;
234 return 0;
235 }
237 /* Dom0 control of perf counters */
238 int perfc_control(xen_sysctl_perfc_op_t *pc)
239 {
240 static DEFINE_SPINLOCK(lock);
241 int rc;
243 spin_lock(&lock);
245 switch ( pc->cmd )
246 {
247 case XEN_SYSCTL_PERFCOP_reset:
248 rc = perfc_copy_info(pc->desc, pc->val);
249 perfc_reset(0);
250 break;
252 case XEN_SYSCTL_PERFCOP_query:
253 rc = perfc_copy_info(pc->desc, pc->val);
254 break;
256 default:
257 rc = -EINVAL;
258 break;
259 }
261 spin_unlock(&lock);
263 pc->nr_counters = NR_PERFCTRS;
264 pc->nr_vals = perfc_nbr_vals;
266 return rc;
267 }
269 /*
270 * Local variables:
271 * mode: C
272 * c-set-style: "BSD"
273 * c-basic-offset: 4
274 * tab-width: 4
275 * indent-tabs-mode: nil
276 * End:
277 */