summaryrefslogtreecommitdiff
path: root/arch/x86/kvm/msrs.h
blob: 7cc182a15b3b3e3fce921f92d0eb1bd912a42f74 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef ARCH_X86_KVM_MSRS_H
#define ARCH_X86_KVM_MSRS_H

#include <linux/kvm_host.h>
#include <linux/user-return-notifier.h>

#include "cpuid.h"
#include "regs.h"

extern bool report_ignored_msrs;
extern bool ignore_msrs;

extern u32 __read_mostly kvm_nr_uret_msrs;

static inline void kvm_pr_unimpl_wrmsr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
{
	if (report_ignored_msrs)
		vcpu_unimpl(vcpu, "Unhandled WRMSR(0x%x) = 0x%llx\n", msr, data);
}

static inline void kvm_pr_unimpl_rdmsr(struct kvm_vcpu *vcpu, u32 msr)
{
	if (report_ignored_msrs)
		vcpu_unimpl(vcpu, "Unhandled RDMSR(0x%x)\n", msr);
}

/*
 * The first...last VMX feature MSRs that are emulated by KVM.  This may or may
 * not cover all known VMX MSRs, as KVM doesn't emulate an MSR until there's an
 * associated feature that KVM supports for nested virtualization.
 */
#define KVM_FIRST_EMULATED_VMX_MSR	MSR_IA32_VMX_BASIC
#define KVM_LAST_EMULATED_VMX_MSR	MSR_IA32_VMX_VMFUNC

/*
 * KVM's internal, non-ABI indices for synthetic MSRs. The values themselves
 * are arbitrary and have no meaning, the only requirement is that they don't
 * conflict with "real" MSRs that KVM supports. Use values at the upper end
 * of KVM's reserved paravirtual MSR range to minimize churn, i.e. these values
 * will be usable until KVM exhausts its supply of paravirtual MSR indices.
 */
#define MSR_KVM_INTERNAL_GUEST_SSP	0x4b564dff

#define MSR_IA32_CR_PAT_DEFAULT	\
	PAT_VALUE(WB, WT, UC_MINUS, UC, WB, WT, UC_MINUS, UC)

void kvm_init_msr_lists(void);
int kvm_get_msr_index_list(struct kvm_msr_list __user *user_msr_list);
int kvm_get_feature_msr_index_list(struct kvm_msr_list __user *user_msr_list);
int kvm_get_feature_msrs(struct kvm_msrs __user *user_msrs);

int kvm_get_msrs(struct kvm_vcpu *vcpu, struct kvm_msrs __user *user_msrs);
int kvm_set_msrs(struct kvm_vcpu *vcpu, struct kvm_msrs __user *user_msrs);

int kvm_get_set_one_reg(struct kvm_vcpu *vcpu, unsigned int ioctl,
			void __user *argp);
int kvm_get_reg_list(struct kvm_vcpu *vcpu,
		     struct kvm_reg_list __user *user_list);

bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer);
int kvm_emulate_msr_read(struct kvm_vcpu *vcpu, u32 index, u64 *data);
int kvm_emulate_msr_write(struct kvm_vcpu *vcpu, u32 index, u64 data);
int __kvm_emulate_msr_read(struct kvm_vcpu *vcpu, u32 index, u64 *data);
int __kvm_emulate_msr_write(struct kvm_vcpu *vcpu, u32 index, u64 data);
int kvm_msr_read(struct kvm_vcpu *vcpu, u32 index, u64 *data);
int kvm_msr_write(struct kvm_vcpu *vcpu, u32 index, u64 data);
int kvm_emulate_rdmsr(struct kvm_vcpu *vcpu);
int kvm_emulate_rdmsr_imm(struct kvm_vcpu *vcpu, u32 msr, int reg);
int kvm_emulate_wrmsr(struct kvm_vcpu *vcpu);
int kvm_emulate_wrmsr_imm(struct kvm_vcpu *vcpu, u32 msr, int reg);

fastpath_t handle_fastpath_wrmsr(struct kvm_vcpu *vcpu);
fastpath_t handle_fastpath_wrmsr_imm(struct kvm_vcpu *vcpu, u32 msr, int reg);

int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr);
int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr);

int kvm_add_user_return_msr(u32 msr);
int kvm_find_user_return_msr(u32 msr);
int kvm_set_user_return_msr(unsigned index, u64 val, u64 mask);
u64 kvm_get_user_return_msr(unsigned int slot);

static inline bool kvm_is_supported_user_return_msr(u32 msr)
{
	return kvm_find_user_return_msr(msr) >= 0;
}

void kvm_user_return_msr_cpu_online(void);
void drop_user_return_notifiers(void);
void kvm_destroy_user_return_msrs(void);

int kvm_emulator_get_msr_with_filter(struct kvm_vcpu *vcpu, u32 msr_index,
				     u64 *pdata);
int kvm_emulator_set_msr_with_filter(struct kvm_vcpu *vcpu, u32 msr_index,
				     u64 data);
int kvm_emulator_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata);

bool kvm_msr_allowed(struct kvm_vcpu *vcpu, u32 index, u32 type);

enum kvm_msr_access {
	MSR_TYPE_R	= BIT(0),
	MSR_TYPE_W	= BIT(1),
	MSR_TYPE_RW	= MSR_TYPE_R | MSR_TYPE_W,
};

/*
 * Internal error codes that are used to indicate that MSR emulation encountered
 * an error that should result in #GP in the guest, unless userspace handles it.
 * Note, '1', '0', and negative numbers are off limits, as they are used by KVM
 * as part of KVM's lightly documented internal KVM_RUN return codes.
 *
 * UNSUPPORTED	- The MSR isn't supported, either because it is completely
 *		  unknown to KVM, or because the MSR should not exist according
 *		  to the vCPU model.
 *
 * FILTERED	- Access to the MSR is denied by a userspace MSR filter.
 */
#define  KVM_MSR_RET_UNSUPPORTED	2
#define  KVM_MSR_RET_FILTERED		3

int kvm_vm_ioctl_set_msr_filter(struct kvm *kvm, struct kvm_msr_filter *filter);
void kvm_free_msr_filter(struct kvm_x86_msr_filter *msr_filter);

int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data);
int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata);

u64 kvm_get_arch_capabilities(void);
int kvm_spec_ctrl_test_value(u64 value);

#define CET_US_RESERVED_BITS		GENMASK(9, 6)
#define CET_US_SHSTK_MASK_BITS		GENMASK(1, 0)
#define CET_US_IBT_MASK_BITS		(GENMASK_ULL(5, 2) | GENMASK_ULL(63, 10))
#define CET_US_LEGACY_BITMAP_BASE(data)	((data) >> 12)

static inline bool kvm_is_valid_u_s_cet(struct kvm_vcpu *vcpu, u64 data)
{
	if (data & CET_US_RESERVED_BITS)
		return false;
	if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK) &&
	    (data & CET_US_SHSTK_MASK_BITS))
		return false;
	if (!guest_cpu_cap_has(vcpu, X86_FEATURE_IBT) &&
	    (data & CET_US_IBT_MASK_BITS))
		return false;
	if (!IS_ALIGNED(CET_US_LEGACY_BITMAP_BASE(data), 4))
		return false;
	/* IBT can be suppressed iff the TRACKER isn't WAIT_ENDBR. */
	if ((data & CET_SUPPRESS) && (data & CET_WAIT_ENDBR))
		return false;

	return true;
}

#endif