[libvirt] [PATCH 06/17] nodeinfo: move host CPU APIs out into virhostcpu.c file

Daniel P. Berrange berrange at redhat.com
Thu Apr 14 15:30:36 UTC 2016


Move all APIs with a virHostCPU name prefix out into new
util/virhostcpu.h & util/virhostcpu.c files

Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
---
 cfg.mk                                             |    6 +-
 po/POTFILES.in                                     |    1 +
 src/Makefile.am                                    |    3 +-
 src/libvirt_linux.syms                             |    2 +-
 src/lxc/lxc_controller.c                           |    2 +-
 src/lxc/lxc_driver.c                               |    1 +
 src/nodeinfo.c                                     | 1171 +-----------------
 src/nodeinfo.h                                     |   13 -
 src/openvz/openvz_driver.c                         |    1 +
 src/qemu/qemu_driver.c                             |    1 +
 src/qemu/qemu_process.c                            |    2 +-
 src/uml/uml_driver.c                               |    1 +
 src/util/vircgroup.c                               |    3 +-
 src/util/virhostcpu.c                              | 1299 ++++++++++++++++++++
 src/util/virhostcpu.h                              |   54 +
 src/{nodeinfopriv.h => util/virhostcpupriv.h}      |   12 +-
 [...snipped countless more test data renames....]
 rename tests/{nodeinfodata => virhostcpudata}/linux-x86_64-test7.expected (100%)
 rename tests/{nodeinfodata => virhostcpudata}/linux-x86_64-test8.cpuinfo (100%)
 rename tests/{nodeinfodata => virhostcpudata}/linux-x86_64-test8.expected (100%)
 rename tests/{nodeinfomock.c => virhostcpumock.c} (95%)
 rename tests/{nodeinfotest.c => virhostcputest.c} (89%)

diff --git a/cfg.mk b/cfg.mk
index cd3b515..b1b8bdc 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -1161,7 +1161,7 @@ exclude_file_name_regexp--sc_prohibit_close = \
   (\.p[yl]$$|\.spec\.in$$|^docs/|^(src/util/virfile\.c|src/libvirt-stream\.c|tests/vir.+mock\.c)$$)
 
 exclude_file_name_regexp--sc_prohibit_empty_lines_at_EOF = \
-  (^tests/(qemuhelp|nodeinfo|virpcitest)data/|\.diff$$)
+  (^tests/(qemuhelp|virhostcpu|virpcitest)data/|\.diff$$)
 
 _src2=src/(util/vircommand|libvirt|lxc/lxc_controller|locking/lock_daemon|logging/log_daemon)
 exclude_file_name_regexp--sc_prohibit_fork_wrappers = \
@@ -1208,7 +1208,7 @@ exclude_file_name_regexp--sc_require_config_h_first = \
 	^(examples/|tools/virsh-edit\.c$$)
 
 exclude_file_name_regexp--sc_trailing_blank = \
-  /qemuhelpdata/|/sysinfodata/.*\.data|/nodeinfodata/.*\.cpuinfo$$
+  /qemuhelpdata/|/sysinfodata/.*\.data|/virhostcpudata/.*\.cpuinfo$$
 
 exclude_file_name_regexp--sc_unmarked_diagnostics = \
   ^(docs/apibuild.py|tests/virt-aa-helper-test)$$
@@ -1239,7 +1239,7 @@ exclude_file_name_regexp--sc_prohibit_mixed_case_abbreviations = \
   ^src/(vbox/vbox_CAPI.*.h|esx/esx_vi.(c|h)|esx/esx_storage_backend_iscsi.c)$$
 
 exclude_file_name_regexp--sc_prohibit_empty_first_line = \
-  ^(README|daemon/THREADS\.txt|src/esx/README|docs/library.xen|tests/(vmwarever|nodeinfo)data/.*)$$
+  ^(README|daemon/THREADS\.txt|src/esx/README|docs/library.xen|tests/(vmwarever|virhostcpu)data/.*)$$
 
 exclude_file_name_regexp--sc_prohibit_useless_translation = \
   ^tests/virpolkittest.c
diff --git a/po/POTFILES.in b/po/POTFILES.in
index ca23526..b0cd8cf 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -195,6 +195,7 @@ src/util/virfile.c
 src/util/virfirewall.c
 src/util/virhash.c
 src/util/virhook.c
+src/util/virhostcpu.c
 src/util/virhostdev.c
 src/util/viridentity.c
 src/util/virinitctl.c
diff --git a/src/Makefile.am b/src/Makefile.am
index f5e57c0..8d2a8e0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -118,6 +118,7 @@ UTIL_SOURCES =							\
 		util/virhash.c util/virhash.h			\
 		util/virhashcode.c util/virhashcode.h		\
 		util/virhook.c util/virhook.h			\
+		util/virhostcpu.c util/virhostcpu.h util/virhostcpupriv.h \
 		util/virhostdev.c util/virhostdev.h		\
 		util/viridentity.c util/viridentity.h		\
 		util/virinitctl.c util/virinitctl.h		\
@@ -190,7 +191,7 @@ util/virkeymaps.h: $(srcdir)/util/keymaps.csv	\
 	  <$(srcdir)/util/keymaps.csv >util/virkeymaps.h
 
 # Internal generic driver infrastructure
-NODE_INFO_SOURCES = nodeinfo.h nodeinfo.c nodeinfopriv.h
+NODE_INFO_SOURCES = nodeinfo.h nodeinfo.c
 DATATYPES_SOURCES = datatypes.h datatypes.c
 DRIVER_SOURCES =							\
 		driver.c driver.h					\
diff --git a/src/libvirt_linux.syms b/src/libvirt_linux.syms
index a2fc076..a864b78 100644
--- a/src/libvirt_linux.syms
+++ b/src/libvirt_linux.syms
@@ -2,7 +2,7 @@
 # Linux-specific private symbols.
 #
 
-# nodeinfo.h
+# util/virhostcpu.h
 virHostCPUGetInfoPopulateLinux;
 virHostCPUGetStatsLinux;
 virHostCPUSetSysFSSystemPathLinux;
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 45ad25e..d59192d 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -59,7 +59,7 @@
 #include "virfile.h"
 #include "virpidfile.h"
 #include "vircommand.h"
-#include "nodeinfo.h"
+#include "virhostcpu.h"
 #include "virrandom.h"
 #include "virprocess.h"
 #include "virnuma.h"
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index c5e9a5f..2cecabc 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -51,6 +51,7 @@
 #include "virnetdevveth.h"
 #include "virnetdevopenvswitch.h"
 #include "nodeinfo.h"
+#include "virhostcpu.h"
 #include "viruuid.h"
 #include "virstats.h"
 #include "virhook.h"
diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index a3d0024..8bf495f 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -46,10 +46,9 @@
 # include <sys/resource.h>
 #endif
 
-#include "c-ctype.h"
 #include "viralloc.h"
-#include "nodeinfopriv.h"
 #include "nodeinfo.h"
+#include "virhostcpu.h"
 #include "physmem.h"
 #include "virerror.h"
 #include "count-one-bits.h"
@@ -66,126 +65,9 @@
 VIR_LOG_INIT("nodeinfo");
 
 
-#if defined(__FreeBSD__) || defined(__APPLE__)
-static int
-virHostCPUGetCountAppleFreeBSD(void)
-{
-    int ncpu_mib[2] = { CTL_HW, HW_NCPU };
-    unsigned long ncpu;
-    size_t ncpu_len = sizeof(ncpu);
-
-    if (sysctl(ncpu_mib, 2, &ncpu, &ncpu_len, NULL, 0) == -1) {
-        virReportSystemError(errno, "%s", _("Cannot obtain CPU count"));
-        return -1;
-    }
-
-    return ncpu;
-}
-#endif /* defined(__FreeBSD__) || defined(__APPLE__) */
-
 #ifdef __FreeBSD__
-# define BSD_CPU_STATS_ALL 4
 # define BSD_MEMORY_STATS_ALL 4
 
-# define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / (stathz ? stathz : hz))
-
-static int
-virHostCPUGetStatsFreebsd(int cpuNum,
-                          virNodeCPUStatsPtr params,
-                          int *nparams)
-{
-    const char *sysctl_name;
-    long *cpu_times;
-    struct clockinfo clkinfo;
-    size_t i, j, cpu_times_size, clkinfo_size;
-    int cpu_times_num, offset, hz, stathz, ret = -1;
-    struct field_cpu_map {
-        const char *field;
-        int idx[CPUSTATES];
-    } cpu_map[] = {
-        {VIR_NODE_CPU_STATS_KERNEL, {CP_SYS}},
-        {VIR_NODE_CPU_STATS_USER, {CP_USER, CP_NICE}},
-        {VIR_NODE_CPU_STATS_IDLE, {CP_IDLE}},
-        {VIR_NODE_CPU_STATS_INTR, {CP_INTR}},
-        {NULL, {0}}
-    };
-
-    if ((*nparams) == 0) {
-        *nparams = BSD_CPU_STATS_ALL;
-        return 0;
-    }
-
-    if ((*nparams) != BSD_CPU_STATS_ALL) {
-        virReportInvalidArg(*nparams,
-                            _("nparams in %s must be equal to %d"),
-                            __FUNCTION__, BSD_CPU_STATS_ALL);
-        return -1;
-    }
-
-    clkinfo_size = sizeof(clkinfo);
-    if (sysctlbyname("kern.clockrate", &clkinfo, &clkinfo_size, NULL, 0) < 0) {
-        virReportSystemError(errno,
-                             _("sysctl failed for '%s'"),
-                             "kern.clockrate");
-        return -1;
-    }
-
-    stathz = clkinfo.stathz;
-    hz = clkinfo.hz;
-
-    if (cpuNum == VIR_NODE_CPU_STATS_ALL_CPUS) {
-        sysctl_name = "kern.cp_time";
-        cpu_times_num = 1;
-        offset = 0;
-    } else {
-        sysctl_name = "kern.cp_times";
-        cpu_times_num = virHostCPUGetCountAppleFreeBSD();
-
-        if (cpuNum >= cpu_times_num) {
-            virReportInvalidArg(cpuNum,
-                                _("Invalid cpuNum in %s"),
-                                __FUNCTION__);
-            return -1;
-        }
-
-        offset = cpu_times_num * CPUSTATES;
-    }
-
-    cpu_times_size = sizeof(long) * cpu_times_num * CPUSTATES;
-
-    if (VIR_ALLOC_N(cpu_times, cpu_times_num * CPUSTATES) < 0)
-        goto cleanup;
-
-    if (sysctlbyname(sysctl_name, cpu_times, &cpu_times_size, NULL, 0) < 0) {
-        virReportSystemError(errno,
-                             _("sysctl failed for '%s'"),
-                             sysctl_name);
-        goto cleanup;
-    }
-
-    for (i = 0; cpu_map[i].field != NULL; i++) {
-        virNodeCPUStatsPtr param = &params[i];
-
-        if (virStrcpyStatic(param->field, cpu_map[i].field) == NULL) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Field '%s' too long for destination"),
-                           cpu_map[i].field);
-            goto cleanup;
-        }
-
-        param->value = 0;
-        for (j = 0; j < ARRAY_CARDINALITY(cpu_map[i].idx); j++)
-            param->value += cpu_times[offset + cpu_map[i].idx[j]] * TICK_TO_NSEC;
-    }
-
-    ret = 0;
-
- cleanup:
-    VIR_FREE(cpu_times);
-
-    return ret;
-}
-
 static int
 virHostMemGetStatsFreeBSD(virNodeMemoryStatsPtr params,
                           int *nparams)
