c3a073c610
This patch adds support for the asynchronous teardown for reboot for protected VMs. When attempting to tear down a protected VM, try to use the new asynchronous interface first. If that fails, fall back to the classic synchronous one. The asynchronous interface involves invoking the new KVM_PV_ASYNC_DISABLE_PREPARE command for the KVM_S390_PV_COMMAND ioctl. This will prepare the current protected VM for asynchronous teardown. Once the protected VM is prepared for teardown, execution can continue immediately. Once the protected VM has been prepared, a new thread is started to actually perform the teardown. The new thread uses the new KVM_PV_ASYNC_DISABLE command for the KVM_S390_PV_COMMAND ioctl. The previously prepared protected VM is torn down in the new thread. Once KVM_PV_ASYNC_DISABLE is invoked, it is possible to use KVM_PV_ASYNC_DISABLE_PREPARE again. If a protected VM has already been prepared and its cleanup has not started, it will not be possible to prepare a new VM. In that case the classic synchronous teardown has to be performed. The synchronous teardown will now also clean up any prepared VMs whose asynchronous teardown has not been initiated yet. This considerably speeds up the reboot of a protected VM; for large VMs especially, it could take a long time to perform a reboot with the traditional synchronous teardown, while with this patch it is almost immediate. Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com> Reviewed-by: Thomas Huth <thuth@redhat.com> Message-Id: <20230214163035.44104-3-imbrenda@linux.ibm.com> Signed-off-by: Thomas Huth <thuth@redhat.com>
97 lines
3.3 KiB
C
97 lines
3.3 KiB
C
/*
|
|
* Protected Virtualization header
|
|
*
|
|
* Copyright IBM Corp. 2020
|
|
* Author(s):
|
|
* Janosch Frank <frankja@linux.ibm.com>
|
|
*
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or (at
|
|
* your option) any later version. See the COPYING file in the top-level
|
|
* directory.
|
|
*/
|
|
#ifndef HW_S390_PV_H
|
|
#define HW_S390_PV_H
|
|
|
|
#include "qapi/error.h"
|
|
#include "sysemu/kvm.h"
|
|
|
|
#ifdef CONFIG_KVM
|
|
#include "cpu.h"
|
|
#include "hw/s390x/s390-virtio-ccw.h"
|
|
|
|
static inline bool s390_is_pv(void)
|
|
{
|
|
static S390CcwMachineState *ccw;
|
|
Object *obj;
|
|
|
|
if (ccw) {
|
|
return ccw->pv;
|
|
}
|
|
|
|
/* we have to bail out for the "none" machine */
|
|
obj = object_dynamic_cast(qdev_get_machine(),
|
|
TYPE_S390_CCW_MACHINE);
|
|
if (!obj) {
|
|
return false;
|
|
}
|
|
ccw = S390_CCW_MACHINE(obj);
|
|
return ccw->pv;
|
|
}
|
|
|
|
int s390_pv_query_info(void);
|
|
int s390_pv_vm_enable(void);
|
|
void s390_pv_vm_disable(void);
|
|
bool s390_pv_vm_try_disable_async(void);
|
|
int s390_pv_set_sec_parms(uint64_t origin, uint64_t length);
|
|
int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak);
|
|
void s390_pv_prep_reset(void);
|
|
int s390_pv_verify(void);
|
|
void s390_pv_unshare(void);
|
|
void s390_pv_inject_reset_error(CPUState *cs);
|
|
uint64_t kvm_s390_pv_dmp_get_size_cpu(void);
|
|
uint64_t kvm_s390_pv_dmp_get_size_mem_state(void);
|
|
uint64_t kvm_s390_pv_dmp_get_size_completion_data(void);
|
|
bool kvm_s390_pv_info_basic_valid(void);
|
|
int kvm_s390_dump_init(void);
|
|
int kvm_s390_dump_cpu(S390CPU *cpu, void *buff);
|
|
int kvm_s390_dump_mem_state(uint64_t addr, size_t len, void *dest);
|
|
int kvm_s390_dump_completion_data(void *buff);
|
|
#else /* CONFIG_KVM */
|
|
static inline bool s390_is_pv(void) { return false; }
|
|
static inline int s390_pv_query_info(void) { return 0; }
|
|
static inline int s390_pv_vm_enable(void) { return 0; }
|
|
static inline void s390_pv_vm_disable(void) {}
|
|
static inline bool s390_pv_vm_try_disable_async(void) { return false; }
|
|
static inline int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) { return 0; }
|
|
static inline int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) { return 0; }
|
|
static inline void s390_pv_prep_reset(void) {}
|
|
static inline int s390_pv_verify(void) { return 0; }
|
|
static inline void s390_pv_unshare(void) {}
|
|
static inline void s390_pv_inject_reset_error(CPUState *cs) {};
|
|
static inline uint64_t kvm_s390_pv_dmp_get_size_cpu(void) { return 0; }
|
|
static inline uint64_t kvm_s390_pv_dmp_get_size_mem_state(void) { return 0; }
|
|
static inline uint64_t kvm_s390_pv_dmp_get_size_completion_data(void) { return 0; }
|
|
static inline bool kvm_s390_pv_info_basic_valid(void) { return false; }
|
|
static inline int kvm_s390_dump_init(void) { return 0; }
|
|
static inline int kvm_s390_dump_cpu(S390CPU *cpu, void *buff) { return 0; }
|
|
static inline int kvm_s390_dump_mem_state(uint64_t addr, size_t len,
|
|
void *dest) { return 0; }
|
|
static inline int kvm_s390_dump_completion_data(void *buff) { return 0; }
|
|
#endif /* CONFIG_KVM */
|
|
|
|
int s390_pv_kvm_init(ConfidentialGuestSupport *cgs, Error **errp);
|
|
static inline int s390_pv_init(ConfidentialGuestSupport *cgs, Error **errp)
|
|
{
|
|
if (!cgs) {
|
|
return 0;
|
|
}
|
|
if (kvm_enabled()) {
|
|
return s390_pv_kvm_init(cgs, errp);
|
|
}
|
|
|
|
error_setg(errp, "Protected Virtualization requires KVM");
|
|
return -1;
|
|
}
|
|
|
|
#endif /* HW_S390_PV_H */
|