target/i386: Add support for save/load of exception error code

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>
This commit is contained in:
Xin Wang
2025-08-19 22:58:34 +08:00
committed by Paolo Bonzini
parent 88f72048d2
commit 27535e9cca

View File

@@ -462,6 +462,24 @@ static const VMStateDescription vmstate_exception_info = {
}
};
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)
{
@@ -1746,6 +1764,7 @@ const VMStateDescription vmstate_x86_cpu = {
},
.subsections = (const VMStateDescription * const []) {
&vmstate_exception_info,
&vmstate_error_code,
&vmstate_async_pf_msr,
&vmstate_async_pf_int_msr,
&vmstate_pv_eoi_msr,