@@ -263,26 +145,13 @@ virHostMemGetStatsFreeBSD(virNodeMemoryStatsPtr params,
 
 #ifdef __linux__
 # define SYSFS_SYSTEM_PATH "/sys/devices/system"
-# define CPUINFO_PATH "/proc/cpuinfo"
-# define PROCSTAT_PATH "/proc/stat"
 # define MEMINFO_PATH "/proc/meminfo"
 # define SYSFS_MEMORY_SHARED_PATH "/sys/kernel/mm/ksm"
 # define SYSFS_THREAD_SIBLINGS_LIST_LENGTH_MAX 8192
 
-# define LINUX_NB_CPU_STATS 4
 # define LINUX_NB_MEMORY_STATS_ALL 4
 # define LINUX_NB_MEMORY_STATS_CELL 2
 
-static const char *sysfs_system_path = SYSFS_SYSTEM_PATH;
-
-void virHostCPUSetSysFSSystemPathLinux(const char *path)
-{
-    if (path)
-        sysfs_system_path = path;
-    else
-        sysfs_system_path = SYSFS_SYSTEM_PATH;
-}
-
 /* Return the positive decimal contents of the given
  * DIR/cpu%u/FILE, or -1 on error.  If DEFAULT_VALUE is non-negative
  * and the file could not be found, return that instead of an error;
@@ -329,635 +198,6 @@ virNodeGetCpuValue(const char *dir, unsigned int cpu, const char *file,
     return value;
 }
 
-static unsigned long
-virHostCPUCountThreadSiblings(const char *dir, unsigned int cpu)
-{
-    unsigned long ret = 0;
-    char *path;
-    char *str = NULL;
-    size_t i;
-
-    if (virAsprintf(&path, "%s/cpu%u/topology/thread_siblings",
-                    dir, cpu) < 0)
-        return 0;
-
-    if (!virFileExists(path)) {
-        /* If file doesn't exist, then pretend our only
-         * sibling is ourself */
-        ret = 1;
-        goto cleanup;
-    }
-
-    if (virFileReadAll(path, SYSFS_THREAD_SIBLINGS_LIST_LENGTH_MAX, &str) < 0)
-        goto cleanup;
-
-    for (i = 0; str[i] != '\0'; i++) {
-        if (c_isxdigit(str[i]))
-            ret += count_one_bits(virHexToBin(str[i]));
-    }
-
- cleanup:
-    VIR_FREE(str);
-    VIR_FREE(path);
-    return ret;
-}
-
-static int
-virHostCPUParseSocket(const char *dir,
-                      virArch arch,
-                      unsigned int cpu)
-{
-    int ret = virNodeGetCpuValue(dir, cpu, "topology/physical_package_id", 0);
-
-    if (ARCH_IS_ARM(arch) || ARCH_IS_PPC(arch) || ARCH_IS_S390(arch)) {
-        /* arm, ppc and s390(x) has -1 */
-        if (ret < 0)
-            ret = 0;
-    }
-
-    return ret;
-}
-
-/* parses a node entry, returning number of processors in the node and
- * filling arguments */
-static int
-ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3)
-ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(6)
-ATTRIBUTE_NONNULL(7) ATTRIBUTE_NONNULL(8)
-ATTRIBUTE_NONNULL(9)
-virHostCPUParseNode(const char *node,
-                    virArch arch,
-                    virBitmapPtr present_cpus_map,
-                    virBitmapPtr online_cpus_map,
-                    int threads_per_subcore,
-                    int *sockets,
-                    int *cores,
-                    int *threads,
-                    int *offline)
-{
-    /* Biggest value we can expect to be used as either socket id
-     * or core id. Bitmaps will need to be sized accordingly */
-    const int ID_MAX = 4095;
-    int ret = -1;
-    int processors = 0;
-    DIR *cpudir = NULL;
-    struct dirent *cpudirent = NULL;
-    virBitmapPtr node_cpus_map = NULL;
-    virBitmapPtr sockets_map = NULL;
-    virBitmapPtr *cores_maps = NULL;
-    int npresent_cpus = virBitmapSize(present_cpus_map);
-    int sock_max = 0;
-    int sock;
-    int core;
-    size_t i;
-    int siblings;
-    unsigned int cpu;
-    int direrr;
-
-    *threads = 0;
-    *cores = 0;
-    *sockets = 0;
-
-    if (!(cpudir = opendir(node))) {
-        virReportSystemError(errno, _("cannot opendir %s"), node);
-        goto cleanup;
-    }
-
-    /* Keep track of the CPUs that belong to the current node */
-    if (!(node_cpus_map = virBitmapNew(npresent_cpus)))
-        goto cleanup;
-
-    /* enumerate sockets in the node */
-    if (!(sockets_map = virBitmapNew(ID_MAX + 1)))
-        goto cleanup;
-
-    while ((direrr = virDirRead(cpudir, &cpudirent, node)) > 0) {
-        if (sscanf(cpudirent->d_name, "cpu%u", &cpu) != 1)
-            continue;
-
-        if (!virBitmapIsBitSet(present_cpus_map, cpu))
-            continue;
-
-        /* Mark this CPU as part of the current node */
-        if (virBitmapSetBit(node_cpus_map, cpu) < 0)
-            goto cleanup;
-
-        if (!virBitmapIsBitSet(online_cpus_map, cpu))
-            continue;
-
-        /* Parse socket */
-        if ((sock = virHostCPUParseSocket(node, arch, cpu)) < 0)
-            goto cleanup;
-        if (sock > ID_MAX) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Socket %d can't be handled (max socket is %d)"),
-                           sock, ID_MAX);
-            goto cleanup;
-        }
-
-        if (virBitmapSetBit(sockets_map, sock) < 0)
-            goto cleanup;
-
-        if (sock > sock_max)
-            sock_max = sock;
-    }
-
-    if (direrr < 0)
-        goto cleanup;
-
-    sock_max++;
-
-    /* allocate cores maps for each socket */
-    if (VIR_ALLOC_N(cores_maps, sock_max) < 0)
-        goto cleanup;
-
-    for (i = 0; i < sock_max; i++)
-        if (!(cores_maps[i] = virBitmapNew(ID_MAX + 1)))
-            goto cleanup;
-
-    /* Iterate over all CPUs in the node, in ascending order */
-    for (cpu = 0; cpu < npresent_cpus; cpu++) {
-
-        /* Skip CPUs that are not part of the current node */
-        if (!virBitmapIsBitSet(node_cpus_map, cpu))
-            continue;
-
-        if (!virBitmapIsBitSet(online_cpus_map, cpu)) {
-            if (threads_per_subcore > 0 &&
-                cpu % threads_per_subcore != 0 &&
-                virBitmapIsBitSet(online_cpus_map,
-                                  cpu - (cpu % threads_per_subcore))) {
-                /* Secondary offline threads are counted as online when
-                 * subcores are in use and the corresponding primary
-                 * thread is online */
-                processors++;
-            } else {
-                /* But they are counted as offline otherwise */
-                (*offline)++;
-            }
-            continue;
-        }
-
-        processors++;
-
-        /* Parse socket */
-        if ((sock = virHostCPUParseSocket(node, arch, cpu)) < 0)
-            goto cleanup;
-        if (!virBitmapIsBitSet(sockets_map, sock)) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("CPU socket topology has changed"));
-            goto cleanup;
-        }
-
-        /* Parse core */
-        if (ARCH_IS_S390(arch)) {
-            /* logical cpu is equivalent to a core on s390 */
-            core = cpu;
-        } else {
-            if ((core = virNodeGetCpuValue(node, cpu,
-                                           "topology/core_id", 0)) < 0)
-                goto cleanup;
-        }
-        if (core > ID_MAX) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Core %d can't be handled (max core is %d)"),
-                           core, ID_MAX);
-            goto cleanup;
-        }
-
-        if (virBitmapSetBit(cores_maps[sock], core) < 0)
-            goto cleanup;
-
-        if (!(siblings = virHostCPUCountThreadSiblings(node, cpu)))
-            goto cleanup;
-
-        if (siblings > *threads)
-            *threads = siblings;
-    }
-
-    /* finalize the returned data */
-    *sockets = virBitmapCountBits(sockets_map);
-
-    for (i = 0; i < sock_max; i++) {
-        if (!virBitmapIsBitSet(sockets_map, i))
-            continue;
-
-        core = virBitmapCountBits(cores_maps[i]);
-        if (core > *cores)
-            *cores = core;
-    }
-
-    if (threads_per_subcore > 0) {
-        /* The thread count ignores offline threads, which means that only
-         * only primary threads have been considered so far. If subcores
-         * are in use, we need to also account for secondary threads */
-        *threads *= threads_per_subcore;
-    }
-    ret = processors;
-
- cleanup:
-    /* don't shadow a more serious error */
-    if (cpudir && closedir(cpudir) < 0 && ret >= 0) {
-        virReportSystemError(errno, _("problem closing %s"), node);
-        ret = -1;
-    }
-    if (cores_maps)
-        for (i = 0; i < sock_max; i++)
-            virBitmapFree(cores_maps[i]);
-    VIR_FREE(cores_maps);
-    virBitmapFree(sockets_map);
-    virBitmapFree(node_cpus_map);
-
-    return ret;
-}
-
-/* Check whether the host subcore configuration is valid.
- *
- * A valid configuration is one where no secondary thread is online;
- * the primary thread in a subcore is always the first one */
-static bool
-virHostCPUHasValidSubcoreConfiguration(int threads_per_subcore)
-{
-    virBitmapPtr online_cpus = NULL;
-    int cpu = -1;
-    bool ret = false;
-
-    /* No point in checking if subcores are not in use */
-    if (threads_per_subcore <= 0)
-        goto cleanup;
-
-    if (!(online_cpus = virHostCPUGetOnlineBitmap()))
-        goto cleanup;
-
-    while ((cpu = virBitmapNextSetBit(online_cpus, cpu)) >= 0) {
-
-        /* A single online secondary thread is enough to
-         * make the configuration invalid */
-        if (cpu % threads_per_subcore != 0)
-            goto cleanup;
-    }
-
-    ret = true;
-
- cleanup:
-    virBitmapFree(online_cpus);
-
-    return ret;
-}
-
-int
-virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
-                               virArch arch,
-                               unsigned int *cpus,
-                               unsigned int *mhz,
-                               unsigned int *nodes,
-                               unsigned int *sockets,
-                               unsigned int *cores,
-                               unsigned int *threads)
-{
-    virBitmapPtr present_cpus_map = NULL;
-    virBitmapPtr online_cpus_map = NULL;
-    char line[1024];
-    DIR *nodedir = NULL;
-    struct dirent *nodedirent = NULL;
-    int nodecpus, nodecores, nodesockets, nodethreads, offline = 0;
-    int threads_per_subcore = 0;
-    unsigned int node;
-    int ret = -1;
-    char *sysfs_nodedir = NULL;
-    char *sysfs_cpudir = NULL;
-    int direrr;
-
-    *mhz = 0;
-    *cpus = *nodes = *sockets = *cores = *threads = 0;
-
-    /* Start with parsing CPU clock speed from /proc/cpuinfo */
-    while (fgets(line, sizeof(line), cpuinfo) != NULL) {
-        if (ARCH_IS_X86(arch)) {
-            char *buf = line;
-            if (STRPREFIX(buf, "cpu MHz")) {
-                char *p;
-                unsigned int ui;
-
-                buf += 7;
-                while (*buf && c_isspace(*buf))
-                    buf++;
-
-                if (*buf != ':' || !buf[1]) {
-                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                   _("parsing cpu MHz from cpuinfo"));
-                    goto cleanup;
-                }
-
-                if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 &&
-                    /* Accept trailing fractional part.  */
-                    (*p == '\0' || *p == '.' || c_isspace(*p)))
-                    *mhz = ui;
-            }
-        } else if (ARCH_IS_PPC(arch)) {
-            char *buf = line;
-            if (STRPREFIX(buf, "clock")) {
-                char *p;
-                unsigned int ui;
-
-                buf += 5;
-                while (*buf && c_isspace(*buf))
-                    buf++;
-
-                if (*buf != ':' || !buf[1]) {
-                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                   _("parsing cpu MHz from cpuinfo"));
-                    goto cleanup;
-                }
-
-                if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 &&
-                    /* Accept trailing fractional part.  */
-                    (*p == '\0' || *p == '.' || c_isspace(*p)))
-                    *mhz = ui;
-                /* No other interesting infos are available in /proc/cpuinfo.
-                 * However, there is a line identifying processor's version,
-                 * identification and machine, but we don't want it to be caught
-                 * and parsed in next iteration, because it is not in expected
-                 * format and thus lead to error. */
-            }
-        } else if (ARCH_IS_ARM(arch)) {
-            char *buf = line;
-            if (STRPREFIX(buf, "BogoMIPS")) {
-                char *p;
-                unsigned int ui;
-
-                buf += 8;
-                while (*buf && c_isspace(*buf))
-                    buf++;
-
-                if (*buf != ':' || !buf[1]) {
-                    virReportError(VIR_ERR_INTERNAL_ERROR,
-                                   "%s", _("parsing cpu MHz from cpuinfo"));
-                    goto cleanup;
-                }
-
-                if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
-                    /* Accept trailing fractional part.  */
-                    && (*p == '\0' || *p == '.' || c_isspace(*p)))
-                    *mhz = ui;
-            }
-        } else if (ARCH_IS_S390(arch)) {
-            /* s390x has no realistic value for CPU speed,
-             * assign a value of zero to signify this */
-            *mhz = 0;
-        } else {
-            VIR_WARN("Parser for /proc/cpuinfo needs to be adapted for your architecture");
-            break;
-        }
-    }
-
-    /* Get information about what CPUs are present in the host and what
-     * CPUs are online, so that we don't have to so for each node */
-    present_cpus_map = virHostCPUGetPresentBitmap();
-    if (!present_cpus_map)
-        goto cleanup;
-    online_cpus_map = virHostCPUGetOnlineBitmap();
-    if (!online_cpus_map)
-        goto cleanup;
-
-    /* OK, we've parsed clock speed out of /proc/cpuinfo. Get the
-     * core, node, socket, thread and topology information from /sys
-     */
-    if (virAsprintf(&sysfs_nodedir, "%s/node", sysfs_system_path) < 0)
-        goto cleanup;
-
-    if (!(nodedir = opendir(sysfs_nodedir))) {
-        /* the host isn't probably running a NUMA architecture */
-        goto fallback;
-    }
-
-    /* PPC-KVM needs the secondary threads of a core to be offline on the
-     * host. The kvm scheduler brings the secondary threads online in the
-     * guest context. Moreover, P8 processor has split-core capability
-     * where, there can be 1,2 or 4 subcores per core. The primaries of the
-     * subcores alone will be online on the host for a subcore in the
-     * host. Even though the actual threads per core for P8 processor is 8,
-     * depending on the subcores_per_core = 1, 2 or 4, the threads per
-     * subcore will vary accordingly to 8, 4 and 2 repectively.
-     * So, On host threads_per_core what is arrived at from sysfs in the
-     * current logic is actually the subcores_per_core. Threads per subcore
-     * can only be obtained from the kvm device. For example, on P8 wih 1
-     * core having 8 threads, sub_cores_percore=4, the threads 0,2,4 & 6
-     * will be online. The sysfs reflects this and in the current logic
-     * variable 'threads' will be 4 which is nothing but subcores_per_core.
-     * If the user tampers the cpu online/offline states using chcpu or other
-     * means, then it is an unsupported configuration for kvm.
-     * The code below tries to keep in mind
-     *  - when the libvirtd is run inside a KVM guest or Phyp based guest.
-     *  - Or on the kvm host where user manually tampers the cpu states to
-     *    offline/online randomly.
-     * On hosts other than POWER this will be 0, in which case a simpler
-     * thread-counting logic will be used  */
-    if ((threads_per_subcore = virHostCPUGetThreadsPerSubcore(arch)) < 0)
-        goto cleanup;
-
-    /* If the subcore configuration is not valid, just pretend subcores
-     * are not in use and count threads one by one */
-    if (!virHostCPUHasValidSubcoreConfiguration(threads_per_subcore))
-        threads_per_subcore = 0;
-
-    while ((direrr = virDirRead(nodedir, &nodedirent, sysfs_nodedir)) > 0) {
-        if (sscanf(nodedirent->d_name, "node%u", &node) != 1)
-            continue;
-
-        (*nodes)++;
-
-        if (virAsprintf(&sysfs_cpudir, "%s/node/%s",
-                        sysfs_system_path, nodedirent->d_name) < 0)
-            goto cleanup;
-
-        if ((nodecpus = virHostCPUParseNode(sysfs_cpudir, arch,
-                                            present_cpus_map,
-                                            online_cpus_map,
-                                            threads_per_subcore,
-                                            &nodesockets, &nodecores,
-                                            &nodethreads, &offline)) < 0)
-            goto cleanup;
-
-        VIR_FREE(sysfs_cpudir);
-
-        *cpus += nodecpus;
-
-        if (nodesockets > *sockets)
-            *sockets = nodesockets;
-
-        if (nodecores > *cores)
-            *cores = nodecores;
-
-        if (nodethreads > *threads)
-            *threads = nodethreads;
-    }
-
-    if (direrr < 0)
-        goto cleanup;
-
-    if (*cpus && *nodes)
-        goto done;
-
- fallback:
-    VIR_FREE(sysfs_cpudir);
-
-    if (virAsprintf(&sysfs_cpudir, "%s/cpu", sysfs_system_path) < 0)
-        goto cleanup;
-
-    if ((nodecpus = virHostCPUParseNode(sysfs_cpudir, arch,
-                                        present_cpus_map,
-                                        online_cpus_map,
-                                        threads_per_subcore,
-                                        &nodesockets, &nodecores,
-                                        &nodethreads, &offline)) < 0)
-        goto cleanup;
-
-    *nodes = 1;
-    *cpus = nodecpus;
-    *sockets = nodesockets;
-    *cores = nodecores;
-    *threads = nodethreads;
-
- done:
-    /* There should always be at least one cpu, socket, node, and thread. */
-    if (*cpus == 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no CPUs found"));
-        goto cleanup;
-    }
-
-    if (*sockets == 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no sockets found"));
-        goto cleanup;
-    }
-
-    if (*threads == 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no threads found"));
-        goto cleanup;
-    }
-
-    /* Now check if the topology makes sense. There are machines that don't
-     * expose their real number of nodes or for example the AMD Bulldozer
-     * architecture that exposes their Clustered integer core modules as both
-     * threads and cores. This approach throws off our detection. Unfortunately
-     * the nodeinfo structure isn't designed to carry the full topology so
-     * we're going to lie about the detected topology to notify the user
-     * to check the host capabilities for the actual topology. */
-    if ((*nodes *
-         *sockets *
-         *cores *
-         *threads) != (*cpus + offline)) {
-        *nodes = 1;
-        *sockets = 1;
-        *cores = *cpus + offline;
-        *threads = 1;
-    }
-
-    ret = 0;
-
- cleanup:
-    /* don't shadow a more serious error */
-    if (nodedir && closedir(nodedir) < 0 && ret >= 0) {
-        virReportSystemError(errno, _("problem closing %s"), sysfs_nodedir);
-        ret = -1;
-    }
-
-    virBitmapFree(present_cpus_map);
-    virBitmapFree(online_cpus_map);
-    VIR_FREE(sysfs_nodedir);
-    VIR_FREE(sysfs_cpudir);
-    return ret;
-}
-
-static int
-virHostCPUStatsAssign(virNodeCPUStatsPtr param,
-                      const char *name,
-                      unsigned long long value)
-{
-    if (virStrcpyStatic(param->field, name) == NULL) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       "%s", _("kernel cpu time field is too long"
-                               " for the destination"));
-        return -1;
-    }
-    param->value = value;
-    return 0;
-}
-
-# define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / sysconf(_SC_CLK_TCK))
-
-int
-virHostCPUGetStatsLinux(FILE *procstat,
-                        int cpuNum,
-                        virNodeCPUStatsPtr params,
-                        int *nparams)
-{
-    int ret = -1;
-    char line[1024];
-    unsigned long long usr, ni, sys, idle, iowait;
-    unsigned long long irq, softirq, steal, guest, guest_nice;
-    char cpu_header[4 + INT_BUFSIZE_BOUND(cpuNum)];
-
-    if ((*nparams) == 0) {
-        /* Current number of cpu stats supported by linux */
-        *nparams = LINUX_NB_CPU_STATS;
-        ret = 0;
-        goto cleanup;
-    }
-
-    if ((*nparams) != LINUX_NB_CPU_STATS) {
-        virReportInvalidArg(*nparams,
-                            _("nparams in %s must be equal to %d"),
-                            __FUNCTION__, LINUX_NB_CPU_STATS);
-        goto cleanup;
-    }
-
-    if (cpuNum == VIR_NODE_CPU_STATS_ALL_CPUS) {
-        strcpy(cpu_header, "cpu ");
-    } else {
-        snprintf(cpu_header, sizeof(cpu_header), "cpu%d ", cpuNum);
-    }
-
-    while (fgets(line, sizeof(line), procstat) != NULL) {
-        char *buf = line;
-
-        if (STRPREFIX(buf, cpu_header)) { /* aka logical CPU time */
-            if (sscanf(buf,
-                       "%*s %llu %llu %llu %llu %llu" // user ~ iowait
-                       "%llu %llu %llu %llu %llu",    // irq  ~ guest_nice
-                       &usr, &ni, &sys, &idle, &iowait,
-                       &irq, &softirq, &steal, &guest, &guest_nice) < 4) {
-                continue;
-            }
-
-            if (virHostCPUStatsAssign(&params[0], VIR_NODE_CPU_STATS_KERNEL,
-                                      (sys + irq + softirq) * TICK_TO_NSEC) < 0)
-                goto cleanup;
-
-            if (virHostCPUStatsAssign(&params[1], VIR_NODE_CPU_STATS_USER,
-                                      (usr + ni) * TICK_TO_NSEC) < 0)
-                goto cleanup;
-
-            if (virHostCPUStatsAssign(&params[2], VIR_NODE_CPU_STATS_IDLE,
-                                      idle * TICK_TO_NSEC) < 0)
-                goto cleanup;
-
-            if (virHostCPUStatsAssign(&params[3], VIR_NODE_CPU_STATS_IOWAIT,
-                                      iowait * TICK_TO_NSEC) < 0)
-                goto cleanup;
-
-            ret = 0;
-            goto cleanup;
-        }
-    }
-
-    virReportInvalidArg(cpuNum,
-                        _("Invalid cpuNum in %s"),
-                        __FUNCTION__);
-
- cleanup:
-    return ret;
-}
 
 static int
 virHostMemGetStatsLinux(FILE *meminfo,
@@ -1065,84 +305,6 @@ virHostMemGetStatsLinux(FILE *meminfo,
     return ret;
 }
 
-static char *
-virHostCPUGetGlobalPathLinux(const char *file)
-{
-    char *path = NULL;
-
-    if (virAsprintf(&path, "%s/cpu/%s", sysfs_system_path, file) < 0)
-        return NULL;
-
-    return path;
-}
-
-static char *
-virHostCPUGetPresentPathLinux(void)
-{
-    return virHostCPUGetGlobalPathLinux("present");
-}
-
-static char *
-virHostCPUGetOnlinePathLinux(void)
-{
-    return virHostCPUGetGlobalPathLinux("online");
-}
-
-/* Determine the number of CPUs (maximum CPU id + 1) from a file containing
- * a list of CPU ids, like the Linux sysfs cpu/present file */
-static int
-virHostCPUParseCountLinux(const char *path)
-{
-    char *str = NULL;
-    char *tmp;
-    int ret = -1;
-
-    if (virFileReadAll(path, 5 * VIR_DOMAIN_CPUMASK_LEN, &str) < 0)
-        goto cleanup;
-
-    tmp = str;
-    do {
-        if (virStrToLong_i(tmp, &tmp, 10, &ret) < 0 ||
-            !strchr(",-\n", *tmp)) {
-            virReportError(VIR_ERR_NO_SUPPORT,
-                           _("failed to parse %s"), path);
-            ret = -1;
-            goto cleanup;
-        }
-    } while (*tmp++ != '\n');
-    ret++;
-
- cleanup:
-    VIR_FREE(str);
-    return ret;
-}
-
-/*
- * Linux maintains cpu bit map under cpu/online. For example, if
- * cpuid=5's flag is not set and max cpu is 7, the map file shows
- * 0-4,6-7. This function parses it and returns cpumap.
- */
-static virBitmapPtr
-virHostCPUParseMapLinux(int max_cpuid, const char *path)
-{
-    virBitmapPtr map = NULL;
-    char *str = NULL;
-
-    if (virFileReadAll(path, 5 * VIR_DOMAIN_CPUMASK_LEN, &str) < 0)
-        goto error;
-
-    if (virBitmapParse(str, 0, &map, max_cpuid) < 0)
-        goto error;
-
-    VIR_FREE(str);
-    return map;
-
- error:
-    VIR_FREE(str);
-    virBitmapFree(map);
-    return NULL;
-}
-
 
 static virBitmapPtr
 virNodeGetSiblingsListLinux(const char *dir, int cpu_id)
@@ -1169,73 +331,6 @@ virNodeGetSiblingsListLinux(const char *dir, int cpu_id)
 #endif
 
 
-static int
-virHostCPUGetInfo(virArch hostarch,
-                  unsigned int *cpus,
-                  unsigned int *mhz,
-                  unsigned int *nodes,
-                  unsigned int *sockets,
-                  unsigned int *cores,
-                  unsigned int *threads)
-{
-#ifdef __linux__
-    int ret = -1;
-    FILE *cpuinfo = fopen(CPUINFO_PATH, "r");
-
-    if (!cpuinfo) {
-        virReportSystemError(errno,
-                             _("cannot open %s"), CPUINFO_PATH);
-        return -1;
-    }
-
-    ret = virHostCPUGetInfoPopulateLinux(cpuinfo, hostarch,
-                                         cpus, mhz, nodes,
-                                         sockets, cores, threads);
-    if (ret < 0)
-        goto cleanup;
-
- cleanup:
-    VIR_FORCE_FCLOSE(cpuinfo);
-    return ret;
-#elif defined(__FreeBSD__) || defined(__APPLE__)
-    unsigned long cpu_freq;
-    size_t cpu_freq_len = sizeof(cpu_freq);
-
-    *cpus = virHostCPUGetCountAppleFreeBSD();
-    if (*cpus == -1)
-        return -1;
-
-    *nodes = 1;
-    *sockets = 1;
-    *cores = *cpus;
-    *threads = 1;
-
-# ifdef __FreeBSD__
-    if (sysctlbyname("dev.cpu.0.freq", &cpu_freq, &cpu_freq_len, NULL, 0) < 0) {
-        virReportSystemError(errno, "%s", _("cannot obtain CPU freq"));
-        return -1;
-    }
-
-    *mhz = cpu_freq;
-# else
-    if (sysctlbyname("hw.cpufrequency", &cpu_freq, &cpu_freq_len, NULL, 0) < 0) {
-        virReportSystemError(errno, "%s", _("cannot obtain CPU freq"));
-        return -1;
-    }
-
-    *mhz = cpu_freq / 1000000;
-# endif
-
-    return 0;
-#else
-    /* XXX Solaris will need an impl later if they port QEMU driver */
-    virReportError(VIR_ERR_NO_SUPPORT, "%s",
-                   _("node info not implemented on this platform"));
-    return -1;
-#endif
-}
-
-
 int
 nodeGetInfo(virNodeInfoPtr nodeinfo)
 {
@@ -1260,36 +355,6 @@ nodeGetInfo(virNodeInfoPtr nodeinfo)
     return 0;
 }
 
-int
-virHostCPUGetStats(int cpuNum ATTRIBUTE_UNUSED,
-                   virNodeCPUStatsPtr params ATTRIBUTE_UNUSED,
-                   int *nparams ATTRIBUTE_UNUSED,
-                   unsigned int flags)
-{
-    virCheckFlags(0, -1);
-
-#ifdef __linux__
-    {
-        int ret;
-        FILE *procstat = fopen(PROCSTAT_PATH, "r");
-        if (!procstat) {
-            virReportSystemError(errno,
-                                 _("cannot open %s"), PROCSTAT_PATH);
-            return -1;
-        }
-        ret = virHostCPUGetStatsLinux(procstat, cpuNum, params, nparams);
-        VIR_FORCE_FCLOSE(procstat);
-
-        return ret;
-    }
-#elif defined(__FreeBSD__)
-    return virHostCPUGetStatsFreeBSD(cpuNum, params, nparams);
-#else
-    virReportError(VIR_ERR_NO_SUPPORT, "%s",
-                   _("node CPU stats not implemented on this platform"));
-    return -1;
-#endif
-}
 
 int
 virHostMemGetStats(int cellNum ATTRIBUTE_UNUSED,
@@ -1348,146 +413,6 @@ virHostMemGetStats(int cellNum ATTRIBUTE_UNUSED,
 #endif
 }
 
-int
-virHostCPUGetCount(void)
-{
-#if defined(__linux__)
-    /* To support older kernels that lack cpu/present, such as 2.6.18
-     * in RHEL5, we fall back to count cpu/cpuNN entries; this assumes
-     * that such kernels also lack hotplug, and therefore cpu/cpuNN
-     * will be consecutive.
-     */
-    char *present_path = NULL;
-    char *cpupath = NULL;
-    int ncpu = -1;
-
-    if (!(present_path = virHostCPUGetPresentPathLinux()))
-        return -1;
-
-    if (virFileExists(present_path)) {
-        ncpu = virHostCPUParseCountLinux(present_path);
-        goto cleanup;
-    }
-
-    if (virAsprintf(&cpupath, "%s/cpu/cpu0", sysfs_system_path) < 0)
-        goto cleanup;
-    if (virFileExists(cpupath)) {
-        ncpu = 0;
-        do {
-            ncpu++;
-            VIR_FREE(cpupath);
-            if (virAsprintf(&cpupath, "%s/cpu/cpu%d",
-                            sysfs_system_path, ncpu) < 0) {
-                ncpu = -1;
-                goto cleanup;
-            }
-        } while (virFileExists(cpupath));
-    } else {
-        /* no cpu/cpu0: we give up */
-        virReportError(VIR_ERR_NO_SUPPORT, "%s",
-                       _("host cpu counting not supported on this node"));
-    }
-
- cleanup:
-    VIR_FREE(present_path);
-    VIR_FREE(cpupath);
-    return ncpu;
-#elif defined(__FreeBSD__) || defined(__APPLE__)
-    return virHostCPUGetCountAppleFreeBSD();
-#else
-    virReportError(VIR_ERR_NO_SUPPORT, "%s",
-                   _("host cpu counting not implemented on this platform"));
-    return -1;
-#endif
-}
-
-virBitmapPtr
-virHostCPUGetPresentBitmap(void)
-{
-#ifdef __linux__
-    virBitmapPtr present_cpus = NULL;
-    char *present_path = NULL;
-    int npresent_cpus;
-
-    if ((npresent_cpus = virHostCPUGetCount()) < 0)
-        goto cleanup;
-
-    if (!(present_path = virHostCPUGetPresentPathLinux()))
-        goto cleanup;
-
-    /* If the cpu/present file is available, parse it and exit */
-    if (virFileExists(present_path)) {
-        present_cpus = virHostCPUParseMapLinux(npresent_cpus, present_path);
-        goto cleanup;
-    }
-
-    /* If the file is not available, we can assume that the kernel is
-     * too old to support non-consecutive CPU ids and just mark all
-     * possible CPUs as present */
-    if (!(present_cpus = virBitmapNew(npresent_cpus)))
-        goto cleanup;
-
-    virBitmapSetAll(present_cpus);
-
- cleanup:
-    VIR_FREE(present_path);
-
-    return present_cpus;
-#endif
-    virReportError(VIR_ERR_NO_SUPPORT, "%s",
-                   _("node present CPU map not implemented on this platform"));
-    return NULL;
-}
-
-virBitmapPtr
-virHostCPUGetOnlineBitmap(void)
-{
-#ifdef __linux__
-    char *online_path = NULL;
-    char *cpudir = NULL;
-    virBitmapPtr cpumap;
-    int present;
-
-    present = virHostCPUGetCount();
-    if (present < 0)
-        return NULL;
-
-    if (!(online_path = virHostCPUGetOnlinePathLinux()))
-        return NULL;
-    if (virFileExists(online_path)) {
-        cpumap = virHostCPUParseMapLinux(present, online_path);
-    } else {
-        size_t i;
-
-        cpumap = virBitmapNew(present);
-        if (!cpumap)
-            goto cleanup;
-
-        if (virAsprintf(&cpudir, "%s/cpu", sysfs_system_path) < 0)
-            goto cleanup;
-
-        for (i = 0; i < present; i++) {
-            int online = virNodeGetCpuValue(cpudir, i, "online", 1);
-            if (online < 0) {
-                virBitmapFree(cpumap);
-                cpumap = NULL;
-                goto cleanup;
-            }
-            if (online)
-                ignore_value(virBitmapSetBit(cpumap, i));
-        }
-    }
-
- cleanup:
-    VIR_FREE(online_path);
-    VIR_FREE(cpudir);
-    return cpumap;
-#else
-    virReportError(VIR_ERR_NO_SUPPORT, "%s",
-                   _("node online CPU map not implemented on this platform"));
-    return NULL;
-#endif
-}
 
 #ifdef __linux__
 static int
@@ -1791,36 +716,6 @@ virHostMemGetParameters(virTypedParameterPtr params ATTRIBUTE_UNUSED,
 #endif
 }
 
-int
-virHostCPUGetMap(unsigned char **cpumap,
-                 unsigned int *online,
-                 unsigned int flags)
-{
-    virBitmapPtr cpus = NULL;
-    int ret = -1;
-    int dummy;
-
-    virCheckFlags(0, -1);
-
-    if (!cpumap && !online)
-        return virHostCPUGetCount();
-
-    if (!(cpus = virHostCPUGetOnlineBitmap()))
-        goto cleanup;
-
-    if (cpumap && virBitmapToData(cpus, cpumap, &dummy) < 0)
-        goto cleanup;
-    if (online)
-        *online = virBitmapCountBits(cpus);
-
-    ret = virBitmapSize(cpus);
-
- cleanup:
-    if (ret < 0 && cpumap)
-        VIR_FREE(*cpumap);
-    virBitmapFree(cpus);
-    return ret;
-}
 
 static int
 nodeCapsInitNUMAFake(const char *cpupath ATTRIBUTE_UNUSED,
@@ -2329,67 +1224,3 @@ virHostMemAllocPages(unsigned int npages,
  cleanup:
     return ret;
 }
-
-#if HAVE_LINUX_KVM_H && defined(KVM_CAP_PPC_SMT)
-
-/* Get the number of threads per subcore.
- *
- * This will be 2, 4 or 8 on POWER hosts, depending on the current
- * micro-threading configuration, and 0 everywhere else.
- *
- * Returns the number of threads per subcore if subcores are in use, zero
- * if subcores are not in use, and a negative value on error */
-int
-virHostCPUGetThreadsPerSubcore(virArch arch)
-{
-    int threads_per_subcore = 0;
-    const char *kvmpath = "/dev/kvm";
-    int kvmfd;
-
-    if (ARCH_IS_PPC64(arch)) {
-
-        /* It's okay if /dev/kvm doesn't exist, because
-         *   a. we might be running in a guest
-         *   b. the kvm module might not be installed or enabled
-         * In either case, falling back to the subcore-unaware thread
-         * counting logic is the right thing to do */
-        if (!virFileExists(kvmpath))
-            goto out;
-
-        if ((kvmfd = open(kvmpath, O_RDONLY)) < 0) {
-            /* This can happen when running as a regular user if
-             * permissions are tight enough, in which case erroring out
-             * is better than silently falling back and reporting
-             * different nodeinfo depending on the user */
-            virReportSystemError(errno,
-                                 _("Failed to open '%s'"),
-                                 kvmpath);
-            threads_per_subcore = -1;
-            goto out;
-        }
-
-        /* For Phyp and KVM based guests the ioctl for KVM_CAP_PPC_SMT
-         * returns zero and both primary and secondary threads will be
-         * online */
-        threads_per_subcore = ioctl(kvmfd,
-                                    KVM_CHECK_EXTENSION,
-                                    KVM_CAP_PPC_SMT);
-
-        VIR_FORCE_CLOSE(kvmfd);
-    }
-
- out:
-    return threads_per_subcore;
-}
-
-#else
-
-/* Fallback for nodeGetThreadsPerSubcore() used when KVM headers
- * are not available on the system */
-int
-virHostCPUGetThreadsPerSubcore(virArch arch ATTRIBUTE_UNUSED)
-{
-    return 0;
-}
-
-#endif /* HAVE_LINUX_KVM_H && defined(KVM_CAP_PPC_SMT) */
diff --git a/src/nodeinfo.h b/src/nodeinfo.h
index 08b9f9d..918fcb5 100644
--- a/src/nodeinfo.h
+++ b/src/nodeinfo.h
@@ -29,10 +29,6 @@
 int nodeGetInfo(virNodeInfoPtr nodeinfo);
 int nodeCapsInitNUMA(virCapsPtr caps);
 
-int virHostCPUGetStats(int cpuNum,
-                       virNodeCPUStatsPtr params,
-                       int *nparams,
-                       unsigned int flags);
 int virHostMemGetStats(int cellNum,
                        virNodeMemoryStatsPtr params,
                        int *nparams,
@@ -43,11 +39,6 @@ int virHostMemGetCellsFree(unsigned long long *freeMems,
 int virHostMemGetInfo(unsigned long long *mem,
                       unsigned long long *freeMem);
 
-virBitmapPtr virHostCPUGetPresentBitmap(void);
-virBitmapPtr virHostCPUGetOnlineBitmap(void);
-int virHostCPUGetCount(void);
-int virHostCPUGetThreadsPerSubcore(virArch arch);
-
 int virHostMemGetParameters(virTypedParameterPtr params,
                             int *nparams,
                             unsigned int flags);
@@ -56,10 +47,6 @@ int virHostMemSetParameters(virTypedParameterPtr params,
                             int nparams,
                             unsigned int flags);
 
-int virHostCPUGetMap(unsigned char **cpumap,
-                     unsigned int *online,
-                     unsigned int flags);
-
 int virHostMemGetFreePages(unsigned int npages,
                            unsigned int *pages,
                            int startCell,
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
index ef11745..910ccfe 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -49,6 +49,7 @@
 #include "virbuffer.h"
 #include "openvz_conf.h"
 #include "nodeinfo.h"
+#include "virhostcpu.h"
 #include "viralloc.h"
 #include "virfile.h"
 #include "virtypedparam.h"
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 38aab15..ec04fb7 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -63,6 +63,7 @@
 #include "datatypes.h"
 #include "virbuffer.h"
 #include "nodeinfo.h"
+#include "virhostcpu.h"
 #include "virstats.h"
 #include "capabilities.h"
 #include "viralloc.h"
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 7d01e38..5ae38bf 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -54,7 +54,7 @@
 #include "virhook.h"
 #include "virfile.h"
 #include "virpidfile.h"
-#include "nodeinfo.h"
+#include "virhostcpu.h"
 #include "domain_audit.h"
 #include "domain_nwfilter.h"
 #include "locking/domain_lock.h"
diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
index 19ba901..4048b11 100644
--- a/src/uml/uml_driver.c
+++ b/src/uml/uml_driver.c
@@ -46,6 +46,7 @@
 #include "uml_conf.h"
 #include "virbuffer.h"
 #include "nodeinfo.h"
+#include "virhostcpu.h"
 #include "virstats.h"
 #include "capabilities.h"
 #include "viralloc.h"
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
index 05097f8..0124dbe 100644
--- a/src/util/vircgroup.c
+++ b/src/util/vircgroup.c
@@ -52,8 +52,7 @@
 #include "virstring.h"
 #include "virsystemd.h"
 #include "virtypedparam.h"
-
-#include "nodeinfo.h"
+#include "virhostcpu.h"
 
 VIR_LOG_INIT("util.cgroup");
 
diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c
new file mode 100644
index 0000000..72ea943
--- /dev/null
+++ b/src/util/virhostcpu.c
@@ -0,0 +1,1299 @@
+/*
+ * virhostcpu.c: helper APIs for host CPU info
+ *
+ * Copyright (C) 2006-2016 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * This 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.
+ *
+ * This 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 this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daniel P. Berrange <berrange at redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
+#include <dirent.h>
+#include <sys/utsname.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#if HAVE_LINUX_KVM_H
+# include <linux/kvm.h>
+#endif
+
+#if defined(__FreeBSD__) || defined(__APPLE__)
+# include <sys/time.h>
+# include <sys/types.h>
+# include <sys/sysctl.h>
+# include <sys/resource.h>
+#endif
+
+#include "c-ctype.h"
+#include "viralloc.h"
+#include "virhostcpupriv.h"
+#include "physmem.h"
+#include "virerror.h"
+#include "count-one-bits.h"
+#include "intprops.h"
+#include "virarch.h"
+#include "virfile.h"
+#include "virtypedparam.h"
+#include "virstring.h"
+#include "virnuma.h"
+#include "virlog.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+VIR_LOG_INIT("util.hostcpu");
+
+
+#if defined(__FreeBSD__) || defined(__APPLE__)
+static int
+virHostCPUGetCountAppleFreeBSD(void)
+{
+    int ncpu_mib[2] = { CTL_HW, HW_NCPU };
+    unsigned long ncpu;
+    size_t ncpu_len = sizeof(ncpu);
+
+    if (sysctl(ncpu_mib, 2, &ncpu, &ncpu_len, NULL, 0) == -1) {
+        virReportSystemError(errno, "%s", _("Cannot obtain CPU count"));
+        return -1;
+    }
+
+    return ncpu;
+}
+#endif /* defined(__FreeBSD__) || defined(__APPLE__) */
+
+#ifdef __FreeBSD__
+# define BSD_CPU_STATS_ALL 4
+# define BSD_MEMORY_STATS_ALL 4
+
+# define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / (stathz ? stathz : hz))
+
+static int
+virHostCPUGetStatsFreebsd(int cpuNum,
+                          virNodeCPUStatsPtr params,
+                          int *nparams)
+{
+    const char *sysctl_name;
+    long *cpu_times;
+    struct clockinfo clkinfo;
+    size_t i, j, cpu_times_size, clkinfo_size;
+    int cpu_times_num, offset, hz, stathz, ret = -1;
+    struct field_cpu_map {
+        const char *field;
+        int idx[CPUSTATES];
+    } cpu_map[] = {
+        {VIR_NODE_CPU_STATS_KERNEL, {CP_SYS}},
+        {VIR_NODE_CPU_STATS_USER, {CP_USER, CP_NICE}},
+        {VIR_NODE_CPU_STATS_IDLE, {CP_IDLE}},
+        {VIR_NODE_CPU_STATS_INTR, {CP_INTR}},
+        {NULL, {0}}
+    };
+
+    if ((*nparams) == 0) {
+        *nparams = BSD_CPU_STATS_ALL;
+        return 0;
+    }
+
+    if ((*nparams) != BSD_CPU_STATS_ALL) {
+        virReportInvalidArg(*nparams,
+                            _("nparams in %s must be equal to %d"),
+                            __FUNCTION__, BSD_CPU_STATS_ALL);
+        return -1;
+    }
+
+    clkinfo_size = sizeof(clkinfo);
+    if (sysctlbyname("kern.clockrate", &clkinfo, &clkinfo_size, NULL, 0) < 0) {
+        virReportSystemError(errno,
+                             _("sysctl failed for '%s'"),
+                             "kern.clockrate");
+        return -1;
+    }
+
+    stathz = clkinfo.stathz;
+    hz = clkinfo.hz;
+
+    if (cpuNum == VIR_NODE_CPU_STATS_ALL_CPUS) {
+        sysctl_name = "kern.cp_time";
+        cpu_times_num = 1;
+        offset = 0;
+    } else {
+        sysctl_name = "kern.cp_times";
+        cpu_times_num = virHostCPUGetCountAppleFreeBSD();
+
+        if (cpuNum >= cpu_times_num) {
+            virReportInvalidArg(cpuNum,
+                                _("Invalid cpuNum in %s"),
+                                __FUNCTION__);
+            return -1;
+        }
+
+        offset = cpu_times_num * CPUSTATES;
+    }
+
+    cpu_times_size = sizeof(long) * cpu_times_num * CPUSTATES;
+
+    if (VIR_ALLOC_N(cpu_times, cpu_times_num * CPUSTATES) < 0)
+        goto cleanup;
+
+    if (sysctlbyname(sysctl_name, cpu_times, &cpu_times_size, NULL, 0) < 0) {
+        virReportSystemError(errno,
+                             _("sysctl failed for '%s'"),
+                             sysctl_name);
+        goto cleanup;
+    }
+
+    for (i = 0; cpu_map[i].field != NULL; i++) {
+        virNodeCPUStatsPtr param = &params[i];
+
+        if (virStrcpyStatic(param->field, cpu_map[i].field) == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Field '%s' too long for destination"),
+                           cpu_map[i].field);
+            goto cleanup;
+        }
+
+        param->value = 0;
+        for (j = 0; j < ARRAY_CARDINALITY(cpu_map[i].idx); j++)
+            param->value += cpu_times[offset + cpu_map[i].idx[j]] * TICK_TO_NSEC;
+    }
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(cpu_times);
+
+    return ret;
+}
+
+#endif /* __FreeBSD__ */
+
+#ifdef __linux__
+# define SYSFS_SYSTEM_PATH "/sys/devices/system"
+# define CPUINFO_PATH "/proc/cpuinfo"
+# define PROCSTAT_PATH "/proc/stat"
+# define SYSFS_THREAD_SIBLINGS_LIST_LENGTH_MAX 8192
+
+# define LINUX_NB_CPU_STATS 4
+
+static const char *sysfs_system_path = SYSFS_SYSTEM_PATH;
+
+void virHostCPUSetSysFSSystemPathLinux(const char *path)
+{
+    if (path)
+        sysfs_system_path = path;
+    else
+        sysfs_system_path = SYSFS_SYSTEM_PATH;
+}
+
+/* Return the positive decimal contents of the given
+ * DIR/cpu%u/FILE, or -1 on error.  If DEFAULT_VALUE is non-negative
+ * and the file could not be found, return that instead of an error;
+ * this is useful for machines that cannot hot-unplug cpu0, or where
+ * hot-unplugging is disabled, or where the kernel is too old
+ * to support NUMA cells, etc.  */
+static int
+virHostCPUGetValue(const char *dir, unsigned int cpu, const char *file,
+                   int default_value)
+{
+    char *path;
+    FILE *pathfp;
+    int value = -1;
+    char value_str[INT_BUFSIZE_BOUND(value)];
+    char *tmp;
+
+    if (virAsprintf(&path, "%s/cpu%u/%s", dir, cpu, file) < 0)
+        return -1;
+
+    pathfp = fopen(path, "r");
+    if (pathfp == NULL) {
+        if (default_value >= 0 && errno == ENOENT)
+            value = default_value;
+        else
+            virReportSystemError(errno, _("cannot open %s"), path);
+        goto cleanup;
+    }
+
+    if (fgets(value_str, sizeof(value_str), pathfp) == NULL) {
+        virReportSystemError(errno, _("cannot read from %s"), path);
+        goto cleanup;
+    }
+    if (virStrToLong_i(value_str, &tmp, 10, &value) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("could not convert '%s' to an integer"),
+                       value_str);
+        goto cleanup;
+    }
+
+ cleanup:
+    VIR_FORCE_FCLOSE(pathfp);
+    VIR_FREE(path);
+
+    return value;
+}
+
+static unsigned long
+virHostCPUCountThreadSiblings(const char *dir, unsigned int cpu)
+{
+    unsigned long ret = 0;
+    char *path;
+    char *str = NULL;
+    size_t i;
+
+    if (virAsprintf(&path, "%s/cpu%u/topology/thread_siblings",
+                    dir, cpu) < 0)
+        return 0;
+
+    if (!virFileExists(path)) {
+        /* If file doesn't exist, then pretend our only
+         * sibling is ourself */
+        ret = 1;
+        goto cleanup;
+    }
+
+    if (virFileReadAll(path, SYSFS_THREAD_SIBLINGS_LIST_LENGTH_MAX, &str) < 0)
+        goto cleanup;
+
+    for (i = 0; str[i] != '\0'; i++) {
+        if (c_isxdigit(str[i]))
+            ret += count_one_bits(virHexToBin(str[i]));
+    }
+
+ cleanup:
+    VIR_FREE(str);
+    VIR_FREE(path);
+    return ret;
+}
+
+static int
+virHostCPUParseSocket(const char *dir,
+                   virArch arch,
+                   unsigned int cpu)
+{
+    int ret = virHostCPUGetValue(dir, cpu, "topology/physical_package_id", 0);
+
+    if (ARCH_IS_ARM(arch) || ARCH_IS_PPC(arch) || ARCH_IS_S390(arch)) {
+        /* arm, ppc and s390(x) has -1 */
+        if (ret < 0)
+            ret = 0;
+    }
+
+    return ret;
+}
+
+/* parses a node entry, returning number of processors in the node and
+ * filling arguments */
+static int
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3)
+ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(6)
+ATTRIBUTE_NONNULL(7) ATTRIBUTE_NONNULL(8)
+ATTRIBUTE_NONNULL(9)
+virHostCPUParseNode(const char *node,
+                    virArch arch,
+                    virBitmapPtr present_cpus_map,
+                    virBitmapPtr online_cpus_map,
+                    int threads_per_subcore,
+                    int *sockets,
+                    int *cores,
+                    int *threads,
+                    int *offline)
+{
+    /* Biggest value we can expect to be used as either socket id
+     * or core id. Bitmaps will need to be sized accordingly */
+    const int ID_MAX = 4095;
+    int ret = -1;
+    int processors = 0;
+    DIR *cpudir = NULL;
+    struct dirent *cpudirent = NULL;
+    virBitmapPtr node_cpus_map = NULL;
+    virBitmapPtr sockets_map = NULL;
+    virBitmapPtr *cores_maps = NULL;
+    int npresent_cpus = virBitmapSize(present_cpus_map);
+    int sock_max = 0;
+    int sock;
+    int core;
+    size_t i;
+    int siblings;
+    unsigned int cpu;
+    int direrr;
+
+    *threads = 0;
+    *cores = 0;
+    *sockets = 0;
+
+    if (!(cpudir = opendir(node))) {
+        virReportSystemError(errno, _("cannot opendir %s"), node);
+        goto cleanup;
+    }
+
+    /* Keep track of the CPUs that belong to the current node */
+    if (!(node_cpus_map = virBitmapNew(npresent_cpus)))
+        goto cleanup;
+
+    /* enumerate sockets in the node */
+    if (!(sockets_map = virBitmapNew(ID_MAX + 1)))
+        goto cleanup;
+
+    while ((direrr = virDirRead(cpudir, &cpudirent, node)) > 0) {
+        if (sscanf(cpudirent->d_name, "cpu%u", &cpu) != 1)
+            continue;
+
+        if (!virBitmapIsBitSet(present_cpus_map, cpu))
+            continue;
+
+        /* Mark this CPU as part of the current node */
+        if (virBitmapSetBit(node_cpus_map, cpu) < 0)
+            goto cleanup;
+
+        if (!virBitmapIsBitSet(online_cpus_map, cpu))
+            continue;
+
+        /* Parse socket */
+        if ((sock = virHostCPUParseSocket(node, arch, cpu)) < 0)
+            goto cleanup;
+        if (sock > ID_MAX) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Socket %d can't be handled (max socket is %d)"),
+                           sock, ID_MAX);
+            goto cleanup;
+        }
+
+        if (virBitmapSetBit(sockets_map, sock) < 0)
+            goto cleanup;
+
+        if (sock > sock_max)
+            sock_max = sock;
+    }
+
+    if (direrr < 0)
+        goto cleanup;
+
+    sock_max++;
+
+    /* allocate cores maps for each socket */
+    if (VIR_ALLOC_N(cores_maps, sock_max) < 0)
+        goto cleanup;
+
+    for (i = 0; i < sock_max; i++)
+        if (!(cores_maps[i] = virBitmapNew(ID_MAX + 1)))
+            goto cleanup;
+
+    /* Iterate over all CPUs in the node, in ascending order */
+    for (cpu = 0; cpu < npresent_cpus; cpu++) {
+
+        /* Skip CPUs that are not part of the current node */
+        if (!virBitmapIsBitSet(node_cpus_map, cpu))
+            continue;
+
+        if (!virBitmapIsBitSet(online_cpus_map, cpu)) {
+            if (threads_per_subcore > 0 &&
+                cpu % threads_per_subcore != 0 &&
+                virBitmapIsBitSet(online_cpus_map,
+                                  cpu - (cpu % threads_per_subcore))) {
+                /* Secondary offline threads are counted as online when
+                 * subcores are in use and the corresponding primary
+                 * thread is online */
+                processors++;
+            } else {
+                /* But they are counted as offline otherwise */
+                (*offline)++;
+            }
+            continue;
+        }
+
+        processors++;
+
+        /* Parse socket */
+        if ((sock = virHostCPUParseSocket(node, arch, cpu)) < 0)
+            goto cleanup;
+        if (!virBitmapIsBitSet(sockets_map, sock)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("CPU socket topology has changed"));
+            goto cleanup;
+        }
+
+        /* Parse core */
+        if (ARCH_IS_S390(arch)) {
+            /* logical cpu is equivalent to a core on s390 */
+            core = cpu;
+        } else {
+            if ((core = virHostCPUGetValue(node, cpu,
+                                           "topology/core_id", 0)) < 0)
+                goto cleanup;
+        }
+        if (core > ID_MAX) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Core %d can't be handled (max core is %d)"),
+                           core, ID_MAX);
+            goto cleanup;
+        }
+
+        if (virBitmapSetBit(cores_maps[sock], core) < 0)
+            goto cleanup;
+
+        if (!(siblings = virHostCPUCountThreadSiblings(node, cpu)))
+            goto cleanup;
+
+        if (siblings > *threads)
+            *threads = siblings;
+    }
+
+    /* finalize the returned data */
+    *sockets = virBitmapCountBits(sockets_map);
+
+    for (i = 0; i < sock_max; i++) {
+        if (!virBitmapIsBitSet(sockets_map, i))
+            continue;
+
+        core = virBitmapCountBits(cores_maps[i]);
+        if (core > *cores)
+            *cores = core;
+    }
+
+    if (threads_per_subcore > 0) {
+        /* The thread count ignores offline threads, which means that only
+         * only primary threads have been considered so far. If subcores
+         * are in use, we need to also account for secondary threads */
+        *threads *= threads_per_subcore;
+    }
+    ret = processors;
+
+ cleanup:
+    /* don't shadow a more serious error */
+    if (cpudir && closedir(cpudir) < 0 && ret >= 0) {
+        virReportSystemError(errno, _("problem closing %s"), node);
+        ret = -1;
+    }
+    if (cores_maps)
+        for (i = 0; i < sock_max; i++)
+            virBitmapFree(cores_maps[i]);
+    VIR_FREE(cores_maps);
+    virBitmapFree(sockets_map);
+    virBitmapFree(node_cpus_map);
+
+    return ret;
+}
+
+/* Check whether the host subcore configuration is valid.
+ *
+ * A valid configuration is one where no secondary thread is online;
+ * the primary thread in a subcore is always the first one */
+static bool
+virHostCPUHasValidSubcoreConfiguration(int threads_per_subcore)
+{
+    virBitmapPtr online_cpus = NULL;
+    int cpu = -1;
+    bool ret = false;
+
+    /* No point in checking if subcores are not in use */
+    if (threads_per_subcore <= 0)
+        goto cleanup;
+
+    if (!(online_cpus = virHostCPUGetOnlineBitmap()))
+        goto cleanup;
+
+    while ((cpu = virBitmapNextSetBit(online_cpus, cpu)) >= 0) {
+
+        /* A single online secondary thread is enough to
+         * make the configuration invalid */
+        if (cpu % threads_per_subcore != 0)
+            goto cleanup;
+    }
+
+    ret = true;
+
+ cleanup:
+    virBitmapFree(online_cpus);
+
+    return ret;
+}
+
+int
+virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
+                               virArch arch,
+                               unsigned int *cpus,
+                               unsigned int *mhz,
+                               unsigned int *nodes,
+                               unsigned int *sockets,
+                               unsigned int *cores,
+                               unsigned int *threads)
+{
+    virBitmapPtr present_cpus_map = NULL;
+    virBitmapPtr online_cpus_map = NULL;
+    char line[1024];
+    DIR *nodedir = NULL;
+    struct dirent *nodedirent = NULL;
+    int nodecpus, nodecores, nodesockets, nodethreads, offline = 0;
+    int threads_per_subcore = 0;
+    unsigned int node;
+    int ret = -1;
+    char *sysfs_nodedir = NULL;
+    char *sysfs_cpudir = NULL;
+    int direrr;
+
+    *mhz = 0;
+    *cpus = *nodes = *sockets = *cores = *threads = 0;
+
+    /* Start with parsing CPU clock speed from /proc/cpuinfo */
+    while (fgets(line, sizeof(line), cpuinfo) != NULL) {
+        if (ARCH_IS_X86(arch)) {
+            char *buf = line;
+            if (STRPREFIX(buf, "cpu MHz")) {
+                char *p;
+                unsigned int ui;
+
+                buf += 7;
+                while (*buf && c_isspace(*buf))
+                    buf++;
+
+                if (*buf != ':' || !buf[1]) {
+                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                   _("parsing cpu MHz from cpuinfo"));
+                    goto cleanup;
+                }
+
+                if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 &&
+                    /* Accept trailing fractional part.  */
+                    (*p == '\0' || *p == '.' || c_isspace(*p)))
+                    *mhz = ui;
+            }
+        } else if (ARCH_IS_PPC(arch)) {
+            char *buf = line;
+            if (STRPREFIX(buf, "clock")) {
+                char *p;
+                unsigned int ui;
+
+                buf += 5;
+                while (*buf && c_isspace(*buf))
+                    buf++;
+
+                if (*buf != ':' || !buf[1]) {
+                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                   _("parsing cpu MHz from cpuinfo"));
+                    goto cleanup;
+                }
+
+                if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 &&
+                    /* Accept trailing fractional part.  */
+                    (*p == '\0' || *p == '.' || c_isspace(*p)))
+                    *mhz = ui;
+                /* No other interesting infos are available in /proc/cpuinfo.
+                 * However, there is a line identifying processor's version,
+                 * identification and machine, but we don't want it to be caught
+                 * and parsed in next iteration, because it is not in expected
+                 * format and thus lead to error. */
+            }
+        } else if (ARCH_IS_ARM(arch)) {
+            char *buf = line;
+            if (STRPREFIX(buf, "BogoMIPS")) {
+                char *p;
+                unsigned int ui;
+
+                buf += 8;
+                while (*buf && c_isspace(*buf))
+                    buf++;
+
+                if (*buf != ':' || !buf[1]) {
+                    virReportError(VIR_ERR_INTERNAL_ERROR,
+                                   "%s", _("parsing cpu MHz from cpuinfo"));
+                    goto cleanup;
+                }
+
+                if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
+                    /* Accept trailing fractional part.  */
+                    && (*p == '\0' || *p == '.' || c_isspace(*p)))
+                    *mhz = ui;
+            }
+        } else if (ARCH_IS_S390(arch)) {
+            /* s390x has no realistic value for CPU speed,
+             * assign a value of zero to signify this */
+            *mhz = 0;
+        } else {
+            VIR_WARN("Parser for /proc/cpuinfo needs to be adapted for your architecture");
+            break;
+        }
+    }
+
+    /* Get information about what CPUs are present in the host and what
+     * CPUs are online, so that we don't have to so for each node */
+    present_cpus_map = virHostCPUGetPresentBitmap();
+    if (!present_cpus_map)
+        goto cleanup;
+    online_cpus_map = virHostCPUGetOnlineBitmap();
+    if (!online_cpus_map)
+        goto cleanup;
+
+    /* OK, we've parsed clock speed out of /proc/cpuinfo. Get the
+     * core, node, socket, thread and topology information from /sys
+     */
+    if (virAsprintf(&sysfs_nodedir, "%s/node", sysfs_system_path) < 0)
+        goto cleanup;
+
+    if (!(nodedir = opendir(sysfs_nodedir))) {
+        /* the host isn't probably running a NUMA architecture */
+        goto fallback;
+    }
+
+    /* PPC-KVM needs the secondary threads of a core to be offline on the
+     * host. The kvm scheduler brings the secondary threads online in the
+     * guest context. Moreover, P8 processor has split-core capability
+     * where, there can be 1,2 or 4 subcores per core. The primaries of the
+     * subcores alone will be online on the host for a subcore in the
+     * host. Even though the actual threads per core for P8 processor is 8,
+     * depending on the subcores_per_core = 1, 2 or 4, the threads per
+     * subcore will vary accordingly to 8, 4 and 2 repectively.
+     * So, On host threads_per_core what is arrived at from sysfs in the
+     * current logic is actually the subcores_per_core. Threads per subcore
+     * can only be obtained from the kvm device. For example, on P8 wih 1
+     * core having 8 threads, sub_cores_percore=4, the threads 0,2,4 & 6
+     * will be online. The sysfs reflects this and in the current logic
+     * variable 'threads' will be 4 which is nothing but subcores_per_core.
+     * If the user tampers the cpu online/offline states using chcpu or other
+     * means, then it is an unsupported configuration for kvm.
+     * The code below tries to keep in mind
+     *  - when the libvirtd is run inside a KVM guest or Phyp based guest.
+     *  - Or on the kvm host where user manually tampers the cpu states to
+     *    offline/online randomly.
+     * On hosts other than POWER this will be 0, in which case a simpler
+     * thread-counting logic will be used  */
+    if ((threads_per_subcore = virHostCPUGetThreadsPerSubcore(arch)) < 0)
+        goto cleanup;
+
+    /* If the subcore configuration is not valid, just pretend subcores
+     * are not in use and count threads one by one */
+    if (!virHostCPUHasValidSubcoreConfiguration(threads_per_subcore))
+        threads_per_subcore = 0;
+
+    while ((direrr = virDirRead(nodedir, &nodedirent, sysfs_nodedir)) > 0) {
+        if (sscanf(nodedirent->d_name, "node%u", &node) != 1)
+            continue;
+
+        (*nodes)++;
+
+        if (virAsprintf(&sysfs_cpudir, "%s/node/%s",
+                        sysfs_system_path, nodedirent->d_name) < 0)
+            goto cleanup;
+
+        if ((nodecpus = virHostCPUParseNode(sysfs_cpudir, arch,
+                                            present_cpus_map,
+                                            online_cpus_map,
+                                            threads_per_subcore,
+                                            &nodesockets, &nodecores,
+                                            &nodethreads, &offline)) < 0)
+            goto cleanup;
+
+        VIR_FREE(sysfs_cpudir);
+
+        *cpus += nodecpus;
+
+        if (nodesockets > *sockets)
+            *sockets = nodesockets;
+
+        if (nodecores > *cores)
+            *cores = nodecores;
+
+        if (nodethreads > *threads)
+            *threads = nodethreads;
+    }
+
+    if (direrr < 0)
+        goto cleanup;
+
+    if (*cpus && *nodes)
+        goto done;
+
+ fallback:
+    VIR_FREE(sysfs_cpudir);
+
+    if (virAsprintf(&sysfs_cpudir, "%s/cpu", sysfs_system_path) < 0)
+        goto cleanup;
+
+    if ((nodecpus = virHostCPUParseNode(sysfs_cpudir, arch,
+                                        present_cpus_map,
+                                        online_cpus_map,
+                                        threads_per_subcore,
+                                        &nodesockets, &nodecores,
+                                        &nodethreads, &offline)) < 0)
+        goto cleanup;
+
+    *nodes = 1;
+    *cpus = nodecpus;
+    *sockets = nodesockets;
+    *cores = nodecores;
+    *threads = nodethreads;
+
+ done:
+    /* There should always be at least one cpu, socket, node, and thread. */
+    if (*cpus == 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no CPUs found"));
+        goto cleanup;
+    }
+
+    if (*sockets == 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no sockets found"));
+        goto cleanup;
+    }
+
+    if (*threads == 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no threads found"));
+        goto cleanup;
+    }
+
+    /* Now check if the topology makes sense. There are machines that don't
+     * expose their real number of nodes or for example the AMD Bulldozer
+     * architecture that exposes their Clustered integer core modules as both
+     * threads and cores. This approach throws off our detection. Unfortunately
+     * the nodeinfo structure isn't designed to carry the full topology so
+     * we're going to lie about the detected topology to notify the user
+     * to check the host capabilities for the actual topology. */
+    if ((*nodes *
+         *sockets *
+         *cores *
+         *threads) != (*cpus + offline)) {
+        *nodes = 1;
+        *sockets = 1;
+        *cores = *cpus + offline;
+        *threads = 1;
+    }
+
+    ret = 0;
+
+ cleanup:
+    /* don't shadow a more serious error */
+    if (nodedir && closedir(nodedir) < 0 && ret >= 0) {
+        virReportSystemError(errno, _("problem closing %s"), sysfs_nodedir);
+        ret = -1;
+    }
+
+    virBitmapFree(present_cpus_map);
+    virBitmapFree(online_cpus_map);
+    VIR_FREE(sysfs_nodedir);
+    VIR_FREE(sysfs_cpudir);
+    return ret;
+}
+
+static int
+virHostCPUStatsAssign(virNodeCPUStatsPtr param,
+                      const char *name,
+                      unsigned long long value)
+{
+    if (virStrcpyStatic(param->field, name) == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "%s", _("kernel cpu time field is too long"
+                               " for the destination"));
+        return -1;
+    }
+    param->value = value;
+    return 0;
+}
+
+# define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / sysconf(_SC_CLK_TCK))
+
+int
+virHostCPUGetStatsLinux(FILE *procstat,
+                        int cpuNum,
+                        virNodeCPUStatsPtr params,
+                        int *nparams)
+{
+    int ret = -1;
+    char line[1024];
+    unsigned long long usr, ni, sys, idle, iowait;
+    unsigned long long irq, softirq, steal, guest, guest_nice;
+    char cpu_header[4 + INT_BUFSIZE_BOUND(cpuNum)];
+
+    if ((*nparams) == 0) {
+        /* Current number of cpu stats supported by linux */
+        *nparams = LINUX_NB_CPU_STATS;
+        ret = 0;
+        goto cleanup;
+    }
+
+    if ((*nparams) != LINUX_NB_CPU_STATS) {
+        virReportInvalidArg(*nparams,
+                            _("nparams in %s must be equal to %d"),
+                            __FUNCTION__, LINUX_NB_CPU_STATS);
+        goto cleanup;
+    }
+
+    if (cpuNum == VIR_NODE_CPU_STATS_ALL_CPUS) {
+        strcpy(cpu_header, "cpu ");
+    } else {
+        snprintf(cpu_header, sizeof(cpu_header), "cpu%d ", cpuNum);
+    }
+
+    while (fgets(line, sizeof(line), procstat) != NULL) {
+        char *buf = line;
+
+        if (STRPREFIX(buf, cpu_header)) { /* aka logical CPU time */
+            if (sscanf(buf,
+                       "%*s %llu %llu %llu %llu %llu" // user ~ iowait
+                       "%llu %llu %llu %llu %llu",    // irq  ~ guest_nice
+                       &usr, &ni, &sys, &idle, &iowait,
+                       &irq, &softirq, &steal, &guest, &guest_nice) < 4) {
+                continue;
+            }
+
+            if (virHostCPUStatsAssign(&params[0], VIR_NODE_CPU_STATS_KERNEL,
+                                      (sys + irq + softirq) * TICK_TO_NSEC) < 0)
+                goto cleanup;
+
+            if (virHostCPUStatsAssign(&params[1], VIR_NODE_CPU_STATS_USER,
+                                      (usr + ni) * TICK_TO_NSEC) < 0)
+                goto cleanup;
+
+            if (virHostCPUStatsAssign(&params[2], VIR_NODE_CPU_STATS_IDLE,
+                                      idle * TICK_TO_NSEC) < 0)
+                goto cleanup;
+
+            if (virHostCPUStatsAssign(&params[3], VIR_NODE_CPU_STATS_IOWAIT,
+                                      iowait * TICK_TO_NSEC) < 0)
+                goto cleanup;
+
+            ret = 0;
+            goto cleanup;
+        }
+    }
+
+    virReportInvalidArg(cpuNum,
+                        _("Invalid cpuNum in %s"),
+                        __FUNCTION__);
+
+ cleanup:
+    return ret;
+}
+
+
+static char *
+virHostCPUGetGlobalPathLinux(const char *file)
+{
+    char *path = NULL;
+
+    if (virAsprintf(&path, "%s/cpu/%s", sysfs_system_path, file) < 0)
+        return NULL;
+
+    return path;
+}
+
+static char *
+virHostCPUGetPresentPathLinux(void)
+{
+    return virHostCPUGetGlobalPathLinux("present");
+}
+
+static char *
+virHostCPUGetOnlinePathLinux(void)
+{
+    return virHostCPUGetGlobalPathLinux("online");
+}
+
+/* Determine the number of CPUs (maximum CPU id + 1) from a file containing
+ * a list of CPU ids, like the Linux sysfs cpu/present file */
+static int
+virHostCPUParseCountLinux(const char *path)
+{
+    char *str = NULL;
+    char *tmp;
+    int ret = -1;
+
+    if (virFileReadAll(path, 5 * VIR_HOST_CPU_MASK_LEN, &str) < 0)
+        goto cleanup;
+
+    tmp = str;
+    do {
+        if (virStrToLong_i(tmp, &tmp, 10, &ret) < 0 ||
+            !strchr(",-\n", *tmp)) {
+            virReportError(VIR_ERR_NO_SUPPORT,
+                           _("failed to parse %s"), path);
+            ret = -1;
+            goto cleanup;
+        }
+    } while (*tmp++ != '\n');
+    ret++;
+
+ cleanup:
+    VIR_FREE(str);
+    return ret;
+}
+
+/*
+ * Linux maintains cpu bit map under cpu/online. For example, if
+ * cpuid=5's flag is not set and max cpu is 7, the map file shows
+ * 0-4,6-7. This function parses it and returns cpumap.
+ */
+static virBitmapPtr
+virHostCPUParseMapLinux(int max_cpuid, const char *path)
+{
+    virBitmapPtr map = NULL;
+    char *str = NULL;
+
+    if (virFileReadAll(path, 5 * VIR_HOST_CPU_MASK_LEN, &str) < 0)
+        goto error;
+
+    if (virBitmapParse(str, 0, &map, max_cpuid) < 0)
+        goto error;
+
+    VIR_FREE(str);
+    return map;
+
+ error:
+    VIR_FREE(str);
+    virBitmapFree(map);
+    return NULL;
+}
+#endif
+
+
+int
+virHostCPUGetInfo(virArch hostarch,
+                  unsigned int *cpus,
+                  unsigned int *mhz,
+                  unsigned int *nodes,
+                  unsigned int *sockets,
+                  unsigned int *cores,
+                  unsigned int *threads)
+{
+#ifdef __linux__
+    int ret = -1;
+    FILE *cpuinfo = fopen(CPUINFO_PATH, "r");
+
+    if (!cpuinfo) {
+        virReportSystemError(errno,
+                             _("cannot open %s"), CPUINFO_PATH);
+        return -1;
+    }
+
+    ret = virHostCPUGetInfoPopulateLinux(cpuinfo, hostarch,
+                                         cpus, mhz, nodes,
+                                         sockets, cores, threads);
+    if (ret < 0)
+        goto cleanup;
+
+ cleanup:
+    VIR_FORCE_FCLOSE(cpuinfo);
+    return ret;
+#elif defined(__FreeBSD__) || defined(__APPLE__)
+    unsigned long cpu_freq;
+    size_t cpu_freq_len = sizeof(cpu_freq);
+
+    *cpus = virHostCPUGetCountAppleFreeBSD();
+    if (*cpus == -1)
+        return -1;
+
+    *nodes = 1;
+    *sockets = 1;
+    *cores = *cpus;
+    *threads = 1;
+
+# ifdef __FreeBSD__
+    if (sysctlbyname("dev.cpu.0.freq", &cpu_freq, &cpu_freq_len, NULL, 0) < 0) {
+        virReportSystemError(errno, "%s", _("cannot obtain CPU freq"));
+        return -1;
+    }
+
+    *mhz = cpu_freq;
+# else
+    if (sysctlbyname("hw.cpufrequency", &cpu_freq, &cpu_freq_len, NULL, 0) < 0) {
+        virReportSystemError(errno, "%s", _("cannot obtain CPU freq"));
+        return -1;
+    }
+
+    *mhz = cpu_freq / 1000000;
+# endif
+
+    return 0;
+#else
+    /* XXX Solaris will need an impl later if they port QEMU driver */
+    virReportError(VIR_ERR_NO_SUPPORT, "%s",
+                   _("node info not implemented on this platform"));
+    return -1;
+#endif
+}
+
+
+int
+virHostCPUGetStats(int cpuNum ATTRIBUTE_UNUSED,
+                   virNodeCPUStatsPtr params ATTRIBUTE_UNUSED,
+                   int *nparams ATTRIBUTE_UNUSED,
+                   unsigned int flags)
+{
+    virCheckFlags(0, -1);
+
+#ifdef __linux__
+    {
+        int ret;
+        FILE *procstat = fopen(PROCSTAT_PATH, "r");
+        if (!procstat) {
+            virReportSystemError(errno,
+                                 _("cannot open %s"), PROCSTAT_PATH);
+            return -1;
+        }
+        ret = virHostCPUGetStatsLinux(procstat, cpuNum, params, nparams);
+        VIR_FORCE_FCLOSE(procstat);
+
+        return ret;
+    }
+#elif defined(__FreeBSD__)
+    return virHostCPUGetStatsFreeBSD(cpuNum, params, nparams);
+#else
+    virReportError(VIR_ERR_NO_SUPPORT, "%s",
+                   _("node CPU stats not implemented on this platform"));
+    return -1;
+#endif
+}
+
+
+int
+virHostCPUGetCount(void)
+{
+#if defined(__linux__)
+    /* To support older kernels that lack cpu/present, such as 2.6.18
+     * in RHEL5, we fall back to count cpu/cpuNN entries; this assumes
+     * that such kernels also lack hotplug, and therefore cpu/cpuNN
+     * will be consecutive.
+     */
+    char *present_path = NULL;
+    char *cpupath = NULL;
+    int ncpu = -1;
+
+    if (!(present_path = virHostCPUGetPresentPathLinux()))
+        return -1;
+
+    if (virFileExists(present_path)) {
+        ncpu = virHostCPUParseCountLinux(present_path);
+        goto cleanup;
+    }
+
+    if (virAsprintf(&cpupath, "%s/cpu/cpu0", sysfs_system_path) < 0)
+        goto cleanup;
+    if (virFileExists(cpupath)) {
+        ncpu = 0;
+        do {
+            ncpu++;
+            VIR_FREE(cpupath);
+            if (virAsprintf(&cpupath, "%s/cpu/cpu%d",
+                            sysfs_system_path, ncpu) < 0) {
+                ncpu = -1;
+                goto cleanup;
+            }
+        } while (virFileExists(cpupath));
+    } else {
+        /* no cpu/cpu0: we give up */
+        virReportError(VIR_ERR_NO_SUPPORT, "%s",
+                       _("host cpu counting not supported on this node"));
+    }
+
+ cleanup:
+    VIR_FREE(present_path);
+    VIR_FREE(cpupath);
+    return ncpu;
+#elif defined(__FreeBSD__) || defined(__APPLE__)
+    return virHostCPUGetCountAppleFreeBSD();
+#else
+    virReportError(VIR_ERR_NO_SUPPORT, "%s",
+                   _("host cpu counting not implemented on this platform"));
+    return -1;
+#endif
+}
+
+virBitmapPtr
+virHostCPUGetPresentBitmap(void)
+{
+#ifdef __linux__
+    virBitmapPtr present_cpus = NULL;
+    char *present_path = NULL;
+    int npresent_cpus;
+
+    if ((npresent_cpus = virHostCPUGetCount()) < 0)
+        goto cleanup;
+
+    if (!(present_path = virHostCPUGetPresentPathLinux()))
+        goto cleanup;
+
+    /* If the cpu/present file is available, parse it and exit */
+    if (virFileExists(present_path)) {
+        present_cpus = virHostCPUParseMapLinux(npresent_cpus, present_path);
+        goto cleanup;
+    }
+
+    /* If the file is not available, we can assume that the kernel is
+     * too old to support non-consecutive CPU ids and just mark all
+     * possible CPUs as present */
+    if (!(present_cpus = virBitmapNew(npresent_cpus)))
+        goto cleanup;
+
+    virBitmapSetAll(present_cpus);
+
+ cleanup:
+    VIR_FREE(present_path);
+
+    return present_cpus;
+#endif
+    virReportError(VIR_ERR_NO_SUPPORT, "%s",
+                   _("node present CPU map not implemented on this platform"));
+    return NULL;
+}
+
+virBitmapPtr
+virHostCPUGetOnlineBitmap(void)
+{
+#ifdef __linux__
+    char *online_path = NULL;
+    char *cpudir = NULL;
+    virBitmapPtr cpumap;
+    int present;
+
+    present = virHostCPUGetCount();
+    if (present < 0)
+        return NULL;
+
+    if (!(online_path = virHostCPUGetOnlinePathLinux()))
+        return NULL;
+    if (virFileExists(online_path)) {
+        cpumap = virHostCPUParseMapLinux(present, online_path);
+    } else {
+        size_t i;
+
+        cpumap = virBitmapNew(present);
+        if (!cpumap)
+            goto cleanup;
+
+        if (virAsprintf(&cpudir, "%s/cpu", sysfs_system_path) < 0)
+            goto cleanup;
+
+        for (i = 0; i < present; i++) {
+            int online = virHostCPUGetValue(cpudir, i, "online", 1);
+            if (online < 0) {
+                virBitmapFree(cpumap);
+                cpumap = NULL;
+                goto cleanup;
+            }
+            if (online)
+                ignore_value(virBitmapSetBit(cpumap, i));
+        }
+    }
+
+ cleanup:
+    VIR_FREE(online_path);
+    VIR_FREE(cpudir);
+    return cpumap;
+#else
+    virReportError(VIR_ERR_NO_SUPPORT, "%s",
+                   _("node online CPU map not implemented on this platform"));
+    return NULL;
+#endif
+}
+
+
+int
+virHostCPUGetMap(unsigned char **cpumap,
+                 unsigned int *online,
+                 unsigned int flags)
+{
+    virBitmapPtr cpus = NULL;
+    int ret = -1;
+    int dummy;
+
+    virCheckFlags(0, -1);
+
+    if (!cpumap && !online)
+        return virHostCPUGetCount();
+
+    if (!(cpus = virHostCPUGetOnlineBitmap()))
+        goto cleanup;
+
+    if (cpumap && virBitmapToData(cpus, cpumap, &dummy) < 0)
+        goto cleanup;
+    if (online)
+        *online = virBitmapCountBits(cpus);
+
+    ret = virBitmapSize(cpus);
+
+ cleanup:
+    if (ret < 0 && cpumap)
+        VIR_FREE(*cpumap);
+    virBitmapFree(cpus);
+    return ret;
+}
+
+
+#if HAVE_LINUX_KVM_H && defined(KVM_CAP_PPC_SMT)
+
+/* Get the number of threads per subcore.
+ *
+ * This will be 2, 4 or 8 on POWER hosts, depending on the current
+ * micro-threading configuration, and 0 everywhere else.
+ *
+ * Returns the number of threads per subcore if subcores are in use, zero
+ * if subcores are not in use, and a negative value on error */
+int
+virHostCPUGetThreadsPerSubcore(virArch arch)
+{
+    int threads_per_subcore = 0;
+    const char *kvmpath = "/dev/kvm";
+    int kvmfd;
+
+    if (ARCH_IS_PPC64(arch)) {
+
+        /* It's okay if /dev/kvm doesn't exist, because
+         *   a. we might be running in a guest
+         *   b. the kvm module might not be installed or enabled
+         * In either case, falling back to the subcore-unaware thread
+         * counting logic is the right thing to do */
+        if (!virFileExists(kvmpath))
+            goto out;
+
+        if ((kvmfd = open(kvmpath, O_RDONLY)) < 0) {
+            /* This can happen when running as a regular user if
+             * permissions are tight enough, in which case erroring out
+             * is better than silently falling back and reporting
+             * different nodeinfo depending on the user */
+            virReportSystemError(errno,
+                                 _("Failed to open '%s'"),
+                                 kvmpath);
+            threads_per_subcore = -1;
+            goto out;
+        }
+
+        /* For Phyp and KVM based guests the ioctl for KVM_CAP_PPC_SMT
+         * returns zero and both primary and secondary threads will be
+         * online */
+        threads_per_subcore = ioctl(kvmfd,
+                                    KVM_CHECK_EXTENSION,
+                                    KVM_CAP_PPC_SMT);
+
+        VIR_FORCE_CLOSE(kvmfd);
+    }
+
+ out:
+    return threads_per_subcore;
+}
+
+#else
+
+/* Fallback for nodeGetThreadsPerSubcore() used when KVM headers
+ * are not available on the system */
+int
+virHostCPUGetThreadsPerSubcore(virArch arch ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+#endif /* HAVE_LINUX_KVM_H && defined(KVM_CAP_PPC_SMT) */
diff --git a/src/util/virhostcpu.h b/src/util/virhostcpu.h
new file mode 100644
index 0000000..e5ffc70
--- /dev/null
+++ b/src/util/virhostcpu.h
@@ -0,0 +1,54 @@
+/*
+ * virhostcpu.h: helper APIs for host CPU info
+ *
+ * Copyright (C) 2006-2016 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * This 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.
+ *
+ * This 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 this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daniel P. Berrange <berrange at redhat.com>
+ */
+
+#ifndef __VIR_HOSTCPU_H__
+# define __VIR_HOSTCPU_H__
+
+# include "internal.h"
+# include "virarch.h"
+# include "virbitmap.h"
+
+# define VIR_HOST_CPU_MASK_LEN 1024
+
+int virHostCPUGetStats(int cpuNum,
+                       virNodeCPUStatsPtr params,
+                       int *nparams,
+                       unsigned int flags);
+
+virBitmapPtr virHostCPUGetPresentBitmap(void);
+virBitmapPtr virHostCPUGetOnlineBitmap(void);
+int virHostCPUGetCount(void);
+int virHostCPUGetThreadsPerSubcore(virArch arch);
+
+int virHostCPUGetMap(unsigned char **cpumap,
+                     unsigned int *online,
+                     unsigned int flags);
+int virHostCPUGetInfo(virArch hostarch,
+                      unsigned int *cpus,
+                      unsigned int *mhz,
+                      unsigned int *nodes,
+                      unsigned int *sockets,
+                      unsigned int *cores,
+                      unsigned int *threads);
+
+#endif /* __VIR_HOSTCPU_H__*/
diff --git a/src/nodeinfopriv.h b/src/util/virhostcpupriv.h
similarity index 86%
rename from src/nodeinfopriv.h
rename to src/util/virhostcpupriv.h
index 0fd4391..de30983 100644
--- a/src/nodeinfopriv.h
+++ b/src/util/virhostcpupriv.h
@@ -1,7 +1,7 @@
 /*
- * nodeinfopriv.h: internal APIs for testing nodeinfo code
+ * virhostcpupriv.h: helper APIs for host CPU info
  *
- * Copyright (C) 2014 Red Hat, Inc.
+ * Copyright (C) 2014-2016 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -19,10 +19,10 @@
  *
  */
 
-#ifndef __NODEINFO_PRIV_H__
-# define __NODEINFO_PRIV_H__
+#ifndef __VIR_HOSTCPU_PRIV_H__
+# define __VIR_HOSTCPU_PRIV_H__
 
-# include "nodeinfo.h"
+# include "virhostcpu.h"
 
 # ifdef __linux__
 void virHostCPUSetSysFSSystemPathLinux(const char *path);
@@ -42,4 +42,4 @@ int virHostCPUGetStatsLinux(FILE *procstat,
                             int *nparams);
 # endif
 
-#endif /* __NODEINFO_PRIV_H__ */
+#endif /* __VIR_HOSTCPU_PRIV_H__ */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index db4f88b..16677cb 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -107,7 +107,7 @@ EXTRA_DIST =		\
 	networkxml2xmlupdateout \
 	nodedevschemadata \
 	nodedevschematest \
-	nodeinfodata     \
+	virhostcpudata \
 	nssdata \
 	nwfilterschematest \
 	nwfilterxml2firewalldata \
@@ -160,7 +160,7 @@ EXTRA_DIST =		\
 
 test_helpers = commandhelper ssh test_conf
 test_programs = virshtest sockettest \
-	nodeinfotest virbuftest \
+	virhostcputest virbuftest \
 	commandtest seclabeltest \
 	virhashtest \
 	viratomictest \
@@ -426,7 +426,7 @@ test_libraries = libshunload.la \
 		vircgroupmock.la \
 		virpcimock.la \
 		virnetdevmock.la \
-		nodeinfomock.la \
+		virhostcpumock.la \
 		nssmock.la \
 		$(NULL)
 if WITH_QEMU
@@ -875,9 +875,9 @@ test_conf_SOURCES = \
 	test_conf.c
 test_conf_LDADD = $(LDADDS)
 
-nodeinfotest_SOURCES = \
-	nodeinfotest.c testutils.h testutils.c
-nodeinfotest_LDADD = $(LDADDS)
+virhostcputest_SOURCES = \
+	virhostcputest.c testutils.h testutils.c
+virhostcputest_LDADD = $(LDADDS)
 
 commandtest_SOURCES = \
 	commandtest.c testutils.h testutils.c
@@ -1068,11 +1068,11 @@ virpcimock_la_CFLAGS = $(AM_CFLAGS)
 virpcimock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS)
 virpcimock_la_LIBADD = $(MOCKLIBS_LIBS)
 
