/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2011 NetApp, Inc.4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND16* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18* ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE19* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS21* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*/2728#include <sys/types.h>2930#include <machine/cpufunc.h>31#include <machine/vmm.h>32#include <machine/specialreg.h>3334#include <errno.h>35#include <stdio.h>36#include <stdlib.h>37#include <string.h>3839#include <vmmapi.h>4041#include "debug.h"42#include "xmsr.h"4344static int cpu_vendor_intel, cpu_vendor_amd, cpu_vendor_hygon;4546int47emulate_wrmsr(struct vcpu *vcpu __unused, uint32_t num, uint64_t val __unused)48{4950if (cpu_vendor_intel) {51switch (num) {52case 0xd04: /* Sandy Bridge uncore PMCs */53case 0xc24:54return (0);55case MSR_BIOS_UPDT_TRIG:56return (0);57case MSR_BIOS_SIGN:58return (0);59default:60break;61}62} else if (cpu_vendor_amd || cpu_vendor_hygon) {63switch (num) {64case MSR_HWCR:65/*66* Ignore writes to hardware configuration MSR.67*/68return (0);6970case MSR_NB_CFG1:71case MSR_LS_CFG:72case MSR_IC_CFG:73return (0); /* Ignore writes */7475case MSR_PERFEVSEL0:76case MSR_PERFEVSEL1:77case MSR_PERFEVSEL2:78case MSR_PERFEVSEL3:79/* Ignore writes to the PerfEvtSel MSRs */80return (0);8182case MSR_K7_PERFCTR0:83case MSR_K7_PERFCTR1:84case MSR_K7_PERFCTR2:85case MSR_K7_PERFCTR3:86/* Ignore writes to the PerfCtr MSRs */87return (0);8889case MSR_P_STATE_CONTROL:90/* Ignore write to change the P-state */91return (0);9293default:94break;95}96}97return (-1);98}99100int101emulate_rdmsr(struct vcpu *vcpu __unused, uint32_t num, uint64_t *val)102{103int error = 0;104105if (cpu_vendor_intel) {106switch (num) {107case MSR_BIOS_SIGN:108case MSR_IA32_PLATFORM_ID:109case MSR_PKG_ENERGY_STATUS:110case MSR_PP0_ENERGY_STATUS:111case MSR_PP1_ENERGY_STATUS:112case MSR_DRAM_ENERGY_STATUS:113case MSR_MISC_FEATURE_ENABLES:114*val = 0;115break;116case MSR_RAPL_POWER_UNIT:117/*118* Use the default value documented in section119* "RAPL Interfaces" in Intel SDM vol3.120*/121*val = 0x000a1003;122break;123case MSR_IA32_FEATURE_CONTROL:124/*125* Windows guests check this MSR.126* Set the lock bit to avoid writes127* to this MSR.128*/129*val = IA32_FEATURE_CONTROL_LOCK;130break;131default:132error = -1;133break;134}135} else if (cpu_vendor_amd || cpu_vendor_hygon) {136switch (num) {137case MSR_BIOS_SIGN:138*val = 0;139break;140case MSR_HWCR:141/*142* Bios and Kernel Developer's Guides for AMD Families143* 12H, 14H, 15H and 16H.144*/145*val = 0x01000010; /* Reset value */146*val |= 1 << 9; /* MONITOR/MWAIT disable */147break;148149case MSR_NB_CFG1:150case MSR_LS_CFG:151case MSR_IC_CFG:152/*153* The reset value is processor family dependent so154* just return 0.155*/156*val = 0;157break;158159case MSR_PERFEVSEL0:160case MSR_PERFEVSEL1:161case MSR_PERFEVSEL2:162case MSR_PERFEVSEL3:163/*164* PerfEvtSel MSRs are not properly virtualized so just165* return zero.166*/167*val = 0;168break;169170case MSR_K7_PERFCTR0:171case MSR_K7_PERFCTR1:172case MSR_K7_PERFCTR2:173case MSR_K7_PERFCTR3:174/*175* PerfCtr MSRs are not properly virtualized so just176* return zero.177*/178*val = 0;179break;180181case MSR_SMM_ADDR:182case MSR_SMM_MASK:183/*184* Return the reset value defined in the AMD Bios and185* Kernel Developer's Guide.186*/187*val = 0;188break;189190case MSR_P_STATE_LIMIT:191case MSR_P_STATE_CONTROL:192case MSR_P_STATE_STATUS:193case MSR_P_STATE_CONFIG(0): /* P0 configuration */194*val = 0;195break;196197/*198* OpenBSD guests test bit 0 of this MSR to detect if the199* workaround for erratum 721 is already applied.200* https://support.amd.com/TechDocs/41322_10h_Rev_Gd.pdf201*/202case 0xC0011029:203*val = 1;204break;205206case MSR_VM_CR:207/*208* We currently don't support nested virt.209* Windows seems to ignore the cpuid bits and reads this210* MSR anyways.211*/212*val = VM_CR_SVMDIS;213break;214215default:216error = -1;217break;218}219} else {220error = -1;221}222return (error);223}224225int226init_msr(void)227{228int error;229u_int regs[4];230char cpu_vendor[13];231232do_cpuid(0, regs);233((u_int *)&cpu_vendor)[0] = regs[1];234((u_int *)&cpu_vendor)[1] = regs[3];235((u_int *)&cpu_vendor)[2] = regs[2];236cpu_vendor[12] = '\0';237238error = 0;239if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {240cpu_vendor_amd = 1;241} else if (strcmp(cpu_vendor, "HygonGenuine") == 0) {242cpu_vendor_hygon = 1;243} else if (strcmp(cpu_vendor, "GenuineIntel") == 0) {244cpu_vendor_intel = 1;245} else {246EPRINTLN("Unknown cpu vendor \"%s\"", cpu_vendor);247error = ENOENT;248}249return (error);250}251252253