1271912Sneel/*-
2336190Saraujo * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3336190Saraujo *
4271912Sneel * Copyright (c) 2014, Neel Natu (neel@freebsd.org)
5271912Sneel * All rights reserved.
6271912Sneel *
7271912Sneel * Redistribution and use in source and binary forms, with or without
8271912Sneel * modification, are permitted provided that the following conditions
9271912Sneel * are met:
10271912Sneel * 1. Redistributions of source code must retain the above copyright
11271912Sneel *    notice unmodified, this list of conditions, and the following
12271912Sneel *    disclaimer.
13271912Sneel * 2. Redistributions in binary form must reproduce the above copyright
14271912Sneel *    notice, this list of conditions and the following disclaimer in the
15271912Sneel *    documentation and/or other materials provided with the distribution.
16271912Sneel *
17271912Sneel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18271912Sneel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19271912Sneel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20271912Sneel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21271912Sneel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22271912Sneel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23271912Sneel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24271912Sneel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25271912Sneel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26271912Sneel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27271912Sneel */
28271912Sneel
29271912Sneel#include <sys/cdefs.h>
30271912Sneel__FBSDID("$FreeBSD: stable/11/sys/amd64/vmm/amd/svm_msr.c 349958 2019-07-12 22:31:12Z jhb $");
31271912Sneel
32282281Sneel#include <sys/param.h>
33271912Sneel#include <sys/errno.h>
34282281Sneel#include <sys/systm.h>
35271912Sneel
36271912Sneel#include <machine/cpufunc.h>
37271912Sneel#include <machine/specialreg.h>
38282281Sneel#include <machine/vmm.h>
39271912Sneel
40282281Sneel#include "svm.h"
41282281Sneel#include "vmcb.h"
42282281Sneel#include "svm_softc.h"
43271912Sneel#include "svm_msr.h"
44271912Sneel
45271912Sneel#ifndef MSR_AMDK8_IPM
46271912Sneel#define	MSR_AMDK8_IPM	0xc0010055
47271912Sneel#endif
48271912Sneel
49271912Sneelenum {
50271912Sneel	IDX_MSR_LSTAR,
51271912Sneel	IDX_MSR_CSTAR,
52271912Sneel	IDX_MSR_STAR,
53271912Sneel	IDX_MSR_SF_MASK,
54271912Sneel	HOST_MSR_NUM		/* must be the last enumeration */
55271912Sneel};
56271912Sneel
57271912Sneelstatic uint64_t host_msrs[HOST_MSR_NUM];
58271912Sneel
59271912Sneelvoid
60271912Sneelsvm_msr_init(void)
61271912Sneel{
62271912Sneel	/*
63271912Sneel	 * It is safe to cache the values of the following MSRs because they
64271912Sneel	 * don't change based on curcpu, curproc or curthread.
65271912Sneel	 */
66271912Sneel	host_msrs[IDX_MSR_LSTAR] = rdmsr(MSR_LSTAR);
67271912Sneel	host_msrs[IDX_MSR_CSTAR] = rdmsr(MSR_CSTAR);
68271912Sneel	host_msrs[IDX_MSR_STAR] = rdmsr(MSR_STAR);
69271912Sneel	host_msrs[IDX_MSR_SF_MASK] = rdmsr(MSR_SF_MASK);
70271912Sneel}
71271912Sneel
72271912Sneelvoid
73271912Sneelsvm_msr_guest_init(struct svm_softc *sc, int vcpu)
74271912Sneel{
75271912Sneel	/*
76271912Sneel	 * All the MSRs accessible to the guest are either saved/restored by
77271912Sneel	 * hardware on every #VMEXIT/VMRUN (e.g., G_PAT) or are saved/restored
78271912Sneel	 * by VMSAVE/VMLOAD (e.g., MSR_GSBASE).
79271912Sneel	 *
80271912Sneel	 * There are no guest MSRs that are saved/restored "by hand" so nothing
81271912Sneel	 * more to do here.
82271912Sneel	 */
83271912Sneel	return;
84271912Sneel}
85271912Sneel
86271912Sneelvoid
87271912Sneelsvm_msr_guest_enter(struct svm_softc *sc, int vcpu)
88271912Sneel{
89271912Sneel	/*
90271912Sneel	 * Save host MSRs (if any) and restore guest MSRs (if any).
91271912Sneel	 */
92271912Sneel}
93271912Sneel
94271912Sneelvoid
95271912Sneelsvm_msr_guest_exit(struct svm_softc *sc, int vcpu)
96271912Sneel{
97271912Sneel	/*
98271912Sneel	 * Save guest MSRs (if any) and restore host MSRs.
99271912Sneel	 */
100271912Sneel	wrmsr(MSR_LSTAR, host_msrs[IDX_MSR_LSTAR]);
101271912Sneel	wrmsr(MSR_CSTAR, host_msrs[IDX_MSR_CSTAR]);
102271912Sneel	wrmsr(MSR_STAR, host_msrs[IDX_MSR_STAR]);
103271912Sneel	wrmsr(MSR_SF_MASK, host_msrs[IDX_MSR_SF_MASK]);
104271912Sneel
105271912Sneel	/* MSR_KGSBASE will be restored on the way back to userspace */
106271912Sneel}
107271912Sneel
108271912Sneelint
109271912Sneelsvm_rdmsr(struct svm_softc *sc, int vcpu, u_int num, uint64_t *result,
110271912Sneel    bool *retu)
111271912Sneel{
112271912Sneel	int error = 0;
113271912Sneel
114271912Sneel	switch (num) {
115282336Sneel	case MSR_MCG_CAP:
116282336Sneel	case MSR_MCG_STATUS:
117282336Sneel		*result = 0;
118282336Sneel		break;
119282281Sneel	case MSR_MTRRcap:
120282281Sneel	case MSR_MTRRdefType:
121282281Sneel	case MSR_MTRR4kBase ... MSR_MTRR4kBase + 8:
122282281Sneel	case MSR_MTRR16kBase ... MSR_MTRR16kBase + 1:
123282281Sneel	case MSR_MTRR64kBase:
124282296Sneel	case MSR_SYSCFG:
125271912Sneel	case MSR_AMDK8_IPM:
126349958Sjhb	case MSR_EXTFEATURES:
127271912Sneel		*result = 0;
128271912Sneel		break;
129271912Sneel	default:
130271912Sneel		error = EINVAL;
131271912Sneel		break;
132271912Sneel	}
133271912Sneel
134271912Sneel	return (error);
135271912Sneel}
136271912Sneel
137271912Sneelint
138271912Sneelsvm_wrmsr(struct svm_softc *sc, int vcpu, u_int num, uint64_t val, bool *retu)
139271912Sneel{
140271912Sneel	int error = 0;
141271912Sneel
142271912Sneel	switch (num) {
143282336Sneel	case MSR_MCG_CAP:
144282336Sneel	case MSR_MCG_STATUS:
145282336Sneel		break;		/* ignore writes */
146282281Sneel	case MSR_MTRRcap:
147282281Sneel		vm_inject_gp(sc->vm, vcpu);
148282281Sneel		break;
149282281Sneel	case MSR_MTRRdefType:
150282281Sneel	case MSR_MTRR4kBase ... MSR_MTRR4kBase + 8:
151282281Sneel	case MSR_MTRR16kBase ... MSR_MTRR16kBase + 1:
152282281Sneel	case MSR_MTRR64kBase:
153282296Sneel	case MSR_SYSCFG:
154282281Sneel		break;		/* Ignore writes */
155271912Sneel	case MSR_AMDK8_IPM:
156271912Sneel		/*
157271912Sneel		 * Ignore writes to the "Interrupt Pending Message" MSR.
158271912Sneel		 */
159271912Sneel		break;
160297806Sanish	case MSR_K8_UCODE_UPDATE:
161297806Sanish		/*
162297806Sanish		 * Ignore writes to microcode update register.
163297806Sanish		 */
164297806Sanish		break;
165349958Sjhb	case MSR_EXTFEATURES:
166349958Sjhb		break;
167271912Sneel	default:
168271912Sneel		error = EINVAL;
169271912Sneel		break;
170271912Sneel	}
171271912Sneel
172271912Sneel	return (error);
173271912Sneel}
174