From nobody Wed Nov 5 17:38:11 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; dkim=fail spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1496851059364788.1477288598802; Wed, 7 Jun 2017 08:57:39 -0700 (PDT) Received: from localhost ([::1]:44786 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dIdKy-0001l7-QK for importer@patchew.org; Wed, 07 Jun 2017 11:57:36 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:48424) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dIdJL-0000ZD-If for qemu-devel@nongnu.org; Wed, 07 Jun 2017 11:55:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dIdJJ-0005Yq-3O for qemu-devel@nongnu.org; Wed, 07 Jun 2017 11:55:55 -0400 Received: from mail-qt0-x244.google.com ([2607:f8b0:400d:c0d::244]:36145) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dIdJI-0005Yj-U3 for qemu-devel@nongnu.org; Wed, 07 Jun 2017 11:55:53 -0400 Received: by mail-qt0-x244.google.com with SMTP id s33so1989851qtg.3 for ; Wed, 07 Jun 2017 08:55:52 -0700 (PDT) Received: from bigtime.twiddle.net.com (184-217-116-168.pools.spcsdns.net. [184.217.116.168]) by smtp.gmail.com with ESMTPSA id i28sm1272525qta.52.2017.06.07.08.55.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 07 Jun 2017 08:55:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=amvS1ivjZuFYPZtmgdCrw9JjiDMzqeQAqsFSZnbqlMM=; b=YS6km1luQOeriLuJ0FP7iFF2z8QgUl4BRJbumDIKK2UPGSKbcG6ee+fZ2cxDt1iSOX D9/r18Xdev9zGR0cM2ZKOwIeL2P83HYHkeiH2QCcatALqb/itX5u5Rw9cQ6TNCcOYlOW JuinkiMI/UxO9ao468ZdvrpSJMhVz4zz/cDdpUXS87WBM/D8IEUxtviK3K7woGKUfNz/ CFQtwwJtrIVuh2XrjNG6Vsh3sGVQLlykW1TnNDCEKJwM/kj43Cla4MOzpjVGXdC2Di3p xmkVxQX6CTNsihiVrtJPkTMrXr2djALb6Ogz1Gt1W9/ISBel4+rSsiMLmLSsrGfwbysX CWmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=amvS1ivjZuFYPZtmgdCrw9JjiDMzqeQAqsFSZnbqlMM=; b=RwFqSyAaj3XPVT1YjoM/KehLMRk8Qo+oI9sJRMWpjT6/buNRhXA2DInwH6py+5fs6+ 9n7AyadZgIYl6GK1sXZDW3PHRtWjJM+Ln4RK6xVSpfnXaTHnxsKhiagbdUD6PpvaUEoS LGrgQ0ieZAUdJI2QC/jJGfcAnggkSrnnv5i7G7BbJ7/QnYOhsgkWwjBB/YnFk/UIvhfe Z1R9jB7b6j9xhKjEwlu8TrVEW3yogQYuZo+Q3/cFWr5Rx4t0kTh0nskTY9DL2z4N6Ovu hshmbkXrHU3yhnUsybml9IqEdo4cB6jxXIsVWbfiFx+RsKOGOst6lb2G8WjTFpECqdq+ IELQ== X-Gm-Message-State: AODbwcDynkVhtm6/eOO/yivA4xx98Hbng4YeDoO6yT4BwrJ3aKl04U3M zKQmQPciHpJ/9xk2C+s= X-Received: by 10.200.0.153 with SMTP id c25mr37964648qtg.28.1496850951909; Wed, 07 Jun 2017 08:55:51 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Wed, 7 Jun 2017 08:55:30 -0700 Message-Id: <20170607155536.1193-2-rth@twiddle.net> X-Mailer: git-send-email 2.9.4 In-Reply-To: <20170607155536.1193-1-rth@twiddle.net> References: <20170607155536.1193-1-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400d:c0d::244 Subject: [Qemu-devel] [PATCH v4 1/7] util: add cacheinfo X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: cota@braap.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: "Emilio G. Cota" Add helpers to gather cache info from the host at init-time. For now, only export the host's I/D cache line sizes, which we will use to improve cache locality to avoid false sharing. Suggested-by: Richard Henderson Suggested-by: Geert Martin Ijewski Tested-by: Geert Martin Ijewski Signed-off-by: Emilio G. Cota Message-Id: <1496794624-4083-1-git-send-email-cota@braap.org> [rth: Move all implementations from tcg/ppc/] Signed-off-by: Richard Henderson --- include/qemu/osdep.h | 3 + tcg/ppc/tcg-target.inc.c | 71 +------------------ util/Makefile.objs | 1 + util/cacheinfo.c | 174 +++++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 180 insertions(+), 69 deletions(-) create mode 100644 util/cacheinfo.c diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 1c9f5e2..ee43521 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -470,4 +470,7 @@ char *qemu_get_pid_name(pid_t pid); */ pid_t qemu_fork(Error **errp); =20 +extern int qemu_icache_linesize; +extern int qemu_dcache_linesize; + #endif diff --git a/tcg/ppc/tcg-target.inc.c b/tcg/ppc/tcg-target.inc.c index 8d50f18..1f690df 100644 --- a/tcg/ppc/tcg-target.inc.c +++ b/tcg/ppc/tcg-target.inc.c @@ -2820,14 +2820,11 @@ void tcg_register_jit(void *buf, size_t buf_size) } #endif /* __ELF__ */ =20 -static size_t dcache_bsize =3D 16; -static size_t icache_bsize =3D 16; - void flush_icache_range(uintptr_t start, uintptr_t stop) { uintptr_t p, start1, stop1; - size_t dsize =3D dcache_bsize; - size_t isize =3D icache_bsize; + size_t dsize =3D qemu_dcache_linesize; + size_t isize =3D qemu_icache_linesize; =20 start1 =3D start & ~(dsize - 1); stop1 =3D (stop + dsize - 1) & ~(dsize - 1); @@ -2844,67 +2841,3 @@ void flush_icache_range(uintptr_t start, uintptr_t s= top) asm volatile ("sync" : : : "memory"); asm volatile ("isync" : : : "memory"); } - -#if defined _AIX -#include - -static void __attribute__((constructor)) tcg_cache_init(void) -{ - icache_bsize =3D _system_configuration.icache_line; - dcache_bsize =3D _system_configuration.dcache_line; -} - -#elif defined __linux__ -static void __attribute__((constructor)) tcg_cache_init(void) -{ - unsigned long dsize =3D qemu_getauxval(AT_DCACHEBSIZE); - unsigned long isize =3D qemu_getauxval(AT_ICACHEBSIZE); - - if (dsize =3D=3D 0 || isize =3D=3D 0) { - if (dsize =3D=3D 0) { - fprintf(stderr, "getauxval AT_DCACHEBSIZE failed\n"); - } - if (isize =3D=3D 0) { - fprintf(stderr, "getauxval AT_ICACHEBSIZE failed\n"); - } - exit(1); - } - dcache_bsize =3D dsize; - icache_bsize =3D isize; -} - -#elif defined __APPLE__ -#include - -static void __attribute__((constructor)) tcg_cache_init(void) -{ - size_t len; - unsigned cacheline; - int name[2] =3D { CTL_HW, HW_CACHELINE }; - - len =3D sizeof(cacheline); - if (sysctl(name, 2, &cacheline, &len, NULL, 0)) { - perror("sysctl CTL_HW HW_CACHELINE failed"); - exit(1); - } - dcache_bsize =3D cacheline; - icache_bsize =3D cacheline; -} - -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -#include - -static void __attribute__((constructor)) tcg_cache_init(void) -{ - size_t len =3D 4; - unsigned cacheline; - - if (sysctlbyname ("machdep.cacheline_size", &cacheline, &len, NULL, 0)= ) { - fprintf(stderr, "sysctlbyname machdep.cacheline_size failed: %s\n", - strerror(errno)); - exit(1); - } - dcache_bsize =3D cacheline; - icache_bsize =3D cacheline; -} -#endif diff --git a/util/Makefile.objs b/util/Makefile.objs index c6205eb..94d9477 100644 --- a/util/Makefile.objs +++ b/util/Makefile.objs @@ -20,6 +20,7 @@ util-obj-y +=3D host-utils.o util-obj-y +=3D bitmap.o bitops.o hbitmap.o util-obj-y +=3D fifo8.o util-obj-y +=3D acl.o +util-obj-y +=3D cacheinfo.o util-obj-y +=3D error.o qemu-error.o util-obj-y +=3D id.o util-obj-y +=3D iov.o qemu-config.o qemu-sockets.o uri.o notify.o diff --git a/util/cacheinfo.c b/util/cacheinfo.c new file mode 100644 index 0000000..0238ca6 --- /dev/null +++ b/util/cacheinfo.c @@ -0,0 +1,174 @@ +/* + * cacheinfo.c - helpers to query the host about its caches + * + * Copyright (C) 2017, Emilio G. Cota + * License: GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" + +int qemu_icache_linesize =3D 0; +int qemu_dcache_linesize =3D 0; + +#if defined(_AIX) +# include + +static void sys_cache_info(void) +{ + qemu_icache_linesize =3D _system_configuration.icache_line; + qemu_dcache_linesize =3D _system_configuration.dcache_line; +} + +#elif defined(_WIN32) + +static void sys_cache_info(void) +{ + SYSTEM_LOGICAL_PROCESSOR_INFORMATION *buf; + DWORD size =3D 0; + BOOL success; + size_t i, n; + + /* Check for the required buffer size first. Note that if the zero + size we use for the probe results in success, then there is no + data available; fail in that case. */ + success =3D GetLogicalProcessorInformation(0, &size); + if (success || GetLastError() !=3D ERROR_INSUFFICIENT_BUFFER) { + return; + } + + n =3D size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); + size =3D n * sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); + buf =3D g_new0(SYSTEM_LOGICAL_PROCESSOR_INFORMATION, n); + if (!GetLogicalProcessorInformation(buf, &size)) { + goto fail; + } + + for (i =3D 0; i < n; i++) { + if (buf[i].Relationship =3D=3D RelationCache + && buf[i].Cache.Level =3D=3D 1) { + switch (buf[i].Cache.Type) { + case CacheUnified: + qemu_icache_linesize =3D buf[i].Cache.LineSize; + qemu_dcache_linesize =3D buf[i].Cache.LineSize; + break; + case CacheInstruction: + qemu_icache_linesize =3D buf[i].Cache.LineSize; + break; + case CacheData: + qemu_dcache_linesize =3D buf[i].Cache.LineSize; + break; + } + } + } + fail: + g_free(buf); +} + +#elif defined(__APPLE__) \ + || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +# include +# if defined(__APPLE__) +# define SYSCTL_CACHELINE_NAME "hw.cachelinesize" +# else +# define SYSCTL_CACHELINE_NAME "machdep.cacheline_size" +# endif + +static void sys_cache_info(void) +{ + /* There's only a single sysctl for both I/D cache line sizes. */ + size_t len =3D sizeof(qemu_icache_linesize); + if (!sysctlbyname(SYSCTL_CACHELINE_NAME, &qemu_icache_linesize, + &len, NULL, 0)) { + qemu_dcache_linesize =3D qemu_icache_linesize; + } +} + +#else +/* POSIX, with extra Linux ifdefs. */ + +static int icache_info(void) +{ +# ifdef _SC_LEVEL1_ICACHE_LINESIZE + { + long x =3D sysconf(_SC_LEVEL1_ICACHE_LINESIZE); + if (x > 0) { + return x; + } + } +# endif +# ifdef AT_ICACHEBSIZE + /* glibc does not always export this through sysconf, e.g. on PPC */ + { + unsigned long x =3D qemu_getauxval(AT_ICACHEBSIZE); + if (x > 0) { + return x; + } + } +# endif + return 0; +} + +/* Similarly for the D cache. */ +static int dcache_info(void) +{ +# ifdef _SC_LEVEL1_DCACHE_LINESIZE + { + long x =3D sysconf(_SC_LEVEL1_DCACHE_LINESIZE); + if (x > 0) { + return x; + } + } +# endif +# ifdef AT_DCACHEBSIZE + { + unsigned long x =3D qemu_getauxval(AT_DCACHEBSIZE); + if (x > 0) { + return x; + } + } +# endif + return 0; +} + +static void sys_cache_info(void) +{ + qemu_icache_linesize =3D icache_info(); + qemu_dcache_linesize =3D dcache_info(); +} +#endif + +static void __attribute__((constructor)) init_cache_info(void) +{ + int isize, dsize; + + sys_cache_info(); + + isize =3D qemu_icache_linesize; + dsize =3D qemu_dcache_linesize; + + /* If we can only find one of the two, assume they're the same. */ + if (isize) { + if (dsize) { + /* Success! */ + return; + } else { + dsize =3D isize; + } + } else if (dsize) { + isize =3D dsize; + } else { +#if defined(_ARCH_PPC) + /* For PPC, we're going to use the icache size computed for + flush_icache_range. Which means that we must use the + architecture minimum. */ + isize =3D dsize =3D 16; +#else + /* Otherwise, 64 bytes is not uncommon. */ + isize =3D dsize =3D 64; +#endif + } + + qemu_icache_linesize =3D isize; + qemu_dcache_linesize =3D dsize; +} --=20 2.9.4