On confidential guests KVM virtual machine file descriptor changes as a part of the guest reset process. Xen capabilities needs to be re-initialized in KVM against the new file descriptor.
This patch is untested on confidential guests and exists only for completeness. Signed-off-by: Ani Sinha <[email protected]> --- target/i386/kvm/xen-emu.c | 45 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c index 52de019834..4f4cde7c58 100644 --- a/target/i386/kvm/xen-emu.c +++ b/target/i386/kvm/xen-emu.c @@ -44,9 +44,12 @@ #include "xen-compat.h" +NotifierWithReturn xen_vmfd_change_notifier; +static bool hyperv_enabled; static void xen_vcpu_singleshot_timer_event(void *opaque); static void xen_vcpu_periodic_timer_event(void *opaque); static int vcpuop_stop_singleshot_timer(CPUState *cs); +static int do_initialize_xen_caps(KVMState *s, uint32_t hypercall_msr); #ifdef TARGET_X86_64 #define hypercall_compat32(longmode) (!(longmode)) @@ -54,6 +57,25 @@ static int vcpuop_stop_singleshot_timer(CPUState *cs); #define hypercall_compat32(longmode) (false) #endif +static int xen_handle_vmfd_change(NotifierWithReturn *n, + void *data, Error** errp) +{ + int ret; + + ret = do_initialize_xen_caps(kvm_state, XEN_HYPERCALL_MSR); + if (ret < 0) { + return ret; + } + + if (hyperv_enabled) { + ret = do_initialize_xen_caps(kvm_state, XEN_HYPERCALL_MSR_HYPERV); + if (ret < 0) { + return ret; + } + } + return 0; +} + static bool kvm_gva_to_gpa(CPUState *cs, uint64_t gva, uint64_t *gpa, size_t *len, bool is_write) { @@ -111,15 +133,16 @@ static inline int kvm_copy_to_gva(CPUState *cs, uint64_t gva, void *buf, return kvm_gva_rw(cs, gva, buf, sz, true); } -int kvm_xen_init(KVMState *s, uint32_t hypercall_msr) +static int do_initialize_xen_caps(KVMState *s, uint32_t hypercall_msr) { + int xen_caps, ret; const int required_caps = KVM_XEN_HVM_CONFIG_HYPERCALL_MSR | KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL | KVM_XEN_HVM_CONFIG_SHARED_INFO; + struct kvm_xen_hvm_config cfg = { .msr = hypercall_msr, .flags = KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL, }; - int xen_caps, ret; xen_caps = kvm_check_extension(s, KVM_CAP_XEN_HVM); if (required_caps & ~xen_caps) { @@ -143,6 +166,21 @@ int kvm_xen_init(KVMState *s, uint32_t hypercall_msr) strerror(-ret)); return ret; } + return xen_caps; +} + +int kvm_xen_init(KVMState *s, uint32_t hypercall_msr) +{ + int xen_caps; + + xen_caps = do_initialize_xen_caps(s, hypercall_msr); + if (xen_caps < 0) { + return xen_caps; + } + + if (!hyperv_enabled && (hypercall_msr == XEN_HYPERCALL_MSR_HYPERV)) { + hyperv_enabled = true; + } /* If called a second time, don't repeat the rest of the setup. */ if (s->xen_caps) { @@ -185,6 +223,9 @@ int kvm_xen_init(KVMState *s, uint32_t hypercall_msr) xen_primary_console_reset(); xen_xenstore_reset(); + xen_vmfd_change_notifier.notify = xen_handle_vmfd_change; + kvm_vmfd_add_change_notifier(&xen_vmfd_change_notifier); + return 0; } -- 2.42.0