-nodeinfomock_la_SOURCES = \
-	nodeinfomock.c
-nodeinfomock_la_CFLAGS = $(AM_CFLAGS)
-nodeinfomock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS)
-nodeinfomock_la_LIBADD = $(MOCKLIBS_LIBS)
+virhostcpumock_la_SOURCES = \
+	virhostcpumock.c
+virhostcpumock_la_CFLAGS = $(AM_CFLAGS)
+virhostcpumock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS)
+virhostcpumock_la_LIBADD = $(MOCKLIBS_LIBS)
 
 nsstest_SOURCES = \
 	nsstest.c testutils.h testutils.c
diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
index 148721d..566ffa8 100644
--- a/tests/vircgrouptest.c
+++ b/tests/vircgrouptest.c
@@ -34,7 +34,7 @@
 # include "virfile.h"
 # include "virbuffer.h"
 # include "testutilslxc.h"
-# include "nodeinfo.h"
+# include "virhostcpu.h"
 
 # define VIR_FROM_THIS VIR_FROM_NONE
 
diff --git a/tests/nodeinfodata/linux-aarch64-f21-mustang.cpuinfo b/tests/virhostcpudata/linux-aarch64-f21-mustang.cpuinfo
similarity index 100%
rename from tests/nodeinfodata/linux-aarch64-f21-mustang.cpuinfo
rename to tests/virhostcpudata/linux-aarch64-f21-mustang.cpuinfo
diff --git a/tests/nodeinfodata/linux-aarch64-f21-mustang.expected b/tests/virhostcpudata/linux-aarch64-f21-mustang.expected
similarity index 100%
rename from tests/nodeinfodata/linux-aarch64-f21-mustang.expected
rename to tests/virhostcpudata/linux-aarch64-f21-mustang.expected
diff --git a/tests/nodeinfodata/linux-aarch64-rhelsa-3.19.0-mustang.cpuinfo b/tests/virhostcpudata/linux-aarch64-rhelsa-3.19.0-mustang.cpuinfo
similarity index 100%
rename from tests/nodeinfodata/linux-aarch64-rhelsa-3.19.0-mustang.cpuinfo
rename to tests/virhostcpudata/linux-aarch64-rhelsa-3.19.0-mustang.cpuinfo

