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#elif defined __NetBSD__ 108 return -1; /* fall back to assembly on NetBSD */ 109#else 110 unsigned int data[2]; 111 int fd = _msr_open(); 112 int ret; 113 114 if (fd == -1) 115 return -1; 116 117 ret = lseek(fd, (off_t) addr, SEEK_SET); 118 119 if (ret == -1) 120 return -1; 121 122 ret = read(fd, (void *) data, sizeof(data)); 123 124 if (ret != 8) 125 return -1; 126 127 *hi = data[1]; 128 *lo = data[0]; 129#endif 130 return 0; 131} 132 133int 134GeodeWriteMSR(unsigned long addr, unsigned long lo, unsigned long hi) 135{ 136#ifdef __OpenBSD__ 137 struct amdmsr_req req; 138 int fd = _msr_open(); 139 140 req.addr = addr; 141 req.val = (u_int64_t) hi << 32 | (u_int64_t)lo; 142 143 if (ioctl(fd, WRMSR, &req) == -1) 144 FatalError("Unable to write MSR at address 0x%06x: %s\n", addr, 145 strerror(errno)); 146#elif defined __FreeBSD__ 147 cpuctl_msr_args_t args; 148 int fd = _msr_open(); 149 150 args.msr = addr; 151 args.data = (u_int64_t) hi << 32 | (u_int64_t)lo; 152 153 if (ioctl(fd, CPUCTL_WRMSR, &args) == -1) 154 FatalError("Unable to write MSR at address 0x%06x: %s\n", addr, 155 strerror(errno)); 156#elif defined __NetBSD__ 157 return -1; /* fall back to assembly on NetBSD */ 158#else 159 unsigned int data[2]; 160 int fd = _msr_open(); 161 162 if (fd == -1) 163 return -1; 164 165 if (lseek(fd, (off_t) addr, SEEK_SET) == -1) 166 return -1; 167 168 data[0] = lo; 169 data[1] = hi; 170 171 if (write(fd, (void *) data, 8) != 8) 172 return -1; 173#endif 174 return 0; 175} 176