Added new class Msr.
This commit is contained in:
parent
3730bcd434
commit
c48e2e6af8
8 changed files with 438 additions and 29 deletions
70
src/hw/msr/Msr.cpp
Normal file
70
src/hw/msr/Msr.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "hw/msr/Msr.h"
|
||||
#include "base/io/log/Log.h"
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
static const char *kTag = YELLOW_BG_BOLD(WHITE_BOLD_S " msr ");
|
||||
static std::weak_ptr<Msr> instance;
|
||||
|
||||
|
||||
} // namespace xmrig
|
||||
|
||||
|
||||
|
||||
const char *xmrig::Msr::tag()
|
||||
{
|
||||
return kTag;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::shared_ptr<xmrig::Msr> xmrig::Msr::get()
|
||||
{
|
||||
auto msr = instance.lock();
|
||||
if (!msr) {
|
||||
msr = std::make_shared<Msr>();
|
||||
instance = msr;
|
||||
}
|
||||
|
||||
if (msr->isAvailable()) {
|
||||
return msr;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
xmrig::MsrItem xmrig::Msr::read(uint32_t reg, int32_t cpu, bool verbose) const
|
||||
{
|
||||
uint64_t value = 0;
|
||||
if (rdmsr(reg, cpu, value)) {
|
||||
return { reg, value };
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
LOG_WARN("%s " YELLOW_BOLD("cannot read MSR 0x%08" PRIx32), tag(), reg);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
61
src/hw/msr/Msr.h
Normal file
61
src/hw/msr/Msr.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef XMRIG_MSR_H
|
||||
#define XMRIG_MSR_H
|
||||
|
||||
|
||||
#include "base/tools/Object.h"
|
||||
#include "hw/msr/MsrItem.h"
|
||||
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace xmrig
|
||||
{
|
||||
|
||||
|
||||
class MsrPrivate;
|
||||
|
||||
|
||||
class Msr
|
||||
{
|
||||
public:
|
||||
XMRIG_DISABLE_COPY_MOVE(Msr)
|
||||
|
||||
Msr();
|
||||
~Msr();
|
||||
|
||||
static const char *tag();
|
||||
static std::shared_ptr<Msr> get();
|
||||
|
||||
bool isAvailable() const;
|
||||
MsrItem read(uint32_t reg, int32_t cpu = -1, bool verbose = true) const;
|
||||
|
||||
private:
|
||||
bool rdmsr(uint32_t reg, int32_t cpu, uint64_t &value) const;
|
||||
|
||||
MsrPrivate *d_ptr = nullptr;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace xmrig */
|
||||
|
||||
|
||||
#endif /* XMRIG_MSR_H */
|
64
src/hw/msr/MsrItem.cpp
Normal file
64
src/hw/msr/MsrItem.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "hw/msr/MsrItem.h"
|
||||
#include "3rdparty/rapidjson/document.h"
|
||||
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
xmrig::MsrItem::MsrItem(const rapidjson::Value &value)
|
||||
{
|
||||
if (!value.IsString()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto kv = String(value.GetString()).split(':');
|
||||
if (kv.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_reg = strtoul(kv[0], nullptr, 0);
|
||||
m_value = strtoull(kv[1], nullptr, 0);
|
||||
m_mask = (kv.size() > 2) ? strtoull(kv[2], nullptr, 0) : kNoMask;
|
||||
}
|
||||
|
||||
|
||||
rapidjson::Value xmrig::MsrItem::toJSON(rapidjson::Document &doc) const
|
||||
{
|
||||
return toString().toJSON(doc);
|
||||
}
|
||||
|
||||
|
||||
xmrig::String xmrig::MsrItem::toString() const
|
||||
{
|
||||
constexpr size_t size = 48;
|
||||
|
||||
auto buf = new char[size]();
|
||||
|
||||
if (m_mask != kNoMask) {
|
||||
snprintf(buf, size, "0x%" PRIx32 ":0x%" PRIx64 ":0x%" PRIx64, m_reg, m_value, m_mask);
|
||||
}
|
||||
else {
|
||||
snprintf(buf, size, "0x%" PRIx32 ":0x%" PRIx64, m_reg, m_value);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
65
src/hw/msr/MsrItem.h
Normal file
65
src/hw/msr/MsrItem.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef XMRIG_MSRITEM_H
|
||||
#define XMRIG_MSRITEM_H
|
||||
|
||||
|
||||
#include "base/tools/String.h"
|
||||
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace xmrig
|
||||
{
|
||||
|
||||
|
||||
class MsrItem
|
||||
{
|
||||
public:
|
||||
constexpr static uint64_t kNoMask = std::numeric_limits<uint64_t>::max();
|
||||
|
||||
inline MsrItem() = default;
|
||||
inline MsrItem(uint32_t reg, uint64_t value, uint64_t mask = kNoMask) : m_reg(reg), m_value(value), m_mask(mask) {}
|
||||
|
||||
MsrItem(const rapidjson::Value &value);
|
||||
|
||||
inline bool isValid() const { return m_reg > 0; }
|
||||
inline uint32_t reg() const { return m_reg; }
|
||||
inline uint64_t value() const { return m_value; }
|
||||
inline uint64_t mask() const { return m_mask; }
|
||||
|
||||
rapidjson::Value toJSON(rapidjson::Document &doc) const;
|
||||
String toString() const;
|
||||
|
||||
private:
|
||||
uint32_t m_reg = 0;
|
||||
uint64_t m_value = 0;
|
||||
uint64_t m_mask = kNoMask;
|
||||
};
|
||||
|
||||
|
||||
using MsrItems = std::vector<MsrItem>;
|
||||
|
||||
|
||||
} /* namespace xmrig */
|
||||
|
||||
|
||||
#endif /* XMRIG_MSRITEM_H */
|
86
src/hw/msr/Msr_linux.cpp
Normal file
86
src/hw/msr/Msr_linux.cpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "hw/msr/Msr.h"
|
||||
#include "3rdparty/fmt/core.h"
|
||||
#include "base/io/log/Log.h"
|
||||
|
||||
|
||||
#include <array>
|
||||
#include <cctype>
|
||||
#include <cinttypes>
|
||||
#include <cstdio>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
class MsrPrivate
|
||||
{
|
||||
public:
|
||||
bool available = true;
|
||||
};
|
||||
|
||||
|
||||
} // namespace xmrig
|
||||
|
||||
|
||||
xmrig::Msr::Msr() : d_ptr(new MsrPrivate())
|
||||
{
|
||||
if (system("/sbin/modprobe msr allow_writes=on > /dev/null 2>&1") != 0) {
|
||||
LOG_WARN("%s " YELLOW_BOLD("msr kernel module is not available"), Msr::tag());
|
||||
|
||||
d_ptr->available = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
xmrig::Msr::~Msr()
|
||||
{
|
||||
delete d_ptr;
|
||||
}
|
||||
|
||||
|
||||
bool xmrig::Msr::isAvailable() const
|
||||
{
|
||||
return d_ptr->available;
|
||||
}
|
||||
|
||||
|
||||
bool xmrig::Msr::rdmsr(uint32_t reg, int32_t cpu, uint64_t &value) const
|
||||
{
|
||||
const auto name = fmt::format("/dev/cpu/{}/msr", cpu < 0 ? 0 : cpu);
|
||||
const int fd = open(name.c_str(), O_RDONLY);
|
||||
|
||||
if (fd < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool success = pread(fd, &value, sizeof value, reg) == sizeof value;
|
||||
close(fd);
|
||||
|
||||
return success;
|
||||
}
|
204
src/hw/msr/Msr_win.cpp
Normal file
204
src/hw/msr/Msr_win.cpp
Normal file
|
@ -0,0 +1,204 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "hw/msr/Msr.h"
|
||||
#include "base/io/log/Log.h"
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
#define SERVICE_NAME L"WinRing0_1_2_0"
|
||||
#define IOCTL_READ_MSR CTL_CODE(40000, 0x821, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_WRITE_MSR CTL_CODE(40000, 0x822, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
static const wchar_t *kServiceName = SERVICE_NAME;
|
||||
|
||||
|
||||
class MsrPrivate
|
||||
{
|
||||
public:
|
||||
bool uninstall()
|
||||
{
|
||||
if (driver != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(driver);
|
||||
}
|
||||
|
||||
if (!service) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
|
||||
if (!reuse) {
|
||||
SERVICE_STATUS serviceStatus;
|
||||
|
||||
if (!ControlService(service, SERVICE_CONTROL_STOP, &serviceStatus)) {
|
||||
result = false;
|
||||
}
|
||||
|
||||
if (!DeleteService(service)) {
|
||||
LOG_ERR("%s " RED("failed to remove WinRing0 driver, error %u"), Msr::tag(), GetLastError());
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
CloseServiceHandle(service);
|
||||
service = nullptr;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool reuse = false;
|
||||
HANDLE driver = INVALID_HANDLE_VALUE;
|
||||
SC_HANDLE manager = nullptr;
|
||||
SC_HANDLE service = nullptr;
|
||||
};
|
||||
|
||||
|
||||
} // namespace xmrig
|
||||
|
||||
|
||||
xmrig::Msr::Msr() : d_ptr(new MsrPrivate())
|
||||
{
|
||||
DWORD err = 0;
|
||||
|
||||
d_ptr->manager = OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS);
|
||||
if (!d_ptr->manager) {
|
||||
if ((err = GetLastError()) == ERROR_ACCESS_DENIED) {
|
||||
LOG_WARN("%s " YELLOW_BOLD("to access MSR registers Administrator privileges required."), tag());
|
||||
}
|
||||
else {
|
||||
LOG_ERR("%s " RED("failed to open service control manager, error %u"), tag(), err);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<wchar_t> dir;
|
||||
|
||||
do {
|
||||
dir.resize(dir.empty() ? MAX_PATH : dir.size() * 2);
|
||||
GetModuleFileNameW(nullptr, dir.data(), dir.size());
|
||||
err = GetLastError();
|
||||
} while (err == ERROR_INSUFFICIENT_BUFFER);
|
||||
|
||||
if (err != ERROR_SUCCESS) {
|
||||
LOG_ERR("%s " RED("failed to get path to driver, error %u"), tag(), err);
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto it = dir.end() - 1; it != dir.begin(); --it) {
|
||||
if ((*it == L'\\') || (*it == L'/')) {
|
||||
++it;
|
||||
*it = L'\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const std::wstring path = std::wstring(dir.data()) + L"WinRing0x64.sys";
|
||||
|
||||
d_ptr->service = OpenServiceW(d_ptr->manager, kServiceName, SERVICE_ALL_ACCESS);
|
||||
if (d_ptr->service) {
|
||||
LOG_WARN("%s " YELLOW("service ") YELLOW_BOLD("WinRing0_1_2_0") YELLOW(" already exists"), tag());
|
||||
|
||||
SERVICE_STATUS status;
|
||||
const auto rc = QueryServiceStatus(d_ptr->service, &status);
|
||||
|
||||
if (rc) {
|
||||
DWORD dwBytesNeeded = 0;
|
||||
|
||||
QueryServiceConfigA(d_ptr->service, nullptr, 0, &dwBytesNeeded);
|
||||
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
std::vector<BYTE> buffer(dwBytesNeeded);
|
||||
auto config = reinterpret_cast<LPQUERY_SERVICE_CONFIGA>(buffer.data());
|
||||
|
||||
if (QueryServiceConfigA(d_ptr->service, config, buffer.size(), &dwBytesNeeded)) {
|
||||
LOG_INFO("%s " YELLOW("service path: ") YELLOW_BOLD("\"%s\""), tag(), config->lpBinaryPathName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rc && status.dwCurrentState == SERVICE_RUNNING) {
|
||||
d_ptr->reuse = true;
|
||||
}
|
||||
else if (!d_ptr->uninstall()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!d_ptr->reuse) {
|
||||
d_ptr->service = CreateServiceW(d_ptr->manager, kServiceName, kServiceName, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, path.c_str(), nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
if (!d_ptr->service) {
|
||||
LOG_ERR("%s " RED("failed to install WinRing0 driver, error %u"), tag(), GetLastError());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!StartService(d_ptr->service, 0, nullptr)) {
|
||||
err = GetLastError();
|
||||
if (err != ERROR_SERVICE_ALREADY_RUNNING) {
|
||||
if (err == ERROR_FILE_NOT_FOUND) {
|
||||
LOG_ERR("%s " RED("failed to start WinRing0 driver: ") RED_BOLD("\"WinRing0x64.sys not found\""), tag());
|
||||
}
|
||||
else {
|
||||
LOG_ERR("%s " RED("failed to start WinRing0 driver, error %u"), tag(), err);
|
||||
}
|
||||
|
||||
d_ptr->uninstall();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d_ptr->driver = CreateFileW(L"\\\\.\\" SERVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (d_ptr->driver == INVALID_HANDLE_VALUE) {
|
||||
LOG_ERR("%s " RED("failed to connect to WinRing0 driver, error %u"), tag(), GetLastError());;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
xmrig::Msr::~Msr()
|
||||
{
|
||||
d_ptr->uninstall();
|
||||
|
||||
delete d_ptr;
|
||||
}
|
||||
|
||||
|
||||
bool xmrig::Msr::isAvailable() const
|
||||
{
|
||||
return d_ptr->driver != INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
|
||||
bool xmrig::Msr::rdmsr(uint32_t reg, int32_t, uint64_t &value) const
|
||||
{
|
||||
DWORD size = 0;
|
||||
|
||||
return DeviceIoControl(d_ptr->driver, IOCTL_READ_MSR, ®, sizeof(reg), &value, sizeof(value), &size, nullptr) != 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue