1 /* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
2  ****************************************************************************
3  * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge
4  ****************************************************************************
5  *
6  *        File: xenperf.c
7  *      Author: Rolf Neugebauer (rolf.neugebauer@intel.com)
8  *        Date: Nov 2004
9  *
10  * Description:
11  */
12 
13 #include <xenctrl.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <sys/mman.h>
17 #include <errno.h>
18 #include <string.h>
19 
20 #define X(name) [__HYPERVISOR_##name] = #name
21 static const char *const hypercall_name_table[64] =
22 {
23     X(set_trap_table),
24     X(mmu_update),
25     X(set_gdt),
26     X(stack_switch),
27     X(set_callbacks),
28     X(fpu_taskswitch),
29     X(sched_op_compat),
30     X(platform_op),
31     X(set_debugreg),
32     X(get_debugreg),
33     X(update_descriptor),
34     X(memory_op),
35     X(multicall),
36     X(update_va_mapping),
37     X(set_timer_op),
38     X(event_channel_op_compat),
39     X(xen_version),
40     X(console_io),
41     X(physdev_op_compat),
42     X(grant_table_op),
43     X(vm_assist),
44     X(update_va_mapping_otherdomain),
45     X(iret),
46     X(vcpu_op),
47     X(set_segment_base),
48     X(mmuext_op),
49     X(xsm_op),
50     X(nmi_op),
51     X(sched_op),
52     X(callback_op),
53     X(xenoprof_op),
54     X(event_channel_op),
55     X(physdev_op),
56     X(hvm_op),
57     X(sysctl),
58     X(domctl),
59     X(kexec_op),
60     X(tmem_op),
61     X(argo_op),
62     X(xenpmu_op),
63     X(dm_op),
64     X(hypfs_op),
65 #if defined(__i386__) || defined(__x86_64__)
66     X(mca),
67     [__HYPERVISOR_arch_1] = "paging-domctl-continuation",
68 #else
69     X(arch_0),
70     X(arch_1),
71 #endif
72     X(arch_2),
73     X(arch_3),
74     X(arch_4),
75     X(arch_5),
76     X(arch_6),
77     X(arch_7),
78 };
79 #undef X
80 
main(int argc,char * argv[])81 int main(int argc, char *argv[])
82 {
83     int              i, j;
84     xc_interface    *xc_handle;
85     DECLARE_HYPERCALL_BUFFER(xc_perfc_desc_t, pcd);
86     DECLARE_HYPERCALL_BUFFER(xc_perfc_val_t, pcv);
87     xc_perfc_val_t  *val;
88     int num_desc, num_val;
89     unsigned int     reset = 0, full = 0, pretty = 0;
90     char hypercall_name[36];
91 
92     if ( argc > 1 )
93     {
94         char *p = argv[1];
95         if ( p[0] == '-' )
96         {
97             switch ( p[1] )
98             {
99             case 'f':
100                 full = 1;
101                 break;
102             case 'p':
103                 full = 1;
104                 pretty = 1;
105                 break;
106             case 'r':
107                 reset = 1;
108                 break;
109             default:
110                 goto error;
111             }
112         }
113         else
114         {
115         error:
116             printf("%s: [-r]\n", argv[0]);
117             printf("no args: print digested counters\n");
118             printf("    -f : print full arrays/histograms\n");
119             printf("    -p : print full arrays/histograms in pretty format\n");
120             printf("    -r : reset counters\n");
121             return 0;
122         }
123     }
124 
125     if ( (xc_handle = xc_interface_open(0,0,0)) == 0 )
126     {
127         fprintf(stderr, "Error opening xc interface: %d (%s)\n",
128                 errno, strerror(errno));
129         return 1;
130     }
131 
132     if ( reset )
133     {
134         if ( xc_perfc_reset(xc_handle) != 0 )
135         {
136             fprintf(stderr, "Error resetting performance counters: %d (%s)\n",
137                     errno, strerror(errno));
138             return 1;
139         }
140 
141         return 0;
142     }
143 
144     if ( xc_perfc_query_number(xc_handle, &num_desc, &num_val) != 0 )
145     {
146         fprintf(stderr, "Error getting number of perf counters: %d (%s)\n",
147                 errno, strerror(errno));
148         return 1;
149     }
150 
151     pcd = xc_hypercall_buffer_alloc(xc_handle, pcd, sizeof(*pcd) * num_desc);
152     pcv = xc_hypercall_buffer_alloc(xc_handle, pcv, sizeof(*pcv) * num_val);
153 
154     if ( pcd == NULL || pcv == NULL)
155     {
156         fprintf(stderr, "Could not allocate buffers: %d (%s)\n",
157                 errno, strerror(errno));
158         exit(-1);
159     }
160 
161     if ( xc_perfc_query(xc_handle, HYPERCALL_BUFFER(pcd), HYPERCALL_BUFFER(pcv)) != 0 )
162     {
163         fprintf(stderr, "Error getting perf counter: %d (%s)\n",
164                 errno, strerror(errno));
165         return 1;
166     }
167 
168     val = pcv;
169     for ( i = 0; i < num_desc; i++ )
170     {
171         unsigned long long sum = 0;
172 
173         printf ("%-35s ", pcd[i].name);
174 
175         for ( j = 0; j < pcd[i].nr_vals; j++ )
176             sum += val[j];
177         printf("T=%10llu ", sum);
178 
179         if ( sum && (full || (pcd[i].nr_vals <= 4)) )
180         {
181             if ( pretty && (strcmp(pcd[i].name, "hypercalls") == 0) )
182             {
183                 printf("\n");
184                 for( j = 0; j < pcd[i].nr_vals; j++ )
185                 {
186                     if ( val[j] == 0 )
187                         continue;
188                     if ( (j < 64) && hypercall_name_table[j] )
189                         strncpy(hypercall_name, hypercall_name_table[j],
190                                 sizeof(hypercall_name));
191                     else
192                         snprintf(hypercall_name, sizeof(hypercall_name), "[%d]", j);
193                     hypercall_name[sizeof(hypercall_name)-1]='\0';
194                     printf("%-35s ", hypercall_name);
195                     printf("%12u\n", (unsigned int)val[j]);
196                 }
197             }
198             else
199             {
200                 for ( j = 0; j < pcd[i].nr_vals; j++ )
201                     printf(" %10u", (unsigned int)val[j]);
202                 printf("\n");
203             }
204         }
205         else
206         {
207             printf("\n");
208         }
209 
210         val += pcd[i].nr_vals;
211     }
212 
213     xc_hypercall_buffer_free(xc_handle, pcd);
214     xc_hypercall_buffer_free(xc_handle, pcv);
215     return 0;
216 }
217