From nobody Wed Nov 5 15:40:36 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 1497418021217129.68846975208896; Tue, 13 Jun 2017 22:27:01 -0700 (PDT) Received: from localhost ([::1]:46461 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dL0pX-0004x1-NL for importer@patchew.org; Wed, 14 Jun 2017 01:26:59 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44929) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dL0m0-0001mI-4m for qemu-devel@nongnu.org; Wed, 14 Jun 2017 01:23:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dL0ly-0007K1-LD for qemu-devel@nongnu.org; Wed, 14 Jun 2017 01:23:20 -0400 Received: from mail-qk0-x244.google.com ([2607:f8b0:400d:c09::244]:36499) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dL0ly-0007Js-FK for qemu-devel@nongnu.org; Wed, 14 Jun 2017 01:23:18 -0400 Received: by mail-qk0-x244.google.com with SMTP id r62so6489389qkf.3 for ; Tue, 13 Jun 2017 22:23:18 -0700 (PDT) Received: from bigtime.twiddle.net.com (97-113-165-157.tukw.qwest.net. [97.113.165.157]) by smtp.gmail.com with ESMTPSA id 34sm10959480qtp.17.2017.06.13.22.23.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 13 Jun 2017 22:23:16 -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=mSXsaVTnyhyY7yqMOcq37Usptf55a8CzsMdbHZST7io=; b=tTL/EJBPmARoZcYh038gwt8XxHF0yi3WO3AV4SrLJls4zfvIZ5Za9DVnsM6f8QMkKV GzNBi+yF8YfI5q4UxvdZoQ9HZV1XO1/zjf4Bc1YGxbaxj7khGTuV9EwuX4ugSLjIvTC3 zq4/ng5KFyz3rvyJzHW3ZedagQNxLGQsEPcIcO/eMTPIwtwjyhtAjDmNSO/wjbLSoaVl LoDeFJ8kX/zQq1Em0a+fVzvSETnrpulJvMJitR2Q6woGdmBWBkYQP9FZZY/ZFBc3bv+G hnN07eV06AquY/RNoNvY3PRu6JR0p+WmyGMdkjuEj+Cy5mR9ZY3zRHSa6puMn25gUmOH F5Ng== 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=mSXsaVTnyhyY7yqMOcq37Usptf55a8CzsMdbHZST7io=; b=SeqO1GlEU1zRyQk2M5I4m4P/NZAH+UBtmoMmCsGc2AYixhUi/IXM6oulcYm+NETnzZ BeLQHmHloMnbPRWThA7WPCNn6lWsl9TS5aZLMGOV9re2Q0+0C0xZpEygBAd9E+HsGQKe Du1kL7+uhTE3DZqpKyb6jfvrjyHsqdlSrbty62z4R8+p6St3cZZWrikmoFFjHno4jk59 xscvlxhuYiUhVUMzT1XvvC/ANk3HjhZM4MrkJkMHNRJsqcLJM+f3j9+SWPRQOCsHNnOU eyR0RleplDGiDf8K+2z7XI5bKeHDKnZS3X87n6waFDZ7blMaR1Rd+wCByOzJFWrfcIXx 07zA== X-Gm-Message-State: AKS2vOzGoLkc9qD2GM63IEvwLDQOgmd7DUfBvpf5TXnhcm/lGH+RekSJ n3h9qP1uqp7XwAAJCvM= X-Received: by 10.233.235.145 with SMTP id b139mr4489188qkg.208.1497417797513; Tue, 13 Jun 2017 22:23:17 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Tue, 13 Jun 2017 22:23:02 -0700 Message-Id: <20170614052311.13785-2-rth@twiddle.net> X-Mailer: git-send-email 2.9.4 In-Reply-To: <20170614052311.13785-1-rth@twiddle.net> References: <20170614052311.13785-1-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400d:c09::244 Subject: [Qemu-devel] [PULL 01/10] 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: peter.maydell@linaro.org, "Emilio G. Cota" 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 | 185 +++++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 191 insertions(+), 69 deletions(-) create mode 100644 util/cacheinfo.c diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index fb008a2..8559634 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -483,4 +483,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..f987522 --- /dev/null +++ b/util/cacheinfo.c @@ -0,0 +1,185 @@ +/* + * 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; + +/* + * Operating system specific detection mechanisms. + */ + +#if defined(_AIX) +# include + +static void sys_cache_info(int *isize, int *dsize) +{ + *isize =3D _system_configuration.icache_line; + *dsize =3D _system_configuration.dcache_line; +} + +#elif defined(_WIN32) + +static void sys_cache_info(int *isize, int *dsize) +{ + 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: + *isize =3D *dsize =3D buf[i].Cache.LineSize; + break; + case CacheInstruction: + *isize =3D buf[i].Cache.LineSize; + break; + case CacheData: + *dsize =3D buf[i].Cache.LineSize; + break; + default: + 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(int *isize, int *dsize) +{ + /* There's only a single sysctl for both I/D cache line sizes. */ + long size; + size_t len =3D sizeof(size); + if (!sysctlbyname(SYSCTL_CACHELINE_NAME, &size, &len, NULL, 0)) { + *isize =3D *dsize =3D size; + } +} + +#else +/* POSIX */ + +static void sys_cache_info(int *isize, int *dsize) +{ +# ifdef _SC_LEVEL1_ICACHE_LINESIZE + *isize =3D sysconf(_SC_LEVEL1_ICACHE_LINESIZE); +# endif +# ifdef _SC_LEVEL1_DCACHE_LINESIZE + *dsize =3D sysconf(_SC_LEVEL1_DCACHE_LINESIZE); +# endif +} +#endif /* sys_cache_info */ + +/* + * Architecture (+ OS) specific detection mechanisms. + */ + +#if defined(__aarch64__) + +static void arch_cache_info(int *isize, int *dsize) +{ + if (*isize =3D=3D 0 || *dsize =3D=3D 0) { + unsigned ctr; + + /* The real cache geometry is in CCSIDR_EL1/CLIDR_EL1/CSSELR_EL1, + but (at least under Linux) these are marked protected by the + kernel. However, CTR_EL0 contains the minimum linesize in the + entire hierarchy, and is used by userspace cache flushing. */ + asm volatile("mrs\t%0, ctr_el0" : "=3Dr"(ctr)); + if (*isize =3D=3D 0) { + *isize =3D 4 << (ctr & 0xf); + } + if (*dsize =3D=3D 0) { + *dsize =3D 4 << ((ctr >> 16) & 0xf); + } + } +} + +#elif defined(_ARCH_PPC) && defined(__linux__) + +static void arch_cache_info(int *isize, int *dsize) +{ + if (*isize =3D=3D 0) { + *isize =3D qemu_getauxval(AT_ICACHEBSIZE); + } + if (*dsize =3D=3D 0) { + *dsize =3D qemu_getauxval(AT_DCACHEBSIZE); + } +} + +#else +static void arch_cache_info(int *isize, int *dsize) { } +#endif /* arch_cache_info */ + +/* + * ... and if all else fails ... + */ + +static void fallback_cache_info(int *isize, int *dsize) +{ + /* If we can only find one of the two, assume they're the same. */ + if (*isize) { + if (*dsize) { + /* Success! */ + } 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 + } +} + +static void __attribute__((constructor)) init_cache_info(void) +{ + int isize =3D 0, dsize =3D 0; + + sys_cache_info(&isize, &dsize); + arch_cache_info(&isize, &dsize); + fallback_cache_info(&isize, &dsize); + + qemu_icache_linesize =3D isize; + qemu_dcache_linesize =3D dsize; +} --=20 2.9.4