From patchwork Thu Dec 17 10:38:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tvrtko Ursulin X-Patchwork-Id: 11979543 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.9 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,HK_RANDOM_FROM,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 08CA4C4361B for ; Thu, 17 Dec 2020 10:38:27 +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 8C3F12388E for ; Thu, 17 Dec 2020 10:38:26 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8C3F12388E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com 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 EE0696E249; Thu, 17 Dec 2020 10:38:25 +0000 (UTC) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by gabe.freedesktop.org (Postfix) with ESMTPS id 386C46E249; Thu, 17 Dec 2020 10:38:25 +0000 (UTC) IronPort-SDR: ZVEYgzrYypuVLzhI1rsWp9Gi/KlXSkpV1nFmfn6yV0qtp9eS0Bt/vubXHqlX8j5c+5jy5L511V CkXBGMetizBQ== X-IronPort-AV: E=McAfee;i="6000,8403,9837"; a="171725556" X-IronPort-AV: E=Sophos;i="5.78,426,1599548400"; d="scan'208";a="171725556" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Dec 2020 02:38:23 -0800 IronPort-SDR: yV/EJGGaxbyx60n6ap8x+rFod42eb4Xj+Nnz9t9LUcf7IBZVg9huFonVtlTDStmEnCMxj9rRMX hRIPrjKQHTJg== X-IronPort-AV: E=Sophos;i="5.78,426,1599548400"; d="scan'208";a="339243357" Received: from acherneg-mobl.ger.corp.intel.com (HELO localhost.localdomain) ([10.214.210.48]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Dec 2020 02:38:22 -0800 From: Tvrtko Ursulin To: igt-dev@lists.freedesktop.org Date: Thu, 17 Dec 2020 10:38:10 +0000 Message-Id: <20201217103812.1174024-1-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 1/3] intel_gpu_top: Support exiting the tool by pressing 'q' X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Intel-gfx@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Tvrtko Ursulin Analoguous to top(1) we can enable the user to exit from the tool by pressing 'q' on the console. v2: * Fix sleep period with closed stdin. (Chris) Signed-off-by: Tvrtko Ursulin --- man/intel_gpu_top.rst | 6 ++++ tools/intel_gpu_top.c | 80 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst index 5552e9699d26..2e0c3a05acc1 100644 --- a/man/intel_gpu_top.rst +++ b/man/intel_gpu_top.rst @@ -48,6 +48,12 @@ OPTIONS -d Select a specific GPU using supported filter. +RUNTIME CONTROL +=============== + +Supported keys: + + 'q' Exit from the tool. DEVICE SELECTION ================ diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c index dbd353673e55..46221c9543eb 100644 --- a/tools/intel_gpu_top.c +++ b/tools/intel_gpu_top.c @@ -23,24 +23,26 @@ #include "igt_device_scan.h" -#include -#include -#include -#include #include -#include #include -#include -#include -#include +#include +#include #include #include -#include -#include -#include -#include #include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "igt_perf.h" @@ -1246,6 +1248,54 @@ static char *tr_pmu_name(struct igt_device_card *card) return device; } +static void interactive_stdin(void) +{ + struct termios termios = { }; + int ret; + + ret = fcntl(0, F_GETFL, NULL); + ret |= O_NONBLOCK; + ret = fcntl(0, F_SETFL, ret); + assert(ret == 0); + + ret = tcgetattr(0, &termios); + assert(ret == 0); + + termios.c_lflag &= ~ICANON; + termios.c_cc[VMIN] = 1; + termios.c_cc[VTIME] = 0; /* Deciseconds only - we'll use poll. */ + + ret = tcsetattr(0, TCSAFLUSH, &termios); + assert(ret == 0); +} + +static void process_stdin(unsigned int timeout_us) +{ + struct pollfd p = { .fd = 0, .events = POLLIN }; + int ret; + + ret = poll(&p, 1, timeout_us / 1000); + if (ret <= 0) { + if (ret < 0) + stop_top = true; + return; + } + + for (;;) { + char c; + + ret = read(0, &c, 1); + if (ret <= 0) + break; + + switch (c) { + case 'q': + stop_top = true; + break; + }; + } +} + int main(int argc, char **argv) { unsigned int period_us = DEFAULT_PERIOD_MS * 1000; @@ -1315,6 +1365,7 @@ int main(int argc, char **argv) switch (output_mode) { case INTERACTIVE: pops = &term_pops; + interactive_stdin(); break; case STDOUT: pops = &stdout_pops; @@ -1427,7 +1478,10 @@ int main(int argc, char **argv) if (stop_top) break; - usleep(period_us); + if (output_mode == INTERACTIVE) + process_stdin(period_us); + else + usleep(period_us); } free(codename); From patchwork Thu Dec 17 10:38:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tvrtko Ursulin X-Patchwork-Id: 11979547 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.9 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,HK_RANDOM_FROM,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A34EFC2BB48 for ; Thu, 17 Dec 2020 10:38:31 +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 46D512388E for ; Thu, 17 Dec 2020 10:38:31 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 46D512388E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com 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 AB6AE6E28B; Thu, 17 Dec 2020 10:38:30 +0000 (UTC) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by gabe.freedesktop.org (Postfix) with ESMTPS id 751E06E25B; Thu, 17 Dec 2020 10:38:26 +0000 (UTC) IronPort-SDR: b5WCNryenhTbFaHHMGLetRGh0S88JAn3GMpxTDuQQrcg1ZNXERDdHOMgt4E1yYOI5x8bz8kDCP nKLFESzDsJyg== X-IronPort-AV: E=McAfee;i="6000,8403,9837"; a="171725563" X-IronPort-AV: E=Sophos;i="5.78,426,1599548400"; d="scan'208";a="171725563" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Dec 2020 02:38:26 -0800 IronPort-SDR: i5Msx/fy1+lm7BmPfxOvRVUMdJ0Zprn+8r77C2huB6iArN3rdRakIneZPh1Oyc+OJRN5hwPUA4 Va06jHLCHANQ== X-IronPort-AV: E=Sophos;i="5.78,426,1599548400"; d="scan'208";a="339243373" Received: from acherneg-mobl.ger.corp.intel.com (HELO localhost.localdomain) ([10.214.210.48]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Dec 2020 02:38:24 -0800 From: Tvrtko Ursulin To: igt-dev@lists.freedesktop.org Date: Thu, 17 Dec 2020 10:38:11 +0000 Message-Id: <20201217103812.1174024-2-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201217103812.1174024-1-tvrtko.ursulin@linux.intel.com> References: <20201217103812.1174024-1-tvrtko.ursulin@linux.intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 2/3] intel_gpu_top: Aggregate engine busyness per class X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Intel-gfx@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Tvrtko Ursulin Similarly to how top(1) handles SMP, we can default to showing engines of a same class as a single bar graph entry. To achieve this a little bit of hackery is employed. PMU sampling is left as is and only at the presentation layer we create a fake set of engines, one for each class, summing and normalizing the load respectively. v2: * Fix building the aggregated engines. * Tidy static variable handling. Signed-off-by: Tvrtko Ursulin --- man/intel_gpu_top.rst | 1 + tools/intel_gpu_top.c | 209 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 197 insertions(+), 13 deletions(-) diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst index 2e0c3a05acc1..35ab10da9bb4 100644 --- a/man/intel_gpu_top.rst +++ b/man/intel_gpu_top.rst @@ -54,6 +54,7 @@ RUNTIME CONTROL Supported keys: 'q' Exit from the tool. + '1' Toggle between aggregated engine class and physical engine mode. DEVICE SELECTION ================ diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c index 46221c9543eb..d1149eb8e14d 100644 --- a/tools/intel_gpu_top.c +++ b/tools/intel_gpu_top.c @@ -76,8 +76,16 @@ struct engine { struct pmu_counter sema; }; +struct engine_class { + unsigned int class; + const char *name; + unsigned int num_engines; +}; + struct engines { unsigned int num_engines; + unsigned int num_classes; + struct engine_class *class; unsigned int num_counters; DIR *root; int fd; @@ -1118,6 +1126,8 @@ print_imc(struct engines *engines, double t, int lines, int con_w, int con_h) return lines; } +static bool class_view; + static int print_engines_header(struct engines *engines, double t, int lines, int con_w, int con_h) @@ -1133,8 +1143,13 @@ print_engines_header(struct engines *engines, double t, pops->open_struct("engines"); if (output_mode == INTERACTIVE) { - const char *a = " ENGINE BUSY "; const char *b = " MI_SEMA MI_WAIT"; + const char *a; + + if (class_view) + a = " ENGINES BUSY "; + else + a = " ENGINE BUSY "; printf("\033[7m%s%*s%s\033[0m\n", a, (int)(con_w - 1 - strlen(a) - strlen(b)), @@ -1214,6 +1229,181 @@ print_engines_footer(struct engines *engines, double t, return lines; } +static int class_cmp(const void *_a, const void *_b) +{ + const struct engine_class *a = _a; + const struct engine_class *b = _b; + + return a->class - b->class; +} + +static void init_engine_classes(struct engines *engines) +{ + struct engine_class *classes; + unsigned int i, num; + int max = -1; + + for (i = 0; i < engines->num_engines; i++) { + struct engine *engine = engine_ptr(engines, i); + + if ((int)engine->class > max) + max = engine->class; + } + assert(max >= 0); + + num = max + 1; + + classes = calloc(num, sizeof(*classes)); + assert(classes); + + for (i = 0; i < engines->num_engines; i++) { + struct engine *engine = engine_ptr(engines, i); + + classes[engine->class].num_engines++; + } + + for (i = 0; i < num; i++) { + classes[i].class = i; + classes[i].name = class_display_name(i); + } + + qsort(classes, num, sizeof(*classes), class_cmp); + + engines->num_classes = num; + engines->class = classes; +} + +static void __pmu_sum(struct pmu_pair *dst, struct pmu_pair *src) +{ + dst->prev += src->prev; + dst->cur += src->cur; +} + +static void __pmu_normalize(struct pmu_pair *val, unsigned int n) +{ + val->prev /= n; + val->cur /= n; +} + +static struct engines *init_class_engines(struct engines *engines) +{ + unsigned int num_present; + struct engines *classes; + unsigned int i, j, k; + + init_engine_classes(engines); + + num_present = 0; /* Classes with engines. */ + for (i = 0; i < engines->num_classes; i++) { + if (engines->class[i].num_engines) + num_present++; + } + + classes = calloc(1, sizeof(struct engines) + + num_present * sizeof(struct engine)); + assert(classes); + + classes->num_engines = num_present; + classes->num_classes = engines->num_classes; + classes->class = engines->class; + + j = 0; + for (i = 0; i < engines->num_classes; i++) { + struct engine *engine = engine_ptr(classes, j); + + /* Skip classes with no engines. */ + if (!engines->class[i].num_engines) + continue; + + assert(j < num_present); + + engine->class = i; + engine->instance = -1; + + engine->display_name = strdup(class_display_name(i)); + assert(engine->display_name); + engine->short_name = strdup(class_short_name(i)); + assert(engine->short_name); + + /* + * Copy over pmu metadata from one real engine of the same + * class. + */ + for (k = 0; k < engines->num_engines; k++) { + struct engine *e = engine_ptr(engines, k); + + if (e->class == i) { + engine->num_counters = e->num_counters; + engine->busy = e->busy; + engine->sema = e->sema; + engine->wait = e->wait; + break; + } + } + + j++; /* Next "class engine" to populate. */ + } + + return classes; +} + +static struct engines *update_class_engines(struct engines *engines) +{ + static struct engines *classes; + unsigned int i, j; + + if (!classes) + classes = init_class_engines(engines); + + for (i = 0; i < classes->num_engines; i++) { + struct engine *engine = engine_ptr(classes, i); + unsigned int num_engines = + classes->class[engine->class].num_engines; + + assert(num_engines); + + memset(&engine->busy.val, 0, sizeof(engine->busy.val)); + memset(&engine->sema.val, 0, sizeof(engine->sema.val)); + memset(&engine->wait.val, 0, sizeof(engine->wait.val)); + + for (j = 0; j < engines->num_engines; j++) { + struct engine *e = engine_ptr(engines, j); + + if (e->class == engine->class) { + __pmu_sum(&engine->busy.val, &e->busy.val); + __pmu_sum(&engine->sema.val, &e->sema.val); + __pmu_sum(&engine->wait.val, &e->wait.val); + } + } + + __pmu_normalize(&engine->busy.val, num_engines); + __pmu_normalize(&engine->sema.val, num_engines); + __pmu_normalize(&engine->wait.val, num_engines); + } + + return classes; +} + +static int +print_engines(struct engines *engines, double t, int lines, int w, int h) +{ + struct engines *show; + + if (class_view) + show = update_class_engines(engines); + else + show = engines; + + lines = print_engines_header(show, t, lines, w, h); + + for (unsigned int i = 0; i < show->num_engines && lines < h; i++) + lines = print_engine(show, i, t, lines, w, h); + + lines = print_engines_footer(show, t, lines, w, h); + + return lines; +} + static bool stop_top; static void sigint_handler(int sig) @@ -1292,6 +1482,9 @@ static void process_stdin(unsigned int timeout_us) case 'q': stop_top = true; break; + case '1': + class_view ^= true; + break; }; } } @@ -1302,7 +1495,6 @@ int main(int argc, char **argv) int con_w = -1, con_h = -1; char *output_path = NULL; struct engines *engines; - unsigned int i; int ret = 0, ch; bool list_device = false; char *pmu_device, *opt_device = NULL; @@ -1366,6 +1558,7 @@ int main(int argc, char **argv) case INTERACTIVE: pops = &term_pops; interactive_stdin(); + class_view = true; break; case STDOUT: pops = &stdout_pops; @@ -1462,17 +1655,7 @@ int main(int argc, char **argv) lines = print_imc(engines, t, lines, con_w, con_h); - lines = print_engines_header(engines, t, lines, con_w, - con_h); - - for (i = 0; - i < engines->num_engines && lines < con_h; - i++) - lines = print_engine(engines, i, t, lines, - con_w, con_h); - - lines = print_engines_footer(engines, t, lines, con_w, - con_h); + lines = print_engines(engines, t, lines, con_w, con_h); } if (stop_top) From patchwork Thu Dec 17 10:38:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tvrtko Ursulin X-Patchwork-Id: 11979545 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.9 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,HK_RANDOM_FROM,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B6DA0C4361B for ; Thu, 17 Dec 2020 10:38:30 +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 422A42388E for ; Thu, 17 Dec 2020 10:38:30 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 422A42388E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com 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 87EFF6E25B; Thu, 17 Dec 2020 10:38:29 +0000 (UTC) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by gabe.freedesktop.org (Postfix) with ESMTPS id 959EC6E25B; Thu, 17 Dec 2020 10:38:28 +0000 (UTC) IronPort-SDR: d/1zEPMuKl9ACkAlp5Yl4MF276wfFpWWitYXS27dFhpIK4ZT8F8XD5iOpQJPnOsWJr0/VrUHnd Wi64V65tuU3A== X-IronPort-AV: E=McAfee;i="6000,8403,9837"; a="171725565" X-IronPort-AV: E=Sophos;i="5.78,426,1599548400"; d="scan'208";a="171725565" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Dec 2020 02:38:28 -0800 IronPort-SDR: 3LVOsPcwMkhISDxcig3IMkF8sMWj5BvIA+4SWRS3Kg/zSptm6qP0DR6Q3d+4dAflHufOAx/FaF l/2EjpIEtP8g== X-IronPort-AV: E=Sophos;i="5.78,426,1599548400"; d="scan'208";a="339243388" Received: from acherneg-mobl.ger.corp.intel.com (HELO localhost.localdomain) ([10.214.210.48]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Dec 2020 02:38:26 -0800 From: Tvrtko Ursulin To: igt-dev@lists.freedesktop.org Date: Thu, 17 Dec 2020 10:38:12 +0000 Message-Id: <20201217103812.1174024-3-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201217103812.1174024-1-tvrtko.ursulin@linux.intel.com> References: <20201217103812.1174024-1-tvrtko.ursulin@linux.intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t 3/3] intel_gpu_top: Fix interactive mode on serial console X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Intel-gfx@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Tvrtko Ursulin TIOCGWINSZ returns zero columns and rows on serial so lets assume 80x24. Signed-off-by: Tvrtko Ursulin --- tools/intel_gpu_top.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c index d1149eb8e14d..72ad7cbe9a8c 100644 --- a/tools/intel_gpu_top.c +++ b/tools/intel_gpu_top.c @@ -1640,6 +1640,11 @@ int main(int argc, char **argv) } else if (ioctl(0, TIOCGWINSZ, &ws) != -1) { con_w = ws.ws_col; con_h = ws.ws_row; + if (con_w == 0 && con_h == 0) { + /* Serial console. */ + con_w = 80; + con_h = 24; + } } pmu_sample(engines);