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

cpu: Add code to fetch/test cpuinfo data

This patch add ability to test /proc/cpuinfo data
we're interested in at the moment.

The code provides the following functionality

 - cpu_init, to parse cpuinfo and check if the
   host cpu we're running on is suitable enough
   for FPU checkpoint/restore. If FPU present then
   there must be at least fxsave capability present

 - cpu_set_feature/cpu_has_feature helpers which
   provides to test certain bits and set them where
   needed (we need to set bits when parse cpuinfo)

Note, we reserve space for all cpuinfo bits known
by the kernel at moment, while use only three FPU
related bits for a while. This is done because we might
need to use or find out other features in future.

After all it's just 40 bytes of memory needed to keep
all possible bits.
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 666f4ebb
...@@ -117,6 +117,7 @@ OBJS += pstree.o ...@@ -117,6 +117,7 @@ OBJS += pstree.o
OBJS += protobuf.o OBJS += protobuf.o
OBJS += tty.o OBJS += tty.o
OBJS += cr-exec.o OBJS += cr-exec.o
OBJS += cpu.o
DEPS := $(patsubst %.o,%.d,$(OBJS)) DEPS := $(patsubst %.o,%.d,$(OBJS))
......
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include "compiler.h"
#include "types.h"
#include "log.h"
#include "util.h"
#include "bitops.h"
#include "proc_parse.h"
#include "fpu.h"
#include "cpu.h"
#undef LOG_PREFIX
#define LOG_PREFIX "cpu: "
const char * const x86_cap_flags[NCAPINTS_BITS] = {
[X86_FEATURE_FPU] = "fpu",
[X86_FEATURE_FXSR] = "fxsr",
[X86_FEATURE_XSAVE] = "xsave",
};
static DECLARE_BITMAP(cpu_features, NCAPINTS_BITS);
#define cpu_has(bit) test_bit(bit, cpu_features)
void cpu_set_feature(unsigned int feature)
{
if (likely(feature < NCAPINTS_BITS))
set_bit(feature, cpu_features);
}
bool cpu_has_feature(unsigned int feature)
{
if (likely(feature < NCAPINTS_BITS))
return cpu_has(feature);
return false;
}
int cpu_init(void)
{
if (parse_cpuinfo_features())
return -1;
BUILD_BUG_ON(sizeof(struct xsave_struct) != XSAVE_SIZE);
BUILD_BUG_ON(sizeof(struct i387_fxsave_struct) != FXSAVE_SIZE);
/*
* Make sure that at least FPU is onboard
* and fxsave is supported.
*/
if (cpu_has(X86_FEATURE_FPU)) {
if (!cpu_has(X86_FEATURE_FXSR)) {
pr_err("missing support fxsave/restore insns\n");
return -1;
}
}
pr_debug("fpu:%d fxsr:%d xsave:%d\n",
!!cpu_has(X86_FEATURE_FPU),
!!cpu_has(X86_FEATURE_FXSR),
!!cpu_has(X86_FEATURE_XSAVE));
return 0;
}
#ifndef CPU_H__
#define CPU_H__
#include "types.h"
/*
* Adopted from linux kernel.
*/
#define NCAPINTS (10) /* N 32-bit words worth of info */
#define NCAPINTS_BITS (NCAPINTS * 32)
#define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */
#define X86_FEATURE_FXSR (0*32+24) /* FXSAVE/FXRSTOR, CR4.OSFXSR */
#define X86_FEATURE_XSAVE (4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
extern const char * const x86_cap_flags[NCAPINTS_BITS];
extern void cpu_set_feature(unsigned int feature);
extern bool cpu_has_feature(unsigned int feature);
extern int cpu_init(void);
#endif /* CPU_H__ */
...@@ -138,5 +138,6 @@ union fdinfo_entries { ...@@ -138,5 +138,6 @@ union fdinfo_entries {
extern int parse_fdinfo(int fd, int type, extern int parse_fdinfo(int fd, int type,
int (*cb)(union fdinfo_entries *e, void *arg), void *arg); int (*cb)(union fdinfo_entries *e, void *arg), void *arg);
extern int parse_cpuinfo_features(void);
#endif /* PROC_PARSE_H__ */ #endif /* PROC_PARSE_H__ */
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "util.h" #include "util.h"
#include "crtools.h" #include "crtools.h"
#include "mount.h" #include "mount.h"
#include "cpu.h"
#include "proc_parse.h" #include "proc_parse.h"
#include "protobuf.h" #include "protobuf.h"
...@@ -31,6 +32,37 @@ static char *buf = __buf.buf; ...@@ -31,6 +32,37 @@ static char *buf = __buf.buf;
#define BUF_SIZE sizeof(__buf.buf) #define BUF_SIZE sizeof(__buf.buf)
int parse_cpuinfo_features(void)
{
FILE *cpuinfo;
cpuinfo = fopen("/proc/cpuinfo", "r");
if (!cpuinfo) {
pr_perror("Can't open cpuinfo file");
return -1;
}
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 (!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);
}
}
fclose(cpuinfo);
return 0;
}
/* check the @line starts with "%lx-%lx" format */ /* check the @line starts with "%lx-%lx" format */
static bool is_vma_range_fmt(char *line) static bool is_vma_range_fmt(char *line)
{ {
......
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