[CRIU] [PATCH 7/9] cpuinfo: x86 -- Add dump and validation of cpuinfo image

Cyrill Gorcunov gorcunov at openvz.org
Thu Sep 25 06:03:26 PDT 2014


If a user requested criu to dump cpuinfo image then we
write one on dump and verify on restore. At the moment
we require all cpu feature bits to match the destination
cpu in a sake of simplicity, but in future we need deps
engine which would filer out bits and test if cpu we're
restoring on is more capable than one we were dumping at
allowing to proceed restore procedure.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 arch/aarch64/cpu.c         |  10 ++++
 arch/arm/cpu.c             |  10 ++++
 arch/x86/cpu.c             | 138 +++++++++++++++++++++++++++++++++++++++++++++
 arch/x86/include/asm/cpu.h |   2 +
 cr-dump.c                  |   5 ++
 cr-restore.c               |   3 +
 include/cpu.h              |   2 +
 7 files changed, 170 insertions(+)

diff --git a/arch/aarch64/cpu.c b/arch/aarch64/cpu.c
index fc1b73e6dd5f..3a1d4122d3ac 100644
--- a/arch/aarch64/cpu.c
+++ b/arch/aarch64/cpu.c
@@ -12,3 +12,13 @@ int cpu_init(void)
 {
 	return 0;
 }
+
+int cpu_dump_cpuinfo(void)
+{
+	return 0;
+}
+
+int cpu_validate_image_cpuinfo(void)
+{
+	return 0;
+}
diff --git a/arch/arm/cpu.c b/arch/arm/cpu.c
index fc1b73e6dd5f..3a1d4122d3ac 100644
--- a/arch/arm/cpu.c
+++ b/arch/arm/cpu.c
@@ -12,3 +12,13 @@ int cpu_init(void)
 {
 	return 0;
 }
+
+int cpu_dump_cpuinfo(void)
+{
+	return 0;
+}
+
+int cpu_validate_image_cpuinfo(void)
+{
+	return 0;
+}
diff --git a/arch/x86/cpu.c b/arch/x86/cpu.c
index 12943e46927c..1a4710d1b581 100644
--- a/arch/x86/cpu.c
+++ b/arch/x86/cpu.c
@@ -13,12 +13,16 @@
 
 #include "compiler.h"
 
+#include "cr_options.h"
 #include "proc_parse.h"
 #include "util.h"
 #include "log.h"
 
 #include "cpu.h"
 
+#include "protobuf.h"
+#include "protobuf/cpuinfo.pb-c.h"
+
 #undef	LOG_PREFIX
 #define LOG_PREFIX "cpu: "
 
@@ -220,3 +224,137 @@ int cpu_init(void)
 
 	return 0;
 }
