[CRIU] [PATCH 18/22] compel: Move in cpu interface

Cyrill Gorcunov gorcunov at openvz.org
Wed Oct 19 12:21:33 PDT 2016


We will need it when parasite engine will
be creating signal frames.

Export appropriate headers and use it in CRIU
by linking with libcompel.a.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 compel/Makefile                                    |  19 +++
 compel/arch/aarch64/src/lib/cpu.c                  |  28 +++
 .../arch/aarch64/src/lib/include/compel/asm/cpu.h  |   6 +
 .../src/lib/include/compel/asm/processor-flags.h   |   4 +
 .../aarch64/src/lib/include/compel/asm/processor.h |   4 +
 compel/arch/arm/src/lib/cpu.c                      |  28 +++
 compel/arch/arm/src/lib/include/compel/asm/cpu.h   |   6 +
 .../src/lib/include/compel}/asm/processor-flags.h  |   6 +-
 .../arm/src/lib/include/compel}/asm/processor.h    |   6 +-
 compel/arch/ppc64/src/lib/cpu.c                    |  42 +++++
 compel/arch/ppc64/src/lib/include/compel/asm/cpu.h |  10 ++
 .../src/lib/include/compel/asm/processor-flags.h   |   4 +
 .../ppc64/src/lib/include/compel/asm/processor.h   |   4 +
 compel/arch/x86/src/lib/cpu.c                      | 189 +++++++++++++++++++++
 .../arch/x86/src/lib/include/compel}/asm/cpu.h     |  29 ++--
 .../src/lib/include/compel}/asm/processor-flags.h  |   6 +-
 .../x86/src/lib/include/compel/asm/processor.h     |   4 +
 compel/include/uapi/compel/cpu.h                   |  14 ++
 criu/Makefile                                      |   1 +
 criu/arch/aarch64/cpu.c                            |   5 -
 criu/arch/aarch64/crtools.c                        |   3 +-
 criu/arch/aarch64/include/asm/cpu.h                |   1 -
 criu/arch/aarch64/include/asm/processor-flags.h    |   4 -
 criu/arch/arm/cpu.c                                |   5 -
 criu/arch/arm/crtools.c                            |   3 +-
 criu/arch/arm/include/asm/cpu.h                    |   1 -
 criu/arch/ppc64/cpu.c                              |  17 +-
 criu/arch/ppc64/include/asm/cpu.h                  |   1 -
 criu/arch/ppc64/include/asm/processor-flags.h      |   4 -
 criu/arch/x86/cpu.c                                | 177 +------------------
 criu/arch/x86/crtools.c                            |   2 +-
 criu/arch/x86/infect.c                             |   2 +-
 criu/include/cpu.h                                 |   3 +-
 criu/parasite-syscall.c                            |   2 +-
 34 files changed, 400 insertions(+), 240 deletions(-)
 create mode 100644 compel/arch/aarch64/src/lib/cpu.c
 create mode 100644 compel/arch/aarch64/src/lib/include/compel/asm/cpu.h
 create mode 100644 compel/arch/aarch64/src/lib/include/compel/asm/processor-flags.h
 create mode 100644 compel/arch/aarch64/src/lib/include/compel/asm/processor.h
 create mode 100644 compel/arch/arm/src/lib/cpu.c
 create mode 100644 compel/arch/arm/src/lib/include/compel/asm/cpu.h
 rename {criu/arch/arm/include => compel/arch/arm/src/lib/include/compel}/asm/processor-flags.h (90%)
 rename {criu/arch/arm/include => compel/arch/arm/src/lib/include/compel}/asm/processor.h (81%)
 create mode 100644 compel/arch/ppc64/src/lib/cpu.c
 create mode 100644 compel/arch/ppc64/src/lib/include/compel/asm/cpu.h
 create mode 100644 compel/arch/ppc64/src/lib/include/compel/asm/processor-flags.h
 create mode 100644 compel/arch/ppc64/src/lib/include/compel/asm/processor.h
 create mode 100644 compel/arch/x86/src/lib/cpu.c
 rename {criu/arch/x86/include => compel/arch/x86/src/lib/include/compel}/asm/cpu.h (94%)
 rename {criu/arch/x86/include => compel/arch/x86/src/lib/include/compel}/asm/processor-flags.h (88%)
 create mode 100644 compel/arch/x86/src/lib/include/compel/asm/processor.h
 create mode 100644 compel/include/uapi/compel/cpu.h
 delete mode 100644 criu/arch/aarch64/include/asm/cpu.h
 delete mode 100644 criu/arch/aarch64/include/asm/processor-flags.h
 delete mode 100644 criu/arch/arm/include/asm/cpu.h
 delete mode 100644 criu/arch/ppc64/include/asm/cpu.h
 delete mode 100644 criu/arch/ppc64/include/asm/processor-flags.h

diff --git a/compel/Makefile b/compel/Makefile
index bab15489deff..3fa47455d3fb 100644
--- a/compel/Makefile
+++ b/compel/Makefile
@@ -25,10 +25,29 @@ host-lib-y		+= src/lib/handle-elf.o
 lib-y			+= src/lib/fds.o
 lib-y			+= src/lib/argv.o
 lib-y			+= src/lib/compel.o
+lib-y			+= arch/$(ARCH)/src/lib/cpu.o
 
 #
 # This requires arch specific header to
 # be generated into uapi
