1
/* Copyright (C) 2003,2004 Andi Kleen, SuSE Labs.
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
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.
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
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. */
21
#define _LARGE_FILE_SOURCE 1
31
#include <sys/fcntl.h>
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;
38
#define err(x) perror(x),exit(1)
40
#define PERFEVTSEL0 0xc0010000
41
#define PERFEVTSEL1 0xc0010001
42
#define PERFEVTSEL2 0xc0010002
43
#define PERFEVTSEL3 0xc0010003
45
#define PERFCTR0 0xc0010004
46
#define PERFCTR1 0xc0010005
47
#define PERFCTR2 0xc0010006
48
#define PERFCTR3 0xc0010007
51
#define PERFEVTSEL_EN (1 << 22)
52
#define PERFEVTSEL_OS (1 << 17)
53
#define PERFEVTSEL_USR (1 << 16)
55
#define BASE (EVENT | PERFEVTSEL_EN | PERFEVTSEL_OS | PERFEVTSEL_USR)
68
void Vprintf(char *fmt, ...)
73
vfprintf(stderr,fmt,ap);
77
unsigned long long rdmsr(int cpu, unsigned long msr)
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));
87
void wrmsr(int cpu, unsigned long msr, unsigned long long value)
89
if (pwrite(msrfd[cpu], &value, 8, msr) != 8) {
90
fprintf(stderr, "wdmsr of %lx failed: %s\n", msr, strerror(errno));
95
int cpufilter(int cpu)
103
for (s = cfilter;;) {
104
num = strtoul(s, &end, 0);
119
void checkcounter(int cpu, int clear)
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]);
130
} else if (evtsel == (BASE | (masks[i-1] << 8))) {
131
/* everything fine */
133
Vprintf("reinit force %d\n", cpu);
134
wrmsr(cpu, PERFEVTSEL0 + i, BASE | (masks[i - 1] << 8));
137
fprintf(stderr, "perfctr %d cpu %d already used with %Lx\n",
139
fprintf(stderr, "Consider using -f if you know what you're doing.\n");
143
Vprintf("clearing %d\n", cpu);
144
wrmsr(cpu, PERFCTR0 + i, 0);
149
void setup(int clear)
155
memset(msrfd, -1, sizeof(msrfd));
156
dir = opendir("/dev/cpu");
158
err("cannot open /dev/cpu");
159
while ((d = readdir(dir)) != NULL) {
162
long cpunum = strtoul(d->d_name, &end, 0);
165
if (cpunum > MAXCPU) {
166
fprintf(stderr, "too many cpus %ld %s\n", cpunum, d->d_name);
169
if (!cpufilter(cpunum))
171
snprintf(buf, 63, "/dev/cpu/%ld/msr", cpunum);
172
msrfd[cpunum] = open64(buf, O_RDWR);
173
if (msrfd[cpunum] < 0)
176
checkcounter(cpunum, clear);
180
fprintf(stderr, "No CPU found using MSR driver.\n");
185
void printf_padded(int pad, char *fmt, ...)
190
vsnprintf(buf, pad, fmt, ap);
191
printf("%-*s", pad, buf);
195
void print_header(void)
197
printf_padded(4, "CPU ");
198
printf_padded(16, "LOCAL");
199
printf_padded(16, "LOCAL->REMOTE");
200
printf_padded(16, "REMOTE->LOCAL");
204
void print_cpu(int cpu)
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);
212
printf_padded(16, "%Lu", val);
214
printf_padded(16, "%Lu", val - lastval[i]);
226
for (cpu = 0; cpu < MAXCPU; ++cpu) {
246
FILE *f = fopen("/proc/cpuinfo", "r");
249
while (getline(&line, &size, f) > 0) {
250
if (!strncmp("vendor_id", line, 9)) {
251
if (!strstr(line, "AMD"))
254
if (!strncmp("cpu family", line, 10)) {
255
char *s = line + strcspn(line,":");
258
family = strtoul(s, NULL, 0);
264
printf("not a opteron cpu\n");
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");
285
int main(int ac, char **av)
289
while ((opt = getopt(ac,av,"ifscmaC:v")) != -1) {
321
delay = strtoul(av[optind], &end, 10);