1ea7e5fe0Smrg/* 2ea7e5fe0Smrg * Copyright (c) 2008 Advanced Micro Devices, Inc. 3ea7e5fe0Smrg * 4ea7e5fe0Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5ea7e5fe0Smrg * copy of this software and associated documentation files (the "Software"), 6ea7e5fe0Smrg * to deal in the Software without restriction, including without limitation 7ea7e5fe0Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8ea7e5fe0Smrg * and/or sell copies of the Software, and to permit persons to whom the 9ea7e5fe0Smrg * Software is furnished to do so, subject to the following conditions: 10ea7e5fe0Smrg * 11ea7e5fe0Smrg * The above copyright notice and this permission notice shall be included in 12ea7e5fe0Smrg * all copies or substantial portions of the Software. 13ea7e5fe0Smrg * 14ea7e5fe0Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15ea7e5fe0Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16ea7e5fe0Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17ea7e5fe0Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18ea7e5fe0Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19ea7e5fe0Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20ea7e5fe0Smrg * DEALINGS IN THE SOFTWARE. 21ea7e5fe0Smrg * 22ea7e5fe0Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 23ea7e5fe0Smrg * contributors may be used to endorse or promote products derived from this 24ea7e5fe0Smrg * software without specific prior written permission. 25ea7e5fe0Smrg */ 26ea7e5fe0Smrg 27ea7e5fe0Smrg#ifdef HAVE_CONFIG_H 28ea7e5fe0Smrg#include "config.h" 29ea7e5fe0Smrg#endif 30ea7e5fe0Smrg 31f29dbc25Smrg#include <stdio.h> 32f29dbc25Smrg#include <unistd.h> 33f29dbc25Smrg#include <fcntl.h> 34f29dbc25Smrg#include <sys/types.h> 35f29dbc25Smrg#include <errno.h> 36621ff18cSmrg 37621ff18cSmrg#ifdef __OpenBSD__ 38621ff18cSmrg#include <sys/ioctl.h> 39621ff18cSmrg#include <machine/amdmsr.h> 40621ff18cSmrg#endif 41621ff18cSmrg 4244802259Smrg#ifdef __FreeBSD__ 4344802259Smrg#include <sys/ioctl.h> 4444802259Smrg#include <sys/cpuctl.h> 4544802259Smrg#endif 4644802259Smrg 4700be8644Schristos#include "xorg-server.h" 4800be8644Schristos 49f29dbc25Smrg#include "os.h" 50f29dbc25Smrg#include "geode.h" 51f29dbc25Smrg 52621ff18cSmrg#ifdef __OpenBSD__ 53621ff18cSmrg#define _PATH_MSRDEV "/dev/amdmsr" 54621ff18cSmrg#define X_PRIVSEP 5544802259Smrg#elif defined __FreeBSD__ 5644802259Smrg#define _PATH_MSRDEV "/dev/cpuctl0" 57621ff18cSmrg#else 58621ff18cSmrg#define _PATH_MSRDEV "/dev/cpu/0/msr" 59621ff18cSmrg#endif 60621ff18cSmrg 61f29dbc25Smrgstatic int 62f29dbc25Smrg_msr_open(void) 63f29dbc25Smrg{ 64f29dbc25Smrg static int msrfd = 0; 65f29dbc25Smrg 66f29dbc25Smrg if (msrfd == 0) { 67621ff18cSmrg#ifdef X_PRIVSEP 68621ff18cSmrg msrfd = priv_open_device(_PATH_MSRDEV); 69621ff18cSmrg#else 70621ff18cSmrg msrfd = open(_PATH_MSRDEV, O_RDWR); 71621ff18cSmrg#endif 72ea7e5fe0Smrg if (msrfd == -1) 73621ff18cSmrg FatalError("Unable to open %s: %s\n", _PATH_MSRDEV, 74621ff18cSmrg strerror(errno)); 75f29dbc25Smrg } 76f29dbc25Smrg 77f29dbc25Smrg return msrfd; 78f29dbc25Smrg} 79f29dbc25Smrg 80f29dbc25Smrgint 81f29dbc25SmrgGeodeReadMSR(unsigned long addr, unsigned long *lo, unsigned long *hi) 82f29dbc25Smrg{ 83621ff18cSmrg#ifdef __OpenBSD__ 84621ff18cSmrg struct amdmsr_req req; 85621ff18cSmrg int fd = _msr_open(); 86621ff18cSmrg 87621ff18cSmrg req.addr = addr; 88621ff18cSmrg 89621ff18cSmrg if (ioctl(fd, RDMSR, &req) == -1) 90621ff18cSmrg FatalError("Unable to read MSR at address %0x06x: %s\n", addr, 91621ff18cSmrg strerror(errno)); 92621ff18cSmrg 93621ff18cSmrg *hi = req.val >> 32; 94621ff18cSmrg *lo = req.val & 0xffffffff; 9544802259Smrg#elif defined __FreeBSD__ 9644802259Smrg cpuctl_msr_args_t args; 9744802259Smrg int fd = _msr_open(); 9844802259Smrg 9944802259Smrg args.msr = addr; 10044802259Smrg 10144802259Smrg if (ioctl(fd, CPUCTL_RDMSR, &args) == -1) 10244802259Smrg FatalError("Unable to read MSR at address %0x06x: %s\n", addr, 10344802259Smrg strerror(errno)); 10444802259Smrg 10544802259Smrg *hi = args.data >> 32; 10644802259Smrg *lo = args.data & 0xffffffff; 107cf0238e3Snia#elif defined __NetBSD__ 108cf0238e3Snia return -1; /* fall back to assembly on NetBSD */ 109621ff18cSmrg#else 110f29dbc25Smrg unsigned int data[2]; 111f29dbc25Smrg int fd = _msr_open(); 112f29dbc25Smrg int ret; 113f29dbc25Smrg 114f29dbc25Smrg if (fd == -1) 115ea7e5fe0Smrg return -1; 116f29dbc25Smrg 117ea7e5fe0Smrg ret = lseek(fd, (off_t) addr, SEEK_SET); 118f29dbc25Smrg 119f29dbc25Smrg if (ret == -1) 120ea7e5fe0Smrg return -1; 121f29dbc25Smrg 122ea7e5fe0Smrg ret = read(fd, (void *) data, sizeof(data)); 123f29dbc25Smrg 124f29dbc25Smrg if (ret != 8) 125ea7e5fe0Smrg return -1; 126f29dbc25Smrg 127f29dbc25Smrg *hi = data[1]; 128f29dbc25Smrg *lo = data[0]; 129621ff18cSmrg#endif 130f29dbc25Smrg return 0; 131f29dbc25Smrg} 132f29dbc25Smrg 133f29dbc25Smrgint 134f29dbc25SmrgGeodeWriteMSR(unsigned long addr, unsigned long lo, unsigned long hi) 135f29dbc25Smrg{ 136621ff18cSmrg#ifdef __OpenBSD__ 137621ff18cSmrg struct amdmsr_req req; 138621ff18cSmrg int fd = _msr_open(); 139621ff18cSmrg 140621ff18cSmrg req.addr = addr; 141621ff18cSmrg req.val = (u_int64_t) hi << 32 | (u_int64_t)lo; 142621ff18cSmrg 143621ff18cSmrg if (ioctl(fd, WRMSR, &req) == -1) 144621ff18cSmrg FatalError("Unable to write MSR at address 0x%06x: %s\n", addr, 145621ff18cSmrg strerror(errno)); 14644802259Smrg#elif defined __FreeBSD__ 14744802259Smrg cpuctl_msr_args_t args; 14844802259Smrg int fd = _msr_open(); 14944802259Smrg 15044802259Smrg args.msr = addr; 15144802259Smrg args.data = (u_int64_t) hi << 32 | (u_int64_t)lo; 15244802259Smrg 15344802259Smrg if (ioctl(fd, CPUCTL_WRMSR, &args) == -1) 15444802259Smrg FatalError("Unable to write MSR at address 0x%06x: %s\n", addr, 15544802259Smrg strerror(errno)); 156cf0238e3Snia#elif defined __NetBSD__ 157cf0238e3Snia return -1; /* fall back to assembly on NetBSD */ 158621ff18cSmrg#else 159f29dbc25Smrg unsigned int data[2]; 160f29dbc25Smrg int fd = _msr_open(); 161f29dbc25Smrg 162f29dbc25Smrg if (fd == -1) 163ea7e5fe0Smrg return -1; 164f29dbc25Smrg 165ea7e5fe0Smrg if (lseek(fd, (off_t) addr, SEEK_SET) == -1) 166ea7e5fe0Smrg return -1; 167f29dbc25Smrg 168f29dbc25Smrg data[0] = lo; 169f29dbc25Smrg data[1] = hi; 170f29dbc25Smrg 171ea7e5fe0Smrg if (write(fd, (void *) data, 8) != 8) 172ea7e5fe0Smrg return -1; 173621ff18cSmrg#endif 174f29dbc25Smrg return 0; 175f29dbc25Smrg} 176