+$(obj)/include/uapi/compel/asm/cpu.h: $(obj)/arch/$(ARCH)/src/lib/include/compel/asm/cpu.h
+	$(call msg-gen, $@)
+	$(Q) cp $^ $@
+cleanup-y		+= $(obj)/include/uapi/compel/asm/cpu.h
+headers-y		+= $(obj)/include/uapi/compel/asm/cpu.h
+
+$(obj)/include/uapi/compel/asm/processor-flags.h: $(obj)/arch/$(ARCH)/src/lib/include/compel/asm/processor-flags.h
+	$(call msg-gen, $@)
+	$(Q) cp $^ $@
+cleanup-y		+= $(obj)/include/uapi/compel/asm/processor-flags.h
+headers-y		+= $(obj)/include/uapi/compel/asm/processor-flags.h
+
+$(obj)/include/uapi/compel/asm/processor.h: $(obj)/arch/$(ARCH)/src/lib/include/compel/asm/processor.h
+	$(call msg-gen, $@)
+	$(Q) cp $^ $@
+cleanup-y		+= $(obj)/include/uapi/compel/asm/processor.h
+headers-y		+= $(obj)/include/uapi/compel/asm/processor.h
+
 $(obj)/include/uapi/compel/asm/bitops.h: $(obj)/arch/$(ARCH)/src/lib/include/compel/asm/bitops.h
 	$(call msg-gen, $@)
 	$(Q) cp $^ $@
diff --git a/compel/arch/aarch64/src/lib/cpu.c b/compel/arch/aarch64/src/lib/cpu.c
new file mode 100644
index 000000000000..ddfcba02bba5
--- /dev/null
+++ b/compel/arch/aarch64/src/lib/cpu.c
@@ -0,0 +1,28 @@
+#include <string.h>
+#include <stdbool.h>
+
+#include "uapi/compel/cpu.h"
+
+#include "asm/bitops.h"
+
+#include "log.h"
+
+#undef	LOG_PREFIX
+#define LOG_PREFIX "cpu: "
+
+static compel_cpuinfo_t rt_info;
+static bool rt_info_done = false;
+
+void compel_set_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { }
+void compel_clear_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { }
+int compel_test_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { return 0; }
+int compel_cpuid(compel_cpuinfo_t *info) { return 0; }
+
+bool cpu_has_feature(unsigned int feature)
+{
+	if (!rt_info_done) {
+		compel_cpuid(&rt_info);
+		rt_info_done = true;
+	}
+	return compel_test_cpu_cap(&rt_info, feature);
+}
diff --git a/compel/arch/aarch64/src/lib/include/compel/asm/cpu.h b/compel/arch/aarch64/src/lib/include/compel/asm/cpu.h
new file mode 100644
index 000000000000..c35460e15bde
--- /dev/null
+++ b/compel/arch/aarch64/src/lib/include/compel/asm/cpu.h
@@ -0,0 +1,6 @@
+#ifndef UAPI_COMPEL_ASM_CPU_H__
+#define UAPI_COMPEL_ASM_CPU_H__
+
+typedef struct { } compel_cpuinfo_t;
+
+#endif /* UAPI_COMPEL_ASM_CPU_H__ */
diff --git a/compel/arch/aarch64/src/lib/include/compel/asm/processor-flags.h b/compel/arch/aarch64/src/lib/include/compel/asm/processor-flags.h
new file mode 100644
index 000000000000..15719184a3ba
--- /dev/null
+++ b/compel/arch/aarch64/src/lib/include/compel/asm/processor-flags.h
@@ -0,0 +1,4 @@
+#ifndef UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__
+#define UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__
+
+#endif /* UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__ */
diff --git a/compel/arch/aarch64/src/lib/include/compel/asm/processor.h b/compel/arch/aarch64/src/lib/include/compel/asm/processor.h
new file mode 100644
index 000000000000..7376f8879a1a
--- /dev/null
+++ b/compel/arch/aarch64/src/lib/include/compel/asm/processor.h
@@ -0,0 +1,4 @@
+#ifndef UAPI_COMPEL_ASM_PROCESSOR_H__
+#define UAPI_COMPEL_ASM_PROCESSOR_H__
+
+#endif /* UAPI_COMPEL_ASM_PROCESSOR_H__ */
diff --git a/compel/arch/arm/src/lib/cpu.c b/compel/arch/arm/src/lib/cpu.c
new file mode 100644
index 000000000000..ddfcba02bba5
--- /dev/null
+++ b/compel/arch/arm/src/lib/cpu.c
@@ -0,0 +1,28 @@
+#include <string.h>
+#include <stdbool.h>
+
+#include "uapi/compel/cpu.h"
+
+#include "asm/bitops.h"
+
+#include "log.h"
+
+#undef	LOG_PREFIX
+#define LOG_PREFIX "cpu: "
+
+static compel_cpuinfo_t rt_info;
+static bool rt_info_done = false;
+
+void compel_set_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { }
+void compel_clear_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { }
+int compel_test_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { return 0; }
+int compel_cpuid(compel_cpuinfo_t *info) { return 0; }
+
+bool cpu_has_feature(unsigned int feature)
+{
+	if (!rt_info_done) {
+		compel_cpuid(&rt_info);
+		rt_info_done = true;
+	}
+	return compel_test_cpu_cap(&rt_info, feature);
+}
diff --git a/compel/arch/arm/src/lib/include/compel/asm/cpu.h b/compel/arch/arm/src/lib/include/compel/asm/cpu.h
new file mode 100644
index 000000000000..c35460e15bde
--- /dev/null
+++ b/compel/arch/arm/src/lib/include/compel/asm/cpu.h
@@ -0,0 +1,6 @@
+#ifndef UAPI_COMPEL_ASM_CPU_H__
+#define UAPI_COMPEL_ASM_CPU_H__
+
+typedef struct { } compel_cpuinfo_t;
+
+#endif /* UAPI_COMPEL_ASM_CPU_H__ */
diff --git a/criu/arch/arm/include/asm/processor-flags.h b/compel/arch/arm/src/lib/include/compel/asm/processor-flags.h
similarity index 90%
rename from criu/arch/arm/include/asm/processor-flags.h
rename to compel/arch/arm/src/lib/include/compel/asm/processor-flags.h
index fc00a9e64a2e..c772a911f39b 100644
--- a/criu/arch/arm/include/asm/processor-flags.h
+++ b/compel/arch/arm/src/lib/include/compel/asm/processor-flags.h
@@ -1,5 +1,5 @@
-#ifndef __CR_PROCESSOR_FLAGS_H__
-#define __CR_PROCESSOR_FLAGS_H__
+#ifndef UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__
+#define UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__
 
 /* Copied from the Linux kernel header arch/arm/include/uapi/asm/ptrace.h */
 
