Skip to content

Instantly share code, notes, and snippets.

@qodroi
Created September 23, 2022 05:38
Show Gist options
  • Save qodroi/cb6e5f95b63f0d56756da2996de19618 to your computer and use it in GitHub Desktop.
Save qodroi/cb6e5f95b63f0d56756da2996de19618 to your computer and use it in GitHub Desktop.
Read MSRs by accessing the Linux-provided CPU MSR device interface
/**
* Copyright 2022 Roi L.
* SPDX-License-Identifier: GPL-3.0-only
*
* Read Machine-Specific-Register values by accessing the Linux-provided CPU MSR interface.
*/
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <inttypes.h>
enum Bool { FALSE, TRUE }; /* Just cause */
#define MAX_F_SIZE (20)
#define CPU_ID_MSR (1u << (5))
#define DIE(msg) do { \
printf("%s\n", msg); exit(-1); \
} while (0)
#define ASSERT(expr) assert(expr)
#define CRAFT_PATH(buffer, cpun) \
snprintf(buffer, MAX_F_SIZE, "/dev/cpu/%d/msr", cpun);
static char f[MAX_F_SIZE]; /* Global MSR path, replaced on each call if needed */
static uint64_t pread_msr(off_t reg_offset, int cpun)
{
int msfd;
uint64_t data = 0;
CRAFT_PATH(f, cpun);
if ((msfd = open(f, O_RDONLY)) == -1)
DIE("Failed to open MSR file.");
if (pread(msfd, &data, sizeof(data), reg_offset) < 0)
DIE("Failed to pread MSR value.");
close(msfd);
return data;
}
/* Make sure our CPU has MSR support via cpuid */
static inline int CPU_MSR_SUPPORT(void)
{
uint32_t edx, eax = 1;
asm volatile(".byte 0x0f, 0xa2" : "=d"(edx) : "0"(eax));
return (edx & CPU_ID_MSR) ? TRUE : FALSE;
}
int main(int argc, char const *argv[])
{
ASSERT(CPU_MSR_SUPPORT() == TRUE);
if (argc < 3) DIE("Usage: ./main <CPU NUMBER> <MSR_ADDRESS>");
uint64_t data;
data = pread_msr(strtol(argv[2], NULL, 16), atoi(argv[1]));
if (data)
printf("%" PRIx64 "\n", data);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment