NB: On other systems the code is not equal to the default implementation, but should not explode because setup_cpu_msr() returns an error and therefore no other functions should be called. --- The whole code needs some refactoring: - error handling for rdmsr (e.g. add msr_t *parameter and return int instead) - lots of duplicate code...
Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at --- physmap.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 84 insertions(+), 10 deletions(-)
diff --git a/physmap.c b/physmap.c index 4ebfb06..f625b5a 100644 --- a/physmap.c +++ b/physmap.c @@ -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) +{ + 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) +{ + cpu_msr_args_t args; + + args.msr = 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%d", cpu); + + 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,7 @@ void cleanup_cpu_msr(void) fd_msr = -1; }
-#else - -#if defined(__MACH__) && defined(__APPLE__) +#elif defined(__MACH__) && defined(__APPLE__) int setup_cpu_msr(int cpu) { // Always succeed for now @@ -494,6 +569,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 +592,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