When a confidential virtual machine is reset, a new guest context in the accelerator must be generated post reset. Therefore, the old accelerator guest file handle must be closed and a new one created. To this end, a per-accelerator callback, "rebuild_guest" is introduced that would get called when a confidential guest is reset. Subsequent patches will introduce specific implementation of this callback for KVM accelerator.
Signed-off-by: Ani Sinha <[email protected]> --- include/accel/accel-ops.h | 2 ++ system/runstate.c | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/include/accel/accel-ops.h b/include/accel/accel-ops.h index 23a8c246e1..f46492e3fe 100644 --- a/include/accel/accel-ops.h +++ b/include/accel/accel-ops.h @@ -23,6 +23,8 @@ struct AccelClass { AccelOpsClass *ops; int (*init_machine)(AccelState *as, MachineState *ms); + /* used mainly by confidential guests to rebuild guest state upon reset */ + int (*rebuild_guest)(MachineState *ms); bool (*cpu_common_realize)(CPUState *cpu, Error **errp); void (*cpu_common_unrealize)(CPUState *cpu); /* get_stats: Append statistics to @buf */ diff --git a/system/runstate.c b/system/runstate.c index 13f32bed8c..e7b50e6a3b 100644 --- a/system/runstate.c +++ b/system/runstate.c @@ -42,6 +42,7 @@ #include "qapi/qapi-commands-run-state.h" #include "qapi/qapi-events-run-state.h" #include "qemu/accel.h" +#include "accel/accel-ops.h" #include "qemu/error-report.h" #include "qemu/job.h" #include "qemu/log.h" @@ -509,6 +510,9 @@ void qemu_system_reset(ShutdownCause reason) { MachineClass *mc; ResetType type; + AccelClass *ac = ACCEL_GET_CLASS(current_accel()); + bool guest_state_rebuilt = false; + int ret; mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL; @@ -521,6 +525,29 @@ void qemu_system_reset(ShutdownCause reason) default: type = RESET_TYPE_COLD; } + + if (!cpus_are_resettable() && + (reason == SHUTDOWN_CAUSE_GUEST_RESET || + reason == SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET)) { + if (ac->rebuild_guest) { + ret = ac->rebuild_guest(current_machine); + if (ret < 0) { + error_report("unable to rebuild guest: %s(%d)", + strerror(-ret), ret); + vm_stop(RUN_STATE_INTERNAL_ERROR); + } else { + info_report("virtual machine state has been rebuilt with new " + "guest file handle."); + guest_state_rebuilt = true; + } + } else if (!cpus_are_resettable()) { + error_report("accelerator does not support reset!"); + } else { + error_report("accelerator does not support rebuilding guest state," + " proceeding with normal reset!"); + } + } + if (mc && mc->reset) { mc->reset(current_machine, type); } else { @@ -543,7 +570,16 @@ void qemu_system_reset(ShutdownCause reason) * it does _more_ than cpu_synchronize_all_post_reset(). */ if (cpus_are_resettable()) { - cpu_synchronize_all_post_reset(); + if (guest_state_rebuilt) { + /* + * If guest state has been rebuilt, then we + * need to sync full cpu state for non confidential guests post + * reset. + */ + cpu_synchronize_all_post_init(); + } else { + cpu_synchronize_all_post_reset(); + } } vm_set_suspended(false); -- 2.42.0
