For now, qemu save/load CPU exception info(such as exception_nr and
has_error_code), while the exception error_code is ignored. This will
cause the dest hypervisor reinject a vCPU exception with error_code(0),
potentially causing a guest kernel panic.
For instance, if src VM stopped with an user-mode write #PF (error_code 6),
the dest hypervisor will reinject an #PF with error_code(0) when vCPU resume,
then guest kernel panic as:
BUG: unable to handle page fault for address:
00007f80319cb010
#PF: supervisor read access in user mode
#PF: error_code(0x0000) - not-present page
RIP: 0033:0x40115d
To fix it, support save/load exception error_code.
Signed-off-by: Xin Wang <wangxinxin.wang@huawei.com>
Link: https://lore.kernel.org/r/20250819145834.3998-1-wangxinxin.wang@huawei.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
}
};
+static bool cpu_errcode_needed(void *opaque)
+{
+ X86CPU *cpu = opaque;
+
+ return cpu->env.has_error_code != 0;
+}
+
+static const VMStateDescription vmstate_error_code = {
+ .name = "cpu/error_code",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = cpu_errcode_needed,
+ .fields = (const VMStateField[]) {
+ VMSTATE_INT32(env.error_code, X86CPU),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
/* Poll control MSR enabled by default */
static bool poll_control_msr_needed(void *opaque)
{
},
.subsections = (const VMStateDescription * const []) {
&vmstate_exception_info,
+ &vmstate_error_code,
&vmstate_async_pf_msr,
&vmstate_async_pf_int_msr,
&vmstate_pv_eoi_msr,