+
+int cpu_dump_cpuinfo(void)
+{
+	CpuinfoEntry cpu_info = CPUINFO_ENTRY__INIT;
+	CpuinfoX86Entry cpu_x86_info = CPUINFO_X86_ENTRY__INIT;
+	CpuinfoX86Entry *cpu_x86_info_ptr = &cpu_x86_info;
+	int fd;
+
+	fd = open_image(CR_FD_CPUINFO, O_DUMP);
+	if (fd < 0)
+		return -1;
+
+	cpu_info.x86_entry = &cpu_x86_info_ptr;
+	cpu_info.n_x86_entry = 1;
+
+	cpu_x86_info.vendor_id = (rt_cpu_info.x86_vendor == X86_VENDOR_INTEL) ?
+		CPUINFO_X86_ENTRY__VENDOR__INTEL :
+		CPUINFO_X86_ENTRY__VENDOR__AMD;
+	cpu_x86_info.cpu_family = rt_cpu_info.x86_family;
+	cpu_x86_info.model = rt_cpu_info.x86_model;
+	cpu_x86_info.stepping = rt_cpu_info.x86_mask;
+	cpu_x86_info.capability_ver = 1;
+	cpu_x86_info.n_capability = ARRAY_SIZE(rt_cpu_info.x86_capability);
+	cpu_x86_info.capability = (void *)rt_cpu_info.x86_capability;
+
+	if (rt_cpu_info.x86_model_id[0])
+		cpu_x86_info.model_id = rt_cpu_info.x86_model_id;
+
+	if (pb_write_one(fd, &cpu_info, PB_CPUINFO) < 0)
+		return -1;
+
+	close(fd);
+	return 0;
+}
+
+int cpu_validate_features(CpuinfoX86Entry *img_x86_entry)
+{
+	/*
+	 * A user knows what he is doing and disabled
+	 * capabilities check.
+	 */
+	if (opts.cpu_cap == CPU_CAP_NONE)
+		return 0;
+
+	if (img_x86_entry->n_capability != ARRAY_SIZE(rt_cpu_info.x86_capability)) {
+		/*
+		 * Image carries different number of bits.
+		 * Simply reject, we can't guarantee anything
+		 * in such case.
+		 */
+		pr_err("Size of features in image mismatch "
+		       "one provided by run time CPU (%d:%d)\n",
+		       (unsigned)img_x86_entry->n_capability,
+		       (unsigned)ARRAY_SIZE(rt_cpu_info.x86_capability));
+		return -1;
+	}
+
+	if ((opts.cpu_cap & ~CPU_CAP_FPU) == CPU_CAP_FPU) {
+		/*
+		 * If we're requested to check FPU only ignore
+		 * any other bit. It's up to a user if the
+		 * rest of mismatches won't cause problems.
+		 */
+
+#define __mismatch_fpu_bit(__bit)					\
+		(test_bit(__bit, (void *)img_x86_entry->capability) &&	\
+		 !cpu_has_feature(__bit))
+		if (__mismatch_fpu_bit(X86_FEATURE_FPU)		||
+		    __mismatch_fpu_bit(X86_FEATURE_FXSR)	||
+		    __mismatch_fpu_bit(X86_FEATURE_XSAVE)) {
+			pr_err("FPU feature required by image "
+			       "is not supported on host.\n");
+			return -1;
+		} else
+			return 0;
+#undef __mismatch_fpu_bit
+	}
+
+	/*
+	 * FIXME We need to bring ability to run images with lower
+	 * features on more capable CPU.
+	 */
+
+	if (memcmp(img_x86_entry->capability, rt_cpu_info.x86_capability,
+		   sizeof(rt_cpu_info.x86_capability))) {
+			pr_err("CPU capabilites do not match run time\n");
+			return -1;
+	}
+
+	return 0;
+}
+
+int cpu_validate_image_cpuinfo(void)
+{
+	CpuinfoX86Entry *img_x86_entry;
+	CpuinfoEntry *img_cpu_info;
+	int fd, ret = -1;
+
+	fd = open_image(CR_FD_CPUINFO, O_RSTR | O_OPT);
+	if (fd < 0) {
+		if (fd == -ENOENT)
+			return 0;
+		return -1;
+	}
+
+	if (pb_read_one(fd, &img_cpu_info, PB_CPUINFO) < 0)
+		goto err;
+
+	if (img_cpu_info->n_x86_entry != 1) {
+		pr_err("No x86 related cpuinfo in image, "
+		       "corruption (n_x86_entry = %zi)\n",
+		       img_cpu_info->n_x86_entry);
+		goto err;
+	}
+
+	img_x86_entry = img_cpu_info->x86_entry[0];
+	if (img_x86_entry->vendor_id != CPUINFO_X86_ENTRY__VENDOR__INTEL &&
+	    img_x86_entry->vendor_id != CPUINFO_X86_ENTRY__VENDOR__AMD) {
+		pr_err("Unknown cpu vendor %d\n", img_x86_entry->vendor_id);
+		goto err;
+	}
+
+	if (img_x86_entry->n_capability != ARRAY_SIZE(rt_cpu_info.x86_capability)) {
+		pr_err("Image carries %u words while %u expected\n",
+		       (unsigned)img_x86_entry->n_capability,
+		       (unsigned)ARRAY_SIZE(rt_cpu_info.x86_capability));
+		return -1;
+	}
+
+	ret = cpu_validate_features(img_x86_entry);
+err:
+	close(fd);
+	return ret;
+}
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index db7ab5c6af0b..3ad4187fbd87 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -200,5 +200,7 @@ static inline unsigned int cpuid_edx(unsigned int op)
 
 extern bool cpu_has_feature(unsigned int feature);
 extern int cpu_init(void);
+extern int cpu_dump_cpuinfo(void);
+extern int cpu_validate_image_cpuinfo(void);
 
 #endif /* __CR_CPU_H__ */
diff --git a/cr-dump.c b/cr-dump.c
index d00c158d205e..1df1ba06aeab 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -1787,6 +1787,11 @@ int cr_dump_tasks(pid_t pid)
 	if (write_img_inventory())
 		goto err;
 
+	if (opts.cpu_cap & CPU_CAP_CPUINFO) {
+		if (cpu_dump_cpuinfo())
+			goto err;
+	}
+
 	if (connect_to_page_server())
 		goto err;
 
diff --git a/cr-restore.c b/cr-restore.c
index a903ab2bd1b5..cd108351ecd7 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -1857,6 +1857,9 @@ int cr_restore_tasks(void)
 	if (vdso_init())
 		goto err;
 
+	if (cpu_validate_image_cpuinfo())
+		goto err;
+
 	if (prepare_task_entries() < 0)
 		goto err;
 
diff --git a/include/cpu.h b/include/cpu.h
index aa3516b97f97..7dbe68f7735c 100644
--- a/include/cpu.h
+++ b/include/cpu.h
@@ -5,5 +5,7 @@
 
 extern bool cpu_has_feature(unsigned int feature);
 extern int cpu_init(void);
+extern int cpu_dump_cpuinfo(void);
+extern int cpu_validate_image_cpuinfo(void);
 
 #endif /* __CR_CPU_H__ */
-- 
1.9.3



More information about the CRIU mailing list