@@ -39,4 +39,4 @@
 #define PSR_x           0x0000ff00      /* Extension            */
 #define PSR_c           0x000000ff      /* Control              */
 
-#endif
+#endif /* UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__ */
diff --git a/criu/arch/arm/include/asm/processor.h b/compel/arch/arm/src/lib/include/compel/asm/processor.h
similarity index 81%
rename from criu/arch/arm/include/asm/processor.h
rename to compel/arch/arm/src/lib/include/compel/asm/processor.h
index a390cfd322ec..d5c0077448f5 100644
--- a/criu/arch/arm/include/asm/processor.h
+++ b/compel/arch/arm/src/lib/include/compel/asm/processor.h
@@ -1,5 +1,5 @@
-#ifndef __CR_PROCESSOR_H__
-#define __CR_PROCESSOR_H__
+#ifndef UAPI_COMPEL_ASM_PROCESSOR_H__
+#define UAPI_COMPEL_ASM_PROCESSOR_H__
 
 /* Copied from linux kernel arch/arm/include/asm/unified.h */
 
@@ -25,4 +25,4 @@ static inline void prefetchw(const void *ptr)
 		:: "p" (ptr));
 }
 
-#endif /* __CR_PROCESSOR_H__ */
+#endif /* UAPI_COMPEL_ASM_PROCESSOR_H__ */
diff --git a/compel/arch/ppc64/src/lib/cpu.c b/compel/arch/ppc64/src/lib/cpu.c
new file mode 100644
index 000000000000..eb3798489a91
--- /dev/null
+++ b/compel/arch/ppc64/src/lib/cpu.c
@@ -0,0 +1,42 @@
+#include <sys/auxv.h>
+#include <asm/cputable.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#include "uapi/compel/cpu.h"
+
+#include "asm/bitops.h"
+
+#include "log.h"
+
+#undef	LOG_PREFIX
+#define LOG_PREFIX "cpu: "
+
+static compel_cpuinfo_t rt_info;
+static bool rt_info_done = false;
+
+void compel_set_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { }
+void compel_clear_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { }
+int compel_test_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { return 0; }
+
+int compel_cpuid(compel_cpuinfo_t *info)
+{
+	info->hwcap[0] = getauxval(AT_HWCAP);
+	info->hwcap[1] = getauxval(AT_HWCAP2);
+
+	if (!info->hwcap[0] || !info->hwcap[1]) {
+		pr_err("Can't read the hardware capabilities");
+		return -1;
+	}
+
+	return 0;
+}
+
+bool cpu_has_feature(unsigned int feature)
+{
+	if (!rt_info_done) {
+		compel_cpuid(&rt_info);
+		rt_info_done = true;
+	}
+	return compel_test_cpu_cap(&rt_info, feature);
+}
diff --git a/compel/arch/ppc64/src/lib/include/compel/asm/cpu.h b/compel/arch/ppc64/src/lib/include/compel/asm/cpu.h
new file mode 100644
index 000000000000..59925868c15a
--- /dev/null
+++ b/compel/arch/ppc64/src/lib/include/compel/asm/cpu.h
@@ -0,0 +1,10 @@
+#ifndef UAPI_COMPEL_ASM_CPU_H__
+#define UAPI_COMPEL_ASM_CPU_H__
+
+#include <stdint.h>
+
+typedef struct {
+	uint64_t	hwcap[2];
+} compel_cpuinfo_t;
+
+#endif /* UAPI_COMPEL_ASM_CPU_H__ */
diff --git a/compel/arch/ppc64/src/lib/include/compel/asm/processor-flags.h b/compel/arch/ppc64/src/lib/include/compel/asm/processor-flags.h
new file mode 100644
index 000000000000..15719184a3ba
--- /dev/null
+++ b/compel/arch/ppc64/src/lib/include/compel/asm/processor-flags.h
@@ -0,0 +1,4 @@
+#ifndef UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__
+#define UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__
+
+#endif /* UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__ */
diff --git a/compel/arch/ppc64/src/lib/include/compel/asm/processor.h b/compel/arch/ppc64/src/lib/include/compel/asm/processor.h
new file mode 100644
index 000000000000..7376f8879a1a
--- /dev/null
+++ b/compel/arch/ppc64/src/lib/include/compel/asm/processor.h
@@ -0,0 +1,4 @@
+#ifndef UAPI_COMPEL_ASM_PROCESSOR_H__
+#define UAPI_COMPEL_ASM_PROCESSOR_H__
+
+#endif /* UAPI_COMPEL_ASM_PROCESSOR_H__ */
diff --git a/compel/arch/x86/src/lib/cpu.c b/compel/arch/x86/src/lib/cpu.c
new file mode 100644
index 000000000000..7e379d04d0f3
--- /dev/null
+++ b/compel/arch/x86/src/lib/cpu.c
@@ -0,0 +1,189 @@
+#include <string.h>
+#include <stdbool.h>
+
+#include "uapi/compel/cpu.h"
+
+#include "asm/bitops.h"
+
+#include "compiler.h"
+#include "log.h"
+
+#undef	LOG_PREFIX
+#define LOG_PREFIX "cpu: "
+
+static compel_cpuinfo_t rt_info;
+static bool rt_info_done = false;
+
+void compel_set_cpu_cap(compel_cpuinfo_t *c, unsigned int feature)
+{
+	if (likely(feature < NCAPINTS_BITS))
+		set_bit(feature, (unsigned long *)c->x86_capability);
+}
+
+void compel_clear_cpu_cap(compel_cpuinfo_t *c, unsigned int feature)
+{
+	if (likely(feature < NCAPINTS_BITS))
+		clear_bit(feature, (unsigned long *)c->x86_capability);
+}
+
+int compel_test_cpu_cap(compel_cpuinfo_t *c, unsigned int feature)
+{
+	if (likely(feature < NCAPINTS_BITS))
+		return test_bit(feature, (unsigned long *)c->x86_capability);
+	return 0;
+}
+
+int compel_cpuid(compel_cpuinfo_t *c)
+{
+	/*
+	 * See cpu_detect() in the kernel, also
+	 * read cpuid specs not only from general
+	 * SDM but for extended instructions set
+	 * reference.
+	 */
+
+	/* Get vendor name */
+	cpuid(0x00000000,
+	      (unsigned int *)&c->cpuid_level,
+	      (unsigned int *)&c->x86_vendor_id[0],
+	      (unsigned int *)&c->x86_vendor_id[8],
+	      (unsigned int *)&c->x86_vendor_id[4]);
+
+	if (!strcmp(c->x86_vendor_id, "GenuineIntel")) {
+		c->x86_vendor = X86_VENDOR_INTEL;
+	} else if (!strcmp(c->x86_vendor_id, "AuthenticAMD")) {
+		c->x86_vendor = X86_VENDOR_AMD;
+	} else {
+		pr_err("Unsupported CPU vendor %s\n",
+		       c->x86_vendor_id);
+		return -1;
+	}
+
+	c->x86_family = 4;
+
+	/* Intel-defined flags: level 0x00000001 */
+	if (c->cpuid_level >= 0x00000001) {
+		uint32_t eax, ebx, ecx, edx;
+
+		cpuid(0x00000001, &eax, &ebx, &ecx, &edx);
+		c->x86_family = (eax >> 8) & 0xf;
+		c->x86_model = (eax >> 4) & 0xf;
+		c->x86_mask = eax & 0xf;
+
+		if (c->x86_family == 0xf)
+			c->x86_family += (eax >> 20) & 0xff;
+		if (c->x86_family >= 0x6)
+			c->x86_model += ((eax >> 16) & 0xf) << 4;
+
+		c->x86_capability[0] = edx;
+		c->x86_capability[4] = ecx;
+	}
+
+	/* Additional Intel-defined flags: level 0x00000007 */
+	if (c->cpuid_level >= 0x00000007) {
+		uint32_t eax, ebx, ecx, edx;
+
+		cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx);
+		c->x86_capability[9] = ebx;
+		c->x86_capability[11] = ecx;
+	}
+
+	/* Extended state features: level 0x0000000d */
+	if (c->cpuid_level >= 0x0000000d) {
+		uint32_t eax, ebx, ecx, edx;
+
+		cpuid_count(0x0000000d, 1, &eax, &ebx, &ecx, &edx);
+		c->x86_capability[10] = eax;
+	}
+
+	/* AMD-defined flags: level 0x80000001 */
+	c->extended_cpuid_level = cpuid_eax(0x80000000);
+
+	if ((c->extended_cpuid_level & 0xffff0000) == 0x80000000) {
+		if (c->extended_cpuid_level >= 0x80000001) {
+			c->x86_capability[1] = cpuid_edx(0x80000001);
+			c->x86_capability[6] = cpuid_ecx(0x80000001);
+		}
+	}
+
+	/*
+	 * We're don't care about scattered features for now,
+	 * otherwise look into init_scattered_cpuid_features()
+	 * in kernel.
+	 */
+
+	if (c->extended_cpuid_level >= 0x80000004) {
+		unsigned int *v;
+		char *p, *q;
+		v = (unsigned int *)c->x86_model_id;
+		cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
+		cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
+		cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
+		c->x86_model_id[48] = 0;
+
+		/*
+		 * Intel chips right-justify this string for some dumb reason;
+		 * undo that brain damage:
+		 */
+		p = q = &c->x86_model_id[0];
+		while (*p == ' ')
+			p++;
+		if (p != q) {
+			while (*p)
+				*q++ = *p++;
+			while (q <= &c->x86_model_id[48])
+				*q++ = '\0';	/* Zero-pad the rest */
+		}
+	}
+
+	/* On x86-64 NOP is always present */
+	compel_set_cpu_cap(c, X86_FEATURE_NOPL);
+
+	switch (c->x86_vendor) {
+	case X86_VENDOR_INTEL:
+		/*
+		 * Strictly speaking we need to read MSR_IA32_MISC_ENABLE
+		 * here but on ring3 it's impossible.
+		 */
+		if (c->x86_family == 15) {
+			compel_clear_cpu_cap(c, X86_FEATURE_REP_GOOD);
+			compel_clear_cpu_cap(c, X86_FEATURE_ERMS);
+		} else if (c->x86_family == 6) {
+			/* On x86-64 rep is fine */
+			compel_set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+		}
+
+		/* See filter_cpuid_features in kernel */
+		if ((int32_t)c->cpuid_level < (int32_t)0x0000000d)
+			compel_clear_cpu_cap(c, X86_FEATURE_XSAVE);
+		break;
+	case X86_VENDOR_AMD:
+		/*
+		 * Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+		 * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
+		 */
+		compel_clear_cpu_cap(c, 0 * 32 + 31);
+		if (c->x86_family >= 0x10)
+			compel_set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+		if (c->x86_family == 0xf) {
+			uint32_t level;
+
+			/* On C+ stepping K8 rep microcode works well for copy/memset */
+			level = cpuid_eax(1);
+			if ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
+				compel_set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+		}
+		break;
+	}
+
+	return 0;
+}
+
+bool cpu_has_feature(unsigned int feature)
+{
+	if (!rt_info_done) {
+		compel_cpuid(&rt_info);
+		rt_info_done = true;
+	}
+	return compel_test_cpu_cap(&rt_info, feature);
+}
diff --git a/criu/arch/x86/include/asm/cpu.h b/compel/arch/x86/src/lib/include/compel/asm/cpu.h
similarity index 94%
rename from criu/arch/x86/include/asm/cpu.h
rename to compel/arch/x86/src/lib/include/compel/asm/cpu.h
index 6f49229d6396..ae5cee230cff 100644
--- a/criu/arch/x86/include/asm/cpu.h
+++ b/compel/arch/x86/src/lib/include/compel/asm/cpu.h
@@ -1,7 +1,7 @@
-#ifndef __CR_ASM_CPU_H__
-#define __CR_ASM_CPU_H__
+#ifndef UAPI_COMPEL_ASM_CPU_H__
+#define UAPI_COMPEL_ASM_CPU_H__
 
