source: trunk/packages/xen-3.1/xen-3.1/xen/common/perfc.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 17 years ago

Add xen and xen-common

File size: 7.6 KB
Line 
1
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>
12
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 },
17static 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};
26
27#define NR_PERFCTRS (sizeof(perfc_info) / sizeof(perfc_info[0]))
28
29DEFINE_PER_CPU(perfc_t[NUM_PERFCOUNTERS], perfcounters);
30
31void perfc_printall(unsigned char key)
32{
33    unsigned int i, j;
34    s_time_t now = NOW();
35
36    printk("Xen performance counters SHOW  (now = 0x%08X:%08X)\n",
37           (u32)(now>>32), (u32)now);
38
39    for ( i = j = 0; i < NR_PERFCTRS; i++ )
40    {
41        unsigned int k, cpu;
42        unsigned long long sum = 0;
43
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;
72
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;
99
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    }
117
118    arch_perfc_printall();
119}
120
121void perfc_reset(unsigned char key)
122{
123    unsigned int i, j;
124    s_time_t now = NOW();
125
126    if ( key != '\0' )
127        printk("Xen performance counters RESET (now = 0x%08X:%08X)\n",
128               (u32)(now>>32), (u32)now);
129
130    /* leave STATUS counters alone -- don't reset */
131
132    for ( i = j = 0; i < NR_PERFCTRS; i++ )
133    {
134        unsigned int cpu;
135
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    }
153
154    arch_perfc_reset();
155}
156
157static xen_sysctl_perfc_desc_t perfc_d[NR_PERFCTRS];
158static xen_sysctl_perfc_val_t *perfc_vals;
159static unsigned int      perfc_nbr_vals;
160static int               perfc_init = 0;
161static 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;
165
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);
172
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    }
189
190    if ( guest_handle_is_null(desc) )
191        return 0;
192
193    if ( perfc_vals == NULL )
194        return -ENOMEM;
195
196    /* Architecture may fill counters from hardware.  */
197    arch_perfc_gather();
198
199    /* We gather the counts together every time. */
200    for ( i = j = v = 0; i < NR_PERFCTRS; i++ )
201    {
202        unsigned int cpu;
203
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;
219
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);
229
230    if ( copy_to_guest(desc, (xen_sysctl_perfc_desc_t *)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}
236
237/* Dom0 control of perf counters */
238int perfc_control(xen_sysctl_perfc_op_t *pc)
239{
240    static DEFINE_SPINLOCK(lock);
241    int rc;
242
243    spin_lock(&lock);
244
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;
251
252    case XEN_SYSCTL_PERFCOP_query:
253        rc = perfc_copy_info(pc->desc, pc->val);
254        break;
255
256    default:
257        rc = -EINVAL;
258        break;
259    }
260
261    spin_unlock(&lock);
262
263    pc->nr_counters = NR_PERFCTRS;
264    pc->nr_vals = perfc_nbr_vals;
265
266    return rc;
267}
268
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 */
Note: See TracBrowser for help on using the repository browser.