@samitouri / QOSamiQemu / commits / d8813fdc4b

target/sparc: set reg window data structures currently after vmstate load

In the SPARC CPU state, env->regwptr points into the env->regbase array at wherever the architectural CWP (current window pointer) says we are in the register windows. We don't migrate this directly, since it's a host pointer, so we must ensure it is set up again after migration load. We also have to deal with a special case when CWP is (nwindows - 1). In this case, while running we keep the "in" register data for this window in a temporary location at the end of the regbase[] array, so that generated code doesn't have to special case this "wrap around" case. In cpu_pre_save() we call cpu_set_cwp() to force a copy of the wrapped data from its temporary location into the architectural location in window 0's "out" registers. We then migrate only (nwindows * 16) entries in the regbase[] array. So on the destination we need to copy the "in" register data back to its temporary location again. For 32-bit SPARC we get this right, because the CWP is in the PSR. The get_psr() function does: env->cwp = 0; cpu_put_psr_raw(env, val); which causes cpu_put_psr_raw() to call cpu_set_cwp() in a way that sets up both regwptr and the wrapped-register data. However, for 64-bit SPARC the CWP is not in the PSR, and cpu_put_psr_raw() will not call cpu_set_cwp(). This leaves the guest register state in a corrupted state, and the guest will likely crash on the destination if it didn't happen to be executing with CWP == 0. Fix this by adding a custom vmstate_cwp VMStateInfo with corresponding get_cwp() and put_cwp() helpers which does the same for the 64-bit case. Cc: qemu-stable@nongnu.org Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Message-ID: <20260725123411.993099-1-mark.cave-ayland@ilande.co.uk> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>

Mark Cave-Ayland committed Jul 25, 2026 at 13:33 UTC d8813fdc4bdf3038cc55d03dab2d9dbbeb340226
1 file changed +39 -1
target/sparc/machine.c
+39 -1
@@ -151,6 +151,37 @@ static const VMStateInfo vmstate_xcc = {
151 .get = get_xcc,
152 .put = put_xcc,
153 };
154 +
155 +static int get_cwp(QEMUFile *f, void *opaque, size_t size,
156 + const VMStateField *field)
157 +{
158 + SPARCCPU *cpu = opaque;
159 + CPUSPARCState *env = &cpu->env;
160 + uint32_t val = qemu_get_be32(f);
161 +
162 + /* needed to ensure that the wrapping registers are correctly updated */
163 + env->cwp = 0;
164 + cpu_set_cwp(env, val);
165 +
166 + return 0;
167 +}
168 +
169 +static int put_cwp(QEMUFile *f, void *opaque, size_t size,
170 + const VMStateField *field, JSONWriter *vmdesc)
171 +{
172 + SPARCCPU *cpu = opaque;
173 + CPUSPARCState *env = &cpu->env;
174 + uint32_t val = env->cwp;
175 +
176 + qemu_put_be32(f, val);
177 + return 0;
178 +}
179 +
180 +static const VMStateInfo vmstate_cwp = {
181 + .name = "uint32",
182 + .get = get_cwp,
183 + .put = put_cwp,
184 +};
185 #else
186 static bool fq_needed(void *opaque)
187 {
@@ -286,7 +317,14 @@ const VMStateDescription vmstate_sparc_cpu = {
317 VMSTATE_CPU_TIMER(env.hstick, SPARCCPU),
318 /* On SPARC32 env.psrpil and env.cwp are migrated as part of the PSR */
319 VMSTATE_UINT32(env.psrpil, SPARCCPU),
289 - VMSTATE_UINT32(env.cwp, SPARCCPU),
320 + {
321 + .name = "env.cwp",
322 + .version_id = 0,
323 + .size = sizeof(uint32_t),
324 + .info = &vmstate_cwp,
325 + .flags = VMS_SINGLE,
326 + .offset = 0,
327 + },
328 #endif
329 VMSTATE_END_OF_LIST()
330 },