mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-22 09:58:09 +00:00
compel: Move cpu interface to compel
We will need it when parasite engine will be creating signal frames. Export appropriate headers and use it in CRIU by linking with libcompel.a. Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This commit is contained in:
parent
1a30731b1f
commit
aabb45bece
4
Makefile
4
Makefile
@ -228,9 +228,9 @@ $(SOCCR_A): |soccr/built-in.o
|
|||||||
#
|
#
|
||||||
# But note that we're already included
|
# But note that we're already included
|
||||||
# the nmk so we can reuse it there.
|
# the nmk so we can reuse it there.
|
||||||
criu/%: images/built-in.o compel/plugins/std.built-in.o compel/compel-host $(VERSION_HEADER) .FORCE
|
criu/%: images/built-in.o compel/plugins/std.built-in.o compel/libcompel.a compel/compel-host $(VERSION_HEADER) .FORCE
|
||||||
$(Q) $(MAKE) $(build)=criu $@
|
$(Q) $(MAKE) $(build)=criu $@
|
||||||
criu: images/built-in.o compel/plugins/std.built-in.o compel/compel-host $(SOCCR_A) $(VERSION_HEADER)
|
criu: images/built-in.o compel/plugins/std.built-in.o compel/libcompel.a compel/compel-host $(SOCCR_A) $(VERSION_HEADER)
|
||||||
$(Q) $(MAKE) $(build)=criu all
|
$(Q) $(MAKE) $(build)=criu all
|
||||||
.PHONY: criu
|
.PHONY: criu
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ compel-uapi-links += $(SRC_DIR)/compel/include/asm
|
|||||||
compel-deps += $(compel-uapi-links)
|
compel-deps += $(compel-uapi-links)
|
||||||
compel-deps += $(COMPEL_VERSION_HEADER)
|
compel-deps += $(COMPEL_VERSION_HEADER)
|
||||||
compel-deps += $(CONFIG_HEADER)
|
compel-deps += $(CONFIG_HEADER)
|
||||||
|
compel-deps += include/common/asm
|
||||||
|
|
||||||
#
|
#
|
||||||
# Compel itself.
|
# Compel itself.
|
||||||
|
@ -22,6 +22,8 @@ host-lib-y += src/lib/handle-elf.o
|
|||||||
lib-y += src/lib/log.o
|
lib-y += src/lib/log.o
|
||||||
host-lib-y += src/lib/log.o
|
host-lib-y += src/lib/log.o
|
||||||
|
|
||||||
|
lib-y += arch/$(ARCH)/src/lib/cpu.o
|
||||||
|
|
||||||
ifeq ($(ARCH),x86)
|
ifeq ($(ARCH),x86)
|
||||||
lib-y += src/lib/handle-elf-32.o
|
lib-y += src/lib/handle-elf-32.o
|
||||||
host-lib-y += src/lib/handle-elf-32.o
|
host-lib-y += src/lib/handle-elf-32.o
|
||||||
|
28
compel/arch/aarch64/src/lib/cpu.c
Normal file
28
compel/arch/aarch64/src/lib/cpu.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "uapi/compel/cpu.h"
|
||||||
|
|
||||||
|
#include "common/bitops.h"
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#undef LOG_PREFIX
|
||||||
|
#define LOG_PREFIX "cpu: "
|
||||||
|
|
||||||
|
static compel_cpuinfo_t rt_info;
|
||||||
|
static bool rt_info_done = false;
|
||||||
|
|
||||||
|
void compel_set_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { }
|
||||||
|
void compel_clear_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { }
|
||||||
|
int compel_test_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { return 0; }
|
||||||
|
int compel_cpuid(compel_cpuinfo_t *info) { return 0; }
|
||||||
|
|
||||||
|
bool cpu_has_feature(unsigned int feature)
|
||||||
|
{
|
||||||
|
if (!rt_info_done) {
|
||||||
|
compel_cpuid(&rt_info);
|
||||||
|
rt_info_done = true;
|
||||||
|
}
|
||||||
|
return compel_test_cpu_cap(&rt_info, feature);
|
||||||
|
}
|
6
compel/arch/aarch64/src/lib/include/uapi/asm/cpu.h
Normal file
6
compel/arch/aarch64/src/lib/include/uapi/asm/cpu.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef UAPI_COMPEL_ASM_CPU_H__
|
||||||
|
#define UAPI_COMPEL_ASM_CPU_H__
|
||||||
|
|
||||||
|
typedef struct { } compel_cpuinfo_t;
|
||||||
|
|
||||||
|
#endif /* UAPI_COMPEL_ASM_CPU_H__ */
|
@ -0,0 +1,4 @@
|
|||||||
|
#ifndef UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__
|
||||||
|
#define UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__
|
||||||
|
|
||||||
|
#endif /* UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__ */
|
28
compel/arch/arm/src/lib/cpu.c
Normal file
28
compel/arch/arm/src/lib/cpu.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "uapi/compel/cpu.h"
|
||||||
|
|
||||||
|
#include "common/bitops.h"
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#undef LOG_PREFIX
|
||||||
|
#define LOG_PREFIX "cpu: "
|
||||||
|
|
||||||
|
static compel_cpuinfo_t rt_info;
|
||||||
|
static bool rt_info_done = false;
|
||||||
|
|
||||||
|
void compel_set_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { }
|
||||||
|
void compel_clear_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { }
|
||||||
|
int compel_test_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { return 0; }
|
||||||
|
int compel_cpuid(compel_cpuinfo_t *info) { return 0; }
|
||||||
|
|
||||||
|
bool cpu_has_feature(unsigned int feature)
|
||||||
|
{
|
||||||
|
if (!rt_info_done) {
|
||||||
|
compel_cpuid(&rt_info);
|
||||||
|
rt_info_done = true;
|
||||||
|
}
|
||||||
|
return compel_test_cpu_cap(&rt_info, feature);
|
||||||
|
}
|
6
compel/arch/arm/src/lib/include/uapi/asm/cpu.h
Normal file
6
compel/arch/arm/src/lib/include/uapi/asm/cpu.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef UAPI_COMPEL_ASM_CPU_H__
|
||||||
|
#define UAPI_COMPEL_ASM_CPU_H__
|
||||||
|
|
||||||
|
typedef struct { } compel_cpuinfo_t;
|
||||||
|
|
||||||
|
#endif /* UAPI_COMPEL_ASM_CPU_H__ */
|
42
compel/arch/ppc64/src/lib/cpu.c
Normal file
42
compel/arch/ppc64/src/lib/cpu.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include <sys/auxv.h>
|
||||||
|
#include <asm/cputable.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "uapi/compel/cpu.h"
|
||||||
|
|
||||||
|
#include "common/bitops.h"
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#undef LOG_PREFIX
|
||||||
|
#define LOG_PREFIX "cpu: "
|
||||||
|
|
||||||
|
static compel_cpuinfo_t rt_info;
|
||||||
|
static bool rt_info_done = false;
|
||||||
|
|
||||||
|
void compel_set_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { }
|
||||||
|
void compel_clear_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { }
|
||||||
|
int compel_test_cpu_cap(compel_cpuinfo_t *info, unsigned int feature) { return 0; }
|
||||||
|
|
||||||
|
int compel_cpuid(compel_cpuinfo_t *info)
|
||||||
|
{
|
||||||
|
info->hwcap[0] = getauxval(AT_HWCAP);
|
||||||
|
info->hwcap[1] = getauxval(AT_HWCAP2);
|
||||||
|
|
||||||
|
if (!info->hwcap[0] || !info->hwcap[1]) {
|
||||||
|
pr_err("Can't read the hardware capabilities");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cpu_has_feature(unsigned int feature)
|
||||||
|
{
|
||||||
|
if (!rt_info_done) {
|
||||||
|
compel_cpuid(&rt_info);
|
||||||
|
rt_info_done = true;
|
||||||
|
}
|
||||||
|
return compel_test_cpu_cap(&rt_info, feature);
|
||||||
|
}
|
10
compel/arch/ppc64/src/lib/include/uapi/asm/cpu.h
Normal file
10
compel/arch/ppc64/src/lib/include/uapi/asm/cpu.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef UAPI_COMPEL_ASM_CPU_H__
|
||||||
|
#define UAPI_COMPEL_ASM_CPU_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t hwcap[2];
|
||||||
|
} compel_cpuinfo_t;
|
||||||
|
|
||||||
|
#endif /* UAPI_COMPEL_ASM_CPU_H__ */
|
@ -0,0 +1,4 @@
|
|||||||
|
#ifndef UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__
|
||||||
|
#define UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__
|
||||||
|
|
||||||
|
#endif /* UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__ */
|
4
compel/arch/ppc64/src/lib/include/uapi/asm/processor.h
Normal file
4
compel/arch/ppc64/src/lib/include/uapi/asm/processor.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#ifndef UAPI_COMPEL_ASM_PROCESSOR_H__
|
||||||
|
#define UAPI_COMPEL_ASM_PROCESSOR_H__
|
||||||
|
|
||||||
|
#endif /* UAPI_COMPEL_ASM_PROCESSOR_H__ */
|
189
compel/arch/x86/src/lib/cpu.c
Normal file
189
compel/arch/x86/src/lib/cpu.c
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "uapi/compel/cpu.h"
|
||||||
|
|
||||||
|
#include "common/bitops.h"
|
||||||
|
#include "common/compiler.h"
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#undef LOG_PREFIX
|
||||||
|
#define LOG_PREFIX "cpu: "
|
||||||
|
|
||||||
|
static compel_cpuinfo_t rt_info;
|
||||||
|
static bool rt_info_done = false;
|
||||||
|
|
||||||
|
void compel_set_cpu_cap(compel_cpuinfo_t *c, unsigned int feature)
|
||||||
|
{
|
||||||
|
if (likely(feature < NCAPINTS_BITS))
|
||||||
|
set_bit(feature, (unsigned long *)c->x86_capability);
|
||||||
|
}
|
||||||
|
|
||||||
|
void compel_clear_cpu_cap(compel_cpuinfo_t *c, unsigned int feature)
|
||||||
|
{
|
||||||
|
if (likely(feature < NCAPINTS_BITS))
|
||||||
|
clear_bit(feature, (unsigned long *)c->x86_capability);
|
||||||
|
}
|
||||||
|
|
||||||
|
int compel_test_cpu_cap(compel_cpuinfo_t *c, unsigned int feature)
|
||||||
|
{
|
||||||
|
if (likely(feature < NCAPINTS_BITS))
|
||||||
|
return test_bit(feature, (unsigned long *)c->x86_capability);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int compel_cpuid(compel_cpuinfo_t *c)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* See cpu_detect() in the kernel, also
|
||||||
|
* read cpuid specs not only from general
|
||||||
|
* SDM but for extended instructions set
|
||||||
|
* reference.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Get vendor name */
|
||||||
|
cpuid(0x00000000,
|
||||||
|
(unsigned int *)&c->cpuid_level,
|
||||||
|
(unsigned int *)&c->x86_vendor_id[0],
|
||||||
|
(unsigned int *)&c->x86_vendor_id[8],
|
||||||
|
(unsigned int *)&c->x86_vendor_id[4]);
|
||||||
|
|
||||||
|
if (!strcmp(c->x86_vendor_id, "GenuineIntel")) {
|
||||||
|
c->x86_vendor = X86_VENDOR_INTEL;
|
||||||
|
} else if (!strcmp(c->x86_vendor_id, "AuthenticAMD")) {
|
||||||
|
c->x86_vendor = X86_VENDOR_AMD;
|
||||||
|
} else {
|
||||||
|
pr_err("Unsupported CPU vendor %s\n",
|
||||||
|
c->x86_vendor_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->x86_family = 4;
|
||||||
|
|
||||||
|
/* Intel-defined flags: level 0x00000001 */
|
||||||
|
if (c->cpuid_level >= 0x00000001) {
|
||||||
|
uint32_t eax, ebx, ecx, edx;
|
||||||
|
|
||||||
|
cpuid(0x00000001, &eax, &ebx, &ecx, &edx);
|
||||||
|
c->x86_family = (eax >> 8) & 0xf;
|
||||||
|
c->x86_model = (eax >> 4) & 0xf;
|
||||||
|
c->x86_mask = eax & 0xf;
|
||||||
|
|
||||||
|
if (c->x86_family == 0xf)
|
||||||
|
c->x86_family += (eax >> 20) & 0xff;
|
||||||
|
if (c->x86_family >= 0x6)
|
||||||
|
c->x86_model += ((eax >> 16) & 0xf) << 4;
|
||||||
|
|
||||||
|
c->x86_capability[0] = edx;
|
||||||
|
c->x86_capability[4] = ecx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Additional Intel-defined flags: level 0x00000007 */
|
||||||
|
if (c->cpuid_level >= 0x00000007) {
|
||||||
|
uint32_t eax, ebx, ecx, edx;
|
||||||
|
|
||||||
|
cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx);
|
||||||
|
c->x86_capability[9] = ebx;
|
||||||
|
c->x86_capability[11] = ecx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extended state features: level 0x0000000d */
|
||||||
|
if (c->cpuid_level >= 0x0000000d) {
|
||||||
|
uint32_t eax, ebx, ecx, edx;
|
||||||
|
|
||||||
|
cpuid_count(0x0000000d, 1, &eax, &ebx, &ecx, &edx);
|
||||||
|
c->x86_capability[10] = eax;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AMD-defined flags: level 0x80000001 */
|
||||||
|
c->extended_cpuid_level = cpuid_eax(0x80000000);
|
||||||
|
|
||||||
|
if ((c->extended_cpuid_level & 0xffff0000) == 0x80000000) {
|
||||||
|
if (c->extended_cpuid_level >= 0x80000001) {
|
||||||
|
c->x86_capability[1] = cpuid_edx(0x80000001);
|
||||||
|
c->x86_capability[6] = cpuid_ecx(0x80000001);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We're don't care about scattered features for now,
|
||||||
|
* otherwise look into init_scattered_cpuid_features()
|
||||||
|
* in kernel.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (c->extended_cpuid_level >= 0x80000004) {
|
||||||
|
unsigned int *v;
|
||||||
|
char *p, *q;
|
||||||
|
v = (unsigned int *)c->x86_model_id;
|
||||||
|
cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
|
||||||
|
cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
|
||||||
|
cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
|
||||||
|
c->x86_model_id[48] = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Intel chips right-justify this string for some dumb reason;
|
||||||
|
* undo that brain damage:
|
||||||
|
*/
|
||||||
|
p = q = &c->x86_model_id[0];
|
||||||
|
while (*p == ' ')
|
||||||
|
p++;
|
||||||
|
if (p != q) {
|
||||||
|
while (*p)
|
||||||
|
*q++ = *p++;
|
||||||
|
while (q <= &c->x86_model_id[48])
|
||||||
|
*q++ = '\0'; /* Zero-pad the rest */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* On x86-64 NOP is always present */
|
||||||
|
compel_set_cpu_cap(c, X86_FEATURE_NOPL);
|
||||||
|
|
||||||
|
switch (c->x86_vendor) {
|
||||||
|
case X86_VENDOR_INTEL:
|
||||||
|
/*
|
||||||
|
* Strictly speaking we need to read MSR_IA32_MISC_ENABLE
|
||||||
|
* here but on ring3 it's impossible.
|
||||||
|
*/
|
||||||
|
if (c->x86_family == 15) {
|
||||||
|
compel_clear_cpu_cap(c, X86_FEATURE_REP_GOOD);
|
||||||
|
compel_clear_cpu_cap(c, X86_FEATURE_ERMS);
|
||||||
|
} else if (c->x86_family == 6) {
|
||||||
|
/* On x86-64 rep is fine */
|
||||||
|
compel_set_cpu_cap(c, X86_FEATURE_REP_GOOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See filter_cpuid_features in kernel */
|
||||||
|
if ((int32_t)c->cpuid_level < (int32_t)0x0000000d)
|
||||||
|
compel_clear_cpu_cap(c, X86_FEATURE_XSAVE);
|
||||||
|
break;
|
||||||
|
case X86_VENDOR_AMD:
|
||||||
|
/*
|
||||||
|
* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
|
||||||
|
* 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
|
||||||
|
*/
|
||||||
|
compel_clear_cpu_cap(c, 0 * 32 + 31);
|
||||||
|
if (c->x86_family >= 0x10)
|
||||||
|
compel_set_cpu_cap(c, X86_FEATURE_REP_GOOD);
|
||||||
|
if (c->x86_family == 0xf) {
|
||||||
|
uint32_t level;
|
||||||
|
|
||||||
|
/* On C+ stepping K8 rep microcode works well for copy/memset */
|
||||||
|
level = cpuid_eax(1);
|
||||||
|
if ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
|
||||||
|
compel_set_cpu_cap(c, X86_FEATURE_REP_GOOD);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cpu_has_feature(unsigned int feature)
|
||||||
|
{
|
||||||
|
if (!rt_info_done) {
|
||||||
|
compel_cpuid(&rt_info);
|
||||||
|
rt_info_done = true;
|
||||||
|
}
|
||||||
|
return compel_test_cpu_cap(&rt_info, feature);
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef __CR_ASM_CPU_H__
|
#ifndef __CR_ASM_CPU_H__
|
||||||
#define __CR_ASM_CPU_H__
|
#define __CR_ASM_CPU_H__
|
||||||
|
|
||||||
#include "asm/types.h"
|
#include <stdint.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adopted from linux kernel and enhanced from Intel/AMD manuals.
|
* Adopted from linux kernel and enhanced from Intel/AMD manuals.
|
||||||
@ -176,8 +176,6 @@ static inline unsigned int cpuid_edx(unsigned int op)
|
|||||||
return edx;
|
return edx;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define X86_FEATURE_VERSION 1
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
X86_VENDOR_INTEL = 0,
|
X86_VENDOR_INTEL = 0,
|
||||||
X86_VENDOR_AMD = 1,
|
X86_VENDOR_AMD = 1,
|
||||||
@ -186,22 +184,17 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct cpuinfo_x86 {
|
struct cpuinfo_x86 {
|
||||||
u8 x86_family;
|
uint8_t x86_family;
|
||||||
u8 x86_vendor;
|
uint8_t x86_vendor;
|
||||||
u8 x86_model;
|
uint8_t x86_model;
|
||||||
u8 x86_mask;
|
uint8_t x86_mask;
|
||||||
u32 x86_capability[NCAPINTS];
|
uint32_t x86_capability[NCAPINTS];
|
||||||
u32 extended_cpuid_level;
|
uint32_t extended_cpuid_level;
|
||||||
int cpuid_level;
|
int cpuid_level;
|
||||||
char x86_vendor_id[16];
|
char x86_vendor_id[16];
|
||||||
char x86_model_id[64];
|
char x86_model_id[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool cpu_has_feature(unsigned int feature);
|
typedef struct cpuinfo_x86 compel_cpuinfo_t;
|
||||||
extern int cpu_init(void);
|
|
||||||
extern int cpu_dump_cpuinfo(void);
|
|
||||||
extern int cpu_validate_cpuinfo(void);
|
|
||||||
extern int cpuinfo_dump(void);
|
|
||||||
extern int cpuinfo_check(void);
|
|
||||||
|
|
||||||
#endif /* __CR_CPU_H__ */
|
#endif /* __CR_ASM_CPU_H__ */
|
14
compel/include/uapi/cpu.h
Normal file
14
compel/include/uapi/cpu.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef UAPI_COMPEL_CPU_H__
|
||||||
|
#define UAPI_COMPEL_CPU_H__
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <compel/asm/cpu.h>
|
||||||
|
|
||||||
|
extern void compel_set_cpu_cap(compel_cpuinfo_t *info, unsigned int feature);
|
||||||
|
extern void compel_clear_cpu_cap(compel_cpuinfo_t *info, unsigned int feature);
|
||||||
|
extern int compel_test_cpu_cap(compel_cpuinfo_t *info, unsigned int feature);
|
||||||
|
extern int compel_cpuid(compel_cpuinfo_t *info);
|
||||||
|
extern bool cpu_has_feature(unsigned int feature);
|
||||||
|
|
||||||
|
#endif /* UAPI_COMPEL_CPU_H__ */
|
@ -73,6 +73,7 @@ PROGRAM-BUILTINS += images/built-in.o
|
|||||||
PROGRAM-BUILTINS += $(obj)/built-in.o
|
PROGRAM-BUILTINS += $(obj)/built-in.o
|
||||||
PROGRAM-BUILTINS += $(ARCH-LIB)
|
PROGRAM-BUILTINS += $(ARCH-LIB)
|
||||||
PROGRAM-BUILTINS += soccr/libsoccr.a
|
PROGRAM-BUILTINS += soccr/libsoccr.a
|
||||||
|
PROGRAM-BUILTINS += compel/libcompel.a
|
||||||
|
|
||||||
$(obj)/built-in.o: pie
|
$(obj)/built-in.o: pie
|
||||||
$(Q) $(MAKE) $(call build-as,Makefile.crtools,criu) all
|
$(Q) $(MAKE) $(call build-as,Makefile.crtools,criu) all
|
||||||
|
@ -4,11 +4,6 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
|
||||||
bool cpu_has_feature(unsigned int feature)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cpu_init(void)
|
int cpu_init(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include <linux/elf.h>
|
#include <linux/elf.h>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include <compel/asm/processor-flags.h>
|
||||||
|
|
||||||
#include "asm/restorer.h"
|
#include "asm/restorer.h"
|
||||||
#include "common/compiler.h"
|
#include "common/compiler.h"
|
||||||
#include "ptrace.h"
|
#include "ptrace.h"
|
||||||
|
@ -1 +0,0 @@
|
|||||||
#include <stdbool.h>
|
|
@ -4,11 +4,6 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
|
||||||
bool cpu_has_feature(unsigned int feature)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cpu_init(void)
|
int cpu_init(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include <compel/asm/processor-flags.h>
|
||||||
|
|
||||||
#include "asm/restorer.h"
|
#include "asm/restorer.h"
|
||||||
#include "common/compiler.h"
|
#include "common/compiler.h"
|
||||||
#include "asm/dump.h"
|
#include "asm/dump.h"
|
||||||
|
@ -1 +0,0 @@
|
|||||||
#include <stdbool.h>
|
|
@ -6,7 +6,6 @@
|
|||||||
#include <asm/cputable.h>
|
#include <asm/cputable.h>
|
||||||
|
|
||||||
#include "asm/types.h"
|
#include "asm/types.h"
|
||||||
#include "asm/cpu.h"
|
|
||||||
|
|
||||||
#include "cr_options.h"
|
#include "cr_options.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
@ -17,7 +16,7 @@
|
|||||||
#include "protobuf.h"
|
#include "protobuf.h"
|
||||||
#include "images/cpuinfo.pb-c.h"
|
#include "images/cpuinfo.pb-c.h"
|
||||||
|
|
||||||
static uint64_t hwcap[2];
|
static compel_cpuinfo_t rt_cpuinfo;
|
||||||
|
|
||||||
#ifdef __LITTLE_ENDIAN__
|
#ifdef __LITTLE_ENDIAN__
|
||||||
#define CURRENT_ENDIANNESS CPUINFO_PPC64_ENTRY__ENDIANNESS__LITTLEENDIAN
|
#define CURRENT_ENDIANNESS CPUINFO_PPC64_ENTRY__ENDIANNESS__LITTLEENDIAN
|
||||||
@ -27,14 +26,7 @@ static uint64_t hwcap[2];
|
|||||||
|
|
||||||
int cpu_init(void)
|
int cpu_init(void)
|
||||||
{
|
{
|
||||||
hwcap[0] = getauxval(AT_HWCAP);
|
return compel_cpuid(&rt_cpuinfo);
|
||||||
hwcap[1] = getauxval(AT_HWCAP2);
|
|
||||||
|
|
||||||
if (!hwcap[0] || !hwcap[1]) {
|
|
||||||
pr_err("Can't read the hardware capabilities");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cpu_dump_cpuinfo(void)
|
int cpu_dump_cpuinfo(void)
|
||||||
@ -54,7 +46,7 @@ int cpu_dump_cpuinfo(void)
|
|||||||
|
|
||||||
cpu_ppc64_info.endian = CURRENT_ENDIANNESS;
|
cpu_ppc64_info.endian = CURRENT_ENDIANNESS;
|
||||||
cpu_ppc64_info.n_hwcap = 2;
|
cpu_ppc64_info.n_hwcap = 2;
|
||||||
cpu_ppc64_info.hwcap = hwcap;
|
cpu_ppc64_info.hwcap = rt_cpuinfo.hwcap;
|
||||||
|
|
||||||
ret = pb_write_one(img, &cpu_info, PB_CPUINFO);
|
ret = pb_write_one(img, &cpu_info, PB_CPUINFO);
|
||||||
|
|
||||||
@ -92,7 +84,8 @@ int cpu_validate_cpuinfo(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_FEATURE(s,f) do { \
|
#define CHECK_FEATURE(s,f) do { \
|
||||||
if ((cpu_ppc64_entry->hwcap[s] & f) && !(hwcap[s] & f)) { \
|
if ((cpu_ppc64_entry->hwcap[s] & f) && \
|
||||||
|
!(rt_cpuinfo.hwcap[s] & f)) { \
|
||||||
pr_err("CPU Feature %s required by image " \
|
pr_err("CPU Feature %s required by image " \
|
||||||
"is not supported on host.\n", #f); \
|
"is not supported on host.\n", #f); \
|
||||||
goto error; \
|
goto error; \
|
||||||
|
@ -1 +0,0 @@
|
|||||||
#include <stdbool.h>
|
|
@ -10,6 +10,7 @@
|
|||||||
#include "asm/types.h"
|
#include "asm/types.h"
|
||||||
#include "asm/cpu.h"
|
#include "asm/cpu.h"
|
||||||
#include "asm/fpu.h"
|
#include "asm/fpu.h"
|
||||||
|
#include <compel/cpu.h>
|
||||||
|
|
||||||
#include "common/compiler.h"
|
#include "common/compiler.h"
|
||||||
|
|
||||||
@ -26,181 +27,11 @@
|
|||||||
#undef LOG_PREFIX
|
#undef LOG_PREFIX
|
||||||
#define LOG_PREFIX "cpu: "
|
#define LOG_PREFIX "cpu: "
|
||||||
|
|
||||||
static struct cpuinfo_x86 rt_cpu_info;
|
static compel_cpuinfo_t rt_cpu_info;
|
||||||
|
|
||||||
static void set_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
|
|
||||||
{
|
|
||||||
if (likely(feature < NCAPINTS_BITS))
|
|
||||||
set_bit(feature, (unsigned long *)c->x86_capability);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
|
|
||||||
{
|
|
||||||
if (likely(feature < NCAPINTS_BITS))
|
|
||||||
clear_bit(feature, (unsigned long *)c->x86_capability);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int test_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
|
|
||||||
{
|
|
||||||
if (likely(feature < NCAPINTS_BITS))
|
|
||||||
return test_bit(feature, (unsigned long *)c->x86_capability);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cpu_has_feature(unsigned int feature)
|
|
||||||
{
|
|
||||||
return test_cpu_cap(&rt_cpu_info, feature);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cpu_init_cpuid(struct cpuinfo_x86 *c)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* See cpu_detect() in the kernel, also
|
|
||||||
* read cpuid specs not only from general
|
|
||||||
* SDM but for extended instructions set
|
|
||||||
* reference.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Get vendor name */
|
|
||||||
cpuid(0x00000000,
|
|
||||||
(unsigned int *)&c->cpuid_level,
|
|
||||||
(unsigned int *)&c->x86_vendor_id[0],
|
|
||||||
(unsigned int *)&c->x86_vendor_id[8],
|
|
||||||
(unsigned int *)&c->x86_vendor_id[4]);
|
|
||||||
|
|
||||||
if (!strcmp(c->x86_vendor_id, "GenuineIntel")) {
|
|
||||||
c->x86_vendor = X86_VENDOR_INTEL;
|
|
||||||
} else if (!strcmp(c->x86_vendor_id, "AuthenticAMD")) {
|
|
||||||
c->x86_vendor = X86_VENDOR_AMD;
|
|
||||||
} else {
|
|
||||||
pr_err("Unsupported CPU vendor %s\n",
|
|
||||||
c->x86_vendor_id);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
c->x86_family = 4;
|
|
||||||
|
|
||||||
/* Intel-defined flags: level 0x00000001 */
|
|
||||||
if (c->cpuid_level >= 0x00000001) {
|
|
||||||
u32 eax, ebx, ecx, edx;
|
|
||||||
|
|
||||||
cpuid(0x00000001, &eax, &ebx, &ecx, &edx);
|
|
||||||
c->x86_family = (eax >> 8) & 0xf;
|
|
||||||
c->x86_model = (eax >> 4) & 0xf;
|
|
||||||
c->x86_mask = eax & 0xf;
|
|
||||||
|
|
||||||
if (c->x86_family == 0xf)
|
|
||||||
c->x86_family += (eax >> 20) & 0xff;
|
|
||||||
if (c->x86_family >= 0x6)
|
|
||||||
c->x86_model += ((eax >> 16) & 0xf) << 4;
|
|
||||||
|
|
||||||
c->x86_capability[0] = edx;
|
|
||||||
c->x86_capability[4] = ecx;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Additional Intel-defined flags: level 0x00000007 */
|
|
||||||
if (c->cpuid_level >= 0x00000007) {
|
|
||||||
u32 eax, ebx, ecx, edx;
|
|
||||||
|
|
||||||
cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx);
|
|
||||||
c->x86_capability[9] = ebx;
|
|
||||||
c->x86_capability[11] = ecx;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Extended state features: level 0x0000000d */
|
|
||||||
if (c->cpuid_level >= 0x0000000d) {
|
|
||||||
u32 eax, ebx, ecx, edx;
|
|
||||||
|
|
||||||
cpuid_count(0x0000000d, 1, &eax, &ebx, &ecx, &edx);
|
|
||||||
c->x86_capability[10] = eax;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* AMD-defined flags: level 0x80000001 */
|
|
||||||
c->extended_cpuid_level = cpuid_eax(0x80000000);
|
|
||||||
|
|
||||||
if ((c->extended_cpuid_level & 0xffff0000) == 0x80000000) {
|
|
||||||
if (c->extended_cpuid_level >= 0x80000001) {
|
|
||||||
c->x86_capability[1] = cpuid_edx(0x80000001);
|
|
||||||
c->x86_capability[6] = cpuid_ecx(0x80000001);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We're don't care about scattered features for now,
|
|
||||||
* otherwise look into init_scattered_cpuid_features()
|
|
||||||
* in kernel.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (c->extended_cpuid_level >= 0x80000004) {
|
|
||||||
unsigned int *v;
|
|
||||||
char *p, *q;
|
|
||||||
v = (unsigned int *)c->x86_model_id;
|
|
||||||
cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
|
|
||||||
cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
|
|
||||||
cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
|
|
||||||
c->x86_model_id[48] = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Intel chips right-justify this string for some dumb reason;
|
|
||||||
* undo that brain damage:
|
|
||||||
*/
|
|
||||||
p = q = &c->x86_model_id[0];
|
|
||||||
while (*p == ' ')
|
|
||||||
p++;
|
|
||||||
if (p != q) {
|
|
||||||
while (*p)
|
|
||||||
*q++ = *p++;
|
|
||||||
while (q <= &c->x86_model_id[48])
|
|
||||||
*q++ = '\0'; /* Zero-pad the rest */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* On x86-64 NOP is always present */
|
|
||||||
set_cpu_cap(c, X86_FEATURE_NOPL);
|
|
||||||
|
|
||||||
switch (c->x86_vendor) {
|
|
||||||
case X86_VENDOR_INTEL:
|
|
||||||
/*
|
|
||||||
* Strictly speaking we need to read MSR_IA32_MISC_ENABLE
|
|
||||||
* here but on ring3 it's impossible.
|
|
||||||
*/
|
|
||||||
if (c->x86_family == 15) {
|
|
||||||
clear_cpu_cap(c, X86_FEATURE_REP_GOOD);
|
|
||||||
clear_cpu_cap(c, X86_FEATURE_ERMS);
|
|
||||||
} else if (c->x86_family == 6) {
|
|
||||||
/* On x86-64 rep is fine */
|
|
||||||
set_cpu_cap(c, X86_FEATURE_REP_GOOD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See filter_cpuid_features in kernel */
|
|
||||||
if ((s32)c->cpuid_level < (s32)0x0000000d)
|
|
||||||
clear_cpu_cap(c, X86_FEATURE_XSAVE);
|
|
||||||
break;
|
|
||||||
case X86_VENDOR_AMD:
|
|
||||||
/*
|
|
||||||
* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
|
|
||||||
* 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
|
|
||||||
*/
|
|
||||||
clear_cpu_cap(c, 0 * 32 + 31);
|
|
||||||
if (c->x86_family >= 0x10)
|
|
||||||
set_cpu_cap(c, X86_FEATURE_REP_GOOD);
|
|
||||||
if (c->x86_family == 0xf) {
|
|
||||||
u32 level;
|
|
||||||
|
|
||||||
/* On C+ stepping K8 rep microcode works well for copy/memset */
|
|
||||||
level = cpuid_eax(1);
|
|
||||||
if ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
|
|
||||||
set_cpu_cap(c, X86_FEATURE_REP_GOOD);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cpu_init(void)
|
int cpu_init(void)
|
||||||
{
|
{
|
||||||
if (cpu_init_cpuid(&rt_cpu_info))
|
if (compel_cpuid(&rt_cpu_info))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
BUILD_BUG_ON(sizeof(struct xsave_struct) != XSAVE_SIZE);
|
BUILD_BUG_ON(sizeof(struct xsave_struct) != XSAVE_SIZE);
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
#include "asm/cpu.h"
|
#include "asm/cpu.h"
|
||||||
#include "kerndat.h"
|
#include "kerndat.h"
|
||||||
|
|
||||||
#include "compel/include/asm/processor-flags.h"
|
#include <compel/asm/processor-flags.h>
|
||||||
|
#include <compel/cpu.h>
|
||||||
#include "compel/include/errno.h"
|
#include "compel/include/errno.h"
|
||||||
#include <compel/plugins/std/syscall-codes.h>
|
#include <compel/plugins/std/syscall-codes.h>
|
||||||
#include <compel/plugins/std/syscall.h>
|
#include <compel/plugins/std/syscall.h>
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#ifndef __CR_CPU_H__
|
#ifndef __CR_CPU_H__
|
||||||
#define __CR_CPU_H__
|
#define __CR_CPU_H__
|
||||||
|
|
||||||
#include "asm/cpu.h"
|
#include <compel/cpu.h>
|
||||||
|
|
||||||
extern bool cpu_has_feature(unsigned int feature);
|
|
||||||
extern int cpu_init(void);
|
extern int cpu_init(void);
|
||||||
extern int cpu_dump_cpuinfo(void);
|
extern int cpu_dump_cpuinfo(void);
|
||||||
extern int cpu_validate_cpuinfo(void);
|
extern int cpu_validate_cpuinfo(void);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user