mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-22 18:07:57 +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
|
||||
# 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 $@
|
||||
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
|
||||
.PHONY: criu
|
||||
|
||||
|
@ -33,6 +33,7 @@ compel-uapi-links += $(SRC_DIR)/compel/include/asm
|
||||
compel-deps += $(compel-uapi-links)
|
||||
compel-deps += $(COMPEL_VERSION_HEADER)
|
||||
compel-deps += $(CONFIG_HEADER)
|
||||
compel-deps += include/common/asm
|
||||
|
||||
#
|
||||
# Compel itself.
|
||||
|
@ -22,6 +22,8 @@ host-lib-y += src/lib/handle-elf.o
|
||||
lib-y += src/lib/log.o
|
||||
host-lib-y += src/lib/log.o
|
||||
|
||||
lib-y += arch/$(ARCH)/src/lib/cpu.o
|
||||
|
||||
ifeq ($(ARCH),x86)
|
||||
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__
|
||||
#define __CR_ASM_CPU_H__
|
||||
|
||||
#include "asm/types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
#define X86_FEATURE_VERSION 1
|
||||
|
||||
enum {
|
||||
X86_VENDOR_INTEL = 0,
|
||||
X86_VENDOR_AMD = 1,
|
||||
@ -186,22 +184,17 @@ enum {
|
||||
};
|
||||
|
||||
struct cpuinfo_x86 {
|
||||
u8 x86_family;
|
||||
u8 x86_vendor;
|
||||
u8 x86_model;
|
||||
u8 x86_mask;
|
||||
u32 x86_capability[NCAPINTS];
|
||||
u32 extended_cpuid_level;
|
||||
uint8_t x86_family;
|
||||
uint8_t x86_vendor;
|
||||
uint8_t x86_model;
|
||||
uint8_t x86_mask;
|
||||
uint32_t x86_capability[NCAPINTS];
|
||||
uint32_t extended_cpuid_level;
|
||||
int cpuid_level;
|
||||
char x86_vendor_id[16];
|
||||
char x86_model_id[64];
|
||||
};
|
||||
|
||||
extern bool cpu_has_feature(unsigned int feature);
|
||||
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);
|
||||
typedef struct cpuinfo_x86 compel_cpuinfo_t;
|
||||
|
||||
#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 += $(ARCH-LIB)
|
||||
PROGRAM-BUILTINS += soccr/libsoccr.a
|
||||
PROGRAM-BUILTINS += compel/libcompel.a
|
||||
|
||||
$(obj)/built-in.o: pie
|
||||
$(Q) $(MAKE) $(call build-as,Makefile.crtools,criu) all
|
||||
|
@ -4,11 +4,6 @@
|
||||
#include <errno.h>
|
||||
#include "cpu.h"
|
||||
|
||||
bool cpu_has_feature(unsigned int feature)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int cpu_init(void)
|
||||
{
|
||||
return 0;
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include <linux/elf.h>
|
||||
|
||||
#include "types.h"
|
||||
#include <compel/asm/processor-flags.h>
|
||||
|
||||
#include "asm/restorer.h"
|
||||
#include "common/compiler.h"
|
||||
#include "ptrace.h"
|
||||
|
@ -1 +0,0 @@
|
||||
#include <stdbool.h>
|
@ -4,11 +4,6 @@
|
||||
#include <errno.h>
|
||||
#include "cpu.h"
|
||||
|
||||
bool cpu_has_feature(unsigned int feature)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int cpu_init(void)
|
||||
{
|
||||
return 0;
|
||||
|
@ -2,6 +2,8 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "types.h"
|
||||
#include <compel/asm/processor-flags.h>
|
||||
|
||||
#include "asm/restorer.h"
|
||||
#include "common/compiler.h"
|
||||
#include "asm/dump.h"
|
||||
|
@ -1 +0,0 @@
|
||||
#include <stdbool.h>
|
@ -6,7 +6,6 @@
|
||||
#include <asm/cputable.h>
|
||||
|
||||
#include "asm/types.h"
|
||||
#include "asm/cpu.h"
|
||||
|
||||
#include "cr_options.h"
|
||||
#include "image.h"
|
||||
@ -17,7 +16,7 @@
|
||||
#include "protobuf.h"
|
||||
#include "images/cpuinfo.pb-c.h"
|
||||
|
||||
static uint64_t hwcap[2];
|
||||
static compel_cpuinfo_t rt_cpuinfo;
|
||||
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
#define CURRENT_ENDIANNESS CPUINFO_PPC64_ENTRY__ENDIANNESS__LITTLEENDIAN
|
||||
@ -27,14 +26,7 @@ static uint64_t hwcap[2];
|
||||
|
||||
int cpu_init(void)
|
||||
{
|
||||
hwcap[0] = getauxval(AT_HWCAP);
|
||||
hwcap[1] = getauxval(AT_HWCAP2);
|
||||
|
||||
if (!hwcap[0] || !hwcap[1]) {
|
||||
pr_err("Can't read the hardware capabilities");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
return compel_cpuid(&rt_cpuinfo);
|
||||
}
|
||||
|
||||
int cpu_dump_cpuinfo(void)
|
||||
@ -54,7 +46,7 @@ int cpu_dump_cpuinfo(void)
|
||||
|
||||
cpu_ppc64_info.endian = CURRENT_ENDIANNESS;
|
||||
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);
|
||||
|
||||
@ -92,7 +84,8 @@ int cpu_validate_cpuinfo(void)
|
||||
}
|
||||
|
||||
#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 " \
|
||||
"is not supported on host.\n", #f); \
|
||||
goto error; \
|
||||
|
@ -1 +0,0 @@
|
||||
#include <stdbool.h>
|
@ -10,6 +10,7 @@
|
||||
#include "asm/types.h"
|
||||
#include "asm/cpu.h"
|
||||
#include "asm/fpu.h"
|
||||
#include <compel/cpu.h>
|
||||
|
||||
#include "common/compiler.h"
|
||||
|
||||
@ -26,181 +27,11 @@
|
||||
#undef LOG_PREFIX
|
||||
#define LOG_PREFIX "cpu: "
|
||||
|
||||
static struct cpuinfo_x86 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;
|
||||
}
|
||||
static compel_cpuinfo_t rt_cpu_info;
|
||||
|
||||
int cpu_init(void)
|
||||
{
|
||||
if (cpu_init_cpuid(&rt_cpu_info))
|
||||
if (compel_cpuid(&rt_cpu_info))
|
||||
return -1;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct xsave_struct) != XSAVE_SIZE);
|
||||
|
@ -9,7 +9,8 @@
|
||||
#include "asm/cpu.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/plugins/std/syscall-codes.h>
|
||||
#include <compel/plugins/std/syscall.h>
|
||||
|
@ -1,9 +1,8 @@
|
||||
#ifndef __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_dump_cpuinfo(void);
|
||||
extern int cpu_validate_cpuinfo(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user