On 19/02/2026 10:31, Ani Sinha wrote:


On 19 Feb 2026, at 3:09 PM, Paul Durrant <[email protected]> wrote:

On 18/02/2026 11:42, Ani Sinha wrote:
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.
Signed-off-by: Ani Sinha <[email protected]>
---
  target/i386/kvm/xen-emu.c | 50 +++++++++++++++++++++++++++++++++++++--
  1 file changed, 48 insertions(+), 2 deletions(-)
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index 52de019834..69527145eb 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,30 @@ 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;
+
+    /* we are not interested in pre vmfd change notification */
+    if (((VmfdChangeNotifier *)data)->pre) {
+        return 0;
+    }
+
+    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;

This seems odd. Why use the hyperv_enabled boolean, rather than simply the msr 
value, since when hyperv_enabled is set you will be calling 
do_initialize_xen_caps() twice.

I am not sure of enabling capabilities for Xen. I assumed we need to call 
kvm_xen_init() twice, once normally with XEN_HYPERCALL_MSR and if hyper is 
enabled, again with XEN_HYPERCALL_MSR_HYPERV. Is that not the case? Is it one 
or the other but not both? It seems kvm_arch_init() calls kvm_xen_init() once 
with XEN_HYPERCALL_MSR and another time vcpu_arch_init() calls it again if 
hyperv is enabled with XEN_HYPERCALL_MSR_HYPERV .

Yes, it has to be assumed that XEN_HYPERCALL_MSR is correct until Hyper-V supported is enabled, which comes later, at which point the MSR is changed. So you only need save the latest MSR value and use that in xen_handle_vmfd_change().



+}
+
  static bool kvm_gva_to_gpa(CPUState *cs, uint64_t gva, uint64_t *gpa,
                             size_t *len, bool is_write)
  {
@@ -111,15 +138,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;
+

Gratuitous whitespace change.

      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 +171,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;
+    }
+

Clearly here the code would be simpler here if you just saved the value of 
hypercall_msr which you have used in the call above.

+    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 +228,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;
  }




Reply via email to