@samitouri / QOSamiQemu / commits / c38eb12c85

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