[CRIU] [PATCH 05/15] cpuinfo: x86 -- Rework cpuinfo parsing

Pavel Emelyanov xemul at parallels.com
Tue Sep 23 11:05:36 PDT 2014


On 09/19/2014 06:03 PM, Cyrill Gorcunov wrote:
> We need more data to handle not features only.
> 
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
>  arch/x86/cpu.c       | 200 ++++++++++++++++++++++++++++++++++++++++++++++++---
>  include/proc_parse.h |   2 +-
>  proc_parse.c         |  18 ++---
>  3 files changed, 199 insertions(+), 21 deletions(-)
> 
> diff --git a/arch/x86/cpu.c b/arch/x86/cpu.c
> index 2ea4e06bccc0..1ff8de1831ad 100644
> --- a/arch/x86/cpu.c
> +++ b/arch/x86/cpu.c
> @@ -28,6 +28,7 @@
>  static CpuinfoEntry cpu_info = CPUINFO_ENTRY__INIT;
>  static CpuinfoX86Entry cpu_x86_info = CPUINFO_X86_ENTRY__INIT;
>  static CpuinfoX86Entry *cpu_x86_info_ptr = &cpu_x86_info;
> +static char cpu_model_name[256];
>  
>  const char * const x86_cap_flags[NCAPINTS_BITS] = {
>  	[X86_FEATURE_FPU]		= "fpu",
> @@ -102,14 +103,197 @@ bool cpu_has_feature(unsigned int feature)
>  	return false;
>  }
>  
> -static int proc_cpuinfo_match(char *tok)
> +static int proc_cpuinfo_handler(char *line)
>  {
> -	if (!strcmp(tok, x86_cap_flags[X86_FEATURE_FXSR]))
> -		cpu_set_feature(X86_FEATURE_FXSR);
> -	else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_XSAVE]))
> -		cpu_set_feature(X86_FEATURE_XSAVE);
> -	else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_FPU]))
> -		cpu_set_feature(X86_FEATURE_FPU);
> +	/*
> +	 * Typical structure is (per-core/ht)
> +	 *
> +	 *	processor	: 3
> +	 *	vendor_id	: GenuineIntel
> +	 *	cpu family	: 6
> +	 *	model		: 42
> +	 *	model name	: Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz
> +	 *	stepping	: 7
> +	 *	microcode	: 0x29
> +	 *	cpu MHz		: 800.195
> +	 *	cache size	: 3072 KB
> +	 *	physical id	: 0
> +	 *	siblings	: 4
> +	 *	core id		: 1
> +	 *	cpu cores	: 2
> +	 *	apicid		: 3
> +	 *	initial apicid	: 3
> +	 *	fpu		: yes
> +	 *	fpu_exception	: yes
> +	 *	cpuid level	: 13
> +	 *	wp		: yes
> +	 *	flags		: fpu vme de pse tsc msr pae mce cx8 apic ...
> +	 *	bogomips	: 4984.07
> +	 *	clflush size	: 64
> +	 *	cache_alignment	: 64
> +	 *	address sizes	: 36 bits physical, 48 bits virtual
> +	 *	power management:
> +	 *
> +	 * Note we assume that all CPUs in the system are same
> +	 * class and parse only first one. Still if needed we may
> +	 * parse every core entry increasing the numbers of entries
> +	 * in protobuf image. For a while it's not needed so lets
> +	 * stick with simple.
> +	 */
> +
> +	if (!strncmp(line, "vendor_id\t: ", 12)) {
> +		if (!strncmp(&line[12], "GenuineIntel", 12)) {
> +			cpu_x86_info.vendor_id = CPUINFO_X86_ENTRY__VENDOR__INTEL;
> +		} else if (!strncmp(&line[12], "AuthenticAMD", 12)) {
> +			cpu_x86_info.vendor_id = CPUINFO_X86_ENTRY__VENDOR__AMD;
> +		} else {
> +			pr_err("Unsupported CPU vendor `%s'\n", &line[12]);
> +			return -1;
> +		}
> +	} else if (!strncmp(line, "cpu family\t: ", 13)) {
> +		cpu_x86_info.cpu_family = atoi(&line[13]);
> +	} else if (!strncmp(line, "model\t\t: ", 9)) {
> +		cpu_x86_info.model = atoi(&line[9]);
> +	} else if (!strncmp(line, "model name\t: ", 13)) {
> +		strncpy(cpu_model_name, &line[13], min(sizeof(cpu_model_name),
> +						       strlen(&line[13]) - 1));
> +		cpu_x86_info.model_name = cpu_model_name;
> +	} else if (!strncmp(line, "stepping\t: ", 11)) {
> +		cpu_x86_info.has_stepping = true;
> +		cpu_x86_info.stepping = atoi(&line[11]);
> +	} else if (!strncmp(line, "physical id\t: ", 14)) {
> +		cpu_x86_info.has_physical_id = true;
> +		cpu_x86_info.physical_id = atoi(&line[14]);
> +	} else if (!strncmp(line, "siblings\t: ", 11)) {
> +		cpu_x86_info.has_siblings = true;
> +		cpu_x86_info.siblings = atoi(&line[11]);
> +	} else if (!strncmp(line, "core id\t\t: ", 11)) {
> +		cpu_x86_info.has_core_id = true;
> +		cpu_x86_info.core_id = atoi(&line[11]);
> +	} else if (!strncmp(line, "cpu cores\t: ", 12)) {
> +		cpu_x86_info.has_cpu_cores = true;
> +		cpu_x86_info.cpu_cores = atoi(&line[12]);
> +	} else if (!strncmp(line, "flags\t\t:", 8)) {
> +		char *tok;
> +
> +		for (tok = strtok(line, " \t\n"); tok;
> +		     tok = strtok(NULL, " \t\n")) {
> +			if (!strcmp(tok, x86_cap_flags[X86_FEATURE_FPU]))
> +				cpu_set_feature(X86_FEATURE_FPU);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_CX8]))
> +				cpu_set_feature(X86_FEATURE_CX8);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_CMOV]))
> +				cpu_set_feature(X86_FEATURE_CMOV);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_CLFLUSH]))
> +				cpu_set_feature(X86_FEATURE_CLFLUSH);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_MMX]))
> +				cpu_set_feature(X86_FEATURE_MMX);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_FXSR]))
> +				cpu_set_feature(X86_FEATURE_FXSR);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_XMM]))
> +				cpu_set_feature(X86_FEATURE_XMM);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_XMM2]))
> +				cpu_set_feature(X86_FEATURE_XMM2);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_SYSCALL]))
> +				cpu_set_feature(X86_FEATURE_SYSCALL);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_MMXEXT]))
> +				cpu_set_feature(X86_FEATURE_MMXEXT);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_RDTSCP]))
> +				cpu_set_feature(X86_FEATURE_RDTSCP);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_3DNOWEXT]))
> +				cpu_set_feature(X86_FEATURE_3DNOWEXT);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_3DNOW]))
> +				cpu_set_feature(X86_FEATURE_3DNOW);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_REP_GOOD]))
> +				cpu_set_feature(X86_FEATURE_REP_GOOD);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_NOPL]))
> +				cpu_set_feature(X86_FEATURE_NOPL);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_XMM3]))
> +				cpu_set_feature(X86_FEATURE_XMM3);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_PCLMULQDQ]))
> +				cpu_set_feature(X86_FEATURE_PCLMULQDQ);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_MWAIT]))
> +				cpu_set_feature(X86_FEATURE_MWAIT);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_TM2]))
> +				cpu_set_feature(X86_FEATURE_TM2);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_SSSE3]))
> +				cpu_set_feature(X86_FEATURE_SSSE3);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_FMA]))
> +				cpu_set_feature(X86_FEATURE_FMA);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_CX16]))
> +				cpu_set_feature(X86_FEATURE_CX16);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_XMM4_1]))
> +				cpu_set_feature(X86_FEATURE_XMM4_1);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_XMM4_2]))
> +				cpu_set_feature(X86_FEATURE_XMM4_2);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_MOVBE]))
> +				cpu_set_feature(X86_FEATURE_MOVBE);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_POPCNT]))
> +				cpu_set_feature(X86_FEATURE_POPCNT);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_AES]))
> +				cpu_set_feature(X86_FEATURE_AES);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_XSAVE]))
> +				cpu_set_feature(X86_FEATURE_XSAVE);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_AVX]))
> +				cpu_set_feature(X86_FEATURE_AVX);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_F16C]))
> +				cpu_set_feature(X86_FEATURE_F16C);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_RDRAND]))
> +				cpu_set_feature(X86_FEATURE_RDRAND);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_ABM]))
> +				cpu_set_feature(X86_FEATURE_ABM);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_SSE4A]))
> +				cpu_set_feature(X86_FEATURE_SSE4A);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_MISALIGNSSE]))
> +				cpu_set_feature(X86_FEATURE_MISALIGNSSE);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_3DNOWPREFETCH]))
> +				cpu_set_feature(X86_FEATURE_3DNOWPREFETCH);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_XOP]))
> +				cpu_set_feature(X86_FEATURE_XOP);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_FMA4]))
> +				cpu_set_feature(X86_FEATURE_FMA4);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_TBM]))
> +				cpu_set_feature(X86_FEATURE_TBM);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_XSAVEOPT]))
> +				cpu_set_feature(X86_FEATURE_XSAVEOPT);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_BMI1]))
> +				cpu_set_feature(X86_FEATURE_BMI1);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_HLE]))
> +				cpu_set_feature(X86_FEATURE_HLE);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_AVX2]))
> +				cpu_set_feature(X86_FEATURE_AVX2);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_BMI2]))
> +				cpu_set_feature(X86_FEATURE_BMI2);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_ERMS]))
> +				cpu_set_feature(X86_FEATURE_ERMS);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_INVPCID]))
> +				cpu_set_feature(X86_FEATURE_INVPCID);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_RTM]))
> +				cpu_set_feature(X86_FEATURE_RTM);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_MPX]))
> +				cpu_set_feature(X86_FEATURE_MPX);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_AVX512F]))
> +				cpu_set_feature(X86_FEATURE_AVX512F);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_RDSEED]))
> +				cpu_set_feature(X86_FEATURE_RDSEED);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_ADX]))
> +				cpu_set_feature(X86_FEATURE_ADX);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_CLFLUSHOPT]))
> +				cpu_set_feature(X86_FEATURE_CLFLUSHOPT);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_AVX512PF]))
> +				cpu_set_feature(X86_FEATURE_AVX512PF);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_AVX512ER]))
> +				cpu_set_feature(X86_FEATURE_AVX512ER);
> +			else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_AVX512CD]))
> +				cpu_set_feature(X86_FEATURE_AVX512CD);