-#include "asm/types.h"
+#include <stdint.h>
 
 /*
  * Adopted from linux kernel and enhanced from Intel/AMD manuals.
@@ -176,8 +176,6 @@ static inline unsigned int cpuid_edx(unsigned int op)
 	return edx;
 }
 
-#define X86_FEATURE_VERSION		1
-
 enum {
 	X86_VENDOR_INTEL	= 0,
 	X86_VENDOR_AMD		= 1,
@@ -186,22 +184,17 @@ enum {
 };
 
 struct cpuinfo_x86 {
-	u8			x86_family;
-	u8			x86_vendor;
-	u8			x86_model;
-	u8			x86_mask;
-	u32			x86_capability[NCAPINTS];
-	u32			extended_cpuid_level;
+	uint8_t			x86_family;
+	uint8_t			x86_vendor;
+	uint8_t			x86_model;
+	uint8_t			x86_mask;
+	uint32_t		x86_capability[NCAPINTS];
+	uint32_t		extended_cpuid_level;
 	int			cpuid_level;
 	char			x86_vendor_id[16];
 	char			x86_model_id[64];
 };
 
-extern bool cpu_has_feature(unsigned int feature);
-extern int cpu_init(void);
-extern int cpu_dump_cpuinfo(void);
-extern int cpu_validate_cpuinfo(void);
-extern int cpuinfo_dump(void);
-extern int cpuinfo_check(void);
+typedef struct cpuinfo_x86 compel_cpuinfo_t;
 
-#endif /* __CR_CPU_H__ */
+#endif /* UAPI_COMPEL_ASM_CPU_H__ */
diff --git a/criu/arch/x86/include/asm/processor-flags.h b/compel/arch/x86/src/lib/include/compel/asm/processor-flags.h
similarity index 88%
rename from criu/arch/x86/include/asm/processor-flags.h
rename to compel/arch/x86/src/lib/include/compel/asm/processor-flags.h
index 9f1bccdbece8..dd33dbfd17b0 100644
--- a/criu/arch/x86/include/asm/processor-flags.h
+++ b/compel/arch/x86/src/lib/include/compel/asm/processor-flags.h
@@ -1,5 +1,5 @@
-#ifndef __CR_PROCESSOR_FLAGS_H__
-#define __CR_PROCESSOR_FLAGS_H__
+#ifndef UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__
+#define UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__
 
 /* Taken from linux kernel headers */
 
