cpuid: first revision
This commit is contained in:
parent
909201d125
commit
8beef4d855
|
@ -1,3 +1,9 @@
|
||||||
# e2k-libs
|
# e2k-libs
|
||||||
|
|
||||||
Small e2k single header libraries for everyone to use
|
Small e2k single header libraries for everyone to use
|
||||||
|
|
||||||
|
## cpuid
|
||||||
|
|
||||||
|
A CPUID that doesn't rely on Linux kernel to get processor info.
|
||||||
|
|
||||||
|
Maybe useful for those cases, when /proc/cpuinfo is not available or invalid.
|
||||||
|
|
|
@ -0,0 +1,200 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2020 Alibek Omarov <a1ba.omarov@gmail.com>
|
||||||
|
|
||||||
|
This work is free. You can redistribute it and/or modify it under the
|
||||||
|
terms of the Do What The Fuck You Want To Public License, Version 2,
|
||||||
|
as published by Sam Hocevar. See http://www.wtfpl.net/ for more details.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#ifndef E2K_CPUID_H
|
||||||
|
#define E2K_CPUID_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e2k cpuid single-header library, v1
|
||||||
|
*
|
||||||
|
* Changes from v0:
|
||||||
|
* - initial release
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
typedef struct e2k_cpuid_s
|
||||||
|
{
|
||||||
|
char model[16]; // string representation of model
|
||||||
|
uint32_t mdl; // actual model id
|
||||||
|
uint32_t revision;
|
||||||
|
uint32_t l2_wb_len; // L2 cache writeback length
|
||||||
|
uint32_t cores;
|
||||||
|
uint32_t pn; // ???
|
||||||
|
uint32_t vt_version;
|
||||||
|
uint32_t have_vt;
|
||||||
|
uint32_t is_guest;
|
||||||
|
} e2k_cpuid_t;
|
||||||
|
|
||||||
|
typedef enum e2k_cpuid_mdl_e
|
||||||
|
{
|
||||||
|
MDL_E2S = 0x03, /* Elbrus-4C */
|
||||||
|
MDL_ES2 = 0x04, /* Elbrus-2C+ */
|
||||||
|
MDL_ES2_NO_DSP = 0x06, /* Elbrus-2CM */
|
||||||
|
MDL_E8C = 0x07, /* Elbrus-8C */
|
||||||
|
MDL_E1CP = 0x08, /* Elbrus-1C+ */
|
||||||
|
MDL_E8C2 = 0x09, /* Elbrus-8C2 */
|
||||||
|
MDL_E12C = 0x0a, /* Elbrus-12C */
|
||||||
|
MDL_E16C = 0x0b, /* Elbrus-16C */
|
||||||
|
MDL_E2C3 = 0x0c, /* Elbrus-2C3 */
|
||||||
|
} e2k_cpuid_mdl_t;
|
||||||
|
|
||||||
|
int e2k_cpuid( e2k_cpuid_t *cpuid );
|
||||||
|
int e2k_cpuid_from_regs( e2k_cpuid_t *cpuid, uint64_t idr, uint32_t core_mode /* only v6 */ );
|
||||||
|
int e2k_cpuid_model_from_mdl( char *out, size_t len, uint32_t mdl );
|
||||||
|
|
||||||
|
#ifdef E2K_CPUID_IMPLEMENTATION
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define extract32( v, s, len ) ((( v ) >> ( s )) & ( ~0U >> ( 32 - ( len ))))
|
||||||
|
#define extract64( v, s, len ) ((( v ) >> ( s )) & ( ~0ULL >> ( 64 - ( len ))))
|
||||||
|
|
||||||
|
#define IDR_MDL_START 0
|
||||||
|
#define IDR_MDL_BITS 8
|
||||||
|
#define IDR_REV_START ( IDR_MDL_START + IDR_MDL_BITS )
|
||||||
|
#define IDR_REV_BITS 4
|
||||||
|
#define IDR_WBL_START ( IDR_REV_START + IDR_REV_BITS )
|
||||||
|
#define IDR_WBL_BITS 3
|
||||||
|
#define IDR_CORE_START ( IDR_WBL_START + IDR_WBL_BITS )
|
||||||
|
#define IDR_CORE_BITS 5
|
||||||
|
#define IDR_PN_START ( IDR_CORE_START + IDR_CORE_BITS )
|
||||||
|
#define IDR_PN_BITS 4
|
||||||
|
#define IDR_HW_VT_START ( IDR_PN_START + IDR_PN_BITS )
|
||||||
|
#define IDR_HW_VT_BITS 1
|
||||||
|
#define IDR_HW_VT_VER_START ( IDR_HW_VT_START + IDR_HW_VT_BITS )
|
||||||
|
#define IDR_HW_VT_VER_BITS 4
|
||||||
|
|
||||||
|
#define CORE_MODE_GUEST_START 3
|
||||||
|
#define CORE_MODE_GUEST_BITS 1
|
||||||
|
|
||||||
|
#define IDR_WBL_TO_BYTES(wbl) ((wbl) ? (1 << (wbl + 4)) : 1)
|
||||||
|
|
||||||
|
int e2k_cpuid_model_from_mdl( char *out, size_t len, uint32_t mdl )
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
switch( mdl )
|
||||||
|
{
|
||||||
|
case MDL_E2S: str = "Elbrus-4C"; break;
|
||||||
|
case MDL_ES2: str = "Elbrus-2C+"; break;
|
||||||
|
case MDL_ES2_NO_DSP: str = "Elbrus-2CM"; break;
|
||||||
|
case MDL_E8C: str = "Elbrus-8C"; break;
|
||||||
|
case MDL_E1CP: str = "Elbrus-1C+"; break;
|
||||||
|
case MDL_E8C2: str = "Elbrus-8C2"; break;
|
||||||
|
case MDL_E12C: str = "Elbrus-12C"; break;
|
||||||
|
case MDL_E16C: str = "Elbrus-16C"; break;
|
||||||
|
case MDL_E2C3: str = "Elbrus-2C3"; break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
if( mdl < MDL_E2S )
|
||||||
|
str = "E3M LOL";
|
||||||
|
else if( mdl > MDL_E2C3 )
|
||||||
|
str = "UpdateCpuidPls";
|
||||||
|
retval = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy( out, str, len );
|
||||||
|
out[len - 1] = 0;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int e2k_cpuid_from_regs( e2k_cpuid_t *cpuid, uint64_t idr, uint32_t core_mode )
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
memset( cpuid, 0, sizeof( *cpuid ));
|
||||||
|
|
||||||
|
cpuid->mdl = extract64( idr, IDR_MDL_START, IDR_MDL_BITS );
|
||||||
|
cpuid->revision = extract64( idr, IDR_REV_START, IDR_REV_BITS );
|
||||||
|
cpuid->l2_wb_len = extract64( idr, IDR_WBL_START, IDR_WBL_BITS );
|
||||||
|
|
||||||
|
// only v6 and higher
|
||||||
|
if( cpuid->mdl > MDL_E12C )
|
||||||
|
{
|
||||||
|
cpuid->cores = extract64( idr, IDR_CORE_START, IDR_CORE_BITS );
|
||||||
|
cpuid->pn = extract64( idr, IDR_PN_START, IDR_PN_BITS );
|
||||||
|
cpuid->have_vt = extract64( idr, IDR_HW_VT_START, IDR_HW_VT_BITS );
|
||||||
|
cpuid->vt_version = extract64( idr, IDR_HW_VT_VER_START, IDR_HW_VT_VER_BITS );
|
||||||
|
|
||||||
|
cpuid->is_guest = extract32( core_mode, CORE_MODE_GUEST_START, CORE_MODE_GUEST_BITS );
|
||||||
|
}
|
||||||
|
|
||||||
|
// finalize data
|
||||||
|
cpuid->l2_wb_len = IDR_WBL_TO_BYTES( cpuid->l2_wb_len );
|
||||||
|
retval = e2k_cpuid_model_from_mdl( cpuid->model, sizeof( cpuid->model ), cpuid->mdl );
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t e2k_get_core_mode( void ) __attribute__((noinline));
|
||||||
|
#if __iset__ >= 6
|
||||||
|
uint32_t e2k_get_core_mode( void )
|
||||||
|
{
|
||||||
|
register uint32_t core_mode = 0;
|
||||||
|
#pragma no_asm_inline
|
||||||
|
__asm__ volatile
|
||||||
|
(
|
||||||
|
"\t rrs \t%%core_mode, %0\n"
|
||||||
|
: "=r"(core_mode)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
__asm__ volatile
|
||||||
|
(
|
||||||
|
"e2k_get_core_mode:\n"
|
||||||
|
".dword 0x04108022\n"
|
||||||
|
".dword 0x58ecc082\n"
|
||||||
|
".dword 0x040000c4\n"
|
||||||
|
".dword 0x01c00000\n"
|
||||||
|
".dword 0x00000000\n"
|
||||||
|
".dword 0x00000110\n"
|
||||||
|
".dword 0x04000001\n"
|
||||||
|
".dword 0x90c0c083\n"
|
||||||
|
".dword 0x04100011\n"
|
||||||
|
".dword 0x3e04c083\n"
|
||||||
|
".dword 0x01c00000\n"
|
||||||
|
".dword 0x00000000\n"
|
||||||
|
".dword 0x04004292\n"
|
||||||
|
".dword 0x8cc68380\n"
|
||||||
|
".dword 0xf0000000\n"
|
||||||
|
".dword 0x00000000\n"
|
||||||
|
".dword 0x00001001\n"
|
||||||
|
".dword 0xc0000c20\n"
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int e2k_cpuid( e2k_cpuid_t *cpuid )
|
||||||
|
{
|
||||||
|
uint64_t idr;
|
||||||
|
uint32_t core_mode = 0;
|
||||||
|
uint32_t mdl;
|
||||||
|
|
||||||
|
__asm__ volatile( "\trrd \t%%idr, %0\n" : "=r"(idr));
|
||||||
|
|
||||||
|
mdl = extract64( idr, IDR_MDL_START, IDR_MDL_BITS );
|
||||||
|
|
||||||
|
if( mdl >= MDL_E12C )
|
||||||
|
{
|
||||||
|
core_mode = e2k_get_core_mode();
|
||||||
|
}
|
||||||
|
|
||||||
|
return e2k_cpuid_from_regs( cpuid, idr, core_mode );
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef IDR_WBL_TO_BYTES
|
||||||
|
#undef extract32
|
||||||
|
#undef extract64
|
||||||
|
|
||||||
|
#endif // E2K_CPUID_IMPLEMENTATION
|
||||||
|
#endif // E2K_CPUID_H
|
|
@ -0,0 +1,19 @@
|
||||||
|
#define E2K_CPUID_IMPLEMENTATION
|
||||||
|
#include "e2k_cpuid.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main( int argc, char **argv )
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
e2k_cpuid_t cpuid;
|
||||||
|
if(( err = e2k_cpuid( &cpuid )))
|
||||||
|
{
|
||||||
|
printf( "Error %d\n", err );
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf( "Model: %s\nRevision: %d\nCores: %d\nL2 writeback length: %d\nHave VT: %d\nVT version: %d\nUnder KVM: %d\n",
|
||||||
|
cpuid.model, cpuid.revision, cpuid.cores, cpuid.l2_wb_len, cpuid.have_vt, cpuid.vt_version, cpuid.is_guest );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue