diff --git a/util/msrtool/Makefile.in b/util/msrtool/Makefile.in index f20dd9fe1a..4e0e3814fb 100644 --- a/util/msrtool/Makefile.in +++ b/util/msrtool/Makefile.in @@ -27,7 +27,7 @@ CFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ TARGETS = geodelx.o cs5536.o k8.o -SYSTEMS = linux.o darwin.o +SYSTEMS = linux.o darwin.o freebsd.o OBJS = $(PROGRAM).o msrutils.o sys.o $(SYSTEMS) $(TARGETS) all: $(PROGRAM) diff --git a/util/msrtool/freebsd.c b/util/msrtool/freebsd.c new file mode 100644 index 0000000000..912e1c9bac --- /dev/null +++ b/util/msrtool/freebsd.c @@ -0,0 +1,105 @@ +/* + * This file is part of msrtool. + * + * Copyright (c) 2009 Andriy Gapon + * Copyright (c) 2009 Peter Stuge + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#include "msrtool.h" + +static int msr_fd[MAX_CORES] = {-1, -1, -1, -1, -1, -1, -1, -1}; + +int freebsd_probe(const struct sysdef *system) +{ +#ifdef __FreeBSD__ + struct stat st; + + return stat("/dev/cpuctl0", &st) == 0; +#else + return 0; +#endif +} + +int freebsd_open(uint8_t cpu, enum SysModes mode) +{ +#ifdef __FreeBSD__ + int flags; + char devname[32]; + + if (cpu >= MAX_CORES) + return 0; + + if (SYS_RDWR == mode) + flags = O_RDWR; + else if (SYS_WRONLY == mode) + flags = O_WRONLY; + else + flags = O_RDONLY; + + snprintf(devname, sizeof(devname), "/dev/cpuctl%u", cpu); + msr_fd[cpu] = open(devname, flags); + if (msr_fd[cpu] < 0) { + perror(devname); + return 0; + } + return 1; +#else + return 0; +#endif +} + +int freebsd_close(uint8_t cpu) +{ + if (cpu >= MAX_CORES) + return 0; + + if (msr_fd[cpu] != -1) + close(msr_fd[cpu]); + msr_fd[cpu] = -1; + return 1; +} + +int freebsd_rdmsr(uint8_t cpu, uint32_t addr, struct msr *val) +{ +#ifdef __FreeBSD__ + cpuctl_msr_args_t args; + + if (cpu >= MAX_CORES) + return 0; + + if (msr_fd[cpu] < 0) + return 0; + + args.msr = addr; + if (ioctl(msr_fd[cpu], CPUCTL_RDMSR, &args) < 0) { + perror("ioctl(CPUCTL_RDMSR)"); + return 0; + } + + val->hi = args.data >> 32; + val->lo = args.data & 0xffffffff; + return 1; +#else + return 0; +#endif +} diff --git a/util/msrtool/msrtool.c b/util/msrtool/msrtool.c index 251da40d99..4ed86baf58 100644 --- a/util/msrtool/msrtool.c +++ b/util/msrtool/msrtool.c @@ -49,6 +49,7 @@ static struct targetdef alltargets[] = { static struct sysdef allsystems[] = { { "linux", "Linux with /dev/cpu/*/msr", linux_probe, linux_open, linux_close, linux_rdmsr }, { "darwin", "OS X with DirectIO", darwin_probe, darwin_open, darwin_close, darwin_rdmsr }, + { "freebsd", "FreeBSD with /dev/cpuctl*", freebsd_probe, freebsd_open, freebsd_close, freebsd_rdmsr }, { SYSTEM_EOT } }; diff --git a/util/msrtool/msrtool.h b/util/msrtool/msrtool.h index fa37c8507a..c2cd6cb3a8 100644 --- a/util/msrtool/msrtool.h +++ b/util/msrtool/msrtool.h @@ -28,6 +28,10 @@ #define __DARWIN__ #include #endif +#if defined(__FreeBSD__) +#include +#include +#endif #include #define HEXCHARS "0123456789abcdefABCDEF" @@ -186,6 +190,12 @@ extern int darwin_open(uint8_t cpu, enum SysModes mode); extern int darwin_close(uint8_t cpu); extern int darwin_rdmsr(uint8_t cpu, uint32_t addr, struct msr *val); +/* freebsd.c */ +extern int freebsd_probe(const struct sysdef *system); +extern int freebsd_open(uint8_t cpu, enum SysModes mode); +extern int freebsd_close(uint8_t cpu); +extern int freebsd_rdmsr(uint8_t cpu, uint32_t addr, struct msr *val); + /** target externs **/ /* geodelx.c */