1*8f02c5e4SNeel Natu /*- 2*8f02c5e4SNeel Natu * Copyright (c) 2014, Neel Natu (neel@freebsd.org) 3*8f02c5e4SNeel Natu * All rights reserved. 4*8f02c5e4SNeel Natu * 5*8f02c5e4SNeel Natu * Redistribution and use in source and binary forms, with or without 6*8f02c5e4SNeel Natu * modification, are permitted provided that the following conditions 7*8f02c5e4SNeel Natu * are met: 8*8f02c5e4SNeel Natu * 1. Redistributions of source code must retain the above copyright 9*8f02c5e4SNeel Natu * notice unmodified, this list of conditions, and the following 10*8f02c5e4SNeel Natu * disclaimer. 11*8f02c5e4SNeel Natu * 2. Redistributions in binary form must reproduce the above copyright 12*8f02c5e4SNeel Natu * notice, this list of conditions and the following disclaimer in the 13*8f02c5e4SNeel Natu * documentation and/or other materials provided with the distribution. 14*8f02c5e4SNeel Natu * 15*8f02c5e4SNeel Natu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16*8f02c5e4SNeel Natu * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17*8f02c5e4SNeel Natu * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18*8f02c5e4SNeel Natu * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19*8f02c5e4SNeel Natu * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20*8f02c5e4SNeel Natu * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21*8f02c5e4SNeel Natu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22*8f02c5e4SNeel Natu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23*8f02c5e4SNeel Natu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24*8f02c5e4SNeel Natu * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25*8f02c5e4SNeel Natu */ 26*8f02c5e4SNeel Natu 27*8f02c5e4SNeel Natu #include <sys/cdefs.h> 28*8f02c5e4SNeel Natu __FBSDID("$FreeBSD$"); 29*8f02c5e4SNeel Natu 30*8f02c5e4SNeel Natu #include <sys/types.h> 31*8f02c5e4SNeel Natu #include <sys/errno.h> 32*8f02c5e4SNeel Natu 33*8f02c5e4SNeel Natu #include <machine/cpufunc.h> 34*8f02c5e4SNeel Natu #include <machine/specialreg.h> 35*8f02c5e4SNeel Natu 36*8f02c5e4SNeel Natu #include "svm_msr.h" 37*8f02c5e4SNeel Natu 38*8f02c5e4SNeel Natu #ifndef MSR_AMDK8_IPM 39*8f02c5e4SNeel Natu #define MSR_AMDK8_IPM 0xc0010055 40*8f02c5e4SNeel Natu #endif 41*8f02c5e4SNeel Natu 42*8f02c5e4SNeel Natu enum { 43*8f02c5e4SNeel Natu IDX_MSR_LSTAR, 44*8f02c5e4SNeel Natu IDX_MSR_CSTAR, 45*8f02c5e4SNeel Natu IDX_MSR_STAR, 46*8f02c5e4SNeel Natu IDX_MSR_SF_MASK, 47*8f02c5e4SNeel Natu HOST_MSR_NUM /* must be the last enumeration */ 48*8f02c5e4SNeel Natu }; 49*8f02c5e4SNeel Natu 50*8f02c5e4SNeel Natu static uint64_t host_msrs[HOST_MSR_NUM]; 51*8f02c5e4SNeel Natu 52*8f02c5e4SNeel Natu void 53*8f02c5e4SNeel Natu svm_msr_init(void) 54*8f02c5e4SNeel Natu { 55*8f02c5e4SNeel Natu /* 56*8f02c5e4SNeel Natu * It is safe to cache the values of the following MSRs because they 57*8f02c5e4SNeel Natu * don't change based on curcpu, curproc or curthread. 58*8f02c5e4SNeel Natu */ 59*8f02c5e4SNeel Natu host_msrs[IDX_MSR_LSTAR] = rdmsr(MSR_LSTAR); 60*8f02c5e4SNeel Natu host_msrs[IDX_MSR_CSTAR] = rdmsr(MSR_CSTAR); 61*8f02c5e4SNeel Natu host_msrs[IDX_MSR_STAR] = rdmsr(MSR_STAR); 62*8f02c5e4SNeel Natu host_msrs[IDX_MSR_SF_MASK] = rdmsr(MSR_SF_MASK); 63*8f02c5e4SNeel Natu } 64*8f02c5e4SNeel Natu 65*8f02c5e4SNeel Natu void 66*8f02c5e4SNeel Natu svm_msr_guest_init(struct svm_softc *sc, int vcpu) 67*8f02c5e4SNeel Natu { 68*8f02c5e4SNeel Natu /* 69*8f02c5e4SNeel Natu * All the MSRs accessible to the guest are either saved/restored by 70*8f02c5e4SNeel Natu * hardware on every #VMEXIT/VMRUN (e.g., G_PAT) or are saved/restored 71*8f02c5e4SNeel Natu * by VMSAVE/VMLOAD (e.g., MSR_GSBASE). 72*8f02c5e4SNeel Natu * 73*8f02c5e4SNeel Natu * There are no guest MSRs that are saved/restored "by hand" so nothing 74*8f02c5e4SNeel Natu * more to do here. 75*8f02c5e4SNeel Natu */ 76*8f02c5e4SNeel Natu return; 77*8f02c5e4SNeel Natu } 78*8f02c5e4SNeel Natu 79*8f02c5e4SNeel Natu void 80*8f02c5e4SNeel Natu svm_msr_guest_enter(struct svm_softc *sc, int vcpu) 81*8f02c5e4SNeel Natu { 82*8f02c5e4SNeel Natu /* 83*8f02c5e4SNeel Natu * Save host MSRs (if any) and restore guest MSRs (if any). 84*8f02c5e4SNeel Natu */ 85*8f02c5e4SNeel Natu } 86*8f02c5e4SNeel Natu 87*8f02c5e4SNeel Natu void 88*8f02c5e4SNeel Natu svm_msr_guest_exit(struct svm_softc *sc, int vcpu) 89*8f02c5e4SNeel Natu { 90*8f02c5e4SNeel Natu /* 91*8f02c5e4SNeel Natu * Save guest MSRs (if any) and restore host MSRs. 92*8f02c5e4SNeel Natu */ 93*8f02c5e4SNeel Natu wrmsr(MSR_LSTAR, host_msrs[IDX_MSR_LSTAR]); 94*8f02c5e4SNeel Natu wrmsr(MSR_CSTAR, host_msrs[IDX_MSR_CSTAR]); 95*8f02c5e4SNeel Natu wrmsr(MSR_STAR, host_msrs[IDX_MSR_STAR]); 96*8f02c5e4SNeel Natu wrmsr(MSR_SF_MASK, host_msrs[IDX_MSR_SF_MASK]); 97*8f02c5e4SNeel Natu 98*8f02c5e4SNeel Natu /* MSR_KGSBASE will be restored on the way back to userspace */ 99*8f02c5e4SNeel Natu } 100*8f02c5e4SNeel Natu 101*8f02c5e4SNeel Natu int 102*8f02c5e4SNeel Natu svm_rdmsr(struct svm_softc *sc, int vcpu, u_int num, uint64_t *result, 103*8f02c5e4SNeel Natu bool *retu) 104*8f02c5e4SNeel Natu { 105*8f02c5e4SNeel Natu int error = 0; 106*8f02c5e4SNeel Natu 107*8f02c5e4SNeel Natu switch (num) { 108*8f02c5e4SNeel Natu case MSR_AMDK8_IPM: 109*8f02c5e4SNeel Natu *result = 0; 110*8f02c5e4SNeel Natu break; 111*8f02c5e4SNeel Natu default: 112*8f02c5e4SNeel Natu error = EINVAL; 113*8f02c5e4SNeel Natu break; 114*8f02c5e4SNeel Natu } 115*8f02c5e4SNeel Natu 116*8f02c5e4SNeel Natu return (error); 117*8f02c5e4SNeel Natu } 118*8f02c5e4SNeel Natu 119*8f02c5e4SNeel Natu int 120*8f02c5e4SNeel Natu svm_wrmsr(struct svm_softc *sc, int vcpu, u_int num, uint64_t val, bool *retu) 121*8f02c5e4SNeel Natu { 122*8f02c5e4SNeel Natu int error = 0; 123*8f02c5e4SNeel Natu 124*8f02c5e4SNeel Natu switch (num) { 125*8f02c5e4SNeel Natu case MSR_AMDK8_IPM: 126*8f02c5e4SNeel Natu /* 127*8f02c5e4SNeel Natu * Ignore writes to the "Interrupt Pending Message" MSR. 128*8f02c5e4SNeel Natu */ 129*8f02c5e4SNeel Natu break; 130*8f02c5e4SNeel Natu default: 131*8f02c5e4SNeel Natu error = EINVAL; 132*8f02c5e4SNeel Natu break; 133*8f02c5e4SNeel Natu } 134*8f02c5e4SNeel Natu 135*8f02c5e4SNeel Natu return (error); 136*8f02c5e4SNeel Natu } 137