memtest86plus/system/cpuid.h

230 lines
6.1 KiB
C

// SPDX-License-Identifier: GPL-2.0
#ifndef CPUID_H
#define CPUID_H
/**
* \file
*
* Provides access to the CPUID information.
*
*//*
* Copyright (C) 2020-2022 Martin Whitaker.
* Copyright (C) 2004-2022 Sam Demeulemeester.
*
* Derived from memtest86+ cpuid.h
*/
#include <stdint.h>
#define CPU_ECORE_ID 0x20
#define CPU_PCORE_ID 0x40
typedef enum {
CORE_UNKNOWN,
CORE_PCORE,
CORE_ECORE
} core_type_t;
/**
* Structures that hold the collected CPUID information.
*/
typedef union {
uint32_t raw[2];
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;
uint32_t extendedBrandID : 32; // AMD Only
};
} 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 : 12; // ECX feature flags, bit 20
uint32_t x2apic : 1;
uint32_t : 10; // 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[4];
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 {
int core_count;
int thread_count;
int is_hybrid;
int ecore_count;
int pcore_count;
} cpuid_topology_t;
typedef struct {
uint32_t max_cpuid;
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_topology_t topology;
} 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);
/**
* Return the Core Type (for Hybrid CPUs)
*/
core_type_t get_ap_hybrid_type(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