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:
committed by
Pavel Emelyanov
parent
bbc38f3dac
commit
fd07bc7791
@@ -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
|
||||||
|
122
arch/x86/cpu.c
122
arch/x86/cpu.c
@@ -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;
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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"
|
||||||
|
@@ -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 {
|
||||||
|
Reference in New Issue
Block a user