mirror of
https://github.com/memtest86plus/memtest86plus.git
synced 2024-11-30 11:03:48 -06:00
201 lines
5.5 KiB
C
201 lines
5.5 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#ifndef CPUID_H
|
|
#define CPUID_H
|
|
/*
|
|
* Provides access to the CPUID information.
|
|
*
|
|
* Copyright (C) 2020 Martin Whitaker.
|
|
*
|
|
* Derived from memtest86+ cpuid.h
|
|
* (original contained no copyright statement)
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
|
|
/*
|
|
* Structures that hold the collected CPUID information.
|
|
*/
|
|
|
|
typedef union {
|
|
uint32_t raw;
|
|
struct {
|
|
uint32_t stepping : 4;
|
|
uint32_t model : 4;
|
|
uint32_t family : 4;
|
|
uint32_t processorType : 2;
|
|
uint32_t : 2;
|
|
uint32_t extendedModel : 4;
|
|
uint32_t extendedFamily : 8;
|
|
uint32_t : 4;
|
|
};
|
|
} cpuid_version_t;
|
|
|
|
typedef union {
|
|
uint32_t raw;
|
|
struct {
|
|
uint32_t brandIndex : 8;
|
|
uint32_t cflushLineSize : 8;
|
|
uint32_t logicalProcessorCount : 8;
|
|
uint32_t apicID : 8;
|
|
};
|
|
} cpuid_proc_info_t;
|
|
|
|
typedef union {
|
|
uint32_t raw[3];
|
|
struct {
|
|
uint32_t fpu : 1; // EDX feature flags, bit 0 */
|
|
uint32_t vme : 1;
|
|
uint32_t de : 1;
|
|
uint32_t pse : 1;
|
|
uint32_t rdtsc : 1;
|
|
uint32_t msr : 1;
|
|
uint32_t pae : 1;
|
|
uint32_t mce : 1;
|
|
uint32_t cx8 : 1;
|
|
uint32_t apic : 1;
|
|
uint32_t : 1;
|
|
uint32_t sep : 1;
|
|
uint32_t mtrr : 1;
|
|
uint32_t pge : 1;
|
|
uint32_t mca : 1;
|
|
uint32_t cmov : 1;
|
|
uint32_t pat : 1;
|
|
uint32_t pse36 : 1;
|
|
uint32_t psn : 1;
|
|
uint32_t cflush : 1;
|
|
uint32_t : 1;
|
|
uint32_t ds : 1;
|
|
uint32_t acpi : 1;
|
|
uint32_t mmx : 1;
|
|
uint32_t fxsr : 1;
|
|
uint32_t sse : 1;
|
|
uint32_t sse2 : 1;
|
|
uint32_t ss : 1;
|
|
uint32_t htt : 1;
|
|
uint32_t tm : 1;
|
|
uint32_t bit30 : 1;
|
|
uint32_t pbe : 1; // EDX feature flags, bit 31
|
|
uint32_t sse3 : 1; // ECX feature flags, bit 0
|
|
uint32_t mulq : 1;
|
|
uint32_t bit2 : 1;
|
|
uint32_t mon : 1;
|
|
uint32_t dscpl : 1;
|
|
uint32_t vmx : 1;
|
|
uint32_t smx : 1;
|
|
uint32_t eist : 1;
|
|
uint32_t tm2 : 1;
|
|
uint32_t : 23; // ECX feature flags, bit 31
|
|
uint32_t : 29; // EDX extended feature flags, bit 0
|
|
uint32_t lm : 1;
|
|
uint32_t : 2; // EDX extended feature flags, bit 31
|
|
};
|
|
} cpuid_feature_flags_t;
|
|
|
|
#define CPUID_VENDOR_LENGTH 3
|
|
#define CPUID_VENDOR_STR_LENGTH (CPUID_VENDOR_LENGTH * sizeof(uint32_t) + 1) // includes space for null terminator
|
|
|
|
typedef union {
|
|
uint32_t raw[CPUID_VENDOR_LENGTH];
|
|
char str[CPUID_VENDOR_STR_LENGTH];
|
|
} cpuid_vendor_string_t;
|
|
|
|
#define CPUID_BRAND_LENGTH 12
|
|
#define CPUID_BRAND_STR_LENGTH (CPUID_BRAND_LENGTH * sizeof(uint32_t) + 1) // includes space for null terminator
|
|
|
|
typedef union {
|
|
uint32_t raw[CPUID_BRAND_LENGTH];
|
|
char str[CPUID_BRAND_STR_LENGTH];
|
|
} cpuid_brand_string_t;
|
|
|
|
typedef union {
|
|
uint32_t raw[12];
|
|
struct {
|
|
uint32_t : 24;
|
|
uint32_t l1_i_size : 8;
|
|
uint32_t : 24;
|
|
uint32_t l1_d_size : 8;
|
|
uint32_t : 16;
|
|
uint32_t l2_size : 16;
|
|
uint32_t : 18;
|
|
uint32_t l3_size : 14;
|
|
};
|
|
} cpuid_cache_info_t;
|
|
|
|
typedef union {
|
|
uint32_t raw;
|
|
struct {
|
|
uint32_t : 1;
|
|
};
|
|
} cpuid_custom_features;
|
|
|
|
typedef struct {
|
|
uint32_t max_vcpuid;
|
|
uint32_t max_xcpuid;
|
|
uint32_t dts_pmp;
|
|
cpuid_version_t version;
|
|
cpuid_proc_info_t proc_info;
|
|
cpuid_feature_flags_t flags;
|
|
cpuid_vendor_string_t vendor_id;
|
|
cpuid_brand_string_t brand_id;
|
|
cpuid_cache_info_t cache_info;
|
|
cpuid_custom_features custom;
|
|
} cpuid_info_t;
|
|
|
|
typedef union {
|
|
uint32_t raw;
|
|
struct {
|
|
uint32_t ctype : 5;
|
|
uint32_t level : 3;
|
|
uint32_t is_self_initializing : 1;
|
|
uint32_t is_fully_associative : 1;
|
|
uint32_t reserved : 4;
|
|
uint32_t num_threads_sharing : 12;
|
|
uint32_t num_cores_on_die : 6;
|
|
};
|
|
} cpuid4_eax_t;
|
|
|
|
typedef union {
|
|
uint32_t raw;
|
|
struct {
|
|
uint32_t coherency_line_size : 12;
|
|
uint32_t physical_line_partition : 10;
|
|
uint32_t ways_of_associativity : 10;
|
|
};
|
|
} cpuid4_ebx_t;
|
|
|
|
typedef union {
|
|
uint32_t raw;
|
|
struct {
|
|
uint32_t number_of_sets : 32;
|
|
};
|
|
} cpuid4_ecx_t;
|
|
|
|
/*
|
|
* The CPUID information collected by cpuid_init();
|
|
*/
|
|
extern cpuid_info_t cpuid_info;
|
|
|
|
/*
|
|
* Reads the CPUID information and stores it in cpuid_info.
|
|
*/
|
|
void cpuid_init(void);
|
|
|
|
/*
|
|
* Executes the cpuid instruction.
|
|
*/
|
|
static inline void cpuid(uint32_t op, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
|
|
{
|
|
*eax = op;
|
|
*ecx = count;
|
|
__asm__ __volatile__ ("cpuid"
|
|
: "=a" (*eax),
|
|
"=b" (*ebx),
|
|
"=c" (*ecx),
|
|
"=d" (*edx)
|
|
: "0" (*eax),
|
|
"2" (*ecx)
|
|
);
|
|
}
|
|
|
|
#endif // CPUID_H
|