how do u mix da heat

This commit is contained in:
Hane 2023-07-24 20:00:22 +02:00
commit 14b4d72d8a
5 changed files with 280 additions and 191 deletions

View file

@ -1 +1 @@
clang++ -D DEBUG src\tmrtsc.hpp -Wall -Wextra -Wpedantic -std=c++11 -g -gcodeview -Wl,-pdb= -L C:\capybara\libclang\x86_64-w64-mingw32\bin -l c++ -l unwind --verbose clang++ -DDEBUG -shared src\tmrtsc.cpp -o build\libtmrtsc.dll -Wall -Wextra -Wpedantic -std=c++11 -g -gcodeview -Wl,-pdb= -L C:\capybara\libclang\x86_64-w64-mingw32\bin -l c++ -l unwind --verbose

3
buildtest.bat Normal file
View file

@ -0,0 +1,3 @@
clang++ src\test\test.cpp -o build\test.exe -Wall -Wextra -Wpedantic -std=c++11 -g -gcodeview -Wl,-pdb= -L C:\capybara\libclang\x86_64-w64-mingw32\bin -l c++ -l unwind -L D:\Contenido\Capybara\Cositas\tmr\build -l tmrtsc --verbose
REM -fms-runtime-lib dll_dbg

41
src/test/test.cpp Normal file
View file

@ -0,0 +1,41 @@
#ifdef _WIN64
#define UNICODE
#define WIN32_LEAN_AND_MEAN
//#define DllImport __declspec( dllimport )
#include <Windows.h>
#include <libloaderapi.h>
#endif
#include "../debug.h"
#include "../tmrtsc.hpp"
using namespace tmr;
#ifdef _WIN64
int main(int argc, char** argv){
HMODULE dell;
DWORD fracaso;
int sleep = 1000;
dell = LoadLibraryExW(TEXT("libtmrtsc.dll"), NULL, NULL);
if (dell == NULL) {
fracaso = GetLastError();
return -1;
}
TSCTimer* timer = nullptr;
fracaso = TSCTimer::getTimer(timer);
if(fracaso != OPERATION_SUCCESSFUL)
return -2;
uint64_t t1 = timer->getTimeStamp();
Sleep(sleep);
uint64_t t2 = timer->getTimeStamp();
uint64_t fr = timer->getBaseFrequency();
std::cout << "Windows Momento: \nt1: " << t1 << " t2: " << " fr: " << fr << std::endl;
return 0;
}
#else
int main(int argc, char** argv){
return -9;
}
#endif

207
src/tmrtsc.cpp Normal file
View file

