├── README ├── .github ├── CODEOWNERS └── workflows │ └── github-actions.yml ├── rpm ├── msr-safe.sysconfig ├── 10-msr-safe.rules ├── build_rpm.sh ├── msr-safe.service ├── msr-safe.sh └── msr-safe.spec ├── .gitlab ├── subscribed-pipelines.yml └── cztb2-build-and-test.yml ├── dkms.conf ├── .gitignore ├── THANKS ├── msr-smp.h ├── msr_batch.h ├── .gitlab-ci.yml ├── msrsave ├── msrsave.h ├── msrsave.1 ├── msrsave_main.c ├── spank_msrsafe.c ├── msrsave_test.c └── msrsave.c ├── msr_allowlist.h ├── NOTICE ├── msr_version.h ├── msr_safe.h ├── msr-smp.c ├── Makefile ├── examples └── example.c ├── msr_version.c ├── msr_batch.c ├── msr_entry.c ├── msr_allowlist.c ├── allowlists ├── al_06_8F ├── al_19_21 ├── al_19_1 └── al_06_2A ├── LICENSE └── README.md /README: -------------------------------------------------------------------------------- 1 | README.md -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @slabasan @rountree 2 | -------------------------------------------------------------------------------- /rpm/msr-safe.sysconfig: -------------------------------------------------------------------------------- 1 | # Override the allowlist 2 | # ALLOWLIST=/usr/share/msr-safe/allowlists/al_0655 3 | -------------------------------------------------------------------------------- /rpm/10-msr-safe.rules: -------------------------------------------------------------------------------- 1 | SUBSYSTEM=="msr_safe", GROUP="msr", MODE="0660" 2 | SUBSYSTEM=="msr_batch", GROUP="msr", MODE="0660" 3 | SUBSYSTEM=="msr_allowlist", GROUP="msr", MODE="0660" 4 | -------------------------------------------------------------------------------- /.gitlab/subscribed-pipelines.yml: -------------------------------------------------------------------------------- 1 | # Trigger a build pipeline for the following systems 2 | cztb2-build-and-test: 3 | variables: 4 | CI_MACHINE: "cztb2" 5 | extends: [.build] 6 | -------------------------------------------------------------------------------- /dkms.conf: -------------------------------------------------------------------------------- 1 | PACKAGE_NAME="msr-safe" 2 | PACKAGE_VERSION="git" 3 | MAKE[0]="KERNELVER=$kernelver make module" 4 | BUILT_MODULE_NAME[0]="msr-safe" 5 | DEST_MODULE_LOCATION[0]="/updates" 6 | AUTOINSTALL="yes" 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | a.out 2 | .*.tmp 3 | .*.swp 4 | .*.cmd 5 | .tmp_versions 6 | Module.symvers 7 | *.o 8 | *.ko 9 | *.mod.c 10 | *.unsigned 11 | modules.order 12 | msrsave/libspank_msrsafe.so 13 | msrsave/msrsave 14 | msrsave/msrsave_test 15 | *.mod 16 | -------------------------------------------------------------------------------- /THANKS: -------------------------------------------------------------------------------- 1 | Thank you to everyone who has contributed and helped with this project: 2 | 3 | Kathleen Shoga 4 | Peter Bailey 5 | Trent D'Hooge 6 | Jim Foraker 7 | David Lowenthal 8 | Tapasya Patki 9 | Barry Rountree 10 | Marty McFadden 11 | 12 | Special thanks to Kendrick Shaw at Case Western Reserve University for his initial suggestion to explore MSRs. 13 | -------------------------------------------------------------------------------- /msr-smp.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011-2021 Lawrence Livermore National Security, LLC and other 2 | // msr-safe Project Developers. See the top-level COPYRIGHT file for 3 | // details. 4 | // 5 | // SPDX-License-Identifier: GPL-2.0-only 6 | 7 | #ifndef MSR_SMP_INCLUDE 8 | #define MSR_SMP_INCLUDE 9 | 10 | int msr_safe_batch(struct msr_batch_array *oa); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /msr_batch.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011-2021 Lawrence Livermore National Security, LLC and other 2 | // msr-safe Project Developers. See the top-level COPYRIGHT file for 3 | // details. 4 | // 5 | // SPDX-License-Identifier: GPL-2.0-only 6 | 7 | #ifndef MSR_BATCH_HEADER_INCLUDE 8 | #define MSR_BATCH_HEADER_INCLUDE 9 | 10 | void msrbatch_cleanup(int majordev); 11 | 12 | int msrbatch_init(int *majordev); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /rpm/build_rpm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | 7 | DIR=$(dirname $(readlink -f $0)) 8 | REV=$(git rev-parse HEAD) 9 | TMPDIR=$(mktemp -d) 10 | 11 | tar -C "${DIR}/../.." -zcf "${TMPDIR}/msr-safe-${REV}.tar.gz" --transform s/msr-safe/msr-safe-${REV}/ msr-safe 12 | mv "${TMPDIR}/msr-safe-${REV}.tar.gz" "${DIR}/" 13 | rpmbuild -D "_sourcedir ${DIR}" -ba "${DIR}/msr-safe.spec" 14 | rm "${DIR}/msr-safe-${REV}.tar.gz" 15 | rmdir "${TMPDIR}" 16 | -------------------------------------------------------------------------------- /rpm/msr-safe.service: -------------------------------------------------------------------------------- 1 | # /etc/systemd/system/llnl-allowlist.service 2 | # (C) 2015 Steve Sylvester (steve.s.sylvester intel.com) 3 | # 4 | # msr-safe systemd unit file: 5 | # Set a default MSR allowlist via /dev/cpu/msr_allowlist. 6 | 7 | [Unit] 8 | Description=Sets default MSR allowlist 9 | After=nss-user-lookup.target nslcd.service network.target 10 | 11 | [Service] 12 | Type=oneshot 13 | RemainAfterExit=yes 14 | User=root 15 | ExecStart=/usr/sbin/msr-safe start 16 | ExecStop=/usr/sbin/msr-safe stop 17 | 18 | [Install] 19 | WantedBy=multi-user.target 20 | 21 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | include: [component: $CI_SERVER_FQDN/lc-components/id_tokens/id_tokens-component@main] 2 | 3 | variables: 4 | CUSTOM_CI_BUILDS_DIR: "/usr/workspace/msr/gitlab-runner" 5 | BUILD_ROOT: ${CI_PROJECT_DIR} 6 | TARGET_BRANCH: ${CI_COMMIT_REF_NAME} 7 | 8 | stages: 9 | - build 10 | 11 | # Template for jobs triggering a build-and-test sub-pipelines: 12 | .build: 13 | stage: build 14 | trigger: 15 | include: 16 | - local: '.gitlab/${CI_MACHINE}-build-and-test.yml' 17 | strategy: depend 18 | forward: 19 | pipeline_variables: true 20 | 21 | include: 22 | - local: .gitlab/subscribed-pipelines.yml 23 | -------------------------------------------------------------------------------- /msrsave/msrsave.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, 2016, Intel Corporation 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #ifndef MSRSAVE_H_INCLUDE 8 | #define MSRSAVE_H_INCLUDE 9 | 10 | #include 11 | 12 | int msr_save(const char *out_path, 13 | const char *allowlist_path, 14 | const char *msr_path, 15 | int num_cpu, 16 | FILE *output_log, 17 | FILE *error_log); 18 | 19 | int msr_restore(const char *in_path, 20 | const char *allowlist_path, 21 | const char *msr_path, 22 | int num_cpu, 23 | FILE *output_log, 24 | FILE *error_log); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /.github/workflows/github-actions.yml: -------------------------------------------------------------------------------- 1 | name: msr-safe CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | 10 | jobs: 11 | 12 | build-msr-safe: 13 | strategy: 14 | matrix: 15 | env: [ ubuntu-latest, ubuntu-20.04 ] 16 | 17 | runs-on: ${{matrix.env}} 18 | 19 | steps: 20 | # checkout msr-safe repository under $GITHUB_WORKSPACE 21 | - uses: actions/checkout@v2 22 | 23 | - name: Install linux headers 24 | run: | 25 | sudo apt-get update 26 | sudo apt-get install -y linux-headers-`uname -r` 27 | 28 | - name: Compile check 29 | run: | 30 | export CC=gcc 31 | export CXX=g++ 32 | ${CC} --version 33 | ${CXX} --version 34 | uname -a 35 | # build 36 | make VERBOSE=1 37 | -------------------------------------------------------------------------------- /msr_allowlist.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011-2021 Lawrence Livermore National Security, LLC and other 2 | // msr-safe Project Developers. See the top-level COPYRIGHT file for 3 | // details. 4 | // 5 | // SPDX-License-Identifier: GPL-2.0-only 6 | 7 | /* 8 | * Internal declarations for x86 MSR allowlist implementation functions. 9 | * 10 | * Thank you to everyone who has contributed and helped with this project: 11 | * 12 | * Kathleen Shoga, Peter Bailey, Trent D'Hooge, Jim Foraker, David Lowenthal 13 | * Tapasya Patki, Barry Rountree, Kendrick Shaw, Marty McFadden 14 | */ 15 | 16 | #ifndef _ARCH_X68_KERNEL_MSR_ALLOWLIST_HEADER_INCLUDE 17 | #define _ARCH_X68_KERNEL_MSR_ALLOWLIST_HEADER_INCLUDE 18 | 19 | #include 20 | 21 | int msr_allowlist_init(int *majordev); 22 | 23 | void msr_allowlist_cleanup(int majordev); 24 | 25 | int msr_allowlist_exists(void); 26 | 27 | int msr_allowlist_maskexists(loff_t reg); 28 | 29 | u64 msr_allowlist_readmask(loff_t reg); 30 | 31 | u64 msr_allowlist_writemask(loff_t reg); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /rpm/msr-safe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -o nounset 4 | set -o pipefail 5 | 6 | . /etc/sysconfig/msr-safe 7 | 8 | al_cpu() { 9 | printf 'al_%.2X_%X\n' \ 10 | $(grep -m1 'cpu family' /proc/cpuinfo | cut -f2 -d: | tr -d ' ') \ 11 | $(grep -m1 'model' /proc/cpuinfo | cut -f2 -d: | tr -d ' ') 12 | } 13 | 14 | start() { 15 | if [ -z "${AL_CPU:-}" ]; then 16 | AL_CPU=$(al_cpu) 17 | fi 18 | 19 | if [ -z "${ALLOWLIST:-}" ]; then 20 | ALLOWLIST="/usr/share/msr-safe/allowlists/${AL_CPU}" 21 | fi 22 | 23 | if [ -f "${ALLOWLIST}" ]; then 24 | /sbin/modprobe msr-safe && \ 25 | cat "${ALLOWLIST}" > /dev/cpu/msr_allowlist 26 | 27 | return $? 28 | else 29 | return 1 30 | fi 31 | } 32 | 33 | stop() { 34 | echo > /dev/cpu/msr_allowlist && \ 35 | /sbin/rmmod msr-safe 36 | 37 | return $? 38 | } 39 | 40 | rc=0 41 | 42 | case "${1:-}" in 43 | start) 44 | start 45 | rc=$? 46 | ;; 47 | stop) 48 | stop 49 | rc=$? 50 | ;; 51 | *) 52 | echo $"Usage: $0 {start|stop}" 53 | exit 2 54 | esac 55 | 56 | exit $rc 57 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | This work was produced under the auspices of the U.S. Department of 2 | Energy by Lawrence Livermore National Laboratory under Contract 3 | DE-AC52-07NA27344. 4 | 5 | This work was prepared as an account of work sponsored by an agency of 6 | the United States Government. Neither the United States Government nor 7 | Lawrence Livermore National Security, LLC, nor any of their employees 8 | makes any warranty, expressed or implied, or assumes any legal liability 9 | or responsibility for the accuracy, completeness, or usefulness of any 10 | information, apparatus, product, or process disclosed, or represents that 11 | its use would not infringe privately owned rights. 12 | 13 | Reference herein to any specific commercial product, process, or service 14 | by trade name, trademark, manufacturer, or otherwise does not necessarily 15 | constitute or imply its endorsement, recommendation, or favoring by the 16 | United States Government or Lawrence Livermore National Security, LLC. 17 | 18 | The views and opinions of authors expressed herein do not necessarily 19 | state or reflect those of the United States Government or Lawrence 20 | Livermore National Security, LLC, and shall not be used for advertising 21 | or product endorsement purposes. 22 | -------------------------------------------------------------------------------- /msr_version.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011-2021 Lawrence Livermore National Security, LLC and other 2 | // msr-safe Project Developers. See the top-level COPYRIGHT file for 3 | // details. 4 | // 5 | // SPDX-License-Identifier: GPL-2.0-only 6 | 7 | /* 8 | * Internal declarations for x86 MSR version implementation functions. 9 | * 10 | * Thank you to everyone who has contributed and helped with this project: 11 | * 12 | * Kathleen Shoga, Peter Bailey, Trent D'Hooge, Jim Foraker, David Lowenthal 13 | * Tapasya Patki, Barry Rountree, Kendrick Shaw, Marty McFadden 14 | */ 15 | 16 | #ifndef _ARCH_X68_KERNEL_MSR_VERSION_HEADER_INCLUDE 17 | #define _ARCH_X68_KERNEL_MSR_VERSION_HEADER_INCLUDE 18 | 19 | #include 20 | 21 | int msr_version_init(int *majordev); 22 | 23 | void msr_version_cleanup(int majordev); 24 | 25 | #define MSR_SAFE_VERSION_MAJOR 1 26 | #define MSR_SAFE_VERSION_MINOR 8 27 | #define MSR_SAFE_VERSION_PATCH 0 28 | 29 | #define MSR_SAFE_VERSION_u32 ( \ 30 | ( MSR_SAFE_VERSION_MAJOR << 16 ) \ 31 | | ( MSR_SAFE_VERSION_MINOR << 8 ) \ 32 | | ( MSR_SAFE_VERSION_PATCH << 0 ) ) 33 | 34 | #define MAKESTRING( s ) #s 35 | #define MAKE_VERSION_STRING(major,minor,patch) \ 36 | MAKESTRING( major ) \ 37 | "." \ 38 | MAKESTRING( minor ) \ 39 | "." \ 40 | MAKESTRING( patch ) 41 | 42 | #define MSR_SAFE_VERSION_STR MAKE_VERSION_STRING(\ 43 | MSR_SAFE_VERSION_MAJOR,\ 44 | MSR_SAFE_VERSION_MINOR,\ 45 | MSR_SAFE_VERSION_PATCH) 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /msrsave/msrsave.1: -------------------------------------------------------------------------------- 1 | .\" Copyright (c) 2016, Intel Corporation 2 | .\" 3 | .\" SPDX-License-Identifier: GPL-2.0-only 4 | .\" 5 | .\" generated with Ronn/v0.7.3 6 | .\" http://github.com/rtomayko/ronn/tree/0.7.3 7 | . 8 | .TH "MSRSAVE" "1" "December 2016" "" "" 9 | . 10 | .SH "NAME" 11 | \fBmsrsave\fR \- msr\-safe save and restore application 12 | . 13 | .SH "SYNOPSIS" 14 | . 15 | .TP 16 | \fBSAVE MSR:\fR 17 | \fBmsrsave\fR outfile 18 | . 19 | .TP 20 | \fBRESTORE MSR:\fR 21 | \fBmsrsave\fR \fB\-r\fR infile 22 | . 23 | .TP 24 | \fBPRINT VERSION OR HELP:\fR 25 | \fBmsrsave \-\-version\fR | \fB\-\-help\fR 26 | . 27 | .SH "DESCRIPTION" 28 | The \fBmsrsave\fR application is used to save to a file the state of 29 | all write accesible MSR values defined in the current MSR allowlist 30 | or restore the MSR values from a saved state file\. The msrsave 31 | application also respects the standard \fB\-\-version\fR and 32 | \fB\-\-help\fR options for printing the msr\-safe package version or a 33 | brief message about usage\. 34 | . 35 | .SH "OPTIONS" 36 | . 37 | .TP 38 | \fB\-\-help\fR 39 | . 40 | .br 41 | Print brief summary of the command line usage information, then exit\. 42 | . 43 | .TP 44 | \fB\-\-version\fR 45 | . 46 | .br 47 | Print version of msr\-safe package to standard output, then exit\. 48 | . 49 | .TP 50 | \fB\-r\fR 51 | . 52 | .br 53 | Restore the MSR values that are recorded in an existing MSR saved state 54 | file\. 55 | . 56 | .SH "COPYRIGHT" 57 | Copyright (C) 2016, Intel Corporation\. All rights reserved\. 58 | -------------------------------------------------------------------------------- /msr_safe.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011-2021 Lawrence Livermore National Security, LLC and other 2 | // msr-safe Project Developers. See the top-level COPYRIGHT file for 3 | // details. 4 | // 5 | // SPDX-License-Identifier: GPL-2.0-only 6 | 7 | /* 8 | * This file defines the ioctl interface for submitting a batch of MSR 9 | * requests. This file should be distributed to a place where kernel 10 | * module interface header files are kept for a distribution running this 11 | * module so that user-space applications and libraries that wish to use 12 | * the batch interface may #include this file to get the interface. 13 | */ 14 | 15 | #ifndef MSR_SAFE_HEADER_INCLUDE 16 | #define MSR_SAFE_HEADER_INCLUDE 17 | 18 | #include 19 | #include 20 | 21 | struct msr_batch_op 22 | { 23 | __u16 cpu; // In: CPU to execute {rd/wr}msr instruction 24 | __u16 isrdmsr; // In: 0=wrmsr, non-zero=rdmsr 25 | __s32 err; // Out: set if error occurred with this operation 26 | __u32 msr; // In: MSR Address to perform operation 27 | __u64 msrdata; // In/Out: Input/Result to/from operation 28 | __u64 wmask; // Out: Write mask applied to wrmsr 29 | }; 30 | 31 | struct msr_batch_array 32 | { 33 | __u32 numops; // In: # of operations in operations array 34 | __u32 version; // In: MSR_SAFE_VERSION_u32 (see msr_version.h) 35 | struct msr_batch_op *ops; // In: Array[numops] of operations 36 | }; 37 | 38 | #define X86_IOC_MSR_BATCH _IOWR('c', 0xA2, struct msr_batch_array) 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /.gitlab/cztb2-build-and-test.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - status_initiate 3 | - build 4 | - status_update 5 | 6 | .on_cztb2: 7 | tags: 8 | - shell 9 | - cztb2 10 | rules: 11 | # Only report failure if the pipeline failed. 12 | - if: '$CI_JOB_NAME =~ /status_failure/' 13 | when: on_failure 14 | # A true statement is expected to allow jobs to run. Here is the default. 15 | - when: on_success 16 | 17 | .status_report: &status_report 18 | - export context="cztb2" 19 | - | 20 | curl --url "https://api.github.com/repos/llnl/${CI_PROJECT_NAME}/statuses/${CI_COMMIT_SHA}" \ 21 | --header 'Content-Type: application/json' \ 22 | --header "authorization: Bearer ${GITHUB_TOKEN}" \ 23 | --data "{ \"state\": \"${pipeline_status}\", \"target_url\": \"${CI_PIPELINE_URL}\", \"description\": \"GitLab ${context} pipeline\", \"context\": \"ci/gitlab/${context}\" }" 24 | 25 | status_pending: 26 | tags: 27 | - shell 28 | - cztb2 29 | extends: [.on_cztb2] 30 | stage: status_initiate 31 | script: 32 | - export pipeline_status="pending" 33 | - *status_report 34 | 35 | status_success: 36 | tags: 37 | - shell 38 | - cztb2 39 | extends: [.on_cztb2] 40 | stage: status_update 41 | script: 42 | - export pipeline_status="success" 43 | - *status_report 44 | when: on_success 45 | 46 | status_failure: 47 | tags: 48 | - shell 49 | - cztb2 50 | extends: [.on_cztb2] 51 | stage: status_update 52 | script: 53 | - export pipeline_status="failure" 54 | - *status_report 55 | when: on_failure 56 | 57 | # build across power lab 58 | build-cztb2: 59 | tags: 60 | - shell 61 | - cztb2 62 | stage: build 63 | script: 64 | - git clone $MSR_SAFE_ANSIBLE 65 | - cd msr-safe-ansible-setup 66 | - echo "TARGET_BRANCH=${TARGET_BRANCH}" 67 | - ansible-playbook msr-safe-powerlab-playbook.yml --extra-vars "branch=${TARGET_BRANCH}" 68 | -------------------------------------------------------------------------------- /msr-smp.c: -------------------------------------------------------------------------------- 1 | // Copyright 2011-2021 Lawrence Livermore National Security, LLC and other 2 | // msr-safe Project Developers. See the top-level COPYRIGHT file for 3 | // details. 4 | // 5 | // SPDX-License-Identifier: GPL-2.0-only 6 | 7 | /* 8 | * (proposed) extensions to arch/x86/lib/msr_smp.c 9 | * 10 | * This file is the implementation proposed to arch/x86/lib/msr_smp.c 11 | * that will allow for batching rdmsr/wrmsr requests. 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "msr_safe.h" 21 | #include "msr-smp.h" 22 | 23 | static void __msr_safe_batch(void *info) 24 | { 25 | struct msr_batch_array *oa = info; 26 | struct msr_batch_op *op; 27 | int this_cpu = smp_processor_id(); 28 | u32 *dp; 29 | u64 oldmsr; 30 | u64 newmsr; 31 | 32 | for (op = oa->ops; op < oa->ops + oa->numops; ++op) 33 | { 34 | if (op->cpu != this_cpu) 35 | { 36 | continue; 37 | } 38 | 39 | op->err = 0; 40 | dp = (u32 *)&oldmsr; 41 | if (rdmsr_safe(op->msr, &dp[0], &dp[1])) 42 | { 43 | op->err = -EIO; 44 | continue; 45 | } 46 | if (op->isrdmsr) 47 | { 48 | op->msrdata = oldmsr; 49 | continue; 50 | } 51 | 52 | newmsr = op->msrdata & op->wmask; 53 | newmsr |= (oldmsr & ~op->wmask); 54 | dp = (u32 *)&newmsr; 55 | if (wrmsr_safe(op->msr, dp[0], dp[1])) 56 | { 57 | op->err = -EIO; 58 | } 59 | } 60 | } 61 | 62 | #ifdef CONFIG_CPUMASK_OFFSTACK 63 | 64 | int msr_safe_batch(struct msr_batch_array *oa) 65 | { 66 | cpumask_var_t cpus_to_run_on; 67 | struct msr_batch_op *op; 68 | 69 | if (!zalloc_cpumask_var(&cpus_to_run_on, GFP_KERNEL)) 70 | { 71 | return -ENOMEM; 72 | } 73 | 74 | for (op = oa->ops; op < oa->ops + oa->numops; ++op) 75 | { 76 | cpumask_set_cpu(op->cpu, cpus_to_run_on); 77 | } 78 | 79 | on_each_cpu_mask(cpus_to_run_on, __msr_safe_batch, oa, 1); 80 | 81 | free_cpumask_var(cpus_to_run_on); 82 | 83 | for (op = oa->ops; op < oa->ops + oa->numops; ++op) 84 | { 85 | if (op->err) 86 | { 87 | return op->err; 88 | } 89 | } 90 | 91 | return 0; 92 | } 93 | 94 | #else 95 | 96 | int msr_safe_batch(struct msr_batch_array *oa) 97 | { 98 | struct cpumask cpus_to_run_on; 99 | struct msr_batch_op *op; 100 | 101 | cpumask_clear(&cpus_to_run_on); 102 | for (op = oa->ops; op < oa->ops + oa->numops; ++op) 103 | { 104 | cpumask_set_cpu(op->cpu, &cpus_to_run_on); 105 | } 106 | 107 | on_each_cpu_mask(&cpus_to_run_on, __msr_safe_batch, oa, 1); 108 | 109 | for (op = oa->ops; op < oa->ops + oa->numops; ++op) 110 | { 111 | if (op->err) 112 | { 113 | return op->err; 114 | } 115 | } 116 | 117 | return 0; 118 | } 119 | 120 | #endif //CONFIG_CPUMASK_OFFSTACK 121 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2011-2021 Lawrence Livermore National Security, LLC and other 2 | # msr-safe Project Developers. See the top-level COPYRIGHT file for 3 | # details. 4 | # 5 | # SPDX-License-Identifier: GPL-2.0-only 6 | 7 | # Uncomment following line(s) to enable debug output from different 8 | # portions of kernel module. 9 | # 10 | #CFLAGS_msr_allowlist.o := -DDEBUG 11 | #CFLAGS_msr_entry.o := -DDEBUG 12 | #CFLAGS_msr_batch.o := -DDEBUG 13 | #CFLAGS_msr-smp.o := -DDEBUG 14 | 15 | KERNELVER ?= $(shell uname -r) 16 | 17 | obj-m += msr-safe.o 18 | msr-safe-objs := msr_entry.o msr_allowlist.o msr-smp.o msr_batch.o msr_version.o 19 | 20 | all: module msrsave/msrsave 21 | make -C /lib/modules/$(KERNELVER)/build M=$(PWD) modules 22 | 23 | module: 24 | make -C /lib/modules/$(KERNELVER)/build M=$(PWD) modules 25 | 26 | clean: 27 | make -C /lib/modules/$(KERNELVER)/build M=$(PWD) clean 28 | rm -f msrsave/msrsave.o msrsave/msrsave msrsave/msrsave_test msrsave/spank_msrsafe.o msrsave/libspank_msrsafe.so 29 | 30 | check: msrsave/msrsave_test 31 | msrsave/msrsave_test 32 | 33 | msrsave/msrsave.o: msrsave/msrsave.c msrsave/msrsave.h 34 | $(CC) $(CFLAGS) -fPIC -c msrsave/msrsave.c -o $@ 35 | 36 | msrsave/msrsave_main.o: msrsave/msrsave_main.c msrsave/msrsave.h 37 | $(CC) $(CFLAGS) -fPIC -c msrsave/msrsave_main.c -o $@ 38 | 39 | msrsave/msrsave: msrsave/msrsave_main.o msrsave/msrsave.o 40 | $(CC) $(CFLAGS) $^ -o $@ 41 | 42 | msrsave/msrsave_test.o: msrsave/msrsave_test.c msrsave/msrsave.h 43 | 44 | msrsave/msrsave_test: msrsave/msrsave_test.o msrsave/msrsave.o 45 | 46 | SLURM_CFLAGS ?= -I/usr/include -fPIC -shared 47 | SLURM_LDFLAGS ?= -L/usr/lib64 -lslurm -shared 48 | spank: msrsave/libspank_msrsafe.so 49 | 50 | msrsave/spank_msrsafe.o: msrsave/spank_msrsafe.c 51 | $(CC) $(CFLAGS) $(SLURM_CFLAGS) -c $^ -o $@ 52 | 53 | msrsave/libspank_msrsafe.so: msrsave/spank_msrsafe.o msrsave/msrsave.o 54 | $(CC) $(LDFLAGS) $(SLURM_LDFLAGS) $^ -o $@ 55 | 56 | INSTALL ?= install 57 | prefix ?= $(HOME)/build 58 | exec_prefix ?= $(prefix) 59 | sbindir ?= $(exec_prefix)/sbin 60 | libdir ?= $(exec_preffix)/lib 61 | datarootdir ?= $(prefix)/share 62 | mandir ?= $(datarootdir)/man 63 | man1dir ?= $(mandir)/man1 64 | 65 | install: msrsave/msrsave msrsave/msrsave.1 66 | $(INSTALL) -d $(DESTDIR)/$(sbindir) 67 | $(INSTALL) msrsave/msrsave $(DESTDIR)/$(sbindir) 68 | $(INSTALL) -d $(DESTDIR)/$(man1dir) 69 | $(INSTALL) -m 644 msrsave/msrsave.1 $(DESTDIR)/$(man1dir) 70 | 71 | install-spank: spank 72 | $(INSTALL) -d $(DESTDIR)/$(libdir)/slurm 73 | $(INSTALL) msrsave/libspank_msrsafe.so $(DESTDIR)/$(libdir)/slurm/libspank_msrsafe.so 74 | 75 | # The current spack package ignore this Makefile for building the 76 | # msr-safe.ko kernel module, as it is building against an arbitrary 77 | # version of the linux kernel and thus $(shell uname -r) is not useful. 78 | # 79 | # Installation relies on the spack package setting DESTDIR to the 80 | # msr-safe package prefix spec variable. 81 | # 82 | # Later iterations of the spack package might also build and install 83 | # msrsave. That will likely require a reworking of this Makefile. 84 | # Prefer single-source-of-truth in that case. 85 | spack-install: 86 | $(INSTALL) -d $(DESTDIR)/lib/modules 87 | $(INSTALL) msr-safe.ko $(DESTDIR)/lib/modules 88 | $(INSTALL) -d $(DESTDIR)/include 89 | $(INSTALL) msr_safe.h $(DESTDIR)/include 90 | 91 | .SUFFIXES: .c .o 92 | .PHONY: all module clean install spank install-spank 93 | -------------------------------------------------------------------------------- /examples/example.c: -------------------------------------------------------------------------------- 1 | /* This example assumes the user has the following permissions: 2 | * 3 | * write /dev/cpu/msr_allowlist 4 | * read/write /dev/cpu//msr_safe 5 | * read /dev/cpu/msr_batch 6 | * 7 | * Typically, only the administrator will have write permissions 8 | * on the allowlist. 9 | * 10 | * Production code should have more robust error handling than 11 | * what is shown here. 12 | * 13 | * This example should be able to run successfully on an x86 14 | * processor from the past ten years or so. 15 | * 16 | */ 17 | 18 | 19 | #include // printf(3) 20 | #include // assert(3) 21 | #include // open(2) 22 | #include // write(2), pwrite(2), pread(2) 23 | #include // strlen(3), memset(3) 24 | #include // uint8_t 25 | #include // PRIu8 26 | #include // exit(3) 27 | #include // ioctl(2) 28 | 29 | #include "../msr_safe.h" // batch data structs 30 | 31 | #define MSR_MPERF 0xE7 32 | 33 | char const *const allowlist = "0xE7 0xFFFFFFFFFFFFFFFF\n"; // MPERF 34 | 35 | static uint8_t const nCPUs = 32; 36 | 37 | void set_allowlist() 38 | { 39 | int fd = open("/dev/cpu/msr_allowlist", O_WRONLY); 40 | assert(-1 != fd); 41 | ssize_t nbytes = write(fd, allowlist, strlen(allowlist)); 42 | assert(strlen(allowlist) == nbytes); 43 | close(fd); 44 | } 45 | 46 | void measure_serial_latency() 47 | { 48 | int fd[nCPUs], rc; 49 | char filename[255]; 50 | uint64_t data[nCPUs]; 51 | memset(data, 0, sizeof(uint64_t)*nCPUs); 52 | 53 | // Open each of the msr_safe devices (one per CPU) 54 | for (uint8_t i = 0; i < nCPUs; i++) 55 | { 56 | rc = snprintf(filename, 254, "/dev/cpu/%"PRIu8"/msr_safe", i); 57 | assert(-1 != rc); 58 | fd[i] = open(filename, O_RDWR); 59 | assert(-1 != fd[i]); 60 | } 61 | // Write 0 to each MPERF register 62 | for (uint8_t i = 0; i < nCPUs; i++) 63 | { 64 | rc = pwrite(fd[i], &data[i], sizeof(uint64_t), MSR_MPERF); 65 | assert(8 == rc); 66 | } 67 | 68 | // Read each MPERF register 69 | for (uint8_t i = 0; i < nCPUs; i++) 70 | { 71 | pread(fd[i], &data[i], sizeof(uint64_t), MSR_MPERF); 72 | assert(8 == rc); 73 | } 74 | 75 | // Show results 76 | printf("Serial cycles from first write to last read:" 77 | "%"PRIu64" (on %"PRIu8" CPUs)\n", 78 | data[nCPUs - 1], nCPUs); 79 | } 80 | 81 | void measure_batch_latency() 82 | { 83 | struct msr_batch_array rbatch, wbatch; 84 | struct msr_batch_op r_ops[nCPUs], w_ops[nCPUs]; 85 | int fd, rc; 86 | 87 | fd = open("/dev/cpu/msr_batch", O_RDONLY); 88 | assert(-1 != fd); 89 | 90 | for (uint8_t i = 0; i < nCPUs; i++) 91 | { 92 | r_ops[i].cpu = w_ops[i].cpu = i; 93 | r_ops[i].isrdmsr = 1; 94 | w_ops[i].isrdmsr = 0; 95 | r_ops[i].msr = w_ops[i].msr = MSR_MPERF; 96 | w_ops[i].msrdata = 0; 97 | } 98 | rbatch.numops = wbatch.numops = nCPUs; 99 | rbatch.ops = r_ops; 100 | wbatch.ops = w_ops; 101 | 102 | rc = ioctl(fd, X86_IOC_MSR_BATCH, &wbatch); 103 | assert(-1 != rc); 104 | rc = ioctl(fd, X86_IOC_MSR_BATCH, &rbatch); 105 | assert(-1 != rc); 106 | 107 | printf("Batch cycles from first write to last read:" 108 | "%llu (on %"PRIu8" CPUs)\n", 109 | r_ops[nCPUs - 1].msrdata, nCPUs); 110 | } 111 | 112 | int main() 113 | { 114 | set_allowlist(); 115 | measure_serial_latency(); 116 | measure_batch_latency(); 117 | return 0; 118 | } 119 | -------------------------------------------------------------------------------- /rpm/msr-safe.spec: -------------------------------------------------------------------------------- 1 | %global tag %(git describe --tags --abbrev=0 | sed -e "s|^v||") 2 | %global rev %(git rev-parse HEAD) 3 | %global shortrev %(r=%{rev}; echo ${r:0:12}) 4 | 5 | Name: msr-safe 6 | Version: %{tag}.git%{shortrev}%{?dist} 7 | Release: 1 8 | License: GPLv2 9 | Summary: Allows safer access to model specific registers (MSRs) 10 | Url: https://github.com/LLNL/msr-safe 11 | Group: System Environment/Daemons 12 | Source0: https://github.com/LLNL/%{name}/archive/%{rev}.tar.gz#/%{name}-%{rev}.tar.gz 13 | Source1: msr-safe.service 14 | Source2: msr-safe.sysconfig 15 | Source3: 10-msr-safe.rules 16 | Source4: msr-safe.sh 17 | BuildRoot: %{_tmppath}/%{name}-%{version}-build 18 | BuildRequires: %kernel_module_package_buildreqs 19 | BuildRequires: systemd 20 | 21 | %kernel_module_package default 22 | 23 | %description 24 | Allows safer access to model specific registers (MSRs) 25 | 26 | %prep 27 | %autosetup -n %{name}-%{rev} 28 | 29 | %build 30 | for flavor in %flavors_to_build; do 31 | rm -rf obj/$flavor 32 | mkdir -p obj/$flavor 33 | cp -r msr* Makefile obj/$flavor 34 | %{__make} -C %{kernel_source $flavor} M=$PWD/obj/$flavor 35 | done 36 | %{__make} CPPFLAGS="-DVERSION=\\\"%{version}-%{release}\\\"" msrsave/msrsave 37 | 38 | %install 39 | %{__make} install DESTDIR=%{buildroot} prefix=%{_prefix} sbindir=%{_sbindir} mandir=%{_mandir} 40 | install -d %{buildroot}/%{_datadir}/msr-safe/allowlists 41 | install -m 0644 allowlists/* %{buildroot}/%{_datadir}/msr-safe/allowlists/ 42 | install -d %{buildroot}%{_unitdir} 43 | install -m 0644 %{SOURCE1} %{buildroot}%{_unitdir}/msr-safe.service 44 | install -d %{buildroot}/%{_sysconfdir}/sysconfig 45 | install -m 0644 %{SOURCE2} %{buildroot}/%{_sysconfdir}/sysconfig/msr-safe 46 | install -d %{buildroot}/%{_udevrulesdir} 47 | install -m 0644 %{SOURCE3} %{buildroot}/%{_udevrulesdir}/10-msr-safe.rules 48 | install -d %{buildroot}%{_sbindir} 49 | install -m 0755 %{SOURCE4} %{buildroot}%{_sbindir}/msr-safe 50 | 51 | export INSTALL_MOD_PATH=$RPM_BUILD_ROOT 52 | export INSTALL_MOD_DIR=extra/%{name} 53 | for flavor in %flavors_to_build ; do 54 | make -C %{kernel_source $flavor} modules_install \ 55 | M=$PWD/obj/$flavor 56 | done 57 | 58 | %clean 59 | rm -rf %{buildroot} 60 | 61 | %pre 62 | getent group msr >/dev/null || groupadd -r msr 63 | exit 0 64 | 65 | %post 66 | /usr/bin/udevadm control --reload-rules 67 | if which weak-modules >/dev/null 2>&1; then 68 | echo /lib/modules/%{latest_kernel}/extra/msr-safe/msr-safe.ko | weak-modules --add-modules 69 | fi 70 | /usr/bin/systemctl daemon-reload >/dev/null 2>&1 71 | /usr/bin/systemctl enable msr-safe >/dev/null 2>&1 || : 72 | 73 | %preun 74 | if [ $1 -eq 0 ] ; then 75 | /usr/bin/systemctl stop msr-safe >/dev/null 2>&1 76 | /usr/bin/systemctl disable msr-safe >/dev/null 2>&1 77 | fi 78 | if which weak-modules >/dev/null 2>&1; then 79 | echo /lib/modules/%{latest_kernel}/extra/msr-safe/msr-safe.ko | weak-modules --remove-modules 80 | fi 81 | 82 | %postun 83 | if [ "$1" -ge "1" ] ; then 84 | /usr/bin/systemctl try-restart msr-safe >/dev/null 2>&1 || : 85 | fi 86 | 87 | %files 88 | %defattr(-,root,root,-) 89 | %{_datadir}/msr-safe/allowlists/* 90 | %{_unitdir}/msr-safe.service 91 | %{_udevrulesdir}/10-msr-safe.rules 92 | %config %{_sysconfdir}/sysconfig/msr-safe 93 | %doc README 94 | %{_sbindir}/msrsave 95 | %{_sbindir}/msr-safe 96 | %dir %{_mandir}/man1 97 | %doc %{_mandir}/man1/msrsave.1.gz 98 | 99 | 100 | %changelog 101 | * Fri Sep 11 2020 Stephanie Brink 102 | - Update license 103 | * Tue Aug 23 2017 Ben Allen 9240638-4 104 | - Rev package version to 0.4 105 | * Tue Jan 17 2017 Ben Allen 7bfb843-2 106 | - Rev package version to 0.2 107 | * Mon Dec 05 2016 Christopher M. Cantalupo 108 | - Add msrsave application build and install. 109 | * Wed Apr 20 2016 Ben Allen 7667118-1 110 | - Initial release (v7667118) 111 | 112 | -------------------------------------------------------------------------------- /msr_version.c: -------------------------------------------------------------------------------- 1 | // Copyright 2011-2021 Lawrence Livermore National Security, LLC and other 2 | // msr-safe Project Developers. See the top-level COPYRIGHT file for 3 | // details. 4 | // 5 | // SPDX-License-Identifier: GPL-2.0-only 6 | 7 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "msr_version.h" 16 | 17 | static struct class *cdev_class; 18 | static char cdev_created; 19 | static char cdev_registered; 20 | static char cdev_class_created; 21 | 22 | static int open_version(struct inode *inode, struct file *file) 23 | { 24 | return 0; 25 | } 26 | 27 | static ssize_t read_version(struct file *file, char __user *buf, size_t count, loff_t *ppos) 28 | { 29 | size_t len = strlen( THIS_MODULE->version ) + 1 < count ? 30 | strlen( THIS_MODULE->version ) + 1 : 31 | count; 32 | if (*ppos > 0) 33 | { 34 | return 0; 35 | } 36 | if (len > count) 37 | { 38 | return -EFAULT; 39 | } 40 | if (copy_to_user(buf, THIS_MODULE->version, len)) 41 | { 42 | return -EFAULT; 43 | } 44 | *ppos = 1; 45 | return len; 46 | } 47 | 48 | static const struct file_operations fops = 49 | { 50 | .owner = THIS_MODULE, 51 | .read = read_version, 52 | .open = open_version 53 | }; 54 | 55 | #define msr_version_nodename_selector _Generic(\ 56 | (((struct class *)0)->devnode),\ 57 | char * (*) ( struct device *, mode_t *) : msr_version_nodename1,\ 58 | char * (*) ( struct device *, umode_t *) : msr_version_nodename2,\ 59 | char * (*) (const struct device *, umode_t *) : msr_version_nodename3 \ 60 | ) 61 | 62 | static char *msr_version_nodename1(struct device *dev, mode_t *mode) 63 | { 64 | if (mode) 65 | { 66 | *mode = 0400; // read-only 67 | } 68 | return kasprintf(GFP_KERNEL, "cpu/msr_safe_version"); 69 | } 70 | 71 | static char *msr_version_nodename2(struct device *dev, umode_t *mode) 72 | { 73 | if (mode) 74 | { 75 | *mode = 0400; // read-only 76 | } 77 | return kasprintf(GFP_KERNEL, "cpu/msr_safe_version"); 78 | } 79 | 80 | static char *msr_version_nodename3(const struct device *dev, umode_t *mode) 81 | { 82 | if (mode) 83 | { 84 | *mode = 0400; // read-only 85 | } 86 | return kasprintf(GFP_KERNEL, "cpu/msr_safe_version"); 87 | } 88 | 89 | void msr_version_cleanup(int majordev) 90 | { 91 | if (cdev_created) 92 | { 93 | cdev_created = 0; 94 | device_destroy(cdev_class, MKDEV(majordev, 0)); 95 | } 96 | 97 | if (cdev_class_created) 98 | { 99 | cdev_class_created = 0; 100 | class_destroy(cdev_class); 101 | } 102 | 103 | if (cdev_registered) 104 | { 105 | cdev_registered = 0; 106 | unregister_chrdev(majordev, "cpu/msr_safe_version"); 107 | } 108 | } 109 | 110 | int msr_version_init(int *majordev) 111 | { 112 | int err = 0; 113 | struct device *dev; 114 | 115 | err = register_chrdev(*majordev, "cpu/msr_safe_version", &fops); 116 | if (err < 0) 117 | { 118 | pr_debug("%s: unable to register chrdev\n", __FUNCTION__); 119 | msr_version_cleanup(*majordev); 120 | err = -EBUSY; 121 | return err; 122 | } 123 | if (err > 0) 124 | { 125 | *majordev = err; 126 | } 127 | cdev_registered = 1; 128 | 129 | cdev_class = class_create( 130 | #if LINUX_VERSION_CODE < KERNEL_VERSION(6,4,0) 131 | THIS_MODULE, 132 | #endif 133 | "msr_safe_version"); 134 | if (IS_ERR(cdev_class)) 135 | { 136 | err = PTR_ERR(cdev_class); 137 | msr_version_cleanup(*majordev); 138 | return err; 139 | } 140 | cdev_class_created = 1; 141 | 142 | cdev_class->devnode = msr_version_nodename_selector; 143 | 144 | dev = device_create(cdev_class, NULL, MKDEV(*majordev, 0), NULL, "msr_safe_version"); 145 | if (IS_ERR(dev)) 146 | { 147 | err = PTR_ERR(dev); 148 | msr_version_cleanup(*majordev); 149 | return err; 150 | } 151 | cdev_created = 1; 152 | return 0; 153 | } 154 | -------------------------------------------------------------------------------- /msrsave/msrsave_main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Intel Corporation 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "msrsave.h" 17 | #include "../msr_version.h" 18 | 19 | int main(int argc, char **argv) 20 | { 21 | const char *usage = "NAME\n" 22 | " msrsave - msr-safe save and restore application\n" 23 | "\n" 24 | "SYNOPSIS\n" 25 | " SAVE MSR:\n" 26 | " msrsave outfile\n" 27 | "\n" 28 | " RESTORE MSR:\n" 29 | " msrsave -r infile\n" 30 | "\n" 31 | " PRINT VERSION OR HELP:\n" 32 | " msrsave --version | --help\n" 33 | "\n" 34 | "DESCRIPTION\n" 35 | " The msrsave application is used to save to a file the state of all write\n" 36 | " accessible MSR values defined in the current MSR allowlist or restore the MSR\n" 37 | " values from a saved state file. The msrsave application also respects the\n" 38 | " standard --version and --help options for printing the msr-safe pack-\n" 39 | " age version or a brief message about usage.\n" 40 | "\n" 41 | "OPTIONS\n" 42 | " --help\n" 43 | " Print brief summary of the command line usage information, then exit.\n" 44 | "\n" 45 | " --version\n" 46 | " Print version of msr-safe package to standard output, then exit.\n" 47 | "\n" 48 | " -r\n" 49 | " Restore the MSR values that are recorded in an existing MSR saved state\n" 50 | " file.\n" 51 | "\n" 52 | "COPYRIGHT\n" 53 | " Copyright (C) 2016, Intel Corporation. All rights reserved.\n" 54 | "\n" 55 | "\n"; 56 | 57 | if (argc > 1 && strncmp(argv[1], "--version", strlen("--version") + 1) == 0) 58 | { 59 | printf("%s\n", MSR_SAFE_VERSION_STR); 60 | printf("\nCopyright (C) 2016, Intel Corporation. All rights reserved.\n\n"); 61 | return 0; 62 | } 63 | if (argc > 1 && (strncmp(argv[1], "--help", strlen("--help") + 1) == 0 || strncmp(argv[1], "-h", strlen("-h") + 1) == 0)) 64 | { 65 | printf(usage, argv[0]); 66 | return 0; 67 | } 68 | 69 | int err = 0; 70 | int do_restore = 0; 71 | int opt = 0; 72 | 73 | while (!err && (opt = getopt(argc, argv, "r")) != -1) 74 | { 75 | switch (opt) 76 | { 77 | case 'r': 78 | do_restore = 1; 79 | break; 80 | default: 81 | fprintf(stderr, "Error: Unknown parameter \"%c\"\n\n", opt); 82 | fprintf(stderr, usage, argv[0]); 83 | err = EINVAL; 84 | break; 85 | } 86 | } 87 | 88 | if (!err && optind == argc) 89 | { 90 | fprintf(stderr, "Error: No file name specified.\n\n"); 91 | fprintf(stderr, usage, argv[0]); 92 | err = EINVAL; 93 | } 94 | 95 | if (!err) 96 | { 97 | const char *file_name = argv[optind]; 98 | const char *msr_path = "/dev/cpu/%d/msr_safe"; 99 | const char *msr_allowlist_path = "/dev/cpu/msr_allowlist"; 100 | int num_cpu = sysconf(_SC_NPROCESSORS_ONLN); 101 | if (do_restore) 102 | { 103 | err = msr_restore(file_name, msr_allowlist_path, msr_path, num_cpu, stdout, stderr); 104 | } 105 | else 106 | { 107 | err = msr_save(file_name, msr_allowlist_path, msr_path, num_cpu, stdout, stderr); 108 | } 109 | } 110 | 111 | return err; 112 | } 113 | -------------------------------------------------------------------------------- /msr_batch.c: -------------------------------------------------------------------------------- 1 | // Copyright 2011-2021 Lawrence Livermore National Security, LLC and other 2 | // msr-safe Project Developers. See the top-level COPYRIGHT file for 3 | // details. 4 | // 5 | // SPDX-License-Identifier: GPL-2.0-only 6 | 7 | /* 8 | * x86 MSR batch access device 9 | * 10 | * This device is accessed by ioctl() to submit a batch of MSR requests 11 | * which may be used instead of or in addition to the lseek()/write()/read() 12 | * mechanism provided by msr_safe.c 13 | * 14 | * This driver uses /dev/cpu/msr_batch as its device file. 15 | */ 16 | 17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "msr_batch.h" 33 | #include "msr_safe.h" 34 | #include "msr-smp.h" 35 | #include "msr_allowlist.h" 36 | 37 | static struct class *cdev_class; 38 | static char cdev_created; 39 | static char cdev_registered; 40 | static char cdev_class_created; 41 | 42 | static int msrbatch_apply_allowlist(struct msr_batch_array *oa) 43 | { 44 | struct msr_batch_op *op; 45 | int err = 0; 46 | 47 | for (op = oa->ops; op < oa->ops + oa->numops; ++op) 48 | { 49 | op->err = 0; 50 | 51 | if (op->cpu >= nr_cpu_ids || !cpu_online(op->cpu)) 52 | { 53 | pr_debug("No such CPU %d\n", op->cpu); 54 | op->err = err = -ENXIO; // No such CPU 55 | continue; 56 | } 57 | 58 | if (!msr_allowlist_maskexists(op->msr)) 59 | { 60 | pr_debug("No allowlist entry for MSR %x\n", op->msr); 61 | op->err = err = -EACCES; 62 | } 63 | else 64 | { 65 | op->wmask = msr_allowlist_writemask(op->msr); 66 | /* Check for read-only case */ 67 | if (op->wmask == 0 && !op->isrdmsr) 68 | { 69 | pr_debug("MSR %x is read-only\n", op->msr); 70 | op->err = err = -EROFS; 71 | } 72 | } 73 | } 74 | return err; 75 | } 76 | 77 | static long msrbatch_ioctl(struct file *f, unsigned int ioc, unsigned long arg) 78 | { 79 | int err = 0; 80 | struct msr_batch_array __user *uoa; 81 | struct msr_batch_op __user *uops; 82 | struct msr_batch_array koa; 83 | 84 | if (ioc != X86_IOC_MSR_BATCH) 85 | { 86 | pr_debug("Invalid ioctl op %u\n", ioc); 87 | return -ENOTTY; 88 | } 89 | 90 | if (!(f->f_mode & FMODE_READ)) 91 | { 92 | pr_debug("File not open for reading\n"); 93 | return -EBADF; 94 | } 95 | 96 | uoa = (struct msr_batch_array *)arg; 97 | 98 | if (copy_from_user(&koa, uoa, sizeof(koa))) 99 | { 100 | pr_debug("Copy of batch array descriptor failed\n"); 101 | return -EFAULT; 102 | } 103 | 104 | if (koa.numops <= 0) 105 | { 106 | pr_debug("Invalid # of ops %d\n", koa.numops); 107 | return -EINVAL; 108 | } 109 | 110 | uops = koa.ops; 111 | 112 | koa.ops = kmalloc_array(koa.numops, sizeof(*koa.ops), GFP_KERNEL); 113 | if (!koa.ops) 114 | { 115 | return -E2BIG; 116 | } 117 | 118 | if (copy_from_user(koa.ops, uops, koa.numops * sizeof(*koa.ops))) 119 | { 120 | pr_debug("Copy of batch array failed\n"); 121 | err = -EFAULT; 122 | goto bundle_alloc; 123 | } 124 | 125 | err = msrbatch_apply_allowlist(&koa); 126 | if (err) 127 | { 128 | pr_debug("Failed to apply allowlist %d\n", err); 129 | goto copyout_and_return; 130 | } 131 | 132 | err = msr_safe_batch(&koa); 133 | if (err != 0) 134 | { 135 | pr_debug("msr_safe_batch failed: %d\n", err); 136 | goto copyout_and_return; 137 | } 138 | 139 | copyout_and_return: 140 | if (copy_to_user(uops, koa.ops, koa.numops * sizeof(*uops))) 141 | { 142 | pr_debug("copy batch data back to user failed\n"); 143 | if (!err) 144 | { 145 | err = -EFAULT; 146 | } 147 | } 148 | bundle_alloc: 149 | kfree(koa.ops); 150 | 151 | return err; 152 | } 153 | 154 | static const struct file_operations fops = 155 | { 156 | .owner = THIS_MODULE, 157 | .unlocked_ioctl = msrbatch_ioctl, 158 | .compat_ioctl = msrbatch_ioctl 159 | }; 160 | 161 | void msrbatch_cleanup(int majordev) 162 | { 163 | if (cdev_created) 164 | { 165 | cdev_created = 0; 166 | device_destroy(cdev_class, MKDEV(majordev, 0)); 167 | } 168 | 169 | if (cdev_class_created) 170 | { 171 | cdev_class_created = 0; 172 | class_destroy(cdev_class); 173 | } 174 | 175 | if (cdev_registered) 176 | { 177 | cdev_registered = 0; 178 | unregister_chrdev(majordev, "cpu/msr_batch"); 179 | } 180 | } 181 | 182 | #define msrbatch_nodename_selector _Generic(\ 183 | (((struct class *)0)->devnode),\ 184 | char* (*) ( struct device *, mode_t *) : msrbatch_nodename1,\ 185 | char* (*) ( struct device *, umode_t *) : msrbatch_nodename2,\ 186 | char* (*) (const struct device *, umode_t *) : msrbatch_nodename3 \ 187 | ) 188 | 189 | static char *msrbatch_nodename1(struct device *dev, mode_t *mode) 190 | { 191 | return kasprintf(GFP_KERNEL, "cpu/msr_batch"); 192 | } 193 | 194 | static char *msrbatch_nodename2(struct device *dev, umode_t *mode) 195 | { 196 | return kasprintf(GFP_KERNEL, "cpu/msr_batch"); 197 | } 198 | 199 | static char *msrbatch_nodename3(const struct device *dev, umode_t *mode) 200 | { 201 | return kasprintf(GFP_KERNEL, "cpu/msr_batch"); 202 | } 203 | 204 | int msrbatch_init(int *majordev) 205 | { 206 | int err = 0; 207 | struct device *dev; 208 | 209 | err = register_chrdev(*majordev, "cpu/msr_batch", &fops); 210 | if (err < 0) 211 | { 212 | pr_debug("%s: unable to register chrdev\n", __FUNCTION__); 213 | msrbatch_cleanup(*majordev); 214 | return -EBUSY; 215 | } 216 | if (err > 0) 217 | { 218 | *majordev = err; 219 | } 220 | cdev_registered = 1; 221 | 222 | cdev_class = class_create( 223 | #if LINUX_VERSION_CODE < KERNEL_VERSION(6,4,0) 224 | THIS_MODULE, 225 | #endif 226 | "msr_batch"); 227 | if (IS_ERR(cdev_class)) 228 | { 229 | err = PTR_ERR(cdev_class); 230 | msrbatch_cleanup(*majordev); 231 | return err; 232 | } 233 | cdev_class_created = 1; 234 | 235 | cdev_class->devnode = msrbatch_nodename_selector; 236 | 237 | dev = device_create(cdev_class, NULL, MKDEV(*majordev, 0), NULL, "msr_batch"); 238 | if (IS_ERR(dev)) 239 | { 240 | err = PTR_ERR(dev); 241 | msrbatch_cleanup(*majordev); 242 | return err; 243 | } 244 | cdev_created = 1; 245 | return 0; 246 | } 247 | -------------------------------------------------------------------------------- /msrsave/spank_msrsafe.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Intel Corporation 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | /* 8 | * The msr-safe Linux kernel module enables user access to read and 9 | * write capabilities for a restricted set of allowed Model 10 | * Specific Registers (MSRs) on x86 platforms. The purpose of this 11 | * slurm plugin is to ensure that MSRs modified within a user's slurm 12 | * job allocation are reset to their original state before the compute 13 | * node is returned to the pool available to other users of the 14 | * system. The msr-safe kernel module is targeting HPC systems that 15 | * enforce single user occupancy per compute node, and is not 16 | * appropriate for systems where compute nodes are shared between 17 | * users. The modifications that one user makes to allowed 18 | * registers may impact subsequent users of the processor if not 19 | * restored. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "slurm/spank.h" 31 | 32 | #include "msrsave.h" 33 | 34 | #define SLURM_SPANK_MSRSAFE_BUFFER_SIZE 1024 35 | 36 | SPANK_PLUGIN(msr-safe, 1); 37 | 38 | int slurm_spank_init(spank_t spank_ctx, int argc, char **argv); 39 | int slurm_spank_slurmd_init(spank_t spank_ctx, int argc, char **argv); 40 | int slurm_spank_job_prolog(spank_t spank_ctx, int argc, char **argv); 41 | int slurm_spank_job_epilog(spank_t spank_ctx, int argc, char **argv); 42 | 43 | static int slurm_spank_msrsafe_read_log(FILE *log_fid); 44 | 45 | #ifdef SLURM_SPANK_MSRSAVE_TEST 46 | /* If test is defined then print to standard output rather 47 | than slurm log. */ 48 | 49 | #include 50 | #define slurm_info printf 51 | 52 | int main(int argc, char **argv) 53 | { 54 | spank_t spank_ctx; 55 | printf("SAVE SCRIPT:\n"); 56 | slurm_spank_job_prolog(spank_ctx, 0, NULL); 57 | printf("\n\nRESTORE SCRIPT:\n"); 58 | slurm_spank_job_epilog(spank_ctx, 0, NULL); 59 | printf("\n\n"); 60 | return 0; 61 | } 62 | /* END TEST PROGRAM */ 63 | 64 | #endif 65 | 66 | static int slurm_spank_msrsafe_read_log(FILE *log_fid) 67 | { 68 | char buffer[SLURM_SPANK_MSRSAFE_BUFFER_SIZE]; 69 | size_t buffer_pos = 0; 70 | int err = 0; 71 | int character = 0; 72 | 73 | if (log_fid == NULL) { 74 | err = 1; 75 | } 76 | else { 77 | do { 78 | character = fgetc(log_fid); 79 | if (character == '\n' || 80 | character == EOF || 81 | buffer_pos == SLURM_SPANK_MSRSAFE_BUFFER_SIZE - 1) { 82 | buffer[buffer_pos] = '\0'; 83 | slurm_info("%s", buffer); 84 | buffer_pos = 0; 85 | } 86 | else { 87 | buffer[buffer_pos] = character; 88 | ++buffer_pos; 89 | } 90 | } while (character != EOF); 91 | } 92 | return err; 93 | } 94 | 95 | #ifndef SLURM_SPANK_MSRSAVE_FILE_PREFIX 96 | #define SLURM_SPANK_MSRSAVE_FILE_PREFIX "/var/run/slurm-msrsave" 97 | #endif 98 | 99 | int slurm_spank_init(spank_t spank_ctx, int argc, char **argv) 100 | { 101 | slurm_info("Loaded msrsave restore plugin."); 102 | return 0; 103 | } 104 | 105 | int slurm_spank_slurmd_init(spank_t spank_ctx, int argc, char **argv) 106 | { 107 | slurm_info("Loaded msrsave restore plugin."); 108 | } 109 | 110 | int slurm_spank_job_prolog(spank_t spank_ctx, int argc, char **argv) 111 | { 112 | slurm_info("Running msr-safe plugin to save register values."); 113 | 114 | int err = 0; 115 | FILE *out_log = NULL; 116 | char out_log_name[NAME_MAX * 2]; 117 | char msrsave_file[NAME_MAX * 2]; 118 | const char *allowlist_path = "/dev/cpu/msr_allowlist"; 119 | const char *msr_path = "/dev/cpu/%d/msr_safe"; 120 | int num_cpu = sysconf(_SC_NPROCESSORS_ONLN); 121 | char hostname[NAME_MAX]; 122 | hostname[NAME_MAX - 1] = '\0'; 123 | err = gethostname(hostname, NAME_MAX - 1); 124 | if (err) { 125 | slurm_info("gethostname failed."); 126 | } 127 | if (!err) { 128 | snprintf(out_log_name, NAME_MAX * 2, "/tmp/slurm-msrsave-outlog-%s.XXXXXXXXXX", hostname); 129 | err = mkstemp(out_log_name); 130 | if (err) { 131 | slurm_info("failed to create msrsave output log"); 132 | } 133 | } 134 | if (!err) { 135 | out_log = fopen(out_log_name, "w+"); 136 | if (out_log == NULL) { 137 | slurm_info("failed to open %s for writing", out_log_name); 138 | } 139 | } 140 | if (!err) { 141 | snprintf(msrsave_file, NAME_MAX * 2, "%s-%s", SLURM_SPANK_MSRSAVE_FILE_PREFIX, hostname); 142 | err = msr_save(msrsave_file, allowlist_path, msr_path, num_cpu, out_log, out_log); 143 | if (err) { 144 | slurm_info("msr_save failed:"); 145 | } 146 | rewind(out_log); 147 | slurm_spank_msrsafe_read_log(out_log); 148 | } 149 | if (!err) { 150 | slurm_info("Completed msr-safe plugin to save register values."); 151 | } 152 | if (out_log) { 153 | fclose(out_log); 154 | unlink(out_log_name); 155 | } 156 | return err; 157 | } 158 | 159 | int slurm_spank_job_epilog(spank_t spank_ctx, int argc, char **argv) 160 | { 161 | slurm_info("Running msr-safe plugin to restore register values."); 162 | int err = 0; 163 | FILE *out_log = NULL; 164 | char out_log_name[NAME_MAX * 2]; 165 | char msrsave_file[NAME_MAX * 2]; 166 | const char *allowlist_path = "/dev/cpu/msr_allowlist"; 167 | const char *msr_path = "/dev/cpu/%d/msr_safe"; 168 | int num_cpu = sysconf(_SC_NPROCESSORS_ONLN); 169 | char hostname[NAME_MAX]; 170 | hostname[NAME_MAX - 1] = '\0'; 171 | err = gethostname(hostname, NAME_MAX - 1); 172 | if (err) { 173 | slurm_info("gethostname failed."); 174 | } 175 | if (!err) { 176 | snprintf(out_log_name, NAME_MAX * 2, "/tmp/slurm-msrsave-outlog-%s.XXXXXXXXXX", hostname); 177 | err = mkstemp(out_log_name); 178 | if (err) { 179 | slurm_info("failed to create msrsave output log"); 180 | } 181 | } 182 | if (!err) { 183 | out_log = fopen(out_log_name, "w+"); 184 | if (out_log == NULL) { 185 | slurm_info("failed to open %s for writing", out_log_name); 186 | } 187 | } 188 | if (!err) { 189 | snprintf(msrsave_file, NAME_MAX * 2, "%s-%s", SLURM_SPANK_MSRSAVE_FILE_PREFIX, hostname); 190 | err = msr_restore(msrsave_file, allowlist_path, msr_path, num_cpu, out_log, out_log); 191 | if (err) { 192 | slurm_info("msr_restore failed:"); 193 | } 194 | rewind(out_log); 195 | slurm_spank_msrsafe_read_log(out_log); 196 | } 197 | if (!err) { 198 | slurm_info("Completed msr-safe plugin to restore register values."); 199 | } 200 | if (out_log) { 201 | fclose(out_log); 202 | unlink(out_log_name); 203 | } 204 | return err; 205 | } 206 | 207 | #undef SLURM_SPANK_MSRSAVE_FILE_PREFIX 208 | -------------------------------------------------------------------------------- /msrsave/msrsave_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Intel Corporation 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "msrsave.h" 16 | 17 | void msrsave_test_mock_msr(void *buffer, size_t buffer_size, const char *path_format, int num_cpu); 18 | void msrsave_test_check_msr(uint64_t *buffer, size_t num_check, const char *path_format, int num_cpu); 19 | 20 | void msrsave_test_mock_msr(void *buffer, size_t buffer_size, const char *path_format, int num_cpu) 21 | { 22 | /* Create mock msr files for each CPU */ 23 | int i; 24 | char this_path[NAME_MAX] = {}; 25 | for (i = 0; i < num_cpu; ++i) 26 | { 27 | snprintf(this_path, NAME_MAX, path_format, i); 28 | FILE *fid = fopen(this_path, "w"); 29 | assert(fid != 0); 30 | fwrite(buffer, 1, buffer_size, fid); 31 | fclose(fid); 32 | } 33 | } 34 | 35 | void msrsave_test_check_msr(uint64_t *check_val, size_t num_check, const char *path_format, int num_cpu) 36 | { 37 | /* Check that values in the file match expected */ 38 | int i, j; 39 | char this_path[NAME_MAX] = {}; 40 | uint64_t *read_val = malloc(num_check * sizeof(uint64_t)); 41 | assert(read_val != NULL); 42 | for (i = 0; i < num_cpu; ++i) 43 | { 44 | snprintf(this_path, NAME_MAX, path_format, i); 45 | FILE *fid = fopen(this_path, "r"); 46 | assert(fid != 0); 47 | fread(read_val, sizeof(uint64_t), num_check, fid); 48 | fclose(fid); 49 | for (j = 0; j < num_check; ++j) 50 | { 51 | assert(check_val[j] == read_val[j]); 52 | } 53 | } 54 | free(read_val); 55 | } 56 | 57 | int main(int argc, char **argv) 58 | { 59 | int err = 0; 60 | const uint64_t allowlist_off[] = {0x0000000000000000ULL, 61 | 0x0000000000000008ULL, 62 | 0x0000000000000010ULL, 63 | 0x0000000000000018ULL, 64 | 0x0000000000000020ULL, 65 | 0x0000000000000028ULL, 66 | 0x0000000000000030ULL, 67 | 0x0000000000000038ULL, 68 | 0x0000000000000040ULL, 69 | 0x0000000000000048ULL, 70 | 0x0000000000000050ULL, 71 | 0x0000000000000058ULL, 72 | 0x0000000000000060ULL, 73 | 0x0000000000000068ULL, 74 | 0x0000000000000070ULL, 75 | 0x0000000000000078ULL, 76 | 0x0000000000000080ULL, 77 | 0x0000000000000088ULL, 78 | 0x0000000000000090ULL, 79 | 0x0000000000000098ULL, 80 | 0x1000000000000100ULL /* negative offset should be skipped */ 81 | }; 82 | 83 | const uint64_t allowlist_mask[] = {0x8000000000000000ULL, 84 | 0x8000000000000000ULL, 85 | 0x8000000000000000ULL, 86 | 0x8000000000000000ULL, 87 | 0x8000000000000000ULL, 88 | 0x8000000000000000ULL, 89 | 0x8000000000000000ULL, 90 | 0x8000000000000000ULL, 91 | 0x8000000000000000ULL, 92 | 0x8000000000000000ULL, 93 | 0x8000000000000000ULL, 94 | 0x8000000000000000ULL, 95 | 0x8000000000000000ULL, 96 | 0x8000000000000000ULL, 97 | 0x8000000000000000ULL, 98 | 0x8000000000000000ULL, 99 | 0x8000000000000000ULL, 100 | 0x8000000000000000ULL, 101 | 0x8000000000000000ULL, 102 | 0xFFFFFFFFFFFFFFFFULL, 103 | 0x8000000000000000ULL}; 104 | 105 | enum {NUM_MSR = sizeof(allowlist_off) / sizeof(uint64_t)}; 106 | assert(NUM_MSR == sizeof(allowlist_mask) / sizeof(uint64_t)); 107 | const char *test_save_path = "msrsave_test_store"; 108 | const char *test_allowlist_path = "msrsave_test_allowlist"; 109 | const char *test_msr_path = "msrsave_test_msr.%d"; 110 | const char *allowlist_format = "0x%.8zX 0x%.16zX\n"; 111 | const int num_cpu = 10; 112 | int i; 113 | 114 | /* Create a mock white list from the data in the constants above. */ 115 | FILE *fid = fopen(test_allowlist_path, "w"); 116 | assert(fid != NULL); 117 | for (i = 0; i < NUM_MSR; ++i) 118 | { 119 | fprintf(fid, allowlist_format, allowlist_off[i], allowlist_mask[i]); 120 | } 121 | fclose(fid); 122 | 123 | uint64_t lval = 0x0; 124 | uint64_t hval = 0xDEADBEEF; 125 | uint64_t msr_val[NUM_MSR]; 126 | 127 | /* Create mock msr data */ 128 | for (i = 0; i < NUM_MSR; ++i) 129 | { 130 | lval = i; 131 | msr_val[i] = lval | (hval << 32); 132 | } 133 | 134 | msrsave_test_mock_msr(msr_val, sizeof(msr_val), test_msr_path, num_cpu); 135 | 136 | const char *log_file_name = "msrsave_test.log"; 137 | FILE *log_file = fopen(log_file_name, "w"); 138 | /* Save the current state to a file */ 139 | err = msr_save(test_save_path, test_allowlist_path, test_msr_path, num_cpu, log_file, log_file); 140 | assert(err == 0); 141 | 142 | /* Overwrite the mock msr files with new data */ 143 | /* This modifies both bit 63 and bit 62 from the original value 144 | however only bit 63 is covered by the write mask and will be restored. */ 145 | hval = 0x1EADBEEF; 146 | for (i = 0; i < NUM_MSR; ++i) 147 | { 148 | lval = NUM_MSR - i; 149 | msr_val[i] = lval | (hval << 32); 150 | } 151 | 152 | msrsave_test_mock_msr(msr_val, sizeof(msr_val), test_msr_path, num_cpu); 153 | 154 | /* Restore to the original values */ 155 | err = msr_restore(test_save_path, test_allowlist_path, test_msr_path, num_cpu, log_file, log_file); 156 | assert(err == 0); 157 | 158 | /* Check that the values that are writable have been restored. */ 159 | /* Check that the values that are not writable have been unaltered. */ 160 | hval = 0x9EADBEEF; 161 | for (i = 0; i < NUM_MSR - 1; ++i) 162 | { 163 | if (allowlist_mask[i] & 0xFFFFFFFF) { 164 | msr_val[i] = 0xDEADBEEF00000000 | i; 165 | } 166 | else { 167 | lval = NUM_MSR - i; 168 | msr_val[i] = lval | (hval << 32); 169 | } 170 | } 171 | 172 | msrsave_test_check_msr(msr_val, sizeof(msr_val) / sizeof(uint64_t), test_msr_path, num_cpu); 173 | 174 | char this_path[NAME_MAX] = {}; 175 | for (i = 0; i < num_cpu; ++i) 176 | { 177 | snprintf(this_path, NAME_MAX, test_msr_path, i); 178 | unlink(this_path); 179 | } 180 | unlink(test_allowlist_path); 181 | unlink(test_save_path); 182 | fclose(log_file); 183 | if (!err) { 184 | unlink(log_file_name); 185 | } 186 | return err; 187 | } 188 | -------------------------------------------------------------------------------- /msr_entry.c: -------------------------------------------------------------------------------- 1 | // Copyright 2011-2020 Lawrence Livermore National Security, LLC and other 2 | // msr-safe Project Developers. See the top-level COPYRIGHT file for 3 | // details. 4 | // 5 | // SPDX-License-Identifier: GPL-2.0-only 6 | 7 | // Copyright 2000-2008 H. Peter Anvin - All Rights Reserved 8 | // Copyright 2009 Intel Corporation; author: H. Peter Anvin 9 | // 10 | // SPDX-License-Identifier: GPL-2.0-or-later 11 | 12 | /* 13 | * x86 MSR access device 14 | * 15 | * This device is accessed by lseek() to the appropriate register number 16 | * and then read/write in chunks of 8 bytes. A larger size means multiple 17 | * reads or writes of the same register. 18 | * 19 | * This driver uses /dev/cpu/%d/msr where %d is the minor number, and on 20 | * an SMP box will direct the access to CPU %d. 21 | */ 22 | 23 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #include "msr_batch.h" 45 | #include "msr_allowlist.h" 46 | #include "msr_version.h" 47 | 48 | static struct class *msr_class; 49 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) 50 | static enum cpuhp_state cpuhp_msr_state; 51 | #endif 52 | static int mdev_msr_safe; 53 | static int mdev_msr_allowlist; 54 | static int mdev_msr_batch; 55 | static int mdev_msr_version; 56 | 57 | module_param(mdev_msr_safe, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 58 | MODULE_PARM_DESC(mdev_msr_safe, "Major number for msr_safe (int)."); 59 | module_param(mdev_msr_allowlist, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 60 | MODULE_PARM_DESC(mdev_msr_allowlist, "Major number for msr_allowlist (int)."); 61 | module_param(mdev_msr_batch, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 62 | MODULE_PARM_DESC(mdev_msr_batch, "Major number for msr_batch (int)."); 63 | module_param(mdev_msr_version, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 64 | MODULE_PARM_DESC(mdev_msr_version, "Major number for msr_version (int)."); 65 | 66 | static loff_t msr_seek(struct file *file, loff_t offset, int orig) 67 | { 68 | loff_t ret; 69 | struct inode *inode = file->f_mapping->host; 70 | 71 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0) 72 | inode_lock(inode); 73 | #else 74 | mutex_lock(&inode->i_mutex); 75 | #endif 76 | switch (orig) 77 | { 78 | case SEEK_SET: 79 | file->f_pos = offset; 80 | ret = file->f_pos; 81 | break; 82 | case SEEK_CUR: 83 | file->f_pos += offset; 84 | ret = file->f_pos; 85 | break; 86 | default: 87 | ret = -EINVAL; 88 | } 89 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0) 90 | inode_unlock(inode); 91 | #else 92 | mutex_unlock(&inode->i_mutex); 93 | #endif 94 | return ret; 95 | } 96 | 97 | static ssize_t msr_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) 98 | { 99 | u32 __user *tmp = (u32 __user *) buf; 100 | u32 data[2]; 101 | u32 reg = *ppos; 102 | int cpu = iminor(file->f_path.dentry->d_inode); 103 | int err = 0; 104 | 105 | if (count != 8) 106 | { 107 | return -EINVAL; /* Single read only.*/ 108 | } 109 | 110 | if (!msr_allowlist_maskexists(reg)) 111 | { 112 | return -EACCES; 113 | } 114 | 115 | err = rdmsr_safe_on_cpu(cpu, reg, &data[0], &data[1]); 116 | if (err) 117 | { 118 | return err; 119 | } 120 | 121 | if (copy_to_user(tmp, &data, 8)) 122 | { 123 | return -EFAULT; 124 | } 125 | 126 | return 8; 127 | } 128 | 129 | static ssize_t msr_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 130 | { 131 | const u32 __user *tmp = (const u32 __user *)buf; 132 | u32 curdata[2]; 133 | u32 data[2]; 134 | u32 reg = *ppos; 135 | u64 mask; 136 | int cpu = iminor(file->f_path.dentry->d_inode); 137 | int err = 0; 138 | 139 | if (count != 8) /* single write only */ 140 | { 141 | return -EINVAL; 142 | } 143 | 144 | mask = msr_allowlist_writemask(reg); 145 | 146 | if (mask == 0) 147 | { 148 | return -EACCES; 149 | } 150 | 151 | if (copy_from_user(&data, tmp, 8)) 152 | { 153 | return -EFAULT; 154 | } 155 | 156 | if (mask != 0xffffffffffffffff) 157 | { 158 | err = rdmsr_safe_on_cpu(cpu, reg, &curdata[0], &curdata[1]); 159 | if (err) 160 | { 161 | return err; 162 | } 163 | 164 | *(u64 *)&curdata[0] &= ~mask; 165 | *(u64 *)&data[0] &= mask; 166 | *(u64 *)&data[0] |= *(u64 *)&curdata[0]; 167 | } 168 | 169 | err = wrmsr_safe_on_cpu(cpu, reg, data[0], data[1]); 170 | if (err) 171 | { 172 | return err; 173 | } 174 | 175 | return 8; 176 | } 177 | 178 | static int msr_open(struct inode *inode, struct file *file) 179 | { 180 | unsigned int cpu = iminor(file->f_path.dentry->d_inode); 181 | 182 | if (cpu >= nr_cpu_ids || !cpu_online(cpu)) 183 | { 184 | return -ENXIO; // No such CPU 185 | } 186 | 187 | return 0; 188 | } 189 | 190 | static int msr_close(struct inode *inode, struct file *file) 191 | { 192 | return 0; 193 | } 194 | 195 | /* File operations we support */ 196 | static const struct file_operations msr_fops = 197 | { 198 | .owner = THIS_MODULE, 199 | .llseek = msr_seek, 200 | .read = msr_read, 201 | .write = msr_write, 202 | .open = msr_open, 203 | .release = msr_close 204 | }; 205 | 206 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) 207 | static int msr_device_create(int cpu) 208 | #else 209 | static int msr_device_create(unsigned int cpu) 210 | #endif 211 | { 212 | struct device *dev; 213 | 214 | dev = device_create(msr_class, NULL, MKDEV(mdev_msr_safe, cpu), NULL, "msr_safe%d", cpu); 215 | return IS_ERR(dev) ? PTR_ERR(dev) : 0; 216 | } 217 | 218 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) 219 | static void msr_device_destroy(int cpu) 220 | { 221 | device_destroy(msr_class, MKDEV(mdev_msr_safe, cpu)); 222 | } 223 | #else 224 | static int msr_device_destroy(unsigned int cpu) 225 | { 226 | device_destroy(msr_class, MKDEV(mdev_msr_safe, cpu)); 227 | return 0; 228 | } 229 | #endif 230 | 231 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) 232 | static int msr_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) 233 | { 234 | unsigned int cpu = (unsigned long)hcpu; 235 | int err = 0; 236 | 237 | switch (action) 238 | { 239 | case CPU_UP_PREPARE: 240 | err = msr_device_create(cpu); 241 | break; 242 | case CPU_UP_CANCELED: 243 | case CPU_UP_CANCELED_FROZEN: 244 | case CPU_DEAD: 245 | msr_device_destroy(cpu); 246 | break; 247 | } 248 | return notifier_from_errno(err); 249 | } 250 | 251 | static struct notifier_block __refdata msr_class_cpu_notifier = 252 | { 253 | .notifier_call = msr_class_cpu_callback, 254 | }; 255 | #endif 256 | 257 | /* The type of (((struct class *)0)->devnode) has changed at least 258 | * twice in the mainline linux kernel. Trying to pin these changes 259 | * to specific mainline kernel versions runs into the problem of 260 | * distros backporting features to older kernels. Instead, we are 261 | * now keying off of the change in the parameter types.*/ 262 | 263 | #define msr_devnode_selector _Generic(\ 264 | (((struct class *)0)->devnode),\ 265 | char * (*) (struct device *, mode_t *) : msr_devnode1,\ 266 | char * (*) (struct device *, umode_t *) : msr_devnode2,\ 267 | char * (*) (const struct device *, umode_t *) : msr_devnode3\ 268 | ) 269 | 270 | static char *msr_devnode1(struct device *dev, mode_t *mode) 271 | { 272 | return kasprintf(GFP_KERNEL, "cpu/%u/msr_safe", MINOR(dev->devt)); 273 | } 274 | 275 | static char *msr_devnode2(struct device *dev, umode_t *mode) 276 | { 277 | return kasprintf(GFP_KERNEL, "cpu/%u/msr_safe", MINOR(dev->devt)); 278 | } 279 | 280 | static char *msr_devnode3(const struct device *dev, umode_t *mode) 281 | { 282 | return kasprintf(GFP_KERNEL, "cpu/%u/msr_safe", MINOR(dev->devt)); 283 | } 284 | 285 | static int __init msr_init(void) 286 | { 287 | int err = 0; 288 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) 289 | int i; 290 | #endif 291 | 292 | err = msrbatch_init(&mdev_msr_batch); 293 | if (err != 0) 294 | { 295 | pr_debug("failed to initialize msr_batch\n"); 296 | goto out; 297 | } 298 | 299 | err = msr_allowlist_init(&mdev_msr_allowlist); 300 | if (err != 0) 301 | { 302 | pr_debug("failed to initialize msr_allowlist\n"); 303 | goto out_batch; 304 | } 305 | 306 | err = msr_version_init(&mdev_msr_version); 307 | if (err != 0) 308 | { 309 | pr_debug("failed to initialize msr_version\n"); 310 | goto out_version; 311 | } 312 | 313 | /* 314 | * register_chrdev will return: 315 | * If major == 0, dynamically allocate a major and return its number 316 | * If major > 0, attempt to reserve a device with the given major 317 | * number and return zero on success 318 | * Return a negative errno on failure 319 | */ 320 | err = __register_chrdev(mdev_msr_safe, 0, num_possible_cpus(), "cpu/msr_safe", &msr_fops); 321 | if (err < 0) 322 | { 323 | pr_debug("unable to get major %d for msr_safe\n", mdev_msr_safe); 324 | err = -EBUSY; 325 | goto out_wlist; 326 | } 327 | if (err > 0) 328 | { 329 | mdev_msr_safe = err; 330 | } 331 | 332 | pr_debug("msr_safe major dev: %i\n", mdev_msr_safe); 333 | pr_debug("msr_batch major dev: %i\n", mdev_msr_batch); 334 | pr_debug("msr_allowlist major dev: %i\n", mdev_msr_allowlist); 335 | pr_debug("msr_version major dev: %i\n", mdev_msr_version); 336 | 337 | msr_class = class_create( 338 | #if LINUX_VERSION_CODE < KERNEL_VERSION(6,4,0) 339 | THIS_MODULE, 340 | #endif 341 | "msr_safe"); 342 | if (IS_ERR(msr_class)) 343 | { 344 | err = PTR_ERR(msr_class); 345 | goto out_chrdev; 346 | } 347 | msr_class->devnode = msr_devnode_selector; 348 | 349 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) 350 | i = 0; 351 | for_each_online_cpu(i) 352 | err = msr_device_create(i); 353 | if (err != 0) 354 | { 355 | goto out_class; 356 | } 357 | register_hotcpu_notifier(&msr_class_cpu_notifier); 358 | #else 359 | err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/msr:online", msr_device_create, msr_device_destroy); 360 | if (err < 0) 361 | { 362 | goto out_class; 363 | } 364 | cpuhp_msr_state = err; 365 | #endif 366 | return 0; 367 | 368 | out_class: 369 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) 370 | i = 0; 371 | for_each_online_cpu(i) 372 | msr_device_destroy(i); 373 | #endif 374 | class_destroy(msr_class); 375 | out_chrdev: 376 | __unregister_chrdev(mdev_msr_safe, 0, num_possible_cpus(), "cpu/msr_safe"); 377 | out_wlist: 378 | msr_allowlist_cleanup(mdev_msr_allowlist); 379 | out_batch: 380 | msrbatch_cleanup(mdev_msr_batch); 381 | out_version: 382 | msr_version_cleanup(mdev_msr_version); 383 | out: 384 | return err; 385 | } 386 | module_init(msr_init); 387 | 388 | static void __exit msr_exit(void) 389 | { 390 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) 391 | int cpu = 0; 392 | 393 | for_each_online_cpu(cpu) 394 | msr_device_destroy(cpu); 395 | #else 396 | cpuhp_remove_state(cpuhp_msr_state); 397 | #endif 398 | class_destroy(msr_class); 399 | __unregister_chrdev(mdev_msr_safe, 0, num_possible_cpus(), "cpu/msr_safe"); 400 | 401 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) 402 | unregister_hotcpu_notifier(&msr_class_cpu_notifier); 403 | #endif 404 | 405 | msr_allowlist_cleanup(mdev_msr_allowlist); 406 | msrbatch_cleanup(mdev_msr_batch); 407 | msr_version_cleanup(mdev_msr_version); 408 | } 409 | 410 | module_exit(msr_exit) 411 | 412 | MODULE_AUTHOR("M. Fadden, K. Shoga, B. Rountree, H. P. Anvin"); 413 | MODULE_DESCRIPTION("x86 generic MSR driver (+LLNL Approved List)"); 414 | MODULE_VERSION(MSR_SAFE_VERSION_STR); 415 | MODULE_LICENSE("GPL"); 416 | -------------------------------------------------------------------------------- /msr_allowlist.c: -------------------------------------------------------------------------------- 1 | // Copyright 2011-2021 Lawrence Livermore National Security, LLC and other 2 | // msr-safe Project Developers. See the top-level COPYRIGHT file for 3 | // details. 4 | // 5 | // SPDX-License-Identifier: GPL-2.0-only 6 | 7 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "msr_allowlist.h" 20 | 21 | #define MAX_WLIST_BSIZE ((128 * 1024) + 1) // "+1" for null character 22 | 23 | struct allowlist_entry 24 | { 25 | u64 wmask; // Bits that may be written 26 | u64 msr; // Address of msr (used as hash key) 27 | struct hlist_node hlist; 28 | }; 29 | 30 | struct allowlist_data 31 | { 32 | u32 entries; // WL entries successfully parsed 33 | int ecode; // 0 if things look good 34 | char *partial_line; 35 | int partial_len; // Length of partial line 36 | struct allowlist_entry *allowlist; 37 | }; 38 | 39 | static void delete_allowlist(void); 40 | static int create_allowlist(int nentries); 41 | static struct allowlist_entry *find_in_allowlist(u64 msr); 42 | static void add_to_allowlist(struct allowlist_entry *entry); 43 | static int parse_next_allowlist_entry(char *inbuf, char **nextinbuf, struct allowlist_entry *entry); 44 | static ssize_t read_allowlist(struct file *file, char __user *buf, size_t count, loff_t *ppos); 45 | static struct class *cdev_class; 46 | static char cdev_created; 47 | static char cdev_registered; 48 | static char cdev_class_created; 49 | 50 | static DEFINE_HASHTABLE(allowlist_hash, 6); 51 | static DEFINE_MUTEX(allowlist_mutex); 52 | static struct allowlist_entry *allowlist; 53 | static int allowlist_numentries; 54 | 55 | int msr_allowlist_maskexists(loff_t reg) 56 | { 57 | struct allowlist_entry *entry; 58 | 59 | mutex_lock(&allowlist_mutex); 60 | entry = find_in_allowlist((u64)reg); 61 | mutex_unlock(&allowlist_mutex); 62 | 63 | return entry != NULL; 64 | } 65 | 66 | u64 msr_allowlist_writemask(loff_t reg) 67 | { 68 | struct allowlist_entry *entry; 69 | 70 | mutex_lock(&allowlist_mutex); 71 | entry = find_in_allowlist((u64)reg); 72 | mutex_unlock(&allowlist_mutex); 73 | 74 | return entry ? entry->wmask : 0; 75 | } 76 | 77 | static int open_allowlist(struct inode *inode, struct file *file) 78 | { 79 | return 0; 80 | } 81 | 82 | /* 83 | * After copying data from user space, we make two passes through it. 84 | * The first pass is to ensure that the input file is valid. If the file is 85 | * valid, we will then delete the current white list and then perform the 86 | * second pass to actually create the new white list. 87 | */ 88 | static ssize_t write_allowlist(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 89 | { 90 | int err = 0; 91 | const u32 __user *tmp = (const u32 __user *)buf; 92 | char *s; 93 | int res; 94 | int num_entries; 95 | struct allowlist_entry *entry; 96 | char *kbuf; 97 | 98 | pr_debug("%s: %p, %zu, %llu\n", __FUNCTION__, buf, count, *ppos); 99 | if (count <= 2) 100 | { 101 | mutex_lock(&allowlist_mutex); 102 | delete_allowlist(); 103 | hash_init(allowlist_hash); 104 | mutex_unlock(&allowlist_mutex); 105 | return count; 106 | } 107 | 108 | if (count+1 > MAX_WLIST_BSIZE) 109 | { 110 | pr_err("%s: buffer of %zu bytes too large\n", __FUNCTION__, count); 111 | return -E2BIG; 112 | } 113 | 114 | kbuf = kzalloc(count+1, GFP_KERNEL); 115 | if (ZERO_OR_NULL_PTR(kbuf)) 116 | { 117 | pr_err("%s: memory alloc(%zu) failed\n", __FUNCTION__, count+1); 118 | return -ENOMEM; 119 | } 120 | 121 | if (copy_from_user(kbuf, tmp, count)) 122 | { 123 | pr_err("%s: copy_from_user(%zu) failed\n", __FUNCTION__, count); 124 | err = -EFAULT; 125 | goto out_freebuffer; 126 | } 127 | 128 | /* Pass 1: */ 129 | for (num_entries = 0, s = kbuf, res = 1; res > 0; ) 130 | { 131 | res = parse_next_allowlist_entry(s, &s, 0); 132 | if (res < 0) 133 | { 134 | pr_err("%s: parse error\n", __FUNCTION__); 135 | err = res; 136 | goto out_freebuffer; 137 | } 138 | 139 | if (res) 140 | { 141 | num_entries++; 142 | } 143 | } 144 | 145 | if (num_entries == 0) 146 | { 147 | pr_err("%s: No valid entries found in %zu bytes of input\n", __FUNCTION__, count); 148 | err = -ENOMSG; 149 | goto out_freebuffer; 150 | } 151 | 152 | /* Pass 2: */ 153 | mutex_lock(&allowlist_mutex); 154 | res = create_allowlist(num_entries); 155 | if (res < 0) 156 | { 157 | pr_err("%s: create_allowlist(%d) failed\n", __FUNCTION__, num_entries); 158 | err = res; 159 | goto out_releasemutex; 160 | } 161 | 162 | for (entry = allowlist, s = kbuf, res = 1; res > 0; entry++) 163 | { 164 | res = parse_next_allowlist_entry(s, &s, entry); 165 | if (res < 0) 166 | { 167 | pr_err("%s: Table corrupted\n", __FUNCTION__); 168 | delete_allowlist(); 169 | err = res; // This should not happen! 170 | goto out_releasemutex; 171 | } 172 | 173 | if (res) 174 | { 175 | if (find_in_allowlist(entry->msr)) 176 | { 177 | pr_err("%s: Duplicate: %llX\n", __FUNCTION__, entry->msr); 178 | err = -ENOTUNIQ; 179 | delete_allowlist(); 180 | goto out_releasemutex; 181 | } 182 | add_to_allowlist(entry); 183 | } 184 | } 185 | 186 | out_releasemutex: 187 | mutex_unlock(&allowlist_mutex); 188 | out_freebuffer: 189 | kfree(kbuf); 190 | return err ? err : count; 191 | } 192 | 193 | static ssize_t read_allowlist(struct file *file, char __user *buf, size_t count, loff_t *ppos) 194 | { 195 | loff_t idx = *ppos; 196 | u32 __user *tmp = (u32 __user *) buf; 197 | char kbuf[200]; 198 | int len; 199 | struct allowlist_entry e; 200 | 201 | mutex_lock(&allowlist_mutex); 202 | *ppos = 0; 203 | 204 | if (idx >= allowlist_numentries || idx < 0) 205 | { 206 | mutex_unlock(&allowlist_mutex); 207 | return 0; 208 | } 209 | 210 | e = allowlist[idx]; 211 | mutex_unlock(&allowlist_mutex); 212 | 213 | if (idx == 0) 214 | { 215 | len = sprintf(kbuf, "%-10s %-18s\n" "0x%08llX 0x%016llX\n", "#MSR", "Write mask", e.msr, e.wmask); 216 | } 217 | else 218 | { 219 | len = sprintf(kbuf, "0x%08llX 0x%016llX\n", e.msr, e.wmask); 220 | } 221 | 222 | 223 | if (len > count) 224 | { 225 | return -E2BIG; 226 | } 227 | 228 | if (copy_to_user(tmp, kbuf, len)) 229 | { 230 | return -EFAULT; 231 | } 232 | 233 | *ppos = idx+1; 234 | return len; 235 | } 236 | 237 | static const struct file_operations fops = 238 | { 239 | .owner = THIS_MODULE, 240 | .read = read_allowlist, 241 | .write = write_allowlist, 242 | .open = open_allowlist 243 | }; 244 | 245 | static void delete_allowlist(void) 246 | { 247 | if (ZERO_OR_NULL_PTR(allowlist)) 248 | { 249 | return; 250 | } 251 | 252 | kfree(allowlist); 253 | allowlist = 0; 254 | allowlist_numentries = 0; 255 | } 256 | 257 | static int create_allowlist(int nentries) 258 | { 259 | hash_init(allowlist_hash); 260 | delete_allowlist(); 261 | allowlist_numentries = nentries; 262 | allowlist = kcalloc(nentries, sizeof(*allowlist), GFP_KERNEL); 263 | 264 | if (ZERO_OR_NULL_PTR(allowlist)) 265 | { 266 | return -ENOMEM; 267 | } 268 | return 0; 269 | } 270 | 271 | static struct allowlist_entry *find_in_allowlist(u64 msr) 272 | { 273 | struct allowlist_entry *entry = 0; 274 | 275 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39) 276 | struct hlist_node *node; 277 | if (allowlist) 278 | { 279 | hash_for_each_possible(allowlist_hash, entry, node, hlist, msr) 280 | if (entry && entry->msr == msr) 281 | { 282 | return entry; 283 | } 284 | } 285 | #else 286 | if (allowlist) 287 | { 288 | hash_for_each_possible(allowlist_hash, entry, hlist, msr) 289 | if (entry && entry->msr == msr) 290 | { 291 | return entry; 292 | } 293 | } 294 | #endif 295 | return 0; 296 | } 297 | 298 | 299 | static void add_to_allowlist(struct allowlist_entry *entry) 300 | { 301 | hash_add(allowlist_hash, &entry->hlist, entry->msr); 302 | } 303 | 304 | static int parse_next_allowlist_entry(char *inbuf, char **nextinbuf, struct allowlist_entry *entry) 305 | { 306 | char *s = skip_spaces(inbuf); 307 | int i; 308 | u64 data[2]; 309 | 310 | while (*s == '#') 311 | { 312 | /* Skip remaining portion of line */ 313 | for (s = s + 1; *s && *s != '\n'; s++) 314 | { 315 | ; 316 | } 317 | s = skip_spaces(s); 318 | } 319 | 320 | if (*s == 0) 321 | { 322 | return 0; // This means we are done with the input buffer 323 | } 324 | 325 | for (i = 0; i < 2; i++) 326 | { 327 | /* we should have the first of 3 #s now */ 328 | char *s2; 329 | int err; 330 | char tmp; 331 | 332 | s2 = s = skip_spaces(s); 333 | while (!isspace(*s) && *s) 334 | { 335 | s++; 336 | } 337 | 338 | if (*s == 0) 339 | { 340 | pr_debug("%s: Premature EOF\n", __FUNCTION__); 341 | return -EILSEQ; 342 | } 343 | 344 | tmp = *s; 345 | *s = 0; /* Null-terminate this portion of string */ 346 | err = kstrtoull(s2, 0, &data[i]); 347 | if (err) 348 | { 349 | return err; 350 | } 351 | *s++ = tmp; 352 | } 353 | 354 | if (entry) 355 | { 356 | entry->msr = data[0]; 357 | entry->wmask = data[1]; 358 | } 359 | 360 | *nextinbuf = s; /* Return where we left off to caller */ 361 | return *nextinbuf - inbuf; 362 | } 363 | 364 | 365 | #define msr_allowlist_nodename_selector _Generic(\ 366 | (((struct class *)0)->devnode),\ 367 | char* (*) (struct device *, mode_t *) : msr_allowlist_nodename1,\ 368 | char* (*) (struct device *, umode_t *) : msr_allowlist_nodename2,\ 369 | char* (*) (const struct device *, umode_t *) : msr_allowlist_nodename3 \ 370 | ) 371 | 372 | static char *msr_allowlist_nodename1(struct device *dev, mode_t *mode) 373 | { 374 | return kasprintf(GFP_KERNEL, "cpu/msr_allowlist"); 375 | } 376 | 377 | static char *msr_allowlist_nodename2(struct device *dev, umode_t *mode) 378 | { 379 | return kasprintf(GFP_KERNEL, "cpu/msr_allowlist"); 380 | } 381 | 382 | static char *msr_allowlist_nodename3(const struct device *dev, umode_t *mode) 383 | { 384 | return kasprintf(GFP_KERNEL, "cpu/msr_allowlist"); 385 | } 386 | 387 | void msr_allowlist_cleanup(int majordev) 388 | { 389 | delete_allowlist(); 390 | 391 | if (cdev_created) 392 | { 393 | cdev_created = 0; 394 | device_destroy(cdev_class, MKDEV(majordev, 0)); 395 | } 396 | 397 | if (cdev_class_created) 398 | { 399 | cdev_class_created = 0; 400 | class_destroy(cdev_class); 401 | } 402 | 403 | if (cdev_registered) 404 | { 405 | cdev_registered = 0; 406 | unregister_chrdev(majordev, "cpu/msr_allowlist"); 407 | } 408 | } 409 | 410 | int msr_allowlist_init(int *majordev) 411 | { 412 | int err = 0; 413 | struct device *dev; 414 | 415 | err = register_chrdev(*majordev, "cpu/msr_allowlist", &fops); 416 | if (err < 0) 417 | { 418 | pr_debug("%s: unable to register chrdev\n", __FUNCTION__); 419 | msr_allowlist_cleanup(*majordev); 420 | err = -EBUSY; 421 | return err; 422 | } 423 | if (err > 0) 424 | { 425 | *majordev = err; 426 | } 427 | cdev_registered = 1; 428 | 429 | cdev_class = class_create( 430 | #if LINUX_VERSION_CODE < KERNEL_VERSION(6,4,0) 431 | THIS_MODULE, 432 | #endif 433 | "msr_allowlist"); 434 | if (IS_ERR(cdev_class)) 435 | { 436 | err = PTR_ERR(cdev_class); 437 | msr_allowlist_cleanup(*majordev); 438 | return err; 439 | } 440 | cdev_class_created = 1; 441 | 442 | cdev_class->devnode = msr_allowlist_nodename_selector; 443 | 444 | dev = device_create(cdev_class, NULL, MKDEV(*majordev, 0), NULL, "msr_allowlist"); 445 | if (IS_ERR(dev)) 446 | { 447 | err = PTR_ERR(dev); 448 | msr_allowlist_cleanup(*majordev); 449 | return err; 450 | } 451 | cdev_created = 1; 452 | return 0; 453 | } 454 | -------------------------------------------------------------------------------- /allowlists/al_06_8F: -------------------------------------------------------------------------------- 1 | ## This file contains the model-specific registers available in 06_8F processors 2 | ## based on a close reading of volume 4 of the Intel 64 and IA-32 Architectures 3 | ## Software Development Manual (335592-079US March 2023). 4 | ## Uncommenting allows reading a particular MSR. 5 | ## Modifying the write mask allows writing to those particular bits. 6 | ## Be sure to cat the modified list into /dev/cpu/msr_allowlist. 7 | ## See the README file for more details. 8 | ## 9 | ## MSR # Write Mask # Comment 10 | # 0x00000033 0x0000000000000000 # "MSR_MEMORY_CTRL (Table: 2-52)" 11 | # 0x000000A7 0x0000000000000000 # "MSR_BIOS_DEBUG (Table: 2-52)" 12 | # 0x000000BC 0x0000000000000000 # "IA32_MISC_PACKAGE_CTLS (Table: 2-52)" 13 | # 0x000000CF 0x0000000000000000 # "IA32_CORE_CAPABILITIES (Table: 2-52)" 14 | # 0x000000E1 0x0000000000000000 # "IA32_UMWAIT_CONTROL (Table: 2-52)" 15 | # 0x000000ED 0x0000000000000000 # "MSR_RAR_CONTROL (Table: 2-52)" 16 | # 0x000000EE 0x0000000000000000 # "MSR_RAR_ACTION_VECTOR_BASE (Table: 2-52)" 17 | # 0x000000EF 0x0000000000000000 # "MSR_RAR_PAYLOAD_TABLE_BASE (Table: 2-52)" 18 | # 0x000000F0 0x0000000000000000 # "MSR_RAR_INFO (Table: 2-52)" 19 | # 0x00000105 0x0000000000000000 # "MSR_CORE_BIST (Table: 2-52)" 20 | # 0x0000010A 0x0000000000000000 # "IA32_ARCH_CAPABILITIES (Table: 2-52)" 21 | # 0x000001A4 0x0000000000000000 # "MSR_PREFETCH_CONTROL (Table: 2-52)" 22 | # 0x000001AD 0x0000000000000000 # "MSR_PRIMARY_TURBO_RATIO_LIMIT (Table: 2-52)" 23 | # 0x000001AE 0x0000000000000000 # "MSR_TURBO_RATIO_LIMIT_CORES (Table: 2-52)" 24 | # 0x000001C4 0x0000000000000000 # "IA32_XFD (Table: 2-52)" 25 | # 0x000001C5 0x0000000000000000 # "IA32_XFD_ERR (Table: 2-52)" 26 | # 0x000002C2 0x0000000000000000 # "MSR_COPY_SCAN_HASHES (Table: 2-52)" 27 | # 0x000002C3 0x0000000000000000 # "MSR_SCAN_HASHES_STATUS (Table: 2-52)" 28 | # 0x000002C4 0x0000000000000000 # "MSR_AUTHENTICATE_AND_COPY_CHUNK (Table: 2-52)" 29 | # 0x000002C5 0x0000000000000000 # "MSR_CHUNKS_AUTHENTICATION_STATUS (Table: 2-52)" 30 | # 0x000002C6 0x0000000000000000 # "MSR_ACTIVATE_SCAN (Table: 2-52)" 31 | # 0x000002C7 0x0000000000000000 # "MSR_SCAN_STATUS (Table: 2-52)" 32 | # 0x000002C8 0x0000000000000000 # "MSR_SCAN_MODULE_ID (Table: 2-52)" 33 | # 0x000002C9 0x0000000000000000 # "MSR_LAST_SAF_WP (Table: 2-52)" 34 | # 0x000002D9 0x0000000000000000 # "MSR_INTEGRITY_CAPABILITIES (Table: 2-52)" 35 | # 0x00000410 0x0000000000000000 # "IA32_MC4_CTL (Table: 2-52)" 36 | # 0x00000411 0x0000000000000000 # "IA32_MC4_STATUS (Table: 2-52)" 37 | # 0x00000412 0x0000000000000000 # "IA32_MC4_ADDR (Table: 2-52)" 38 | # 0x00000413 0x0000000000000000 # "IA32_MC4_MISC (Table: 2-52)" 39 | # 0x00000492 0x0000000000000000 # "IA32_VMX_PROCBASED_CTLS3 (Table: 2-52)" 40 | # 0x00000493 0x0000000000000000 # "IA32_VMX_EXIT_CTLS2 (Table: 2-52)" 41 | # 0x00000540 0x0000000000000000 # "MSR_THREAD_UARCH_CTL (Table: 2-52)" 42 | # 0x0000065C 0x0000000000000000 # "MSR_PLATFORM_POWER_LIMIT (Table: 2-52)" 43 | # 0x000006A0 0x0000000000000000 # "IA32_U_CET (Table: 2-52)" 44 | # 0x000006A2 0x0000000000000000 # "IA32_S_CET (Table: 2-52)" 45 | # 0x000006A4 0x0000000000000000 # "IA32_PL0_SSP (Table: 2-52)" 46 | # 0x000006A5 0x0000000000000000 # "IA32_PL1_SSP (Table: 2-52)" 47 | # 0x000006A6 0x0000000000000000 # "IA32_PL2_SSP (Table: 2-52)" 48 | # 0x000006A7 0x0000000000000000 # "IA32_PL3_SSP (Table: 2-52)" 49 | # 0x000006A8 0x0000000000000000 # "IA32_INTERRUPT_SSP_TABLE_ADDR (Table: 2-52)" 50 | # 0x000006E1 0x0000000000000000 # "IA32_PKRS (Table: 2-52)" 51 | # 0x00000776 0x0000000000000000 # "IA32_HWP_CTL (Table: 2-52)" 52 | # 0x00000981 0x0000000000000000 # "IA32_TME_CAPABILITY (Table: 2-52)" 53 | # 0x00000985 0x0000000000000000 # "IA32_UINTR_RR (Table: 2-52)" 54 | # 0x00000986 0x0000000000000000 # "IA32_UINTR_HANDLER (Table: 2-52)" 55 | # 0x00000987 0x0000000000000000 # "IA32_UINTR_STACKADJUST (Table: 2-52)" 56 | # 0x00000988 0x0000000000000000 # "IA32_UINTR_MISC (Table: 2-52)" 57 | # 0x00000989 0x0000000000000000 # "IA32_UINTR_PD (Table: 2-52)" 58 | # 0x0000098A 0x0000000000000000 # "IA32_UINTR_TT (Table: 2-52)" 59 | # 0x00000C70 0x0000000000000000 # "MSR_B1_PMON_EVNT_SEL0 (Table: 2-52)" 60 | # 0x00000C71 0x0000000000000000 # "MSR_B1_PMON_CTR0 (Table: 2-52)" 61 | # 0x00000C72 0x0000000000000000 # "MSR_B1_PMON_EVNT_SEL1 (Table: 2-52)" 62 | # 0x00000C73 0x0000000000000000 # "MSR_B1_PMON_CTR1 (Table: 2-52)" 63 | # 0x00000C74 0x0000000000000000 # "MSR_B1_PMON_EVNT_SEL2 (Table: 2-52)" 64 | # 0x00000C75 0x0000000000000000 # "MSR_B1_PMON_CTR2 (Table: 2-52)" 65 | # 0x00000C76 0x0000000000000000 # "MSR_B1_PMON_EVNT_SEL3 (Table: 2-52)" 66 | # 0x00000C77 0x0000000000000000 # "MSR_B1_PMON_CTR3 (Table: 2-52)" 67 | # 0x00000C82 0x0000000000000000 # "MSR_W_PMON_BOX_OVF_CTRL (Table: 2-52)" 68 | # 0x00000C8F 0x0000000000000000 # "IA32_PQR_ASSOC (Table: 2-52)" 69 | # 0x00000C90 0x0000000000000000 # "IA32_L3_QOS_MASK_0 (Table: 2-52)" 70 | # 0x00000C91 0x0000000000000000 # "IA32_L3_QOS_MASK_1 (Table: 2-52)" 71 | # 0x00000C92 0x0000000000000000 # "IA32_L3_QOS_MASK_2 (Table: 2-52)" 72 | # 0x00000C93 0x0000000000000000 # "IA32_L3_QOS_MASK_3 (Table: 2-52)" 73 | # 0x00000C94 0x0000000000000000 # "IA32_L3_QOS_MASK_4 (Table: 2-52)" 74 | # 0x00000C95 0x0000000000000000 # "IA32_L3_QOS_MASK_5 (Table: 2-52)" 75 | # 0x00000C96 0x0000000000000000 # "IA32_L3_QOS_MASK_6 (Table: 2-52)" 76 | # 0x00000C97 0x0000000000000000 # "IA32_L3_QOS_MASK_7 (Table: 2-52)" 77 | # 0x00000C98 0x0000000000000000 # "IA32_L3_QOS_MASK_8 (Table: 2-52)" 78 | # 0x00000C99 0x0000000000000000 # "IA32_L3_QOS_MASK_9 (Table: 2-52)" 79 | # 0x00000C9A 0x0000000000000000 # "IA32_L3_QOS_MASK_10 (Table: 2-52)" 80 | # 0x00000C9B 0x0000000000000000 # "IA32_L3_QOS_MASK_11 (Table: 2-52)" 81 | # 0x00000C9C 0x0000000000000000 # "IA32_L3_QOS_MASK_12 (Table: 2-52)" 82 | # 0x00000C9D 0x0000000000000000 # "IA32_L3_QOS_MASK_13 (Table: 2-52)" 83 | # 0x00000C9E 0x0000000000000000 # "IA32_L3_QOS_MASK_14 (Table: 2-52)" 84 | # 0x00000D10 0x0000000000000000 # "IA32_L2_QOS_MASK_0 (Table: 2-52)" 85 | # 0x00000D11 0x0000000000000000 # "IA32_L2_QOS_MASK_1 (Table: 2-52)" 86 | # 0x00000D12 0x0000000000000000 # "IA32_L2_QOS_MASK_2 (Table: 2-52)" 87 | # 0x00000D13 0x0000000000000000 # "IA32_L2_QOS_MASK_3 (Table: 2-52)" 88 | # 0x00000D14 0x0000000000000000 # "IA32_L2_QOS_MASK_4 (Table: 2-52)" 89 | # 0x00000D15 0x0000000000000000 # "IA32_L2_QOS_MASK_5 (Table: 2-52)" 90 | # 0x00000D16 0x0000000000000000 # "IA32_L2_QOS_MASK_6 (Table: 2-52)" 91 | # 0x00000D17 0x0000000000000000 # "IA32_L2_QOS_MASK_7 (Table: 2-52)" 92 | # 0x00000D93 0x0000000000000000 # "IA32_PASID (Table: 2-52)" 93 | # 0x00001200 0x0000000000000000 # "IA32_LBR_0_INFO (Table: 2-52)" 94 | # 0x00001201 0x0000000000000000 # "IA32_LBR_1_INFO (Table: 2-52)" 95 | # 0x00001202 0x0000000000000000 # "IA32_LBR_2_INFO (Table: 2-52)" 96 | # 0x00001203 0x0000000000000000 # "IA32_LBR_3_INFO (Table: 2-52)" 97 | # 0x00001204 0x0000000000000000 # "IA32_LBR_4_INFO (Table: 2-52)" 98 | # 0x00001205 0x0000000000000000 # "IA32_LBR_5_INFO (Table: 2-52)" 99 | # 0x00001206 0x0000000000000000 # "IA32_LBR_6_INFO (Table: 2-52)" 100 | # 0x00001207 0x0000000000000000 # "IA32_LBR_7_INFO (Table: 2-52)" 101 | # 0x00001208 0x0000000000000000 # "IA32_LBR_8_INFO (Table: 2-52)" 102 | # 0x00001209 0x0000000000000000 # "IA32_LBR_9_INFO (Table: 2-52)" 103 | # 0x0000120A 0x0000000000000000 # "IA32_LBR_10_INFO (Table: 2-52)" 104 | # 0x0000120B 0x0000000000000000 # "IA32_LBR_11_INFO (Table: 2-52)" 105 | # 0x0000120C 0x0000000000000000 # "IA32_LBR_12_INFO (Table: 2-52)" 106 | # 0x0000120D 0x0000000000000000 # "IA32_LBR_13_INFO (Table: 2-52)" 107 | # 0x0000120E 0x0000000000000000 # "IA32_LBR_14_INFO (Table: 2-52)" 108 | # 0x0000120F 0x0000000000000000 # "IA32_LBR_15_INFO (Table: 2-52)" 109 | # 0x00001210 0x0000000000000000 # "IA32_LBR_16_INFO (Table: 2-52)" 110 | # 0x00001211 0x0000000000000000 # "IA32_LBR_17_INFO (Table: 2-52)" 111 | # 0x00001212 0x0000000000000000 # "IA32_LBR_18_INFO (Table: 2-52)" 112 | # 0x00001213 0x0000000000000000 # "IA32_LBR_19_INFO (Table: 2-52)" 113 | # 0x00001214 0x0000000000000000 # "IA32_LBR_20_INFO (Table: 2-52)" 114 | # 0x00001215 0x0000000000000000 # "IA32_LBR_21_INFO (Table: 2-52)" 115 | # 0x00001216 0x0000000000000000 # "IA32_LBR_22_INFO (Table: 2-52)" 116 | # 0x00001217 0x0000000000000000 # "IA32_LBR_23_INFO (Table: 2-52)" 117 | # 0x00001218 0x0000000000000000 # "IA32_LBR_24_INFO (Table: 2-52)" 118 | # 0x00001219 0x0000000000000000 # "IA32_LBR_25_INFO (Table: 2-52)" 119 | # 0x0000121A 0x0000000000000000 # "IA32_LBR_26_INFO (Table: 2-52)" 120 | # 0x0000121B 0x0000000000000000 # "IA32_LBR_27_INFO (Table: 2-52)" 121 | # 0x0000121C 0x0000000000000000 # "IA32_LBR_28_INFO (Table: 2-52)" 122 | # 0x0000121D 0x0000000000000000 # "IA32_LBR_29_INFO (Table: 2-52)" 123 | # 0x0000121E 0x0000000000000000 # "IA32_LBR_30_INFO (Table: 2-52)" 124 | # 0x0000121F 0x0000000000000000 # "IA32_LBR_31_INFO (Table: 2-52)" 125 | # 0x00001406 0x0000000000000000 # "IA32_MCU_CONTROL (Table: 2-52)" 126 | # 0x000014CE 0x0000000000000000 # "IA32_LBR_CTL (Table: 2-52)" 127 | # 0x000014CF 0x0000000000000000 # "IA32_LBR_DEPTH (Table: 2-52)" 128 | # 0x00001500 0x0000000000000000 # "IA32_LBR_0_FROM_IP (Table: 2-52)" 129 | # 0x00001501 0x0000000000000000 # "IA32_LBR_1_FROM_IP (Table: 2-52)" 130 | # 0x00001502 0x0000000000000000 # "IA32_LBR_2_FROM_IP (Table: 2-52)" 131 | # 0x00001503 0x0000000000000000 # "IA32_LBR_3_FROM_IP (Table: 2-52)" 132 | # 0x00001504 0x0000000000000000 # "IA32_LBR_4_FROM_IP (Table: 2-52)" 133 | # 0x00001505 0x0000000000000000 # "IA32_LBR_5_FROM_IP (Table: 2-52)" 134 | # 0x00001506 0x0000000000000000 # "IA32_LBR_6_FROM_IP (Table: 2-52)" 135 | # 0x00001507 0x0000000000000000 # "IA32_LBR_7_FROM_IP (Table: 2-52)" 136 | # 0x00001508 0x0000000000000000 # "IA32_LBR_8_FROM_IP (Table: 2-52)" 137 | # 0x00001509 0x0000000000000000 # "IA32_LBR_9_FROM_IP (Table: 2-52)" 138 | # 0x0000150A 0x0000000000000000 # "IA32_LBR_10_FROM_IP (Table: 2-52)" 139 | # 0x0000150B 0x0000000000000000 # "IA32_LBR_11_FROM_IP (Table: 2-52)" 140 | # 0x0000150C 0x0000000000000000 # "IA32_LBR_12_FROM_IP (Table: 2-52)" 141 | # 0x0000150D 0x0000000000000000 # "IA32_LBR_13_FROM_IP (Table: 2-52)" 142 | # 0x0000150E 0x0000000000000000 # "IA32_LBR_14_FROM_IP (Table: 2-52)" 143 | # 0x0000150F 0x0000000000000000 # "IA32_LBR_15_FROM_IP (Table: 2-52)" 144 | # 0x00001510 0x0000000000000000 # "IA32_LBR_16_FROM_IP (Table: 2-52)" 145 | # 0x00001511 0x0000000000000000 # "IA32_LBR_17_FROM_IP (Table: 2-52)" 146 | # 0x00001512 0x0000000000000000 # "IA32_LBR_18_FROM_IP (Table: 2-52)" 147 | # 0x00001513 0x0000000000000000 # "IA32_LBR_19_FROM_IP (Table: 2-52)" 148 | # 0x00001514 0x0000000000000000 # "IA32_LBR_20_FROM_IP (Table: 2-52)" 149 | # 0x00001515 0x0000000000000000 # "IA32_LBR_21_FROM_IP (Table: 2-52)" 150 | # 0x00001516 0x0000000000000000 # "IA32_LBR_22_FROM_IP (Table: 2-52)" 151 | # 0x00001517 0x0000000000000000 # "IA32_LBR_23_FROM_IP (Table: 2-52)" 152 | # 0x00001518 0x0000000000000000 # "IA32_LBR_24_FROM_IP (Table: 2-52)" 153 | # 0x00001519 0x0000000000000000 # "IA32_LBR_25_FROM_IP (Table: 2-52)" 154 | # 0x0000151A 0x0000000000000000 # "IA32_LBR_26_FROM_IP (Table: 2-52)" 155 | # 0x0000151B 0x0000000000000000 # "IA32_LBR_27_FROM_IP (Table: 2-52)" 156 | # 0x0000151C 0x0000000000000000 # "IA32_LBR_28_FROM_IP (Table: 2-52)" 157 | # 0x0000151D 0x0000000000000000 # "IA32_LBR_29_FROM_IP (Table: 2-52)" 158 | # 0x0000151E 0x0000000000000000 # "IA32_LBR_30_FROM_IP (Table: 2-52)" 159 | # 0x0000151F 0x0000000000000000 # "IA32_LBR_31_FROM_IP (Table: 2-52)" 160 | # 0x00001600 0x0000000000000000 # "IA32_LBR_0_TO_IP (Table: 2-52)" 161 | # 0x00001601 0x0000000000000000 # "IA32_LBR_1_TO_IP (Table: 2-52)" 162 | # 0x00001602 0x0000000000000000 # "IA32_LBR_2_TO_IP (Table: 2-52)" 163 | # 0x00001603 0x0000000000000000 # "IA32_LBR_3_TO_IP (Table: 2-52)" 164 | # 0x00001604 0x0000000000000000 # "IA32_LBR_4_TO_IP (Table: 2-52)" 165 | # 0x00001605 0x0000000000000000 # "IA32_LBR_5_TO_IP (Table: 2-52)" 166 | # 0x00001606 0x0000000000000000 # "IA32_LBR_6_TO_IP (Table: 2-52)" 167 | # 0x00001607 0x0000000000000000 # "IA32_LBR_7_TO_IP (Table: 2-52)" 168 | # 0x00001608 0x0000000000000000 # "IA32_LBR_8_TO_IP (Table: 2-52)" 169 | # 0x00001609 0x0000000000000000 # "IA32_LBR_9_TO_IP (Table: 2-52)" 170 | # 0x0000160A 0x0000000000000000 # "IA32_LBR_10_TO_IP (Table: 2-52)" 171 | # 0x0000160B 0x0000000000000000 # "IA32_LBR_11_TO_IP (Table: 2-52)" 172 | # 0x0000160C 0x0000000000000000 # "IA32_LBR_12_TO_IP (Table: 2-52)" 173 | # 0x0000160D 0x0000000000000000 # "IA32_LBR_13_TO_IP (Table: 2-52)" 174 | # 0x0000160E 0x0000000000000000 # "IA32_LBR_14_TO_IP (Table: 2-52)" 175 | # 0x0000160F 0x0000000000000000 # "IA32_LBR_15_TO_IP (Table: 2-52)" 176 | # 0x00001610 0x0000000000000000 # "IA32_LBR_16_TO_IP (Table: 2-52)" 177 | # 0x00001611 0x0000000000000000 # "IA32_LBR_17_TO_IP (Table: 2-52)" 178 | # 0x00001612 0x0000000000000000 # "IA32_LBR_18_TO_IP (Table: 2-52)" 179 | # 0x00001613 0x0000000000000000 # "IA32_LBR_19_TO_IP (Table: 2-52)" 180 | # 0x00001614 0x0000000000000000 # "IA32_LBR_20_TO_IP (Table: 2-52)" 181 | # 0x00001615 0x0000000000000000 # "IA32_LBR_21_TO_IP (Table: 2-52)" 182 | # 0x00001616 0x0000000000000000 # "IA32_LBR_22_TO_IP (Table: 2-52)" 183 | # 0x00001617 0x0000000000000000 # "IA32_LBR_23_TO_IP (Table: 2-52)" 184 | # 0x00001618 0x0000000000000000 # "IA32_LBR_24_TO_IP (Table: 2-52)" 185 | # 0x00001619 0x0000000000000000 # "IA32_LBR_25_TO_IP (Table: 2-52)" 186 | # 0x0000161A 0x0000000000000000 # "IA32_LBR_26_TO_IP (Table: 2-52)" 187 | # 0x0000161B 0x0000000000000000 # "IA32_LBR_27_TO_IP (Table: 2-52)" 188 | # 0x0000161C 0x0000000000000000 # "IA32_LBR_28_TO_IP (Table: 2-52)" 189 | # 0x0000161D 0x0000000000000000 # "IA32_LBR_29_TO_IP (Table: 2-52)" 190 | # 0x0000161E 0x0000000000000000 # "IA32_LBR_30_TO_IP (Table: 2-52)" 191 | # 0x0000161F 0x0000000000000000 # "IA32_LBR_31_TO_IP (Table: 2-52)" 192 | -------------------------------------------------------------------------------- /allowlists/al_19_21: -------------------------------------------------------------------------------- 1 | # Based on "Processor Programming Reference (PPR) for AMD Family 2 | # 19h Model 21h, Revision B0 Processors", Rev 3.05 - Apr 22, 2021, 3 | # pages 96-194. 4 | # https://www.amd.com/system/files/TechDocs/56214-B0-PUB.zip 5 | # NOTE: The r/w notes are a gross simplification. 6 | # Please consult the actual manual before doing stuff that matters. 7 | # 8 | # register writemask comments 9 | 0x00000010 0x0000000000000000 # Time Stamp Counter, r/w, volatile, inc at P0 freq. 10 | #0x0000001B 0x0000000000000000 # APIC Base Address, r/w 11 | #0x0000002A 0x0000000000000000 # Cluster ID, r/o 12 | #0x00000048 0x0000000000000000 # Speculative Control, r/w 13 | #0x00000049 0x0000000000000000 # Prediction Command, w/o 14 | #0x0000008B 0x0000000000000000 # Patch Level, r/o 15 | 0x000000E7 0x0000000000000000 # Max Performance Frequency Clock Count, r/w, volatile, inc at P0 clock 16 | 0x000000E8 0x0000000000000000 # Actual Performance Frequency Clock Count, r/w, volatile, inc per clock 17 | #0x000000FE 0x0000000000000000 # MTRR Capabilities, r/o 18 | #0x00000174 0x0000000000000000 # SYSENTER_CS, r/w 19 | #0x00000175 0x0000000000000000 # SYSENTER_ESP, r/w 20 | #0x00000176 0x0000000000000000 # SYSENTER_EIP, r/w 21 | #0x00000179 0x0000000000000000 # Global Machine Check Capabilities, r/o 22 | #0x0000017A 0x0000000000000000 # Global Machine Check Status, r/w, volatile 23 | #0x0000017B 0x0000000000000000 # Global Machine Check Exception Reporting Control, r/w 24 | #0x000001D9 0x0000000000000000 # Debug Control, r/w 25 | #0x000001DB 0x0000000000000000 # Last Branch From IP, r/o, volatile 26 | #0x000001DC 0x0000000000000000 # Last Branch To IP, r/o, volatile 27 | #0x000001DD 0x0000000000000000 # Last Exception From IP, r/o, volatile 28 | #0x000001DE 0x0000000000000000 # Last Exception To IP, r/o, volatile 29 | #0x00000200 0x0000000000000000 # Variable-Size MTRRs Base, r/w 30 | #0x00000201 0x0000000000000000 # " 31 | #0x00000202 0x0000000000000000 # " 32 | #0x00000203 0x0000000000000000 # " 33 | #0x00000204 0x0000000000000000 # " 34 | #0x00000205 0x0000000000000000 # " 35 | #0x00000206 0x0000000000000000 # " 36 | #0x00000207 0x0000000000000000 # " 37 | #0x00000208 0x0000000000000000 # " 38 | #0x00000009 0x0000000000000000 # " 39 | #0x0000020A 0x0000000000000000 # " 40 | #0x0000020B 0x0000000000000000 # " 41 | #0x0000020C 0x0000000000000000 # " 42 | #0x0000020D 0x0000000000000000 # " 43 | #0x0000020E 0x0000000000000000 # " 44 | #0x0000020F 0x0000000000000000 # Variable-Size MTRRs Mask, r/w 45 | #0x00000210 0x0000000000000000 # NOTE: The documuentation states this MSR range is from 46 | #0x00000211 0x0000000000000000 # "0000_020[1...F]". I am interpreting that as 47 | #0x00000212 0x0000000000000000 # "0000_02[10...1F]". This may not be correct. 48 | #0x00000213 0x0000000000000000 # 49 | #0x00000214 0x0000000000000000 # " 50 | #0x00000215 0x0000000000000000 # " 51 | #0x00000216 0x0000000000000000 # " 52 | #0x00000217 0x0000000000000000 # " 53 | #0x00000218 0x0000000000000000 # " 54 | #0x00000219 0x0000000000000000 # " 55 | #0x0000021A 0x0000000000000000 # " 56 | #0x0000021B 0x0000000000000000 # " 57 | #0x0000021C 0x0000000000000000 # " 58 | #0x0000021D 0x0000000000000000 # " 59 | #0x0000021E 0x0000000000000000 # " 60 | #0x0000021F 0x0000000000000000 # " 61 | #0x00000250 0x0000000000000000 # Fixed-Size MTRRs, r/o 62 | #0x00000258 0x0000000000000000 # Fixed-Size MTRRs, r/o 63 | #0x00000259 0x0000000000000000 # Fixed-Size MTRRs, r/o 64 | #0x00000268 0x0000000000000000 # Fixed-Size MTRRs, r/o 65 | #0x00000269 0x0000000000000000 # Fixed-Size MTRRs, r/o 66 | #0x0000026A 0x0000000000000000 # Fixed-Size MTRRs, r/o 67 | #0x0000026B 0x0000000000000000 # Fixed-Size MTRRs, r/o 68 | #0x0000026C 0x0000000000000000 # Fixed-Size MTRRs, r/o 69 | #0x0000026D 0x0000000000000000 # Fixed-Size MTRRs, r/o 70 | #0x0000026E 0x0000000000000000 # Fixed-Size MTRRs, r/o 71 | #0x0000026F 0x0000000000000000 # Fixed-Size MTRRs, r/o 72 | #0x00000277 0x0000000000000000 # Page Attribute Table, r/w 73 | #0x000002FF 0x0000000000000000 # MTRR Default Memory Type, r/w 74 | #0x000006A0 0x0000000000000000 # User CET, r/w 75 | #0x000006A2 0x0000000000000000 # Supervisor CET, r/w 76 | #0x000006A4 0x0000000000000000 # PL0 Shadow Stack Pointer, r/w 77 | #0x000006A5 0x0000000000000000 # PL1 Shadow Stack Pointer, r/w 78 | #0x000006A6 0x0000000000000000 # PL2 Shadow Stack Pointer, r/w 79 | #0x000006A7 0x0000000000000000 # PL3 Shadow Stack Pointer, r/w 80 | #0x000006A8 0x0000000000000000 # Interrupt SSP Table Address, r/w 81 | #0x00000802 0x0000000000000000 # APIC ID 82 | #0x00000803 0x0000000000000000 # APIC Version 83 | #0x00000808 0x0000000000000000 # Task Priority, r/w, volatile 84 | #0x00000809 0x0000000000000000 # Arbitration Priority, r/o 85 | #0x0000080A 0x0000000000000000 # Processor Priority, r/o 86 | #0x0000080B 0x0000000000000000 # End Of Interrupt, write-1-only 87 | #0x0000080D 0x0000000000000000 # Logical Destination Register, r/o 88 | #0x0000080F 0x0000000000000000 # Spurrious Interrupt Vector, r/w 89 | #0x00000810 0x0000000000000000 # In Service Register, r/o 90 | #0x00000811 0x0000000000000000 # " 91 | #0x00000812 0x0000000000000000 # " 92 | #0x00000813 0x0000000000000000 # " 93 | #0x00000814 0x0000000000000000 # " 94 | #0x00000815 0x0000000000000000 # " 95 | #0x00000816 0x0000000000000000 # " 96 | #0x00000817 0x0000000000000000 # " 97 | #0x00000818 0x0000000000000000 # Trigger Mode Register, r/o 98 | #0x00000819 0x0000000000000000 # " 99 | #0x0000081A 0x0000000000000000 # " 100 | #0x0000081B 0x0000000000000000 # " 101 | #0x0000081C 0x0000000000000000 # " 102 | #0x0000081D 0x0000000000000000 # " 103 | #0x0000081E 0x0000000000000000 # " 104 | #0x0000081F 0x0000000000000000 # " 105 | #0x00000820 0x0000000000000000 # Interrupt Request Register, r/o 106 | #0x00000821 0x0000000000000000 # " 107 | #0x00000822 0x0000000000000000 # " 108 | #0x00000823 0x0000000000000000 # " 109 | #0x00000824 0x0000000000000000 # " 110 | #0x00000825 0x0000000000000000 # " 111 | #0x00000826 0x0000000000000000 # " 112 | #0x00000827 0x0000000000000000 # " 113 | #0x00000828 0x0000000000000000 # Error Status Register, r/write-0-only 114 | #0x00000830 0x0000000000000000 # Interrupt Command, r/w 115 | #0x00000832 0x0000000000000000 # LVT Timer, r/w 116 | #0x00000833 0x0000000000000000 # LVT Thermal Sensor, r/w 117 | #0x00000834 0x0000000000000000 # LVT Performance Monitor, r/w 118 | #0x00000835 0x0000000000000000 # LVT LINT1 (?), r/w 119 | #0x00000836 0x0000000000000000 # LVT LINT0 (?), r/w 120 | #0x00000837 0x0000000000000000 # LVT Error, r/w 121 | #0x00000838 0x0000000000000000 # Timer Initial Count, r/w 122 | #0x00000839 0x0000000000000000 # Timer Current Count, r/o 123 | #0x0000083E 0x0000000000000000 # Timer Divide Configuration, r/w 124 | #0x0000083F 0x0000000000000000 # Self IPI, w/o 125 | #0x00000840 0x0000000000000000 # Extended APIC Feature, r/o 126 | #0x00000841 0x0000000000000000 # Extended APIC Control, r/w 127 | #0x00000842 0x0000000000000000 # Specific End Of Interrupt, r/w 128 | #0x00000848 0x0000000000000000 # Interrupt Enable 0, r/w 129 | #0x00000849 0x0000000000000000 # Interrupt Enable 1, r/w 130 | #0x0000084A 0x0000000000000000 # Interrupt Enable 2, r/w 131 | #0x0000084B 0x0000000000000000 # Interrupt Enable 3, r/w 132 | #0x0000084C 0x0000000000000000 # Interrupt Enable 4, r/w 133 | #0x0000084D 0x0000000000000000 # Interrupt Enable 5, r/w 134 | #0x0000084E 0x0000000000000000 # Interrupt Enable 6, r/w 135 | #0x0000084F 0x0000000000000000 # Interrupt Enable 7, r/w 136 | #0x00000850 0x0000000000000000 # Extended Interrupt Local Vector Table, r/w 137 | #0x00000851 0x0000000000000000 # " 138 | #0x00000852 0x0000000000000000 # " 139 | #0x00000853 0x0000000000000000 # " 140 | #0x00000C81 0x0000000000000000 # L3 QoS Configuration, r/w 141 | #0x00000C8D 0x0000000000000000 # Monitoring Event Select, r/w 142 | #0x00000C8E 0x0000000000000000 # QOS L3 Counter, r/o 143 | #0x00000C8F 0x0000000000000000 # Resource Association, r/w 144 | #0x00000C90 0x0000000000000000 # L3 QOS Allocation Mask, r/w 145 | #0x00000C91 0x0000000000000000 # " 146 | #0x00000C92 0x0000000000000000 # " 147 | #0x00000C93 0x0000000000000000 # " 148 | #0x00000C94 0x0000000000000000 # " 149 | #0x00000C95 0x0000000000000000 # " 150 | #0x00000C96 0x0000000000000000 # " 151 | #0x00000C97 0x0000000000000000 # " 152 | #0x00000C98 0x0000000000000000 # " 153 | #0x00000C99 0x0000000000000000 # " 154 | #0x00000C9A 0x0000000000000000 # " 155 | #0x00000C9B 0x0000000000000000 # " 156 | #0x00000C9C 0x0000000000000000 # " 157 | #0x00000C9D 0x0000000000000000 # " 158 | #0x00000C9E 0x0000000000000000 # " 159 | #0x00000C9F 0x0000000000000000 # " 160 | #0x00000DA0 0x0000000000000000 # Extended Supervisor State, r/w 161 | #0xC0000080 0x0000000000000000 # Extended Feature Enable, r/w 162 | #0xC0000081 0x0000000000000000 # SYSCALL Target Address, r/w 163 | #0xC0000082 0x0000000000000000 # Long Mode SYSCALL Target Address, r/w 164 | #0xC0000083 0x0000000000000000 # Compatibility Mode SYSCALL Target Address, r/w 165 | #0xC0000084 0x0000000000000000 # SYSCALL Flag Mask, r/w 166 | #0xC00000E7 0x0000000000000000 # Read-Only Max Performance Frequency Clock Count, r/o, volatile 167 | #0xC00000E8 0x0000000000000000 # Read-Only Actual Performance Frequency Clock Count, r/o, volatile 168 | #0xC00000E9 0x0000000000000000 # Instructions Retired Performance Count, r/o, volatile 169 | #0xC0000100 0x0000000000000000 # FS Base, r/w 170 | #0xC0000101 0x0000000000000000 # GS Base, r/w 171 | #0xC0000102 0x0000000000000000 # Kernel GS Base, r/w 172 | #0xC0000103 0x0000000000000000 # Auxiliary Time Stamp Counter, r/w, volatile 173 | #0xC0000104 0x0000000000000000 # Time Stamp Counter Ratio, r/w 174 | #0xC0000200 0x0000000000000000 # L3 QOS Bandwidth Control, r/w 175 | #0xC0000201 0x0000000000000000 # " 176 | #0xC0000202 0x0000000000000000 # " 177 | #0xC0000203 0x0000000000000000 # " 178 | #0xC0000204 0x0000000000000000 # " 179 | #0xC0000205 0x0000000000000000 # " 180 | #0xC0000206 0x0000000000000000 # " 181 | #0xC0000207 0x0000000000000000 # " 182 | #0xC0000208 0x0000000000000000 # " 183 | #0xC0000209 0x0000000000000000 # " 184 | #0xC000020A 0x0000000000000000 # " 185 | #0xC000020B 0x0000000000000000 # " 186 | #0xC000020C 0x0000000000000000 # " 187 | #0xC000020D 0x0000000000000000 # " 188 | #0xC000020E 0x0000000000000000 # " 189 | #0xC000020F 0x0000000000000000 # " 190 | #0xC0000410 0x0000000000000000 # MCA Interrupt Configuration, r/w 191 | #0xC0010000 0x0000000000000000 # Performance Event Select 0, r/w 192 | #0xC0010001 0x0000000000000000 # Performance Event Select 1, r/w 193 | #0xC0010002 0x0000000000000000 # Performance Event Select 2, r/w 194 | #0xC0010003 0x0000000000000000 # Performance Event Select 3, r/w 195 | #0xC0010004 0x0000000000000000 # Performance Event Counter 0, r/w, volatile 196 | #0xC0010005 0x0000000000000000 # Performance Event Counter 1, r/w, volatile 197 | #0xC0010006 0x0000000000000000 # Performance Event Counter 2, r/w, volatile 198 | #0xC0010007 0x0000000000000000 # Performance Event Counter 3, r/w, volatile 199 | #0xC0010010 0x0000000000000000 # System Configuration, r/w 200 | #0xC0010015 0x0000000000000000 # Hardware Configuration, r/w 201 | ##Note: IO Range Base addresses given as MSRC001_001[6..8] (p 161) 202 | ## IO Range Mask addresses given as MSRC001_001[7..9] (p 162) 203 | ## Intrepreting as MSRC001_001[6,8] and MSRC001_001[7,9]. 204 | ## See https://community.amd.com/t5/newcomers-start-here/ppr-documentation-errata/m-p/561391#M2275 205 | #0xC0010016 0x0000000000000000 # IO Range Base 0, r/w 206 | #0xC0010017 0x0000000000000000 # IO Range Mask 0, r/w 207 | #0xC0010018 0x0000000000000000 # IO Range Base 1, r/w 208 | #0xC0010019 0x0000000000000000 # IO Range Mask 1, r/w 209 | #0xC001001A 0x0000000000000000 # Top Of Memory, r/w 210 | #0xC001001D 0x0000000000000000 # Top Of Memory 2 211 | #0xC0010022 0x0000000000000000 # Machine Check Exception Redirection, r/w 212 | #0xC0010030 0x0000000000000000 # Processor Name String 213 | #0xC0010031 0x0000000000000000 # " 214 | #0xC0010032 0x0000000000000000 # " 215 | #0xC0010033 0x0000000000000000 # " 216 | #0xC0010034 0x0000000000000000 # " 217 | #0xC0010035 0x0000000000000000 # " 218 | #0xC0010050 0x0000000000000000 # IO Trap, r/w 219 | #0xC0010051 0x0000000000000000 # " 220 | #0xC0010052 0x0000000000000000 # " 221 | #0xC0010053 0x0000000000000000 # " 222 | #0xC0010054 0x0000000000000000 # IO Trap Control, r/w 223 | #0xC0010055 0x0000000000000000 # [Reserved] 224 | #0xC0010056 0x0000000000000000 # SMI Trigger IO Cycle, r/w 225 | #0xC0010058 0x0000000000000000 # MMIO Configuration Base Address 226 | 0xC0010061 0x0000000000000000 # P-state Current Limit, r/o, volatile 227 | 0xC0010062 0x0000000000000000 # P-state Control, r/w 228 | 0xC0010063 0x0000000000000000 # P-state Status, r/o, volatile 229 | 0xC0010064 0x0000000000000000 # P-state 7 (or is it 0?), r/w 230 | 0xC0010065 0x0000000000000000 # P-state 6, r/w 231 | 0xC0010066 0x0000000000000000 # P-state 5, r/w 232 | 0xC0010067 0x0000000000000000 # P-state 4, r/w 233 | 0xC0010068 0x0000000000000000 # P-state 3, r/w 234 | 0xC0010069 0x0000000000000000 # P-state 2, r/w 235 | 0xC001006A 0x0000000000000000 # P-state 1, r/w 236 | 0xC001006B 0x0000000000000000 # P-state 0, r/w 237 | #0xC0010073 0x0000000000000000 # C-state Base Address, r/w 238 | #0xC0010074 0x0000000000000000 # CPU Watchdog Timer, r/w 239 | #0xC0010111 0x0000000000000000 # SMM Base Address, r/o 240 | #0xC0010112 0x0000000000000000 # SMM TSeg Base Address, r/w 241 | #0xC0010113 0x0000000000000000 # SMMTSeg Mask, r/w 242 | #0xC0010114 0x0000000000000000 # Virtual Machine Control, r/w 243 | #0xC0010115 0x0000000000000000 # IGNNE, r/w 244 | #0xC0010116 0x0000000000000000 # SMM Control, w/o 245 | #0xC0010117 0x0000000000000000 # Virtual Machine Host Save Physical Address, r/w 246 | #0xC0010118 0x0000000000000000 # SVM Lock Key, r/w 247 | #0xC001011A 0x0000000000000000 # Local SMI Status, r/w 248 | #0xC001011B 0x0000000000000000 # AVIC Doorbell, w/o 249 | #0xC001011E 0x0000000000000000 # VM Page Flush, w/o 250 | #0xC0010130 0x0000000000000000 # Guest Host Communication Block, r/w 251 | #0xC0010131 0x0000000000000000 # SEV Status, r/o 252 | #0xC0010140 0x0000000000000000 # OS Visible Work-around Length, r/w 253 | #0xC0010141 0x0000000000000000 # OS Visible Work-around Status, r/w 254 | 0xC0010200 0x0000030FFFD7FFFF # Performance Event Select 0, r/w 255 | 0xC0010201 0x0000FFFFFFFFFFFF # Performance Event Counter 0, r/w, volatile 256 | 0xC0010202 0x0000030FFFD7FFFF # Performance Event Select 1, r/w 257 | 0xC0010203 0x0000FFFFFFFFFFFF # Performance Event Counter 1, r/w, volatile 258 | 0xC0010204 0x0000030FFFD7FFFF # Performance Event Select 2, r/w 259 | 0xC0010205 0x0000FFFFFFFFFFFF # Performance Event Counter 2, r/w, volatile 260 | 0xC0010206 0x0000030FFFD7FFFF # Performance Event Select 3, r/w 261 | 0xC0010207 0x0000FFFFFFFFFFFF # Performance Event Counter 3, r/w, volatile 262 | 0xC0010208 0x0000030FFFD7FFFF # Performance Event Select 4, r/w 263 | 0xC0010209 0x0000FFFFFFFFFFFF # Performance Event Counter 4, r/w, volatile 264 | 0xC001020A 0x0000030FFFD7FFFF # Performance Event Select 5, r/w 265 | 0xC001020B 0x0000FFFFFFFFFFFF # Performance Event Counter 5, r/w, volatile 266 | 0xC0010230 0x0F07DC000040FFFF # L3 Performance Event Select, r/w 267 | 0xC0010231 0x0001FFFFFFFFFFFF # Performance Event Counter, r/w, volatile 268 | 0xC0010232 0x0F07DC000040FFFF # L3 Performance Event Select, r/w 269 | 0xC0010233 0x0001FFFFFFFFFFFF # Performance Event Counter, r/w, volatile 270 | 0xC0010234 0x0F07DC000040FFFF # L3 Performance Event Select, r/w 271 | 0xC0010235 0x0001FFFFFFFFFFFF # Performance Event Counter, r/w, volatile 272 | 0xC0010236 0x0F07DC000040FFFF # L3 Performance Event Select, r/w 273 | 0xC0010237 0x0001FFFFFFFFFFFF # Performance Event Counter, r/w, volatile 274 | 0xC0010238 0x0F07DC000040FFFF # L3 Performance Event Select, r/w 275 | 0xC0010239 0x0001FFFFFFFFFFFF # Performance Event Counter, r/w, volatile 276 | 0xC001023A 0x0F07DC000040FFFF # L3 Performance Event Select, r/w 277 | 0xC001023B 0x0001FFFFFFFFFFFF # Performance Event Counter, r/w, volatile 278 | 0xC0010240 0x1800000F0040FFFF # Data Fabric Performance Event Select, r/w 279 | 0xC0010241 0x0000FFFFFFFFFFFF # Data Fabric Performance Event Counter, r/w, volatile 280 | 0xC0010242 0x1800000F0040FFFF # Data Fabric Performance Event Select, r/w 281 | 0xC0010243 0x0000FFFFFFFFFFFF # Data Fabric Performance Event Counter, r/w, volatile 282 | 0xC0010244 0x1800000F0040FFFF # Data Fabric Performance Event Select, r/w 283 | 0xC0010245 0x0000FFFFFFFFFFFF # Data Fabric Performance Event Counter, r/w, volatile 284 | 0xC0010246 0x1800000F0040FFFF # Data Fabric Performance Event Select, r/w 285 | 0xC0010247 0x0000FFFFFFFFFFFF # Data Fabric Performance Event Counter, r/w, volatile 286 | 0xC0010299 0x0000000000000000 # RAPL Power Unit, r/o, volatile 287 | 0xC001029A 0x0000000000000000 # Core Energy Status, r/o, volatile 288 | 0xC001029B 0x0000000000000000 # Package Energy Status, r/o, volatile 289 | 0xC00102F0 0x0000000000000000 # Protected Processor Inventory Number Control, r/o 290 | 0xC00102F1 0x0000000000000000 # Protected Processor Inventory Number, r/o 291 | #0xC0011002 0x0000000000000000 # CPUID Features for CPUID Fn00000007_E[A,B]X, r/w 292 | #0xC0011003 0x0000000000000000 # Thermal and Power Management CPUID Features, r/w 293 | #0xC0011004 0x0000000000000000 # CPUID Features for CPUID Fn00000001_E[C,D]X, r/w 294 | #0xC0011005 0x0000000000000000 # CPUID Features for CPUID Fn80000001_E[C,D]X, r/w 295 | #0xC0011019 0x0000000000000000 # Address Mask for DR1 Breakpoint, r/w 296 | #0xC001101A 0x0000000000000000 # Address Mask for DR2 Breakpoint, r/w 297 | #0xC001101B 0x0000000000000000 # Address Mask for DR3 Breakpoint, r/w 298 | #0xC001101C 0x0000000000000000 # Address Mask for DR0 Breakpoints, r/w 299 | #0xC0011030 0x0000000000000000 # IBS Fetch Control, r/w, volatile 300 | #0xC0011031 0x0000000000000000 # IBS Fetch Linear Address, r/w, volatile 301 | #0xC0011032 0x0000000000000000 # IBS Fetch Physical Address, r/w, volatile 302 | #0xC0011033 0x0000000000000000 # IBS Execution Control, r/w, volatile 303 | #0xC0011034 0x0000000000000000 # IBS Op RIP, r/w, volatile 304 | #0xC0011035 0x0000000000000000 # IBS Op Data, r/w, volatile 305 | #0xC0011036 0x0000000000000000 # IBS Op Data 2, r/w, volatile 306 | #0xC0011037 0x0000000000000000 # IBS Op Data 3, r/w, volatile 307 | #0xC0011038 0x0000000000000000 # IBS DC Linear Address, r/w, volatile 308 | #0xC0011039 0x0000000000000000 # IBS DC Physical Address, r/w, volatile 309 | #0xC001103A 0x0000000000000000 # IBS Control, r/o 310 | #0xC001103B 0x0000000000000000 # IBS Branch Target Address, r/w, volatile 311 | #0xC001103C 0x0000000000000000 # IBS Fetch Control Extended, r/o, volatile 312 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /allowlists/al_19_1: -------------------------------------------------------------------------------- 1 | ## This file contains the model-specific registers available in AMD processors of Architecture Zen3 2 | ## based on a close reading of Processor Programming Reference (PPR) for AMD Family 19h Model 01h, Revision B1 Processors (May 28 2021) 3 | ## Uncommenting allows reading a particular MSR. 4 | ## Modifying the write mask allows writing to those particular bits. 5 | ## Be sure to cat the modified list into /dev/cpu/msr_allowlist. 6 | ## See the README file for more details. 7 | ## 8 | ## MSR # Write Mask # Comment 9 | # 0x00000010 0x0000000000000000 # Time Stamp Counter 10 | # 0x0000001B 0x0000000000000000 # APIC Base Address 11 | # 0x0000002A 0x0000000000000000 # Cluster ID 12 | # 0x00000048 0x0000000000000000 # Speculative Control 13 | # 0x00000049 0x0000000000000000 # Prediction Command 14 | # 0x0000008B 0x0000000000000000 # Patch Level 15 | # 0x000000E7 0x0000000000000000 # Max Performance Frequency Clock Count 16 | # 0x000000E8 0x0000000000000000 # Actual Performance Frequency Clock Count 17 | # 0x000000FE 0x0000000000000000 # MTRR Capabilities 18 | # 0x00000174 0x0000000000000000 # SYSENTER CS 19 | # 0x00000175 0x0000000000000000 # SYSENTER ESP 20 | # 0x00000176 0x0000000000000000 # SYSENTER EIP 21 | # 0x00000179 0x0000000000000000 # Global Machine Check Capabilities 22 | # 0x0000017A 0x0000000000000000 # Global Machine Check Status 23 | # 0x0000017B 0x0000000000000000 # Global Machine Check Exception Reporting Control 24 | # 0x000001D9 0x0000000000000000 # Debug Control 25 | # 0x000001DB 0x0000000000000000 # Last Branch From IP 26 | # 0x000001DC 0x0000000000000000 # Last Branch To IP 27 | # 0x000001DD 0x0000000000000000 # Last Exception From IP 28 | # 0x000001DE 0x0000000000000000 # Last Exception To IP 29 | # 0x00000200 0x0000000000000000 # Variable-Size MTRRs Base 30 | # 0x00000201 0x0000000000000000 # Variable-Size MTRRs Mask 31 | # 0x00000202 0x0000000000000000 # Variable-Size MTRRs Base 32 | # 0x00000203 0x0000000000000000 # Variable-Size MTRRs Mask 33 | # 0x00000204 0x0000000000000000 # Variable-Size MTRRs Base 34 | # 0x00000205 0x0000000000000000 # Variable-Size MTRRs Mask 35 | # 0x00000206 0x0000000000000000 # Variable-Size MTRRs Base 36 | # 0x00000207 0x0000000000000000 # Variable-Size MTRRs Mask 37 | # 0x00000208 0x0000000000000000 # Variable-Size MTRRs Base 38 | # 0x00000209 0x0000000000000000 # Variable-Size MTRRs Mask 39 | # 0x0000020A 0x0000000000000000 # Variable-Size MTRRs Base 40 | # 0x0000020B 0x0000000000000000 # Variable-Size MTRRs Mask 41 | # 0x0000020C 0x0000000000000000 # Variable-Size MTRRs Base 42 | # 0x0000020D 0x0000000000000000 # Variable-Size MTRRs Mask 43 | # 0x0000020E 0x0000000000000000 # Variable-Size MTRRs Base 44 | # 0x0000020F 0x0000000000000000 # Variable-Size MTRRs Mask 45 | # 0x00000250 0x0000000000000000 # Fixed-Size MTRRs 46 | # 0x00000258 0x0000000000000000 # Fixed-Size MTRRs 47 | # 0x00000259 0x0000000000000000 # Fixed-Size MTRRs 48 | # 0x00000268 0x0000000000000000 # Fixed-Size MTRRs 49 | # 0x00000269 0x0000000000000000 # Fixed-Size MTRRs 50 | # 0x0000026A 0x0000000000000000 # Fixed-Size MTRRs 51 | # 0x0000026B 0x0000000000000000 # Fixed-Size MTRRs 52 | # 0x0000026C 0x0000000000000000 # Fixed-Size MTRRs 53 | # 0x0000026D 0x0000000000000000 # Fixed-Size MTRRs 54 | # 0x0000026E 0x0000000000000000 # Fixed-Size MTRRs 55 | # 0x0000026F 0x0000000000000000 # Fixed-Size MTRRs 56 | # 0x00000277 0x0000000000000000 # Page Attribute Table 57 | # 0x000002FF 0x0000000000000000 # MTRR Default Memory Type 58 | # 0x000006A0 0x0000000000000000 # User CET 59 | # 0x000006A2 0x0000000000000000 # Supervisor CET 60 | # 0x000006A4 0x0000000000000000 # PL0 Shadow Stack Pointer 61 | # 0x000006A5 0x0000000000000000 # PL1 Shadow Stack Pointer 62 | # 0x000006A6 0x0000000000000000 # PL2 Shadow Stack Pointer 63 | # 0x000006A7 0x0000000000000000 # PL3 Shadow Stack Pointer 64 | # 0x000006A8 0x0000000000000000 # Interrupt SSP Table Address 65 | # 0x00000802 0x0000000000000000 # APIC ID 66 | # 0x00000803 0x0000000000000000 # APIC Version 67 | # 0x00000808 0x0000000000000000 # Task Priority 68 | # 0x00000809 0x0000000000000000 # Arbitration Priority 69 | # 0x0000080A 0x0000000000000000 # Processor Priority 70 | # 0x0000080B 0x0000000000000000 # End Of Interrupt 71 | # 0x0000080D 0x0000000000000000 # Logical Destination Register 72 | # 0x0000080F 0x0000000000000000 # Spurious Interrupt Vector 73 | # 0x00000810 0x0000000000000000 # In Service Register 74 | # 0x00000811 0x0000000000000000 # In Service Register 75 | # 0x00000812 0x0000000000000000 # In Service Register 76 | # 0x00000813 0x0000000000000000 # In Service Register 77 | # 0x00000814 0x0000000000000000 # In Service Register 78 | # 0x00000815 0x0000000000000000 # In Service Register 79 | # 0x00000816 0x0000000000000000 # In Service Register 80 | # 0x00000817 0x0000000000000000 # In Service Register 81 | # 0x00000818 0x0000000000000000 # Trigger Mode Register 82 | # 0x00000819 0x0000000000000000 # Trigger Mode Register 83 | # 0x0000081A 0x0000000000000000 # Trigger Mode Register 84 | # 0x0000081B 0x0000000000000000 # Trigger Mode Register 85 | # 0x0000081C 0x0000000000000000 # Trigger Mode Register 86 | # 0x0000081D 0x0000000000000000 # Trigger Mode Register 87 | # 0x0000081E 0x0000000000000000 # Trigger Mode Register 88 | # 0x0000081F 0x0000000000000000 # Trigger Mode Register 89 | # 0x00000820 0x0000000000000000 # Interrupt Request Register 90 | # 0x00000821 0x0000000000000000 # Interrupt Request Register 91 | # 0x00000822 0x0000000000000000 # Interrupt Request Register 92 | # 0x00000824 0x0000000000000000 # Interrupt Request Register 93 | # 0x00000825 0x0000000000000000 # Interrupt Request Register 94 | # 0x00000826 0x0000000000000000 # Interrupt Request Register 95 | # 0x00000827 0x0000000000000000 # Interrupt Request Register 96 | # 0x00000828 0x0000000000000000 # Error Status Register 97 | # 0x00000830 0x0000000000000000 # Interrupt Command 98 | # 0x00000832 0x0000000000000000 # LVT Timer 99 | # 0x00000833 0x0000000000000000 # LVT Thermal Sensor 100 | # 0x00000834 0x0000000000000000 # LVT Performance Monitor 101 | # 0x00000835 0x0000000000000000 # LVT LINT[1:0] 102 | # 0x00000836 0x0000000000000000 # LVT LINT[1:0] 103 | # 0x00000837 0x0000000000000000 # LVT Error 104 | # 0x00000838 0x0000000000000000 # Timer Initial Count 105 | # 0x00000839 0x0000000000000000 # Timer Current Count 106 | # 0x0000083E 0x0000000000000000 # Timer Divide Configuration 107 | # 0x0000083F 0x0000000000000000 # Self IPI 108 | # 0x00000840 0x0000000000000000 # Extended APIC Feature 109 | # 0x00000841 0x0000000000000000 # Extended APIC Control 110 | # 0x00000842 0x0000000000000000 # Specific End Of Interrupt 111 | # 0x00000848 0x0000000000000000 # Interrupt Enable 0 112 | # 0x00000849 0x0000000000000000 # Interrupt Enable 7..1 113 | # 0x0000084A 0x0000000000000000 # Interrupt Enable 7..1 114 | # 0x0000084B 0x0000000000000000 # Interrupt Enable 7..1 115 | # 0x0000084C 0x0000000000000000 # Interrupt Enable 7..1 116 | # 0x0000084D 0x0000000000000000 # Interrupt Enable 7..1 117 | # 0x0000084E 0x0000000000000000 # Interrupt Enable 7..1 118 | # 0x0000084F 0x0000000000000000 # Interrupt Enable 7..1 119 | # 0x00000850 0x0000000000000000 # Extended Interrupt Local Vector Table 120 | # 0x00000851 0x0000000000000000 # Extended Interrupt Local Vector Table 121 | # 0x00000852 0x0000000000000000 # Extended Interrupt Local Vector Table 122 | # 0x00000853 0x0000000000000000 # Extended Interrupt Local Vector Table 123 | # 0x00000C81 0x0000000000000000 # L3 QoS Configuration 124 | # 0x00000C8D 0x0000000000000000 # Monitoring Event Select 125 | # 0x00000C8E 0x0000000000000000 # QOS L3 Counter 126 | # 0x00000C8F 0x0000000000000000 # Resource Association 127 | # 0x00000C90 0x0000000000000000 # L3 QOS Allocation Mask 128 | # 0x00000C91 0x0000000000000000 # L3 QOS Allocation Mask 129 | # 0x00000C92 0x0000000000000000 # L3 QOS Allocation Mask 130 | # 0x00000C93 0x0000000000000000 # L3 QOS Allocation Mask 131 | # 0x00000C94 0x0000000000000000 # L3 QOS Allocation Mask 132 | # 0x00000C95 0x0000000000000000 # L3 QOS Allocation Mask 133 | # 0x00000C96 0x0000000000000000 # L3 QOS Allocation Mask 134 | # 0x00000C97 0x0000000000000000 # L3 QOS Allocation Mask 135 | # 0x00000C98 0x0000000000000000 # L3 QOS Allocation Mask 136 | # 0x00000C99 0x0000000000000000 # L3 QOS Allocation Mask 137 | # 0x00000C9A 0x0000000000000000 # L3 QOS Allocation Mask 138 | # 0x00000C9B 0x0000000000000000 # L3 QOS Allocation Mask 139 | # 0x00000C9C 0x0000000000000000 # L3 QOS Allocation Mask 140 | # 0x00000C9D 0x0000000000000000 # L3 QOS Allocation Mask 141 | # 0x00000C9E 0x0000000000000000 # L3 QOS Allocation Mask 142 | # 0x00000C9F 0x0000000000000000 # L3 QOS Allocation Mask 143 | # 0x00000DA0 0x0000000000000000 # Extended Supervisor State 144 | # 0xC0000080 0x0000000000000000 # Extended Feature Enable 145 | # 0xC0000081 0x0000000000000000 # SYSCALL Target Address 146 | # 0xC0000082 0x0000000000000000 # Long Mode SYSCALL Target Address 147 | # 0xC0000083 0x0000000000000000 # Compatibility Mode SYSCALL Target Address 148 | # 0xC0000084 0x0000000000000000 # SYSCALL Flag Mask 149 | # 0xC00000E7 0x0000000000000000 # Read-Only Max Performance Frequency Clock Count 150 | # 0xC00000E8 0x0000000000000000 # Read-Only Actual Performance Frequency Clock Count 151 | # 0xC00000E9 0x0000000000000000 # Instructions Retired Performance Count 152 | # 0xC0000100 0x0000000000000000 # FS Base 153 | # 0xC0000101 0x0000000000000000 # GS Base 154 | # 0xC0000102 0x0000000000000000 # Kernel GS Base 155 | # 0xC0000103 0x0000000000000000 # Auxiliary Time Stamp Counter 156 | # 0xC0000104 0x0000000000000000 # Time Stamp Counter Ratio 157 | # 0xC0000108 0x0000000000000000 # Prefetch Control 158 | # 0xC000010F 0x0000000000000000 # Debug Extension Configuration 159 | # 0xC0000200 0x0000000000000000 # L3 QOS Bandwidth Control 160 | # 0xC0000201 0x0000000000000000 # L3 QOS Bandwidth Control 161 | # 0xC0000202 0x0000000000000000 # L3 QOS Bandwidth Control 162 | # 0xC0000203 0x0000000000000000 # L3 QOS Bandwidth Control 163 | # 0xC0000204 0x0000000000000000 # L3 QOS Bandwidth Control 164 | # 0xC0000205 0x0000000000000000 # L3 QOS Bandwidth Control 165 | # 0xC0000206 0x0000000000000000 # L3 QOS Bandwidth Control 166 | # 0xC0000207 0x0000000000000000 # L3 QOS Bandwidth Control 167 | # 0xC0000208 0x0000000000000000 # L3 QOS Bandwidth Control 168 | # 0xC0000209 0x0000000000000000 # L3 QOS Bandwidth Control 169 | # 0xC000020A 0x0000000000000000 # L3 QOS Bandwidth Control 170 | # 0xC000020B 0x0000000000000000 # L3 QOS Bandwidth Control 171 | # 0xC000020C 0x0000000000000000 # L3 QOS Bandwidth Control 172 | # 0xC000020D 0x0000000000000000 # L3 QOS Bandwidth Control 173 | # 0xC000020E 0x0000000000000000 # L3 QOS Bandwidth Control 174 | # 0xC000020F 0x0000000000000000 # L3 QOS Bandwidth Control 175 | # 0xC0000410 0x0000000000000000 # MCA Interrupt Configuration 176 | # 0xC0010000 0x0000000000000000 # Performance Event Select 0 177 | # 0xC0010001 0x0000000000000000 # Performance Event Select 1 178 | # 0xC0010002 0x0000000000000000 # Performance Event Select 2 179 | # 0xC0010003 0x0000000000000000 # Performance Event Select 3 180 | # 0xC0010004 0x0000000000000000 # Performance Event Counter [3:0] 181 | # 0xC0010005 0x0000000000000000 # Performance Event Counter [3:0] 182 | # 0xC0010006 0x0000000000000000 # Performance Event Counter [3:0] 183 | # 0xC0010007 0x0000000000000000 # Performance Event Counter [3:0] 184 | # 0xC0010010 0x0000000000000000 # System Configuration 185 | # 0xC0010015 0x0000000000000000 # Hardware Configuration 186 | # 0xC0010016 0x0000000000000000 # IO Range Base 187 | # 0xC0010017 0x0000000000000000 # IO Range Mask 188 | # 0xC0010018 0x0000000000000000 # IO Range Base 189 | # 0xC0010019 0x0000000000000000 # IO Range Mask 190 | # 0xC001001A 0x0000000000000000 # Top Of Memory 191 | # 0xC001001D 0x0000000000000000 # Top Of Memory 2 192 | # 0xC0010022 0x0000000000000000 # Machine Check Exception Redirection 193 | # 0xC0010030 0x0000000000000000 # Processor Name String 194 | # 0xC0010031 0x0000000000000000 # Processor Name String 195 | # 0xC0010032 0x0000000000000000 # Processor Name String 196 | # 0xC0010033 0x0000000000000000 # Processor Name String 197 | # 0xC0010034 0x0000000000000000 # Processor Name String 198 | # 0xC0010035 0x0000000000000000 # Processor Name String 199 | # 0xC0010050 0x0000000000000000 # IO Trap 200 | # 0xC0010051 0x0000000000000000 # IO Trap 201 | # 0xC0010052 0x0000000000000000 # IO Trap 202 | # 0xC0010053 0x0000000000000000 # IO Trap 203 | # 0xC0010054 0x0000000000000000 # IO Trap Control 204 | # 0xC0010055 0x0000000000000000 # Reserved. 205 | # 0xC0010056 0x0000000000000000 # SMI Trigger IO Cycle 206 | # 0xC0010058 0x0000000000000000 # MMIO Configuration Base Address 207 | # 0xC0010061 0x0000000000000000 # P-state Current Limit 208 | # 0xC0010062 0x0000000000000000 # P-state Control 209 | # 0xC0010063 0x0000000000000000 # P-state Status 210 | # 0xC0010064 0x0000000000000000 # P-state [7:0] 211 | # 0xC0010065 0x0000000000000000 # P-state [7:0] 212 | # 0xC0010066 0x0000000000000000 # P-state [7:0] 213 | # 0xC0010067 0x0000000000000000 # P-state [7:0] 214 | # 0xC0010068 0x0000000000000000 # P-state [7:0] 215 | # 0xC0010069 0x0000000000000000 # P-state [7:0] 216 | # 0xC001006A 0x0000000000000000 # P-state [7:0] 217 | # 0xC001006B 0x0000000000000000 # P-state [7:0] 218 | # 0xC0010073 0x0000000000000000 # C-state Base Address 219 | # 0xC0010074 0x0000000000000000 # CPU Watchdog Timer 220 | # 0xC0010111 0x0000000000000000 # SMM Base Address 221 | # 0xC0010112 0x0000000000000000 # SMM TSeg Base Address 222 | # 0xC0010113 0x0000000000000000 # SMM TSeg Mask 223 | # 0xC0010114 0x0000000000000000 # Virtual Machine Control 224 | # 0xC0010115 0x0000000000000000 # IGNNE 225 | # 0xC0010116 0x0000000000000000 # SMM Control 226 | # 0xC0010117 0x0000000000000000 # Virtual Machine Host Save Physical Address 227 | # 0xC0010118 0x0000000000000000 # SVM Lock Key 228 | # 0xC001011A 0x0000000000000000 # Local SMI Status 229 | # 0xC001011B 0x0000000000000000 # AVIC Doorbell 230 | # 0xC001011E 0x0000000000000000 # VM Page Flush 231 | # 0xC0010130 0x0000000000000000 # Guest Host Communication Block 232 | # 0xC0010131 0x0000000000000000 # SEV Status 233 | # 0xC0010132 0x0000000000000000 # RMP Base 234 | # 0xC0010133 0x0000000000000000 # RMP End 235 | # 0xC0010140 0x0000000000000000 # OS Visible Work-around Length 236 | # 0xC0010141 0x0000000000000000 # OS Visible Work-around Status 237 | # 0xC0010200 0x0000000000000000 # Performance Event Select 0 238 | # 0xC0010201 0x0000000000000000 # Performance Event Counter [5:0] 239 | # 0xC0010202 0x0000000000000000 # Performance Event Select 1 240 | # 0xC0010203 0x0000000000000000 # Performance Event Counter [5:0] 241 | # 0xC0010204 0x0000000000000000 # Performance Event Select 2 242 | # 0xC0010205 0x0000000000000000 # Performance Event Counter [5:0] 243 | # 0xC0010206 0x0000000000000000 # Performance Event Select 3 244 | # 0xC0010207 0x0000000000000000 # Performance Event Counter [5:0] 245 | # 0xC0010208 0x0000000000000000 # Performance Event Select 4 246 | # 0xC0010209 0x0000000000000000 # Performance Event Counter [5:0] 247 | # 0xC001020A 0x0000000000000000 # Performance Event Select 5 248 | # 0xC001020B 0x0000000000000000 # Performance Event Counter [5:0] 249 | # 0xC0010230 0x0000000000000000 # L3 Performance Event Select [5:0] 250 | # 0xC0010231 0x0000000000000000 # L3 Performance Event Counter [5:0] 251 | # 0xC0010232 0x0000000000000000 # L3 Performance Event Select [5:0] 252 | # 0xC0010233 0x0000000000000000 # L3 Performance Event Counter [5:0] 253 | # 0xC0010234 0x0000000000000000 # L3 Performance Event Select [5:0] 254 | # 0xC0010235 0x0000000000000000 # L3 Performance Event Counter [5:0] 255 | # 0xC0010236 0x0000000000000000 # L3 Performance Event Select [5:0] 256 | # 0xC0010237 0x0000000000000000 # L3 Performance Event Counter [5:0] 257 | # 0xC0010238 0x0000000000000000 # L3 Performance Event Select [5:0] 258 | # 0xC0010239 0x0000000000000000 # L3 Performance Event Counter [5:0] 259 | # 0xC001023A 0x0000000000000000 # L3 Performance Event Select [5:0] 260 | # 0xC001023B 0x0000000000000000 # L3 Performance Event Counter [5:0] 261 | # 0xC0010240 0x0000000000000000 # Data Fabric Performance Event Select [3:0] 262 | # 0xC0010241 0x0000000000000000 # Data Fabric Performance Event Counter [3:0] 263 | # 0xC0010242 0x0000000000000000 # Data Fabric Performance Event Select [3:0] 264 | # 0xC0010243 0x0000000000000000 # Data Fabric Performance Event Counter [3:0] 265 | # 0xC0010244 0x0000000000000000 # Data Fabric Performance Event Select [3:0] 266 | # 0xC0010245 0x0000000000000000 # Data Fabric Performance Event Counter [3:0] 267 | # 0xC0010246 0x0000000000000000 # Data Fabric Performance Event Select [3:0] 268 | # 0xC0010247 0x0000000000000000 # Data Fabric Performance Event Counter [3:0] 269 | # 0xC0010299 0x0000000000000000 # RAPL Power Unit 270 | # 0xC001029A 0x0000000000000000 # Core Energy Status 271 | # 0xC001029B 0x0000000000000000 # Package Energy Status 272 | # 0xC00102F0 0x0000000000000000 # Protected Processor Inventory Number Control 273 | # 0xC00102F1 0x0000000000000000 # Protected Processor Inventory Number 274 | # 0xC0010300 0x0000000000000000 # Sample Branch From 275 | # 0xC0010301 0x0000000000000000 # Sample Branch To 276 | # 0xC0010302 0x0000000000000000 # Sample Branch From 277 | # 0xC0010303 0x0000000000000000 # Sample Branch To 278 | # 0xC0010304 0x0000000000000000 # Sample Branch From 279 | # 0xC0010305 0x0000000000000000 # Sample Branch To 280 | # 0xC0010306 0x0000000000000000 # Sample Branch From 281 | # 0xC0010307 0x0000000000000000 # Sample Branch To 282 | # 0xC0010308 0x0000000000000000 # Sample Branch From 283 | # 0xC0010309 0x0000000000000000 # Sample Branch To 284 | # 0xC001030A 0x0000000000000000 # Sample Branch From 285 | # 0xC001030B 0x0000000000000000 # Sample Branch To 286 | # 0xC001030C 0x0000000000000000 # Sample Branch From 287 | # 0xC001030D 0x0000000000000000 # Sample Branch To 288 | # 0xC001030E 0x0000000000000000 # Sample Branch From 289 | # 0xC001030F 0x0000000000000000 # Sample Branch To 290 | # 0xC0010310 0x0000000000000000 # Sample Branch From 291 | # 0xC0010311 0x0000000000000000 # Sample Branch To 292 | # 0xC0010312 0x0000000000000000 # Sample Branch From 293 | # 0xC0010313 0x0000000000000000 # Sample Branch To 294 | # 0xC0010314 0x0000000000000000 # Sample Branch From 295 | # 0xC0010315 0x0000000000000000 # Sample Branch To 296 | # 0xC0010316 0x0000000000000000 # Sample Branch From 297 | # 0xC0010317 0x0000000000000000 # Sample Branch To 298 | # 0xC0010318 0x0000000000000000 # Sample Branch From 299 | # 0xC0010319 0x0000000000000000 # Sample Branch To 300 | # 0xC001031A 0x0000000000000000 # Sample Branch From 301 | # 0xC001031B 0x0000000000000000 # Sample Branch To 302 | # 0xC001031C 0x0000000000000000 # Sample Branch From 303 | # 0xC001031D 0x0000000000000000 # Sample Branch To 304 | # 0xC001031E 0x0000000000000000 # Sample Branch From 305 | # 0xC001031F 0x0000000000000000 # Sample Branch To 306 | # 0xC0011002 0x0000000000000000 # CPUID Features for CPUID Fn00000007_E[A,B]X 307 | # 0xC0011003 0x0000000000000000 # Thermal and Power Management CPUID Features 308 | # 0xC0011004 0x0000000000000000 # CPUID Features for CPUID Fn00000001_E[C,D]X 309 | # 0xC0011005 0x0000000000000000 # CPUID Features for CPUID Fn80000001_E[C,D]X 310 | # 0xC0011019 0x0000000000000000 # Address Mask For DR1 Breakpoint 311 | # 0xC001101A 0x0000000000000000 # Address Mask For DR2 Breakpoint 312 | # 0xC001101B 0x0000000000000000 # Address Mask For DR3 Breakpoint 313 | # 0xC0011027 0x0000000000000000 # Address Mask For DR0 Breakpoints 314 | # 0xC0011030 0x0000000000000000 # IBS Fetch Control 315 | # 0xC0011031 0x0000000000000000 # IBS Fetch Linear Address 316 | # 0xC0011032 0x0000000000000000 # IBS Fetch Physical Address 317 | # 0xC0011033 0x0000000000000000 # IBS Execution Control 318 | # 0xC0011034 0x0000000000000000 # IBS Op RIP 319 | # 0xC0011035 0x0000000000000000 # IBS Op Data 320 | # 0xC0011036 0x0000000000000000 # IBS Op Data 2 321 | # 0xC0011037 0x0000000000000000 # IBS Op Data 3 322 | # 0xC0011038 0x0000000000000000 # IBS DC Linear Address 323 | # 0xC0011039 0x0000000000000000 # IBS DC Physical Address 324 | # 0xC001103A 0x0000000000000000 # IBS Control 325 | # 0xC001103B 0x0000000000000000 # IBS Branch Target Address 326 | # 0xC001103C 0x0000000000000000 # IBS Fetch Control Extended -------------------------------------------------------------------------------- /msrsave/msrsave.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Intel Corporation 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "msrsave.h" 19 | 20 | /* Random 64 bit integer to mark bad reads for MSRs with ~0 write mask */ 21 | enum {G_COOKIE_BAD_READ = 0xFB6A58813AEA28CF}; 22 | 23 | static int is_good_value(uint64_t write_val, uint64_t mask) 24 | { 25 | /* Check if value in save file represents a bad read. */ 26 | int result = 1; 27 | if (~mask) 28 | { 29 | result = (write_val == (mask & write_val)); 30 | } 31 | else 32 | { 33 | result = (write_val != G_COOKIE_BAD_READ); 34 | } 35 | return result; 36 | } 37 | 38 | static int msr_parse_allowlist(const char *allowlist_path, size_t *num_msr_ptr, uint64_t **msr_offset_ptr, uint64_t **msr_mask_ptr, FILE *error_log) 39 | { 40 | enum {BUFFER_SIZE = 8192}; 41 | int err = 0; 42 | int tmp_err = 0; 43 | int i; 44 | int tmp_fd = -1; 45 | int allowlist_fd = -1; 46 | size_t num_scan = 0; 47 | size_t num_msr = 0; 48 | ssize_t num_read = 0; 49 | ssize_t num_write = 0; 50 | char *allowlist_buffer = NULL; 51 | char *allowlist_ptr = NULL; 52 | uint64_t *msr_offset = NULL; 53 | uint64_t *msr_mask = NULL; 54 | struct stat allowlist_stat; 55 | char tmp_path[NAME_MAX] = "/tmp/msrsave_allowlist_XXXXXX"; 56 | char err_msg[NAME_MAX]; 57 | char copy_buffer[BUFFER_SIZE]; 58 | 59 | /* Copy allowlist into temporary file */ 60 | tmp_fd = mkstemp(tmp_path); 61 | if (tmp_fd == -1) 62 | { 63 | err = errno ? errno : -1; 64 | fprintf(error_log, "Creation of temporary file named\"%s\" failed!: %s\n", tmp_path, strerror(errno)); 65 | goto exit; 66 | } 67 | 68 | allowlist_fd = open(allowlist_path, O_RDONLY); 69 | if (allowlist_fd == -1) 70 | { 71 | err = errno ? errno : -1; 72 | fprintf(error_log, "Open of allowlist file named \"%s\" failed!: %s\n", allowlist_path, strerror(errno)); 73 | goto exit; 74 | } 75 | 76 | while ((num_read = read(allowlist_fd, copy_buffer, sizeof(copy_buffer)))) 77 | { 78 | if (num_read == -1) 79 | { 80 | err = errno ? errno : -1; 81 | fprintf(error_log, "Read of allowlist file \"%s\" failed!: %s\n", allowlist_path, strerror(errno)); 82 | goto exit; 83 | } 84 | 85 | num_write = write(tmp_fd, copy_buffer, num_read); 86 | if (num_write != num_read) 87 | { 88 | err = errno ? errno : -1; 89 | fprintf(error_log, "Write to temporary file \"%s\" failed!: %s\n", tmp_path, strerror(errno)); 90 | goto exit; 91 | } 92 | } 93 | 94 | tmp_err = close(tmp_fd); 95 | tmp_fd = -1; 96 | if (tmp_err == -1) 97 | { 98 | err = errno ? errno : -1; 99 | fprintf(error_log, "Close of temporary file named\"%s\" failed!: %s\n", tmp_path, strerror(errno)); 100 | goto exit; 101 | } 102 | 103 | tmp_err = close(allowlist_fd); 104 | allowlist_fd = -1; 105 | if (tmp_err == -1) 106 | { 107 | err = errno ? errno : -1; 108 | fprintf(error_log, "Close of allowlist file named\"%s\" failed!: %s\n", allowlist_path, strerror(errno)); 109 | goto exit; 110 | } 111 | 112 | *msr_offset_ptr = NULL; 113 | *msr_mask_ptr = NULL; 114 | 115 | /* Figure out how big the allowlist file is */ 116 | tmp_err = stat(tmp_path, &allowlist_stat); 117 | if (tmp_err != 0) 118 | { 119 | err = errno ? errno : -1; 120 | fprintf(error_log, "stat() of %s failed!: %s\n", tmp_path, strerror(errno)); 121 | goto exit; 122 | } 123 | 124 | if (allowlist_stat.st_size == 0) 125 | { 126 | err = errno ? errno : -1; 127 | fprintf(error_log, "Approved list file (%s) size is zero!: %s\n", tmp_path, strerror(errno)); 128 | goto exit; 129 | } 130 | 131 | /* Allocate buffer for file contents and null terminator */ 132 | allowlist_buffer = (char*)malloc(allowlist_stat.st_size + 1); 133 | if (!allowlist_buffer) 134 | { 135 | err = errno ? errno : -1; 136 | fprintf(error_log, "Could not allocate array of size %zu!: %s\n", allowlist_stat.st_size, strerror(errno)); 137 | goto exit; 138 | } 139 | allowlist_buffer[allowlist_stat.st_size] = '\0'; 140 | 141 | /* Open file */ 142 | tmp_fd = open(tmp_path, O_RDONLY); 143 | if (tmp_fd == -1) 144 | { 145 | err = errno ? errno : -1; 146 | fprintf(error_log, "Could not open allowlist temporary file \"%s\"!: %s\n", tmp_path, strerror(errno)); 147 | goto exit; 148 | } 149 | 150 | /* Read contents */ 151 | num_read = read(tmp_fd, allowlist_buffer, allowlist_stat.st_size); 152 | if (num_read != allowlist_stat.st_size) 153 | { 154 | err = errno ? errno : -1; 155 | fprintf(error_log, "Contents read from allowlist file is too small: %zu < %zu!: %s\n", num_read, allowlist_stat.st_size, strerror(errno)); 156 | goto exit; 157 | } 158 | 159 | /* close file */ 160 | tmp_err = close(tmp_fd); 161 | tmp_fd = -1; 162 | if (tmp_err) 163 | { 164 | err = errno ? errno : -1; 165 | fprintf(error_log, "Unable to close temporary allowlist file called \"%s\": %s\n", tmp_path, strerror(errno)); 166 | goto exit; 167 | } 168 | 169 | /* Count the number of new lines in the file that do not start with # */ 170 | allowlist_ptr = allowlist_buffer; 171 | while (allowlist_ptr && *allowlist_ptr) 172 | { 173 | if (*allowlist_ptr != '#') 174 | { 175 | ++num_msr; 176 | } 177 | allowlist_ptr = strchr(allowlist_ptr, '\n'); 178 | if (allowlist_ptr) 179 | { 180 | ++allowlist_ptr; 181 | } 182 | } 183 | *num_msr_ptr = num_msr; 184 | 185 | /* Allocate buffers for parsed allowlist */ 186 | msr_offset = *msr_offset_ptr = (uint64_t *)malloc(sizeof(uint64_t) * num_msr); 187 | if (!msr_offset) 188 | { 189 | err = errno ? errno : -1; 190 | fprintf(error_log, "Unable to allocate msr offset data of size: %zu!: %s\n", sizeof(uint64_t) * num_msr, strerror(errno)); 191 | goto exit; 192 | } 193 | 194 | msr_mask = *msr_mask_ptr = (uint64_t *)malloc(sizeof(uint64_t) * num_msr); 195 | if (!msr_mask) 196 | { 197 | err = errno ? errno : -1; 198 | fprintf(error_log, "Unable to allocate msr mask data of size: %zu!: %s\n", sizeof(uint64_t) * num_msr, strerror(errno)); 199 | goto exit; 200 | } 201 | 202 | /* Parse the allowlist */ 203 | const char *allowlist_format = "%zX %zX\n"; 204 | allowlist_ptr = allowlist_buffer; 205 | for (i = 0; i < num_msr; ++i) 206 | { 207 | while (*allowlist_ptr == '#') 208 | { 209 | /* '#' is on first position means line is a comment, treat next line. */ 210 | allowlist_ptr = strchr(allowlist_ptr, '\n'); 211 | if (allowlist_ptr) 212 | { 213 | allowlist_ptr++; /* Move the pointer to the next line */ 214 | } 215 | else 216 | { 217 | err = -1; 218 | fprintf(stderr, "Error: Failed to parse allowlist file named \"%s\"\n", allowlist_path); 219 | goto exit; 220 | } 221 | } 222 | num_scan = sscanf(allowlist_ptr, allowlist_format, msr_offset + i, msr_mask + i); 223 | if (num_scan != 2) 224 | { 225 | err = -1; 226 | fprintf(stderr, "Error: Failed to parse allowlist file named \"%s\"\n", allowlist_path); 227 | goto exit; 228 | } 229 | allowlist_ptr = strchr(allowlist_ptr, '\n'); 230 | allowlist_ptr++; /* Move the pointer to the next line */ 231 | if (!allowlist_ptr) 232 | { 233 | err = -1; 234 | fprintf(stderr, "Error: Failed to parse allowlist file named \"%s\"\n", allowlist_path); 235 | goto exit; 236 | } 237 | } 238 | 239 | exit: 240 | unlink(tmp_path); 241 | if (tmp_fd != -1) 242 | { 243 | close(tmp_fd); 244 | } 245 | if (allowlist_fd != -1) 246 | { 247 | close(allowlist_fd); 248 | } 249 | if (allowlist_buffer) 250 | { 251 | free(allowlist_buffer); 252 | } 253 | return err; 254 | } 255 | 256 | int msr_save(const char *save_path, const char *allowlist_path, const char *msr_path_format, int num_cpu, FILE *output_log, FILE *error_log) 257 | { 258 | int err = 0; 259 | int tmp_err = 0; 260 | int i, j; 261 | int msr_fd = -1; 262 | size_t num_msr = 0; 263 | uint64_t *msr_offset = NULL; 264 | uint64_t *msr_mask = NULL; 265 | uint64_t *save_buffer = NULL; 266 | FILE *save_fid = NULL; 267 | 268 | err = msr_parse_allowlist(allowlist_path, &num_msr, &msr_offset, &msr_mask, error_log); 269 | if (err) 270 | { 271 | goto exit; 272 | } 273 | if (!msr_offset || !msr_mask) 274 | { 275 | err = -1; 276 | goto exit; 277 | } 278 | 279 | /* Allocate save buffer, a 2-D array over msr offset and then CPU 280 | (offset major ordering) */ 281 | save_buffer = (uint64_t *)malloc(num_msr * num_cpu * sizeof(uint64_t)); 282 | if (!save_buffer) 283 | { 284 | err = errno ? errno : -1; 285 | fprintf(error_log, "Unable to allocate msr save state buffer of size: %zu!: %s\n", num_msr * num_cpu * sizeof(uint64_t), strerror(errno)); 286 | goto exit; 287 | } 288 | 289 | /* Open all MSR files. 290 | * Read ALL existing data 291 | * Pass through the allowlist mask. */ 292 | for (i = 0; i < num_cpu; ++i) 293 | { 294 | char msr_file_name[NAME_MAX]; 295 | snprintf(msr_file_name, NAME_MAX, msr_path_format, i); 296 | msr_fd = open(msr_file_name, O_RDWR); 297 | if (msr_fd == -1) 298 | { 299 | err = errno ? errno : -1; 300 | fprintf(error_log, "Could not open MSR file \"%s\"!: %s\n", msr_file_name, strerror(errno)); 301 | goto exit; 302 | } 303 | for (j = 0; j < num_msr; ++j) 304 | { 305 | ssize_t read_count = pread(msr_fd, save_buffer + i * num_msr + j, 306 | sizeof(uint64_t), msr_offset[j]); 307 | if (read_count != sizeof(uint64_t)) 308 | { 309 | fprintf(error_log, "Warning: Failed to read msr value 0x%zX from MSR file \"%s\"!\n", msr_offset[j], msr_file_name); 310 | errno = 0; 311 | if (~(msr_mask[j])) 312 | { 313 | save_buffer[i * num_msr + j] = ~(msr_mask[j]); 314 | } 315 | else 316 | { 317 | save_buffer[i * num_msr + j] = G_COOKIE_BAD_READ; 318 | } 319 | } 320 | else 321 | { 322 | save_buffer[i * num_msr + j] &= msr_mask[j]; 323 | if (~(msr_mask[j]) == 0ULL && 324 | save_buffer[i * num_msr + j] == G_COOKIE_BAD_READ) 325 | { 326 | fprintf(error_log, "Error: Extremely unlikely event, read value from MSR that matches our random 64 bit integer used to mark bad reads.\n"); 327 | err = -1; 328 | goto exit; 329 | } 330 | } 331 | } 332 | tmp_err = close(msr_fd); 333 | msr_fd = -1; 334 | if (tmp_err) 335 | { 336 | err = errno ? errno : -1; 337 | fprintf(error_log, "Could not close MSR file \"%s\"!: %s\n", msr_file_name, strerror(errno)); 338 | goto exit; 339 | } 340 | } 341 | 342 | /* Open output file. */ 343 | save_fid = fopen(save_path, "w"); 344 | if (!save_fid) 345 | { 346 | err = errno ? errno : -1; 347 | fprintf(error_log, "Could not open output file \"%s\"!: %s\n", save_path, strerror(errno)); 348 | goto exit; 349 | } 350 | 351 | size_t num_write = fwrite(save_buffer, sizeof(uint64_t), num_msr * num_cpu, save_fid); 352 | if (num_write != num_msr * num_cpu) 353 | { 354 | err = errno ? errno : -1; 355 | fprintf(error_log, "Could not write all values to output file \"%s\"!: %s\n", save_path, strerror(errno)); 356 | goto exit; 357 | } 358 | 359 | tmp_err = fclose(save_fid); 360 | save_fid = NULL; 361 | if (tmp_err) 362 | { 363 | err = errno ? errno : -1; 364 | fprintf(error_log, "Could not close MSR file \"%s\"!: %s\n", save_path, strerror(errno)); 365 | goto exit; 366 | } 367 | 368 | /* Clean up memory and files */ 369 | exit: 370 | if (save_buffer) 371 | { 372 | free(save_buffer); 373 | } 374 | if (msr_offset) 375 | { 376 | free(msr_offset); 377 | } 378 | if (msr_mask) 379 | { 380 | free(msr_mask); 381 | } 382 | if (save_fid) 383 | { 384 | fclose(save_fid); 385 | } 386 | if (msr_fd != -1) 387 | { 388 | close(msr_fd); 389 | } 390 | return err; 391 | } 392 | 393 | int msr_restore(const char *restore_path, const char *allowlist_path, const char *msr_path_format, int num_cpu, FILE *output_log, FILE *error_log) 394 | { 395 | int err = 0; 396 | int tmp_err = 0; 397 | int i, j; 398 | int msr_fd = -1; 399 | int do_print_header = 1; 400 | size_t num_msr = 0; 401 | uint64_t read_val = 0; 402 | uint64_t masked_val = 0; 403 | uint64_t write_val = 0; 404 | uint64_t *msr_offset = NULL; 405 | uint64_t *msr_mask = NULL; 406 | uint64_t *restore_buffer = NULL; 407 | FILE *restore_fid = NULL; 408 | struct stat restore_stat; 409 | struct stat allowlist_stat; 410 | char err_msg[NAME_MAX]; 411 | 412 | err = msr_parse_allowlist(allowlist_path, &num_msr, &msr_offset, &msr_mask, error_log); 413 | if (err) 414 | { 415 | goto exit; 416 | } 417 | if (!msr_offset || !msr_mask) 418 | { 419 | err = -1; 420 | goto exit; 421 | } 422 | 423 | /* Check that the timestamp of the restore file is after the timestamp 424 | for the allowlist file */ 425 | tmp_err = stat(restore_path, &restore_stat); 426 | if (tmp_err != 0) 427 | { 428 | err = errno ? errno : -1; 429 | fprintf(error_log, "stat() of %s failed!: %s\n", restore_path, strerror(errno)); 430 | goto exit; 431 | } 432 | 433 | tmp_err = stat(allowlist_path, &allowlist_stat); 434 | if (tmp_err != 0) 435 | { 436 | err = errno ? errno : -1; 437 | fprintf(error_log, "stat() of %s failed!: %s\n", allowlist_path, strerror(errno)); 438 | goto exit; 439 | } 440 | 441 | if (restore_stat.st_mtime < allowlist_stat.st_mtime) 442 | { 443 | err = -1; 444 | fprintf(error_log, "Error: allowlist was modified after restore file was written!\n"); 445 | goto exit; 446 | } 447 | 448 | /* Allocate restore buffer, a 2-D array over msr offset and then CPU 449 | (offset major ordering) */ 450 | restore_buffer = (uint64_t *)malloc(num_msr * num_cpu * sizeof(uint64_t)); 451 | if (!restore_buffer) 452 | { 453 | err = errno ? errno : -1; 454 | fprintf(error_log, "Unable to allocate msr restore state buffer of size: %zu!: %s\n", num_msr * num_cpu * sizeof(uint64_t), strerror(errno)); 455 | goto exit; 456 | } 457 | 458 | restore_fid = fopen(restore_path, "r"); 459 | if (!restore_fid) 460 | { 461 | err = errno ? errno : -1; 462 | fprintf(error_log, "Could not open restore file \"%s\"!: %s\n", restore_path, strerror(errno)); 463 | goto exit; 464 | } 465 | 466 | size_t num_read = fread(restore_buffer, sizeof(uint64_t), num_msr * num_cpu, restore_fid); 467 | if (num_read != num_msr * num_cpu || fgetc(restore_fid) != EOF) 468 | { 469 | err = errno ? errno : -1; 470 | fprintf(error_log, "Could not read all values from input file \"%s\"!: %s\n", restore_path, strerror(errno)); 471 | goto exit; 472 | } 473 | 474 | tmp_err = fclose(restore_fid); 475 | restore_fid = NULL; 476 | if (tmp_err) 477 | { 478 | err = errno ? errno : -1; 479 | fprintf(error_log, "Could not close MSR file \"%s\"!: %s\n", restore_path, strerror(errno)); 480 | goto exit; 481 | } 482 | 483 | /* Open all MSR files. 484 | * Read ALL existing data 485 | * Pass through the allowlist mask 486 | * Or in restore values 487 | * Write back to MSR files. */ 488 | for (i = 0; i < num_cpu; ++i) 489 | { 490 | char msr_file_name[NAME_MAX]; 491 | snprintf(msr_file_name, NAME_MAX, msr_path_format, i); 492 | msr_fd = open(msr_file_name, O_RDWR); 493 | if (msr_fd == -1) 494 | { 495 | err = errno ? errno : -1; 496 | fprintf(error_log, "Could not open MSR file \"%s\"!: %s\n", msr_file_name, strerror(errno)); 497 | goto exit; 498 | } 499 | for (j = 0; j < num_msr; ++j) 500 | { 501 | write_val = restore_buffer[i * num_msr + j]; 502 | if (is_good_value(write_val, msr_mask[j])) 503 | { 504 | /* Value was read properly when save file was created */ 505 | ssize_t count = pread(msr_fd, &read_val, sizeof(uint64_t), msr_offset[j]); 506 | masked_val = (read_val & msr_mask[j]); 507 | if (count != sizeof(uint64_t)) 508 | { 509 | fprintf(error_log, "Warning: Failed to read msr value at offset 0x%016zX from MSR file \"%s\"!: %s\n", msr_offset[j], msr_file_name, strerror(errno)); 510 | errno = 0; 511 | } 512 | else if (write_val != masked_val) 513 | { 514 | /* Value has changed, and needs to be restored */ 515 | write_val |= (read_val & ~(msr_mask[j])); 516 | count = pwrite(msr_fd, &write_val, sizeof(uint64_t), msr_offset[j]); 517 | if (count != sizeof(uint64_t)) 518 | { 519 | fprintf(error_log, "Warning: Failed to write msr value at offset 0x%016zX to MSR file \"%s\"!: %s\n", msr_offset[j], msr_file_name, strerror(errno)); 520 | errno = 0; 521 | } 522 | else 523 | { 524 | if (do_print_header) 525 | { 526 | fprintf(output_log, "offset, read, restored\n"); 527 | do_print_header = 0; 528 | } 529 | fprintf(output_log, "0x%016zX, 0x%016zX, 0x%016zX\n", msr_offset[j], read_val, write_val); 530 | } 531 | } 532 | } 533 | } 534 | tmp_err = close(msr_fd); 535 | msr_fd = -1; 536 | if (tmp_err) 537 | { 538 | err = errno ? errno : -1; 539 | fprintf(error_log, "Could not close MSR file \"%s\"!: %s\n", msr_file_name, strerror(errno)); 540 | goto exit; 541 | } 542 | } 543 | 544 | /* Clean up memory and files */ 545 | exit: 546 | if (restore_buffer) 547 | { 548 | free(restore_buffer); 549 | } 550 | if (restore_fid) 551 | { 552 | fclose(restore_fid); 553 | } 554 | if (msr_offset) 555 | { 556 | free(msr_offset); 557 | } 558 | if (msr_mask) 559 | { 560 | free(msr_mask); 561 | } 562 | if (msr_fd != -1) 563 | { 564 | close(msr_fd); 565 | } 566 | return err; 567 | } 568 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NAME 2 | 3 | msr_safe - kernel module implementing access-control lists for model-specific registers 4 | 5 | # SYNOPSIS 6 | 7 | **/dev/cpu/\/msr_safe** 8 | **/dev/cpu/msr_batch** 9 | **/dev/cpu/msr_allowlist** 10 | **/dev/cpu/msr_version** 11 | **msr-save** 12 | 13 | # OVERVIEW 14 | msr_safe provides controlled userspace access to model-specific registers 15 | (MSRs). 16 | It allows system administrators to give 17 | register-level read access and bit-level write access to trusted users in 18 | production environments. This access is useful where kernel 19 | drivers have not caught up with new processor features, or performance 20 | constraints requires batch access across dozens or hundreds of registers. 21 | 22 | # SETUP 23 | Building the kernel module requires linux kernel headers. Best practice 24 | for production environments requires creation of *msr-user* and *msr-admin* 25 | groups. Members of the former can read and write MSRs using either the 26 | per-CPU interface or the batch interface, subject to the restrictions 27 | specified in the allowlist. Members of the latter can also change the 28 | contents of the allowlist. 29 | ``` 30 | git clone https://github.com/LLNL/msr-safe 31 | cd msr-safe 32 | make 33 | sudo insmod ./msr-safe.ko 34 | sudo chmod g+rw /dev/cpu/*/msr_safe /dev/cpu/msr_* 35 | sudo chgrp msr-user /dev/cpu/*/msr_safe /dev/cpu/msr_batch /dev/cpu/msr_safe_version 36 | sudo chgrp msr-admin /dev/cpu/msr_allowlist 37 | ``` 38 | 39 | msr_safe uses dynamically allocated major device numbers. These can conflict 40 | with devices that use hard-coded numbers. To work around this, major device 41 | numbers can be specified during module load. 42 | 43 | ``` 44 | sudo insmod msr-safe.ko \ 45 | [ mdev_msr_safe=<#> ] \ 46 | [ mdev_msr_allowlist=<#> ] \ 47 | [ mdev_msr_batch=<#> ] \ 48 | [ mdev_msr_version=<#> ] 49 | ``` 50 | 51 | Use **rmmod(8)** to unload msr-safe. 52 | 53 | ``` 54 | sudo rmmod msr-safe 55 | ``` 56 | 57 | # DKMS 58 | 59 | Copy or clone the repo into /usr/src as the specific directory `msr-safe-git` 60 | 61 | ```console 62 | $ sudo git clone https://github.com/LLNL/msr-safe /usr/src/msr-safe-git 63 | ``` 64 | 65 | Than add it to DKMS: 66 | 67 | ```console 68 | $ sudo dkms add -m msr-safe -v git 69 | ``` 70 | 71 | Try to build and install it: 72 | 73 | ```console 74 | $ sudo dkms build -m msr-safe -v git 75 | $ sudo dkms install -m msr-safe -v git 76 | ``` 77 | 78 | Remove it with: 79 | 80 | ```console 81 | $ sudo dkms remove -m msr-safe -v git --all 82 | ``` 83 | 84 | # Udev 85 | 86 | Rules to adjust permissions on the device files and restore default allowlist: 87 | 88 | ```console 89 | $ cat </dev/null 90 | # Rules to adjust group and permission for all device files. 91 | SUBSYSTEM=="msr_safe", ACTION=="add", GROUP="msr-user", MODE="0660" 92 | SUBSYSTEM=="msr_batch", ACTION=="add", GROUP="msr-user", MODE="0660" 93 | SUBSYSTEM=="msr_safe_version", ACTION=="add", GROUP="msr-user", MODE="0440" 94 | SUBSYSTEM=="msr_allowlist", ACTION=="add", GROUP="msr-admin", MODE="0660" 95 | 96 | # Restore default allowlist 97 | SUBSYSTEM=="msr_allowlist", ACTION=="add", RUN+="/bin/sh -c 'cat /etc/msr-safe/default_allowlist >/dev/cpu/msr_allowlist'" 98 | EOR 99 | ``` 100 | 101 | # DESCRIPTION 102 | ## /dev/cpu/msr_allowlist 103 | 104 | Contains a list of model specific registers and their 105 | writemasks. Supports **read(2)**, **write(2)** and **open(2)**. Any MSR 106 | access using **msr_safe** or **msr_batch** is checked against this list. An MSR 107 | can be read if its address is present in the list. An MSR can only be 108 | written if its address is present in the list and there is at least one bit 109 | writable as indicated by the write mask. For example, 110 | the following entry marks the MSR at address 0x10 (the time stamp counter) as read-only, 111 | as the write mask is 0. 112 | 113 | ``` 114 | 0x00000010 0x0000000000000000 # "MSR_TIME_STAMP_COUNTER" 115 | ``` 116 | 117 | This entry allows MSR_PERF_CTL (at address 0x199) to be read, but only the 118 | bottom sixteen bits are writeable. 119 | ``` 120 | 0x00000199 0x000000000000ffff # "MSR_PERF_CTL" 121 | ``` 122 | 123 | It is up to the system administrator to create appropriate per-architecture, 124 | per-user allowlists. The "safety" of a particular MRS depends on the totality 125 | of the environment. The msr-safe repo provides sample allowlists that have 126 | been useful in other installations; they may or may not be appropriate for 127 | yours. 128 | 129 | To see the existing allowlist: 130 | ``` 131 | cat /dev/cpu/msr_allowlist 132 | ``` 133 | The output will look something like: 134 | ``` 135 | # MSR Write mask 136 | 0x00000010 0x0000000000000000 137 | 0x00000017 0x0000000000000000 138 | 0x000000C1 0x0000000000000000 139 | ... 140 | ``` 141 | Comments are not preserved. 142 | 143 | To install a new allowlist: 144 | ``` 145 | cat > /dev/cpu/msr_allowlist 146 | ``` 147 | 148 | Writing, appending, or modifying a loaded allowlist discards the existing 149 | allowlist. 150 | 151 | Parsing a 152 | new allowlist is done in two passes. If an error occurs during the first pass 153 | the existing allowlist is undisturbed. If an error occurs during the second 154 | pass the allowlist is reset to be empty. In practice, the most common 155 | second-phase error is the discovery of a duplicate allowlist entry. See 156 | **ERRORS** for details. 157 | 158 | ## /dev/cpu/\/msr_safe 159 | 160 | Per logical-cpu interface for model-specific registers. Supports **llseek(2)**, 161 | **read(2)**, **write(2)**, and **open(2)**. Reads or writes a single MSR at a 162 | time. To access multiple MSRs and/or MSRs across multiple logical CPUs, use 163 | **/dev/cpu/msr_batch**. 164 | 165 | The most common approach is to use **pread(2)** and **pwrite(2)**, as these 166 | combine the seek operation with reading and writing. Alternatively, the 167 | device supports __SEEK_SET__ and __SEEK_CUR__ parameters to **llseek(2)**, but 168 | not __SEEK_END__. Both reads and and writes must be exactly 8 bytes. 169 | 170 | 171 | ## /dev/cpu/msr_batch 172 | 173 | Batch interface for MSR access. Only supports **ioctl(2)**, with the first 174 | parameter being the file descriptor, the second parameter being 175 | __X86_IOC_MSR_BATCH__ (defined in __msr_safe.h__), and the third parameter 176 | being a pointer to a __struct msr_batch_array__. 177 | 178 | ``` 179 | struct msr_batch_array 180 | { 181 | __u32 numops; // In: # of operations in operations array 182 | __u32 version; // In: MSR_SAFE_VERSION_u32 (see msr_version.h) 183 | struct msr_batch_op *ops; // In: Array[numops] of operations 184 | }; 185 | ``` 186 | 187 | The maximum __numops__ is system-dependent, but 30k operations is not 188 | unheard-of. 189 | 190 | Starting in version 2.0.0, the __version__ field will be 191 | compared to the version of the loaded kernel module with a mismatch 192 | resulting in an error. Earlier versions do not check this field. 193 | 194 | Each op is contained in a __struct msr_batch_op__: 195 | 196 | ``` 197 | struct msr_batch_op 198 | { 199 | __u16 cpu; // In: CPU to execute {rd/wr}msr instruction 200 | __u16 isrdmsr; // In: 0=wrmsr, non-zero=rdmsr 201 | __s32 err; // Out: set if error occurred with this operation 202 | __u32 msr; // In: MSR address 203 | __u64 msrdata; // In/Out: Data to write or data that was read 204 | __u64 wmask; // Out: Write mask applied to wrmsr 205 | }; 206 | ``` 207 | 208 | The __cpu__ uses the same numbering found in __/dev/cpu/\__. A zero 209 | value for __isrdmsr__ indicates a write operation, any other value indicates a 210 | read operation. __err__ is populated by the kernel if there is an error on a 211 | particular operation, and will be one of __ENXIO__ (the virtual CPU does not 212 | exist or is offline), __EACCES__ (the requested MSR was not found in the 213 | allowlist), or __EROFS__ (a write operation was attempted on an MSR with a write 214 | mask of 0). 215 | 216 | __msr__ is the address of the model-specific register. __msrdata__ is the 217 | value that will be written to or read from the MSR, respectively. 218 | Finally, the __wmask__ records the writemask for the MSR provided in the 219 | allowlist. 220 | 221 | ## /dev/cpu/msr_safe_version 222 | 223 | Starting with version 1.6, this device contains the loaded version of msr-safe. 224 | 225 | # RETURN VALUES 226 | 227 | On success, calls to **write(2)** and **read(2)** return the number of bytes 228 | written or read, which in the case of **/dev/cpu/\/msr_safe** will be 8 229 | (as only a single register per call may be written to or read from). 230 | **llseek(2)** returns the new file offset. **open(2)** returns the new file 231 | descriptor. **ioctl(2)** returns 0. 232 | 233 | On error, All of the following system calls will return -1 and set __errno__ to 234 | the appropriate value. The errors listed below are specific to msr_safe. The 235 | man pages for the individual system calls describe additional errors that may 236 | occur. 237 | 238 | # ERRORS 239 | 240 | ## /dev/cpu/msr_allowlist 241 | 242 | ### **write(2)** 243 | 244 | __E2BIG__ 245 | **\** exceeds MAX_WLIST_BSIZE (defined as (128 * 1024) + 1) 246 | 247 | __EILSEQ__ 248 | Unexpected EOF. 249 | 250 | __EINVAL__ 251 | Address or writemask caused parsing error. 252 | 253 | __EFAULT__ 254 | Kernel **copy_from_user()** failed. 255 | 256 | __ENOMEM__ 257 | Kernel unable to allocate memory to hold the raw or parsed allowlist. 258 | 259 | __ENOMSG__ 260 | No valid allowlist entries found. 261 | 262 | __ENOTUNIQ__ 263 | Duplicate allowlist entries found. 264 | 265 | __ERANGE__ 266 | Address or writemask is too large for an unsigned long long. 267 | 268 | ### **read(2)** 269 | 270 | __E2BIG__ 271 | The **read(2)** **\** parameter was less than 60 bytes. 272 | 273 | __EFAULT__ 274 | Kernel **copy_from_user()** failed. 275 | 276 | 277 | ### **llseek(2)** 278 | 279 | __EINVAL__ 280 | The **\** parameter was 281 | neither __SEEK_CUR__ nor __SEEK_SET__, e.g., __SEEK_END__. 282 | 283 | ## /dev/cpu/\/msr_safe 284 | 285 | ### **read(2)** 286 | 287 | __EACCESS__ 288 | The MSR requested is not in the allowlist. 289 | 290 | __EBUSY__ 291 | Requested virtual CPU is (temporarily?) locked. 292 | 293 | __EFAULT__ 294 | Kernel **copy_to_user()** failed. 295 | 296 | __EIO__ 297 | A general protection fault occurred. See the description for 298 | __EIO__ errors in the **/dev/cpu/msr_batch** section below. 299 | 300 | __EINVAL__ 301 | Number of bytes requested to read is something other than 8. 302 | 303 | __ENXIO__ 304 | Requested virtual CPU does not exist or is offline. 305 | 306 | 307 | ### **write(2)** 308 | 309 | __EACCESS__ 310 | The MSR requested is not in the allowlist. 311 | 312 | __EBUSY__ 313 | Requested virtual CPU is (temporarily?) locked. 314 | 315 | __EFAULT__ 316 | Kernel **copy_from_user()** failed. 317 | 318 | __EIO__ 319 | A general protection fault occurred. See the description for 320 | __EIO__ errors in the **/dev/cpu/msr_batch** section below. 321 | 322 | __EINVAL__ 323 | Number of bytes requested to read is something other than 8. 324 | 325 | __ENXIO__ 326 | Requested virtual CPU does not exist or is offline. 327 | 328 | ### **open(2)** 329 | 330 | __EIO__ 331 | Model-specific registers not supported on this virtual CPU. 332 | 333 | __ENXIO__ 334 | Requested virtual CPU does not exist or is offline. 335 | 336 | ### /dev/cpu/msr_batch 337 | 338 | ### **ioctl(2)** 339 | 340 | All of the operations in the batch will be executed. Each operation may result 341 | in an __EIO__, __ENXIO__, __EACCES__, or __EROFS__ error, which will be 342 | recorded in the __msr_batch_op__ struct. If any operation caused an error, the 343 | first such error becomes the return value for **ioctl(2)**. 344 | 345 | __E2BIG__ 346 | Kernel unable to allocate memory to hold the array of operations. 347 | 348 | __EACCES__ 349 | An individual operation requested an MSR that is not present in the allowlist. 350 | 351 | __EBADF__ 352 | The __msr_batch__ file was not opened for reading. 353 | 354 | __EFAULT__ 355 | Kernel **copy_from_user()** or **copy_to_user()** failed. 356 | 357 | __EINVAL__ 358 | Number of requested batch operations is <=0. 359 | 360 | __EIO__ 361 | A general protection fault occurred. On Intel processors this 362 | can be caused by a) attempting to access an MSR outside of ring 0, b) 363 | attempting to access a non-existent or reserved MSR address, c) writing 1-bits 364 | to a reserved area of an MSR, d) writing a non-canonical address to MSRs that 365 | take memory addresses, or e) writing to MSR bits that are marked as read-only. 366 | 367 | __ENOMEM__ 368 | Kernel unable to allocate memory to hold the results of __zalloc_cpumask_var()__. 369 | 370 | __ENOTTY__ 371 | Invalid ioctl command. As of this writing the only ioctl command 372 | supported on this device is __X86_IOC_MSR_BATCH__, defined in __msr_safe.h__. 373 | 374 | __ENXIO__ 375 | An individual operation requested a virtual CPU does not exist or is offline. 376 | 377 | __EROFS__ 378 | An individual operation requested a write to a read-only MSR. 379 | 380 | 381 | ### **open(2)** 382 | 383 | There are no msr_safe-specific error conditions. 384 | 385 | # ALLOWLIST CONTRIBUTIONS 386 | 387 | The contribs/ folder contains allowlists shared by 388 | our external collaborators, organized by site-name. 389 | 390 | # msr-save 391 | 392 | The msrsave utility provides a mechanism for saving and restoring MSR values 393 | based on entries in the allowlist. To restore MSR values, the register must 394 | have an appropriate writemask. 395 | 396 | Modification of MSRs that are marked as safe in the allowlist may impact 397 | subsequent users on a shared HPC system. It is important the resource manager 398 | on such a system use the msrsave utility to save and restore MSR values between 399 | allocating compute nodes to users. An example of this has been implemented for 400 | the SLURM resource manager as a SPANK plugin. This plugin can be built with the 401 | "make spank" target and installed with the "make install-spank" target. This 402 | uses the SLURM SPANK infrastructure to make a popen(3) call to the msrsave 403 | command line utility in the job epilogue and prologue. 404 | 405 | The version of msrsave (and msr-safe) can be modified by updating the following 406 | compiler flag: 407 | 408 | -DVERSION=\"MAJOR.MINOR.PATCH\" 409 | 410 | The msrsave version can be queried with: 411 | 412 | msrsave --version 413 | 414 | # Security 415 | 416 | ## Model-specific registers 417 | 418 | The safety of a particular model-specific register depends on the system 419 | environment. The sample allowlists provided were developed for non-classified 420 | high performance computing systems where only a single non-privileged user at a 421 | time can access a given compute node. These lists should be re-evaluated for 422 | use in other environments, particularly multi-user environments. 423 | 424 | ## Filesystems permissions 425 | 426 | msr-safe is designed to support multiple classes of users, each of which would 427 | have their own group and allowlist. **Best practice is to unload and reload the 428 | msr-safe kernel module when changing device ownership or permissions.** If 429 | this is not done, a lower-privileged user can open **/dev/cpu/msr_batch** and 430 | retain the file descriptor until the permissions (and allowlist) are changed 431 | to allow higher-privileged users to run and the allowlist remains readable by 432 | the less-privileged user, the less-privileged user can continue using their 433 | original file descriptor with the higher-privileged allowlist. 434 | 435 | # FAQ 436 | 437 | ## Can I append or modify an allowlist in place? 438 | No. Each **write(2)** call discards the previous allowlist. 439 | 440 | ## What happens if an allowlist is changed during an **ioctl(2)** call? 441 | The kernel records all of the relevant writemasks in the __struct 442 | msr_batch_op__ prior to executing the ops. If the allowlist is changed 443 | during a call, the new allowlist will be applied to subsequent calls. 444 | 445 | ## How many operations can fit into one batch? 446 | Determining the formula to provide an upper bound is almost certainly 447 | more trouble than it's worth, but we have easily gotten 30k entries 448 | in a single batch on production machines. 449 | 450 | ## What happens if a CPU is taken offline or brought back online? 451 | We haven't had a good reason to wire up hotplugging. If the collection 452 | of online CPUs changes, it's best to unload and reload the msr-safe kernel 453 | module. 454 | 455 | ## What happens if a CPU is taken offline and a user still has an open file descriptor for that device? 456 | The kernel checks to see if a CPU is online. Attempts to access MSRs using 457 | that file descriptor should generate and error. 458 | 459 | ## Can the batch API be extended to do other operations such as polling? 460 | It can and it has. If you need this functionality please let us know. 461 | The code is brittle enough that we don't use it in production, but we 462 | are happy to share. 463 | 464 | 465 | 466 | # EXAMPLE CODE 467 | ``` 468 | /* This example assumes the user has the following permissions: 469 | * 470 | * write /dev/cpu/msr_allowlist 471 | * read/write /dev/cpu//msr_safe 472 | * read /dev/cpu/msr_batch 473 | * 474 | * Typically, only the administrator will have write permissions 475 | * on the allowlist. 476 | * 477 | * Production code should have more robust error handling than 478 | * what is shown here. 479 | * 480 | * This example should be able to run successfully on an x86 481 | * processor from the past ten years or so. 482 | * 483 | */ 484 | 485 | 486 | #include // printf(3) 487 | #include // assert(3) 488 | #include // open(2) 489 | #include // write(2), pwrite(2), pread(2) 490 | #include // strlen(3), memset(3) 491 | #include // uint8_t 492 | #include // PRIu8 493 | #include // exit(3) 494 | #include // ioctl(2) 495 | 496 | #include "../msr_safe.h" // batch data structs 497 | 498 | #define MSR_MPERF 0xE7 499 | 500 | char const *const allowlist = "0xE7 0xFFFFFFFFFFFFFFFF\n"; // MPERF 501 | 502 | static uint8_t const nCPUs = 32; 503 | 504 | void set_allowlist() 505 | { 506 | int fd = open("/dev/cpu/msr_allowlist", O_WRONLY); 507 | assert(-1 != fd); 508 | ssize_t nbytes = write(fd, allowlist, strlen(allowlist)); 509 | assert(strlen(allowlist) == nbytes); 510 | close(fd); 511 | } 512 | 513 | void measure_serial_latency() 514 | { 515 | int fd[nCPUs], rc; 516 | char filename[255]; 517 | uint64_t data[nCPUs]; 518 | memset(data, 0, sizeof(uint64_t)*nCPUs); 519 | 520 | // Open each of the msr_safe devices (one per CPU) 521 | for (uint8_t i = 0; i < nCPUs; i++) 522 | { 523 | rc = snprintf(filename, 254, "/dev/cpu/%"PRIu8"/msr_safe", i); 524 | assert(-1 != rc); 525 | fd[i] = open(filename, O_RDWR); 526 | assert(-1 != fd[i]); 527 | } 528 | // Write 0 to each MPERF register 529 | for (uint8_t i = 0; i < nCPUs; i++) 530 | { 531 | rc = pwrite(fd[i], &data[i], sizeof(uint64_t), MSR_MPERF); 532 | assert(8 == rc); 533 | } 534 | 535 | // Read each MPERF register 536 | for (uint8_t i = 0; i < nCPUs; i++) 537 | { 538 | pread(fd[i], &data[i], sizeof(uint64_t), MSR_MPERF); 539 | assert(8 == rc); 540 | } 541 | 542 | // Show results 543 | printf("Serial cycles from first write to last read:" 544 | "%"PRIu64" (on %"PRIu8" CPUs)\n", 545 | data[nCPUs - 1], nCPUs); 546 | } 547 | 548 | void measure_batch_latency() 549 | { 550 | struct msr_batch_array rbatch, wbatch; 551 | struct msr_batch_op r_ops[nCPUs], w_ops[nCPUs]; 552 | int fd, rc; 553 | 554 | fd = open("/dev/cpu/msr_batch", O_RDONLY); 555 | assert(-1 != fd); 556 | 557 | for (uint8_t i = 0; i < nCPUs; i++) 558 | { 559 | r_ops[i].cpu = w_ops[i].cpu = i; 560 | r_ops[i].isrdmsr = 1; 561 | w_ops[i].isrdmsr = 0; 562 | r_ops[i].msr = w_ops[i].msr = MSR_MPERF; 563 | w_ops[i].msrdata = 0; 564 | } 565 | rbatch.numops = wbatch.numops = nCPUs; 566 | rbatch.ops = r_ops; 567 | wbatch.ops = w_ops; 568 | 569 | rc = ioctl(fd, X86_IOC_MSR_BATCH, &wbatch); 570 | assert(-1 != rc); 571 | rc = ioctl(fd, X86_IOC_MSR_BATCH, &rbatch); 572 | assert(-1 != rc); 573 | 574 | printf("Batch cycles from first write to last read:" 575 | "%llu (on %"PRIu8" CPUs)\n", 576 | r_ops[nCPUs - 1].msrdata, nCPUs); 577 | } 578 | 579 | int main() 580 | { 581 | set_allowlist(); 582 | measure_serial_latency(); 583 | measure_batch_latency(); 584 | return 0; 585 | } 586 | ``` 587 | 588 | # Release 589 | 590 | msr-safe is released under the GPL v2.0 license. For more details, please 591 | see the [LICENSE](https://github.com/LLNL/msr-safe/blob/main/LICENSE) and 592 | [NOTICE](https://github.com/LLNL/msr-safe/blob/master/NOTICE) files. 593 | 594 | SPDX-License-Identifier: GPL-2.0-only 595 | 596 | `LLNL-CODE-807679` 597 | 598 | License and LLNL release number have been corrected to match internal records. 599 | -------------------------------------------------------------------------------- /allowlists/al_06_2A: -------------------------------------------------------------------------------- 1 | ## This file contains the model-specific registers available in 06_2A processors 2 | ## based on a close reading of volume 4 of the Intel 64 and IA-32 Architectures 3 | ## Software Development Manual (335592-079US March 2023). 4 | ## Uncommenting allows reading a particular MSR. 5 | ## Modifying the write mask allows writing to those particular bits. 6 | ## Be sure to cat the modified list into /dev/cpu/msr_allowlist. 7 | ## See the README file for more details. 8 | ## 9 | ## MSR # Write Mask # Comment 10 | # 0x00000000 0x0000000000000000 # "IA32_P5_MC_ADDR (Table: 2-20)" 11 | # 0x00000001 0x0000000000000000 # "IA32_P5_MC_TYPE (Table: 2-20)" 12 | # 0x00000006 0x0000000000000000 # "IA32_MONITOR_FILTER_SIZE (Table: 2-20)" 13 | # 0x00000010 0x0000000000000000 # "IA32_TIME_STAMP_COUNTER (Table: 2-20)" 14 | # 0x00000017 0x0000000000000000 # "IA32_PLATFORM_ID (Table: 2-20)" 15 | # 0x0000001B 0x0000000000000000 # "IA32_APIC_BASE (Table: 2-20)" 16 | # 0x00000034 0x0000000000000000 # "MSR_SMI_COUNT (Table: 2-20)" 17 | # 0x0000003A 0x0000000000000000 # "IA32_FEATURE_CONTROL (Table: 2-20)" 18 | # 0x00000079 0x0000000000000000 # "IA32_BIOS_UPDT_TRIG (Table: 2-20)" 19 | # 0x0000008B 0x0000000000000000 # "IA32_BIOS_SIGN_ID (Table: 2-20)" 20 | # 0x000000C1 0x0000000000000000 # "IA32_PMC0 (Table: 2-20)" 21 | # 0x000000C2 0x0000000000000000 # "IA32_PMC1 (Table: 2-20)" 22 | # 0x000000C3 0x0000000000000000 # "IA32_PMC2 (Table: 2-20)" 23 | # 0x000000C4 0x0000000000000000 # "IA32_PMC3 (Table: 2-20)" 24 | # 0x000000C5 0x0000000000000000 # "IA32_PMC4 (Table: 2-20)" 25 | # 0x000000C6 0x0000000000000000 # "IA32_PMC5 (Table: 2-20)" 26 | # 0x000000C7 0x0000000000000000 # "IA32_PMC6 (Table: 2-20)" 27 | # 0x000000C8 0x0000000000000000 # "IA32_PMC7 (Table: 2-20)" 28 | # 0x000000CE 0x0000000000000000 # "MSR_PLATFORM_INFO (Table: 2-20)" 29 | # 0x000000E2 0x0000000000000000 # "MSR_PKG_CST_CONFIG_CONTROL (Table: 2-20)" 30 | # 0x000000E4 0x0000000000000000 # "MSR_PMG_IO_CAPTURE_BASE (Table: 2-20)" 31 | # 0x000000E7 0x0000000000000000 # "IA32_MPERF (Table: 2-20)" 32 | # 0x000000E8 0x0000000000000000 # "IA32_APERF (Table: 2-20)" 33 | # 0x000000FE 0x0000000000000000 # "IA32_MTRRCAP (Table: 2-20)" 34 | # 0x0000013C 0x0000000000000000 # "MSR_FEATURE_CONFIG (Table: 2-20)" 35 | # 0x00000174 0x0000000000000000 # "IA32_SYSENTER_CS (Table: 2-20)" 36 | # 0x00000175 0x0000000000000000 # "IA32_SYSENTER_ESP (Table: 2-20)" 37 | # 0x00000176 0x0000000000000000 # "IA32_SYSENTER_EIP (Table: 2-20)" 38 | # 0x00000179 0x0000000000000000 # "IA32_MCG_CAP (Table: 2-20)" 39 | # 0x0000017A 0x0000000000000000 # "IA32_MCG_STATUS (Table: 2-20)" 40 | # 0x00000186 0x0000000000000000 # "IA32_PERFEVTSEL0 (Table: 2-20)" 41 | # 0x00000187 0x0000000000000000 # "IA32_PERFEVTSEL1 (Table: 2-20)" 42 | # 0x00000188 0x0000000000000000 # "IA32_PERFEVTSEL2 (Table: 2-20)" 43 | # 0x00000189 0x0000000000000000 # "IA32_PERFEVTSEL3 (Table: 2-20)" 44 | # 0x0000018A 0x0000000000000000 # "IA32_PERFEVTSEL4 (Table: 2-20)" 45 | # 0x0000018B 0x0000000000000000 # "IA32_PERFEVTSEL5 (Table: 2-20)" 46 | # 0x0000018C 0x0000000000000000 # "IA32_PERFEVTSEL6 (Table: 2-20)" 47 | # 0x0000018D 0x0000000000000000 # "IA32_PERFEVTSEL7 (Table: 2-20)" 48 | # 0x00000198 0x0000000000000000 # "MSR_PERF_STATUS (Table: 2-20)" 49 | # 0x00000199 0x0000000000000000 # "IA32_PERF_CTL (Table: 2-20)" 50 | # 0x0000019A 0x0000000000000000 # "IA32_CLOCK_MODULATION (Table: 2-20)" 51 | # 0x0000019B 0x0000000000000000 # "IA32_THERM_INTERRUPT (Table: 2-20)" 52 | # 0x0000019C 0x0000000000000000 # "IA32_THERM_STATUS (Table: 2-20)" 53 | # 0x000001A0 0x0000000000000000 # "IA32_MISC_ENABLE (Table: 2-20)" 54 | # 0x000001A2 0x0000000000000000 # "MSR_TEMPERATURE_TARGET (Table: 2-20)" 55 | # 0x000001A4 0x0000000000000000 # "MSR_MISC_FEATURE_CONTROL (Table: 2-20)" 56 | # 0x000001A6 0x0000000000000000 # "MSR_OFFCORE_RSP_0 (Table: 2-20)" 57 | # 0x000001A7 0x0000000000000000 # "MSR_OFFCORE_RSP_1 (Table: 2-20)" 58 | # 0x000001AA 0x0000000000000000 # "MSR_MISC_PWR_MGMT (Table: 2-20)" 59 | # 0x000001AD 0x0000000000000000 # "MSR_TURBO_RATIO_LIMIT (Table: 2-21)" 60 | # 0x000001B0 0x0000000000000000 # "IA32_ENERGY_PERF_BIAS (Table: 2-20)" 61 | # 0x000001B1 0x0000000000000000 # "IA32_PACKAGE_THERM_STATUS (Table: 2-20)" 62 | # 0x000001B2 0x0000000000000000 # "IA32_PACKAGE_THERM_INTERRUPT (Table: 2-20)" 63 | # 0x000001C8 0x0000000000000000 # "MSR_LBR_SELECT (Table: 2-20)" 64 | # 0x000001C9 0x0000000000000000 # "MSR_LASTBRANCH_TOS (Table: 2-20)" 65 | # 0x000001D9 0x0000000000000000 # "IA32_DEBUGCTL (Table: 2-20)" 66 | # 0x000001DD 0x0000000000000000 # "MSR_LER_FROM_LIP (Table: 2-20)" 67 | # 0x000001DE 0x0000000000000000 # "MSR_LER_TO_LIP (Table: 2-20)" 68 | # 0x000001F2 0x0000000000000000 # "IA32_SMRR_PHYSBASE (Table: 2-20)" 69 | # 0x000001F3 0x0000000000000000 # "IA32_SMRR_PHYSMASK (Table: 2-20)" 70 | # 0x000001FC 0x0000000000000000 # "MSR_POWER_CTL (Table: 2-20)" 71 | # 0x00000200 0x0000000000000000 # "IA32_MTRR_PHYSBASE0 (Table: 2-20)" 72 | # 0x00000201 0x0000000000000000 # "IA32_MTRR_PHYSMASK0 (Table: 2-20)" 73 | # 0x00000202 0x0000000000000000 # "IA32_MTRR_PHYSBASE1 (Table: 2-20)" 74 | # 0x00000203 0x0000000000000000 # "IA32_MTRR_PHYSMASK1 (Table: 2-20)" 75 | # 0x00000204 0x0000000000000000 # "IA32_MTRR_PHYSBASE2 (Table: 2-20)" 76 | # 0x00000205 0x0000000000000000 # "IA32_MTRR_PHYSMASK2 (Table: 2-20)" 77 | # 0x00000206 0x0000000000000000 # "IA32_MTRR_PHYSBASE3 (Table: 2-20)" 78 | # 0x00000207 0x0000000000000000 # "IA32_MTRR_PHYSMASK3 (Table: 2-20)" 79 | # 0x00000208 0x0000000000000000 # "IA32_MTRR_PHYSBASE4 (Table: 2-20)" 80 | # 0x00000209 0x0000000000000000 # "IA32_MTRR_PHYSMASK4 (Table: 2-20)" 81 | # 0x0000020A 0x0000000000000000 # "IA32_MTRR_PHYSBASE5 (Table: 2-20)" 82 | # 0x0000020B 0x0000000000000000 # "IA32_MTRR_PHYSMASK5 (Table: 2-20)" 83 | # 0x0000020C 0x0000000000000000 # "IA32_MTRR_PHYSBASE6 (Table: 2-20)" 84 | # 0x0000020D 0x0000000000000000 # "IA32_MTRR_PHYSMASK6 (Table: 2-20)" 85 | # 0x0000020E 0x0000000000000000 # "IA32_MTRR_PHYSBASE7 (Table: 2-20)" 86 | # 0x0000020F 0x0000000000000000 # "IA32_MTRR_PHYSMASK7 (Table: 2-20)" 87 | # 0x00000210 0x0000000000000000 # "IA32_MTRR_PHYSBASE8 (Table: 2-20)" 88 | # 0x00000211 0x0000000000000000 # "IA32_MTRR_PHYSMASK8 (Table: 2-20)" 89 | # 0x00000212 0x0000000000000000 # "IA32_MTRR_PHYSBASE9 (Table: 2-20)" 90 | # 0x00000213 0x0000000000000000 # "IA32_MTRR_PHYSMASK9 (Table: 2-20)" 91 | # 0x00000250 0x0000000000000000 # "IA32_MTRR_FIX64K_00000 (Table: 2-20)" 92 | # 0x00000258 0x0000000000000000 # "IA32_MTRR_FIX16K_80000 (Table: 2-20)" 93 | # 0x00000259 0x0000000000000000 # "IA32_MTRR_FIX16K_A0000 (Table: 2-20)" 94 | # 0x00000268 0x0000000000000000 # "IA32_MTRR_FIX4K_C0000 (Table: 2-20)" 95 | # 0x00000269 0x0000000000000000 # "IA32_MTRR_FIX4K_C8000 (Table: 2-20)" 96 | # 0x0000026A 0x0000000000000000 # "IA32_MTRR_FIX4K_D0000 (Table: 2-20)" 97 | # 0x0000026B 0x0000000000000000 # "IA32_MTRR_FIX4K_D8000 (Table: 2-20)" 98 | # 0x0000026C 0x0000000000000000 # "IA32_MTRR_FIX4K_E0000 (Table: 2-20)" 99 | # 0x0000026D 0x0000000000000000 # "IA32_MTRR_FIX4K_E8000 (Table: 2-20)" 100 | # 0x0000026E 0x0000000000000000 # "IA32_MTRR_FIX4K_F0000 (Table: 2-20)" 101 | # 0x0000026F 0x0000000000000000 # "IA32_MTRR_FIX4K_F8000 (Table: 2-20)" 102 | # 0x00000277 0x0000000000000000 # "IA32_PAT (Table: 2-20)" 103 | # 0x00000280 0x0000000000000000 # "IA32_MC0_CTL2 (Table: 2-20)" 104 | # 0x00000281 0x0000000000000000 # "IA32_MC1_CTL2 (Table: 2-20)" 105 | # 0x00000282 0x0000000000000000 # "IA32_MC2_CTL2 (Table: 2-20)" 106 | # 0x00000283 0x0000000000000000 # "IA32_MC3_CTL2 (Table: 2-20)" 107 | # 0x00000284 0x0000000000000000 # "IA32_MC4_CTL2 (Table: 2-20)" 108 | # 0x000002FF 0x0000000000000000 # "IA32_MTRR_DEF_TYPE (Table: 2-20)" 109 | # 0x00000309 0x0000000000000000 # "IA32_FIXED_CTR0 (Table: 2-20)" 110 | # 0x0000030A 0x0000000000000000 # "IA32_FIXED_CTR1 (Table: 2-20)" 111 | # 0x0000030B 0x0000000000000000 # "IA32_FIXED_CTR2 (Table: 2-20)" 112 | # 0x00000345 0x0000000000000000 # "IA32_PERF_CAPABILITIES (Table: 2-20)" 113 | # 0x0000038D 0x0000000000000000 # "IA32_FIXED_CTR_CTRL (Table: 2-20)" 114 | # 0x0000038E 0x0000000000000000 # "IA32_PERF_GLOBAL_STATUS (Table: 2-20)" 115 | # 0x0000038F 0x0000000000000000 # "IA32_PERF_GLOBAL_CTRL (Table: 2-20)" 116 | # 0x00000390 0x0000000000000000 # "IA32_PERF_GLOBAL_OVF_CTRL (Table: 2-20)" 117 | # 0x00000391 0x0000000000000000 # "MSR_UNC_PERF_GLOBAL_CTRL (Table: 2-22)" 118 | # 0x00000392 0x0000000000000000 # "MSR_UNC_PERF_GLOBAL_STATUS (Table: 2-22)" 119 | # 0x00000394 0x0000000000000000 # "MSR_UNC_PERF_FIXED_CTRL (Table: 2-22)" 120 | # 0x00000395 0x0000000000000000 # "MSR_UNC_PERF_FIXED_CTR (Table: 2-22)" 121 | # 0x00000396 0x0000000000000000 # "MSR_UNC_CBO_CONFIG (Table: 2-22)" 122 | # 0x000003B0 0x0000000000000000 # "MSR_UNC_ARB_PERFCTR0 (Table: 2-22)" 123 | # 0x000003B1 0x0000000000000000 # "MSR_UNC_ARB_PERFCTR1 (Table: 2-22)" 124 | # 0x000003B2 0x0000000000000000 # "MSR_UNC_ARB_PERFEVTSEL0 (Table: 2-22)" 125 | # 0x000003B3 0x0000000000000000 # "MSR_UNC_ARB_PERFEVTSEL1 (Table: 2-22)" 126 | # 0x000003F1 0x0000000000000000 # "IA32_PEBS_ENABLE (Table: 2-20)" 127 | # 0x000003F6 0x0000000000000000 # "MSR_PEBS_LD_LAT (Table: 2-20)" 128 | # 0x000003F8 0x0000000000000000 # "MSR_PKG_C3_RESIDENCY (Table: 2-20)" 129 | # 0x000003F9 0x0000000000000000 # "MSR_PKG_C6_RESIDENCY (Table: 2-20)" 130 | # 0x000003FA 0x0000000000000000 # "MSR_PKG_C7_RESIDENCY (Table: 2-20)" 131 | # 0x000003FC 0x0000000000000000 # "MSR_CORE_C3_RESIDENCY (Table: 2-20)" 132 | # 0x000003FD 0x0000000000000000 # "MSR_CORE_C6_RESIDENCY (Table: 2-20)" 133 | # 0x000003FE 0x0000000000000000 # "MSR_CORE_C7_RESIDENCY (Table: 2-20)" 134 | # 0x00000400 0x0000000000000000 # "IA32_MC0_CTL (Table: 2-20)" 135 | # 0x00000401 0x0000000000000000 # "IA32_MC0_STATUS (Table: 2-20)" 136 | # 0x00000402 0x0000000000000000 # "IA32_MC0_ADDR (Table: 2-20)" 137 | # 0x00000403 0x0000000000000000 # "IA32_MC0_MISC (Table: 2-20)" 138 | # 0x00000404 0x0000000000000000 # "IA32_MC1_CTL (Table: 2-20)" 139 | # 0x00000405 0x0000000000000000 # "IA32_MC1_STATUS (Table: 2-20)" 140 | # 0x00000406 0x0000000000000000 # "IA32_MC1_ADDR (Table: 2-20)" 141 | # 0x00000407 0x0000000000000000 # "IA32_MC1_MISC (Table: 2-20)" 142 | # 0x00000408 0x0000000000000000 # "IA32_MC2_CTL (Table: 2-20)" 143 | # 0x00000409 0x0000000000000000 # "IA32_MC2_STATUS (Table: 2-20)" 144 | # 0x0000040A 0x0000000000000000 # "IA32_MC2_ADDR (Table: 2-20)" 145 | # 0x0000040B 0x0000000000000000 # "IA32_MC2_MISC (Table: 2-20)" 146 | # 0x0000040C 0x0000000000000000 # "IA32_MC3_CTL (Table: 2-20)" 147 | # 0x0000040D 0x0000000000000000 # "IA32_MC3_STATUS (Table: 2-20)" 148 | # 0x0000040E 0x0000000000000000 # "IA32_MC3_ADDR (Table: 2-20)" 149 | # 0x0000040F 0x0000000000000000 # "IA32_MC3_MISC (Table: 2-20)" 150 | # 0x00000410 0x0000000000000000 # "IA32_MC4_CTL (Table: 2-20)" 151 | # 0x00000411 0x0000000000000000 # "IA32_MC4_STATUS (Table: 2-20)" 152 | # 0x00000480 0x0000000000000000 # "IA32_VMX_BASIC (Table: 2-20)" 153 | # 0x00000481 0x0000000000000000 # "IA32_VMX_PINBASED_CTLS (Table: 2-20)" 154 | # 0x00000482 0x0000000000000000 # "IA32_VMX_PROCBASED_CTLS (Table: 2-20)" 155 | # 0x00000483 0x0000000000000000 # "IA32_VMX_EXIT_CTLS (Table: 2-20)" 156 | # 0x00000484 0x0000000000000000 # "IA32_VMX_ENTRY_CTLS (Table: 2-20)" 157 | # 0x00000485 0x0000000000000000 # "IA32_VMX_MISC (Table: 2-20)" 158 | # 0x00000486 0x0000000000000000 # "IA32_VMX_CR0_FIXED0 (Table: 2-20)" 159 | # 0x00000487 0x0000000000000000 # "IA32_VMX_CR0_FIXED1 (Table: 2-20)" 160 | # 0x00000488 0x0000000000000000 # "IA32_VMX_CR4_FIXED0 (Table: 2-20)" 161 | # 0x00000489 0x0000000000000000 # "IA32_VMX_CR4_FIXED1 (Table: 2-20)" 162 | # 0x0000048A 0x0000000000000000 # "IA32_VMX_VMCS_ENUM (Table: 2-20)" 163 | # 0x0000048B 0x0000000000000000 # "IA32_VMX_PROCBASED_CTLS2 (Table: 2-20)" 164 | # 0x0000048C 0x0000000000000000 # "IA32_VMX_EPT_VPID_ENUM (Table: 2-20)" 165 | # 0x0000048D 0x0000000000000000 # "IA32_VMX_TRUE_PINBASED_CTLS (Table: 2-20)" 166 | # 0x0000048E 0x0000000000000000 # "IA32_VMX_TRUE_PROCBASED_CTLS (Table: 2-20)" 167 | # 0x0000048F 0x0000000000000000 # "IA32_VMX_TRUE_EXIT_CTLS (Table: 2-20)" 168 | # 0x00000490 0x0000000000000000 # "IA32_VMX_TRUE_ENTRY_CTLS (Table: 2-20)" 169 | # 0x000004C1 0x0000000000000000 # "IA32_A_PMC0 (Table: 2-20)" 170 | # 0x000004C2 0x0000000000000000 # "IA32_A_PMC1 (Table: 2-20)" 171 | # 0x000004C3 0x0000000000000000 # "IA32_A_PMC2 (Table: 2-20)" 172 | # 0x000004C4 0x0000000000000000 # "IA32_A_PMC3 (Table: 2-20)" 173 | # 0x000004C5 0x0000000000000000 # "IA32_A_PMC4 (Table: 2-20)" 174 | # 0x000004C6 0x0000000000000000 # "IA32_A_PMC5 (Table: 2-20)" 175 | # 0x000004C7 0x0000000000000000 # "IA32_A_PMC6 (Table: 2-20)" 176 | # 0x000004C8 0x0000000000000000 # "IA32_A_PMC7 (Table: 2-20)" 177 | # 0x00000600 0x0000000000000000 # "IA32_DS_AREA (Table: 2-20)" 178 | # 0x00000606 0x0000000000000000 # "MSR_RAPL_POWER_UNIT (Table: 2-20)" 179 | # 0x0000060A 0x0000000000000000 # "MSR_PKGC3_IRTL (Table: 2-20)" 180 | # 0x0000060B 0x0000000000000000 # "MSR_PKGC6_IRTL (Table: 2-20)" 181 | # 0x0000060C 0x0000000000000000 # "MSR_PKGC7_IRTL (Table: 2-21)" 182 | # 0x0000060D 0x0000000000000000 # "MSR_PKG_C2_RESIDENCY (Table: 2-20)" 183 | # 0x00000610 0x0000000000000000 # "MSR_PKG_POWER_LIMIT (Table: 2-20)" 184 | # 0x00000611 0x0000000000000000 # "MSR_PKG_ENERGY_STATUS (Table: 2-20)" 185 | # 0x00000614 0x0000000000000000 # "MSR_PKG_POWER_INFO (Table: 2-20)" 186 | # 0x00000638 0x0000000000000000 # "MSR_PP0_POWER_LIMIT (Table: 2-20)" 187 | # 0x00000639 0x0000000000000000 # "MSR_PP0_ENERGY_STATUS (Table: 2-21)" 188 | # 0x0000063A 0x0000000000000000 # "MSR_PP0_POLICY (Table: 2-21)" 189 | # 0x00000640 0x0000000000000000 # "MSR_PP1_POWER_LIMIT (Table: 2-21)" 190 | # 0x00000641 0x0000000000000000 # "MSR_PP1_ENERGY_STATUS (Table: 2-21)" 191 | # 0x00000642 0x0000000000000000 # "MSR_PP1_POLICY (Table: 2-21)" 192 | # 0x00000680 0x0000000000000000 # "MSR_LASTBRANCH_0_FROM_IP (Table: 2-20)" 193 | # 0x00000681 0x0000000000000000 # "MSR_LASTBRANCH_1_FROM_IP (Table: 2-20)" 194 | # 0x00000682 0x0000000000000000 # "MSR_LASTBRANCH_2_FROM_IP (Table: 2-20)" 195 | # 0x00000683 0x0000000000000000 # "MSR_LASTBRANCH_3_FROM_IP (Table: 2-20)" 196 | # 0x00000684 0x0000000000000000 # "MSR_LASTBRANCH_4_FROM_IP (Table: 2-20)" 197 | # 0x00000685 0x0000000000000000 # "MSR_LASTBRANCH_5_FROM_IP (Table: 2-20)" 198 | # 0x00000686 0x0000000000000000 # "MSR_LASTBRANCH_6_FROM_IP (Table: 2-20)" 199 | # 0x00000687 0x0000000000000000 # "MSR_LASTBRANCH_7_FROM_IP (Table: 2-20)" 200 | # 0x00000688 0x0000000000000000 # "MSR_LASTBRANCH_8_FROM_IP (Table: 2-20)" 201 | # 0x00000689 0x0000000000000000 # "MSR_LASTBRANCH_9_FROM_IP (Table: 2-20)" 202 | # 0x0000068A 0x0000000000000000 # "MSR_LASTBRANCH_10_FROM_IP (Table: 2-20)" 203 | # 0x0000068B 0x0000000000000000 # "MSR_LASTBRANCH_11_FROM_IP (Table: 2-20)" 204 | # 0x0000068C 0x0000000000000000 # "MSR_LASTBRANCH_12_FROM_IP (Table: 2-20)" 205 | # 0x0000068D 0x0000000000000000 # "MSR_LASTBRANCH_13_FROM_IP (Table: 2-20)" 206 | # 0x0000068E 0x0000000000000000 # "MSR_LASTBRANCH_14_FROM_IP (Table: 2-20)" 207 | # 0x0000068F 0x0000000000000000 # "MSR_LASTBRANCH_15_FROM_IP (Table: 2-20)" 208 | # 0x000006C0 0x0000000000000000 # "MSR_LASTBRANCH_0_TO_IP (Table: 2-20)" 209 | # 0x000006C1 0x0000000000000000 # "MSR_LASTBRANCH_1_TO_IP (Table: 2-20)" 210 | # 0x000006C2 0x0000000000000000 # "MSR_LASTBRANCH_2_TO_IP (Table: 2-20)" 211 | # 0x000006C3 0x0000000000000000 # "MSR_LASTBRANCH_3_TO_IP (Table: 2-20)" 212 | # 0x000006C4 0x0000000000000000 # "MSR_LASTBRANCH_4_TO_IP (Table: 2-20)" 213 | # 0x000006C5 0x0000000000000000 # "MSR_LASTBRANCH_5_TO_IP (Table: 2-20)" 214 | # 0x000006C6 0x0000000000000000 # "MSR_LASTBRANCH_6_TO_IP (Table: 2-20)" 215 | # 0x000006C7 0x0000000000000000 # "MSR_LASTBRANCH_7_TO_IP (Table: 2-20)" 216 | # 0x000006C8 0x0000000000000000 # "MSR_LASTBRANCH_8_TO_IP (Table: 2-20)" 217 | # 0x000006C9 0x0000000000000000 # "MSR_LASTBRANCH_9_TO_IP (Table: 2-20)" 218 | # 0x000006CA 0x0000000000000000 # "MSR_LASTBRANCH_10_TO_IP (Table: 2-20)" 219 | # 0x000006CB 0x0000000000000000 # "MSR_LASTBRANCH_11_TO_IP (Table: 2-20)" 220 | # 0x000006CC 0x0000000000000000 # "MSR_LASTBRANCH_12_TO_IP (Table: 2-20)" 221 | # 0x000006CD 0x0000000000000000 # "MSR_LASTBRANCH_13_TO_IP (Table: 2-20)" 222 | # 0x000006CE 0x0000000000000000 # "MSR_LASTBRANCH_14_TO_IP (Table: 2-20)" 223 | # 0x000006CF 0x0000000000000000 # "MSR_LASTBRANCH_15_TO_IP (Table: 2-20)" 224 | # 0x000006E0 0x0000000000000000 # "IA32_TSC_DEADLINE (Table: 2-20)" 225 | # 0x00000700 0x0000000000000000 # "MSR_UNC_CBO_0_PERFEVTSEL0 (Table: 2-22)" 226 | # 0x00000701 0x0000000000000000 # "MSR_UNC_CBO_0_PERFEVTSEL1 (Table: 2-22)" 227 | # 0x00000702 0x0000000000000000 # "MSR_UNC_CBO_0_PERFEVTSEL2 (Table: 2-22)" 228 | # 0x00000703 0x0000000000000000 # "MSR_UNC_CBO_0_PERFEVTSEL3 (Table: 2-22)" 229 | # 0x00000705 0x0000000000000000 # "MSR_UNC_CBO_0_UNIT_STATUS (Table: 2-22)" 230 | # 0x00000706 0x0000000000000000 # "MSR_UNC_CBO_0_PERFCTR0 (Table: 2-22)" 231 | # 0x00000707 0x0000000000000000 # "MSR_UNC_CBO_0_PERFCTR1 (Table: 2-22)" 232 | # 0x00000708 0x0000000000000000 # "MSR_UNC_CBO_0_PERFCTR2 (Table: 2-22)" 233 | # 0x00000709 0x0000000000000000 # "MSR_UNC_CBO_0_PERFCTR3 (Table: 2-22)" 234 | # 0x00000710 0x0000000000000000 # "MSR_UNC_CBO_1_PERFEVTSEL0 (Table: 2-22)" 235 | # 0x00000711 0x0000000000000000 # "MSR_UNC_CBO_1_PERFEVTSEL1 (Table: 2-22)" 236 | # 0x00000712 0x0000000000000000 # "MSR_UNC_CBO_1_PERFEVTSEL2 (Table: 2-22)" 237 | # 0x00000713 0x0000000000000000 # "MSR_UNC_CBO_1_PERFEVTSEL3 (Table: 2-22)" 238 | # 0x00000715 0x0000000000000000 # "MSR_UNC_CBO_1_UNIT_STATUS (Table: 2-22)" 239 | # 0x00000716 0x0000000000000000 # "MSR_UNC_CBO_1_PERFCTR0 (Table: 2-22)" 240 | # 0x00000717 0x0000000000000000 # "MSR_UNC_CBO_1_PERFCTR1 (Table: 2-22)" 241 | # 0x00000718 0x0000000000000000 # "MSR_UNC_CBO_1_PERFCTR2 (Table: 2-22)" 242 | # 0x00000719 0x0000000000000000 # "MSR_UNC_CBO_1_PERFCTR3 (Table: 2-22)" 243 | # 0x00000720 0x0000000000000000 # "MSR_UNC_CBO_2_PERFEVTSEL0 (Table: 2-22)" 244 | # 0x00000721 0x0000000000000000 # "MSR_UNC_CBO_2_PERFEVTSEL1 (Table: 2-22)" 245 | # 0x00000722 0x0000000000000000 # "MSR_UNC_CBO_2_PERFEVTSEL2 (Table: 2-22)" 246 | # 0x00000723 0x0000000000000000 # "MSR_UNC_CBO_2_PERFEVTSEL3 (Table: 2-22)" 247 | # 0x00000725 0x0000000000000000 # "MSR_UNC_CBO_2_UNIT_STATUS (Table: 2-22)" 248 | # 0x00000726 0x0000000000000000 # "MSR_UNC_CBO_2_PERFCTR0 (Table: 2-22)" 249 | # 0x00000727 0x0000000000000000 # "MSR_UNC_CBO_2_PERFCTR1 (Table: 2-22)" 250 | # 0x00000728 0x0000000000000000 # "MSR_UNC_CBO_3_PERFCTR2 (Table: 2-22)" 251 | # 0x00000729 0x0000000000000000 # "MSR_UNC_CBO_3_PERFCTR3 (Table: 2-22)" 252 | # 0x00000730 0x0000000000000000 # "MSR_UNC_CBO_3_PERFEVTSEL0 (Table: 2-22)" 253 | # 0x00000731 0x0000000000000000 # "MSR_UNC_CBO_3_PERFEVTSEL1 (Table: 2-22)" 254 | # 0x00000732 0x0000000000000000 # "MSR_UNC_CBO_3_PERFEVTSEL2 (Table: 2-22)" 255 | # 0x00000733 0x0000000000000000 # "MSR_UNC_CBO_3_PERFEVTSEL3 (Table: 2-22)" 256 | # 0x00000735 0x0000000000000000 # "MSR_UNC_CBO_3_UNIT_STATUS (Table: 2-22)" 257 | # 0x00000736 0x0000000000000000 # "MSR_UNC_CBO_3_PERFCTR0 (Table: 2-22)" 258 | # 0x00000737 0x0000000000000000 # "MSR_UNC_CBO_3_PERFCTR1 (Table: 2-22)" 259 | # 0x00000738 0x0000000000000000 # "MSR_UNC_CBO_3_PERFCTR2 (Table: 2-22)" 260 | # 0x00000739 0x0000000000000000 # "MSR_UNC_CBO_3_PERFCTR3 (Table: 2-22)" 261 | # 0x00000740 0x0000000000000000 # "MSR_UNC_CBO_4_PERFEVTSEL0 (Table: 2-22)" 262 | # 0x00000741 0x0000000000000000 # "MSR_UNC_CBO_4_PERFEVTSEL1 (Table: 2-22)" 263 | # 0x00000742 0x0000000000000000 # "MSR_UNC_CBO_4_PERFEVTSEL2 (Table: 2-22)" 264 | # 0x00000743 0x0000000000000000 # "MSR_UNC_CBO_4_PERFEVTSEL3 (Table: 2-22)" 265 | # 0x00000745 0x0000000000000000 # "MSR_UNC_CBO_4_UNIT_STATUS (Table: 2-22)" 266 | # 0x00000746 0x0000000000000000 # "MSR_UNC_CBO_4_PERFCTR0 (Table: 2-22)" 267 | # 0x00000747 0x0000000000000000 # "MSR_UNC_CBO_4_PERFCTR1 (Table: 2-22)" 268 | # 0x00000748 0x0000000000000000 # "MSR_UNC_CBO_4_PERFCTR2 (Table: 2-22)" 269 | # 0x00000749 0x0000000000000000 # "MSR_UNC_CBO_4_PERFCTR3 (Table: 2-22)" 270 | # 0x00000802 0x0000000000000000 # "IA32_X2APIC_APICID (Table: 2-20)" 271 | # 0x00000803 0x0000000000000000 # "IA32_X2APIC_VERSION (Table: 2-20)" 272 | # 0x00000808 0x0000000000000000 # "IA32_X2APIC_TPR (Table: 2-20)" 273 | # 0x0000080A 0x0000000000000000 # "IA32_X2APIC_PPR (Table: 2-20)" 274 | # 0x0000080B 0x0000000000000000 # "IA32_X2APIC_EOI (Table: 2-20)" 275 | # 0x0000080D 0x0000000000000000 # "IA32_X2APIC_LDR (Table: 2-20)" 276 | # 0x0000080F 0x0000000000000000 # "IA32_X2APIC_SIVR (Table: 2-20)" 277 | # 0x00000810 0x0000000000000000 # "IA32_X2APIC_ISR0 (Table: 2-20)" 278 | # 0x00000811 0x0000000000000000 # "IA32_X2APIC_ISR1 (Table: 2-20)" 279 | # 0x00000812 0x0000000000000000 # "IA32_X2APIC_ISR2 (Table: 2-20)" 280 | # 0x00000813 0x0000000000000000 # "IA32_X2APIC_ISR3 (Table: 2-20)" 281 | # 0x00000814 0x0000000000000000 # "IA32_X2APIC_ISR4 (Table: 2-20)" 282 | # 0x00000815 0x0000000000000000 # "IA32_X2APIC_ISR5 (Table: 2-20)" 283 | # 0x00000816 0x0000000000000000 # "IA32_X2APIC_ISR6 (Table: 2-20)" 284 | # 0x00000817 0x0000000000000000 # "IA32_X2APIC_ISR7 (Table: 2-20)" 285 | # 0x00000818 0x0000000000000000 # "IA32_X2APIC_TMR0 (Table: 2-20)" 286 | # 0x00000819 0x0000000000000000 # "IA32_X2APIC_TMR1 (Table: 2-20)" 287 | # 0x0000081A 0x0000000000000000 # "IA32_X2APIC_TMR2 (Table: 2-20)" 288 | # 0x0000081B 0x0000000000000000 # "IA32_X2APIC_TMR3 (Table: 2-20)" 289 | # 0x0000081C 0x0000000000000000 # "IA32_X2APIC_TMR4 (Table: 2-20)" 290 | # 0x0000081D 0x0000000000000000 # "IA32_X2APIC_TMR5 (Table: 2-20)" 291 | # 0x0000081E 0x0000000000000000 # "IA32_X2APIC_TMR6 (Table: 2-20)" 292 | # 0x0000081F 0x0000000000000000 # "IA32_X2APIC_TMR7 (Table: 2-20)" 293 | # 0x00000820 0x0000000000000000 # "IA32_X2APIC_IRR0 (Table: 2-20)" 294 | # 0x00000821 0x0000000000000000 # "IA32_X2APIC_IRR1 (Table: 2-20)" 295 | # 0x00000822 0x0000000000000000 # "IA32_X2APIC_IRR2 (Table: 2-20)" 296 | # 0x00000823 0x0000000000000000 # "IA32_X2APIC_IRR3 (Table: 2-20)" 297 | # 0x00000824 0x0000000000000000 # "IA32_X2APIC_IRR4 (Table: 2-20)" 298 | # 0x00000825 0x0000000000000000 # "IA32_X2APIC_IRR5 (Table: 2-20)" 299 | # 0x00000826 0x0000000000000000 # "IA32_X2APIC_IRR6 (Table: 2-20)" 300 | # 0x00000827 0x0000000000000000 # "IA32_X2APIC_IRR7 (Table: 2-20)" 301 | # 0x00000828 0x0000000000000000 # "IA32_X2APIC_ERS (Table: 2-20)" 302 | # 0x0000082F 0x0000000000000000 # "IA32_X2APIC_LVT_CMCI (Table: 2-20)" 303 | # 0x00000830 0x0000000000000000 # "IA32_X2APIC_ICR (Table: 2-20)" 304 | # 0x00000832 0x0000000000000000 # "IA32_X2APIC_LVT_TIMER (Table: 2-20)" 305 | # 0x00000833 0x0000000000000000 # "IA32_X2APIC_LVT_THERMAL (Table: 2-20)" 306 | # 0x00000834 0x0000000000000000 # "IA32_X2APIC_LVT_PMI (Table: 2-20)" 307 | # 0x00000835 0x0000000000000000 # "IA32_X2APIC_LVT_LINT0 (Table: 2-20)" 308 | # 0x00000836 0x0000000000000000 # "IA32_X2APIC_LVT_LINT1 (Table: 2-20)" 309 | # 0x00000837 0x0000000000000000 # "IA32_X2APIC_LVT_ERROR (Table: 2-20)" 310 | # 0x00000838 0x0000000000000000 # "IA32_X2APIC_INIT_COUNT (Table: 2-20)" 311 | # 0x00000839 0x0000000000000000 # "IA32_X2APIC_CUR_COUNT (Table: 2-20)" 312 | # 0x0000083E 0x0000000000000000 # "IA32_X2APIC_DIV_CONF (Table: 2-20)" 313 | # 0x0000083F 0x0000000000000000 # "IA32_X2APIC_SELF_IPI (Table: 2-20)" 314 | # 0xC0000080 0x0000000000000000 # "IA32_EFER (Table: 2-20)" 315 | # 0xC0000081 0x0000000000000000 # "IA32_STAR (Table: 2-20)" 316 | # 0xC0000082 0x0000000000000000 # "IA32_LSTAR (Table: 2-20)" 317 | # 0xC0000084 0x0000000000000000 # "IA32_FMASK (Table: 2-20)" 318 | # 0xC0000100 0x0000000000000000 # "IA32_FS_BASE (Table: 2-20)" 319 | # 0xC0000101 0x0000000000000000 # "IA32_GS_BASE (Table: 2-20)" 320 | # 0xC0000102 0x0000000000000000 # "IA32_KERNEL_GS_BASE (Table: 2-20)" 321 | # 0xC0000103 0x0000000000000000 # "IA32_TSC_AUX (Table: 2-20)" 322 | --------------------------------------------------------------------------------