version 1.17, 2007/10/25 16:38:06 |
version 1.18, 2007/11/16 15:03:31 |
|
|
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
#include <sysexits.h> |
|
#include <unistd.h> |
#include <unistd.h> |
|
|
#include "pctrvar.h" |
#include "pctrvar.h" |
|
|
static int cflag, eflag, iflag, kflag, uflag; |
static int cflag, eflag, iflag, kflag, uflag; |
static int Mflag, Eflag, Sflag, Iflag, Aflag; |
static int Mflag, Eflag, Sflag, Iflag, Aflag; |
|
|
static int pctr_cpu_creds(void); |
static void pctr_cpu_creds(void); |
static char *pctr_fn2str(u_int32_t); |
static char *pctr_fn2str(u_int32_t); |
static void pctr_printvals(struct pctrst *); |
static void pctr_printvals(struct pctrst *); |
static int pctr_read(struct pctrst *); |
static int pctr_read(struct pctrst *); |
|
|
int ch = -1; |
int ch = -1; |
int list_mode = 0, set_mode = 0; |
int list_mode = 0, set_mode = 0; |
|
|
if (pctr_cpu_creds()) |
pctr_cpu_creds(); |
errx(1, "pctr is supported on i386 and amd64 " |
|
"architectures only"); |
|
|
|
while ((ch = getopt(argc, argv, "cef:iklm:s:t:uMESIA")) != -1) |
while ((ch = getopt(argc, argv, "AcEef:IiklMm:Ss:t:u")) != -1) |
switch (ch) { |
switch (ch) { |
case 'A': |
case 'A': |
if (Mflag || Eflag || Sflag || Iflag) |
|
errx(1, "M, E, S, I and A are mutually " |
|
"exclusive"); |
|
Aflag++; |
Aflag++; |
break; |
break; |
case 'c': |
case 'c': |
cflag++; |
cflag++; |
break; |
break; |
case 'E': |
case 'E': |
case 'I': |
Eflag++; |
case 'M': |
break; |
case 'S': |
|
if (Aflag) |
|
errx(1, "M, E, S, I and A are mutually " |
|
"exclusive"); |
|
switch (ch) { |
|
case 'E': |
|
Eflag++; |
|
break; |
|
case 'I': |
|
Iflag++; |
|
break; |
|
case 'M': |
|
Mflag++; |
|
break; |
|
case 'S': |
|
Sflag++; |
|
break; |
|
} |
|
case 'e': |
case 'e': |
eflag++; |
eflag++; |
break; |
break; |
|
|
func > PCTR_MAX_FUNCT) |
func > PCTR_MAX_FUNCT) |
errx(1, "invalid function number"); |
errx(1, "invalid function number"); |
break; |
break; |
|
case 'I': |
|
Iflag++; |
|
break; |
case 'i': |
case 'i': |
iflag++; |
iflag++; |
break; |
break; |
|
|
case 'l': |
case 'l': |
list_mode++; |
list_mode++; |
break; |
break; |
|
case 'M': |
|
Mflag++; |
|
break; |
case 'm': |
case 'm': |
if (sscanf(optarg, "%x", &masku) <= 0 || masku < 0 || |
if (sscanf(optarg, "%x", &masku) <= 0 || masku < 0 || |
masku > PCTR_MAX_UMASK) |
masku > PCTR_MAX_UMASK) |
errx(1, "invalid unit mask number"); |
errx(1, "invalid unit mask number"); |
break; |
break; |
|
case 'S': |
|
Sflag++; |
|
break; |
case 's': |
case 's': |
set_mode++; |
set_mode++; |
ctr = strtonum(optarg, 0, PCTR_NUM-1, &errstr); |
ctr = strtonum(optarg, 0, PCTR_NUM-1, &errstr); |
|
|
argc -= optind; |
argc -= optind; |
argv += optind; |
argv += optind; |
|
|
|
if (argc) |
|
usage(); |
|
|
|
if (Aflag && (Mflag || Eflag || Sflag || Iflag)) |
|
usage(); |
|
|
if (list_mode) |
if (list_mode) |
pctr_list_fnct(); |
pctr_list_fnct(); |
else if (set_mode) { |
else if (set_mode) { |
|
|
return (0); |
return (0); |
} |
} |
|
|
static int |
static void |
pctr_cpu_creds(void) |
pctr_cpu_creds(void) |
{ |
{ |
int atype; |
int atype; |
|
|
else if (strcmp(arch, "amd64") == 0) |
else if (strcmp(arch, "amd64") == 0) |
atype = ARCH_AMD64; |
atype = ARCH_AMD64; |
else |
else |
return (EX_UNAVAILABLE); /* unsupported arch */ |
errx(1, "architecture %s is not supported", arch); |
|
|
/* Get the CPU id */ |
/* Get the CPU id */ |
mib[0] = CTL_MACHDEP; |
mib[0] = CTL_MACHDEP; |
|
|
tsc_avail = 1; |
tsc_avail = 1; |
break; |
break; |
} |
} |
return (0); |
|
} |
} |
|
|
static __inline int |
static __inline int |
|
|
printf(" (ctr0 only)"); |
printf(" (ctr0 only)"); |
else if (cfnp->flags & CFL_C1) |
else if (cfnp->flags & CFL_C1) |
printf(" (ctr1 only)"); |
printf(" (ctr1 only)"); |
|
if (cfnp->flags & CFL_UM) |
|
printf(" (needs unit mask)"); |
printf("\n"); |
printf("\n"); |
if (cfnp->desc) |
if (cfnp->desc) |
pctr_printdesc(cfnp->desc); |
pctr_printdesc(cfnp->desc); |
|
|
switch (cpu_type) { |
switch (cpu_type) { |
case CPU_P5: |
case CPU_P5: |
if (ctr >= PCTR_INTEL_NUM) |
if (ctr >= PCTR_INTEL_NUM) |
return (EX_DATAERR); |
errx(1, "only %d counters are supported", |
|
PCTR_INTEL_NUM); |
if (cflag) |
if (cflag) |
val |= P5CTR_C; |
val |= P5CTR_C; |
if (kflag) |
if (kflag) |
|
|
if (cpu_type == CPU_CORE) |
if (cpu_type == CPU_CORE) |
cfnp = corefn; |
cfnp = corefn; |
if (ctr >= PCTR_INTEL_NUM) |
if (ctr >= PCTR_INTEL_NUM) |
return (EX_DATAERR); |
errx(1, "only %d counters are supported", |
|
PCTR_INTEL_NUM); |
if (func && (ind = pctr_ctrfn_index(cfnp, func)) < 0) |
if (func && (ind = pctr_ctrfn_index(cfnp, func)) < 0) |
return (EX_DATAERR); |
errx(1, "function %02x is not supported", func); |
if (func && cfnp[ind].flags & CFL_SA) |
if (func && (cfnp[ind].flags & CFL_SA)) |
val |= PCTR_UM_A; |
val |= PCTR_UM_A; |
if (Mflag && cfnp[ind].flags & CFL_MESI) |
if (func && (cfnp[ind].flags & CFL_MESI)) { |
val |= PCTR_UM_M; |
if (Mflag) |
if (Eflag && cfnp[ind].flags & CFL_MESI) |
val |= PCTR_UM_M; |
val |= PCTR_UM_E; |
if (Eflag) |
if (Sflag && cfnp[ind].flags & CFL_MESI) |
val |= PCTR_UM_E; |
val |= PCTR_UM_S; |
if (Sflag) |
if (Iflag && cfnp[ind].flags & CFL_MESI) |
val |= PCTR_UM_S; |
val |= PCTR_UM_I; |
if (Iflag) |
if (func && (cfnp[ind].flags & CFL_MESI) && |
val |= PCTR_UM_I; |
(!Mflag || !Eflag || !Sflag || !Iflag)) |
if (!Mflag || !Eflag || !Sflag || !Iflag) |
val |= PCTR_UM_MESI; |
val |= PCTR_UM_MESI; |
|
} |
if (func && (cfnp[ind].flags & CFL_ED)) |
if (func && (cfnp[ind].flags & CFL_ED)) |
val |= PCTR_E; |
val |= PCTR_E; |
|
if (func && (cfnp[ind].flags & CFL_UM) && !masku) |
|
errx(1, "function %02x needs unit mask specification", |
|
func); |
case CPU_AMD: |
case CPU_AMD: |
if (cpu_type == CPU_AMD && func && |
if (cpu_type == CPU_AMD && func && |
((ind = pctr_ctrfn_index(amdfn, func)) < 0)) |
((ind = pctr_ctrfn_index(amdfn, func)) < 0)) |
return (EX_DATAERR); |
errx(1, "function %02x is not supported", func); |
if (ctr >= PCTR_AMD_NUM) |
if (ctr >= PCTR_AMD_NUM) |
return (EX_DATAERR); |
errx(1, "only %d counters are supported", |
|
PCTR_AMD_NUM); |
if (eflag) |
if (eflag) |
val |= PCTR_E; |
val |= PCTR_E; |
if (iflag) |
if (iflag) |
|
|
} |
} |
|
|
fprintf(stderr, "%s: %s\n", __progname, usg); |
fprintf(stderr, "%s: %s\n", __progname, usg); |
exit(EX_USAGE); |
exit(1); |
} |
} |