Index: head/sysutils/turbostat/Makefile =================================================================== --- head/sysutils/turbostat/Makefile (revision 476319) +++ head/sysutils/turbostat/Makefile (revision 476320) @@ -1,37 +1,38 @@ # $FreeBSD$ PORTNAME= turbostat PORTVERSION= 4.17 # Turbostat itself has a version, but we don't bother +PORTREVISION= 1 CATEGORIES= sysutils MASTER_SITES= https://raw.githubusercontent.com/torvalds/linux/v${PORTVERSION}/tools/power/x86/turbostat/ \ https://raw.githubusercontent.com/torvalds/linux/v${PORTVERSION}/arch/x86/include/asm/ DISTFILES= ${PORTNAME}.c ${PORTNAME}.8 msr-index.h intel-family.h DIST_SUBDIR= ${PORTNAME}-${PORTVERSION} MAINTAINER= d.scott.phillips@intel.com COMMENT= Report power statistics for Intel CPUs LICENSE= GPLv2 ONLY_FOR_ARCHS= amd64 NO_WRKSUBDIR=yes PLIST_FILES= sbin/turbostat man/man8/turbostat.8.gz post-extract: do-extract: @${MKDIR} ${WRKSRC} ${CP} ${_DISTDIR}/${PORTNAME}.c ${WRKSRC} ${CP} ${_DISTDIR}/${PORTNAME}.8 ${WRKSRC} ${CP} ${_DISTDIR}/msr-index.h ${WRKSRC} ${CP} ${_DISTDIR}/intel-family.h ${WRKSRC} do-build: cd ${WRKSRC} && ${CC} ${CFLAGS} -DMSRHEADER='"msr-index.h"' -DINTEL_FAMILY_HEADER='"intel-family.h"' -o ${PORTNAME} ${PORTNAME}.c -lutil do-install: ${INSTALL_PROGRAM} ${WRKSRC}/${PORTNAME} ${STAGEDIR}${PREFIX}/sbin ${INSTALL_MAN} ${WRKSRC}/${PORTNAME}.8 ${STAGEDIR}${MANPREFIX}/man/man8 .include Index: head/sysutils/turbostat/files/patch-turbostat.c =================================================================== --- head/sysutils/turbostat/files/patch-turbostat.c (revision 476319) +++ head/sysutils/turbostat/files/patch-turbostat.c (revision 476320) @@ -1,446 +1,466 @@ ---- turbostat.c.orig 2018-07-23 18:26:58 UTC +--- turbostat.c.orig 2018-07-31 20:42:12 UTC +++ turbostat.c -@@ -41,7 +41,30 @@ +@@ -41,7 +41,31 @@ #include #include #include +#ifdef __FreeBSD__ +#include ++#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define cpu_set_t cpuset_t + +#define CPU_ALLOC(_ign) ({(cpuset_t*)malloc(sizeof(cpuset_t));}) +#define CPU_ALLOC_SIZE(_ign) sizeof(cpuset_t) +#define CPU_FREE free +#define CPU_ISSET_S(cpu, _ign, set) (set && CPU_ISSET(cpu, set)) +#define CPU_SET_S(cpu, _ign, set) CPU_SET(cpu, set) +#define CPU_ZERO_S(_ign, set) CPU_ZERO(set) +#define sched_setaffinity(_x, _y, set) cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(cpuset_t), set) + +#else #include +#endif #include char *proc_stat = "/proc/stat"; -@@ -132,7 +155,9 @@ unsigned int has_misc_feature_control; +@@ -132,7 +156,9 @@ unsigned int has_misc_feature_control; #define RAPL_CORES (RAPL_CORES_ENERGY_STATUS | RAPL_CORES_POWER_LIMIT) #define TJMAX_DEFAULT 100 +#ifndef __FreeBSD__ #define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif /* * buffer size used by sscanf() for added column names -@@ -309,6 +334,7 @@ int cpu_migrate(int cpu) +@@ -309,6 +335,7 @@ int cpu_migrate(int cpu) else return 0; } + int get_msr_fd(int cpu) { char pathname[32]; -@@ -319,18 +345,39 @@ int get_msr_fd(int cpu) +@@ -319,18 +346,39 @@ int get_msr_fd(int cpu) if (fd) return fd; +#ifdef __FreeBSD__ + sprintf(pathname, "/dev/cpuctl%d", cpu); +#else sprintf(pathname, "/dev/cpu/%d/msr", cpu); +#endif fd = open(pathname, O_RDONLY); if (fd < 0) - err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname); + err(-1, "%s open failed, try chown or chmod +r " +#ifdef __FreeBSD__ + "/dev/cpuctl*" +#else + "/dev/cpu/*/msr" +#endif + ", or run as root", pathname); fd_percpu[cpu] = fd; return fd; } +#ifdef __FreeBSD__ int get_msr(int cpu, off_t offset, unsigned long long *msr) { + cpuctl_msr_args_t args; + args.msr = offset; + if (ioctl(get_msr_fd(cpu), CPUCTL_RDMSR, &args)) + err(1, "cpu%d: msr offset 0x%llx read failed", cpu, (unsigned long long)offset); + *msr = args.data; + return 0; +} +#else +int get_msr(int cpu, off_t offset, unsigned long long *msr) +{ ssize_t retval; retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset); -@@ -340,6 +387,7 @@ int get_msr(int cpu, off_t offset, unsigned long long +@@ -340,6 +388,7 @@ int get_msr(int cpu, off_t offset, unsigned long long return 0; } +#endif /* * Each string in this array is compared in --show and --hide cmdline. -@@ -2239,6 +2287,158 @@ int parse_int_file(const char *fmt, ...) +@@ -2239,6 +2288,173 @@ int parse_int_file(const char *fmt, ...) return value; } +#ifdef __FreeBSD__ +static int ncpus; +struct cpuset_list { + cpuset_t *sets; + size_t len; + size_t cap; +}; +static struct cpuset_list packages = {0}; +static struct cpuset_list cores = {0}; + +static void cpuset_list_ensure_space(struct cpuset_list *list) { + if (list->cap > list->len) + return; + + if (list->cap) + list->cap *= 2; + else + list->cap = 2; + -+ list->sets = reallocarray(list->sets, list->cap, sizeof(cpuset_t)); ++ list->sets = realloc(list->sets, list->cap * sizeof(cpuset_t)); +} + +static cpuset_t parse_cpu_mask(const char *i) { + int count, mask_offset; + i = strstr(i, "mask=\""); + if (!i) + errx(1, "failed to parse topology_spec"); + i += sizeof("mask=\"") - 1; + + char sep; + cpuset_t out; + uint64_t *_out = (uint64_t *)&out; + CPU_ZERO(&out); + + do { + int len; + if (sscanf(i, "%lx%c%n", _out, &sep, &len) != 2) + errx(1, "failed to parse topology_spec"); + _out++; + i += len; + } while (sep == ','); + + return out; +} + +static void read_topology_spec(void) +{ + char spec[16384]; + size_t sz = sizeof(spec) - 1; + char *i; + + if (sysctlbyname("kern.sched.topology_spec", spec, &sz, NULL, 0)) + err(1, "sysctl: kern.sched.topology_spec: failed"); + spec[sizeof(spec) - 1] = '\0'; + + /* Skip the entire system entry. */ + i = strstr(spec, " intr_map_len) + return; + + if (intr_map_cap) + intr_map_cap *= 2; + else + intr_map_cap = 2; + -+ intr_map = reallocarray(intr_map, intr_map_cap, sizeof(*intr_map)); ++ intr_map = realloc(intr_map, intr_map_cap * sizeof(*intr_map)); +} + +static void init_intr_map(void) +{ + size_t sz = 0; -+ if (sysctlbyname("hw.intrs", NULL, &sz, NULL, 0)) -+ err(1, "sysctl: hw.intrs: failed"); ++ if (sysctlbyname("hw.intrs", NULL, &sz, NULL, 0)) { ++ warn("sysctl: hw.intrs: per-cpu interrupt data will be unavailable"); ++ return; ++ } + char *intrs = alloca(sz); -+ if (sysctlbyname("hw.intrs", intrs, &sz, NULL, 0)) -+ err(1, "sysctl: hw.intrs: failed"); ++ if (sysctlbyname("hw.intrs", intrs, &sz, NULL, 0)) { ++ warn("sysctl: hw.intrs: per-cpu interrupt data will be unavailable"); ++ return; ++ } + + char *i = intrs; + char *j; + while ((j = strstr(i, "@cpu")) != NULL) { + char *k; + for (k = j; k > i && *k != ':'; k--) + ; + if (*k != ':') + errx(1, "init_intr_map: parse failed"); + k++; + uint64_t intr_num; + if (sscanf(k, "%ld", &intr_num) != 1) + errx(1, "init_intr_map: parse failed"); + j += 4; + uint64_t cpu_num; + if (sscanf(j, "%ld", &cpu_num) != 1) + errx(1, "init_intr_map: parse failed"); + ensure_intr_map(); + intr_map[intr_map_len].intr_num = intr_num; + intr_map[intr_map_len].cpu_num = cpu_num; + intr_map_len++; + + i = j; + } +} + +static int snapshot_proc_interrupts(void) +{ + if (!intr_map) + init_intr_map(); + + size_t sz = 0; + if (sysctlbyname("hw.intrcnt", NULL, &sz, NULL, 0)) + err(1, "sysctl: hw.intrcnt: failed"); + uint64_t *intrcnt = alloca(sz); + if (sysctlbyname("hw.intrcnt", intrcnt, &sz, NULL, 0)) + err(1, "sysctl: hw.intrcnt: failed"); + + for (int i = 0; i < topo.num_cpus; i++) + irqs_per_cpu[i] = 0; + for (int i = 0; i < intr_map_len; i++) + irqs_per_cpu[intr_map[i].cpu_num] += intrcnt[intr_map[i].intr_num]; + + return 0; +} +#else /* * snapshot_proc_interrupts() * -@@ -2491,6 +2784,8 @@ int snapshot_proc_interrupts(void) +@@ -2491,6 +2804,8 @@ int snapshot_proc_interrupts(void) } return 0; } +#endif + /* * snapshot_gfx_rc6_ms() * -@@ -2629,6 +2924,18 @@ restart: +@@ -2629,6 +2944,18 @@ restart: } } +#ifdef __FreeBSD__ +#define check_dev_msr() + +void check_permissions() +{ + if (eaccess("/dev/cpuctl0", F_OK)) + err(errno, "/dev/cpuctl0 missing, kldload cpuctl"); + if (eaccess("/dev/cpuctl0", R_OK)) + err(errno, "cannot read /dev/cpuctl0, (run as root?)"); +} + +#else void check_dev_msr() { struct stat sb; -@@ -2677,6 +2984,7 @@ void check_permissions() +@@ -2677,6 +3004,7 @@ void check_permissions() if (do_exit) exit(-6); } +#endif /* * NHM adds support for additional MSRs: -@@ -4520,8 +4828,21 @@ void setup_all_buffers(void) +@@ -4520,8 +4848,21 @@ void setup_all_buffers(void) for_all_proc_cpus(initialize_counters); } +#ifdef __FreeBSD__ void set_base_cpu(void) { + struct kinfo_proc *proc = kinfo_getproc(getpid()); + if (!proc || proc->ki_oncpu == NOCPU) + err(-ENODEV, "Failed to lookup curcpu"); + base_cpu = proc->ki_oncpu; + free(proc); + + if (debug > 1) + fprintf(outf, "base_cpu = %d\n", base_cpu); +} +#else +void set_base_cpu(void) +{ base_cpu = sched_getcpu(); if (base_cpu < 0) err(-ENODEV, "No valid cpus found"); -@@ -4529,6 +4850,7 @@ void set_base_cpu(void) +@@ -4529,6 +4870,7 @@ void set_base_cpu(void) if (debug > 1) fprintf(outf, "base_cpu = %d\n", base_cpu); } +#endif void turbostat_init() {