2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-31 06:15:24 +00:00

cpu: Add 'ins' mode to --cpu-cap option

In this mode we test if target cpu has all features present
in image file but do not require bit to bit match: target cpu
may be a new one with more features present.

Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
Cyrill Gorcunov
2014-12-17 16:48:00 +03:00
committed by Pavel Emelyanov
parent bbc38f3dac
commit fd07bc7791
6 changed files with 130 additions and 9 deletions

View File

@@ -101,6 +101,12 @@ OPTIONS
procceed. This is *default* mode if *--cpu-cap* is not present procceed. This is *default* mode if *--cpu-cap* is not present
in command line. in command line.
- 'ins' Only require CPU compatibility on instructions level. On *dump*
all capabilities are writen into image file and on *restore*
only subset related to CPU instructions tested if target CPU
supports them. Unlike 'cpu' mode the target CPU may have more
features than ones present in image file.
- 'none'. Ignore capabilities. Most dangerous mode. The behaviour is - 'none'. Ignore capabilities. Most dangerous mode. The behaviour is
implementation dependent. Try to not use it until really implementation dependent. Try to not use it until really
required. One possible need of using this option is when required. One possible need of using this option is when

View File

@@ -261,6 +261,112 @@ int cpu_dump_cpuinfo(void)
return 0; return 0;
} }
#define __ins_bit(__l, __v) (1u << ((__v) - 32u * (__l)))
static u32 x86_ins_capability_mask[NCAPINTS] = {
[0] =
__ins_bit(0, X86_FEATURE_FPU) |
__ins_bit(0, X86_FEATURE_TSC) |
__ins_bit(0, X86_FEATURE_CX8) |
__ins_bit(0, X86_FEATURE_SEP) |
__ins_bit(0, X86_FEATURE_CMOV) |
__ins_bit(0, X86_FEATURE_CLFLUSH) |
__ins_bit(0, X86_FEATURE_MMX) |
__ins_bit(0, X86_FEATURE_FXSR) |
__ins_bit(0, X86_FEATURE_XMM) |
__ins_bit(0, X86_FEATURE_XMM2),
[1] =
__ins_bit(1, X86_FEATURE_SYSCALL) |
__ins_bit(1, X86_FEATURE_MMXEXT) |
__ins_bit(1, X86_FEATURE_RDTSCP) |
__ins_bit(1, X86_FEATURE_3DNOWEXT) |
__ins_bit(1, X86_FEATURE_3DNOW),
[3] =
__ins_bit(3, X86_FEATURE_REP_GOOD) |
__ins_bit(3, X86_FEATURE_NOPL),
[4] =
__ins_bit(4, X86_FEATURE_XMM3) |
__ins_bit(4, X86_FEATURE_PCLMULQDQ) |
__ins_bit(4, X86_FEATURE_MWAIT) |
__ins_bit(4, X86_FEATURE_SSSE3) |
__ins_bit(4, X86_FEATURE_CX16) |
__ins_bit(4, X86_FEATURE_XMM4_1) |
__ins_bit(4, X86_FEATURE_XMM4_2) |
__ins_bit(4, X86_FEATURE_MOVBE) |
__ins_bit(4, X86_FEATURE_POPCNT) |
__ins_bit(4, X86_FEATURE_AES) |
__ins_bit(4, X86_FEATURE_XSAVE) |
__ins_bit(4, X86_FEATURE_OSXSAVE) |
__ins_bit(4, X86_FEATURE_AVX) |
__ins_bit(4, X86_FEATURE_F16C) |
__ins_bit(4, X86_FEATURE_RDRAND),
[6] =
__ins_bit(6, X86_FEATURE_ABM) |
__ins_bit(6, X86_FEATURE_SSE4A) |
__ins_bit(6, X86_FEATURE_MISALIGNSSE) |
__ins_bit(6, X86_FEATURE_3DNOWPREFETCH) |
__ins_bit(6, X86_FEATURE_XOP) |
__ins_bit(6, X86_FEATURE_FMA4) |
__ins_bit(6, X86_FEATURE_TBM),
[9] =
__ins_bit(9, X86_FEATURE_FSGSBASE) |
__ins_bit(9, X86_FEATURE_BMI1) |
__ins_bit(9, X86_FEATURE_HLE) |
__ins_bit(9, X86_FEATURE_AVX2) |
__ins_bit(9, X86_FEATURE_BMI2) |
__ins_bit(9, X86_FEATURE_ERMS) |
__ins_bit(9, X86_FEATURE_RTM) |
__ins_bit(9, X86_FEATURE_MPX) |
__ins_bit(9, X86_FEATURE_AVX512F) |
__ins_bit(9, X86_FEATURE_AVX512DQ) |
__ins_bit(9, X86_FEATURE_RDSEED) |
__ins_bit(9, X86_FEATURE_ADX) |
__ins_bit(9, X86_FEATURE_CLFLUSHOPT) |
__ins_bit(9, X86_FEATURE_AVX512PF) |
__ins_bit(9, X86_FEATURE_AVX512ER) |
__ins_bit(9, X86_FEATURE_AVX512CD) |
__ins_bit(9, X86_FEATURE_SHA) |
__ins_bit(9, X86_FEATURE_AVX512BW) |
__ins_bit(9, X86_FEATURE_AVXVL),
[10] =
__ins_bit(10, X86_FEATURE_XSAVEOPT) |
__ins_bit(10, X86_FEATURE_XSAVEC) |
__ins_bit(10, X86_FEATURE_XGETBV1) |
__ins_bit(10, X86_FEATURE_XSAVES),
[11] =
__ins_bit(11, X86_FEATURE_PREFETCHWT1),
};
#undef __ins_bit
static int cpu_validate_ins_features(CpuinfoX86Entry *img_x86_entry)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(rt_cpu_info.x86_capability); i++) {
u32 s = img_x86_entry->capability[i] & x86_ins_capability_mask[i];
u32 d = rt_cpu_info.x86_capability[i] & x86_ins_capability_mask[i];
/*
* Destination might be more feature rich
* but not the reverse.
*/
if (s & ~d) {
pr_err("CPU instruction capabilities do not match run time\n");
return -1;
}
}
return 0;
}
static int cpu_validate_features(CpuinfoX86Entry *img_x86_entry) static int cpu_validate_features(CpuinfoX86Entry *img_x86_entry)
{ {
if (img_x86_entry->n_capability != ARRAY_SIZE(rt_cpu_info.x86_capability)) { if (img_x86_entry->n_capability != ARRAY_SIZE(rt_cpu_info.x86_capability)) {
@@ -298,10 +404,14 @@ static int cpu_validate_features(CpuinfoX86Entry *img_x86_entry)
} }
/* /*
* FIXME We need to bring ability to run images with lower * Capability on instructions level only.
* features on more capable CPU.
*/ */
if (opts.cpu_cap == CPU_CAP_INS)
return cpu_validate_ins_features(img_x86_entry);
/*
* Strict capability mode. Everything must match.
*/
if (memcmp(img_x86_entry->capability, rt_cpu_info.x86_capability, if (memcmp(img_x86_entry->capability, rt_cpu_info.x86_capability,
sizeof(rt_cpu_info.x86_capability))) { sizeof(rt_cpu_info.x86_capability))) {
pr_err("CPU capabilites do not match run time\n"); pr_err("CPU capabilites do not match run time\n");
@@ -367,10 +477,12 @@ int cpuinfo_check(void)
return 1; return 1;
/* /*
* Force to check all caps because its been * Force to check all caps if empty passed,
* called as a special command from options. * still allow to check instructions only
* and etc.
*/ */
opts.cpu_cap = CPU_CAP_ALL; if (!opts.cpu_cap)
opts.cpu_cap = CPU_CAP_ALL;
if (cpu_validate_cpuinfo()) if (cpu_validate_cpuinfo())
return 1; return 1;

View File

@@ -1832,7 +1832,7 @@ int cr_dump_tasks(pid_t pid)
if (write_img_inventory()) if (write_img_inventory())
goto err; goto err;
if (opts.cpu_cap & CPU_CAP_CPU) { if (opts.cpu_cap & (CPU_CAP_CPU | CPU_CAP_INS)) {
if (cpu_dump_cpuinfo()) if (cpu_dump_cpuinfo())
goto err; goto err;
} }

View File

@@ -1894,7 +1894,7 @@ int cr_restore_tasks(void)
if (vdso_init()) if (vdso_init())
goto err; goto err;
if (opts.cpu_cap & CPU_CAP_CPU) { if (opts.cpu_cap & (CPU_CAP_INS | CPU_CAP_CPU)) {
if (cpu_validate_cpuinfo()) if (cpu_validate_cpuinfo())
goto err; goto err;
} }

View File

@@ -122,6 +122,8 @@ static int parse_cpu_cap(struct cr_options *opts, const char *optarg)
____cpu_set_cap(opts, CPU_CAP_NONE, inverse); ____cpu_set_cap(opts, CPU_CAP_NONE, inverse);
else if (!strncmp(optarg, "cpu", 3)) else if (!strncmp(optarg, "cpu", 3))
____cpu_set_cap(opts, CPU_CAP_CPU, inverse); ____cpu_set_cap(opts, CPU_CAP_CPU, inverse);
else if (!strncmp(optarg, "ins", 3))
____cpu_set_cap(opts, CPU_CAP_INS, inverse);
else else
goto Esyntax; goto Esyntax;
} }
@@ -595,7 +597,7 @@ usage:
" -W|--work-dir DIR directory to cd and write logs/pidfiles/stats to\n" " -W|--work-dir DIR directory to cd and write logs/pidfiles/stats to\n"
" (if not specified, value of --images-dir is used)\n" " (if not specified, value of --images-dir is used)\n"
" --cpu-cap [CAP] require certain cpu capability. CAP: may be one of:\n" " --cpu-cap [CAP] require certain cpu capability. CAP: may be one of:\n"
" 'cpu','fpu','all','none'. To disable capability, prefix it with '^'.\n" " 'cpu','fpu','all','ins','none'. To disable capability, prefix it with '^'.\n"
" --exec-cmd execute the command specified after '--' on successful\n" " --exec-cmd execute the command specified after '--' on successful\n"
" restore making it the parent of the restored process\n" " restore making it the parent of the restored process\n"
"\n" "\n"

View File

@@ -11,7 +11,8 @@
#define CPU_CAP_NONE (0u) #define CPU_CAP_NONE (0u)
#define CPU_CAP_ALL (-1u) #define CPU_CAP_ALL (-1u)
#define CPU_CAP_FPU (1u) /* Only FPU capability required */ #define CPU_CAP_FPU (1u) /* Only FPU capability required */
#define CPU_CAP_CPU (2u) /* CPU capability required */ #define CPU_CAP_CPU (2u) /* Strict CPU capability required */
#define CPU_CAP_INS (4u) /* Instructions CPU capatibility */
#define CPU_CAP_DEFAULT (CPU_CAP_FPU) #define CPU_CAP_DEFAULT (CPU_CAP_FPU)
struct cg_root_opt { struct cg_root_opt {