[CRIU] [PATCH 06/15] cpuinfo: x86 -- Add dump and validation
Pavel Emelyanov
xemul at parallels.com
Tue Sep 23 11:07:04 PDT 2014
On 09/19/2014 06:03 PM, Cyrill Gorcunov wrote:
> 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)
static
> +{
> + 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;
We already have some --cpu-cap fpu meaning. Do we need to check one here?
> +#undef __mismatch_fpu_bit
> + }
> +
> + return memcmp(img_x86_entry->features, cpu_features,
> + min(size, sizeof(cpu_features)));
memcmp?! I believe it's not correct. If the cpu has larger feature
mask than the one from the image, then validation should pass.
> +}
> +
> +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;
>
More information about the CRIU
mailing list