@@ -25,4 +25,4 @@
 #define X86_EFLAGS_VIP	0x00100000 /* Virtual Interrupt Pending */
 #define X86_EFLAGS_ID	0x00200000 /* CPUID detection flag */
 
-#endif /* __CR_PROCESSOR_FLAGS_H__ */
+#endif /* UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__ */
diff --git a/compel/arch/x86/src/lib/include/compel/asm/processor.h b/compel/arch/x86/src/lib/include/compel/asm/processor.h
new file mode 100644
index 000000000000..7376f8879a1a
--- /dev/null
+++ b/compel/arch/x86/src/lib/include/compel/asm/processor.h
@@ -0,0 +1,4 @@
+#ifndef UAPI_COMPEL_ASM_PROCESSOR_H__
+#define UAPI_COMPEL_ASM_PROCESSOR_H__
+
+#endif /* UAPI_COMPEL_ASM_PROCESSOR_H__ */
diff --git a/compel/include/uapi/compel/cpu.h b/compel/include/uapi/compel/cpu.h
new file mode 100644
index 000000000000..662883bc941d
--- /dev/null
+++ b/compel/include/uapi/compel/cpu.h
@@ -0,0 +1,14 @@
+#ifndef UAPI_COMPEL_CPU_H__
+#define UAPI_COMPEL_CPU_H__
+
+#include <stdbool.h>
+
+#include <compel/asm/cpu.h>
+
+extern void compel_set_cpu_cap(compel_cpuinfo_t *info, unsigned int feature);
+extern void compel_clear_cpu_cap(compel_cpuinfo_t *info, unsigned int feature);
+extern int compel_test_cpu_cap(compel_cpuinfo_t *info, unsigned int feature);
+extern int compel_cpuid(compel_cpuinfo_t *info);
+extern bool cpu_has_feature(unsigned int feature);
+
+#endif /* UAPI_COMPEL_CPU_H__ */
diff --git a/criu/Makefile b/criu/Makefile
index e9cc9fd626b7..45875ade4901 100644
--- a/criu/Makefile
+++ b/criu/Makefile
@@ -72,6 +72,7 @@ PROGRAM-BUILTINS	+= criu/pie/native.lib.a
 PROGRAM-BUILTINS	+= images/built-in.o
 PROGRAM-BUILTINS	+= $(obj)/built-in.o
 PROGRAM-BUILTINS	+= $(ARCH-LIB)
