tmr/src/proto/proto.cpp
2023-07-29 03:14:45 +02:00

342 lines
11 KiB
C++

//si, bueno, testx
//dossPxa
/*
* THREADIN THE LINUS: https://linux.die.net/man/2/sched_setaffinity
*/
/*
*THREADIN THE WINDOS: https://learn.microsoft.com/en-us/windows/win32/procthread/process-and-thread-functions
*/
//clangbug: https://bugs.llvm.org/show_bug.cgi?id=24232
//tsc synced across cpu intel: https://community.intel.com/t5/Software-Tuning-Performance/TSCs-per-logical-processor-Per-socket/m-p/1121318
//lfence: https://hadibrais.wordpress.com/2018/05/14/the-significance-of-the-x86-lfence-instruction/
/*
In the Intel(R) 64 and IA-32 Architectures Software Developer's Manual Volume 3B Sec 17.13.1 it says:
"On processors with invariant TSC support, the OS may use the TSC for wall clock timer services."
Does this formally imply that the TSC is always synchronized across all cores?
By default the TSC is synchronized across all cores. However, the TSC value of a core could be changed by some software subsystem using the WRMSR instruction. Take a look at quotes below and I hope they finally answer your estion:
Intel(R) 64 and IA-32 Architectures Software Developer's Manual Volume 3 (3A, 3B & 3C): System Programming Guide Order Number: 325384-044US August 2012 Page 571 17.13 TIME-STAMP COUNTER ... Constant TSC behavior ensures that the duration of each clock tick is uniform and supports the use of the TSC as a wall clock timer even if the processor core changes frequency. ... Page 572 17.13.3 Time-Stamp Counter Adjustment ... Software can modify the value of the time-stamp counter (TSC) of a logical processor by using the WRMSR instruction to write to the IA32_TIME_STAMP_COUNTER MSR (address 10H). Because such a write applies only to that logical processor, software seeking to synchronize the TSC values of multiple logical processors must perform these writes on each logical processor. It may be difficult for software to do this in a way than ensures that all logical processors will have the same value for the TSC at a given point in time. The synchronization of TSC adjustment can be simplified by using the 64-bit IA32_TSC_ADJUST MSR ( address 3BH ). Like the IA32_TIME_STAMP_COUNTER MSR, the IA32_TSC_ADJUST MSR is maintained separately for each logical processor. ...
*/
//TSC is incremented by the base multiplier once every reference clock, so on my Xeon E5-2680 (Sandy Bridge EP) this is an increment of 27 every 10 ns
#ifdef _WIN64
//#include <Windows.h>
//#includqe <sysinfoapi.h>
//#include <powerbase.h>
#define UNICODE
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT _WIN32_WINNT_WIN10 //0x0A00
#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 32767
#include <Windows.h>
#include <winreg.h>
#include <stringapiset.h>
#include <synchapi.h>
#endif
#ifdef NOMESELDELINUS
//hilitos y tal
#endif
#include <vector>
#include <iostream>
#include "../debug.h"
bool checkInvariantTSC(){ //Generic
uint64_t rdx;
asm volatile (".intel_syntax noprefix\t\n" \
"mov eax, 0x80000007\t\n" \
// 080000007h\t\n"
"cpuid\t\n" : "=d" (rdx) );
bool iTSC = rdx & (1<<8);
//"and edx, 10000000\n")
return iTSC;
}
bool 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;
}
/*
1er comentario: https://community.intel.com/t5/Software-Tuning-Performance/TSC-frequency-computation/m-p/1193432
https://community.intel.com/t5/Software-Tuning-Performance/i5-8250U-1-6-GHz-has-a-base-frequency-of-1-8-GHz/m-p/1155718/highlight/true
15H
NOTES: If EBX[31:0] is 0, the TSC/"core crystal clock" ratio is not enumerated.
EBX[31:0]/EAX[31:0] indicates the ratio of the TSC frequency and the core crystal clock frequency.
If ECX is 0, the nominal core crystal clock frequency is not enumerated.
"TSC frequency" = "core crystal clock frequency" * EBX/EAX.
The core crystal clock may differ from the reference clock, bus clock, or core clock frequencies.
EAX Bits 31-00: An unsigned integer which is the denominator of the TSC/"core crystal clock" ratio.
EBX Bits 31-00: An unsigned integer which is the numerator of the TSC/"core crystal clock" ratio.
ECX Bits 31-00: An unsigned integer which is the nominal frequency of the core crystal clock in Hz.
EDX Bits 31-00: Reserved = 0.
*/
char* AMDMeCagoEnTusPutosMuertos () {
/*
* Extended name on AMD systems when using 8000_002-4. 8000_0000 for Extpagequant/vendor. Hijos de puta.
* Now parsing 0H for standard brand name
*/
char* palabritas = (char*)malloc(sizeof(char) * 13);
uint8_t siguienteLetra = 0;
//uint64_t regs[4]; //rax rbx, rcx, rdx; Was used for Extended name/vendor
uint64_t regs[3];//rbx, rcx, rdx;
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;
}
//GMET on??????????? jfc wtf
bool AMDJoderMET(){
uint64_t rdx;
asm volatile ( ".intel_syntax noprefix\t\n" \
"mov eax, 0x8000000A\t\n" \
"cpuid\t\n" : "=d" (rdx));
return (((1<<17) & rdx));
}
int16_t checkFrequencyTSC(uint64_t* freq){
//la idea era hacerla todo aqui; este primero mira el num de pags
if (freq == nullptr) return -1;
uint64_t raxde;
asm volatile ( ".intel_syntax noprefix\t\n" \
"mov eax, 0x0\t\n" \
"cpuid\t\n" : "=a" (raxde) );
log_debugcpp("raxo " << raxde);
if (raxde < 15) {
//check tsc existence??????
uint64_t rdxmsr;
asm volatile ( ".intel_syntax noprefix\t\n" \
"mov eax, 0x01\t\n" \
"cpuid\t\n" : "=a" (raxde), "=d" (rdxmsr) );
if (!((1<<5) & rdxmsr)) return -3;
asm volatile ( ".intel_syntax noprefix\t\n" \
"mov eax, 0x01\t\n" \
"cpuid\t\n" : "=a" (raxde), "=d" (rdxmsr) );
}
uint64_t rbxnum, rcxhz;
asm volatile ( ".intel_syntax noprefix\t\n" \
"mov eax, 0x15\t\n" \
"cpuid\t\n" : "=a" (raxde), "=b" (rbxnum), "=c" (rcxhz) );
//"rdtscp\n" : "=a" (raxlo), "=d" (rdxho));
log_debugcpp("hmm " << raxde << " " << rbxnum << " " << rcxhz);
if (rbxnum == 0 || rcxhz == 0) return -2;
//also 18.17.4 Invariant Time-Keepin Volume 3 Intel
uint64_t TSCFreq = (rcxhz * rbxnum)/raxde;
*freq = TSCFreq;
log_debugcpp("raxo " << TSCFreq << " " << *freq);
return 0;
}
//static inline
uint64_t rdtsc() {
uint64_t raxlo,rdxho;
asm volatile ( ".intel_syntax noprefix\t\n"
"lfence\n" \
"rdtsc\n" \
//"rdtscp\n" : "=a" (raxlo), "=d" (rdxho), "=c" (aux) : : );
"lfence\n" : "=a" (raxlo), "=d" (rdxho));
return (rdxho << 32) + raxlo; //|
}
//static inline
uint64_t rdtscp(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) );
//"rdtscp\n" : "=a" (raxlo), "=d" (rdxho));
if (logicore != nullptr) *logicore = rcx;
return (rdxho << 32) + raxlo; //|
}
//labor encomiable, ahora muere
uint64_t estimandoFreq(){
uint64_t test = rdtsc();
Sleep(1000);
test = rdtsc() - test;
return test;
}
#ifdef _WIN64
//https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getnativesysteminfo
//https://learn.microsoft.com/en-us/windows/win32/api/powerbase/nf-powerbase-callntpowerinformation?redirectedfrom=MSDN
/*
* And this is why I'm reading the reg instead
*/
int64_t getFreqFromReg(){
//https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regenumvaluew
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;
// DOESN'T WORK MS WHY const WORD NULL_ENDING_STRING = -1;
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), 0,
KEY_QUERY_VALUE, &key);
if(status != ERROR_SUCCESS) return -1;
status = RegQueryInfoKey(
key, // key handle
NULL, // buffer for class name
NULL, // size of class string
NULL, // reserved
NULL, // number of subkeys
NULL, // longest subkey size
NULL, // longest class string
&numValues, // number of values for this key
NULL, // longest value name
&longestDataSize, // longest value data
NULL, // security descriptor
NULL); // last write time
if(status != ERROR_SUCCESS) {
RegCloseKey(key);
return -2;
}
dataLen = sizeof(REG_QWORD) * (longestDataSize);
dataContent = (LPBYTE)malloc(dataLen);
for (DWORD i = 0; i < numValues; i++){
valLen = MAX_VALUE_NAME;
//data NULL + len NON_NULL to get dataBufLen;
//data allocated (NON-NULL) + len NON-NULL with previous value for dataLen
//JFC MS WHY. that why we defaultin to biggis. cos not worky. ewe
dataLen = sizeof(REG_QWORD) * (longestDataSize);
status = RegEnumValueW(key,
i,
valName,
&valLen,
NULL,
NULL,
dataContent,
&dataLen
);
if(status != ERROR_SUCCESS) {
RegCloseKey(key);
return -3;
}
if (CSTR_EQUAL == CompareStringEx(
LOCALE_NAME_INVARIANT,
NORM_LINGUISTIC_CASING,
valName,
valLen,
COMPARE_TARGET,
STRING_SIZE,
NULL,
NULL,
0
)
) {
//dataLen = dataLen * 2lu;
/* BROS YO ES QUE ME VOY A CAGAR EN SUS PUTOS MUERTOS
* AS&iacute; QUE PIDES DOS VECES, UNA TAMA&nacute;O, OTRA A TOPE PRESISO, EH
* PUTA BASURA DE API
* status = RegEnumValueW(key,
* i,
* valName,
* &valLen,
* NULL,
* NULL,
* dataContent,
* &dataLen
* );
*/
LPDWORD PMHz = (LPDWORD)dataContent;
DWORD MHz = *PMHz;
free(dataContent);
status = RegCloseKey(key);
return MHz * 1000000;
//break;
}
}
if(status != ERROR_SUCCESS) {
status = RegCloseKey(key);
return -4;
}
}
#endif
int main(int argc, char** argv){
//AMD Momento
char* opiniones = AMDMeCagoEnTusPutosMuertos();
bool w11 = AMDJoderMET();
for (int i = 0; i < 3; i++) {
uint64_t isItActually32GHz = estimandoFreq();
log_debugcpp("ayo we found " << isItActually32GHz << " flash knuckle");
}
int64_t juas = getFreqFromReg();
log_debugcpp("JODER " << juas);
//iwintewel
//Cordura
int16_t result;
uint64_t tf = 0;
//uint64_t* TSCFreq = &tf;
bool iTSC = checkInvariantTSC();
bool RDTSC = checkRDTSCP();
result = checkFrequencyTSC(&tf);
log_debugcpp("INTEL YO HOW WE DOIN " << tf << result);
if (iTSC && !result) {
uint64_t test = rdtsc();
log_debugcpp(test);
uint64_t ayo = 0;
uint64_t* logicore = &ayo;//nullptr;
uint64_t testp = rdtscp(logicore);
log_debugcpp(testp << " + " << &logicore);
return 0;
}
return -1;
}