Re: [libvirt] [PATCH v2 09/12] Add host cache information into capabilities

2017-04-07 Thread Erik Skultety
On Wed, Apr 05, 2017 at 04:36:32PM +0200, Martin Kletzander wrote:
> 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.

I think it's worth putting this into the commit message, along with a snippet
introducing the XML update.

[...]

> +static int
> +virCapabilitiesFormatCaches(virBufferPtr buf,
> +size_t ncaches,
> +virCapsHostCacheBankPtr *caches)
> +{
> +size_t i = 0;
> +
> +if (!ncaches)
> +return 0;
> +
> +virBufferAddLit(buf, "\n");
> +virBufferAdjustIndent(buf, 2);
> +
> +for (i = 0; i < ncaches; i++) {
> +virCapsHostCacheBankPtr bank = caches[i];
> +char *cpus_str = virBitmapFormat(bank->cpus);
> +bool kilos = !(bank->size % 1024);

I'd suggest kibs/kibis/kibi but not kilos.

> +
> +int
> +virCapabilitiesInitCaches(virCapsPtr caps)
> +{
> +size_t i = 0;
> +virBitmapPtr cpus = NULL;
> +ssize_t pos = -1;
> +DIR *dirp = NULL;
> +int ret = -1;
> +char *path = NULL;
> +char *type = NULL;
> +struct dirent *ent = NULL;
> +virCapsHostCacheBankPtr bank = NULL;
> +
> +/* Minimum level to expose in capabilities.  Can be lowered or removed 
> (with
> + * the appropriate code below), but should not be increased, because we'd
> + * lose information. */
> +const int cache_min_level = 3;
> +
> +/* offline CPUs don't provide cache info */
> +if (virFileReadValueBitmap(&cpus, SYSFS_SYSTEM_PATH "cpu/online") < 0)
> +return -1;
> +
> +while ((pos = virBitmapNextSetBit(cpus, pos)) >= 0) {
> +int rv = -1;
> +
> +VIR_FREE(path);
> +if (virAsprintf(&path, SYSFS_SYSTEM_PATH "cpu/cpu%zd/cache/", pos) < 
> 0)
> +goto cleanup;
> +
> +rv = virDirOpenIfExists(&dirp, path);
> +if (rv < 0)
> +goto cleanup;
> +
> +if (!dirp)
> +continue;
> +
> +while ((rv = 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_list",
> +   pos, ent->d_name) < 0)
> +goto cleanup;
> +
> +if (bank->level < cache_min_level) {
> +virCapsHostCacheBankFree(bank);
> +bank = NULL;
> +continue;
> +}

I'd say, make the bank->level read first, then perform ^this check and then
continue with the rest of the checks...you know, to save a few cycles...

> +
> +for (tmp_c = type; *tmp_c != '\0'; tmp_c++)
> +*tmp_c = c_tolower(*tmp_c);
> +
> +tmp_i = virCacheTypeFromString(type);
> +if (tmp_i < 0) {
> +virReportError(VIR_ERR_INTERNAL_ERROR,
> +   _("Unknown cache type '%s'"), type);
> +VIR_FREE(type);
> +goto cleanup;
> +}

I'd maybe add a small static function handling ^this hunk (or add a symmetric
virStringToLower method), but that's a bikeshed for another day.

> +bank->type = tmp_i;
> +
> +for (i = 0; i < caps->host.ncaches; i++) {
> +if (virCapsHostCacheBankEquals(bank, caps->host.caches[i]))
> +break;
> +}
> +if (i == caps->host.ncaches) {
> +if (VIR_APPEND_ELEMENT(caps->host.caches,
> +   caps->host.ncaches,
> +  

Re: [libvirt] [PATCH v2 09/12] Add host cache information into capabilities

2017-04-06 Thread Martin Kletzander

On Thu, Apr 06, 2017 at 02:04:04PM +0800, Eli Qiao wrote:



+
+VIR_ENUM_IMPL(virCache, VIR_CACHE_TYPE_LAST,
+ "unified",
+ "instruction",
+ "data")
+




};

+typedef enum {
+ VIR_CACHE_TYPE_DATA,
+ VIR_CACHE_TYPE_INSTRUCTION,
+ VIR_CACHE_TYPE_UNIFIED,
+
+ VIR_CACHE_TYPE_LAST
+} virCacheType;
+


The sequence is wrong, it should be :

VIR_CACHE_TYPE_UNIFIED,
VIR_CACHE_TYPE_INSTRUCTION,
VIR_CACHE_TYPE_DATA,



Hehe, good catch.  Since the internal values are not exposed anywhere,
the test data aren't affected.  I wish I remembered why I changed that.

For future reviewers, consider the following squashed in:

diff --git i/src/conf/capabilities.h w/src/conf/capabilities.h
index e099cccf6d39..60c8218ce3e5 100644
--- i/src/conf/capabilities.h
+++ w/src/conf/capabilities.h
@@ -139,9 +139,9 @@ struct _virCapsHostSecModel {
};

typedef enum {
-VIR_CACHE_TYPE_DATA,
-VIR_CACHE_TYPE_INSTRUCTION,
VIR_CACHE_TYPE_UNIFIED,
+VIR_CACHE_TYPE_INSTRUCTION,
+VIR_CACHE_TYPE_DATA,

VIR_CACHE_TYPE_LAST
} virCacheType;
--

Martin


signature.asc
Description: Digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v2 09/12] Add host cache information into capabilities

2017-04-05 Thread Eli Qiao

> +
> +VIR_ENUM_IMPL(virCache, VIR_CACHE_TYPE_LAST,
> + "unified",
> + "instruction",
> + "data")
> +


> };
> 
> +typedef enum {
> + VIR_CACHE_TYPE_DATA,
> + VIR_CACHE_TYPE_INSTRUCTION,
> + VIR_CACHE_TYPE_UNIFIED,
> +
> + VIR_CACHE_TYPE_LAST
> +} virCacheType;
> +

The sequence is wrong, it should be :

VIR_CACHE_TYPE_UNIFIED,
VIR_CACHE_TYPE_INSTRUCTION,
VIR_CACHE_TYPE_DATA,


see the above VIR_ENUM_IMPL.
> +VIR_ENUM_DECL(virCache);
> +
> +typedef struct _virCapsHostCacheBank virCapsHostCacheBank;
> 
> 


--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v2 09/12] Add host cache information into capabilities

2017-04-05 Thread Martin Kletzander
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 = 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 = 0;
+
+if (!ncaches)
+return 0;
+
+virBufferAddLit(buf, "\n");
+virBufferAdjustIndent(buf, 2);
+
+for (i = 0; i < ncaches; i++) {
+virCapsHostCacheBankPtr bank = caches[i];
+char *cpus_str = virBitmapFormat(bank->cpus);
+bool kilos = !(bank->size % 1024);
+
+if (!cpus_str)
+return -1;
+
+/*
+ * Let's just *hope* the size is aligned to KiBs so that it does not
+ * 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 = 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 == b->id &&
+a->level == b->level &&
+a->type == b->type &&
+a->size == 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 = 0;
+virBitmapPtr cpus = NULL;
+ssize_t pos = -1;
+DIR *dirp = NULL;
+int ret = -1;
+char *path = NULL;
+char *type = NULL;
+struct dirent *ent = NULL;
+virCapsHostCacheBankPtr bank = NULL;
+
+/* Minimum level to expose in capabilities.  Can be lowered or removed 
(with
+ * the appropriate code below), but should not be increased, because we'd
+ * lose information. */
+const int cache_min_level = 3;
+
+/* offline CPUs don't provide cache info */
+if (virFileReadValueBitmap(&cpus, SYSFS_SYSTEM_PATH "cpu/online") < 0)
+return -1;
+
+while ((pos = virBitmapNextSetBit(cpus, pos)) >= 0) {
+int rv = -1;
+
+VIR_FREE(path);
+if (virAsprintf(&path, SYSFS_SYSTEM_PATH "cpu/cpu%zd/cache/", pos) < 0)
+goto cleanup;
+
+rv = virDirOpenIfExists(&dirp, path);
+if (rv < 0)
+goto cleanup;
+
+if (!dirp)
+continue;
+
+while ((rv = virDirRead(dirp, &ent, path)) > 0) {
+int tmp_i;
+char *tmp_c;
+
+