From patchwork Fri Nov 8 16:50:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 11235277 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 221191390 for ; Fri, 8 Nov 2019 16:51:05 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 097422178F for ; Fri, 8 Nov 2019 16:51:05 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 097422178F Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=chris-wilson.co.uk Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 87E7D6FA0E; Fri, 8 Nov 2019 16:51:04 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0CF426FA0E for ; Fri, 8 Nov 2019 16:51:02 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 19131622-1500050 for multiple; Fri, 08 Nov 2019 16:50:47 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Fri, 8 Nov 2019 16:50:46 +0000 Message-Id: <20191108165046.25545-1-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.24.0 MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t] tools: Add a simple rapl wrapper X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Run a command; print how much power rapl reported the system using. Signed-off-by: Chris Wilson Cc: Andi Shyti Cc: Tvrtko Ursulin --- tools/igt_rapl.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++ tools/meson.build | 5 ++ 2 files changed, 207 insertions(+) create mode 100644 tools/igt_rapl.c diff --git a/tools/igt_rapl.c b/tools/igt_rapl.c new file mode 100644 index 000000000..8d985681f --- /dev/null +++ b/tools/igt_rapl.c @@ -0,0 +1,202 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "igt_perf.h" + +struct parse { + uint64_t config, type; +}; + +struct rapl { + const char *name; + double scale; + int fd; +}; + +__attribute__((format(scanf,3,4))) +static int dir_scanf(int dir, const char *attr, const char *fmt, ...) +{ + FILE *file; + int fd; + int ret = -1; + + fd = openat(dir, attr, O_RDONLY); + if (fd < 0) + return -1; + + file = fdopen(fd, "r"); + if (file) { + va_list ap; + + va_start(ap, fmt); + ret = vfscanf(file, fmt, ap); + va_end(ap); + + fclose(file); + } else { + close(fd); + } + + return ret; +} + +static int rapl_parse(struct parse *r, const char *str, double *scale) +{ + locale_t locale, oldlocale; + bool result = true; + char buf[128]; + int dir; + + memset(r, 0, sizeof(*r)); + + dir = open("/sys/devices/power", O_RDONLY); + if (dir < 0) + return -errno; + + /* Replace user environment with plain C to match kernel format */ + locale = newlocale(LC_ALL, "C", 0); + oldlocale = uselocale(locale); + + result &= dir_scanf(dir, "type", "%"PRIu64, &r->type) == 1; + + snprintf(buf, sizeof(buf), "events/energy-%s", str); + result &= dir_scanf(dir, buf, "event=%"PRIx64, &r->config) == 1; + + snprintf(buf, sizeof(buf), "events/energy-%s.scale", str); + result &= dir_scanf(dir, buf, "%lf", scale) == 1; + + uselocale(oldlocale); + freelocale(locale); + + close(dir); + + if (!result) + return -EINVAL; + + if (isnan(*scale) || !*scale) + return -ERANGE; + + return 0; +} + +static int rapl_open(int fd, const char *domain, double *scale) +{ + struct parse r; + int err; + + err = rapl_parse(&r, domain, scale); + if (err < 0) + goto err; + + return igt_perf_open_group(r.type, r.config, fd); + +err: + errno = 0; + return err; +} + +static int runit(struct rapl *r, int count, int argc, char **argv) +{ + int ret, status; + + switch (ret = fork()) { + case -1: return errno; + case 0: /* child */ + while (count--) + close(r[count].fd); + execvp(argv[0], argv); + exit(1); + break; + default: /* parent */ + if (wait(&status) < 0) { + kill(ret, SIGKILL); + return errno; + } + + return status; + } +} + +static inline double power_J(const uint64_t p0, + const uint64_t p1, + const double scale) +{ + return (p1 - p0) * scale; +} + +static inline double power_s(const uint64_t t0, + const uint64_t t1) +{ + return (t1 - t0) * 1e-9; +} + +static inline double power_W(const uint64_t *s0, + const uint64_t *s1, + int idx, + const double scale) +{ + return power_J(s0[idx+2], s1[idx+2], scale) / power_s(s0[1], s1[1]); +} + +static int rapl_read(int fd, uint64_t *data, int count) +{ + if (read(fd, data, (count + 2) * sizeof(data[0])) < 0) + return -errno; + + return 0; +} + +int main(int argc, char **argv) +{ + static const char *domains[] = { "gpu", "pkg", /* "ram" */}; + uint64_t before[8] = {}, after[8] = {}; + struct rapl r[4]; + int count = 0; + int ret; + int i; + + r[0].fd = -1; + for (i = 0; i < sizeof(domains)/sizeof(*domains); i++) { + r[count].fd = rapl_open(r[0].fd, domains[i], &r[count].scale); + if (r[count].fd < 0) + continue; + + r[count++].name = domains[i]; + } + if (!count) { + fprintf(stderr, "Unable to open any rapl power domains\n"); + return 1; + } + + ret = rapl_read(r[0].fd, before, count); + if (ret < 0) { + fprintf(stderr, "Unable to read perf event\n"); + return 1; + } + + ret = runit(r, count, argc - 1, argv + 1); + + ret = rapl_read(r[0].fd, after, count); + if (ret < 0) { + fprintf(stderr, "Unable to read perf event\n"); + return 1; + } + + printf("time:%.2fms", power_s(before[1], after[1]) * 1e3); + for (i = 0; i < count; i++) + printf(", %s:%.2fms", + r[i].name, power_W(before, after, i, r[i].scale) * 1e3); + printf("\n"); + + return ret; +} diff --git a/tools/meson.build b/tools/meson.build index eecb122bc..5b462c131 100644 --- a/tools/meson.build +++ b/tools/meson.build @@ -100,6 +100,11 @@ executable('intel_gpu_top', 'intel_gpu_top.c', install_rpath : bindir_rpathdir, dependencies : lib_igt_perf) +executable('igt_rapl', 'igt_rapl.c', + install : true, + install_rpath : bindir_rpathdir, + dependencies : lib_igt_perf) + executable('amd_hdmi_compliance', 'amd_hdmi_compliance.c', dependencies : [tool_deps], install_rpath : bindir_rpathdir,