Commit fd07bc77 authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Pavel Emelyanov

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: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent bbc38f3d
...@@ -101,6 +101,12 @@ OPTIONS ...@@ -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
......
...@@ -261,6 +261,112 @@ int cpu_dump_cpuinfo(void) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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: ...@@ -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 @@ ...@@ -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 {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment