From dad1e3091f2d9a3fc03b9ca83c2990e23b4ea32c Mon Sep 17 00:00:00 2001 From: Peter Stuge Date: Sat, 22 Nov 2008 17:13:36 +0000 Subject: msrtool: Release Candidate 1 msrtool can decode MSRs and print the value of every field in human readable form. It can also be used to save a set of MSRs to a file, and at a later time compare the saved values with current values in hardware. Signed-off-by: Peter Stuge Acked-by: Stefan Reinauer git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3766 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- util/msrtool/COPYING | 339 ++++++++++++++++++++++++++++++++++++++++ util/msrtool/Makefile.in | 66 ++++++++ util/msrtool/TODO | 8 + util/msrtool/configure | 162 +++++++++++++++++++ util/msrtool/cs5536.c | 29 ++++ util/msrtool/geodelx.c | 104 ++++++++++++ util/msrtool/linux.c | 88 +++++++++++ util/msrtool/msrtool.c | 399 +++++++++++++++++++++++++++++++++++++++++++++++ util/msrtool/msrtool.h | 183 ++++++++++++++++++++++ util/msrtool/msrutils.c | 299 +++++++++++++++++++++++++++++++++++ util/msrtool/sys.c | 42 +++++ 11 files changed, 1719 insertions(+) create mode 100644 util/msrtool/COPYING create mode 100644 util/msrtool/Makefile.in create mode 100644 util/msrtool/TODO create mode 100755 util/msrtool/configure create mode 100644 util/msrtool/cs5536.c create mode 100644 util/msrtool/geodelx.c create mode 100644 util/msrtool/linux.c create mode 100644 util/msrtool/msrtool.c create mode 100644 util/msrtool/msrtool.h create mode 100644 util/msrtool/msrutils.c create mode 100644 util/msrtool/sys.c (limited to 'util/msrtool') diff --git a/util/msrtool/COPYING b/util/msrtool/COPYING new file mode 100644 index 0000000000..d511905c16 --- /dev/null +++ b/util/msrtool/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/util/msrtool/Makefile.in b/util/msrtool/Makefile.in new file mode 100644 index 0000000000..4972a25f0a --- /dev/null +++ b/util/msrtool/Makefile.in @@ -0,0 +1,66 @@ +# Makefile for msrtool +# +# This file is part of msrtool. +# +# Copyright (c) 2008 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 +# + +PROGRAM = msrtool + +CC = @CC@ +INSTALL = @INSTALL@ +PREFIX = @PREFIX@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ + +TARGETS = geodelx.o cs5536.o +SYSTEMS = linux.o +OBJS = $(PROGRAM).o msrutils.o sys.o $(SYSTEMS) $(TARGETS) + +all: $(PROGRAM) + +$(PROGRAM): $(OBJS) Makefile.deps + $(CC) -o $@ $(OBJS) $(LDFLAGS) + +$(PROGRAM).o: $(PROGRAM).c + $(CC) $(CFLAGS) -DVERSION='"@VERSION@"' -c $< -o $@ + +install: $(PROGRAM) + $(INSTALL) $(PROGRAM) $(PREFIX)/sbin + mkdir -p $(PREFIX)/share/man/man8 + $(INSTALL) $(PROGRAM).8 $(PREFIX)/share/man/man8 + +distprep: distclean Makefile.deps + +clean: + rm -f $(PROGRAM) $(OBJS) + +distclean: clean + rm -f Makefile + +mrproper: distclean + rm -f Makefile.deps + +dep: + rm -f Makefile.deps + $(MAKE) Makefile.deps + +Makefile.deps: $(patsubst %.o,%.c,$(OBJS)) + $(CC) -MM $^ > $@ + +.PHONY: all distprep clean distclean mrproper dep + +-include Makefile.deps diff --git a/util/msrtool/TODO b/util/msrtool/TODO new file mode 100644 index 0000000000..c701e72896 --- /dev/null +++ b/util/msrtool/TODO @@ -0,0 +1,8 @@ +Systems +------- +FreeBSD #defines: see svn diff -r 3697:3698 util/ + +Other ideas +----------- +Move MSR definitions and probe instructions into an external text file? +Handle PCI registers as well? diff --git a/util/msrtool/configure b/util/msrtool/configure new file mode 100755 index 0000000000..f627a6541f --- /dev/null +++ b/util/msrtool/configure @@ -0,0 +1,162 @@ +#!/bin/sh +# +# This file is part of msrtool. +# +# Copyright (c) 2008 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 +# + +# If this is left unset, try to set the version string from the highest +# revision number of the checked out files later. +VERSION="" + +REV="$(svnversion -c . 2>/dev/null)"; REV="${REV/*:}" +VERSION="${VERSION:-$REV}" + +function findprog() { + local WHAT FROMENV FILE + WHAT="${1}" + shift + FROMENV="${1}" + shift + echo -n "searching for ${WHAT} (${*})..." 1>&2 + test -n "${FROMENV}" && { + echo " using environment: ${FROMENV}" 1>&2 + echo "${FROMENV}" + exit 0 + } + for parm in $(seq 0 $#); do + test -z "${1}" && { + shift + continue + } + FILE="$(which "${1}" 2>/dev/null)" + test $? -eq 0 && { + echo "${1}" + break + } + shift + done + test -z "${1}" && { + echo " not found!" 1>&2 + echo 1>&2 + echo "This is a fatal error, configure is exiting!" 1>&2 + exit 1 + } + echo " using ${FILE} in PATH" 1>&2 + exit 0 +} + +function trycompile() { + local WHAT OUT + WHAT="${1}" + shift + echo -n "finding CFLAGS for ${WHAT}... " 1>&2 + OUT="${OUT}\n${CC} ${CFLAGS} -o .config.o -c .config.c" + OUT="${OUT}\n$(${CC} ${CFLAGS} -o .config.o -c .config.c 2>&1)" + test $? -eq 0 && { + echo " using: ${CFLAGS}" 1>&2 + echo "${CFLAGS}" + exit 0 + } + for parm in $(seq 1 $#); do + OUT="${OUT}\n${CC} ${CFLAGS} ${1} -o .config.o -c .config.c 2>&1" + OUT="${OUT}\n$(${CC} ${CFLAGS} ${1} -o .config.o -c .config.c 2>&1)" + test $? -eq 0 && { + echo " using: ${CFLAGS} ${1}" 1>&2 + echo "${CFLAGS} ${1}" + exit 0 + } + shift + done + echo "failed!" 1>&2 + echo 1>&2 + echo -n "The following compiler commands were executed:" 1>&2 + echo -e "${OUT}\n" 1>&2 + echo "This is a fatal error, configure is exiting!" 1>&2 + echo 1>&2 + echo "You can try to fix this by manually setting CFLAGS in the environment before" 1>&2 + echo "running configure. E.g.:" 1>&2 + echo "CFLAGS=-I/opt/somedir/include ${0}" 1>&2 + echo 1>&2 + exit 1 +} + +function trylink() { + local WHAT OUT + WHAT="${1}" + shift + echo -n "finding LDFLAGS for ${WHAT}... " 1>&2 + OUT="${OUT}\n${CC} -o .config .config.o ${LDFLAGS} 2>&1" + OUT="${OUT}\n$(${CC} -o .config .config.o ${LDFLAGS} 2>&1)" + test $? -eq 0 && { + echo " using: ${LDFLAGS}" 1>&2 + echo "${LDFLAGS}" + exit 0 + } + for parm in $(seq 1 $#); do + OUT="${OUT}\n${CC} -o .config .config.o ${LDFLAGS} ${1} 2>&1" + OUT="${OUT}\n$(${CC} -o .config .config.o ${LDFLAGS} ${1} 2>&1)" + test $? -eq 0 && { + echo " using: ${LDFLAGS} ${1}" 1>&2 + echo "${LDFLAGS} ${1}" + exit 0 + } + shift + done + echo "failed!" 1>&2 + echo 1>&2 + echo -n "The following linker commands were executed:" 1>&2 + echo -e "${OUT}\n" 1>&2 + echo "This is a fatal error, configure is exiting!" 1>&2 + echo 1>&2 + echo "You can try to fix this by manually setting LDFLAGS in the environment before" 1>&2 + echo "running configure. E.g.:" 1>&2 + echo "LDFLAGS=-L/opt/somedir/lib ${0}" 1>&2 + echo 1>&2 + exit 1 +} + +CC=$(findprog "compiler" "${CC}" gcc cc icc) || exit +INSTALL=$(findprog "install" "${INSTALL}" install ginstall) || exit + +test -n "$DEBUG" && myCFLAGS="-O2 -g" || myCFLAGS="-Os" +CFLAGS="${CFLAGS} ${myCFLAGS} -Wall -Werror" + +PREFIX="${PREFIX:-/usr/local}" + +OS_ARCH=$(uname) + +echo +echo "configured using the following settings:" +echo +echo "VERSION=${VERSION}" +echo "CC=${CC}" +echo "CFLAGS=${CFLAGS}" +echo "LDFLAGS=${LDFLAGS}" +echo "INSTALL=${INSTALL}" +echo "PREFIX=${PREFIX}" +echo +echo -n "creating Makefile..." +echo "# This file was automatically generated by configure" > Makefile +sed -e "s#@VERSION@#${VERSION}#g" \ + -e "s#@CC@#${CC}#g" \ + -e "s#@CFLAGS@#${CFLAGS}#g" \ + -e "s#@LDFLAGS@#${LDFLAGS}#g" \ + -e "s#@INSTALL@#${INSTALL}#g" \ + -e "s#@PREFIX@#/usr/local#g" \ + Makefile.in >> Makefile +echo " done" +echo diff --git a/util/msrtool/cs5536.c b/util/msrtool/cs5536.c new file mode 100644 index 0000000000..d441891a3f --- /dev/null +++ b/util/msrtool/cs5536.c @@ -0,0 +1,29 @@ +/* + * This file is part of msrtool. + * + * Copyright (c) 2008 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 "msrtool.h" + +int cs5536_probe(const struct targetdef *target) { + /* TODO: PCI 1022:2090 */ + return 0; +} + +const struct msrdef cs5536_msrs[] = { + { MSR_EOT } +}; diff --git a/util/msrtool/geodelx.c b/util/msrtool/geodelx.c new file mode 100644 index 0000000000..db4f0fc5f2 --- /dev/null +++ b/util/msrtool/geodelx.c @@ -0,0 +1,104 @@ +/* + * This file is part of msrtool. + * + * Copyright (c) 2008 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 "msrtool.h" + +int geodelx_probe(const struct targetdef *target) { + struct cpuid_t *id = cpuid(); + return 10 == id->family && 5 == id->model; +} + +const struct msrdef geodelx_msrs[] = { + { 0x4c00000f, MSRTYPE_RDWR, MSR2(0, 0), "GLCP_DELAY_CONTROLS", "GLCP I/O Delay Controls", { + { 63, 1, "EN", "Enable", PRESENT_DEC, { + { MSR1(0), "Use default values" }, + { MSR1(1), "Use value in bits [62:0]" }, + { BITVAL_EOT } + }}, + { 62, 1, "B_DQ", "Buffer Control for DQ DQS DQM TLA drive", PRESENT_DEC, { + { MSR1(1), "Half power" }, + { MSR1(0), "Quarter power" }, + { BITVAL_EOT } + }}, + { 61, 1, "B_CMD", "Buffer Control for RAS CAS CKE CS WE drive", PRESENT_DEC, { + { MSR1(1), "Half power" }, + { MSR1(0), "Quarter power" }, + { BITVAL_EOT } + }}, + { 60, 1, "B_MA", "Buffer Control for MA BA drive", PRESENT_DEC, { + { MSR1(0), "Half power" }, + { MSR1(1), "Full power" }, + { BITVAL_EOT } + }}, + { 59, 1, "SDCLK_SET", "SDCLK Setup", PRESENT_DEC, { + { MSR1(0), "Full SDCLK setup" }, + { MSR1(1), "Half SDCLK setup for control signals" }, + { BITVAL_EOT } + }}, + { 58, 3, "DDR_RLE", "DDR read latch enable position", PRESENT_DEC, NOBITS }, + { 55, 1, "SDCLK_DIS", "SDCLK disable [1,3,5]", PRESENT_DEC, { + { MSR1(0), "All SDCLK output" }, + { MSR1(1), "SDCLK[0,2,4] output only" }, + { BITVAL_EOT } + }}, + { 54, 3, "TLA1_OA", "TLA hint pin output adjust", PRESENT_DEC, NOBITS }, + { 51, 2, "D_TLA1", "Output delay for TLA1", PRESENT_DEC, NOBITS }, + { 49, 2, "D_TLA0", "Output delay for TLA0", PRESENT_DEC, NOBITS }, + { 47, 2, "D_DQ_E", "Output delay for DQ DQM - even byte lanes", PRESENT_DEC, NOBITS }, + { 45, 2, "D_DQ_O", "Output delay for DQ DQM - odd byte lanes", PRESENT_DEC, NOBITS }, + { 43, 2, RESERVED}, + { 41, 2, "D_SDCLK", "Output delay for SDCLK", PRESENT_DEC, NOBITS }, + { 39, 2, "D_CMD_O", "Output delay for CKE CS RAS CAS WE - odd bits", PRESENT_DEC, NOBITS }, + { 37, 2, "D_CMD_E", "Output delay for CKE CS RAS CAS WE - even bits", PRESENT_DEC, NOBITS }, + { 35, 2, "D_MA_O", "Output delay for BA MA - odd bits", PRESENT_DEC, NOBITS }, + { 33, 2, "D_MA_E", "Output delay for BA MA - even bits", PRESENT_DEC, NOBITS }, + { 31, 2, "D_PCI_O", "Output delay for pci_ad IRQ13 SUSPA# INTA# - odd bits", PRESENT_DEC, NOBITS }, + { 29, 2, "D_PCI_E", "Output delay for pci_ad IRQ13 SUSPA# INTA# - even bits", PRESENT_DEC, NOBITS }, + { 27, 2, "D_DOTCLK", "Output delay for DOTCLK", PRESENT_DEC, NOBITS }, + { 25, 2, "D_DRGB_O", "Output delay for DRGB[31:0] - odd bits", PRESENT_DEC, NOBITS }, + { 23, 2, "D_DRGB_E", "Output delay for DRGB[31:0] HSYNC VSYNC DISPEN VDDEN LDE_MOD - even bits", PRESENT_DEC, NOBITS }, + { 21, 2, "D_PCI_IN", "Input delay for pci_ad CBE# PAR STOP# FRAME# IRDY# TRDY# DEVSEL# REQ# GNT# CIS", PRESENT_DEC, NOBITS }, + { 19, 2, "D_TDBGI", "Input delay for TDBGI", PRESENT_DEC, NOBITS }, + { 17, 2, "D_VIP", "Input delay for VID[15:0] VIP_HSYNC VIP_VSYNC", PRESENT_DEC, NOBITS }, + { 15, 2, "D_VIPCLK", "Input delay for VIPCLK", PRESENT_DEC, NOBITS }, + { 13, 1, "H_SDCLK", "Half SDCLK hold select (for cmd addr)", PRESENT_DEC, { + { MSR1(1), "Half SDCLK setup for MA and BA" }, + { MSR1(0), "Full SDCLK setup" }, + { BITVAL_EOT } + }}, + { 12, 2, "PLL_FD_DEL", "PLL Feedback Delay", PRESENT_BIN, { + { MSR1(0), "No feedback delay" }, + { MSR1(1), "~350 ps" }, + { MSR1(2), "~700 ps" }, + { MSR1(3), "~1100 ps (Max feedback delay)" }, + { BITVAL_EOT } + }}, + { 10, 5, RESERVED }, + { 5, 1, "DLL_OV", "DLL Override (to DLL)", PRESENT_DEC, NOBITS }, + { 4, 5, "DLL_OVS/RSDA", "DLL Override Setting or Read Strobe Delay Adjust", PRESENT_DEC, NOBITS }, + { BITS_EOT } + }}, +/* + { 0, MSRTYPE_RDONLY, MSR2(0, 0), "TEMPLATE", "Template MSR", { + { 63, 64, RESERVED }, + { BITS_EOT } + }}, +*/ + { MSR_EOT } +}; diff --git a/util/msrtool/linux.c b/util/msrtool/linux.c new file mode 100644 index 0000000000..efd3087061 --- /dev/null +++ b/util/msrtool/linux.c @@ -0,0 +1,88 @@ +/* + * This file is part of msrtool. + * + * Copyright (c) 2008 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 linux_probe(const struct sysdef *system) { + struct stat st; + return 0 == stat("/dev/cpu/0/msr", &st); +} + +int linux_open(uint8_t cpu, enum SysModes mode) { + int fmode; + char fn[32]; + switch (mode) { + case SYS_RDWR: + fmode = O_RDWR; + break; + case SYS_WRONLY: + fmode = O_WRONLY; + break; + case SYS_RDONLY: + default: + fmode = O_RDONLY; + break; + } + if (cpu >= MAX_CORES) { + fprintf(stderr, "%s: only cores 0-%d are supported. requested=%d\n", __func__, MAX_CORES, cpu); + return 0; + } + if (snprintf(fn, sizeof(fn), "/dev/cpu/%d/msr", cpu) == -1) { + fprintf(stderr, "%s: snprintf: %s\n", __func__, strerror(errno)); + return 0; + } + msr_fd[cpu] = open(fn, fmode); + if (-1 == msr_fd[cpu]) { + fprintf(stderr, "open(%s): %s\n", fn, strerror(errno)); + return 0; + } + return 1; +} + +int linux_close(uint8_t cpu) { + int ret; + if (cpu >= MAX_CORES) { + fprintf(stderr, "%s: only cores 0-%d are supported. requested=%d\n", __func__, MAX_CORES, cpu); + return 0; + } + ret = close(msr_fd[cpu]); + msr_fd[cpu] = 0; + return 0 == ret; +} + +int linux_rdmsr(uint8_t cpu, uint32_t addr, struct msr *val) { + if (lseek(msr_fd[cpu], addr, SEEK_SET) == -1) { + SYSERROR(lseek, addr); + return 0; + } + if (read(msr_fd[cpu], val, 8) != 8) { + SYSERROR(read, addr); + return 0; + } + return 1; +} diff --git a/util/msrtool/msrtool.c b/util/msrtool/msrtool.c new file mode 100644 index 0000000000..6f0b3a0109 --- /dev/null +++ b/util/msrtool/msrtool.c @@ -0,0 +1,399 @@ +/* + * This file is part of msrtool. + * + * Copyright (c) 2008 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 +#include + +#include "msrtool.h" + +#define DEFAULT_CPU 0 +static uint8_t cpu = DEFAULT_CPU; + +uint8_t targets_found = 0; +const struct targetdef **targets = NULL; +const struct sysdef *sys = NULL; +uint8_t reserved = 0, verbose = 0, quiet = 0; + +static struct targetdef alltargets[] = { + { "geodelx", "AMD Geode(tm) LX", geodelx_probe, geodelx_msrs }, + { "cs5536", "AMD Geode(tm) CS5536", cs5536_probe, cs5536_msrs }, + { TARGET_EOT } +}; + +static struct sysdef allsystems[] = { + { "linux", "Linux with /dev/cpu/*/msr", linux_probe, linux_open, linux_close, linux_rdmsr }, + { SYSTEM_EOT } +}; + +static void syntax(char *argv[]) { + printf("syntax: %s [-hvqrkl] [-c cpu] [-m system] [-t target ...]\n", argv[0]); + printf("\t [-i addr=hi[:]lo] | [-s file] | [-d [:]file] | addr...\n"); + printf(" -h\t show this help text\n"); + printf(" -v\t be verbose\n"); + printf(" -q\t be quiet (overrides -v)\n"); + printf(" -r\t include [Reserved] values\n"); + printf(" -k\t list all known systems and targets\n"); + printf(" -l\t list MSRs and bit fields for current target(s) (-kl for ALL targets!)\n"); + printf(" -c\t access MSRs on the specified CPU, default=%d\n", DEFAULT_CPU); + printf(" -m\t force a system, e.g: -m linux\n"); + printf(" -t\t force a target, can be used multiple times, e.g: -t geodelx -t cs5536\n"); + printf(" -i\t immediate mode\n"); + printf("\t decode hex addr=hi:lo for the target without reading hw value\n"); + printf("\t e.g: -i 4c00000f=f2f100ff56960004\n"); + printf(" -s\t stream mode\n"); + printf("\t read one MSR address per line and append current hw value to the line\n"); + printf("\t use the filename - for stdin/stdout\n"); + printf("\t using -l -s ignores input and will output all MSRs with values\n"); + printf(" -d\t diff mode\n"); + printf("\t read one address and value per line and compare with current hw value,\n"); + printf("\t printing differences to stdout. use the filename - to read from stdin\n"); + printf("\t use :file or :- to reverse diff, normally hw values are considered new\n"); + printf(" addr.. direct mode, read and decode values for the given MSR address(es)\n"); +} + +static void *add_target(const struct targetdef *t) { + void *tmp; + tmp = realloc(targets, (targets_found + 2) * sizeof(struct targetdef *)); + if (NULL == tmp) { + perror("realloc"); + return tmp; + } + targets = tmp; + targets[targets_found++] = t; + targets[targets_found] = NULL; + return targets; +} + +int do_stream(const char *streamfn, uint8_t ignoreinput) { + char tmpfn[20], line[256]; + uint8_t tn; + size_t start, len; + int ret = 1; + int fdout = -1; + FILE *fin = NULL, *fout = NULL; + uint32_t addr, linenum; + struct msr m = MSR1(0); + + if (0 == strcmp(streamfn, "-")) { + fin = stdin; + fout = stdout; + } else { + if (!ignoreinput) { + if (NULL == (fin = fopen(streamfn, "r"))) { + perror("fopen()"); + return 1; + } + if (snprintf(tmpfn, sizeof(tmpfn), "msrtoolXXXXXX") >= sizeof(tmpfn)) { + perror("snprintf"); + return 1; + } + if (-1 == (fdout = mkstemp(tmpfn))) { + perror("mkstemp"); + return 1; + } + if (NULL == (fout = fdopen(fdout, "w"))) { + perror("fdopen"); + return 1; + } + } else { + if (NULL == (fout = fopen(streamfn, "w"))) { + perror("fopen"); + return 1; + } + } + } + + if (!sys->open(cpu, SYS_RDONLY)) + goto done; + if (ignoreinput) { + for (tn = 0; tn < targets_found; tn++) + if (dumpmsrdefsvals(fout, targets[tn], cpu)) { + ret = 1; + break; + } + } else { + for (linenum = 1; NULL != fgets(line, sizeof(line), fin); ++linenum) { + start = (0 == strncmp("0x", line, 2)) ? 2 : 0; + if (1 == sscanf(line + start, "%8x", &addr)) { + if (!sys->rdmsr(cpu, addr, &m)) + goto done; + fprintf(fout, "0x%08x 0x%08x%08x\n", addr, m.hi, m.lo); + continue; + } + while (1) { + fprintf(fout, "%s", line); + len = strlen(line); + if (NULL != strchr("\r\n", line[len - 1])) + break; + if (NULL == fgets(line, sizeof(line), fin)) + goto read_done; + } + } +read_done: + if (!feof(fin)) { + fprintf(stderr, "%s:%d: fgets: %s\n", streamfn, linenum, strerror(errno)); + goto done; + } + } + ret = 0; +done: + sys->close(cpu); + if (strcmp(streamfn, "-")) { + if (ret) + unlink(tmpfn); + else if (!ignoreinput) + rename(tmpfn, streamfn); + } + if (!ignoreinput) + fclose(fin); + fclose(fout); + return ret; +} + +int do_diff(const char *difffn) { + char tmpfn[20], line[512]; + size_t start, len; + int ret = 1, tmp; + FILE *fin = NULL, *fout = stdout; + uint8_t rev = 0; + uint32_t addr, linenum; + struct msr mf = MSR1(0), mhw = MSR1(0); + + if (':' == difffn[0]) { + rev = 1; + ++difffn; + } + if (0 == strcmp(difffn, "-")) + fin = stdin; + else if (NULL == (fin = fopen(difffn, "r"))) { + perror("fopen()"); + return 1; + } + + if (!sys->open(cpu, SYS_RDONLY)) + goto done; + for (linenum = 1; NULL != fgets(line, sizeof(line), fin); ++linenum) { + start = (0 == strncmp("0x", line, 2)) ? 2 : 0; + if (sscanf(line + start, "%8x %n%*x", &addr, &tmp) >= 1) { + start += tmp; + for (len = strlen(line) - 1; NULL != strchr("\r\n", line[len]); --len) + line[len] = 0; + if (!str2msr(line + start, &mf)) { + fprintf(stderr, "%s:%d: invalid MSR value '%s'\n", difffn, linenum, line + start); + continue; + } + if (!sys->rdmsr(cpu, addr, &mhw)) + goto done; + if (diff_msr(fout, addr, rev ? mhw : mf, rev ? mf : mhw)) + fprintf(fout, "\n"); + } + } + if (!feof(fin)) + fprintf(stderr, "%s:%d: fgets: %s\n", difffn, linenum, strerror(errno)); + else + ret = 0; +done: + sys->close(cpu); + if (strcmp(difffn, "-")) { + if (ret) + unlink(tmpfn); + else + rename(tmpfn, difffn); + fclose(fin); + fclose(fout); + } + return ret; +} + +int main(int argc, char *argv[]) { + char c; + int ret = 1; + const struct sysdef *s; + const struct targetdef *t; + uint8_t tn, listmsrs = 0, listknown = 0, input = 0; + uint32_t addr = 0; + const char *streamfn = NULL, *difffn = NULL; + struct msr msrval = MSR2(-1, -1); + while ((c = getopt(argc, argv, "hqvrklc:m:t:a:i:s:d:")) != -1) + switch (c) { + case 'h': + syntax(argv); + return 0; + case 'q': + quiet = 1; + break; + case 'v': + ++verbose; + break; + case 'r': + reserved = 1; + break; + case 'k': + listknown = 1; + break; + case 'l': + listmsrs = 1; + break; + case 'c': + cpu = atoi(optarg); + break; + case 'm': + for (s = allsystems; !SYSTEM_ISEOT(*s); s++) + if (!strcmp(s->name, optarg)) { + sys = s; + break; + } + break; + case 't': + for (t = alltargets; !TARGET_ISEOT(*t); t++) + if (!strcmp(t->name, optarg)) { + add_target(t); + break; + } + break; + case 'i': + input = 1; + addr = strtoul(optarg, NULL, 16); + optarg = strchr(optarg, '='); + if (NULL == optarg) { + fprintf(stderr, "missing value in -i argument!\n"); + break; + } + if (!str2msr(++optarg, &msrval)) + fprintf(stderr, "invalid value in -i argument!\n"); + break; + case 's': + streamfn = optarg; + break; + case 'd': + difffn = optarg; + break; + default: + break; + } + + printf_quiet("msrtool %s\n", VERSION); + + if (!sys && !input && !listknown) + for (sys = allsystems; !SYSTEM_ISEOT(*sys); sys++) { + printf_verbose("Probing for system %s: %s\n", sys->name, sys->prettyname); + if (!sys->probe(sys)) + continue; + printf_quiet("Detected system %s: %s\n", sys->name, sys->prettyname); + break; + } + + if (targets) + for (tn = 0; tn < targets_found; tn++) + printf_quiet("Forced target %s: %s\n", targets[tn]->name, targets[tn]->prettyname); + else + for (t = alltargets; !TARGET_ISEOT(*t); t++) { + printf_verbose("Probing for target %s: %s\n", t->name, t->prettyname); + if (!t->probe(t)) + continue; + printf_quiet("Detected target %s: %s\n", t->name, t->prettyname); + add_target(t); + } + + printf_quiet("\n"); + fflush(stdout); + + if (listknown) { + printf("Known systems:\n"); + for (s = allsystems; s->name; s++) + printf("%s: %s\n", s->name, s->prettyname); + printf("\nKnown targets:\n"); + for (t = alltargets; t->name; t++) { + if (listmsrs && alltargets != t) + printf("\n"); + printf("%s: %s\n", t->name, t->prettyname); + if (listmsrs) + dumpmsrdefs(t); + } + printf("\n"); + return 0; + } + + if (sys && !sys->name) { + fprintf(stderr, "Unable to detect the current operating system!\n"); + fprintf(stderr, "Please send a report or patch to coreboot@coreboot.org. Thanks for your help!\n"); + fprintf(stderr, "\n"); + } + + if (!targets_found || !targets) { + fprintf(stderr, "Unable to detect a known target; can not decode any MSRs! (Use -t to force)\n"); + fprintf(stderr, "Please send a report or patch to coreboot@coreboot.org. Thanks for your help!\n"); + fprintf(stderr, "\n"); + return 1; + } + + if (input) { + decodemsr(cpu, addr, msrval); + return 0; + } + + if (sys && !sys->name) + return 1; + + if (listmsrs) { + if (streamfn) + return do_stream(streamfn, 1); + for (tn = 0; tn < targets_found; tn++) { + if (tn) + printf("\n"); + dumpmsrdefs(targets[tn]); + } + printf("\n"); + return 0; + } + + if (streamfn) + return do_stream(streamfn, 0); + + if (!sys->open(cpu, SYS_RDONLY)) + return 1; + + if (difffn) { + ret = do_diff(difffn); + goto done; + } + + if (optind == argc) { + syntax(argv); + printf("\nNo mode or address(es) specified!\n"); + goto done; + } + + for (; optind < argc; optind++) { + addr = strtoul(argv[optind], NULL, 16); + if (!sys->rdmsr(cpu, addr, &msrval)) + break; + decodemsr(cpu, addr, msrval); + } + ret = 0; +done: + sys->close(cpu); + return ret; +} diff --git a/util/msrtool/msrtool.h b/util/msrtool/msrtool.h new file mode 100644 index 0000000000..ab7c227d37 --- /dev/null +++ b/util/msrtool/msrtool.h @@ -0,0 +1,183 @@ +/* + * This file is part of msrtool. + * + * Copyright (c) 2008 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 + */ + +#ifndef MSRTOOL_H +#define MSRTOOL_H + +#include +#include + +#define HEXCHARS "0123456789abcdefABCDEF" + +enum { + MSRTYPE_RDONLY, + MSRTYPE_RDWR, + MSRTYPE_WRONLY, + MSRTYPE_EOT +} MsrTypes; + +enum { + PRESENT_RSVD, + PRESENT_DEC, + PRESENT_BIN, + PRESENT_OCT, + PRESENT_HEX, + PRESENT_HEXDEC +} PresentTypes; + +struct msr { + uint32_t hi; + uint32_t lo; +}; + +struct msrbitvalues { + const struct msr value; + const char *text; +}; + +struct msrbits { + const uint8_t start; + const uint8_t size; + const char *name; + const char *desc; + const uint8_t present; + const struct msrbitvalues bitval[32]; +}; + +struct msrdef { + const uint32_t addr; + const uint8_t type; + const struct msr resetval; + const char *symbol; + const char *desc; + const struct msrbits bits[65]; +}; + +#define MSR1(lo) { 0, (lo) } +#define MSR2(hi,lo) { (hi), (lo) } + +#define BITVAL_EOT .text = NULL +#define BITVAL_ISEOT(bv) (NULL == (bv).text) + +#define BITS_EOT .size = 0 +#define BITS_ISEOT(b) (0 == (b).size) + +#define MSR_EOT .type = MSRTYPE_EOT +#define MSR_ISEOT(m) (MSRTYPE_EOT == (m).type) + +#define NOBITS {{ BITVAL_EOT }} +#define RESERVED "RSVD", "Reserved", PRESENT_HEXDEC, NOBITS + +#define MAX_CORES 8 + +struct targetdef { + const char *name; + const char *prettyname; + int (*probe)(const struct targetdef *target); + const struct msrdef *msrs; +}; + +#define TARGET_EOT .name = NULL +#define TARGET_ISEOT(t) (NULL == (t).name) + + +enum SysModes { + SYS_RDONLY = 0, + SYS_WRONLY, + SYS_RDWR +}; + +struct sysdef { + const char *name; + const char *prettyname; + int (*probe)(const struct sysdef *system); + int (*open)(uint8_t cpu, enum SysModes mode); + int (*close)(uint8_t cpu); + int (*rdmsr)(uint8_t cpu, uint32_t addr, struct msr *val); +}; + +#define SYSTEM_EOT .name = NULL +#define SYSTEM_ISEOT(s) (NULL == (s).name) + + +struct cpuid_t { + uint8_t family; + uint8_t model; + uint8_t stepping; + uint8_t ext_family; + uint8_t ext_model; +}; + + +extern const struct sysdef *sys; + +extern uint8_t targets_found; +extern const struct targetdef **targets; + +extern uint8_t reserved, verbose, quiet; + +#define printf_quiet(x...) do { if (!quiet) fprintf(stderr,x); } while(0) +#define printf_verbose(x...) do { if (verbose && !quiet) fprintf(stderr,x); } while(0) + +#define SYSERROR(call, addr) do { \ + const struct msrdef *m = findmsrdef(addr); \ + if (m) \ + fprintf(stderr, "%s: " #call "(0x%08x) %s: %s\n", __func__, addr, m->symbol, strerror(errno)); \ + else \ + fprintf(stderr, "%s: " #call "(0x%08x): %s\n", __func__, addr, strerror(errno)); \ +} while (0); + +/* sys.c */ +struct cpuid_t *cpuid(void); + +/* msrutils.c */ +void hexprint(FILE *f, const struct msr val, const uint8_t bits); +int msr_eq(const struct msr a, const struct msr b); +struct msr msr_shl(const struct msr a, const uint8_t bits); +struct msr msr_shr(const struct msr a, const uint8_t bits); +void msr_and(struct msr *a, const struct msr b); +const struct msrdef *findmsrdef(const uint32_t addr); +void dumpmsrdefs(const struct targetdef *t); +int dumpmsrdefsvals(FILE *f, const struct targetdef *t, const uint8_t cpu); +uint8_t str2msr(char *str, struct msr *msr); +void decodemsr(const uint8_t cpu, const uint32_t addr, const struct msr val); +uint8_t diff_msr(FILE *fout, const uint32_t addr, const struct msr a, const struct msr b); + + + +/** system externs **/ + +/* linux.c */ +extern int linux_probe(const struct sysdef *system); +extern int linux_open(uint8_t cpu, enum SysModes mode); +extern int linux_close(uint8_t cpu); +extern int linux_rdmsr(uint8_t cpu, uint32_t addr, struct msr *val); + + +/** target externs **/ + +/* geodelx.c */ +extern int geodelx_probe(const struct targetdef *t); +extern const struct msrdef geodelx_msrs[]; + +/* cs5536.c */ +extern int cs5536_probe(const struct targetdef *t); +extern const struct msrdef cs5536_msrs[]; + +#endif /* MSRTOOL_H */ diff --git a/util/msrtool/msrutils.c b/util/msrtool/msrutils.c new file mode 100644 index 0000000000..3c64242a87 --- /dev/null +++ b/util/msrtool/msrutils.c @@ -0,0 +1,299 @@ +/* + * This file is part of msrtool. + * + * Copyright (c) 2008 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 "msrtool.h" + +static void print_bitdef(FILE *f, const struct msrbits *mb, const char *tail) { + uint8_t endbit; + if (!reserved && !strcmp(mb->name, "RSVD")) + return; + if (1 == mb->size) + fprintf(f, "# %5d", mb->start); + else { + endbit = mb->start - mb->size + 1; + fprintf(f, "# %*d:%d", endbit < 10 ? 3 : 2, mb->start, endbit); + } + if (!strcmp(mb->name, "RSVD")) + fprintf(f, " [%s]", mb->desc); + else + fprintf(f, " %s %s", mb->name, mb->desc); + fprintf(f, "%s", tail); +} + +static void print_bitval(FILE *f, const struct msrbits *mb, const struct msr val) { + uint8_t i; + struct msr tmp, mask = MSR1(1); + const struct msrbitvalues *mbv = mb->bitval; + while (mbv->text && !msr_eq(mbv->value, val)) + mbv++; + switch (mb->present) { + case PRESENT_BIN: + mask = msr_shl(mask, mb->size - 1); + for (i = 0; i < mb->size; i++) { + memcpy(&tmp, &val, sizeof(val)); + msr_and(&tmp, mask); + fprintf(f, "%d", (tmp.hi || tmp.lo) ? 1 : 0); + mask = msr_shr(mask, 1); + } + /* TODO */ + break; + case PRESENT_DEC: + fprintf(f, "%d", val.lo); + break; + case PRESENT_OCT: + fprintf(f, "0%o", val.lo); + break; + case PRESENT_HEX: + hexprint(f, val, mb->size); + break; + case PRESENT_HEXDEC: + hexprint(f, val, mb->size); + fprintf(f, " %d", val.lo); + break; + } + if (mbv->text) + fprintf(f, ": %s", mbv->text); + fprintf(f, "\n"); +} + +void hexprint(FILE *f, const struct msr val, const uint8_t bits) { + if (bits <= 4) + fprintf(f, "0x%x", (uint8_t)(val.lo & 0x0f)); + else if (bits <= 8) + fprintf(f, "0x%02x", (uint8_t)(val.lo & 0xff)); + else if (bits <= 16) + fprintf(f, "0x%04x", (uint16_t)(val.lo & 0xffff)); + else if (bits <= 32) + fprintf(f, "0x%08x", val.lo); + else + fprintf(f, "0x%08x%08x", val.hi, val.lo); +} + +int msr_eq(const struct msr a, const struct msr b) { + return a.hi == b.hi && a.lo == b.lo; +} + +struct msr msr_shl(const struct msr a, const uint8_t bits) { + struct msr ret; + + ret.hi = bits < 32 ? a.hi << bits : 0; + ret.lo = bits < 32 ? a.lo << bits : 0; + + if (bits < 32) + ret.hi |= bits ? a.lo >> (32 - bits) : 0; + else + ret.hi |= a.lo << (bits - 32); + + return ret; +} + +struct msr msr_shr(const struct msr a, const uint8_t bits) { + struct msr ret; + + ret.hi = bits < 32 ? a.hi >> bits : 0; + ret.lo = bits < 32 ? a.lo >> bits : 0; + + if (bits < 32) + ret.lo |= bits ? a.hi << (32 - bits) : 0; + else + ret.lo |= a.hi >> (bits - 32); + + return ret; +} + +void msr_and(struct msr *a, const struct msr b) { + a->hi &= b.hi; + a->lo &= b.lo; +} + +const struct msrdef *findmsrdef(const uint32_t addr) { + uint8_t t; + const struct msrdef *m; + if (!targets) + return NULL; + for (t = 0; t < targets_found; t++) + for (m = targets[t]->msrs; !MSR_ISEOT(*m); m++) + if (addr == m->addr) + return m; + return NULL; +} + +void dumpmsrdefs(const struct targetdef *t) { + const struct msrdef *m; + const struct msrbits *mb; + if (!t) + return; + printf("# %s MSRs:\n", t->name); + for (m = t->msrs; !MSR_ISEOT(*m); m++) { + if (t->msrs != m) + printf("\n"); + printf("# %s\n", m->symbol); + for (mb = m->bits; mb->size; mb++) + print_bitdef(stdout, mb, "\n"); + printf("0x%08x\n", m->addr); + } +} + +int dumpmsrdefsvals(FILE *f, const struct targetdef *t, const uint8_t cpu) { + struct msr val = MSR1(0); + const struct msrdef *m; + const struct msrbits *mb; + if (!t) + return 1; + fprintf(f, "# %s MSRs:\n", t->name); + for (m = t->msrs; !MSR_ISEOT(*m); m++) { + if (t->msrs != m) + fprintf(f, "\n"); + if (!sys->rdmsr(cpu, m->addr, &val)) + return 1; + fprintf(f, "# %s\n", m->symbol); + for (mb = m->bits; mb->size; mb++) + print_bitdef(f, mb, "\n"); + fprintf(f, "0x%08x 0x%08x%08x\n", m->addr, val.hi, val.lo); + } + return 0; +} + +/** + * Parse a hexadecimal string into an MSR value. + * + * Leading 0x or 0X is optional, the string is always parsed as hexadecimal. + * Any non-hexadecimal character can be used to separate the high 32 bits and + * the low 32 bits. If there is such a separator, high and low values do not + * need to be zero padded. If there is no separator, the last <=8 digits are + * the low 32 bits and any characters before them are the high 32 bits. + * When there is no separator and less than eight digits, the high 32 bits + * are set to 0. + * Parsing fails when there is a separator and it is followed by another + * non-hexadecimal character. + * + * @param str The string to parse. The string must be writable but will be + * restored before return. + * @param msr Pointer to the struct msr where the value will be stored. + * @return 1 on success, 0 on parse failure. msr is unchanged on failure. + */ +uint8_t str2msr(char *str, struct msr *msr) { + char c; + size_t len, lo; + if (0 == strncmp(str, "0x", 2) || 0 == strncmp(str, "0X", 2)) + str += 2; + len = strspn(str, HEXCHARS); + if (len <= 8 && 0 == str[len]) { + msr->hi = 0; + lo = 0; + } else if (len <= 8) { + lo = len + strcspn(str + len, HEXCHARS); + if (0 == len && 0 == strspn(str + lo, HEXCHARS)) + return 0; + c = str[len]; + str[len] = 0; + msr->hi = strtoul(str, NULL, 16); + str[len] = c; + } else { + lo = len - 8; + c = str[lo]; + str[lo] = 0; + msr->hi = strtoul(str, NULL, 16); + str[lo] = c; + } + msr->lo = strtoul(str + lo, NULL, 16); + return 1; +} + +void decodemsr(const uint8_t cpu, const uint32_t addr, const struct msr val) { + struct msr bitval, mask; + const struct msrdef *m = findmsrdef(addr); + const struct msrbits *mb; + + if (m) + printf("# %s ", m->symbol); + printf("0x%08x = 0x%08x%08x\n", addr, val.hi, val.lo); + if (!m) { + fprintf(stderr, "Sorry - no definition exists for this MSR! Please add it and send a signed-off\n"); + fprintf(stderr, "patch to coreboot@coreboot.org. Thanks for your help!\n"); + return; + } + + for (mb = m->bits; mb->size; mb++) { + if (!reserved && 0 == strcmp(mb->name, "RSVD")) + continue; + print_bitdef(stdout, mb, " = "); + mask.hi = mask.lo = 0xffffffff; + mask = msr_shr(mask, 64 - mb->size); + bitval = msr_shr(val, mb->start - mb->size + 1); + msr_and(&bitval, mask); + print_bitval(stdout, mb, bitval); + } +} + +/** + * Compare two MSR values and print any differences with field definitions and + * both old and new values decoded. + * + * @param f Output stream. + * @param addr MSR address. + * @param a Left value. + * @param b Right value. + * @return 1 when a and b differ, 0 when they are equal or only reserved bits + * differ and processing of reserved bits was not requested (with -r). + */ +uint8_t diff_msr(FILE *f, const uint32_t addr, const struct msr a, const struct msr b) { + uint8_t ret = 0, first = 1; + struct msr aval, bval, mask; + const struct msrdef *m = findmsrdef(addr); + const struct msrbits *mb; + + if (a.hi == b.hi && a.lo == b.lo) + return 0; + + if (!m) { + fprintf(stderr, "MSR 0x%08x has no definition! Please add it and send a Signed-off-by patch\n", addr); + fprintf(stderr, "to coreboot@coreboot.org. Thank you for your help!\n"); + return 1; + } + + for (mb = m->bits; mb->size; mb++) { + if (!reserved && 0 == strcmp(mb->name, "RSVD")) + continue; + mask.hi = mask.lo = 0xffffffff; + mask = msr_shr(mask, 64 - mb->size); + aval = msr_shr(a, mb->start - mb->size + 1); + bval = msr_shr(b, mb->start - mb->size + 1); + msr_and(&aval, mask); + msr_and(&bval, mask); + if (msr_eq(aval, bval)) + continue; + if (first) { + fprintf(f, "# %s\n", m->symbol); + fprintf(f, "-0x%08x 0x%08x%08x\n", addr, a.hi, a.lo); + fprintf(f, "+0x%08x 0x%08x%08x\n", addr, b.hi, b.lo); + first = 0; + ret = 1; + } + print_bitdef(f, mb, "\n-"); + print_bitval(f, mb, aval); + fprintf(f, "+"); + print_bitval(f, mb, bval); + } + return ret; +} diff --git a/util/msrtool/sys.c b/util/msrtool/sys.c new file mode 100644 index 0000000000..95539c8677 --- /dev/null +++ b/util/msrtool/sys.c @@ -0,0 +1,42 @@ +/* + * This file is part of msrtool. + * + * Copyright (c) 2008 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 "msrtool.h" + +static struct cpuid_t id; + +struct cpuid_t *cpuid(void) { + uint32_t outeax; + asm ("cpuid" : "=a" (outeax) : "a" (1) : "%ebx", "%ecx", "%edx"); + id.stepping = outeax & 0xf; + outeax >>= 4; + id.model = outeax & 0xf; + outeax >>= 4; + id.family = outeax & 0xf; + outeax >>= 8; + id.ext_model = outeax & 0xf; + outeax >>= 4; + id.ext_family = outeax & 0xff; + if (0xf == id.family) { + /* Intel says always do this, AMD says only for family f */ + id.model |= (id.ext_model << 4); + id.family += id.ext_family; + } + return &id; +} -- cgit v1.2.3