OMG. Is there some better way of getting this mask? Via sysfs maybe?

> +		}
> +
> +		/*
> +		 * CPU features flags are last in the output!
> +		 */
> +		return 1;
> +	}
> +
>  	return 0;
>  }
>  
> @@ -129,7 +313,7 @@ int cpu_init(void)
>  {
>  	cpu_init_protobuf();
>  
> -	if (parse_cpuinfo_features(proc_cpuinfo_match))
> +	if (parse_cpuinfo(proc_cpuinfo_handler))
>  		return -1;
>  
>  	BUILD_BUG_ON(sizeof(struct xsave_struct) != XSAVE_SIZE);
> diff --git a/include/proc_parse.h b/include/proc_parse.h
> index 7fade0669426..4707fee00ee8 100644
> --- a/include/proc_parse.h
> +++ b/include/proc_parse.h
> @@ -210,7 +210,7 @@ extern int parse_fdinfo(int fd, int type,
>  		int (*cb)(union fdinfo_entries *e, void *arg), void *arg);
>  extern int parse_fdinfo_pid(int pid, int fd, int type,
>  		int (*cb)(union fdinfo_entries *e, void *arg), void *arg);
> -extern int parse_cpuinfo_features(int (*handler)(char *tok));
> +extern int parse_cpuinfo(int (*handler)(char *line));
>  extern int parse_file_locks(void);
>  
>  struct pid;
> diff --git a/proc_parse.c b/proc_parse.c
> index 9aa17d4ec483..a06034180894 100644
> --- a/proc_parse.c
> +++ b/proc_parse.c
> @@ -43,9 +43,10 @@ static char *buf = __buf.buf;
>  
>  #define BUF_SIZE sizeof(__buf.buf)
>  
> -int parse_cpuinfo_features(int (*handler)(char *tok))
> +int parse_cpuinfo(int (*handler)(char *line))
>  {
>  	FILE *cpuinfo;
> +	int ret = -1;
>  
>  	cpuinfo = fopen_proc(PROC_GEN, "cpuinfo");
>  	if (!cpuinfo) {
> @@ -54,20 +55,13 @@ int parse_cpuinfo_features(int (*handler)(char *tok))
>  	}
>  
>  	while (fgets(buf, BUF_SIZE, cpuinfo)) {
> -		char *tok;
> -
> -		if (strncmp(buf, "flags\t\t:", 8))
> -			continue;
> -
> -		for (tok = strtok(buf, " \t\n"); tok;
> -		     tok = strtok(NULL, " \t\n")) {
> -			if (handler(tok) < 0)
> -				break;
> -		}
> +		ret = handler(buf);
> +		if (ret)
> +			break;
>  	}
>  
>  	fclose(cpuinfo);
> -	return 0;
> +	return ret == 1 ? 0 : ret;
>  }
>  
>  /* check the @line starts with "%lx-%lx" format */
> 



More information about the CRIU mailing list