[...snipped countless more renames...]

diff --git a/tests/nodeinfomock.c b/tests/virhostcpumock.c
similarity index 95%
rename from tests/nodeinfomock.c
rename to tests/virhostcpumock.c
index ac12b5e..00d10f1 100644
--- a/tests/nodeinfomock.c
+++ b/tests/virhostcpumock.c
@@ -19,8 +19,7 @@
 
 #include <config.h>
 
-#include "internal.h"
-#include "nodeinfo.h"
+#include "virhostcpu.h"
 
 int
 virHostCPUGetThreadsPerSubcore(virArch arch)
diff --git a/tests/nodeinfotest.c b/tests/virhostcputest.c
similarity index 89%
rename from tests/nodeinfotest.c
rename to tests/virhostcputest.c
index 50b1c82..0643876 100644
--- a/tests/nodeinfotest.c
+++ b/tests/virhostcputest.c
@@ -7,7 +7,7 @@
 
 #include "testutils.h"
 #include "internal.h"
-#include "nodeinfopriv.h"
+#include "virhostcpupriv.h"
 #include "virfile.h"
 #include "virstring.h"
 
@@ -155,26 +155,26 @@ linuxCPUStatsCompareFiles(const char *cpustatfile,
 }
 
 
-struct linuxTestNodeInfoData {
+struct linuxTestHostCPUData {
     const char *testName;
     virArch arch;
 };
 
 static int
-linuxTestNodeInfo(const void *opaque)
+linuxTestHostCPU(const void *opaque)
 {
     int result = -1;
     char *cpuinfo = NULL;
     char *sysfs_prefix = NULL;
     char *output = NULL;
-    struct linuxTestNodeInfoData *data = (struct linuxTestNodeInfoData *) opaque;
+    struct linuxTestHostCPUData *data = (struct linuxTestHostCPUData *) opaque;
     const char *archStr = virArchToString(data->arch);
 
-    if (virAsprintf(&sysfs_prefix, "%s/nodeinfodata/linux-%s",
+    if (virAsprintf(&sysfs_prefix, "%s/virhostcpudata/linux-%s",
                     abs_srcdir, data->testName) < 0 ||
-        virAsprintf(&cpuinfo, "%s/nodeinfodata/linux-%s-%s.cpuinfo",
+        virAsprintf(&cpuinfo, "%s/virhostcpudata/linux-%s-%s.cpuinfo",
                     abs_srcdir, archStr, data->testName) < 0 ||
-        virAsprintf(&output, "%s/nodeinfodata/linux-%s-%s.expected",
+        virAsprintf(&output, "%s/virhostcpudata/linux-%s-%s.expected",
                     abs_srcdir, archStr, data->testName) < 0) {
         goto cleanup;
     }
@@ -204,9 +204,9 @@ linuxTestNodeCPUStats(const void *data)
     char *cpustatfile = NULL;
     char *outfile = NULL;
 
-    if (virAsprintf(&cpustatfile, "%s/nodeinfodata/linux-cpustat-%s.stat",
+    if (virAsprintf(&cpustatfile, "%s/virhostcpudata/linux-cpustat-%s.stat",
                     abs_srcdir, testData->name) < 0 ||
-        virAsprintf(&outfile, "%s/nodeinfodata/linux-cpustat-%s.out",
+        virAsprintf(&outfile, "%s/virhostcpudata/linux-cpustat-%s.out",
                     abs_srcdir, testData->name) < 0)
         goto fail;
 
@@ -225,7 +225,7 @@ mymain(void)
 {
     int ret = 0;
     size_t i;
-    const struct linuxTestNodeInfoData nodeData[] = {
+    const struct linuxTestHostCPUData nodeData[] = {
         {"test1", VIR_ARCH_X86_64},
         {"test1", VIR_ARCH_PPC},
         {"test2", VIR_ARCH_X86_64},
@@ -251,7 +251,7 @@ mymain(void)
         return EXIT_FAILURE;
 
     for (i = 0; i < ARRAY_CARDINALITY(nodeData); i++)
-      if (virtTestRun(nodeData[i].testName, linuxTestNodeInfo, &nodeData[i]) != 0)
+      if (virtTestRun(nodeData[i].testName, linuxTestHostCPU, &nodeData[i]) != 0)
         ret = -1;
 
 # define DO_TEST_CPU_STATS(name, ncpus) \
@@ -266,6 +266,6 @@ mymain(void)
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
 
-VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/nodeinfomock.so")
+VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/virhostcpumock.so")
 
 #endif /* __linux__ */
-- 
2.5.5




More information about the libvir-list mailing list