target/i386/mshv: migrate MTRR MSRs
This change roundtrips memory access/caching MSRs. The mapping scheme is a bit more elaborate on these, so we have added a special handling instead of individual entries in the MSR mapping table. Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com> Link: https://lore.kernel.org/r/20260417105618.3621-22-magnuskulke@linux.microsoft.com Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Magnus Kulke committed
Apr 17, 2026 at 12:56 UTC
c38eb12c85dbc91d77c8881d54a1a1464dd3cc70
1 file changed
+129
-7
target/i386/mshv/msr.c
+129
-7
@@ -77,6 +77,10 @@ static const MshvMsrEnvMap msr_env_map[] = {
77
{ HV_X64_MSR_SIMP, HV_REGISTER_SIMP,
78
offsetof(CPUX86State, msr_hv_synic_msg_page) },
79
80
+ /* MTRR default type */
81
+ { IA32_MSR_MTRR_DEF_TYPE, HV_X64_REGISTER_MSR_MTRR_DEF_TYPE,
82
+ offsetof(CPUX86State, mtrr_deftype) },
83
+
84
/* Other */
85
86
/* TODO: find out processor features that correlate to unsupported MSRs. */
@@ -88,6 +92,98 @@ static const MshvMsrEnvMap msr_env_map[] = {
92
offsetof(CPUX86State, spec_ctrl) },
93
};
94
95
+/*
96
+ * The assocs have to be set according to this schema:
97
+ * 8 entries for 0-7 mtrr_base
98
+ * 8 entries for mtrr_mask 0-7
99
+ * 11 entries for 1 x 64k, 2 x 16k, 8 x 4k fixed MTRR
100
+ * 27 total entries
101
+ */
102
+
103
+#define MSHV_MTRR_MSR_COUNT 27
104
+#define MSHV_MSR_TOTAL_COUNT (ARRAY_SIZE(msr_env_map) + MSHV_MTRR_MSR_COUNT)
105
+
106
+static void store_in_env_mtrr_phys(CPUState *cpu,
107
+ const struct hv_register_assoc *assocs,
108
+ size_t n_assocs)
109
+{
110
+ X86CPU *x86_cpu = X86_CPU(cpu);
111
+ CPUX86State *env = &x86_cpu->env;
112
+ size_t i, fixed_offset;
113
+ hv_register_name hv_name;
114
+ uint64_t base, mask;
115
+
116
+ assert(n_assocs == MSHV_MTRR_MSR_COUNT);
117
+
118
+ for (i = 0; i < MSR_MTRRcap_VCNT; i++) {
119
+ hv_name = HV_X64_REGISTER_MSR_MTRR_PHYS_BASE0 + i;
120
+ assert(assocs[i].name == hv_name);
121
+ hv_name = HV_X64_REGISTER_MSR_MTRR_PHYS_MASK0 + i;
122
+ assert(assocs[i + MSR_MTRRcap_VCNT].name == hv_name);
123
+
124
+ base = assocs[i].value.reg64;
125
+ mask = assocs[i + MSR_MTRRcap_VCNT].value.reg64;
126
+ env->mtrr_var[i].base = base;
127
+ env->mtrr_var[i].mask = mask;
128
+ }
129
+
130
+ /* fixed 1x 64, 2x 16, 8x 4 kB */
131
+ fixed_offset = MSR_MTRRcap_VCNT * 2;
132
+ for (i = 0; i < 11; i++) {
133
+ hv_name = HV_X64_REGISTER_MSR_MTRR_FIX64K00000 + i;
134
+ assert(assocs[fixed_offset + i].name == hv_name);
135
+ env->mtrr_fixed[i] = assocs[fixed_offset + i].value.reg64;
136
+ }
137
+}
138
+
139
+/*
140
+ * The assocs have to be set according to this schema:
141
+ * 8 entries for 0-7 mtrr_base
142
+ * 8 entries for mtrr_mask 0-7
143
+ * 11 entries for 1 x 64k, 2 x 16k, 8 x 4k fixed MTRR
144
+ * 27 total entries
145
+ */
146
+static void load_from_env_mtrr_phys(const CPUState *cpu,
147
+ struct hv_register_assoc *assocs,
148
+ size_t n_assocs)
149
+{
150
+ X86CPU *x86_cpu = X86_CPU(cpu);
151
+ CPUX86State *env = &x86_cpu->env;
152
+ size_t i, fixed_offset;
153
+ uint64_t base, mask, fixed_value;
154
+ hv_register_name base_name, mask_name, fixed_name;
155
+ hv_register_assoc *assoc;
156
+
157
+ assert(n_assocs == MSHV_MTRR_MSR_COUNT);
158
+
159
+ for (i = 0; i < MSR_MTRRcap_VCNT; i++) {
160
+ base = env->mtrr_var[i].base;
161
+ mask = env->mtrr_var[i].mask;
162
+
163
+ base_name = HV_X64_REGISTER_MSR_MTRR_PHYS_BASE0 + i;
164
+ mask_name = HV_X64_REGISTER_MSR_MTRR_PHYS_MASK0 + i;
165
+
166
+ assoc = &assocs[i];
167
+ assoc->name = base_name;
168
+ assoc->value.reg64 = base;
169
+
170
+ assoc = &assocs[i + MSR_MTRRcap_VCNT];
171
+ assoc->name = mask_name;
172
+ assoc->value.reg64 = mask;
173
+ }
174
+
175
+ /* fixed 1x 64, 2x 16, 8x 4 kB */
176
+ fixed_offset = MSR_MTRRcap_VCNT * 2;
177
+ for (i = 0; i < 11; i++) {
178
+ fixed_name = HV_X64_REGISTER_MSR_MTRR_FIX64K00000 + i;
179
+ fixed_value = env->mtrr_fixed[i];
180
+
181
+ assoc = &assocs[fixed_offset + i];
182
+ assoc->name = fixed_name;
183
+ assoc->value.reg64 = fixed_value;
184
+ }
185
+}
186
+
187
int mshv_init_msrs(const CPUState *cpu)
188
{
189
int ret;
@@ -129,8 +225,9 @@ static void store_in_env(CPUState *cpu, const struct hv_register_assoc *assocs,
225
union hv_register_value hv_value;
226
ptrdiff_t offset;
227
uint32_t hv_name;
228
+ size_t mtrr_index;
229
133
- assert(n_assocs <= (ARRAY_SIZE(msr_env_map)));
230
+ assert(n_assocs <= MSHV_MSR_TOTAL_COUNT);
231
232
for (i = 0, j = 0; i < ARRAY_SIZE(msr_env_map); i++) {
233
hv_name = assocs[j].name;
@@ -144,17 +241,38 @@ static void store_in_env(CPUState *cpu, const struct hv_register_assoc *assocs,
241
MSHV_ENV_FIELD(env, offset) = hv_value.reg64;
242
j++;
243
}
244
+
245
+ mtrr_index = j;
246
+ store_in_env_mtrr_phys(cpu, &assocs[mtrr_index], MSHV_MTRR_MSR_COUNT);
247
}
248
249
static void set_hv_name_in_assocs(struct hv_register_assoc *assocs,
250
size_t n_assocs)
251
{
252
size_t i;
253
+ size_t mtrr_offset, mtrr_fixed_offset;
254
+ hv_register_name hv_name;
255
+
256
+ assert(n_assocs == MSHV_MSR_TOTAL_COUNT);
257
154
- assert(n_assocs == ARRAY_SIZE(msr_env_map));
258
for (i = 0; i < ARRAY_SIZE(msr_env_map); i++) {
259
assocs[i].name = msr_env_map[i].hv_name;
260
}
261
+
262
+ mtrr_offset = ARRAY_SIZE(msr_env_map);
263
+ for (i = 0; i < MSR_MTRRcap_VCNT; i++) {
264
+ hv_name = HV_X64_REGISTER_MSR_MTRR_PHYS_BASE0 + i;
265
+ assocs[mtrr_offset + i].name = hv_name;
266
+ hv_name = HV_X64_REGISTER_MSR_MTRR_PHYS_MASK0 + i;
267
+ assocs[mtrr_offset + MSR_MTRRcap_VCNT + i].name = hv_name;
268
+ }
269
+
270
+ /* fixed 1x 64, 2x 16, 8x 4 kB */
271
+ mtrr_fixed_offset = mtrr_offset + MSR_MTRRcap_VCNT * 2;
272
+ for (i = 0; i < 11; i++) {
273
+ hv_name = HV_X64_REGISTER_MSR_MTRR_FIX64K00000 + i;
274
+ assocs[mtrr_fixed_offset + i].name = hv_name;
275
+ }
276
}
277
278
static bool msr_supported(uint32_t name)
@@ -177,8 +295,8 @@ static bool msr_supported(uint32_t name)
295
int mshv_get_msrs(CPUState *cpu)
296
{
297
int ret = 0;
180
- size_t n_assocs = ARRAY_SIZE(msr_env_map);
181
- struct hv_register_assoc assocs[ARRAY_SIZE(msr_env_map)];
298
+ size_t n_assocs = MSHV_MSR_TOTAL_COUNT;
299
+ struct hv_register_assoc assocs[MSHV_MSR_TOTAL_COUNT];
300
size_t i, j;
301
uint32_t name;
302
@@ -219,8 +337,9 @@ static void load_from_env(const CPUState *cpu, struct hv_register_assoc *assocs,
337
CPUX86State *env = &x86_cpu->env;
338
ptrdiff_t offset;
339
union hv_register_value *hv_value;
340
+ size_t mtrr_offset;
341
223
- assert(n_assocs == ARRAY_SIZE(msr_env_map));
342
+ assert(n_assocs == MSHV_MSR_TOTAL_COUNT);
343
344
for (i = 0; i < ARRAY_SIZE(msr_env_map); i++) {
345
mapping = &msr_env_map[i];
@@ -229,12 +348,15 @@ static void load_from_env(const CPUState *cpu, struct hv_register_assoc *assocs,
348
hv_value = &assocs[i].value;
349
hv_value->reg64 = MSHV_ENV_FIELD(env, offset);
350
}
351
+
352
+ mtrr_offset = ARRAY_SIZE(msr_env_map);
353
+ load_from_env_mtrr_phys(cpu, &assocs[mtrr_offset], MSHV_MTRR_MSR_COUNT);
354
}
355
356
int mshv_set_msrs(const CPUState *cpu)
357
{
236
- size_t n_assocs = ARRAY_SIZE(msr_env_map);
237
- struct hv_register_assoc assocs[ARRAY_SIZE(msr_env_map)];
358
+ size_t n_assocs = MSHV_MSR_TOTAL_COUNT;
359
+ struct hv_register_assoc assocs[MSHV_MSR_TOTAL_COUNT];
360
int ret;
361
size_t i, j;
362