~ubuntu-branches/ubuntu/vivid/numactl/vivid-proposed

« back to all changes in this revision

Viewing changes to numamon.c

  • Committer: Package Import Robot
  • Author(s): Daniel J Blueman
  • Date: 2015-04-08 05:30:55 UTC
  • Revision ID: package-import@ubuntu.com-20150408053055-u80t7q2kbrmzfnqt
Tags: 2.0.10-1ubuntu2
d/patches/from-git-6a7c2cf3-fix-uninitialised-mask.patch: Fix libnuma SEGV
due to uninitialised mask. (LP: #1441388)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2003,2004 Andi Kleen, SuSE Labs.
2
 
 
3
 
   numamon is free software; you can redistribute it and/or
4
 
   modify it under the terms of the GNU General Public
5
 
   License as published by the Free Software Foundation; version
6
 
   2.
7
 
 
8
 
   numamon is distributed in the hope that it will be useful,
9
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
 
   General Public License for more details.
12
 
 
13
 
   You should find a copy of v2 of the GNU General Public License somewhere
14
 
   on your Linux system; if not, write to the Free Software Foundation,
15
 
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
 
 
17
 
   Display some numa statistics collected by the CPU.
18
 
   Opteron specific. Also not reliable because the counters
19
 
   are not quite correct in hardware.  */
20
 
 
21
 
#define _LARGE_FILE_SOURCE 1
22
 
#define _GNU_SOURCE 1
23
 
#include <string.h>
24
 
#include <errno.h>
25
 
#include <stdio.h>
26
 
#include <unistd.h>
27
 
#include <dirent.h>
28
 
#include <getopt.h>
29
 
#include <stdarg.h>
30
 
#include <stdlib.h>
31
 
#include <sys/fcntl.h>
32
 
 
33
 
enum { LOCALLOCAL = 0, LOCALREMOTE = 1, REMOTELOCAL = 2 };
34
 
static int mem[] = { [LOCALLOCAL] = 0xa8, [LOCALREMOTE] = 0x98, [REMOTELOCAL] = 0x68 };
35
 
static int io[] = {  [LOCALLOCAL] = 0xa4, [LOCALREMOTE] = 0x94, [REMOTELOCAL] = 0x64 };
36
 
static int *masks = mem;
37
 
 
38
 
#define err(x) perror(x),exit(1)
39
 
 
40
 
#define PERFEVTSEL0 0xc0010000
41
 
#define PERFEVTSEL1 0xc0010001
42
 
#define PERFEVTSEL2 0xc0010002
43
 
#define PERFEVTSEL3 0xc0010003
44
 
 
45
 
#define PERFCTR0 0xc0010004
46
 
#define PERFCTR1 0xc0010005
47
 
#define PERFCTR2 0xc0010006
48
 
#define PERFCTR3 0xc0010007
49
 
 
50
 
#define EVENT 0xe9
51
 
#define PERFEVTSEL_EN (1 << 22)
52
 
#define PERFEVTSEL_OS (1 << 17)
53
 
#define PERFEVTSEL_USR (1 << 16)
54
 
 
55
 
#define BASE (EVENT | PERFEVTSEL_EN | PERFEVTSEL_OS | PERFEVTSEL_USR)
56
 
 
57
 
#define MAXCPU 8
58
 
 
59
 
int force = 0;
60
 
int msrfd[MAXCPU];
61
 
int delay;
62
 
int absolute;
63
 
char *cfilter;
64
 
int verbose;
65
 
 
66
 
void usage(void);
67
 
 
68
 
void Vprintf(char *fmt, ...)
69
 
{
70
 
        va_list ap;
71
 
        va_start(ap,fmt);
72
 
        if (verbose)
73
 
                vfprintf(stderr,fmt,ap);
74
 
        va_end(ap);
75
 
}
76
 
 
77
 
unsigned long long rdmsr(int cpu, unsigned long msr)
78
 
{
79
 
        unsigned long long val;
80
 
        if (pread(msrfd[cpu], &val, 8, msr) != 8) {
81
 
                fprintf(stderr, "rdmsr of %lx failed: %s\n", msr, strerror(errno));
82
 
                exit(1);
83
 
        }
84
 
        return val;
85
 
}
86
 
 
87
 
void wrmsr(int cpu, unsigned long msr, unsigned long long value)
88
 
{
89
 
        if (pwrite(msrfd[cpu], &value, 8, msr) != 8) {
90
 
                fprintf(stderr, "wdmsr of %lx failed: %s\n", msr, strerror(errno));
91
 
                exit(1);
92
 
        }
93
 
}
94
 
 
95
 
int cpufilter(int cpu)
96
 
{
97
 
        long num;
98
 
        char *end;
99
 
        char *s;
100
 
        
101
 
        if (!cfilter)
102
 
                return 1;       
103
 
        for (s = cfilter;;) {
104
 
                num = strtoul(s, &end, 0);
105
 
                if (end == s)
106
 
                        usage();
107
 
                if (cpu == num)
108
 
                        return 1;
109
 
                if (*end == ',')
110
 
                        s = end+1;
111
 
                else if (*end == 0)
112
 
                        break;
113
 
                else
114
 
                        usage();
115
 
        }
116
 
        return 0;
117
 
}
118
 
 
119
 
void checkcounter(int cpu, int clear)
120
 
{
121
 
        int i;
122
 
        for (i = 1; i < 4; i++) {
123
 
                int clear_this = clear;
124
 
                unsigned long long evtsel = rdmsr(cpu, PERFEVTSEL0 + i);
125
 
                Vprintf("%d: %x %Lx\n", cpu, PERFEVTSEL0 + i, evtsel);
126
 
                if (!(evtsel & PERFEVTSEL_EN)) {
127
 
                        Vprintf("reinit %d\n", cpu);
128
 
                        wrmsr(cpu, PERFEVTSEL0 + i, BASE | masks[i - 1]);
129
 
                        clear_this = 1;
130
 
                } else if (evtsel == (BASE | (masks[i-1] << 8))) {
131
 
                        /* everything fine */
132
 
                } else if (force) {
133
 
                        Vprintf("reinit force %d\n", cpu);
134
 
                        wrmsr(cpu, PERFEVTSEL0 + i, BASE | (masks[i - 1] << 8));
135
 
                        clear_this = 1;
136
 
                } else {
137
 
                        fprintf(stderr, "perfctr %d cpu %d already used with %Lx\n",
138
 
                                i, cpu, evtsel);
139
 
                        fprintf(stderr, "Consider using -f if you know what you're doing.\n");
140
 
                        exit(1);
141
 
                }
142
 
                if (clear_this) {
143
 
                        Vprintf("clearing %d\n", cpu);
144
 
                        wrmsr(cpu, PERFCTR0 + i, 0);
145
 
                }
146
 
        }
147
 
}
148
 
 
149
 
void setup(int clear)
150
 
{
151
 
        DIR *dir;
152
 
        struct dirent *d;
153
 
        int numcpus = 0;
154
 
 
155
 
        memset(msrfd, -1, sizeof(msrfd));
156
 
        dir = opendir("/dev/cpu");
157
 
        if (!dir)
158
 
                err("cannot open /dev/cpu");
159
 
        while ((d = readdir(dir)) != NULL) {
160
 
                char buf[64];
161
 
                char *end;
162
 
                long cpunum = strtoul(d->d_name, &end, 0);
163
 
                if (*end != 0)
164
 
                        continue;
165
 
                if (cpunum > MAXCPU) {
166
 
                        fprintf(stderr, "too many cpus %ld %s\n", cpunum, d->d_name);
167
 
                        continue;
168
 
                }
169
 
                if (!cpufilter(cpunum))
170
 
                        continue;
171
 
                snprintf(buf, 63, "/dev/cpu/%ld/msr", cpunum);
172
 
                msrfd[cpunum] = open64(buf, O_RDWR);
173
 
                if (msrfd[cpunum] < 0)
174
 
                        continue;
175
 
                numcpus++;
176
 
                checkcounter(cpunum, clear);
177
 
        }
178
 
        closedir(dir);          
179
 
        if (numcpus == 0) {
180
 
                fprintf(stderr, "No CPU found using MSR driver.\n");
181
 
                exit(1);
182
 
        }
183
 
}
184
 
 
185
 
void printf_padded(int pad, char *fmt, ...)
186
 
{
187
 
        char buf[pad + 1];
188
 
        va_list ap;
189
 
        va_start(ap, fmt);
190
 
        vsnprintf(buf, pad, fmt, ap);
191
 
        printf("%-*s", pad, buf);
192
 
        va_end(ap);
193
 
}
194
 
 
195
 
void print_header(void)
196
 
{
197
 
        printf_padded(4, "CPU ");
198
 
        printf_padded(16, "LOCAL");
199
 
        printf_padded(16, "LOCAL->REMOTE");
200
 
        printf_padded(16, "REMOTE->LOCAL");
201
 
        putchar('\n');
202
 
}
203
 
 
204
 
void print_cpu(int cpu)
205
 
{
206
 
        int i;
207
 
        static unsigned long long lastval[4];
208
 
        printf_padded(4, "%d", cpu);
209
 
        for (i = 1; i < 4; i++) {
210
 
                unsigned long long val = rdmsr(cpu, PERFCTR0 + i);
211
 
                if (absolute)
212
 
                        printf_padded(16, "%Lu", val);
213
 
                else
214
 
                        printf_padded(16, "%Lu", val - lastval[i]);             
215
 
                lastval[i] = val;
216
 
        }
217
 
        putchar('\n');
218
 
}
219
 
 
220
 
void dumpall(void)
221
 
{
222
 
        int cnt = 0;
223
 
        int cpu;
224
 
        print_header();
225
 
        for (;;) {
226
 
                for (cpu = 0; cpu < MAXCPU; ++cpu) {
227
 
                        if (msrfd[cpu] < 0)
228
 
                                continue;
229
 
                        print_cpu(cpu);
230
 
                }
231
 
                if (!delay)
232
 
                        break;
233
 
                sleep(delay);
234
 
                if (++cnt > 40) {
235
 
                        cnt = 0;
236
 
                        print_header();
237
 
                }
238
 
        }               
239
 
}
240
 
 
241
 
void checkk8(void)
242
 
{
243
 
        char *line = NULL;
244
 
        size_t size = 0;
245
 
        int bad = 0;
246
 
        FILE *f = fopen("/proc/cpuinfo", "r");
247
 
        if (!f)
248
 
                return; 
249
 
        while (getline(&line, &size, f) > 0) {
250
 
                if (!strncmp("vendor_id", line, 9)) {
251
 
                        if (!strstr(line, "AMD"))
252
 
                                bad++;
253
 
                }
254
 
                if (!strncmp("cpu family", line, 10)) {
255
 
                        char *s = line + strcspn(line,":");
256
 
                        int family;
257
 
                        if (*s == ':') ++s;
258
 
                        family = strtoul(s, NULL, 0);
259
 
                        if (family != 15)
260
 
                                bad++;
261
 
                }
262
 
        }
263
 
        if (bad) {
264
 
                printf("not a opteron cpu\n");
265
 
                exit(1);
266
 
        }
267
 
        free(line);
268
 
        fclose(f);
269
 
}
270
 
 
271
 
void usage(void)
272
 
{
273
 
        fprintf(stderr, "usage: numamon [args] [delay]\n");
274
 
        fprintf(stderr, "       -f forcibly overwrite counters\n");
275
 
        fprintf(stderr, "       -i count IO (default memory)\n");       
276
 
        fprintf(stderr, "       -a print absolute counter values (with delay)\n");
277
 
        fprintf(stderr, "       -s setup counters and exit\n");         
278
 
        fprintf(stderr, "       -c clear counters and exit\n");         
279
 
        fprintf(stderr, "       -m Print memory traffic (default)\n");  
280
 
        fprintf(stderr, "       -C cpu{,cpu} only print for cpus\n");
281
 
        fprintf(stderr, "       -v Be verbose\n");
282
 
        exit(1);
283
 
}
284
 
 
285
 
int main(int ac, char **av)
286
 
{
287
 
        int opt;
288
 
        checkk8();
289
 
        while ((opt = getopt(ac,av,"ifscmaC:v")) != -1) {
290
 
                switch (opt) {
291
 
                case 'f':
292
 
                        force = 1;
293
 
                        break;
294
 
                case 'c':
295
 
                        setup(1);
296
 
                        exit(0);
297
 
                case 's':
298
 
                        setup(0);
299
 
                        exit(0);
300
 
                case 'm':
301
 
                        masks = mem;
302
 
                        break;
303
 
                case 'i':
304
 
                        masks = io;
305
 
                        break;
306
 
                case 'a':
307
 
                        absolute = 1;
308
 
                        break;
309
 
                case 'C':
310
 
                        cfilter = optarg;
311
 
                        break;
312
 
                case 'v':
313
 
                        verbose = 1;
314
 
                        break;
315
 
                default:
316
 
                        usage();
317
 
                }
318
 
        }
319
 
        if (av[optind]) {
320
 
                char *end;
321
 
                delay = strtoul(av[optind], &end, 10);
322
 
                if (*end)
323
 
                        usage();
324
 
                if (av[optind+1])
325
 
                        usage();
326
 
        }
327
 
 
328
 
        setup(0);
329
 
        dumpall();
330
 
        return 0;
331
 
}