+PROGRAM-BUILTINS	+= compel/libcompel.a
 
 $(obj)/built-in.o: pie
 	$(Q) $(MAKE) $(call build-as,Makefile.crtools,criu) all
diff --git a/criu/arch/aarch64/cpu.c b/criu/arch/aarch64/cpu.c
index 040fe14fcfb7..34313fb1569b 100644
--- a/criu/arch/aarch64/cpu.c
+++ b/criu/arch/aarch64/cpu.c
@@ -4,11 +4,6 @@
 #include <errno.h>
 #include "cpu.h"
 
-bool cpu_has_feature(unsigned int feature)
-{
-	return false;
-}
-
 int cpu_init(void)
 {
 	return 0;
diff --git a/criu/arch/aarch64/crtools.c b/criu/arch/aarch64/crtools.c
index c61df4ae5758..c1da5ef01c2b 100644
--- a/criu/arch/aarch64/crtools.c
+++ b/criu/arch/aarch64/crtools.c
@@ -3,11 +3,12 @@
 
 #include <linux/elf.h>
 
+#include <compel/asm/processor-flags.h>
+
 #include "asm/types.h"
 #include "asm/restorer.h"
 #include "compiler.h"
 #include "ptrace.h"
-#include "asm/processor-flags.h"
 #include "asm/dump.h"
 #include "protobuf.h"
 #include "images/core.pb-c.h"
diff --git a/criu/arch/aarch64/include/asm/cpu.h b/criu/arch/aarch64/include/asm/cpu.h
deleted file mode 100644
index 59118c211d10..000000000000
--- a/criu/arch/aarch64/include/asm/cpu.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <stdbool.h>
diff --git a/criu/arch/aarch64/include/asm/processor-flags.h b/criu/arch/aarch64/include/asm/processor-flags.h
deleted file mode 100644
index c1888af36fa0..000000000000
--- a/criu/arch/aarch64/include/asm/processor-flags.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __CR_PROCESSOR_FLAGS_H__
-#define __CR_PROCESSOR_FLAGS_H__
-
-#endif
diff --git a/criu/arch/arm/cpu.c b/criu/arch/arm/cpu.c
index 040fe14fcfb7..34313fb1569b 100644
--- a/criu/arch/arm/cpu.c
+++ b/criu/arch/arm/cpu.c
@@ -4,11 +4,6 @@
 #include <errno.h>
 #include "cpu.h"
 
-bool cpu_has_feature(unsigned int feature)
-{
-	return false;
-}
-
 int cpu_init(void)
 {
 	return 0;
diff --git a/criu/arch/arm/crtools.c b/criu/arch/arm/crtools.c
index 4caa417f304e..5b6469d59407 100644
--- a/criu/arch/arm/crtools.c
+++ b/criu/arch/arm/crtools.c
@@ -1,12 +1,13 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <compel/asm/processor-flags.h>
+
 #include "asm/types.h"
 #include "asm/restorer.h"
 #include "asm/dump.h"
 #include "compiler.h"
 #include "ptrace.h"
-#include "asm/processor-flags.h"
 #include "protobuf.h"
 #include "images/core.pb-c.h"
 #include "images/creds.pb-c.h"
diff --git a/criu/arch/arm/include/asm/cpu.h b/criu/arch/arm/include/asm/cpu.h
deleted file mode 100644
index 59118c211d10..000000000000
--- a/criu/arch/arm/include/asm/cpu.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <stdbool.h>
diff --git a/criu/arch/ppc64/cpu.c b/criu/arch/ppc64/cpu.c
index 222bc62d12bf..aecba78014d8 100644
--- a/criu/arch/ppc64/cpu.c
+++ b/criu/arch/ppc64/cpu.c
@@ -6,7 +6,6 @@
 #include <asm/cputable.h>
 
 #include "asm/types.h"
-#include "asm/cpu.h"
 
 #include "cr_options.h"
 #include "image.h"
@@ -17,7 +16,7 @@
 #include "protobuf.h"
 #include "images/cpuinfo.pb-c.h"
 
-static uint64_t hwcap[2];
+static compel_cpuinfo_t rt_cpuinfo;
 
 #ifdef __LITTLE_ENDIAN__
 #define CURRENT_ENDIANNESS	CPUINFO_PPC64_ENTRY__ENDIANNESS__LITTLEENDIAN
@@ -27,14 +26,7 @@ static uint64_t hwcap[2];
 
 int cpu_init(void)
 {
-	hwcap[0] = getauxval(AT_HWCAP);
-	hwcap[1] = getauxval(AT_HWCAP2);
-
-	if (!hwcap[0] || !hwcap[1]) {
-		pr_err("Can't read the hardware capabilities");
-		return -1;
-	}
-	return 0;
+	return compel_cpuid(&rt_cpuinfo);
 }
 
 int cpu_dump_cpuinfo(void)
@@ -54,7 +46,7 @@ int cpu_dump_cpuinfo(void)
 
 	cpu_ppc64_info.endian = CURRENT_ENDIANNESS;
 	cpu_ppc64_info.n_hwcap = 2;
-	cpu_ppc64_info.hwcap = hwcap;
+	cpu_ppc64_info.hwcap = rt_cpuinfo.hwcap;
 
 	ret = pb_write_one(img, &cpu_info, PB_CPUINFO);
 
@@ -92,7 +84,8 @@ int cpu_validate_cpuinfo(void)
 	}
 
 #define CHECK_FEATURE(s,f) do {						\
-		if ((cpu_ppc64_entry->hwcap[s] & f) && !(hwcap[s] & f)) { \
+		if ((cpu_ppc64_entry->hwcap[s] & f) &&			\
+		    !(rt_cpuinfo.hwcap[s] & f)) {			\
 			pr_err("CPU Feature %s required by image "	\
 			       "is not supported on host.\n", #f);	\
 			goto error;					\
diff --git a/criu/arch/ppc64/include/asm/cpu.h b/criu/arch/ppc64/include/asm/cpu.h
deleted file mode 100644
index 59118c211d10..000000000000
--- a/criu/arch/ppc64/include/asm/cpu.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <stdbool.h>
diff --git a/criu/arch/ppc64/include/asm/processor-flags.h b/criu/arch/ppc64/include/asm/processor-flags.h
deleted file mode 100644
index c1888af36fa0..000000000000
--- a/criu/arch/ppc64/include/asm/processor-flags.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __CR_PROCESSOR_FLAGS_H__
-#define __CR_PROCESSOR_FLAGS_H__
-
-#endif
diff --git a/criu/arch/x86/cpu.c b/criu/arch/x86/cpu.c
index df77f30c9505..6b8ed155994e 100644
--- a/criu/arch/x86/cpu.c
+++ b/criu/arch/x86/cpu.c
@@ -7,9 +7,10 @@
 #include <sys/types.h>
 
 #include <compel/asm/bitops.h>
+#include <compel/asm/fpu.h>
+#include <compel/cpu.h>
 
 #include "asm/types.h"
-#include "asm/cpu.h"
 
 #include "compiler.h"
 
@@ -26,181 +27,11 @@
 #undef	LOG_PREFIX
 #define LOG_PREFIX "cpu: "
 
-static struct cpuinfo_x86 rt_cpu_info;
-
-static void set_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
-{
-	if (likely(feature < NCAPINTS_BITS))
-		set_bit(feature, (unsigned long *)c->x86_capability);
-}
-
-static void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
-{
-	if (likely(feature < NCAPINTS_BITS))
-		clear_bit(feature, (unsigned long *)c->x86_capability);
-}
-
-static int test_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
-{
-	if (likely(feature < NCAPINTS_BITS))
-		return test_bit(feature, (unsigned long *)c->x86_capability);
-	return 0;
-}
-
-bool cpu_has_feature(unsigned int feature)
-{
-	return test_cpu_cap(&rt_cpu_info, feature);
-}
-
-static int cpu_init_cpuid(struct cpuinfo_x86 *c)
-{
-	/*
-	 * See cpu_detect() in the kernel, also
-	 * read cpuid specs not only from general
-	 * SDM but for extended instructions set
-	 * reference.
-	 */
-
-	/* Get vendor name */
-	cpuid(0x00000000,
-	      (unsigned int *)&c->cpuid_level,
-	      (unsigned int *)&c->x86_vendor_id[0],
-	      (unsigned int *)&c->x86_vendor_id[8],
-	      (unsigned int *)&c->x86_vendor_id[4]);
-
-	if (!strcmp(c->x86_vendor_id, "GenuineIntel")) {
-		c->x86_vendor = X86_VENDOR_INTEL;
-	} else if (!strcmp(c->x86_vendor_id, "AuthenticAMD")) {
-		c->x86_vendor = X86_VENDOR_AMD;
-	} else {
-		pr_err("Unsupported CPU vendor %s\n",
-		       c->x86_vendor_id);
-		return -1;
-	}
-
-	c->x86_family = 4;
-
-	/* Intel-defined flags: level 0x00000001 */
-	if (c->cpuid_level >= 0x00000001) {
-		u32 eax, ebx, ecx, edx;
-
-		cpuid(0x00000001, &eax, &ebx, &ecx, &edx);
-		c->x86_family = (eax >> 8) & 0xf;
-		c->x86_model = (eax >> 4) & 0xf;
-		c->x86_mask = eax & 0xf;
-
-		if (c->x86_family == 0xf)
-			c->x86_family += (eax >> 20) & 0xff;
-		if (c->x86_family >= 0x6)
-			c->x86_model += ((eax >> 16) & 0xf) << 4;
-
-		c->x86_capability[0] = edx;
-		c->x86_capability[4] = ecx;
-	}
-
-	/* Additional Intel-defined flags: level 0x00000007 */
-	if (c->cpuid_level >= 0x00000007) {
-		u32 eax, ebx, ecx, edx;
-
-		cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx);
-		c->x86_capability[9] = ebx;
-		c->x86_capability[11] = ecx;
-	}
-
-	/* Extended state features: level 0x0000000d */
-	if (c->cpuid_level >= 0x0000000d) {
-		u32 eax, ebx, ecx, edx;
-
-		cpuid_count(0x0000000d, 1, &eax, &ebx, &ecx, &edx);
-		c->x86_capability[10] = eax;
-	}
-
-	/* AMD-defined flags: level 0x80000001 */
-	c->extended_cpuid_level = cpuid_eax(0x80000000);
-
-	if ((c->extended_cpuid_level & 0xffff0000) == 0x80000000) {
-		if (c->extended_cpuid_level >= 0x80000001) {
-			c->x86_capability[1] = cpuid_edx(0x80000001);
-			c->x86_capability[6] = cpuid_ecx(0x80000001);
-		}
-	}
-
-	/*
-	 * We're don't care about scattered features for now,
-	 * otherwise look into init_scattered_cpuid_features()
-	 * in kernel.
-	 */
-
-	if (c->extended_cpuid_level >= 0x80000004) {
-		unsigned int *v;
-		char *p, *q;
-		v = (unsigned int *)c->x86_model_id;
-		cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
-		cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
-		cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
-		c->x86_model_id[48] = 0;
-
-		/*
-		 * Intel chips right-justify this string for some dumb reason;
-		 * undo that brain damage:
-		 */
-		p = q = &c->x86_model_id[0];
-		while (*p == ' ')
-			p++;
-		if (p != q) {
-			while (*p)
-				*q++ = *p++;
-			while (q <= &c->x86_model_id[48])
-				*q++ = '\0';	/* Zero-pad the rest */
-		}
-	}
-
-	/* On x86-64 NOP is always present */
-	set_cpu_cap(c, X86_FEATURE_NOPL);
-
-	switch (c->x86_vendor) {
-	case X86_VENDOR_INTEL:
-		/*
-		 * Strictly speaking we need to read MSR_IA32_MISC_ENABLE
-		 * here but on ring3 it's impossible.
-		 */
-		if (c->x86_family == 15) {
-			clear_cpu_cap(c, X86_FEATURE_REP_GOOD);
-			clear_cpu_cap(c, X86_FEATURE_ERMS);
-		} else if (c->x86_family == 6) {
-			/* On x86-64 rep is fine */
-			set_cpu_cap(c, X86_FEATURE_REP_GOOD);
-		}
-
-		/* See filter_cpuid_features in kernel */
-		if ((s32)c->cpuid_level < (s32)0x0000000d)
-			clear_cpu_cap(c, X86_FEATURE_XSAVE);
-		break;
-	case X86_VENDOR_AMD:
-		/*
-		 * Bit 31 in normal CPUID used for nonstandard 3DNow ID;
-		 * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
-		 */
-		clear_cpu_cap(c, 0 * 32 + 31);
-		if (c->x86_family >= 0x10)
-			set_cpu_cap(c, X86_FEATURE_REP_GOOD);
-		if (c->x86_family == 0xf) {
-			u32 level;
-
-			/* On C+ stepping K8 rep microcode works well for copy/memset */
-			level = cpuid_eax(1);
-			if ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
-				set_cpu_cap(c, X86_FEATURE_REP_GOOD);
-		}
-		break;
-	}
-
-	return 0;
-}
+static compel_cpuinfo_t rt_cpu_info;
 
 int cpu_init(void)
 {
-	if (cpu_init_cpuid(&rt_cpu_info))
+	if (compel_cpuid(&rt_cpu_info))
 		return -1;
 
 	BUILD_BUG_ON(sizeof(struct xsave_struct) != XSAVE_SIZE);
diff --git a/criu/arch/x86/crtools.c b/criu/arch/x86/crtools.c
index 49fe9f6c77bd..98b665354d42 100644
--- a/criu/arch/x86/crtools.c
+++ b/criu/arch/x86/crtools.c
@@ -7,8 +7,8 @@
 #include <sys/auxv.h>
 
 #include <compel/plugins/std/syscall-codes.h>
+#include <compel/asm/processor-flags.h>
 
-#include "asm/processor-flags.h"
 #include "asm/parasite-syscall.h"
 #include "asm/restorer.h"
 #include "asm/types.h"
diff --git a/criu/arch/x86/infect.c b/criu/arch/x86/infect.c
index fa07698068a8..70423f6e34c3 100644
--- a/criu/arch/x86/infect.c
+++ b/criu/arch/x86/infect.c
@@ -5,12 +5,12 @@
 #include <sys/mman.h>
 
 #include <compel/plugins/std/syscall-codes.h>
+#include <compel/cpu.h>
 
 #include "asm/parasite-syscall.h"
 #include "err.h"
 #include "asm/types.h"
 #include "errno.h"
-#include "asm/cpu.h"
 #include "parasite-syscall.h"
 #include "infect.h"
 #include "infect-priv.h"
diff --git a/criu/include/cpu.h b/criu/include/cpu.h
index e94525a9e780..e30696790e72 100644
--- a/criu/include/cpu.h
+++ b/criu/include/cpu.h
@@ -1,9 +1,8 @@
 #ifndef __CR_CPU_H__
 #define __CR_CPU_H__
 
-#include "asm/cpu.h"
+#include <compel/cpu.h>
 
-extern bool cpu_has_feature(unsigned int feature);
 extern int cpu_init(void);
 extern int cpu_dump_cpuinfo(void);
 extern int cpu_validate_cpuinfo(void);
diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
index b831a7834f2b..09c9c895afc7 100644
--- a/criu/parasite-syscall.c
+++ b/criu/parasite-syscall.c
@@ -6,6 +6,7 @@
 #include <sys/mman.h>
 
 #include <compel/plugins/std/syscall-codes.h>
+#include <compel/asm/processor-flags.h>
 
 #include "protobuf.h"
 #include "images/sa.pb-c.h"
@@ -16,7 +17,6 @@
 
 #include "imgset.h"
 #include "ptrace.h"
-#include "asm/processor-flags.h"
 #include "parasite-syscall.h"
 #include "parasite.h"
 #include "crtools.h"
-- 
2.7.4



More information about the CRIU mailing list