On Thu, 4 Sep 2025 09:06:35 +0100 Alex Bennée <alex.bennee@xxxxxxxxxx> wrote: > From: Xin Wang <wangxinxin.wang@xxxxxxxxxx> > > 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. this potentially will break migration between new/old QEMU versions due to presence new subsection. But then according to commit message the guest might panic (on dst) when resumed anyways. So patch changes how guest will fail (panic: old => old, old => new vs migration error: new => old ). Peter, do we care and do we need a compat knob to make existing machine type behave old way? > > Signed-off-by: Xin Wang <wangxinxin.wang@xxxxxxxxxx> > Link: https://lore.kernel.org/r/20250819145834.3998-1-wangxinxin.wang@xxxxxxxxxx > Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx> > --- > target/i386/machine.c | 19 +++++++++++++++++++ > 1 file changed, 19 insertions(+) > > diff --git a/target/i386/machine.c b/target/i386/machine.c > index dd2dac1d443..45b7cea80aa 100644 > --- a/target/i386/machine.c > +++ b/target/i386/machine.c > @@ -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,