x86/cpuid: Carve out all CPUID functionality
Carve it out into a special header, where it belongs. No functional changes. Signed-off-by: Borislav Petkov <bp@suse.de> Link: https://lore.kernel.org/r/20221124164150.3040-1-bp@alien8.de
This commit is contained in:
@@ -1,13 +1,132 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* CPUID-related helpers/definitions
|
||||
*
|
||||
* Derived from arch/x86/kvm/cpuid.c
|
||||
*/
|
||||
|
||||
#ifndef _ASM_X86_CPUID_H
|
||||
#define _ASM_X86_CPUID_H
|
||||
|
||||
#include <asm/string.h>
|
||||
|
||||
struct cpuid_regs {
|
||||
u32 eax, ebx, ecx, edx;
|
||||
};
|
||||
|
||||
enum cpuid_regs_idx {
|
||||
CPUID_EAX = 0,
|
||||
CPUID_EBX,
|
||||
CPUID_ECX,
|
||||
CPUID_EDX,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
extern int have_cpuid_p(void);
|
||||
#else
|
||||
static inline int have_cpuid_p(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
|
||||
unsigned int *ecx, unsigned int *edx)
|
||||
{
|
||||
/* ecx is often an input as well as an output. */
|
||||
asm volatile("cpuid"
|
||||
: "=a" (*eax),
|
||||
"=b" (*ebx),
|
||||
"=c" (*ecx),
|
||||
"=d" (*edx)
|
||||
: "0" (*eax), "2" (*ecx)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
#define native_cpuid_reg(reg) \
|
||||
static inline unsigned int native_cpuid_##reg(unsigned int op) \
|
||||
{ \
|
||||
unsigned int eax = op, ebx, ecx = 0, edx; \
|
||||
\
|
||||
native_cpuid(&eax, &ebx, &ecx, &edx); \
|
||||
\
|
||||
return reg; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Native CPUID functions returning a single datum.
|
||||
*/
|
||||
native_cpuid_reg(eax)
|
||||
native_cpuid_reg(ebx)
|
||||
native_cpuid_reg(ecx)
|
||||
native_cpuid_reg(edx)
|
||||
|
||||
#ifdef CONFIG_PARAVIRT_XXL
|
||||
#include <asm/paravirt.h>
|
||||
#else
|
||||
#define __cpuid native_cpuid
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Generic CPUID function
|
||||
* clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
|
||||
* resulting in stale register contents being returned.
|
||||
*/
|
||||
static inline void cpuid(unsigned int op,
|
||||
unsigned int *eax, unsigned int *ebx,
|
||||
unsigned int *ecx, unsigned int *edx)
|
||||
{
|
||||
*eax = op;
|
||||
*ecx = 0;
|
||||
__cpuid(eax, ebx, ecx, edx);
|
||||
}
|
||||
|
||||
/* Some CPUID calls want 'count' to be placed in ecx */
|
||||
static inline void cpuid_count(unsigned int op, int count,
|
||||
unsigned int *eax, unsigned int *ebx,
|
||||
unsigned int *ecx, unsigned int *edx)
|
||||
{
|
||||
*eax = op;
|
||||
*ecx = count;
|
||||
__cpuid(eax, ebx, ecx, edx);
|
||||
}
|
||||
|
||||
/*
|
||||
* CPUID functions returning a single datum
|
||||
*/
|
||||
static inline unsigned int cpuid_eax(unsigned int op)
|
||||
{
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
|
||||
cpuid(op, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
return eax;
|
||||
}
|
||||
|
||||
static inline unsigned int cpuid_ebx(unsigned int op)
|
||||
{
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
|
||||
cpuid(op, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
return ebx;
|
||||
}
|
||||
|
||||
static inline unsigned int cpuid_ecx(unsigned int op)
|
||||
{
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
|
||||
cpuid(op, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
return ecx;
|
||||
}
|
||||
|
||||
static inline unsigned int cpuid_edx(unsigned int op)
|
||||
{
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
|
||||
cpuid(op, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
return edx;
|
||||
}
|
||||
|
||||
static __always_inline bool cpuid_function_is_indexed(u32 function)
|
||||
{
|
||||
switch (function) {
|
||||
@@ -31,4 +150,22 @@ static __always_inline bool cpuid_function_is_indexed(u32 function)
|
||||
return false;
|
||||
}
|
||||
|
||||
#define for_each_possible_hypervisor_cpuid_base(function) \
|
||||
for (function = 0x40000000; function < 0x40010000; function += 0x100)
|
||||
|
||||
static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)
|
||||
{
|
||||
uint32_t base, eax, signature[3];
|
||||
|
||||
for_each_possible_hypervisor_cpuid_base(base) {
|
||||
cpuid(base, &eax, &signature[0], &signature[1], &signature[2]);
|
||||
|
||||
if (!memcmp(sig, signature, 12) &&
|
||||
(leaves == 0 || ((eax - base) >= leaves)))
|
||||
return base;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _ASM_X86_CPUID_H */
|
||||
|
||||
@@ -16,6 +16,7 @@ struct vm86;
|
||||
#include <uapi/asm/sigcontext.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/cpufeatures.h>
|
||||
#include <asm/cpuid.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable_types.h>
|
||||
#include <asm/percpu.h>
|
||||
@@ -146,17 +147,6 @@ struct cpuinfo_x86 {
|
||||
unsigned initialized : 1;
|
||||
} __randomize_layout;
|
||||
|
||||
struct cpuid_regs {
|
||||
u32 eax, ebx, ecx, edx;
|
||||
};
|
||||
|
||||
enum cpuid_regs_idx {
|
||||
CPUID_EAX = 0,
|
||||
CPUID_EBX,
|
||||
CPUID_ECX,
|
||||
CPUID_EDX,
|
||||
};
|
||||
|
||||
#define X86_VENDOR_INTEL 0
|
||||
#define X86_VENDOR_CYRIX 1
|
||||
#define X86_VENDOR_AMD 2
|
||||
@@ -205,45 +195,6 @@ extern void identify_secondary_cpu(struct cpuinfo_x86 *);
|
||||
extern void print_cpu_info(struct cpuinfo_x86 *);
|
||||
void print_cpu_msr(struct cpuinfo_x86 *);
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
extern int have_cpuid_p(void);
|
||||
#else
|
||||
static inline int have_cpuid_p(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
|
||||
unsigned int *ecx, unsigned int *edx)
|
||||
{
|
||||
/* ecx is often an input as well as an output. */
|
||||
asm volatile("cpuid"
|
||||
: "=a" (*eax),
|
||||
"=b" (*ebx),
|
||||
"=c" (*ecx),
|
||||
"=d" (*edx)
|
||||
: "0" (*eax), "2" (*ecx)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
#define native_cpuid_reg(reg) \
|
||||
static inline unsigned int native_cpuid_##reg(unsigned int op) \
|
||||
{ \
|
||||
unsigned int eax = op, ebx, ecx = 0, edx; \
|
||||
\
|
||||
native_cpuid(&eax, &ebx, &ecx, &edx); \
|
||||
\
|
||||
return reg; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Native CPUID functions returning a single datum.
|
||||
*/
|
||||
native_cpuid_reg(eax)
|
||||
native_cpuid_reg(ebx)
|
||||
native_cpuid_reg(ecx)
|
||||
native_cpuid_reg(edx)
|
||||
|
||||
/*
|
||||
* Friendlier CR3 helpers.
|
||||
*/
|
||||
@@ -578,7 +529,6 @@ static __always_inline bool on_thread_stack(void)
|
||||
#ifdef CONFIG_PARAVIRT_XXL
|
||||
#include <asm/paravirt.h>
|
||||
#else
|
||||
#define __cpuid native_cpuid
|
||||
|
||||
static inline void load_sp0(unsigned long sp0)
|
||||
{
|
||||
@@ -589,69 +539,6 @@ static inline void load_sp0(unsigned long sp0)
|
||||
|
||||
unsigned long __get_wchan(struct task_struct *p);
|
||||
|
||||
/*
|
||||
* Generic CPUID function
|
||||
* clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
|
||||
* resulting in stale register contents being returned.
|
||||
*/
|
||||
static inline void cpuid(unsigned int op,
|
||||
unsigned int *eax, unsigned int *ebx,
|
||||
unsigned int *ecx, unsigned int *edx)
|
||||
{
|
||||
*eax = op;
|
||||
*ecx = 0;
|
||||
__cpuid(eax, ebx, ecx, edx);
|
||||
}
|
||||
|
||||
/* Some CPUID calls want 'count' to be placed in ecx */
|
||||
static inline void cpuid_count(unsigned int op, int count,
|
||||
unsigned int *eax, unsigned int *ebx,
|
||||
unsigned int *ecx, unsigned int *edx)
|
||||
{
|
||||
*eax = op;
|
||||
*ecx = count;
|
||||
__cpuid(eax, ebx, ecx, edx);
|
||||
}
|
||||
|
||||
/*
|
||||
* CPUID functions returning a single datum
|
||||
*/
|
||||
static inline unsigned int cpuid_eax(unsigned int op)
|
||||
{
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
|
||||
cpuid(op, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
return eax;
|
||||
}
|
||||
|
||||
static inline unsigned int cpuid_ebx(unsigned int op)
|
||||
{
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
|
||||
cpuid(op, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
return ebx;
|
||||
}
|
||||
|
||||
static inline unsigned int cpuid_ecx(unsigned int op)
|
||||
{
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
|
||||
cpuid(op, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
return ecx;
|
||||
}
|
||||
|
||||
static inline unsigned int cpuid_edx(unsigned int op)
|
||||
{
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
|
||||
cpuid(op, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
return edx;
|
||||
}
|
||||
|
||||
extern void select_idle_routine(const struct cpuinfo_x86 *c);
|
||||
extern void amd_e400_c1e_apic_setup(void);
|
||||
|
||||
@@ -805,24 +692,6 @@ static inline u32 amd_get_nodes_per_socket(void) { return 0; }
|
||||
static inline u32 amd_get_highest_perf(void) { return 0; }
|
||||
#endif
|
||||
|
||||
#define for_each_possible_hypervisor_cpuid_base(function) \
|
||||
for (function = 0x40000000; function < 0x40010000; function += 0x100)
|
||||
|
||||
static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)
|
||||
{
|
||||
uint32_t base, eax, signature[3];
|
||||
|
||||
for_each_possible_hypervisor_cpuid_base(base) {
|
||||
cpuid(base, &eax, &signature[0], &signature[1], &signature[2]);
|
||||
|
||||
if (!memcmp(sig, signature, 12) &&
|
||||
(leaves == 0 || ((eax - base) >= leaves)))
|
||||
return base;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern unsigned long arch_align_stack(unsigned long sp);
|
||||
void free_init_pages(const char *what, unsigned long begin, unsigned long end);
|
||||
extern void free_kernel_image_pages(const char *what, void *begin, void *end);
|
||||
|
||||
Reference in New Issue
Block a user