diff options
-rw-r--r-- | physmap.c | 95 |
1 files changed, 85 insertions, 10 deletions
@@ -282,6 +282,8 @@ void *physmap_try_ro(const char *descr, unsigned long phys_addr, size_t len) PHYSMAP_RO); } +/* MSR abstraction implementations for Linux, OpenBSD, FreeBSD/Dragonfly, OSX, libpayload + * and a non-working default implemenation on the bottom. See also hwaccess.h for some (re)declarations. */ #if defined(__i386__) || defined(__x86_64__) #ifdef __linux__ @@ -381,8 +383,83 @@ void cleanup_cpu_msr(void) /* Clear MSR file descriptor. */ fd_msr = -1; } -#else -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) +#elif defined(__OpenBSD__) /* This does only work for certain AMD Geode LX systems see amdmsr(4). */ +#include <sys/ioctl.h> +#include <machine/amdmsr.h> + +static int fd_msr = -1; + +msr_t rdmsr(int addr) +{ + struct amdmsr_req args; + + msr_t msr = { 0xffffffff, 0xffffffff }; + + args.addr = (uint32_t)addr; + + if (ioctl(fd_msr, RDMSR, &args) < 0) { + msg_perr("Error while executing RDMSR ioctl: %s\n", strerror(errno)); + close(fd_msr); + exit(1); + } + + msr.lo = args.val & 0xffffffff; + msr.hi = args.val >> 32; + + return msr; +} + +int wrmsr(int addr, msr_t msr) +{ + struct amdmsr_req args; + + args.addr = addr; + args.val = (((uint64_t)msr.hi) << 32) | msr.lo; + + if (ioctl(fd_msr, WRMSR, &args) < 0) { + msg_perr("Error while executing WRMSR ioctl: %s\n", strerror(errno)); + close(fd_msr); + exit(1); + } + + return 0; +} + +int setup_cpu_msr(int cpu) +{ + char msrfilename[64]; + memset(msrfilename, 0, sizeof(msrfilename)); + snprintf(msrfilename, sizeof(msrfilename), "/dev/amdmsr"); + + if (fd_msr != -1) { + msg_pinfo("MSR was already initialized\n"); + return -1; + } + + fd_msr = open(msrfilename, O_RDWR); + + if (fd_msr < 0) { + msg_perr("Error while opening %s: %s\n", msrfilename, strerror(errno)); + return -1; + } + + return 0; +} + +void cleanup_cpu_msr(void) +{ + if (fd_msr == -1) { + msg_pinfo("No MSR initialized.\n"); + return; + } + + close(fd_msr); + + /* Clear MSR file descriptor. */ + fd_msr = -1; +} + +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) #include <sys/ioctl.h> typedef struct { @@ -465,9 +542,8 @@ void cleanup_cpu_msr(void) fd_msr = -1; } -#else - -#if defined(__MACH__) && defined(__APPLE__) +#elif defined(__MACH__) && defined(__APPLE__) +/* rdmsr() and wrmsr() are provided by DirectHW which needs neither setup nor cleanup. */ int setup_cpu_msr(int cpu) { // Always succeed for now @@ -494,6 +570,7 @@ int libpayload_wrmsr(int addr, msr_t msr) return 0; } #else +/* default MSR implementation */ msr_t rdmsr(int addr) { msr_t ret = { 0xffffffff, 0xffffffff }; @@ -516,9 +593,7 @@ void cleanup_cpu_msr(void) { // Nothing, yet. } -#endif -#endif -#endif -#else +#endif // OS switches for MSR code +#else // x86 /* Does MSR exist on non-x86 architectures? */ -#endif +#endif // arch switches for MSR code |