14
#include "hw/hyperv/hvgdk_mini.h"
15
#include "linux/mshv.h"
16
#include "qemu/error-report.h"
17
+#include "cpu.h"
18
18
-static uint32_t supported_msrs[64] = {
19
- IA32_MSR_TSC,
20
- IA32_MSR_EFER,
21
- IA32_MSR_KERNEL_GS_BASE,
22
- IA32_MSR_APIC_BASE,
23
- IA32_MSR_PAT,
24
- IA32_MSR_SYSENTER_CS,
25
- IA32_MSR_SYSENTER_ESP,
26
- IA32_MSR_SYSENTER_EIP,
27
- IA32_MSR_STAR,
28
- IA32_MSR_LSTAR,
29
- IA32_MSR_CSTAR,
30
- IA32_MSR_SFMASK,
31
- IA32_MSR_MTRR_DEF_TYPE,
32
- IA32_MSR_MTRR_PHYSBASE0,
33
- IA32_MSR_MTRR_PHYSMASK0,
34
- IA32_MSR_MTRR_PHYSBASE1,
35
- IA32_MSR_MTRR_PHYSMASK1,
36
- IA32_MSR_MTRR_PHYSBASE2,
37
- IA32_MSR_MTRR_PHYSMASK2,
38
- IA32_MSR_MTRR_PHYSBASE3,
39
- IA32_MSR_MTRR_PHYSMASK3,
40
- IA32_MSR_MTRR_PHYSBASE4,
41
- IA32_MSR_MTRR_PHYSMASK4,
42
- IA32_MSR_MTRR_PHYSBASE5,
43
- IA32_MSR_MTRR_PHYSMASK5,
44
- IA32_MSR_MTRR_PHYSBASE6,
45
- IA32_MSR_MTRR_PHYSMASK6,
46
- IA32_MSR_MTRR_PHYSBASE7,
47
- IA32_MSR_MTRR_PHYSMASK7,
48
- IA32_MSR_MTRR_FIX64K_00000,
49
- IA32_MSR_MTRR_FIX16K_80000,
50
- IA32_MSR_MTRR_FIX16K_A0000,
51
- IA32_MSR_MTRR_FIX4K_C0000,
52
- IA32_MSR_MTRR_FIX4K_C8000,
53
- IA32_MSR_MTRR_FIX4K_D0000,
54
- IA32_MSR_MTRR_FIX4K_D8000,
55
- IA32_MSR_MTRR_FIX4K_E0000,
56
- IA32_MSR_MTRR_FIX4K_E8000,
57
- IA32_MSR_MTRR_FIX4K_F0000,
58
- IA32_MSR_MTRR_FIX4K_F8000,
59
- IA32_MSR_TSC_AUX,
60
- IA32_MSR_DEBUG_CTL,
61
- HV_X64_MSR_GUEST_OS_ID,
62
- HV_X64_MSR_SINT0,
63
- HV_X64_MSR_SINT1,
64
- HV_X64_MSR_SINT2,
65
- HV_X64_MSR_SINT3,
66
- HV_X64_MSR_SINT4,
67
- HV_X64_MSR_SINT5,
68
- HV_X64_MSR_SINT6,
69
- HV_X64_MSR_SINT7,
70
- HV_X64_MSR_SINT8,
71
- HV_X64_MSR_SINT9,
72
- HV_X64_MSR_SINT10,
73
- HV_X64_MSR_SINT11,
74
- HV_X64_MSR_SINT12,
75
- HV_X64_MSR_SINT13,
76
- HV_X64_MSR_SINT14,
77
- HV_X64_MSR_SINT15,
78
- HV_X64_MSR_SCONTROL,
79
- HV_X64_MSR_SIEFP,
80
- HV_X64_MSR_SIMP,
81
- HV_X64_MSR_REFERENCE_TSC,
82
- HV_X64_MSR_EOM,
19
+#define MSHV_ENV_FIELD(env, offset) (*(uint64_t *)((char *)(env) + (offset)))
20
+
21
+typedef struct MshvMsrEnvMap {
22
+ uint32_t msr_index;
23
+ uint32_t hv_name;
24
+ ptrdiff_t env_offset;
25
+} MshvMsrEnvMap;
26
+
27
+/* We assert that 64bit access to sysenter_cs is safe because of padding */
28
+QEMU_BUILD_BUG_ON(offsetof(CPUX86State, sysenter_esp) -
29
+ offsetof(CPUX86State, sysenter_cs)
30
+ < sizeof(uint64_t));
31
+
32
+/* Those MSRs have a direct mapping to fields in CPUX86State */
33
+static const MshvMsrEnvMap msr_env_map[] = {
34
+ /* Architectural */
35
+ { IA32_MSR_EFER, HV_X64_REGISTER_EFER, offsetof(CPUX86State, efer) },
36
+ { IA32_MSR_PAT, HV_X64_REGISTER_PAT, offsetof(CPUX86State, pat) },
37
+
38
+ /* Syscall */
39
+ { IA32_MSR_SYSENTER_CS, HV_X64_REGISTER_SYSENTER_CS,
40
+ offsetof(CPUX86State, sysenter_cs) },
41
+ { IA32_MSR_SYSENTER_ESP, HV_X64_REGISTER_SYSENTER_ESP,
42
+ offsetof(CPUX86State, sysenter_esp) },
43
+ { IA32_MSR_SYSENTER_EIP, HV_X64_REGISTER_SYSENTER_EIP,
44
+ offsetof(CPUX86State, sysenter_eip) },
45
+ { IA32_MSR_STAR, HV_X64_REGISTER_STAR,
46
+ offsetof(CPUX86State, star) },
47
+ { IA32_MSR_LSTAR, HV_X64_REGISTER_LSTAR,
48
+ offsetof(CPUX86State, lstar) },
49
+ { IA32_MSR_CSTAR, HV_X64_REGISTER_CSTAR,
50
+ offsetof(CPUX86State, cstar) },
51
+ { IA32_MSR_SFMASK, HV_X64_REGISTER_SFMASK,
52
+ offsetof(CPUX86State, fmask) },
53
+ { IA32_MSR_KERNEL_GS_BASE, HV_X64_REGISTER_KERNEL_GS_BASE,
54
+ offsetof(CPUX86State, kernelgsbase) },
55
+
56
+ /* TSC-related */
57
+ { IA32_MSR_TSC, HV_X64_REGISTER_TSC,
58
+ offsetof(CPUX86State, tsc) },
59
+ { IA32_MSR_TSC_AUX, HV_X64_REGISTER_TSC_AUX,
60
+ offsetof(CPUX86State, tsc_aux) },
61
+ { IA32_MSR_TSC_ADJUST, HV_X64_REGISTER_TSC_ADJUST,
62
+ offsetof(CPUX86State, tsc_adjust) },
63
+
64
+ /* Hyper-V per-partition MSRs */
65
+ { HV_X64_MSR_HYPERCALL, HV_X64_REGISTER_HYPERCALL,
66
+ offsetof(CPUX86State, msr_hv_hypercall) },
67
+ { HV_X64_MSR_GUEST_OS_ID, HV_REGISTER_GUEST_OS_ID,
68
+ offsetof(CPUX86State, msr_hv_guest_os_id) },
69
+ { HV_X64_MSR_REFERENCE_TSC, HV_REGISTER_REFERENCE_TSC,
70
+ offsetof(CPUX86State, msr_hv_tsc) },
71
+
72
+ /* Hyper-V MSRs (non-SINT) */
73
+ { HV_X64_MSR_SCONTROL, HV_REGISTER_SCONTROL,
74
+ offsetof(CPUX86State, msr_hv_synic_control) },
75
+ { HV_X64_MSR_SIEFP, HV_REGISTER_SIEFP,
76
+ offsetof(CPUX86State, msr_hv_synic_evt_page) },
77
+ { HV_X64_MSR_SIMP, HV_REGISTER_SIMP,
78
+ offsetof(CPUX86State, msr_hv_synic_msg_page) },
79
+
80
+ /* Other */
81
+
82
+ /* TODO: find out processor features that correlate to unsupported MSRs. */
83
+ /* { IA32_MSR_MISC_ENABLE, HV_X64_REGISTER_MSR_IA32_MISC_ENABLE, */
84
+ /* offsetof(CPUX86State, msr_ia32_misc_enable) }, */
85
+ /* { IA32_MSR_BNDCFGS, HV_X64_REGISTER_BNDCFGS, */
86
+ /* offsetof(CPUX86State, msr_bndcfgs) }, */
87
+ { IA32_MSR_SPEC_CTRL, HV_X64_REGISTER_SPEC_CTRL,
88
+ offsetof(CPUX86State, spec_ctrl) },
89
};
84
-static const size_t msr_count = ARRAY_SIZE(supported_msrs);
90
86
-static int compare_msr_index(const void *a, const void *b)
91
+int mshv_init_msrs(const CPUState *cpu)
92
{
88
- return *(uint32_t *)a - *(uint32_t *)b;
93
+ int ret;
94
+ uint64_t d_t = MSR_MTRR_ENABLE | MSR_MTRR_MEM_TYPE_WB;
95
+
96
+ const struct hv_register_assoc assocs[] = {
97
+ { .name = HV_X64_REGISTER_SYSENTER_CS, .value.reg64 = 0x0 },
98
+ { .name = HV_X64_REGISTER_SYSENTER_ESP, .value.reg64 = 0x0 },
99
+ { .name = HV_X64_REGISTER_SYSENTER_EIP, .value.reg64 = 0x0 },
100
+ { .name = HV_X64_REGISTER_STAR, .value.reg64 = 0x0 },
101
+ { .name = HV_X64_REGISTER_CSTAR, .value.reg64 = 0x0 },
102
+ { .name = HV_X64_REGISTER_LSTAR, .value.reg64 = 0x0 },
103
+ { .name = HV_X64_REGISTER_KERNEL_GS_BASE, .value.reg64 = 0x0 },
104
+ { .name = HV_X64_REGISTER_SFMASK, .value.reg64 = 0x0 },
105
+ { .name = HV_X64_REGISTER_MSR_MTRR_DEF_TYPE, .value.reg64 = d_t },
106
+ };
107
+
108
+ ret = mshv_set_generic_regs(cpu, assocs, ARRAY_SIZE(assocs));
109
+ if (ret < 0) {
110
+ error_report("failed to put msrs");
111
+ return -1;
112
+ }
113
+
114
+ return 0;
115
}
116
91
-__attribute__((constructor))
92
-static void init_sorted_msr_map(void)
117
+
118
+/*
119
+ * INVARIANT: this fn expects assocs in the same order as they appear in
120
+ * msr_env_map.
121
+ */
122
+static void store_in_env(CPUState *cpu, const struct hv_register_assoc *assocs,
123
+ size_t n_assocs)
124
{
94
- qsort(supported_msrs, msr_count, sizeof(uint32_t), compare_msr_index);
125
+ X86CPU *x86_cpu = X86_CPU(cpu);
126
+ CPUX86State *env = &x86_cpu->env;
127
+ size_t i, j;
128
+ const MshvMsrEnvMap *mapping;
129
+ union hv_register_value hv_value;
130
+ ptrdiff_t offset;
131
+ uint32_t hv_name;
132
+
133
+ assert(n_assocs <= (ARRAY_SIZE(msr_env_map)));
134
+
135
+ for (i = 0, j = 0; i < ARRAY_SIZE(msr_env_map); i++) {
136
+ hv_name = assocs[j].name;
137
+ mapping = &msr_env_map[i];
138
+ if (hv_name != mapping->hv_name) {
139
+ continue;
140
+ }
141
+
142
+ hv_value = assocs[j].value;
143
+ offset = mapping->env_offset;
144
+ MSHV_ENV_FIELD(env, offset) = hv_value.reg64;
145
+ j++;
146
+ }
147
}
148
97
-static int mshv_is_supported_msr(uint32_t msr)
149
+static void set_hv_name_in_assocs(struct hv_register_assoc *assocs,
150
+ size_t n_assocs)
151
{
99
- return bsearch(&msr, supported_msrs, msr_count, sizeof(uint32_t),
100
- compare_msr_index) != NULL;
152
+ size_t i;
153
+
154
+ assert(n_assocs == ARRAY_SIZE(msr_env_map));
155
+ for (i = 0; i < ARRAY_SIZE(msr_env_map); i++) {
156
+ assocs[i].name = msr_env_map[i].hv_name;
157
+ }
158
}
159
103
-static int mshv_msr_to_hv_reg_name(uint32_t msr, uint32_t *hv_reg)
160
+static bool msr_supported(uint32_t name)
161
{
105
- switch (msr) {
106
- case IA32_MSR_TSC:
107
- *hv_reg = HV_X64_REGISTER_TSC;
108
- return 0;
109
- case IA32_MSR_EFER:
110
- *hv_reg = HV_X64_REGISTER_EFER;
111
- return 0;
112
- case IA32_MSR_KERNEL_GS_BASE:
113
- *hv_reg = HV_X64_REGISTER_KERNEL_GS_BASE;
114
- return 0;
115
- case IA32_MSR_APIC_BASE:
116
- *hv_reg = HV_X64_REGISTER_APIC_BASE;
117
- return 0;
118
- case IA32_MSR_PAT:
119
- *hv_reg = HV_X64_REGISTER_PAT;
120
- return 0;
121
- case IA32_MSR_SYSENTER_CS:
122
- *hv_reg = HV_X64_REGISTER_SYSENTER_CS;
123
- return 0;
124
- case IA32_MSR_SYSENTER_ESP:
125
- *hv_reg = HV_X64_REGISTER_SYSENTER_ESP;
126
- return 0;
127
- case IA32_MSR_SYSENTER_EIP:
128
- *hv_reg = HV_X64_REGISTER_SYSENTER_EIP;
129
- return 0;
130
- case IA32_MSR_STAR:
131
- *hv_reg = HV_X64_REGISTER_STAR;
132
- return 0;
133
- case IA32_MSR_LSTAR:
134
- *hv_reg = HV_X64_REGISTER_LSTAR;
135
- return 0;
136
- case IA32_MSR_CSTAR:
137
- *hv_reg = HV_X64_REGISTER_CSTAR;
138
- return 0;
139
- case IA32_MSR_SFMASK:
140
- *hv_reg = HV_X64_REGISTER_SFMASK;
141
- return 0;
142
- case IA32_MSR_MTRR_CAP:
143
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_CAP;
144
- return 0;
145
- case IA32_MSR_MTRR_DEF_TYPE:
146
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_DEF_TYPE;
147
- return 0;
148
- case IA32_MSR_MTRR_PHYSBASE0:
149
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_PHYS_BASE0;
150
- return 0;
151
- case IA32_MSR_MTRR_PHYSMASK0:
152
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_PHYS_MASK0;
153
- return 0;
154
- case IA32_MSR_MTRR_PHYSBASE1:
155
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_PHYS_BASE1;
156
- return 0;
157
- case IA32_MSR_MTRR_PHYSMASK1:
158
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_PHYS_MASK1;
159
- return 0;
160
- case IA32_MSR_MTRR_PHYSBASE2:
161
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_PHYS_BASE2;
162
- return 0;
163
- case IA32_MSR_MTRR_PHYSMASK2:
164
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_PHYS_MASK2;
165
- return 0;
166
- case IA32_MSR_MTRR_PHYSBASE3:
167
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_PHYS_BASE3;
168
- return 0;
169
- case IA32_MSR_MTRR_PHYSMASK3:
170
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_PHYS_MASK3;
171
- return 0;
172
- case IA32_MSR_MTRR_PHYSBASE4:
173
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_PHYS_BASE4;
174
- return 0;
175
- case IA32_MSR_MTRR_PHYSMASK4:
176
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_PHYS_MASK4;
177
- return 0;
178
- case IA32_MSR_MTRR_PHYSBASE5:
179
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_PHYS_BASE5;
180
- return 0;
181
- case IA32_MSR_MTRR_PHYSMASK5:
182
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_PHYS_MASK5;
183
- return 0;
184
- case IA32_MSR_MTRR_PHYSBASE6:
185
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_PHYS_BASE6;
186
- return 0;
187
- case IA32_MSR_MTRR_PHYSMASK6:
188
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_PHYS_MASK6;
189
- return 0;
190
- case IA32_MSR_MTRR_PHYSBASE7:
191
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_PHYS_BASE7;
192
- return 0;
193
- case IA32_MSR_MTRR_PHYSMASK7:
194
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_PHYS_MASK7;
195
- return 0;
196
- case IA32_MSR_MTRR_FIX64K_00000:
197
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_FIX64K00000;
198
- return 0;
199
- case IA32_MSR_MTRR_FIX16K_80000:
200
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_FIX16K80000;
201
- return 0;
202
- case IA32_MSR_MTRR_FIX16K_A0000:
203
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_FIX16KA0000;
204
- return 0;
205
- case IA32_MSR_MTRR_FIX4K_C0000:
206
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_FIX4KC0000;
207
- return 0;
208
- case IA32_MSR_MTRR_FIX4K_C8000:
209
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_FIX4KC8000;
210
- return 0;
211
- case IA32_MSR_MTRR_FIX4K_D0000:
212
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_FIX4KD0000;
213
- return 0;
214
- case IA32_MSR_MTRR_FIX4K_D8000:
215
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_FIX4KD8000;
216
- return 0;
217
- case IA32_MSR_MTRR_FIX4K_E0000:
218
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_FIX4KE0000;
219
- return 0;
220
- case IA32_MSR_MTRR_FIX4K_E8000:
221
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_FIX4KE8000;
222
- return 0;
223
- case IA32_MSR_MTRR_FIX4K_F0000:
224
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_FIX4KF0000;
225
- return 0;
226
- case IA32_MSR_MTRR_FIX4K_F8000:
227
- *hv_reg = HV_X64_REGISTER_MSR_MTRR_FIX4KF8000;
228
- return 0;
229
- case IA32_MSR_TSC_AUX:
230
- *hv_reg = HV_X64_REGISTER_TSC_AUX;
231
- return 0;
232
- case IA32_MSR_BNDCFGS:
233
- *hv_reg = HV_X64_REGISTER_BNDCFGS;
234
- return 0;
235
- case IA32_MSR_DEBUG_CTL:
236
- *hv_reg = HV_X64_REGISTER_DEBUG_CTL;
237
- return 0;
238
- case IA32_MSR_TSC_ADJUST:
239
- *hv_reg = HV_X64_REGISTER_TSC_ADJUST;
240
- return 0;
241
- case IA32_MSR_SPEC_CTRL:
242
- *hv_reg = HV_X64_REGISTER_SPEC_CTRL;
243
- return 0;
244
- case HV_X64_MSR_GUEST_OS_ID:
245
- *hv_reg = HV_REGISTER_GUEST_OS_ID;
246
- return 0;
247
- case HV_X64_MSR_SINT0:
248
- *hv_reg = HV_REGISTER_SINT0;
249
- return 0;
250
- case HV_X64_MSR_SINT1:
251
- *hv_reg = HV_REGISTER_SINT1;
252
- return 0;
253
- case HV_X64_MSR_SINT2:
254
- *hv_reg = HV_REGISTER_SINT2;
255
- return 0;
256
- case HV_X64_MSR_SINT3:
257
- *hv_reg = HV_REGISTER_SINT3;
258
- return 0;
259
- case HV_X64_MSR_SINT4:
260
- *hv_reg = HV_REGISTER_SINT4;
261
- return 0;
262
- case HV_X64_MSR_SINT5:
263
- *hv_reg = HV_REGISTER_SINT5;
264
- return 0;
265
- case HV_X64_MSR_SINT6:
266
- *hv_reg = HV_REGISTER_SINT6;
267
- return 0;
268
- case HV_X64_MSR_SINT7:
269
- *hv_reg = HV_REGISTER_SINT7;
270
- return 0;
271
- case HV_X64_MSR_SINT8:
272
- *hv_reg = HV_REGISTER_SINT8;
273
- return 0;
274
- case HV_X64_MSR_SINT9:
275
- *hv_reg = HV_REGISTER_SINT9;
276
- return 0;
277
- case HV_X64_MSR_SINT10:
278
- *hv_reg = HV_REGISTER_SINT10;
279
- return 0;
280
- case HV_X64_MSR_SINT11:
281
- *hv_reg = HV_REGISTER_SINT11;
282
- return 0;
283
- case HV_X64_MSR_SINT12:
284
- *hv_reg = HV_REGISTER_SINT12;
285
- return 0;
286
- case HV_X64_MSR_SINT13:
287
- *hv_reg = HV_REGISTER_SINT13;
288
- return 0;
289
- case HV_X64_MSR_SINT14:
290
- *hv_reg = HV_REGISTER_SINT14;
291
- return 0;
292
- case HV_X64_MSR_SINT15:
293
- *hv_reg = HV_REGISTER_SINT15;
294
- return 0;
295
- case IA32_MSR_MISC_ENABLE:
296
- *hv_reg = HV_X64_REGISTER_MSR_IA32_MISC_ENABLE;
297
- return 0;
298
- case HV_X64_MSR_SCONTROL:
299
- *hv_reg = HV_REGISTER_SCONTROL;
300
- return 0;
301
- case HV_X64_MSR_SIEFP:
302
- *hv_reg = HV_REGISTER_SIEFP;
303
- return 0;
304
- case HV_X64_MSR_SIMP:
305
- *hv_reg = HV_REGISTER_SIMP;
306
- return 0;
307
- case HV_X64_MSR_REFERENCE_TSC:
308
- *hv_reg = HV_REGISTER_REFERENCE_TSC;
309
- return 0;
310
- case HV_X64_MSR_EOM:
311
- *hv_reg = HV_REGISTER_EOM;
312
- return 0;
313
- default:
314
- error_report("failed to map MSR %u to HV register name", msr);
315
- return -1;
162
+ /*
163
+ * This check is not done comprehensively, it's meant to avoid hvcall
164
+ * failures for certain MSRs on architectures that don't support them.
165
+ */
166
+
167
+ switch (name) {
168
+ case HV_X64_REGISTER_SPEC_CTRL:
169
+ return mshv_state->processor_features.ibrs_support;
170
+ case HV_X64_REGISTER_TSC_ADJUST:
171
+ return mshv_state->processor_features.tsc_adjust_support;
172
}
173
+
174
+ return true;
175
}
176
319
-static int set_msrs(const CPUState *cpu, GList *msrs)
177
+int mshv_get_msrs(CPUState *cpu)
178
{
321
- size_t n_msrs;
322
- GList *entries;
323
- MshvMsrEntry *entry;
324
- enum hv_register_name name;
325
- struct hv_register_assoc *assoc;
326
- int ret;
327
- size_t i = 0;
328
-
329
- n_msrs = g_list_length(msrs);
330
- hv_register_assoc *assocs = g_new0(hv_register_assoc, n_msrs);
331
-
332
- entries = msrs;
333
- for (const GList *elem = entries; elem != NULL; elem = elem->next) {
334
- entry = elem->data;
335
- ret = mshv_msr_to_hv_reg_name(entry->index, &name);
336
- if (ret < 0) {
337
- g_free(assocs);
338
- return ret;
179
+ int ret = 0;
180
+ size_t n_assocs = ARRAY_SIZE(msr_env_map);
181
+ struct hv_register_assoc assocs[ARRAY_SIZE(msr_env_map)];
182
+ size_t i, j;
183
+ uint32_t name;
184
+
185
+ set_hv_name_in_assocs(assocs, n_assocs);
186
+
187
+ /* Filter out MSRs that cannot be read */
188
+ for (i = 0, j = 0; i < n_assocs; i++) {
189
+ name = assocs[i].name;
190
+
191
+ if (!msr_supported(name)) {
192
+ continue;
193
}
340
- assoc = &assocs[i];
341
- assoc->name = name;
342
- /* the union has been initialized to 0 */
343
- assoc->value.reg64 = entry->data;
344
- i++;
194
+
195
+ if (j != i) {
196
+ assocs[j] = assocs[i];
197
+ }
198
+ j++;
199
}
346
- ret = mshv_set_generic_regs(cpu, assocs, n_msrs);
347
- g_free(assocs);
200
+ n_assocs = j;
201
+
202
+ ret = mshv_get_generic_regs(cpu, assocs, n_assocs);
203
if (ret < 0) {
349
- error_report("failed to set msrs");
350
- return -1;
204
+ error_report("Failed to get MSRs");
205
+ return -errno;
206
}
207
+
208
+ store_in_env(cpu, assocs, n_assocs);
209
+
210
return 0;
211
}
212
213
+static void load_from_env(const CPUState *cpu, struct hv_register_assoc *assocs,
214
+ size_t n_assocs)
215
+{
216
+ size_t i;
217
+ const MshvMsrEnvMap *mapping;
218
+ X86CPU *x86_cpu = X86_CPU(cpu);
219
+ CPUX86State *env = &x86_cpu->env;
220
+ ptrdiff_t offset;
221
+ union hv_register_value *hv_value;
222
+
223
+ assert(n_assocs == ARRAY_SIZE(msr_env_map));
224
+
225
+ for (i = 0; i < ARRAY_SIZE(msr_env_map); i++) {
226
+ mapping = &msr_env_map[i];
227
+ offset = mapping->env_offset;
228
+ assocs[i].name = mapping->hv_name;
229
+ hv_value = &assocs[i].value;
230
+ hv_value->reg64 = MSHV_ENV_FIELD(env, offset);
231
+ }
232
+}
233
356
-int mshv_configure_msr(const CPUState *cpu, const MshvMsrEntry *msrs,
357
- size_t n_msrs)
234
+int mshv_set_msrs(const CPUState *cpu)
235
{
359
- GList *valid_msrs = NULL;
360
- uint32_t msr_index;
236
+ size_t n_assocs = ARRAY_SIZE(msr_env_map);
237
+ struct hv_register_assoc assocs[ARRAY_SIZE(msr_env_map)];
238
int ret;
239
+ size_t i, j;
240
+
241
+ load_from_env(cpu, assocs, n_assocs);
242
+
243
+ /* Filter out MSRs that cannot be written */
244
+ for (i = 0, j = 0; i < n_assocs; i++) {
245
+ uint32_t name = assocs[i].name;
246
363
- for (size_t i = 0; i < n_msrs; i++) {
364
- msr_index = msrs[i].index;
365
- /* check whether index of msrs is in SUPPORTED_MSRS */
366
- if (mshv_is_supported_msr(msr_index)) {
367
- valid_msrs = g_list_append(valid_msrs, (void *) &msrs[i]);
247
+ /* Partition-wide MSRs: only write on vCPU 0 */
248
+ if (cpu->cpu_index != 0 &&
249
+ (name == HV_X64_REGISTER_HYPERCALL ||
250
+ name == HV_REGISTER_GUEST_OS_ID ||
251
+ name == HV_REGISTER_REFERENCE_TSC)) {
252
+ continue;
253
}
254
+
255
+ if (!msr_supported(name)) {
256
+ continue;
257
+ }
258
+
259
+ if (j != i) {
260
+ assocs[j] = assocs[i];
261
+ }
262
+ j++;
263
}
264
+ n_assocs = j;
265
371
- ret = set_msrs(cpu, valid_msrs);
372
- g_list_free(valid_msrs);
266
+ ret = mshv_set_generic_regs(cpu, assocs, n_assocs);
267
+ if (ret < 0) {
268
+ error_report("Failed to set MSRs");
269
+ return -errno;
270
+ }
271
374
- return ret;
272
+ return 0;
273
}