From nobody Wed Feb 11 10:29:40 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 14914031288601023.4535729418762; Wed, 5 Apr 2017 07:38:48 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C190E81F07; Wed, 5 Apr 2017 14:38:45 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 971A38B8BB; Wed, 5 Apr 2017 14:38:45 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 4936518523CC; Wed, 5 Apr 2017 14:38:45 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v35EbQar007307 for ; Wed, 5 Apr 2017 10:37:26 -0400 Received: by smtp.corp.redhat.com (Postfix) id BB3C4A8618; Wed, 5 Apr 2017 14:37:26 +0000 (UTC) Received: from caroline.brq.redhat.com (dhcp129-198.brq.redhat.com [10.34.129.198]) by smtp.corp.redhat.com (Postfix) with ESMTP id 151AFA4069; Wed, 5 Apr 2017 14:37:23 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com C190E81F07 Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=libvir-list-bounces@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com C190E81F07 From: Martin Kletzander To: libvir-list@redhat.com Date: Wed, 5 Apr 2017 16:36:32 +0200 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-loop: libvir-list@redhat.com Cc: =?UTF-8?q?Erik=20=C5=A0kult=C3=A9ty?= Subject: [libvirt] [PATCH v2 09/12] Add host cache information into capabilities X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Wed, 05 Apr 2017 14:38:46 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Martin Kletzander --- I'm adding only info about L3 caches, we can add more later, but for now that's more than enough. src/conf/capabilities.c | 200 ++++++++++++++++++++= ++++ src/conf/capabilities.h | 29 ++++ src/libvirt_private.syms | 1 + tests/vircaps2xmldata/vircaps-x86_64-caches.xml | 3 + tests/vircaps2xmltest.c | 3 +- 5 files changed, 235 insertions(+), 1 deletion(-) diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c index 7ed76e65b1a1..416dd1a34aba 100644 --- a/src/conf/capabilities.c +++ b/src/conf/capabilities.c @@ -31,6 +31,7 @@ #include #include "capabilities.h" +#include "c-ctype.h" #include "count-one-bits.h" #include "cpu_conf.h" #include "domain_conf.h" @@ -50,6 +51,8 @@ #define VIR_FROM_THIS VIR_FROM_CAPABILITIES +#define SYSFS_SYSTEM_PATH "/sys/devices/system/" + VIR_LOG_INIT("conf.capabilities") VIR_ENUM_DECL(virCapsHostPMTarget) @@ -237,6 +240,10 @@ virCapabilitiesDispose(void *object) virCapabilitiesClearSecModel(&caps->host.secModels[i]); VIR_FREE(caps->host.secModels); + for (i =3D 0; i < caps->host.ncaches; i++) + virCapsHostCacheBankFree(caps->host.caches[i]); + VIR_FREE(caps->host.caches); + VIR_FREE(caps->host.netprefix); VIR_FREE(caps->host.pagesSize); virCPUDefFree(caps->host.cpu); @@ -860,6 +867,49 @@ virCapabilitiesFormatNUMATopology(virBufferPtr buf, return 0; } +static int +virCapabilitiesFormatCaches(virBufferPtr buf, + size_t ncaches, + virCapsHostCacheBankPtr *caches) +{ + size_t i =3D 0; + + if (!ncaches) + return 0; + + virBufferAddLit(buf, "\n"); + virBufferAdjustIndent(buf, 2); + + for (i =3D 0; i < ncaches; i++) { + virCapsHostCacheBankPtr bank =3D caches[i]; + char *cpus_str =3D virBitmapFormat(bank->cpus); + bool kilos =3D !(bank->size % 1024); + + if (!cpus_str) + return -1; + + /* + * Let's just *hope* the size is aligned to KiBs so that it does n= ot + * bite is back in the future + */ + virBufferAsprintf(buf, + "\n", + bank->id, bank->level, + virCacheTypeToString(bank->type), + bank->size >> (kilos * 10), + kilos ? "KiB" : "B", + cpus_str); + + VIR_FREE(cpus_str); + } + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + + return 0; +} + /** * virCapabilitiesFormatXML: * @caps: capabilities to format @@ -956,6 +1006,10 @@ virCapabilitiesFormatXML(virCapsPtr caps) caps->host.numaCell) < 0) goto error; + if (virCapabilitiesFormatCaches(&buf, caps->host.ncaches, + caps->host.caches) < 0) + goto error; + for (i =3D 0; i < caps->host.nsecModels; i++) { virBufferAddLit(&buf, "\n"); virBufferAdjustIndent(&buf, 2); @@ -1438,3 +1492,149 @@ virCapabilitiesInitPages(virCapsPtr caps) VIR_FREE(pages_size); return ret; } + + +VIR_ENUM_IMPL(virCache, VIR_CACHE_TYPE_LAST, + "unified", + "instruction", + "data") + +bool +virCapsHostCacheBankEquals(virCapsHostCacheBankPtr a, + virCapsHostCacheBankPtr b) +{ + return (a->id =3D=3D b->id && + a->level =3D=3D b->level && + a->type =3D=3D b->type && + a->size =3D=3D b->size && + virBitmapEqual(a->cpus, b->cpus)); +} + +void +virCapsHostCacheBankFree(virCapsHostCacheBankPtr ptr) +{ + if (!ptr) + return; + + virBitmapFree(ptr->cpus); + VIR_FREE(ptr); +} + +int +virCapabilitiesInitCaches(virCapsPtr caps) +{ + size_t i =3D 0; + virBitmapPtr cpus =3D NULL; + ssize_t pos =3D -1; + DIR *dirp =3D NULL; + int ret =3D -1; + char *path =3D NULL; + char *type =3D NULL; + struct dirent *ent =3D NULL; + virCapsHostCacheBankPtr bank =3D NULL; + + /* Minimum level to expose in capabilities. Can be lowered or removed= (with + * the appropriate code below), but should not be increased, because w= e'd + * lose information. */ + const int cache_min_level =3D 3; + + /* offline CPUs don't provide cache info */ + if (virFileReadValueBitmap(&cpus, SYSFS_SYSTEM_PATH "cpu/online") < 0) + return -1; + + while ((pos =3D virBitmapNextSetBit(cpus, pos)) >=3D 0) { + int rv =3D -1; + + VIR_FREE(path); + if (virAsprintf(&path, SYSFS_SYSTEM_PATH "cpu/cpu%zd/cache/", pos)= < 0) + goto cleanup; + + rv =3D virDirOpenIfExists(&dirp, path); + if (rv < 0) + goto cleanup; + + if (!dirp) + continue; + + while ((rv =3D virDirRead(dirp, &ent, path)) > 0) { + int tmp_i; + char *tmp_c; + + if (!STRPREFIX(ent->d_name, "index")) + continue; + + if (VIR_ALLOC(bank) < 0) + goto cleanup; + + if (virFileReadValueUint(&bank->id, + SYSFS_SYSTEM_PATH "cpu/cpu%zd/cache/%= s/id", + pos, ent->d_name) < 0) + goto cleanup; + + if (virFileReadValueUint(&bank->level, + SYSFS_SYSTEM_PATH + "cpu/cpu%zd/cache/%s/level", + pos, ent->d_name) < 0) + goto cleanup; + + if (virFileReadValueString(&type, + SYSFS_SYSTEM_PATH + "cpu/cpu%zd/cache/%s/type", + pos, ent->d_name) < 0) + goto cleanup; + + if (virFileReadValueScaledInt(&bank->size, + SYSFS_SYSTEM_PATH + "cpu/cpu%zd/cache/%s/size", + pos, ent->d_name) < 0) + goto cleanup; + + if (virFileReadValueBitmap(&bank->cpus, + SYSFS_SYSTEM_PATH + "cpu/cpu%zd/cache/%s/shared_cpu_lis= t", + pos, ent->d_name) < 0) + goto cleanup; + + if (bank->level < cache_min_level) { + virCapsHostCacheBankFree(bank); + bank =3D NULL; + continue; + } + + for (tmp_c =3D type; *tmp_c !=3D '\0'; tmp_c++) + *tmp_c =3D c_tolower(*tmp_c); + + tmp_i =3D virCacheTypeFromString(type); + if (tmp_i < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown cache type '%s'"), type); + VIR_FREE(type); + goto cleanup; + } + bank->type =3D tmp_i; + + for (i =3D 0; i < caps->host.ncaches; i++) { + if (virCapsHostCacheBankEquals(bank, caps->host.caches[i])) + break; + } + if (i =3D=3D caps->host.ncaches) { + if (VIR_APPEND_ELEMENT(caps->host.caches, + caps->host.ncaches, + bank) < 0) { + goto cleanup; + } + } + + virCapsHostCacheBankFree(bank); + } + if (rv < 0) + goto cleanup; + } + + ret =3D 0; + cleanup: + VIR_FREE(path); + virDirClose(&dirp); + virCapsHostCacheBankFree(bank); + return ret; +} diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h index d10eef3afdea..e099cccf6d39 100644 --- a/src/conf/capabilities.h +++ b/src/conf/capabilities.h @@ -138,6 +138,26 @@ struct _virCapsHostSecModel { virCapsHostSecModelLabelPtr labels; }; +typedef enum { + VIR_CACHE_TYPE_DATA, + VIR_CACHE_TYPE_INSTRUCTION, + VIR_CACHE_TYPE_UNIFIED, + + VIR_CACHE_TYPE_LAST +} virCacheType; + +VIR_ENUM_DECL(virCache); + +typedef struct _virCapsHostCacheBank virCapsHostCacheBank; +typedef virCapsHostCacheBank *virCapsHostCacheBankPtr; +struct _virCapsHostCacheBank { + unsigned int id; + unsigned int level; /* 1=3DL1, 2=3DL2, 3=3DL3, etc. */ + unsigned long long size; /* B */ + virCacheType type; /* Data, Instruction or Unified */ + virBitmapPtr cpus; /* All CPUs that share this bank */ +}; + typedef struct _virCapsHost virCapsHost; typedef virCapsHost *virCapsHostPtr; struct _virCapsHost { @@ -157,6 +177,9 @@ struct _virCapsHost { size_t nnumaCell_max; virCapsHostNUMACellPtr *numaCell; + size_t ncaches; + virCapsHostCacheBankPtr *caches; + size_t nsecModels; virCapsHostSecModelPtr secModels; @@ -303,4 +326,10 @@ int virCapabilitiesInitPages(virCapsPtr caps); int virCapabilitiesInitNUMA(virCapsPtr caps); +bool virCapsHostCacheBankEquals(virCapsHostCacheBankPtr a, + virCapsHostCacheBankPtr b); +void virCapsHostCacheBankFree(virCapsHostCacheBankPtr ptr); + +int virCapabilitiesInitCaches(virCapsPtr caps); + #endif /* __VIR_CAPABILITIES_H */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d399e0dc063a..b175b3b02901 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -59,6 +59,7 @@ virCapabilitiesFreeNUMAInfo; virCapabilitiesGetCpusForNodemask; virCapabilitiesGetNodeInfo; virCapabilitiesHostSecModelAddBaseLabel; +virCapabilitiesInitCaches; virCapabilitiesInitNUMA; virCapabilitiesInitPages; virCapabilitiesNew; diff --git a/tests/vircaps2xmldata/vircaps-x86_64-caches.xml b/tests/vircap= s2xmldata/vircaps-x86_64-caches.xml index 88f2ec62277e..f2da28e576ac 100644 --- a/tests/vircaps2xmldata/vircaps-x86_64-caches.xml +++ b/tests/vircaps2xmldata/vircaps-x86_64-caches.xml @@ -28,6 +28,9 @@ + + + diff --git a/tests/vircaps2xmltest.c b/tests/vircaps2xmltest.c index af422238520b..8f02314afe8e 100644 --- a/tests/vircaps2xmltest.c +++ b/tests/vircaps2xmltest.c @@ -58,7 +58,8 @@ test_virCapabilities(const void *opaque) if (!caps) goto cleanup; - if (virCapabilitiesInitNUMA(caps) < 0) + if (virCapabilitiesInitNUMA(caps) < 0 || + virCapabilitiesInitCaches(caps) < 0) goto cleanup; virFileMockClearPrefixes(); -- 2.12.2 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list