[CRIU] [PATCH 06/15] cpuinfo: x86 -- Add dump and validation
Cyrill Gorcunov
gorcunov at openvz.org
Fri Sep 19 07:03:08 PDT 2014
Make sure the processor we're restoring on
is not less capable in features.
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
arch/aarch64/cpu.c | 10 +++++
arch/arm/cpu.c | 10 +++++
arch/x86/cpu.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++
cr-dump.c | 5 +++
cr-restore.c | 3 ++
include/cpu.h | 2 +
include/cr_options.h | 1 +
7 files changed, 144 insertions(+)
diff --git a/arch/aarch64/cpu.c b/arch/aarch64/cpu.c
index 6f4b5284a377..f13d635c2c5a 100644
--- a/arch/aarch64/cpu.c
+++ b/arch/aarch64/cpu.c
@@ -16,3 +16,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 6f4b5284a377..f13d635c2c5a 100644
--- a/arch/arm/cpu.c
+++ b/arch/arm/cpu.c
@@ -16,3 +16,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 1ff8de1831ad..d43fdbbeac04 100644
--- a/arch/x86/cpu.c
+++ b/arch/x86/cpu.c
@@ -13,6 +13,7 @@
#include "compiler.h"
+#include "cr_options.h"
#include "proc_parse.h"
#include "util.h"
#include "log.h"
@@ -337,3 +338,115 @@ int cpu_init(void)
return 0;
}
+
+int cpu_dump_cpuinfo(void)
+{
+ int fd;
+
+ fd = open_image(CR_FD_CPUINFO, O_DUMP);
+ if (fd < 0)
+ return -1;
+
+ if (pb_write_one(fd, &cpu_info, PB_CPUINFO) < 0)
+ return -1;
+
+ close(fd);
+ return 0;
+}
+
+int cpu_validate_features(CpuinfoX86Entry *img_x86_entry)
+{
+ size_t size;
+
+ /*
+ * A user knows what he is doing and disabled
+ * capabilities check.
+ */
+ if (opts.cpu_cap == CPU_CAP_NONE)
+ return 0;
+
+ size = img_x86_entry->n_features * sizeof(img_x86_entry->features[0]);
+ if (size > sizeof(cpu_features)) {
+ /*
+ * Image carries more bits that we know of.
+ * Simply reject, we can't guarantee anything
+ * in such case.
+ */
+ pr_err("Size of features in image exceed "
+ "one provided by run time CPU (%d:%d)\n",
+ (unsigned)size, (unsigned)sizeof(cpu_features));
+ return -1;
+ }
+
+ if (opts.cpu_cap & CPU_CAP_FPU) {
+ /*
+ * Check if runtime CPU has all FPU related
+ * bits non less capable.
+ */
+
+ /*
+ * FIXME Make sure the image @features
+ * is big enough to keep FPU bits.
+ */
+
+#define __mismatch_fpu_bit(__bit) \
+ (test_bit(__bit, (void *)img_x86_entry->features) && \
+ !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 false;
+ } else
+ return 0;
+#undef __mismatch_fpu_bit
+ }
+
+ return memcmp(img_x86_entry->features, cpu_features,
+ min(size, sizeof(cpu_features)));
+}
+
+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_features != protobuf_features_words) {
+ pr_err("Image carries only %u words while %u expected\n",
+ (unsigned)img_x86_entry->n_features,
+ (unsigned)protobuf_features_words);
+ return -1;
+ }
+
+ ret = cpu_validate_features(img_x86_entry);
+err:
+ close(fd);
+ return ret;
+}
diff --git a/cr-dump.c b/cr-dump.c
index 91336e82407f..50f03f14e9de 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -1781,6 +1781,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 f0cab1b4a613..c439f20ad2b8 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -1830,6 +1830,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 08220cfa7616..c3e3cc6edc2e 100644
--- a/include/cpu.h
+++ b/include/cpu.h
@@ -6,5 +6,7 @@
extern void cpu_set_feature(unsigned int feature);
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/include/cr_options.h b/include/cr_options.h
index 5a7edd9263db..617894bac91c 100644
--- a/include/cr_options.h
+++ b/include/cr_options.h
@@ -10,6 +10,7 @@
*/
#define CPU_CAP_FPU (1u)
#define CPU_CAP_ALL (-1u)
+#define CPU_CAP_NONE (0u)
struct cg_root_opt {
struct list_head node;
--
1.9.3
More information about the CRIU
mailing list