@ -0,0 +1,207 @@
#include "tmrtsc.hpp"
#if _WIN64
extern "C" {
#endif
namespace tmr {
TSCTimer::TSCTimer(char* vendorName, int64_t baseFreq) {
this->vendorName = vendorName;
this->baseFreq = baseFreq;
this->availableRDTSCP = (checkRDTSCP()) ? true : false;
}
TSCTimer::~TSCTimer () {
free(vendorName);
}
bool TSCTimer::checkInvariantTSC() {
uint64_t rdx;
asm volatile (".intel_syntax noprefix\t\n" \
"mov eax, 0x80000007\t\n" \
"cpuid\t\n" : "=d" (rdx) );
bool iTSC = rdx & (1<<8);
return iTSC;
}
char* TSCTimer::readVendorName () {
char* palabritas = (char*)malloc(sizeof(char) * 13);
uint8_t siguienteLetra = 0;
uint64_t regs[3];
asm volatile ( ".intel_syntax noprefix\t\n" \
"mov eax, 0x0\t\n" \
"cpuid\t\n" : "=b" (regs[0]), "=c" (regs[2]), "=d" (regs[1]) );
int byte = 0;
for (int reg = 0; reg < 3; reg++, byte = 0){
char* charifiedReg = (char*)&regs[reg];
for(; byte < 4; byte++, siguienteLetra++ ){
palabritas[siguienteLetra] = charifiedReg[byte];
}
}
palabritas[siguienteLetra] = '\0';
return palabritas;
}
int64_t TSCTimer::intelRetrieveART(){
//TODO: Find a valid Intel CPU to debug ART route
//if (freq == nullptr) return -
uint64_t raxde, rbxnum, rcxhz;
asm volatile ( ".intel_syntax noprefix\t\n" \
"mov eax, 0x15\t\n" \
"cpuid\t\n" : "=a" (raxde), "=b" (rbxnum), "=c" (rcxhz) );
log_debugcpp("hmm " << raxde << " " << rbxnum << " " << rcxhz);
if (rbxnum == 0 || rcxhz == 0) return ART_NOT_REPORTED;
int64_t TSCFreq = (rcxhz * rbxnum)/raxde;
//*freq = TSCFreq;
log_debugcpp("raxo " << TSCFreq << " " << TSCFreq);
return TSCFreq;
}
#ifdef _WIN64
int64_t TSCTimer::getFreqFromSystem(){
//TODO: close opened key
const WORD STRING_SIZE = 4;
const WCHAR COMPARE_TARGET[STRING_SIZE + 1] = L"~MHz";
DWORD longestDataSize;
LSTATUS status;
HKEY key;
DWORD numValues;
WCHAR valName[MAX_VALUE_NAME]; //uint32_t wtf
DWORD valLen = MAX_VALUE_NAME;
LPBYTE dataContent = nullptr;
DWORD dataLen;
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), 0,
KEY_QUERY_VALUE, &key);
if(status != ERROR_SUCCESS) return CANT_OPEN_KEY;
status = RegQueryInfoKey(
key, // key handle
NULL, // buffer for class name
NULL, // size of class string
NULL, // reserved
NULL, // num of subkeys
NULL, // longest subkey size
NULL, // longest class string
&numValues, // num of values for this key
NULL, // longest value name
&longestDataSize, // longest value data
NULL, // security descriptor
NULL); // last write time
if(status != ERROR_SUCCESS) return CANT_RETRIEVE_KEY_INFO;
dataLen = sizeof(REG_QWORD) * (longestDataSize);
dataContent = (LPBYTE)malloc(dataLen);
for (DWORD i = 0; i < numValues; i++){
valLen = MAX_VALUE_NAME;
dataLen = sizeof(REG_QWORD) * (longestDataSize);
status = RegEnumValueW(key,
i,
valName,
&valLen,
NULL,
NULL,
dataContent,
&dataLen
);
if(status != ERROR_SUCCESS) return CANT_READ_DATA_FROM_VALUE;
if (CSTR_EQUAL == CompareStringEx(
LOCALE_NAME_INVARIANT,
NORM_LINGUISTIC_CASING,
valName,
valLen,
COMPARE_TARGET,
STRING_SIZE,
NULL,
NULL,
0
)
) {
LPDWORD PMHz = (LPDWORD)dataContent;
DWORD MHz = *PMHz;
free(dataContent);
return MHz * 1000000;
}
}
return CANT_READ_DATA_FROM_VALUE;
}
#endif
bool TSCTimer::checkRDTSCP(){ //Generic
uint64_t rdx;
asm volatile (".intel_syntax noprefix\t\n" \
"mov eax, 0x80000001\t\n" \
// 080000007h\t\n"
"cpuid\t\n" : "=d" (rdx) );
bool RDTSCP = rdx & (1<<27);
//"and edx, 10000000\n")
return RDTSCP;
}
uint64_t TSCTimer::readRDTSC() {
uint64_t raxlo,rdxho;
asm volatile ( ".intel_syntax noprefix\t\n"
"lfence\n" \
"rdtsc\n" \
"lfence\n" : "=a" (raxlo), "=d" (rdxho));
return (rdxho << 32) + raxlo; //|
}
uint64_t TSCTimer::readRDTSCP(uint64_t* logicore) {
uint64_t raxlo,rdxho, rcx;
asm volatile ( ".intel_syntax noprefix\t\n"
"rdtscp\t\n"
"lfence\t\n": "=a" (raxlo), "=d" (rdxho), "=c" (rcx) );
if (logicore != nullptr) *logicore = rcx;
return (rdxho << 32) + raxlo; //|
}
int TSCTimer::getTimer(TSCTimer* timer) {
if (!checkInvariantTSC()) return INVARIANT_TSC_NOT_SUPPORTED;
//TODO debug dis
const char vendorNames[2][13] = {
{"AuthenticAMD"},
{"GenuineIntel"}
};
char* vendorName = readVendorName();
int64_t baseFreq;
if (strcmp(vendorName, vendorNames[1]))
baseFreq = intelRetrieveART();
if (baseFreq == ART_NOT_REPORTED)
baseFreq = getFreqFromSystem();
if (baseFreq < OPERATION_SUCCESSFUL)
return CANT_READ_FREQUENCY_FROM_SYSTEM;
timer = new TSCTimer(vendorName, baseFreq);
return OPERATION_SUCCESSFUL;
}
uint64_t TSCTimer::getTimeStamp(){
if (availableRDTSCP)
return readRDTSCP();
else
return readRDTSC();
}
uint64_t TSCTimer::getBaseFrequency(){
return baseFreq;
}
}
#ifdef _WIN64
}
#endif

