cpuid: first revision
This commit is contained in:
parent
909201d125
commit
8beef4d855
|
@ -1,3 +1,9 @@
|
|||
# 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