geode_msr.c revision 00be8644
1/* 2 * Copyright (c) 2008 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 * 22 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 23 * contributors may be used to endorse or promote products derived from this 24 * software without specific prior written permission. 25 */ 26 27#ifdef HAVE_CONFIG_H 28#include "config.h" 29#endif 30 31#include <stdio.h> 32#include <unistd.h> 33#include <fcntl.h> 34#include <sys/types.h> 35#include <errno.h> 36 37#ifdef __OpenBSD__ 38#include <sys/ioctl.h> 39#include <machine/amdmsr.h> 40#endif 41 42#ifdef __FreeBSD__ 43#include <sys/ioctl.h> 44#include <sys/cpuctl.h> 45#endif 46 47#include "xorg-server.h" 48 49#include "os.h" 50#include "geode.h" 51 52#ifdef __OpenBSD__ 53#define _PATH_MSRDEV "/dev/amdmsr" 54#define X_PRIVSEP 55#elif defined __FreeBSD__ 56#define _PATH_MSRDEV "/dev/cpuctl0" 57#else 58#define _PATH_MSRDEV "/dev/cpu/0/msr" 59#endif 60 61static int 62_msr_open(void) 63{ 64 static int msrfd = 0; 65 66 if (msrfd == 0) { 67#ifdef X_PRIVSEP 68 msrfd = priv_open_device(_PATH_MSRDEV); 69#else 70 msrfd = open(_PATH_MSRDEV, O_RDWR); 71#endif 72 if (msrfd == -1) 73 FatalError("Unable to open %s: %s\n", _PATH_MSRDEV, 74 strerror(errno)); 75 } 76 77 return msrfd; 78} 79 80int 81GeodeReadMSR(unsigned long addr, unsigned long *lo, unsigned long *hi) 82{ 83#ifdef __OpenBSD__ 84 struct amdmsr_req req; 85 int fd = _msr_open(); 86 87 req.addr = addr; 88 89 if (ioctl(fd, RDMSR, &req) == -1) 90 FatalError("Unable to read MSR at address %0x06x: %s\n", addr, 91 strerror(errno)); 92 93 *hi = req.val >> 32; 94 *lo = req.val & 0xffffffff; 95#elif defined __FreeBSD__ 96 cpuctl_msr_args_t args; 97 int fd = _msr_open(); 98 99 args.msr = addr; 100 101 if (ioctl(fd, CPUCTL_RDMSR, &args) == -1) 102 FatalError("Unable to read MSR at address %0x06x: %s\n", addr, 103 strerror(errno)); 104 105 *hi = args.data >> 32; 106 *lo = args.data & 0xffffffff; 107#else 108 unsigned int data[2]; 109 int fd = _msr_open(); 110 int ret; 111 112 if (fd == -1) 113 return -1; 114 115 ret = lseek(fd, (off_t) addr, SEEK_SET); 116 117 if (ret == -1) 118 return -1; 119 120 ret = read(fd, (void *) data, sizeof(data)); 121 122 if (ret != 8) 123 return -1; 124 125 *hi = data[1]; 126 *lo = data[0]; 127#endif 128 return 0; 129} 130 131int 132GeodeWriteMSR(unsigned long addr, unsigned long lo, unsigned long hi) 133{ 134#ifdef __OpenBSD__ 135 struct amdmsr_req req; 136 int fd = _msr_open(); 137 138 req.addr = addr; 139 req.val = (u_int64_t) hi << 32 | (u_int64_t)lo; 140 141 if (ioctl(fd, WRMSR, &req) == -1) 142 FatalError("Unable to write MSR at address 0x%06x: %s\n", addr, 143 strerror(errno)); 144#elif defined __FreeBSD__ 145 cpuctl_msr_args_t args; 146 int fd = _msr_open(); 147 148 args.msr = addr; 149 args.data = (u_int64_t) hi << 32 | (u_int64_t)lo; 150 151 if (ioctl(fd, CPUCTL_WRMSR, &args) == -1) 152 FatalError("Unable to write MSR at address 0x%06x: %s\n", addr, 153 strerror(errno)); 154#else 155 unsigned int data[2]; 156 int fd = _msr_open(); 157 158 if (fd == -1) 159 return -1; 160 161 if (lseek(fd, (off_t) addr, SEEK_SET) == -1) 162 return -1; 163 164 data[0] = lo; 165 data[1] = hi; 166 167 if (write(fd, (void *) data, 8) != 8) 168 return -1; 169#endif 170 return 0; 171} 172