View file

@ -1,4 +1,5 @@
//TODO It's threadin' time //TODO It's threadin' time
#pragma once
#ifdef _WIN64 #ifdef _WIN64
#define LIB_EXPORT __declspec(dllexport) #define LIB_EXPORT __declspec(dllexport)
@ -20,22 +21,22 @@
#include <cstring> #include <cstring>
#include "debug.h" #include "debug.h"
/*
* #if _WIN64 #if _WIN64
* extern "C" {) extern "C" {
* #endif #endif
*/
namespace tmr { namespace tmr {
#ifdef _WIN64 #ifdef _WIN64
enum LIB_EXPORT winReturnValues{ enum winReturnValues{
CANT_OPEN_KEY = -1, CANT_OPEN_KEY = -1,
CANT_RETRIEVE_KEY_INFO = -2, CANT_RETRIEVE_KEY_INFO = -2,
CANT_READ_DATA_FROM_VALUE = -3, CANT_READ_DATA_FROM_VALUE = -3,
CANT_RETRIEVE_FREQUENCY = -4 CANT_RETRIEVE_FREQUENCY = -4
}; };
#endif #endif
enum LIB_EXPORT ReturnValues { enum ReturnValues {
OPERATION_SUCCESSFUL = 0, OPERATION_SUCCESSFUL = 0,
INVARIANT_TSC_NOT_SUPPORTED = -1, INVARIANT_TSC_NOT_SUPPORTED = -1,
UNSUPPORTED_CPU = -2, UNSUPPORTED_CPU = -2,
@ -46,211 +47,48 @@ namespace tmr {
class LIB_EXPORT TSCTimer { class LIB_EXPORT TSCTimer {
private: private:
static TSCTimer timer; //static TSCTimer timer;
char* vendorName; char* vendorName;
int64_t baseFreq = ART_NOT_REPORTED; int64_t baseFreq = ART_NOT_REPORTED;
bool availableRDTSCP; bool availableRDTSCP = false;
int64_t art; //reserved int64_t art; //reserved
TSCTimer (char* vendorName, int64_t baseFreq) { TSCTimer(char* vendorName, int64_t baseFreq);
this->vendorName = vendorName;
this->baseFreq = baseFreq;
availableRDTSCP = (checkRDTSCP()) ? true : false;
}
~TSCTimer () { ~TSCTimer();
free(vendorName);
}
static bool checkInvariantTSC() { static bool checkInvariantTSC();
uint64_t rdx;
asm volatile (".intel_syntax noprefix\t\n" \
"mov eax, 0x80000007\t\n" \
"cpuid\t\n" : "=d" (rdx) );
bool iTSC = rdx & (1<<8);
return iTSC;
}
static char* readVendorName ();
static char* readVendorName () {
char* palabritas = (char*)malloc(sizeof(char) * 13);
uint8_t siguienteLetra = 0;
uint64_t regs[3];
asm volatile ( ".intel_syntax noprefix\t\n" \
"mov eax, 0x0\t\n" \
"cpuid\t\n" : "=b" (regs[0]), "=c" (regs[2]), "=d" (regs[1]) );
int byte = 0;
for (int reg = 0; reg < 3; reg++, byte = 0){
char* charifiedReg = (char*)&regs[reg];
for(; byte < 4; byte++, siguienteLetra++ ){
palabritas[siguienteLetra] = charifiedReg[byte];
}
}
palabritas[siguienteLetra] = '\0';
return palabritas;
}
static int64_t intelRetrieveART(){ static int64_t intelRetrieveART();
//TODO: Find a valid Intel CPU to debug ART route
//if (freq == nullptr) return -
uint64_t raxde, rbxnum, rcxhz;
asm volatile ( ".intel_syntax noprefix\t\n" \
"mov eax, 0x15\t\n" \
"cpuid\t\n" : "=a" (raxde), "=b" (rbxnum), "=c" (rcxhz) );
log_debugcpp("hmm " << raxde << " " << rbxnum << " " << rcxhz);
if (rbxnum == 0 || rcxhz == 0) return ART_NOT_REPORTED;
int64_t TSCFreq = (rcxhz * rbxnum)/raxde;
//*freq = TSCFreq;
log_debugcpp("raxo " << TSCFreq << " " << TSCFreq);
return TSCFreq;
}
#ifdef _WIN64 #ifdef _WIN64
static int64_t getFreqFromSystem(){ static int64_t getFreqFromSystem();
//TODO: close opened key
const WORD STRING_SIZE = 4;
const WCHAR COMPARE_TARGET[STRING_SIZE + 1] = L"~MHz";
DWORD longestDataSize;
LSTATUS status;
HKEY key;
DWORD numValues;
WCHAR valName[MAX_VALUE_NAME]; //uint32_t wtf
DWORD valLen = MAX_VALUE_NAME;
LPBYTE dataContent = nullptr;
DWORD dataLen;
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), 0,
KEY_QUERY_VALUE, &key);
if(status != ERROR_SUCCESS) return CANT_OPEN_KEY;
status = RegQueryInfoKey(
key, // key handle
NULL, // buffer for class name
NULL, // size of class string
NULL, // reserved
NULL, // num of subkeys
NULL, // longest subkey size
NULL, // longest class string
&numValues, // num of values for this key
NULL, // longest value name
&longestDataSize, // longest value data
NULL, // security descriptor
NULL); // last write time
if(status != ERROR_SUCCESS) return CANT_RETRIEVE_KEY_INFO;
dataLen = sizeof(REG_QWORD) * (longestDataSize);
dataContent = (LPBYTE)malloc(dataLen);
for (DWORD i = 0; i < numValues; i++){
valLen = MAX_VALUE_NAME;
dataLen = sizeof(REG_QWORD) * (longestDataSize);
status = RegEnumValueW(key,
i,
valName,
&valLen,
NULL,
NULL,
dataContent,
&dataLen
);
if(status != ERROR_SUCCESS) return CANT_READ_DATA_FROM_VALUE;
if (CSTR_EQUAL == CompareStringEx(
LOCALE_NAME_INVARIANT,
NORM_LINGUISTIC_CASING,
valName,
valLen,
COMPARE_TARGET,
STRING_SIZE,
NULL,
NULL,
0
)
) {
LPDWORD PMHz = (LPDWORD)dataContent;
DWORD MHz = *PMHz;
free(dataContent);
return MHz * 1000000;
}
}
return CANT_READ_DATA_FROM_VALUE;
}
#endif #endif
bool checkRDTSCP(){ //Generic bool checkRDTSCP();
uint64_t rdx;
asm volatile (".intel_syntax noprefix\t\n" \
"mov eax, 0x80000001\t\n" \
// 080000007h\t\n"
"cpuid\t\n" : "=d" (rdx) );
bool RDTSCP = rdx & (1<<27);
//"and edx, 10000000\n")
return RDTSCP;
}
uint64_t readRDTSC() { uint64_t readRDTSC();
uint64_t raxlo,rdxho;
asm volatile ( ".intel_syntax noprefix\t\n"
"lfence\n" \
"rdtsc\n" \
"lfence\n" : "=a" (raxlo), "=d" (rdxho));
return (rdxho << 32) + raxlo; //|
}
uint64_t readRDTSCP(uint64_t* logicore = nullptr ) { uint64_t readRDTSCP(uint64_t* logicore = nullptr );
uint64_t raxlo,rdxho, rcx;
asm volatile ( ".intel_syntax noprefix\t\n"
"rdtscp\t\n"
"lfence\t\n": "=a" (raxlo), "=d" (rdxho), "=c" (rcx) );
if (logicore != nullptr) *logicore = rcx;
return (rdxho << 32) + raxlo; //|
}
public: public:
static int getTimer(TSCTimer* timer = nullptr) { static int getTimer(TSCTimer* timer = nullptr);
if (!checkInvariantTSC()) return INVARIANT_TSC_NOT_SUPPORTED;
//TODO debug dis
const char vendorNames[2][13] = {
{"AuthenticAMD"},
{"GenuineIntel"}
};
char* vendorName = readVendorName();
int64_t baseFreq;
if (strcmp(vendorName, vendorNames[1]))
baseFreq = intelRetrieveART();
if (baseFreq == ART_NOT_REPORTED)
baseFreq = getFreqFromSystem();
if (baseFreq < OPERATION_SUCCESSFUL)
return CANT_READ_FREQUENCY_FROM_SYSTEM;
timer = new TSCTimer(vendorName, baseFreq); uint64_t getTimeStamp();
return OPERATION_SUCCESSFUL;
}
uint64_t getTimeStamp(){ uint64_t getBaseFrequency();
if (availableRDTSCP)
return readRDTSCP();
else
return readRDTSC();
}
uint64_t getBaseFrequency(){
return baseFreq;
}
}; };
} }
/*
* #ifdef _WIN64 #ifdef _WIN64
* } }
* #endif #endif
*/