From patchwork Fri Apr 24 11:16:34 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Liebler X-Patchwork-Id: 6420 Received: (qmail 121310 invoked by alias); 24 Apr 2015 11:17:14 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 121295 invoked by uid 89); 24 Apr 2015 11:17:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: plane.gmane.org To: libc-alpha@sourceware.org From: Stefan Liebler Subject: Re: [PATCH] S390: Get cache information via sysconf. Date: Fri, 24 Apr 2015 13:16:34 +0200 Lines: 338 Message-ID: References: <5539F9CA.5030804@linux.vnet.ibm.com> Mime-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.6.0 In-Reply-To: <5539F9CA.5030804@linux.vnet.ibm.com> On 04/24/2015 10:07 AM, Andreas Krebbel wrote: > On 04/17/2015 03:31 PM, Stefan Liebler wrote: >> Hi, >> >> this patch adds support to query cache information on s390 >> via sysconf() function - e.g. with _SC_LEVEL1_ICACHE_SIZE. >> The attributes size, linesize and assoc can be queried >> for cache level 1 - 4 via "extract cpu attribute" instruction, >> which was first available with z10. >> >> Tested on s390/s390x. >> >> Ok to commit? >> >> Bye >> Stefan >> >> --- >> 2015-04-17 Stefan Liebler >> >> * sysdeps/unix/sysv/linux/s390/sysconf.c: New File. >> > Thanks! Just some minor nits. > > +static long > +__getCacheInfo (int level, int attr, int type) > > Urgs camel case ;) Why to start it with __? > > + /* check arguments. */ > + if ((level < 1 || level > CACHE_LEVEL_MAX) > + || (attr < CACHE_ATTR_LINESIZE || attr > CACHE_ATTR_ASSOC) > + || (type < CACHE_TYPE_DATA || type > CACHE_TYPE_INSTRUCTION)) > + return 0L; > + > + /* check if ecag-instruction is available. */ > + /* ecag - extract CPU attribute (only in zarch; arch >= z10; in as 2.24) */ > + if (((GLRO (dl_hwcap) & HWCAP_S390_STFLE) == 0) > +#if !defined __s390x__ > + || ((GLRO (dl_hwcap) & HWCAP_S390_ZARCH) == 0) > + || ((GLRO (dl_hwcap) & HWCAP_S390_HIGH_GPRS) == 0) > +#endif > > Could you please remove the superfluous brackets. > > + /* store facility list and check for z10. > + (see ifunc-resolver for details) */ > ... > + /* check cache topology, if cache is available at this level. */ > ... > + /* get cache information for level, attribute and type. */ > ... > > Comments usually start with a capital letter. > > Perhaps this qualifies for an entry in the NEWS file? > > Bye, > > -Andreas- > > Ok thanks. Here is the changed patch. Tested on s390/s390x. Bye Stefan --- 2015-04-24 Stefan Liebler * NEWS: Mention sysconf() cache information support for s390. * sysdeps/unix/sysv/linux/s390/sysconf.c: New File. diff --git a/NEWS b/NEWS index ccc4d13..a628b5a 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,9 @@ Version 2.22 18080, 18093, 18100, 18104, 18110, 18111, 18128, 18138, 18185, 18197, 18206, 18210, 18211, 18247, 18287. +* Cache information can be queried via sysconf() function on s390 e.g. with + _SC_LEVEL1_ICACHE_SIZE as argument. + * A buffer overflow in gethostbyname_r and related functions performing DNS requests has been fixed. If the NSS functions were called with a misaligned buffer, the buffer length change due to pointer alignment was diff --git a/sysdeps/unix/sysv/linux/s390/sysconf.c b/sysdeps/unix/sysv/linux/s390/sysconf.c new file mode 100644 index 0000000..7d61c50 --- /dev/null +++ b/sysdeps/unix/sysv/linux/s390/sysconf.c @@ -0,0 +1,230 @@ +/* Get system parameters, e.g. cache information. S390/S390x version. + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#include +#include + +static long int linux_sysconf (int name); + +/* Possible arguments for get_cache_info. + The values are reflecting the level/attribute/type indications + of ecag-instruction (extract cpu attribue). */ +#define CACHE_LEVEL_MAX 8 +#define CACHE_ATTR_LINESIZE 1 +#define CACHE_ATTR_SIZE 2 +#define CACHE_ATTR_ASSOC 3 +#define CACHE_TYPE_DATA 0 +#define CACHE_TYPE_INSTRUCTION 1 + +static long +get_cache_info (int level, int attr, int type) +{ + unsigned long int val; + unsigned int cmd; + unsigned long int arg; + + /* Check arguments. */ + if (level < 1 || level > CACHE_LEVEL_MAX + || attr < CACHE_ATTR_LINESIZE || attr > CACHE_ATTR_ASSOC + || type < CACHE_TYPE_DATA || type > CACHE_TYPE_INSTRUCTION) + return 0L; + + /* Check if ecag-instruction is available. + ecag - extract CPU attribute (only in zarch; arch >= z10; in as 2.24) */ + if (!(GLRO (dl_hwcap) & HWCAP_S390_STFLE) +#if !defined __s390x__ + || !(GLRO (dl_hwcap) & HWCAP_S390_ZARCH) + || !(GLRO (dl_hwcap) & HWCAP_S390_HIGH_GPRS) +#endif /* !__s390x__ */ + ) + { + /* stfle (or zarch, high-gprs on s390-32) is not available. + We are on an old machine. Return 256byte for LINESIZE for L1 d/i-cache, + otherwise 0. */ + if (level == 1 && attr == CACHE_ATTR_LINESIZE) + return 256L; + else + return 0L; + } + + /* Store facility list and check for z10. + (see ifunc-resolver for details) */ + register unsigned long reg0 asm("0") = 0; +#ifdef __s390x__ + unsigned long stfle_bits; +# define STFLE_Z10_MASK (1UL << (63 - 34)) +#else + unsigned long long stfle_bits; +# define STFLE_Z10_MASK (1ULL << (63 - 34)) +#endif /* !__s390x__ */ + asm volatile(".machine push" "\n\t" + ".machinemode \"zarch_nohighgprs\"\n\t" + ".machine \"z9-109\"" "\n\t" + "stfle %0" "\n\t" + ".machine pop" "\n" + : "=QS" (stfle_bits), "+d" (reg0) + : : "cc"); + + if (!(stfle_bits & STFLE_Z10_MASK)) + { + /* We are at least on a z9 machine. + Return 256byte for LINESIZE for L1 d/i-cache, + otherwise 0. */ + if (level == 1 && attr == CACHE_ATTR_LINESIZE) + return 256L; + else + return 0L; + } + + /* Check cache topology, if cache is available at this level. */ + arg = (CACHE_LEVEL_MAX - level) * 8; + asm volatile (".machine push\n\t" + ".machine \"z10\"\n\t" + ".machinemode \"zarch_nohighgprs\"\n\t" + "ecag %0,%%r0,0\n\t" /* returns 64bit unsigned integer. */ + "srlg %0,%0,0(%1)\n\t" /* right align 8bit cache info field. */ + ".machine pop" + : "=&d" (val) + : "a" (arg) + ); + val &= 0xCUL; /* Extract cache scope information from cache topology summary. + (bits 4-5 of 8bit-field; 00 means cache does not exist). */ + if (val == 0) + return 0L; + + /* Get cache information for level, attribute and type. */ + cmd = (attr << 4) | ((level - 1) << 1) | type; + asm volatile (".machine push\n\t" + ".machine \"z10\"\n\t" + ".machinemode \"zarch_nohighgprs\"\n\t" + "ecag %0,%%r0,0(%1)\n\t" + ".machine pop" + : "=d" (val) + : "a" (cmd) + ); + return val; +} + +long int +__sysconf (int name) +{ + if (name >= _SC_LEVEL1_ICACHE_SIZE && name <= _SC_LEVEL4_CACHE_LINESIZE) + { + int level; + int attr; + int type; + + switch (name) + { + case _SC_LEVEL1_ICACHE_SIZE: + level = 1; + attr = CACHE_ATTR_SIZE; + type = CACHE_TYPE_INSTRUCTION; + break; + case _SC_LEVEL1_ICACHE_ASSOC: + level = 1; + attr = CACHE_ATTR_ASSOC; + type = CACHE_TYPE_INSTRUCTION; + break; + case _SC_LEVEL1_ICACHE_LINESIZE: + level = 1; + attr = CACHE_ATTR_LINESIZE; + type = CACHE_TYPE_INSTRUCTION; + break; + + case _SC_LEVEL1_DCACHE_SIZE: + level = 1; + attr = CACHE_ATTR_SIZE; + type = CACHE_TYPE_DATA; + break; + case _SC_LEVEL1_DCACHE_ASSOC: + level = 1; + attr = CACHE_ATTR_ASSOC; + type = CACHE_TYPE_DATA; + break; + case _SC_LEVEL1_DCACHE_LINESIZE: + level = 1; + attr = CACHE_ATTR_LINESIZE; + type = CACHE_TYPE_DATA; + break; + + case _SC_LEVEL2_CACHE_SIZE: + level = 2; + attr = CACHE_ATTR_SIZE; + type = CACHE_TYPE_DATA; + break; + case _SC_LEVEL2_CACHE_ASSOC: + level = 2; + attr = CACHE_ATTR_ASSOC; + type = CACHE_TYPE_DATA; + break; + case _SC_LEVEL2_CACHE_LINESIZE: + level = 2; + attr = CACHE_ATTR_LINESIZE; + type = CACHE_TYPE_DATA; + break; + + case _SC_LEVEL3_CACHE_SIZE: + level = 3; + attr = CACHE_ATTR_SIZE; + type = CACHE_TYPE_DATA; + break; + case _SC_LEVEL3_CACHE_ASSOC: + level = 3; + attr = CACHE_ATTR_ASSOC; + type = CACHE_TYPE_DATA; + break; + case _SC_LEVEL3_CACHE_LINESIZE: + level = 3; + attr = CACHE_ATTR_LINESIZE; + type = CACHE_TYPE_DATA; + break; + + case _SC_LEVEL4_CACHE_SIZE: + level = 4; + attr = CACHE_ATTR_SIZE; + type = CACHE_TYPE_DATA; + break; + case _SC_LEVEL4_CACHE_ASSOC: + level = 4; + attr = CACHE_ATTR_ASSOC; + type = CACHE_TYPE_DATA; + break; + case _SC_LEVEL4_CACHE_LINESIZE: + level = 4; + attr = CACHE_ATTR_LINESIZE; + type = CACHE_TYPE_DATA; + break; + + default: + level = 0; + attr = 0; + type = 0; + break; + } + + return get_cache_info (level, attr, type); + } + + return linux_sysconf (name); +} + +/* Now the generic Linux version. */ +#undef __sysconf +#define __sysconf static linux_sysconf +#include