summaryrefslogtreecommitdiffstats
path: root/xmrstak/backend/cpu/autoAdjust.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'xmrstak/backend/cpu/autoAdjust.hpp')
-rw-r--r--xmrstak/backend/cpu/autoAdjust.hpp172
1 files changed, 172 insertions, 0 deletions
diff --git a/xmrstak/backend/cpu/autoAdjust.hpp b/xmrstak/backend/cpu/autoAdjust.hpp
new file mode 100644
index 0000000..32c8576
--- /dev/null
+++ b/xmrstak/backend/cpu/autoAdjust.hpp
@@ -0,0 +1,172 @@
+#pragma once
+#include "jconf.h"
+#include "../../console.h"
+#include "../../jconf.h"
+#include "../../ConfigEditor.hpp"
+#include "../../Params.hpp"
+#include <string>
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif // _WIN32
+
+
+namespace xmrstak
+{
+namespace cpu
+{
+// Mask bits between h and l and return the value
+// This enables us to put in values exactly like in the manual
+// For example EBX[31:22] is get_masked(cpu_info[1], 31, 22)
+inline int32_t get_masked(int32_t val, int32_t h, int32_t l)
+{
+ val &= (0x7FFFFFFF >> (31-(h-l))) << l;
+ return val >> l;
+}
+
+class autoAdjust
+{
+public:
+
+ autoAdjust()
+ {
+ }
+
+ bool printConfig()
+ {
+
+ ConfigEditor configTpl{};
+
+ // load the template of the backend config into a char variable
+ const char *tpl =
+ #include "./config.tpl"
+ ;
+ configTpl.set( std::string(tpl) );
+
+ std::string conf;
+
+ if(!detectL3Size() || L3KB_size < 1024 || L3KB_size > 102400)
+ {
+ if(L3KB_size < 1024 || L3KB_size > 102400)
+ printer::inst()->print_msg(L0, "Autoconf failed: L3 size sanity check failed - %u KB.", L3KB_size);
+
+ conf += std::string(" { \"low_power_mode\" : false, \"no_prefetch\" : true, \"affine_to_cpu\" : false },\n");
+ printer::inst()->print_msg(L0, "Autoconf FAILED. Create config for a single thread. Please try to add new ones until the hashrate slows down.");
+ }
+ else
+ {
+ printer::inst()->print_msg(L0, "Autoconf L3 size detected at %u KB.", L3KB_size);
+
+ detectCPUConf();
+
+ printer::inst()->print_msg(L0, "Autoconf core count detected as %u on %s.", corecnt,
+ linux_layout ? "Linux" : "Windows");
+
+ uint32_t aff_id = 0;
+ for(uint32_t i=0; i < corecnt; i++)
+ {
+ bool double_mode;
+
+ if(L3KB_size <= 0)
+ break;
+
+ double_mode = L3KB_size / 2048 > (int32_t)(corecnt-i);
+
+ conf += std::string(" { \"low_power_mode\" : ");
+ conf += std::string(double_mode ? "true" : "false");
+ conf += std::string(", \"no_prefetch\" : true, \"affine_to_cpu\" : ");
+ conf += std::to_string(aff_id);
+ conf += std::string(" },\n");
+
+ if(!linux_layout || old_amd)
+ {
+ aff_id += 2;
+
+ if(aff_id >= corecnt)
+ aff_id = 1;
+ }
+ else
+ aff_id++;
+
+ if(double_mode)
+ L3KB_size -= 4096;
+ else
+ L3KB_size -= 2048;
+ }
+ }
+
+ configTpl.replace("CPUCONFIG",conf);
+ configTpl.write(Params::inst().configFileCPU);
+ printer::inst()->print_msg(L0, "CPU configuration stored in file '%s'", Params::inst().configFileCPU.c_str());
+
+ return true;
+ }
+
+private:
+ bool detectL3Size()
+ {
+ int32_t cpu_info[4];
+ char cpustr[13] = {0};
+
+ ::jconf::cpuid(0, 0, cpu_info);
+ memcpy(cpustr, &cpu_info[1], 4);
+ memcpy(cpustr+4, &cpu_info[3], 4);
+ memcpy(cpustr+8, &cpu_info[2], 4);
+
+ if(strcmp(cpustr, "GenuineIntel") == 0)
+ {
+ ::jconf::cpuid(4, 3, cpu_info);
+
+ if(get_masked(cpu_info[0], 7, 5) != 3)
+ {
+ printer::inst()->print_msg(L0, "Autoconf failed: Couln't find L3 cache page.");
+ return false;
+ }
+
+ L3KB_size = ((get_masked(cpu_info[1], 31, 22) + 1) * (get_masked(cpu_info[1], 21, 12) + 1) *
+ (get_masked(cpu_info[1], 11, 0) + 1) * (cpu_info[2] + 1)) / 1024;
+
+ return true;
+ }
+ else if(strcmp(cpustr, "AuthenticAMD") == 0)
+ {
+ ::jconf::cpuid(0x80000006, 0, cpu_info);
+
+ L3KB_size = get_masked(cpu_info[3], 31, 18) * 512;
+
+ ::jconf::cpuid(1, 0, cpu_info);
+ if(get_masked(cpu_info[0], 11, 8) < 0x17) //0x17h is Zen
+ old_amd = true;
+
+ return true;
+ }
+ else
+ {
+ printer::inst()->print_msg(L0, "Autoconf failed: Unknown CPU type: %s.", cpustr);
+ return false;
+ }
+ }
+
+ void detectCPUConf()
+ {
+#ifdef _WIN32
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+ corecnt = info.dwNumberOfProcessors;
+ linux_layout = false;
+#else
+ corecnt = sysconf(_SC_NPROCESSORS_ONLN);
+ linux_layout = true;
+#endif // _WIN32
+ }
+
+ int32_t L3KB_size = 0;
+ uint32_t corecnt;
+ bool old_amd = false;
+ bool linux_layout;
+};
+
+} // namespace cpu
+} // namepsace xmrstak
OpenPOWER on IntegriCloud